/** * \brief Draw spinner at its position. * * This function draws a spinner at its position. * The title of the spinner is only drawn if the redraw option is set. * If the spinner is in focus, arrows will be drawn next to the spinner value * to indicate that it is spinnable. * * \param spinner pointer to initialized gfx_mono_spinctrl struct * \param redraw true if title of spinner should be drawn */ void gfx_mono_spinctrl_draw(struct gfx_mono_spinctrl *spinner, bool redraw) { char string_buf[GFX_MONO_SPINCTRL_INT_SPINNER_WIDTH]; uint8_t index; uint8_t offset; if (redraw) { /* Clear line */ gfx_mono_draw_filled_rect(0, spinner->y, GFX_MONO_LCD_WIDTH, SYSFONT_HEIGHT, GFX_PIXEL_CLR); /* Draw title */ gfx_mono_draw_progmem_string((char PROGMEM_PTR_T)spinner->title, GFX_MONO_SPINCTRL_INDICATOR_WIDTH + 1, spinner->y, &sysfont); } if (spinner->in_focus) { gfx_mono_spinctrl_draw_spin_indicator(spinner, true); } else { gfx_mono_spinctrl_draw_spin_indicator(spinner, false); } if (spinner->datatype == SPINTYPE_INTEGER) { offset = GFX_MONO_LCD_WIDTH - (SYSFONT_WIDTH * GFX_MONO_SPINCTRL_INT_SPINNER_WIDTH); snprintf(string_buf, sizeof(string_buf), "%d", spinner->integer_data); /* Delete previous spinner data */ gfx_mono_draw_filled_rect(offset, spinner->y, GFX_MONO_LCD_WIDTH - offset - GFX_MONO_SPINCTRL_SPIN_INDICATOR_WIDTH, SYSFONT_HEIGHT, GFX_PIXEL_CLR); /* Draw integer data */ gfx_mono_draw_string(string_buf, offset, spinner->y, &sysfont); } else if (spinner->datatype == SPINTYPE_STRING) { index = spinner->strings.index; offset = GFX_MONO_LCD_WIDTH - (SYSFONT_WIDTH * GFX_MONO_SPINCTRL_STRING_SPINNER_WIDTH); /* Delete previous spinner data */ gfx_mono_draw_filled_rect(offset, spinner->y, GFX_MONO_LCD_WIDTH - offset - GFX_MONO_SPINCTRL_SPIN_INDICATOR_WIDTH, SYSFONT_HEIGHT, GFX_PIXEL_CLR); /* Draw string data */ gfx_mono_draw_progmem_string( (char PROGMEM_PTR_T)spinner->strings.data[index], offset, spinner->y, &sysfont); } }
/* Function to draw the menu of the song that is currently being played */ void song_menu(uint8_t song_choice) { gfx_mono_draw_filled_rect(0, 0, 128, 32, GFX_PIXEL_CLR); //Clear the screen gfx_mono_draw_string("Currently Playing: ", 1, 2, &sysfont); gfx_mono_draw_progmem_string((char PROGMEM_PTR_T)main_menu_strings[song_choice], 1, 10, &sysfont); }
/** * *\brief Initialize the menu handling. Clear screen and draw menu. * * \param menu menu struct with menu options * */ void gfx_mono_menu_init(struct gfx_mono_menu *menu) { /* Clear screen */ gfx_mono_draw_filled_rect(0, 0, GFX_MONO_LCD_WIDTH, GFX_MONO_LCD_HEIGHT, GFX_PIXEL_CLR); /* Draw the menu title on the top of the screen */ gfx_mono_draw_progmem_string((char PROGMEM_PTR_T)menu->title, 0, 0, &sysfont); /* Draw menu options below */ menu_draw(menu, true); }
/** * \brief Draw menu strings and an icon by the current selection. * * \param menu a menu struct with menu settings * \param redraw clear screen before drawing menu */ static void menu_draw(struct gfx_mono_menu *menu, bool redraw) { static bool redraw_state; uint8_t i; uint8_t line = 1; uint8_t menu_page = menu->current_selection / GFX_MONO_MENU_ELEMENTS_PER_SCREEN; if (menu->current_page != menu_page || redraw == true) { /* clear screen if we have changed the page or menu and prepare * redraw */ gfx_mono_draw_filled_rect(0, SYSFONT_LINESPACING, GFX_MONO_LCD_WIDTH, GFX_MONO_LCD_HEIGHT - SYSFONT_LINESPACING, GFX_PIXEL_CLR); redraw_state = true; } menu->current_page = menu_page; /* Clear old indicator icon */ gfx_mono_draw_filled_rect(0, SYSFONT_LINESPACING, GFX_MONO_MENU_INDICATOR_WIDTH, GFX_MONO_LCD_HEIGHT - SYSFONT_LINESPACING, GFX_PIXEL_CLR); /* Put indicator icon on current selection */ gfx_mono_put_bitmap(&menu_bitmap_indicator, 0, SYSFONT_LINESPACING * ((menu->current_selection % GFX_MONO_MENU_ELEMENTS_PER_SCREEN) + 1)); /* Print visible options if page or menu has changed */ if (redraw_state == true) { for (i = menu_page * GFX_MONO_MENU_ELEMENTS_PER_SCREEN; i < menu_page * GFX_MONO_MENU_ELEMENTS_PER_SCREEN + GFX_MONO_MENU_ELEMENTS_PER_SCREEN && i < menu->num_elements; i++) { gfx_mono_draw_progmem_string( (char PROGMEM_PTR_T)menu->strings[i], GFX_MONO_MENU_INDICATOR_WIDTH + 1, line * SYSFONT_LINESPACING, &sysfont); line++; } redraw_state = false; } }
/** * \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); }