int main(void) { struct adc_config adc_conf; struct adc_channel_config adcch_conf; board_init(); sysclk_init(); sleepmgr_init(); irq_initialize_vectors(); cpu_irq_enable(); gfx_mono_init(); // Enable back light of display ioport_set_pin_high(LCD_BACKLIGHT_ENABLE_PIN); // Initialize configuration structures. adc_read_configuration(&ADCA, &adc_conf); adcch_read_configuration(&ADCA, ADC_CH0, &adcch_conf); /* Configure the ADC module: * - unsigned, 12-bit results * - VCC voltage reference * - 200 kHz maximum clock rate * - manual conversion triggering * - temperature sensor enabled * - callback function */ adc_set_conversion_parameters(&adc_conf, ADC_SIGN_ON, ADC_RES_12, ADC_REF_VCC); adc_set_clock_rate(&adc_conf, 200000UL); adc_set_conversion_trigger(&adc_conf, ADC_TRIG_MANUAL, 1, 0); adc_enable_internal_input(&adc_conf, ADC_INT_TEMPSENSE); adc_write_configuration(&ADCA, &adc_conf); adc_set_callback(&ADCA, &adc_handler); /* Configure ADC channel 0: * - single-ended measurement from temperature sensor * - interrupt flag set on completed conversion * - interrupts disabled */ adcch_set_input(&adcch_conf, ADCCH_POS_PIN1, ADCCH_NEG_NONE, 1); adcch_set_interrupt_mode(&adcch_conf, ADCCH_MODE_COMPLETE); adcch_enable_interrupt(&adcch_conf); adcch_write_configuration(&ADCA, ADC_CH0, &adcch_conf); // Enable the ADC and start the first conversion. adc_enable(&ADCA); adc_start_conversion(&ADCA, ADC_CH0); do { // Sleep until ADC interrupt triggers. sleepmgr_enter_sleep(); } while (1); }
int main(void) { struct adc_config adc_conf; struct adc_channel_config adcch_conf; board_init(); sysclk_init(); sleepmgr_init(); irq_initialize_vectors(); cpu_irq_enable(); // Initialize configuration structures. adc_read_configuration(&ADCA, &adc_conf); adcch_read_configuration(&ADCA, ADC_CH0, &adcch_conf); /* Configure the ADC module: * - unsigned, 12-bit results * - bandgap (1 V) voltage reference * - 200 kHz maximum clock rate * - manual conversion triggering * - temperature sensor enabled * - callback function */ adc_set_conversion_parameters(&adc_conf, ADC_SIGN_OFF, ADC_RES_12, ADC_REF_BANDGAP); adc_set_clock_rate(&adc_conf, 200000UL); adc_set_conversion_trigger(&adc_conf, ADC_TRIG_MANUAL, 1, 0); adc_enable_internal_input(&adc_conf, ADC_INT_TEMPSENSE); adc_write_configuration(&ADCA, &adc_conf); adc_set_callback(&ADCA, &adc_handler); /* Configure ADC channel 0: * - single-ended measurement from temperature sensor * - interrupt flag set on completed conversion * - interrupts disabled */ adcch_set_input(&adcch_conf, ADCCH_POS_TEMPSENSE, ADCCH_NEG_NONE, 1); adcch_set_interrupt_mode(&adcch_conf, ADCCH_MODE_COMPLETE); adcch_enable_interrupt(&adcch_conf); adcch_write_configuration(&ADCA, ADC_CH0, &adcch_conf); // Get measurement for 85 degrees C (358 kelvin) from calibration data. tempsense = adc_get_calibration_data(ADC_CAL_TEMPSENSE); // Enable the ADC and start the first conversion. adc_enable(&ADCA); adc_start_conversion(&ADCA, ADC_CH0); do { // Sleep until ADC interrupt triggers. sleepmgr_enter_sleep(); } while (1); }
void owltemp_init() { struct adc_config adc_conf; struct adc_channel_config adcch_conf; // Clear the configuration structures. memset(&adc_conf, 0, sizeof(struct adc_config)); memset(&adcch_conf, 0, sizeof(struct adc_channel_config)); /* Configure the ADC module: * - unsigned, 12-bit results * - bandgap (1 V) voltage reference * - 200 kHz maximum clock rate * - manual conversion triggering * - temperature sensor enabled * - callback function */ adc_set_conversion_parameters(&adc_conf, ADC_SIGN_OFF, ADC_RES_12, ADC_REF_BANDGAP); adc_set_clock_rate(&adc_conf, 200000UL); adc_set_conversion_trigger(&adc_conf, ADC_TRIG_MANUAL, 0, 0); adc_enable_internal_input(&adc_conf, ADC_INT_TEMPSENSE); adc_write_configuration(&ADCA, &adc_conf); adc_set_callback(&ADCA, &adc_handler); /* Configure ADC channel 0: * - single-ended measurement from temperature sensor * - interrupt flag set on completed conversion * - interrupts disabled */ adcch_set_input(&adcch_conf, ADCCH_POS_TEMPSENSE, ADCCH_NEG_NONE, 1); adcch_set_interrupt_mode(&adcch_conf, ADCCH_MODE_COMPLETE); adcch_enable_interrupt(&adcch_conf); adcch_write_configuration(&ADCA, 0, &adcch_conf); // Get measurement for 85 degrees C (358 kelvin) from calibration data. tempsense = adc_get_calibration_data(ADC_CAL_TEMPSENSE); // Enable the ADC and start the first conversion. adc_enable(&ADCA); adc_start_conversion(&ADCA, ADC_CH0); }
void app_sampling_init(void) { /* QDec configuration */ qdec_get_config_defaults(&qdec_config); qdec_config_phase_pins(&qdec_config, &PORTA, 6, false, 500); qdec_config_enable_rotary(&qdec_config); qdec_config_tc(&qdec_config, &TCC5); qdec_config_revolution(&qdec_config, 40); qdec_enabled(&qdec_config); /* ! ADC module configuration */ struct adc_config adc_conf; /* Configure the ADC module: * - signed, 12-bit results * - VCC reference * - 200 kHz maximum clock rate * - manual conversion triggering * - callback function */ adc_read_configuration(&LIGHT_SENSOR_ADC_MODULE, &adc_conf); adc_set_conversion_parameters(&adc_conf, ADC_SIGN_ON, ADC_RES_12, ADC_REF_VCC); adc_set_clock_rate(&adc_conf, 200000); adc_set_conversion_trigger(&adc_conf, ADC_TRIG_MANUAL, 1, 0); adc_write_configuration(&LIGHT_SENSOR_ADC_MODULE, &adc_conf); adc_set_callback(&LIGHT_SENSOR_ADC_MODULE, &app_sampling_handler); adc_enable(&LIGHT_SENSOR_ADC_MODULE); /* Configure ADC A channel 0 for light and NTC sensors. * - differantial measurement (V- linked on internal GND) * - gain x0.5 * - interrupt flag set on completed conversion * - interrupts enabled */ adcch_read_configuration(&LIGHT_SENSOR_ADC_MODULE, ADC_CH0, &adcch_conf); adcch_set_input(&adcch_conf, LIGHT_SENSOR_ADC_INPUT, ADCCH_NEG_INTERNAL_GND, 0); adcch_set_interrupt_mode(&adcch_conf, ADCCH_MODE_COMPLETE); adcch_enable_interrupt(&adcch_conf); adcch_write_configuration(&LIGHT_SENSOR_ADC_MODULE, ADC_CH0, &adcch_conf); fifo_init(&app_sampling_fifo_desc, app_sampling_fifo_buffer, APP_SAMPLING_FIFO_SIZE); rtc_set_callback(&app_sampling_start); /* Display background */ gfx_mono_draw_line(DISPLAY_SAMPLING_TEXT_POS_X - 3, 0, DISPLAY_SAMPLING_TEXT_POS_X - 3, 32, GFX_PIXEL_SET); app_sampling_display_rate(); gfx_mono_draw_string(DISPLAY_LIGHT_TEXT, DISPLAY_LIGHT_TEXT_POS_X, DISPLAY_LIGHT_TEXT_POS_Y, &sysfont); gfx_mono_draw_filled_rect( DISPLAY_LIGHT_PROBAR_START_POS_X, DISPLAY_LIGHT_PROBAR_START_POS_Y, DISPLAY_LIGHT_PROBAR_START_SIZE_X, DISPLAY_LIGHT_PROBAR_START_SIZE_Y, GFX_PIXEL_SET); gfx_mono_draw_filled_rect( DISPLAY_LIGHT_PROBAR_STOP_POS_X, DISPLAY_LIGHT_PROBAR_STOP_POS_Y, DISPLAY_LIGHT_PROBAR_STOP_SIZE_X, DISPLAY_LIGHT_PROBAR_STOP_SIZE_Y, GFX_PIXEL_SET); /* Start a RTC alarm immediatly */ rtc_set_alarm_relative(0); }
/** * \brief Show menu for error insertion and handle user's selection. * * This function changes device configurations and does some hacks to make * the device behave incorrectly. * * The menu entries are * - Change clock frequency: Changes the peripheral clock divider, simulating * that the clock system has malfunctioned. This should be detected by the * Class B frequency consistency test. * * - Mess with test timer: Changes how often periodic tests are performed, * simulating an error with an interrupt timer. This should be detected by * the Class B interrupt monitor. * * - Change a Flash section: Changes the string for the menu title stored in * program memory to "Out of cheese", simulating Flash memory corruption. * This can be changed back by selecting the menu item again. This should be * detected by the Class B Flash CRC test. * * - Scramble SRAM section: Starts a continuous DMA transfer in the background * to a memory location, simulating transient SRAM corruption. This should * be detected by the periodic and power-on Class B SRAM test. * * - Enter infinite loop: Simulates a runaway program counter by looping * forever. This should be detected by the watchdog timer system which is * tested on device power-up. * * - Change ADC reference: Enables a callback function for the ADC, which will * change the voltage reference after the next completed conversion. This * will cause the analog IO test to fail when user turns up the power to the * plate. */ void oven_classb_error_insertion(void) { uint8_t menu_status; struct keyboard_event input; struct adc_channel_config adcch_conf; /* Initialize menu system */ gfx_mono_menu_init(&error_menu); /* Wait for user to select something in the menu system */ do { do { keyboard_get_key_state(&input); oven_wdt_periodic_reset(); /* Wait for key release */ } while (input.type != KEYBOARD_RELEASE); /* Send key to menu system */ menu_status = gfx_mono_menu_process_key(&error_menu, input.keycode); oven_wdt_periodic_reset(); } while (menu_status == GFX_MONO_MENU_EVENT_IDLE); /* Handle the user's selection */ switch (menu_status) { case 0: /* Change cpu frequency by modifying the prescalers */ sysclk_set_prescalers(CLK_PSADIV_4_gc, CLK_PSBCDIV_1_1_gc); break; case 1: /* Change timing of the periodic temperature tests */ OVEN_PERIODIC_TEMPTEST_TC.CTRLA = TC_CLKSEL_DIV256_gc; break; case 2: /* Change flash section. */ oven_classb_flash_corrupter(); break; case 3: /* Disrupt SRAM by setting up the DMA to write to a location on * the heap, triggered by the class B frequency monitor timer */ PR.PRGEN &= ~PR_DMA_bm; DMA.CTRL |= DMA_ENABLE_bm; DMA.CH0.TRIGSRC = DMA_CH_TRIGSRC_TCD1_CCA_gc; /* Address of Timer D1 CNT base is 0x0960. */ DMA.CH0.SRCADDR0 = 0x60; DMA.CH0.SRCADDR1 = 0x09; DMA.CH0.SRCADDR2 = 0x00; DMA.CH0.DESTADDR0 = ((uint16_t)&variable_for_sram_error) & 0xFF; DMA.CH0.DESTADDR1 = (((uint16_t)&variable_for_sram_error) >> 8) & 0xFF; DMA.CH0.DESTADDR2 = 0x00; DMA.CH0.CTRLA = DMA_CH_BURSTLEN_2BYTE_gc | DMA_CH_REPEAT_bm | DMA_CH_ENABLE_bm; break; case 4: /* Enter infinite loop */ while (1) { } break; case 5: /* Set up ADC channel interrupt */ adc_set_callback(&ADCA, adc_foul_callback); adcch_read_configuration(&ADCA, ADC_CH0, &adcch_conf); adcch_enable_interrupt(&adcch_conf); adcch_write_configuration(&ADCA, ADC_CH0, &adcch_conf); adcch_read_configuration(&ADCA, ADC_CH2, &adcch_conf); adcch_enable_interrupt(&adcch_conf); adcch_write_configuration(&ADCA, ADC_CH2, &adcch_conf); break; case 6: /* Back */ break; case GFX_MONO_MENU_EVENT_EXIT: /* Fall through to default */ default: /* Nothing, go back. */ break; } }
int main(void) { struct adc_config adc_conf; struct adc_channel_config adcch_conf; board_init(); sysclk_init(); sleepmgr_init(); irq_initialize_vectors(); cpu_irq_enable(); // Initialize configuration structures. adc_read_configuration(&ADCA, &adc_conf); adcch_read_configuration(&ADCA, ADC_CH0, &adcch_conf); /* Configure the ADC module: * - unsigned, 12-bit results * - bandgap (1 V) voltage reference * - 200 kHz maximum clock rate * - manual conversion triggering */ adc_set_conversion_parameters(&adc_conf, ADC_SIGN_OFF, ADC_RES_12, ADC_REF_BANDGAP); adc_set_clock_rate(&adc_conf, 200000UL); adc_set_conversion_trigger(&adc_conf, ADC_TRIG_MANUAL, 1, 0); adc_write_configuration(&ADCA, &adc_conf); /* Configure ADC channel 0: * - single-ended measurement from configured input pin * - interrupt flag set on completed conversion */ adcch_set_input(&adcch_conf, INPUT_PIN, ADCCH_NEG_NONE, 1); adcch_set_interrupt_mode(&adcch_conf, ADCCH_MODE_COMPLETE); adcch_disable_interrupt(&adcch_conf); adcch_write_configuration(&ADCA, ADC_CH0, &adcch_conf); // Enable the ADC and do one dummy conversion. adc_enable(&ADCA); adc_start_conversion(&ADCA, ADC_CH0); adc_wait_for_interrupt_flag(&ADCA, ADC_CH0); // Light up LED 1, wait for button press. ioport_set_pin_low(LED1_PIN); wait_for_button(); // Perform oversampling of offset. cal_data.offset = get_mean_sample_value(); // Light up LED 2, wait for button press. ioport_set_pin_low(LED2_PIN); wait_for_button(); // Perform oversampling of 0.9 V for gain calibration. cal_data.gain = get_mean_sample_value() - cal_data.offset; // Turn off LEDs. ioport_set_pin_high(LED1_PIN); ioport_set_pin_high(LED2_PIN); // Enable interrupts on ADC channel, then trigger first conversion. adcch_enable_interrupt(&adcch_conf); adcch_write_configuration(&ADCA, ADC_CH0, &adcch_conf); adc_start_conversion(&ADCA, ADC_CH0); do { // Sleep until ADC interrupt triggers. sleepmgr_enter_sleep(); } while (1); }
/** * \brief This function processes sampled ADC values and calculate * the oversampling result * - Offset error compensation is applied on accumulated ADC value * - After, scaling is done with scaled factor. * - Finally, Analog value at ADC input pin is calculated * - Reset all variable used in ADC ISR and enable ADC interrupt to start * next oversampling Process. */ void adc_oversampled(void) { /* ***********Processing and display of oversampled * Input************* **/ /* Assign sign as +ve (as zero) in default for Rrw ADC count display */ uint8_t sign_flag = 0; /* Offset error Compensation for entire number of samples */ adc_result_accum_processed = adc_result_accumulator - adc_offset; /* Gain error Compensation for entire number of samples */ adc_result_accum_processed = (adc_result_accum_processed * ADC_GAIN_ERROR_FACTOR) >> 16; /* Scale the accumulated result to get over sampled Result */ adc_result_accum_processed = adc_result_accum_processed >> ADC_OVER_SAMP_SCALING_FACTOR; /* Calculate the analog input voltage value * - Input Analog value = (ADC_Count * Reference * Volt)/(2^adcresolution)) */ v_input = (adc_result_accum_processed) * (ADC_OVER_SAMP_REF_VOLT_IN_MICRO); v_input = v_input / ADC_OVER_SAMP_MAX_COUNT; /* If input is negative, assign sign for display and use absolute value */ if (v_input < 0) { v_input = abs(v_input); v_input_ascii_buf[0] = '-'; } else { v_input_ascii_buf[0] = '+'; } /* Convert calculated analog value to ASCII for display */ convert_to_ascii(&v_input_ascii_buf[ASCII_BUFFER_SIZE - 1], v_input); /* Display the result on LCD display */ gfx_mono_draw_string(v_input_ascii_buf, 0, 10, &sysfont); /* If ADC count is negative, assign sign for display and use absolute * value */ if (adc_result_accum_processed < 0) { adc_result_accum_processed = abs(adc_result_accum_processed); sign_flag = 1; } else { sign_flag = 0; } /* Display oversampled raw ADC count on LCD display */ display_adccount((int64_t)adc_result_accum_processed, (uint8_t)42, sign_flag ); /* ***********Processing and display of Single Sampled * Input************* **/ /* Offset error compensation for one sample */ adc_result_one_sample_processed = adc_result_one_sample - adc_offset_one_sample; /* Gain error compensation for one sample */ adc_result_one_sample_processed = (adc_result_one_sample_processed * ADC_GAIN_ERROR_FACTOR) >> 16; /* Calculate the analog input voltage value without oversampling * - Input analog value = (ADC_Count * Reference * Volt)/(2^adcresolution)) */ v_input_one_sample = (adc_result_one_sample_processed) * (ADC_OVER_SAMP_REF_VOLT_IN_MICRO); v_input_one_sample = v_input_one_sample / ADC_NO_OVER_SAMP_MAX_COUNT; /* If input is negative, assign sign for display and use absolute value */ if (v_input_one_sample < 0) { v_input_one_sample = abs(v_input_one_sample); v_input_ascii_buf[0] = '-'; } else { v_input_ascii_buf[0] = '+'; } /* Convert calculated analog value to ASCII for display(no oversampling) */ convert_to_ascii(&v_input_ascii_buf[ASCII_BUFFER_SIZE - 1], v_input_one_sample); /* Display the result on LCD display(no oversampling) */ gfx_mono_draw_string(v_input_ascii_buf, 75, 10, &sysfont); /* If ADC count is negative, assign sign for display and use absolute * value */ if (adc_result_one_sample_processed < 0) { adc_result_one_sample_processed = abs( adc_result_one_sample_processed); sign_flag = 1; } else { sign_flag = 0; } /* Display oversampled raw ADC count on LCD display */ display_adccount((int64_t)adc_result_one_sample_processed, (uint8_t)117, sign_flag ); /*Reset ADC_result accumulator value and ADC_sample count to zero * for next oversampling process */ adc_result_accumulator = 0; adc_result_accum_processed = 0; adc_samplecount = 0; adc_result_one_sample = 0; adc_result_one_sample_processed = 0; /* Configure conversion complete interrupt for ADCB-CH0 to re-start * over sampling */ adcch_set_interrupt_mode(&adc_ch_conf, ADCCH_MODE_COMPLETE); adcch_enable_interrupt(&adc_ch_conf); adcch_write_configuration(&ADCB, ADC_CH0, &adc_ch_conf); }
/** * \brief This function initialize the ADCB,gets ADCB-CH0 offset and configure * ADCB-CH0 for oversampling * - ADCB-CH0 is configured in 12bit, signed differential mode without gain * - To read ADC offset, ADCB-Pin3(PB3) used as both +ve and -ve input * - After reading ADC offset,to start oversampling,ADCB +ve and -ve input * are configured */ void init_adc(void) { /* Initialize configuration structures */ adc_read_configuration(&ADCB, &adc_conf); adcch_read_configuration(&ADCB, ADC_CH0, &adc_ch_conf); /* Configure the ADCB module: * - Signed, 12-bit resolution * - External reference on AREFB pin. * - 250 KSPS ADC clock rate * - Manual conversion triggering * - Callback function */ adc_set_conversion_parameters(&adc_conf, ADC_SIGN_ON, ADC_RES_12, ADC_REF_AREFB); adc_set_clock_rate(&adc_conf, 250000UL); adc_set_conversion_trigger(&adc_conf, ADC_TRIG_MANUAL, 1, 0); adc_write_configuration(&ADCB, &adc_conf); adc_set_callback(&ADCB, &adc_handler); /* Configure ADC B channel 0 for offset calculation * - Differential mode without gain * - Selected Pin3 (PB3) as +ve and -ve input for offset calculation */ adcch_set_input(&adc_ch_conf, ADCCH_POS_PIN3, ADCCH_NEG_PIN3, 1); adcch_write_configuration(&ADCB, ADC_CH0, &adc_ch_conf); /* Enable ADCB */ adc_enable(&ADCB); /* Get ADC offset in to ADC_Offset variable and disable ADC */ adc_offset_one_sample = adc_offset_get_signed(); /* Find ADC_Offset for for total number of samples */ adc_offset = adc_offset_one_sample * ADC_OVER_SAMPLED_NUMBER; /* Disable ADC to configure for oversampling */ adc_disable(&ADCB); /* Configure the ADCB module for oversampling: * - Signed, 12-bit resolution * - External reference on AREFB pin. * - 250 KSPS ADC clock rate * - Free running mode on Channel0 ( First Channel) */ adc_set_conversion_trigger(&adc_conf, ADC_TRIG_FREERUN_SWEEP, 1, 0); adc_write_configuration(&ADCB, &adc_conf); /* Configure ADC B channel 0 for oversampling input * - Differential mode without gain * - Selected Pin1 (PB1) as +ve and Pin2 (PB2) as-ve input * - Conversion complete interrupt */ adcch_set_input(&adc_ch_conf, ADC_OVER_SAMP_POSTIVE_PIN, ADC_OVER_SAMP_NEGATIVE_PIN, 1); adcch_set_interrupt_mode(&adc_ch_conf, ADCCH_MODE_COMPLETE); adcch_enable_interrupt(&adc_ch_conf); adcch_write_configuration(&ADCB, ADC_CH0, &adc_ch_conf); /* Enable ADCB */ adc_enable(&ADCB); }