//----------------------------------------------------------------------------- #include "typedefs.h" #include "application.h" #include "spi_master.h" #include "ad7719_adc.h" #include "atmega_adc.h" #include "usart.h" #include "macros.h" //#include "interpol.h" //#include "w5100_spi_interface.h" #include #include #include //----------------------------------------------------------------------------- // definition of some functions: // these function are implemented in this file, this is not doog coding style. // sooner or later, they will be moved into more apropriate files. U08 increase_adc (U08 channel); U08 increase_ad7719 (U08 channel); void Set_V_Muxer (U08 channel); void Set_T_Muxer(U08 channel); void parse(); void check_if_measured_all() ; void print_ad7719_nicely(bool with_header, bool with_LF) ; void print_adc_nicely(bool with_header, bool with_LF) ; void print_invalid_enable_statement(); void print_help() ; // is not printin help at the moment .... eats up too much RAM void print_adc_enable_status(bool with_headline); void print_ad7719_enable_status(bool with_headline) ; bool check_if_adc_measurement_done(); bool check_if_ad7719_measurement_done(); // end of function definition: //----------------------------------------------------------------------------- // Reference resistance float r_reference = 6.257; // MAIN WORKFLOW GLOBAL VARIABLES bool verbose; bool heartbeat_enable; // USART global variables U08 usart_rx_buffer[USART_RX_BUFFER_SIZE]; U08 usart_tx_buffer[USART_TX_BUFFER_SIZE]; U08 usart_received_chars; U08 usart_rx_buffer_index = 0; U08 usart_tx_buffer_index = 0; U08 usart_last_char; // last received char // USART FLAGS bool usart_tx_buffer_overflow = false; // true if usart_tx_buffer was full. bool usart_rx_ready = false; // EOL was received, parser needs to be called // TIMER global variable volatile U32 local_ms = 0; // AD7719 global variables #define TEMP_CHANNELS 16 #define CHANNEL_BITMAP 2 #define AD7719_READINGS_UNTIL_SETTLED 3 // bei3:480ms U32 ad7719_values[TEMP_CHANNELS]; U08 ad7719_enables[CHANNEL_BITMAP]; U08 ad7719_channels_ready[CHANNEL_BITMAP]; U08 ad7719_readings_since_last_muxing = 0; U08 ad7719_current_channel = 0; U32 ad7719_current_reading = 0; bool ad7719_measured_all = false; bool ad7719_values_printed = true; bool ad7719_print_endless = false; // ATMEGA ADC global variables #define V_CHANNELS 16 #define V_BITMAP 2 #define ADC_READINGS_UNTIL_SETTLED 1 U08 adc_readings_until_mean=250; U32 adc_values[V_CHANNELS]; // stores measured voltage in steps of 16mV U08 adc_enables[V_BITMAP]; U08 adc_channels_ready[V_BITMAP]; U08 adc_readings_since_last_muxing = 0; U08 adc_current_channel = 0; U16 adc_current_reading = 0; bool adc_measured_all = false; bool adc_values_printed = true; bool adc_print_endless = false; bool debug_mode = false; //U32 hb_counter = 0; //----------------------------------------------------------------------------- // M A I N --- M A I N --- M A I N --- M A I N --- M A I N //----------------------------------------------------------------------------- int main(void) { app_init(); // Setup: Watchdog and I/Os usart_init(); // Initialize serial interface spi_init(); // Initialize SPI interface as master ad7719_init(); // Initialize AD7719 ADC as SPI slave atmega_adc_init(); // TIMER2 is used as local clock: // configure timer 2 TCCR2 = (1< counts up every 8us OCR2 = 125-1; // --> output compare interrupt occurs every 125 x 8us = 1ms // Compare Interrupt erlauben TIMSK |= (1< heartbeat // warte 100.000 heartbeats und schreibe die Zeit raus //hb_counter++; //if (hb_counter == 100000){ // hb_counter = 0; // usart_write_float((float)local_ms/1000 , 1,7); // usart_write_str((pU08)" sec.\n"); //} } //---------------------------------------------------------------------------- //IF we need to send away one byte, and ready to send if ( (usart_tx_buffer_index > 0) && (UCSRA & (1<= ADC_READINGS_UNTIL_SETTLED-1) { adc_values[adc_current_channel] += adc_current_reading; ++adc_readings_since_last_muxing; } else { ++adc_readings_since_last_muxing; } } //---------------------------------------------------------------------------- //IF AD7719 ADC just finished a conversion -- every 60ms if (AD7719_IS_READY() && !ad7719_measured_all) { ad7719_current_reading = read_adc(); // --takes at 4MHz SCLK speed about 6us // AD7719 is only read out if settled. saves time. if (ad7719_readings_since_last_muxing == AD7719_READINGS_UNTIL_SETTLED-1) { ad7719_values[ad7719_current_channel] = ad7719_current_reading; ad7719_readings_since_last_muxing=0; if (debug_mode) { usart_write_U32_hex(ad7719_current_reading); usart_write_char('\n'); usart_write_char('\n'); } // now prepare the data to be send away via USART. // note that this channel is ready, now and // proceed to the next enabled channel. ad7719_channels_ready[ad7719_current_channel/8] |= (1<<(ad7719_current_channel%8)); ad7719_current_channel = increase_ad7719 (ad7719_current_channel); Set_T_Muxer(ad7719_current_channel); } else { // the AD7719 did not settle yet, we discard the reading ++ad7719_readings_since_last_muxing; if (debug_mode) { usart_write_U32_hex(ad7719_current_reading); usart_write_char('\n'); } // current reading is not used for anything else } } } // end of MAIN LOOP } // end of main function //----------------------------------------------------------------------------- // E N D E N D E N D E N D E N D E N D E N D //----------------------------------------------------------------------------- ISR (TIMER2_COMP_vect) { ++local_ms; } U08 increase_adc (U08 channel){ U08 effective_channel; for ( U08 increase = 1 ; increase <= V_CHANNELS; increase++) { effective_channel = (channel + increase) % (V_CHANNELS); if (adc_enables[effective_channel/8] & (1<0) { switch (usart_rx_buffer[0]) { case 'E': // user wants to enable/disable something case 'e': enable = true; case 'D': case 'd': if (usart_rx_buffer_index>=1) { // let's see what. if ( usart_rx_buffer[1] != 'r' && usart_rx_buffer[1] != 'v' && usart_rx_buffer[1] != 'h' && usart_rx_buffer[1] != 'p' ) { print_invalid_enable_statement(); break; } } input_number = 0; if (usart_rx_buffer_index >2) { // lets check the first digit if ( usart_rx_buffer[2] >= '0' && usart_rx_buffer[2] <= '9' ) { input_number = usart_rx_buffer[2] - '0'; } else { print_invalid_enable_statement(); break; } } if (usart_rx_buffer_index >3) { // lets check the 2nd digit if ( usart_rx_buffer[3] >= '0' && usart_rx_buffer[3] <= '9' ) { input_number = 10*input_number + usart_rx_buffer[3] - '0'; } else { // okay as well ... if the second digit is missing .. // we might have trailing spaces // that's okay .. we just accept the first number. } } if (usart_rx_buffer_index>2) { usart_write_str((pU08)"\n I will switch "); if (enable) usart_write_str((pU08)"on "); else usart_write_str((pU08)"off "); // now we know, what the user wanted ... and we need to do it. switch (usart_rx_buffer[1]) { case 'r': if (enable) ad7719_enables[input_number/8] |= (1<<(input_number%8)); else { ad7719_enables[input_number/8] &= ~(1<<(input_number%8)); ad7719_channels_ready[input_number/8] &= ~(1<<(input_number%8)); } usart_write_str((pU08)" resistance channel "); usart_write_U08(input_number,2); usart_write_char('\n'); break; case 'v': if (enable) adc_enables[input_number/8] |= (1<<(input_number%8)); else { adc_enables[input_number/8] &= ~(1<<(input_number%8)); adc_channels_ready[input_number/8] &= ~(1<<(input_number%8)); } usart_write_str((pU08)" voltage channel "); usart_write_U08(input_number,2); usart_write_char('\n'); break; case 'h': if (enable) adc_enables[1] |= (1<<(input_number%4)); else { adc_enables[1] &= ~(1<<(input_number%4)); adc_channels_ready[1] &= ~(1<<(input_number%4)); } usart_write_str((pU08)" humidity channel "); usart_write_U08(input_number,2); usart_write_char('\n'); break; case 'p': if (enable) adc_enables[1] |= (1<<((input_number%4) + 4)); else { adc_enables[1] &= ~(1<<((input_number%4) + 4)); adc_channels_ready[1] &= ~(1<<((input_number%4) + 4)); } usart_write_str((pU08)" pressure channel "); usart_write_U08(input_number,2); usart_write_char('\n'); break; default: usart_write_str((pU08)"\n DAMN! this should never happen" "- enable/disable switch-case!\n"); break; } }// end of if usart_rx_buffer_index>2 --> this should not be necessary at all break; case 'b': usart_write_str((pU08)"\nheartbeat "); heartbeat_enable = true; if (usart_rx_buffer[1] == '0'){ heartbeat_enable = false; usart_write_str((pU08)"off\n"); } else { usart_write_str((pU08)"on\n"); } break; case 'G': // GET the Temperature channels, which are enabled ad7719_values_printed = false; for ( U08 i=0; i enable voltage channel 1\n"); usart_write_str((pU08)"e.g.: dr0 --> disable resistance channel 0\n"); } void print_help() { usart_write_str((pU08) "List of MSR commands:\n29.03.2011\n" "E or e -- enable channel: type e? for detailed help\n" "D or d -- disable channel: type d? for detailed help\n" "b0 or b1 -- switch heartbeat PA4 on or off\n" "G -- 'get AD7719' -> measure resistances again\n" "g -- 'get ATmega adc' -> measure voltages again\n" "P -- get & print AD7719 infinitly \n" "p -- get & print ATmega adc infinitly \n" "s -- print status\n" "H or h -- print this help\n" ); } void print_adc_enable_status(bool with_headline) { if (with_headline) { usart_write_str((pU08)"adc channels 15 downto 0:\n i.e. left is pressure and humidity ... right is voltage\n"); } usart_write_U08_bin(adc_enables[1]); usart_write_char(' '); usart_write_U08_bin(adc_enables[0]); usart_write_char(' '); usart_write_char('\n'); usart_write_U08_bin(adc_channels_ready[1]); usart_write_char(' '); usart_write_U08_bin(adc_channels_ready[0]); usart_write_char(' '); } void print_ad7719_enable_status(bool with_headline) { if (with_headline) { usart_write_str((pU08)"ad7719 channels: 15 downto 0:\n"); } usart_write_U08_bin(ad7719_enables[1]); usart_write_char(' '); usart_write_U08_bin(ad7719_enables[0]); usart_write_char(' '); usart_write_char('\n'); usart_write_U08_bin(ad7719_channels_ready[1]); usart_write_char(' '); usart_write_U08_bin(ad7719_channels_ready[0]); }