int main (void) { uint8_t menu_status; struct keyboard_event input; static usart_rs232_options_t SERIAL_OPTIONS = { .baudrate = 57600, .charlength = USART_CHSIZE_8BIT_gc, .paritytype = USART_PMODE_DISABLED_gc, .stopbits = false }; sysclk_init(); board_init(); solenoid_init(); gfx_mono_init(); usart_init_rs232(USART_SERIAL, &SERIAL_OPTIONS); gpio_toggle_pin(NHD_C12832A1Z_BACKLIGHT); while(true) { gfx_mono_menu_init(&main_menu); do { do { keyboard_get_key_state(&input); } while (input.type != KEYBOARD_RELEASE); menu_status = gfx_mono_menu_process_key(&main_menu, input.keycode); } while (menu_status == GFX_MONO_MENU_EVENT_IDLE); //Determine what song to play based on //the input from the user controlling the A3BU switch(menu_status) { case 0: song_menu(0); play_song_with_input(SAMPLE_SONG, SAMPLE_SONG_LENGTH); break; case 1: song_menu(1); play_song_with_input(STAIRWAY, 6); break; case 2: song_menu(2); play_song_with_input(MISERLOU, 1); break; case 3: song_menu(3); play_serial(); break; } } }
/** * \brief Show a menu presenting the date and time applications */ void date_time_application(void) { uint8_t menu_status; struct keyboard_event input; while(true) { gfx_mono_menu_init(&datetime_menu); do { do { keyboard_get_key_state(&input); // Wait for key release } while (input.type != KEYBOARD_RELEASE); // Send key to menu system menu_status = gfx_mono_menu_process_key(&datetime_menu, input.keycode); // Wait for something useful to happen in the menu system } while (menu_status == GFX_MONO_MENU_EVENT_IDLE); switch(menu_status) { case 0: display_date_time_application(); break; case 1: set_date_application(); break; case 2: set_time_application(); break; case 3: timezone_select_application(); break; default: // Return to the main menu on unknown element or back key return; } } }
/** * \brief Main function. * * Initializes the board and reads out the production date stored in EEPROM and * set timezone from EEPROM if it is set. If it is not set it will open the * timezone selector to select the local timezone. It then runs the menu system * in an infinite while loop. */ int main(void) { uint8_t menu_status; struct keyboard_event input; uint32_t rtc_timestamp; sysclk_init(); board_init(); pmic_init(); gfx_mono_init(); touch_init(); adc_sensors_init(); // Enable display backlight gpio_set_pin_high(NHD_C12832A1Z_BACKLIGHT); // Workaround for known issue: Enable RTC32 sysclk sysclk_enable_module(SYSCLK_PORT_GEN, SYSCLK_RTC); while (RTC32.SYNCCTRL & RTC32_SYNCBUSY_bm) { // Wait for RTC32 sysclk to become stable } // If we have battery power and RTC is running, don't initialize RTC32 if (rtc_vbat_system_check(false) != VBAT_STATUS_OK) { rtc_init(); // Set current time to after production date rtc_timestamp = production_date_get_timestamp() + 1; rtc_set_time(rtc_timestamp); } // Get current time rtc_timestamp = rtc_get_time(); // Make sure RTC has not been set to a too early date . if (rtc_timestamp < FIRST_POSSIBLE_TIMESTAMP) { // Set time to 01.01.2011 00:00:00 rtc_set_time(FIRST_POSSIBLE_TIMESTAMP); } // Initialize USB CDC class cdc_start(); cpu_irq_enable(); // Display a splash screen showing button functions button_splash(); // Set timezone from EEPROM or to a default value timezone_init(); /* Main loop. Read keyboard status and pass input to menu system. * When an element has been selected in the menu, it will return the * index of the element that should be run. This can be an application * or another menu. */ while (true) { // (re)initialize menu system gfx_mono_menu_init(&main_menu); do { do { keyboard_get_key_state(&input); // Wait for key release } while (input.type != KEYBOARD_RELEASE); // Send key to menu system menu_status = gfx_mono_menu_process_key(&main_menu, input.keycode); // Wait for something useful to happen in the menu system } while (menu_status == GFX_MONO_MENU_EVENT_IDLE); switch (menu_status) { case 0: ntc_sensor_application(); break; case 1: lightsensor_application(); break; case 2: production_date_application(); break; case 3: date_time_application(); break; case 4: // Toggle LCD Backlight gpio_toggle_pin(NHD_C12832A1Z_BACKLIGHT); break; case GFX_MONO_MENU_EVENT_EXIT: // Fall trough to default and show button splash default: button_splash(); break; }; } }
/** * \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; } }