/** * \brief Initialize Class B tests * * Set up timers, timer callbacks, initialize interrupt monitor, * add interrupts to be monitored. */ void oven_classb_init_tests(void) { /* == Frequency consistency test == */ /* Use Timer D1 for frequency consistency test */ tc_enable(&CLASSB_FREQTEST_TC); tc_set_overflow_interrupt_callback(&CLASSB_FREQTEST_TC, classb_freq_tc_callback); classb_freq_setup_timer(); /* == Frequency consistency test and interrupt monitor timer == */ /* Use relative RTC interrupt from ASF to execute periodic check for * frequency consistency and interrupt monitor. */ rtc_set_alarm_relative(CLASSB_RTC_INT_PERIOD); rtc_set_callback(classb_rtc_callback); /* TODO: Workaround: RTC32_COMPINTLVL is reset to OFF for some reason */ /* after set_alarm_relative is called the the first time. Set to LO. */ RTC32.INTCTRL = RTC32_COMPINTLVL_LO_gc; /* == Interrupt monitor test == */ /* Register the periodic temperature measurement sanity test in the * monitor. * It's run every 600ms => 3.41 times per RTC compare period of 2 secs. * 25% tolerance. */ classb_intmon_reg_int(TEMP_SANITY_TEST, 4, 25); /* Register the periodic classb test execution in the monitor. * It's run every 1000ms => 2 times per RTC compare period of 2 secs. * 50% tolerance. */ classb_intmon_reg_int(PER_CLASSB_TESTS, 2, 50); }
/** * \brief Callback function for ADC interrupts * * \param adc Pointer to ADC module. * \param channel ADC channel number. * \param result Conversion result from ADC channel. */ static void app_sampling_handler(ADC_t *adc, uint8_t channel, adc_result_t result) { /* Store ADC convertion result for the coresponding on-board sensor */ switch (adc_conv[adc_mux_index]) { case LIGHT_SENSOR_ADC_INPUT: light = 2048 - result; break; default: break; } /* Parse table of ADC conversions */ if (++adc_mux_index < sizeof(adc_conv)) { app_sampling_start_next_conversion(); return; } /* End of all conversions */ adc_mux_index = 0; /* Save values in FIFO */ if (2 > fifo_get_free_size(&app_sampling_fifo_desc)) { return; /* Error */ } fifo_push_uint16_nocheck(&app_sampling_fifo_desc, rtc_get_time()); fifo_push_uint16_nocheck(&app_sampling_fifo_desc, (uint16_t)light); LED_Off(LED1_GPIO); /* Enable the next RTC alarm */ app_sampling_rtc_run = true; rtc_set_alarm_relative(app_sampling_rate - 1); }
//TODO: Remove for testing static void alarm(uint32_t time) { ioport_set_pin_level(LED_0_PIN,!ioport_get_pin_level(LED_0_PIN)); //rtc_set_alarm_relative(1024); rtc_set_callback(alarm2); rtc_set_alarm_relative(32768*2); }
/** * \brief main function */ int main(void) { pmic_init(); board_init(); sysclk_init(); sleepmgr_init(); rtc_init(); rtc_set_callback(alarm); cpu_irq_enable(); /* The lowest value which is safe to use is 3. This the use of 2 could * happen in a second change, and we would not get an interrupt. A * value of 3 causes the alarm to be set of in 3-4 seconds. */ rtc_set_alarm_relative(3); while (true) { /* Alarm action is handled in alarm callback so we just go to * sleep here. */ sleepmgr_enter_sleep(); } }
//TODO: Remove for testing static void alarm2(uint32_t time) { int i; for (i=0; i<10; i++) { ioport_set_pin_level(LED_0_PIN,!ioport_get_pin_level(LED_0_PIN)); delay_ms(50); } rtc_set_callback(alarm); rtc_set_alarm_relative(32768); }
void init_vrtc(){ //real time clock inits pmic_init(); sysclk_init(); sleepmgr_init(); rtc_init(); cpu_irq_enable(); //v2x init soft_counter = 0x00; rtc_set_callback(alarm); rtc_set_alarm_relative(32768); }
/** * \brief Alarm callback * * This outputs the last two digits of current time in BCD on the board LEDS, * and then reschedules the alarm in 3 seconds. */ static void alarm(uint32_t time) { uint8_t bcd; // Extract last two digits from time, and put them in bcd bcd = time % 10; time -= bcd; time /= 10; bcd = bcd | ((time % 10) << 4); // LEDS on STK600 are active low, so invert the output bcd = ~bcd; LED_PORT.OUT = bcd; /* Since the next alarm will be rounded up to the next second pass, this will * actually happen in 3 seconds. */ rtc_set_alarm_relative(2); }
void app_sampling_task(void) { static uint16_t time_stamp; static uint8_t time_last; uint8_t time_pos; adc_result_t light; char string[30]; uint8_t light_bar_pos; irqflags_t flags; static uint16_t qdec_position_last = 2; uint16_t qdec_position; /* Manage frequency sample through Quadrature encoder */ qdec_position = qdec_get_position(&qdec_config) / 2; if (qdec_position != qdec_position_last) { /* Quadrature encoder have changed */ qdec_position_last = qdec_position; app_sampling_rate = (qdec_position_last + 1) * 2; flags = cpu_irq_save(); if (app_sampling_rtc_run) { time_stamp = rtc_get_time(); rtc_set_alarm_relative(app_sampling_rate - 1); } cpu_irq_restore(flags); app_sampling_display_rate(); } /* Update sampling progress bar */ time_pos = ((rtc_get_time() - time_stamp) * 8) / app_sampling_rate; if (time_pos > 8) { time_pos = 8; } if (time_last > time_pos) { gfx_mono_draw_filled_circle( DISPLAY_SAMPLING_PROCIRCLE_POS_X, DISPLAY_SAMPLING_PROCIRCLE_POS_Y, DISPLAY_SAMPLING_PROCIRCLE_RADIUS, GFX_PIXEL_CLR, GFX_WHOLE); } if (time_last != time_pos) { gfx_mono_draw_filled_circle( DISPLAY_SAMPLING_PROCIRCLE_POS_X, DISPLAY_SAMPLING_PROCIRCLE_POS_Y, DISPLAY_SAMPLING_PROCIRCLE_RADIUS, GFX_PIXEL_SET, (1lu << time_pos) - 1); } time_last = time_pos; /* Manage FIFO about sensor data */ if (2 > fifo_get_used_size(&app_sampling_fifo_desc)) { return; /* Not enought data */ } /* Get values */ time_stamp = fifo_pull_uint16_nocheck(&app_sampling_fifo_desc); light = (adc_result_t)fifo_pull_uint16_nocheck(&app_sampling_fifo_desc); /* Display values through USART */ sprintf(string, "%4u,%02us - %3d light\r\n", time_stamp / 4, (time_stamp % 4) * 25, light); printf("%s", string); /* Update light progress bar */ light_bar_pos = ((uint32_t)light * DISPLAY_LIGHT_PROBAR_MAX_SIZE_X) / 2048lu; if (light_bar_pos > DISPLAY_LIGHT_PROBAR_MAX_SIZE_X) { light_bar_pos = DISPLAY_LIGHT_PROBAR_MAX_SIZE_X; } gfx_mono_draw_filled_rect(DISPLAY_LIGHT_PROBAR_POS_X, DISPLAY_LIGHT_PROBAR_POS_Y, light_bar_pos, DISPLAY_LIGHT_PROBAR_SIZE_Y, GFX_PIXEL_SET); gfx_mono_draw_filled_rect(DISPLAY_LIGHT_PROBAR_POS_X + light_bar_pos, DISPLAY_LIGHT_PROBAR_POS_Y, DISPLAY_LIGHT_PROBAR_MAX_SIZE_X - light_bar_pos, DISPLAY_LIGHT_PROBAR_SIZE_Y, GFX_PIXEL_CLR); }
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); }