/** * \brief Show explanation screen * * This function draws an explanation screen, and is run if the applications are * started without the jumpers described in the documentation attached. */ static void show_explain_splash(void) { struct keyboard_event input; /* Clear screen */ gfx_mono_draw_filled_rect(0, 0, 128, 32, GFX_PIXEL_CLR); gfx_mono_draw_string("Class B Demonstration", 1, 4, &sysfont); gfx_mono_draw_string("See Application note", 4, 12, &sysfont); gfx_mono_draw_string("AVR1610", 40, 20, &sysfont); /* Any key will exit the loop */ while (true) { oven_wdt_periodic_reset(); keyboard_get_key_state(&input); if (input.type == KEYBOARD_RELEASE) { break; } } /* Clear screen */ gfx_mono_draw_filled_rect(0, 0, 128, 32, GFX_PIXEL_CLR); gfx_mono_draw_string("Attach jumpers betwe-", 0, 4, &sysfont); gfx_mono_draw_string("en ADC2-ADC4 on J2,", 0, 12, &sysfont); gfx_mono_draw_string("and RXD-SS on J1", 0, 20, &sysfont); /* Any key will exit the loop */ while (true) { oven_wdt_periodic_reset(); } }
/** * \brief Show button names on display */ void button_splash(void) { struct keyboard_event input; // Clear screen gfx_mono_draw_filled_rect(0, 0, 128, 32, GFX_PIXEL_CLR); gfx_mono_draw_filled_circle(10, 10, 4, GFX_PIXEL_SET, GFX_WHOLE); gfx_mono_draw_filled_circle(10, 22, 4, GFX_PIXEL_SET, GFX_WHOLE); gfx_mono_draw_filled_circle(117, 10, 4, GFX_PIXEL_SET, GFX_WHOLE); gfx_mono_draw_filled_circle(117, 22, 4, GFX_PIXEL_SET, GFX_WHOLE); gfx_mono_draw_string("Up", 90, 8, &sysfont); gfx_mono_draw_string("Down", 80, 20, &sysfont); gfx_mono_draw_string("Enter", 20, 8, &sysfont); gfx_mono_draw_string("Back", 20, 20, &sysfont); // Any key will exit the loop while (true) { keyboard_get_key_state(&input); if (input.type == KEYBOARD_RELEASE) { break; } } }
/** * \brief Show button names on display * * This function shows the user what the different on-board buttons do. When * the user presses a button, this function exits and the application can * continue. */ static void show_button_splash(void) { struct keyboard_event input; /* Clear screen */ gfx_mono_draw_filled_rect(0, 0, 128, 32, GFX_PIXEL_CLR); gfx_mono_draw_filled_circle(6, 6, 3, GFX_PIXEL_SET, GFX_WHOLE); gfx_mono_draw_filled_circle(6, 24, 3, GFX_PIXEL_SET, GFX_WHOLE); gfx_mono_draw_filled_circle(122, 6, 3, GFX_PIXEL_SET, GFX_WHOLE); gfx_mono_draw_filled_circle(122, 24, 3, GFX_PIXEL_SET, GFX_WHOLE); gfx_mono_draw_string("Oven power/", 50, 0, &sysfont); gfx_mono_draw_string("Up", 94, 8, &sysfont); gfx_mono_draw_string("Down", 90, 22, &sysfont); gfx_mono_draw_string("Menu/", 12, 0, &sysfont); gfx_mono_draw_string("Back", 12, 8, &sysfont); gfx_mono_draw_string("Pot/enter", 12, 22, &sysfont); /* Any key will exit the loop */ while (true) { oven_wdt_periodic_reset(); keyboard_get_key_state(&input); if (input.type == KEYBOARD_RELEASE) { break; } } }
/** * \brief Set the time using a spinner widget */ static void set_time_application(void) { struct keyboard_event input; struct calendar_date date; uint32_t timestamp; uint8_t tz_hours; uint8_t tz_minutes; struct gfx_mono_spinctrl hour_spinner; struct gfx_mono_spinctrl minute_spinner; struct gfx_mono_spinctrl_spincollection time_spinners; uint8_t spinner_status; int16_t spinner_results[2]; // Prepare the spinner widget for time selection gfx_mono_spinctrl_init(&hour_spinner, SPINTYPE_INTEGER, datetime_date_spinner_string_hour, NULL, 0, 23, 0); gfx_mono_spinctrl_init(&minute_spinner, SPINTYPE_INTEGER, datetime_date_spinner_string_minute, NULL, 0, 59, 0); // Create time spincollector gfx_mono_spinctrl_spincollection_init(&time_spinners); gfx_mono_spinctrl_spincollection_add_spinner(&hour_spinner, &time_spinners); gfx_mono_spinctrl_spincollection_add_spinner(&minute_spinner, &time_spinners); // Get timezone settings tz_hours = timezone_get_hours(); tz_minutes = timezone_get_minutes(); timestamp = rtc_get_time(); calendar_timestamp_to_date_tz(timestamp, tz_hours, tz_minutes, &date); // Set spinners to current time as initial position hour_spinner.integer_data = date.hour; minute_spinner.integer_data = date.minute; gfx_mono_spinctrl_spincollection_show(&time_spinners); do { do { keyboard_get_key_state(&input); // Wait for key release } while (input.type != KEYBOARD_RELEASE); // Send key to spinnercollection spinner_status = gfx_mono_spinctrl_spincollection_process_key( &time_spinners, input.keycode, spinner_results); } while (spinner_status != GFX_MONO_SPINCTRL_EVENT_FINISH); date.hour = spinner_results[0]; date.minute = spinner_results[1]; timestamp = calendar_date_to_timestamp_tz(&date, tz_hours, tz_minutes); if(timestamp != 0) { rtc_set_time(timestamp); } }
/** * \brief Lightsensor application * * This application will output the lightsensor value read by the ADC both as * a raw value and by drawing a bar that represent the amount of light hitting * the sensor. * The raw value is sampled 200 times and the average value is used. */ void lightsensor_application(void) { struct keyboard_event input_key; char string_buf[10]; uint32_t lightsensor_val = 0; uint8_t scaled; uint8_t iterations = 0; // Clear screen gfx_mono_draw_filled_rect(0, 0, 128, 32, GFX_PIXEL_CLR); // Put icons at the bottom of the screen indicating light intensity gfx_mono_put_bitmap(&bitmap_moon, 1, 24); // ~1 lux gfx_mono_put_bitmap(&bitmap_cloud, 30, 24); // ~200 lux gfx_mono_put_bitmap(&bitmap_indoor, 60, 24); // ~400 lux gfx_mono_put_bitmap(&bitmap_sun, 118, 24); // ~850 lux // Draw static strings outside the loop gfx_mono_draw_string("Lightsensor", 0, 0, &sysfont); gfx_mono_draw_string("Raw value:", 0, 8, &sysfont); while (true) { // Start an ADC conversion of the lightsensor lightsensor_measure(); while (!lightsensor_data_is_ready()) { // Wait until the conversion is complete } lightsensor_val += lightsensor_get_raw_value(); // Let's average some samples to be outputted if (iterations++ >= LIGHTSENSOR_NUM_SAMPLES) { iterations = 0; lightsensor_val /= LIGHTSENSOR_NUM_SAMPLES; snprintf(string_buf, sizeof(string_buf), "%4ld", lightsensor_val); gfx_mono_draw_string(string_buf, 70, 8, &sysfont); // Scale down to LCD width for drawing bar scaled = lightsensor_val >> 4; // Graphic bar representing the light level gfx_mono_draw_filled_rect(0, 17,scaled, 7, GFX_PIXEL_SET); gfx_mono_draw_filled_rect(scaled, 17,128 - scaled, 7, GFX_PIXEL_CLR); lightsensor_val = 0; } // exit if the "back" button has been pressed and released keyboard_get_key_state(&input_key); if ((input_key.keycode == KEYBOARD_BACK) && (input_key.type == KEYBOARD_RELEASE)) { break; } }
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; } } }
/* Wrapper function that will play the song and also accept an input from the A3BU keyboard buttons */ static void play_song_with_input(struct SongNote song[], uint8_t song_length) { struct keyboard_event key; while(true) { keyboard_get_key_state(&key); if((key.keycode == KEYBOARD_ENTER) && (key.type == KEYBOARD_RELEASE)) { break; } play_song(song, song_length); } }
void network_application() { draw_background(); gfx_draw_filled_rect(5, 26, 310, 182, GFX_COLOR(20, 20, 20)); if(!wifi_ready && wifi_error) { gfx_draw_string_aligned(SYMFONT_WIFI, gfx_get_width() / 2, 120, &symbol_sysfont, GFX_COLOR_TRANSPARENT, GFX_COLOR_RED, TEXT_POS_CENTER_X, TEXT_ALIGN_CENTER); gfx_draw_string_aligned("Not Connected", gfx_get_width() / 2, 155, &sysfont, GFX_COLOR_TRANSPARENT, GFX_COLOR_RED, TEXT_POS_CENTER_X, TEXT_ALIGN_CENTER); } else { gfx_draw_string_aligned(SYMFONT_WIFI, gfx_get_width() / 2, 120, &symbol_sysfont, GFX_COLOR_TRANSPARENT, GFX_COLOR_GREEN, TEXT_POS_CENTER_X, TEXT_ALIGN_CENTER); gfx_draw_string_aligned("Connected", gfx_get_width() / 2, 155, &sysfont, GFX_COLOR_TRANSPARENT, GFX_COLOR_GREEN, TEXT_POS_CENTER_X, TEXT_ALIGN_CENTER); } uint8_t ram_buf[AT45DBX_SECTOR_SIZE]; at45dbx_read_sector_open(0x0007); at45dbx_read_sector_to_ram(ram_buf); at45dbx_read_close(); char mac_string[128]; snprintf(mac_string, sizeof(mac_string), "MAC: %s", ram_buf); gfx_draw_string_aligned(mac_string, 11, 27, &small_sysfont, GFX_COLOR_TRANSPARENT, GFX_COLOR_WHITE, TEXT_POS_LEFT, TEXT_ALIGN_LEFT); if (wifi_error) { gfx_draw_string_aligned(esp_error, 11, 47, &small_sysfont, GFX_COLOR_TRANSPARENT, GFX_COLOR_WHITE, TEXT_POS_LEFT, TEXT_ALIGN_LEFT); } struct keyboard_event input; while(mma8451_orientation() != 6) { esp8266_check_buffer(); keyboard_get_key_state(&input); if (input.type == KEYBOARD_RELEASE) { if (input.keycode == KEYBOARD_B) { break; } } if(mma8451_clear_interrupt() && is_low_power()) { exit_low_power(); } } }
/** * \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 Display current date and time in the selected timezone */ static void display_date_time_application(void) { struct calendar_date date; struct keyboard_event input_key; uint8_t width; uint8_t height; uint8_t offset; int8_t tz_hours_temp; int8_t tz_minutes_temp; uint32_t past_timestamp = 0xFFFFFFFF; uint32_t rtc_timestamp = 0; char string_buf[32] = "Date & Time"; //clear screen gfx_mono_draw_filled_rect(0, 0, 128, 32, GFX_PIXEL_CLR); // Get current timestamp from the RTC32 rtc_timestamp = rtc_get_time(); // Get timezone settings tz_hours_temp = timezone_get_hours(); tz_minutes_temp = timezone_get_minutes(); // Print "Date & Time" at first line of the display 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, 0, &sysfont); // Convert RTC time to a date struct containing the current date and time calendar_timestamp_to_date_tz(rtc_timestamp, tz_hours_temp, tz_minutes_temp, &date); while (true) { // Return from application if "back" key is pressed and released keyboard_get_key_state(&input_key); if ((input_key.keycode == KEYBOARD_BACK) && (input_key.type == KEYBOARD_RELEASE)) { break; } rtc_timestamp = rtc_get_time(); // Update printed time if the time has changed if(rtc_timestamp != past_timestamp) { calendar_add_second_to_date(&date); // Print current date centered on line 3 snprintf(string_buf, sizeof(string_buf),"%s %.2d.%.2d.%d", day[date.dayofweek], date.date + 1, date.month + 1, date.year); 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, 12, &sysfont); snprintf(string_buf, sizeof(string_buf), "%.2d:%.2d:%.2d", date.hour, date.minute, date.second); // Center text 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, 20, &sysfont); past_timestamp = rtc_timestamp; } } }
void schedule_application() { unsigned long now = rtc_get_time(); if (now < 1445990399) { // day 1 } else if (now > 1445990399 && now < 1446076799) { // day 2 } else if (now > 1446076799 && now < 1446163199) { // day 3 } else { // day 4 } uint16_t max_event[] = {5, 26, 25, 18, 26, 13}; //write_data(); //gfx_draw_filled_rect(0, 0, gfx_get_width(), gfx_get_height(), GFX_COLOR_BLACK); draw_background(); //gfx_draw_filled_rect(0, 0, 320, 182, GFX_COLOR(20, 20, 20)); draw_time(); // gfx_draw_string_aligned("Schedule - Keynotes", 11, 2, &sysfont, GFX_COLOR_BLACK, GFX_COLOR_WHITE, TEXT_POS_LEFT, TEXT_ALIGN_LEFT); // gfx_draw_string_aligned("Schedule - Track 1", 11, 2, &sysfont, GFX_COLOR_BLACK, GFX_COLOR_WHITE, TEXT_POS_LEFT, TEXT_ALIGN_LEFT); // gfx_draw_string_aligned("Schedule - Track 2", 11, 2, &sysfont, GFX_COLOR_BLACK, GFX_COLOR_WHITE, TEXT_POS_LEFT, TEXT_ALIGN_LEFT); // gfx_draw_string_aligned("Schedule - Track 3", 11, 2, &sysfont, GFX_COLOR_BLACK, GFX_COLOR_WHITE, TEXT_POS_LEFT, TEXT_ALIGN_LEFT); // gfx_draw_string_aligned("Schedule - Track 4", 11, 2, &sysfont, GFX_COLOR_BLACK, GFX_COLOR_WHITE, TEXT_POS_LEFT, TEXT_ALIGN_LEFT); event_index = 0; event_track = 0; draw_event(); // Presentors // Location and time // Description struct keyboard_event input; while(mma8451_orientation() != 6) { esp8266_check_buffer(); keyboard_get_key_state(&input); if (input.type == KEYBOARD_RELEASE) { if (input.keycode == KEYBOARD_B) { break; } else if (input.keycode == KEYBOARD_A) { } else if (input.keycode == KEYBOARD_UP) { event_index--; if (event_index < 0) { event_index = 0; } draw_event(); } else if (input.keycode == KEYBOARD_DOWN) { event_index++; if (event_index > max_event[event_track]) { event_index = max_event[event_track]; } draw_event(); } else if (input.keycode == KEYBOARD_RIGHT) { event_index = 0; event_track++; if (event_track > 5) { event_track = 0; } draw_event(); } else if (input.keycode == KEYBOARD_LEFT) { event_index = 0; event_track--; if (event_track < 0) { event_track = 5; } draw_event(); } } if(mma8451_clear_interrupt() && is_low_power()) { exit_low_power(); } } }
/** * \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; }; } }
/** * \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; } }
/** * \brief Set the date using a spinner widget. * * This function will set show a spinner widget that lets the user select the * current date. This function will leave the clock unchanged, and only change * the date part of the RTC32 timestamp. */ static void set_date_application(void) { struct calendar_date date; struct calendar_date new_date; struct keyboard_event input; uint32_t current_timestamp; uint32_t new_timestamp; uint8_t tz_hours; uint8_t tz_minutes; struct gfx_mono_spinctrl year_spinner; struct gfx_mono_spinctrl month_spinner; struct gfx_mono_spinctrl day_spinner; struct gfx_mono_spinctrl_spincollection date_spinners; int16_t spinner_results[3]; uint8_t spinner_status; // Prepare the spinner widget for date selection gfx_mono_spinctrl_init(&year_spinner, SPINTYPE_INTEGER, datetime_date_spinner_string_year, NULL, 2011, 2105, 0); gfx_mono_spinctrl_init(&month_spinner, SPINTYPE_INTEGER, datetime_date_spinner_string_month, NULL, 1, 12, 0); gfx_mono_spinctrl_init(&day_spinner, SPINTYPE_INTEGER, datetime_date_spinner_string_day, NULL, 1, 31, 0); // Create date spincollector gfx_mono_spinctrl_spincollection_init(&date_spinners); gfx_mono_spinctrl_spincollection_add_spinner(&year_spinner, &date_spinners); gfx_mono_spinctrl_spincollection_add_spinner(&month_spinner, &date_spinners); gfx_mono_spinctrl_spincollection_add_spinner(&day_spinner, &date_spinners); // Get timezone settings tz_hours = timezone_get_hours(); tz_minutes = timezone_get_minutes(); // Get current time current_timestamp = rtc_get_time(); // Convert the current timestamp to a datestruct calendar_timestamp_to_date_tz(current_timestamp, tz_hours, tz_minutes, &date); // Set the spinner selection to the current date day_spinner.integer_data = date.date + 1; month_spinner.integer_data = date.month + 1; year_spinner.integer_data = date.year; // show the date selection spinner to get a new date gfx_mono_spinctrl_spincollection_show(&date_spinners); do { do { keyboard_get_key_state(&input); // Wait for key release } while (input.type != KEYBOARD_RELEASE); // Send key to spinnercollection spinner_status = gfx_mono_spinctrl_spincollection_process_key( &date_spinners, input.keycode, spinner_results); } while (spinner_status != GFX_MONO_SPINCTRL_EVENT_FINISH); /* The result are stored in the same order that they were added * we subtract one from month and day, as they are indexed from 0 in the * date struct but we present them as starting from 1 in the spinner. */ new_date.year = spinner_results[0]; new_date.month = spinner_results[1] - 1; new_date.date = spinner_results[2] - 1; // Verify date set new_date.hour = 0; new_date.minute = 0; new_date.second = 0; if (calendar_date_to_timestamp_tz(&new_date, tz_hours, tz_minutes) == 0) { //Notify the user that the date was invalid and wait for key gfx_mono_draw_filled_rect(0, 0, GFX_MONO_LCD_WIDTH, GFX_MONO_LCD_HEIGHT, GFX_PIXEL_CLR); gfx_mono_draw_progmem_string( (char PROGMEM_PTR_T)datetime_invalid_date_string, 10, 12, &sysfont); while (true) { keyboard_get_key_state(&input); if (input.type == KEYBOARD_RELEASE) { break; } } return; } // Date OK, change. // Get current time current_timestamp = rtc_get_time(); // Convert the current timestamp to a datestruct calendar_timestamp_to_date_tz(current_timestamp, tz_hours, tz_minutes, &date); // Set new date in struct date.year = new_date.year; date.month = new_date.month; date.date = new_date.date; // Convert back to timestamp new_timestamp = calendar_date_to_timestamp_tz(&date, tz_hours, tz_minutes); // Set new timestamp rtc_set_time(new_timestamp); }
void adc_application(void) { struct keyboard_event input_key; char string_buf[10]; uint32_t adca0_val = 0; uint32_t adca1_val = 0; uint32_t adca2_val = 0; uint32_t adca3_val = 0; uint32_t adcb0_val = 0; uint32_t adcb1_val = 0; uint32_t adcb2_val = 0; uint32_t adcb3_val = 0; // Clear screen gfx_mono_draw_filled_rect(0, 0, 128, 32, GFX_PIXEL_CLR); // Draw static strings outside the loop gfx_mono_draw_string("ADC0", 100, 0, &sysfont); gfx_mono_draw_string("ADC1", 100, 8, &sysfont); gfx_mono_draw_string("ADC2", 100, 16, &sysfont); gfx_mono_draw_string("ADC3", 100, 24, &sysfont); gfx_mono_draw_string("ADC4", 0, 0, &sysfont); gfx_mono_draw_string("ADC5", 0, 8, &sysfont); // gfx_mono_draw_string("ADC6", 0, 16, &sysfont); // gfx_mono_draw_string("ADC7", 0, 24, &sysfont); gfx_mono_draw_string("Light", 0, 16, &sysfont); gfx_mono_draw_string("NTC", 0, 24, &sysfont); while (true) { // Start an ADC conversion /*adc_start_conversion(&ADCA, ADC_CH0); adc_start_conversion(&ADCA, ADC_CH1); adc_start_conversion(&ADCA, ADC_CH2); adc_start_conversion(&ADCA, ADC_CH3);*/ lightsensor_measure(); ntc_measure(); adc_measure(); adc2_measure(); while (!adc_data_is_ready() && !adc2_data_is_ready() && !ntc_data_is_ready() && !lightsensor_data_is_ready()) { // Wait until the conversion is complete } //adc_wait_for_interrupt_flag(&ADCA, ADC_CH0); /*adc0_val = adc_get_result(&ADCA, ADC_CH0); adc1_val = adc_get_result(&ADCA, ADC_CH1); adc2_val = adc_get_result(&ADCA, ADC_CH2); adc3_val = adc_get_result(&ADCA, ADC_CH3);*/ adca0_val = lightsensor_get_raw_value(); adca1_val = ntc_get_raw_value(); adca2_val = adc_get_raw_value(); adca3_val = adc2_get_raw_value(); snprintf(string_buf, sizeof(string_buf), "%4ld", adca0_val); gfx_mono_draw_string(string_buf, 30, 16, &sysfont); snprintf(string_buf, sizeof(string_buf), "%4ld", adca1_val); gfx_mono_draw_string(string_buf, 30, 24, &sysfont); snprintf(string_buf, sizeof(string_buf), "%4ld", adca2_val); gfx_mono_draw_string(string_buf, 30, 0, &sysfont); snprintf(string_buf, sizeof(string_buf), "%4ld", adca3_val); gfx_mono_draw_string(string_buf, 30, 8, &sysfont); // Start an ADCB conversion /*adc_start_conversion(&ADCB, ADC_CH0); adc_start_conversion(&ADCB, ADC_CH1); adc_start_conversion(&ADCB, ADC_CH2); adc_start_conversion(&ADCB, ADC_CH3);*/ adcb0_measure(); adcb1_measure(); adcb2_measure(); adcb3_measure(); while (!adcb0_data_is_ready() && !adcb1_data_is_ready() && !adcb2_data_is_ready() && !adcb3_data_is_ready()) { // Wait until the conversion is complete } //adc_wait_for_interrupt_flag(&ADCB, ADC_CH0); /*adc0_val = adc_get_result(&ADCA, ADC_CH0); adc1_val = adc_get_result(&ADCA, ADC_CH1); adc2_val = adc_get_result(&ADCA, ADC_CH2); adc3_val = adc_get_result(&ADCA, ADC_CH3);*/ adcb0_val = adcb0_get_raw_value(); adcb1_val = adcb1_get_raw_value(); adcb2_val = adcb2_get_raw_value(); adcb3_val = adcb3_get_raw_value(); snprintf(string_buf, sizeof(string_buf), "%4ld", adcb0_val); gfx_mono_draw_string(string_buf, 60, 0, &sysfont); snprintf(string_buf, sizeof(string_buf), "%4ld", adcb1_val); gfx_mono_draw_string(string_buf, 60, 8, &sysfont); snprintf(string_buf, sizeof(string_buf), "%4ld", adcb2_val); gfx_mono_draw_string(string_buf, 60, 16, &sysfont); snprintf(string_buf, sizeof(string_buf), "%4ld", adcb3_val); gfx_mono_draw_string(string_buf, 60, 24, &sysfont); keyboard_get_key_state(&input_key); if ((input_key.keycode == KEYBOARD_ENTER) && (input_key.type == KEYBOARD_RELEASE)) { break; } } }
void battery_application() { draw_background(); gfx_draw_string_aligned("Power Info", gfx_get_width() / 2, 2, &sysfont, GFX_COLOR_TRANSPARENT, GFX_COLOR_WHITE, TEXT_POS_CENTER_X, TEXT_ALIGN_LEFT); uint8_t battery = max1704x_bat(); char batlvl[5]; if (battery > 100) { battery = 100; } //battery = 19; uint16_t x = 75; uint16_t y = 40; gfx_draw_rect(x, y, 164, 54, GFX_COLOR_WHITE); gfx_draw_filled_rect(x+164, y+15, 3, 20, GFX_COLOR_WHITE); if (battery < 20) { gfx_draw_filled_rect(x+2, y+2, battery/6 * 10, 50, GFX_COLOR_RED); } else { gfx_draw_filled_rect(x+2, y+2, battery/6 * 10, 50, GFX_COLOR_GREEN); } snprintf(batlvl, sizeof(batlvl), "%d%%", battery); if (battery > 20) { gfx_draw_string_aligned(batlvl, gfx_get_width() /2, 50, &large_sysfont, GFX_COLOR_TRANSPARENT, GFX_COLOR_WHITE, TEXT_POS_CENTER_X, TEXT_ALIGN_LEFT); } else { gfx_draw_string_aligned(batlvl, gfx_get_width() /2, 50, &large_sysfont, GFX_COLOR_TRANSPARENT, GFX_COLOR_WHITE, TEXT_POS_CENTER_X, TEXT_ALIGN_LEFT); } char atime[32]; snprintf(atime, sizeof(atime), "Seconds Awake: %lu", get_time_awake()); gfx_draw_string_aligned(atime, 70, 100, &sysfont, GFX_COLOR_TRANSPARENT, GFX_COLOR_WHITE, TEXT_POS_LEFT, TEXT_ALIGN_LEFT); char stime[32]; snprintf(stime, sizeof(stime), "Seconds Sleeping: %lu", get_time_sleep()); gfx_draw_string_aligned(stime, 70, 120, &sysfont, GFX_COLOR_TRANSPARENT, GFX_COLOR_WHITE, TEXT_POS_LEFT, TEXT_ALIGN_LEFT); gfx_draw_filled_circle(gfx_get_width() /2, 80+80+10+10, 25, GFX_COLOR_WHITE, GFX_WHOLE); gfx_draw_string_aligned(SYMFONT_MOON, gfx_get_width() /2, 152+10, &symbol_sysfont, GFX_COLOR_TRANSPARENT, GFX_COLOR(200, 101, 18), TEXT_POS_CENTER_X, TEXT_ALIGN_CENTER); gfx_draw_string_aligned("Enter Sleep Mode", gfx_get_width() / 2, 152+15+30+15, &sysfont, GFX_COLOR_TRANSPARENT, GFX_COLOR_WHITE, TEXT_POS_CENTER_X, TEXT_ALIGN_LEFT); struct keyboard_event input; while(mma8451_orientation() != 6) { esp8266_check_buffer(); if(mma8451_clear_interrupt() && is_low_power()) { exit_low_power(); } keyboard_get_key_state(&input); if (input.type == KEYBOARD_RELEASE) { if (input.keycode == KEYBOARD_B) { break; } else if (input.keycode == KEYBOARD_A) { esp8266_enter_standby(); enter_low_power(); break; } } } }