/** * \brief Production date application * * This application will display the time since the XMEGA-A3BU Xplained board * has been produced. During production the production time is stored in EEPROM * and the RTC is initialized to the same time. The RTC is then left running * from the battery backup. This application reads out the production date from * EEPROM and shows the difference between the current time and the production * date; in other words the time the RTC timer has been running on battery * since production. * * \note If the EEPROM is erased and no production date can be set, it will * default to time 01.01.1970, the start of the UNIX time epoch. */ void production_date_application(void) { struct keyboard_event input_key; uint32_t past_timestamp = 0xFFFFFFFF; uint32_t rtc_timestamp; struct calendar_date rtc_date; struct calendar_date date_diff; struct calendar_date production_date; uint32_t production_date_timestamp; uint16_t months; uint8_t width; uint8_t height; uint8_t offset; char string_buf[22]; // Clear screen gfx_mono_draw_filled_rect(0, 0, 128, 32, GFX_PIXEL_CLR); // Draw application title gfx_mono_draw_string("Time since production", 0, 0, &sysfont); // Get production timestamp production_date_timestamp = production_date_get_timestamp(); // Convert timestamp to date struct calendar_timestamp_to_date(production_date_timestamp, &production_date); // Exit the application if "back" key is pressed while (true) { keyboard_get_key_state(&input_key); if ((input_key.keycode == KEYBOARD_BACK) && (input_key.type == KEYBOARD_RELEASE)) { break; } // Get current time from RTC32 rtc_timestamp = rtc_get_time(); if (rtc_timestamp == past_timestamp) { // Same time as last time, no need for update continue; } past_timestamp = rtc_timestamp; // Convert timestamp to date struct calendar_timestamp_to_date(rtc_timestamp, &rtc_date); // Find the difference between the current date and production date calendar_time_between_dates(&rtc_date, &production_date, &date_diff); // Use months + year*12 as we are a line short to have both year and month months = (date_diff.year * 12) + date_diff.month; // Center month string on screen. Align day string with month string snprintf(string_buf, sizeof(string_buf), "%2d Months", months); gfx_mono_get_string_bounding_box(string_buf, &sysfont, &width, &height); offset = (GFX_MONO_LCD_WIDTH - width) / 2; gfx_mono_draw_string(string_buf, offset, 8, &sysfont); snprintf(string_buf, sizeof(string_buf), "%2d Days", date_diff.date); gfx_mono_draw_string(string_buf, offset, 16, &sysfont); // Display hour, minute, second snprintf(string_buf, sizeof(string_buf),"%.2d:%.2d:%.2d", date_diff.hour, date_diff.minute, date_diff.second); gfx_mono_get_string_bounding_box(string_buf, &sysfont, &width, &height); offset = (GFX_MONO_LCD_WIDTH - width) / 2; gfx_mono_draw_string(string_buf, offset, 24, &sysfont); } }
/** * \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; }; } }