/** * \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); } }
/** * \internal * \brief Test spinning through a spincollection and cancelling * * This test checks that spinning in a spincollection with two spinners * and pressing the back button results in the correct event. * * \param test Current test case. */ static void run_event_back_spincollection_test(const struct test_case *test) { int16_t actual[2]; uint8_t actual_status_code; uint8_t expected_status_code; struct gfx_mono_spinctrl spinner; struct gfx_mono_spinctrl spinner2; struct gfx_mono_spinctrl_spincollection spincollection; expected_status_code = GFX_MONO_SPINCTRL_EVENT_BACK; // Initialize spinners and spincollection and add spinners to collection gfx_mono_spinctrl_init(&spinner, SPINTYPE_INTEGER, spinnertitle2, NULL, 40, 48, 0); gfx_mono_spinctrl_init(&spinner2, SPINTYPE_INTEGER, spinnertitle3, NULL, 55, 110, 0); gfx_mono_spinctrl_spincollection_init(&spincollection); gfx_mono_spinctrl_spincollection_add_spinner(&spinner, &spincollection); gfx_mono_spinctrl_spincollection_add_spinner(&spinner2, &spincollection); // Go down to next spinner gfx_mono_spinctrl_spincollection_process_key(&spincollection, GFX_MONO_SPINCTRL_KEYCODE_DOWN, actual); // Select current spinner gfx_mono_spinctrl_spincollection_process_key(&spincollection, GFX_MONO_SPINCTRL_KEYCODE_ENTER, actual); // Spin spinner gfx_mono_spinctrl_spincollection_process_key(&spincollection, GFX_MONO_SPINCTRL_KEYCODE_DOWN, actual); // Spin spinner gfx_mono_spinctrl_spincollection_process_key(&spincollection, GFX_MONO_SPINCTRL_KEYCODE_DOWN, actual); // Spin spinner gfx_mono_spinctrl_spincollection_process_key(&spincollection, GFX_MONO_SPINCTRL_KEYCODE_DOWN, actual); // Deselect spinner gfx_mono_spinctrl_spincollection_process_key(&spincollection, GFX_MONO_SPINCTRL_KEYCODE_BACK, actual); // Cancel spincollection actual_status_code = gfx_mono_spinctrl_spincollection_process_key( &spincollection, GFX_MONO_SPINCTRL_KEYCODE_BACK, actual); test_assert_true(test, actual_status_code == expected_status_code, "Status code mismatch: %d != %d", actual_status_code, expected_status_code); }
/** * \internal * \brief Test spinning through a spincollection with only one spinner * * This test checks that spinning in a spincollection with only one integer * spinner gives the correct result. * * \param test Current test case. */ static void run_single_spinner_spincollection_test(const struct test_case *test) { int16_t actual[1]; int16_t expected[1]; uint8_t actual_status_code; uint8_t expected_status_code; struct gfx_mono_spinctrl spinner; struct gfx_mono_spinctrl_spincollection spincollection; expected[0] = 46; expected_status_code = GFX_MONO_SPINCTRL_EVENT_FINISH; // Initialize spinner and spincollection and add spinner to collection gfx_mono_spinctrl_init(&spinner, SPINTYPE_INTEGER, spinnertitle2, NULL, 40, 48, 0); gfx_mono_spinctrl_spincollection_init(&spincollection); gfx_mono_spinctrl_spincollection_add_spinner(&spinner, &spincollection); // Choose spinner gfx_mono_spinctrl_spincollection_process_key(&spincollection, GFX_MONO_SPINCTRL_KEYCODE_ENTER, actual); // Step up spinner value gfx_mono_spinctrl_spincollection_process_key(&spincollection, GFX_MONO_SPINCTRL_KEYCODE_UP, actual); // Step up spinner value gfx_mono_spinctrl_spincollection_process_key(&spincollection, GFX_MONO_SPINCTRL_KEYCODE_UP, actual); // Step up spinner value gfx_mono_spinctrl_spincollection_process_key(&spincollection, GFX_MONO_SPINCTRL_KEYCODE_UP, actual); // Step up spinner value gfx_mono_spinctrl_spincollection_process_key(&spincollection, GFX_MONO_SPINCTRL_KEYCODE_UP, actual); // Step up spinner value gfx_mono_spinctrl_spincollection_process_key(&spincollection, GFX_MONO_SPINCTRL_KEYCODE_UP, actual); // Step up spinner value gfx_mono_spinctrl_spincollection_process_key(&spincollection, GFX_MONO_SPINCTRL_KEYCODE_UP, actual); // Select current spinner value gfx_mono_spinctrl_spincollection_process_key(&spincollection, GFX_MONO_SPINCTRL_KEYCODE_ENTER, actual); // Go down to OK button gfx_mono_spinctrl_spincollection_process_key(&spincollection, GFX_MONO_SPINCTRL_KEYCODE_DOWN, actual); // Select OK button actual_status_code = gfx_mono_spinctrl_spincollection_process_key( &spincollection, GFX_MONO_SPINCTRL_KEYCODE_ENTER, actual); test_assert_true(test, actual_status_code == expected_status_code, "Status code mismatch: %d != %d", actual_status_code, expected_status_code); test_assert_true(test, actual[0] == expected[0], "Result mismatch: %d != %d", actual[0], expected[0]); }
/** * \brief Main entry of example application */ int main(void) { struct gfx_mono_spinctrl spinner1; struct gfx_mono_spinctrl spinner2; struct gfx_mono_spinctrl spinner3; struct gfx_mono_spinctrl_spincollection spinners; /** * Starts off by initializing the system clock before configuring the * board and the monochrome graphical system. */ system_init(); gfx_mono_init(); int16_t tmp[3]; // Initialize spinners gfx_mono_spinctrl_init(&spinner1, SPINTYPE_STRING, spinnertitle, spinner_choicestrings, 0, 3, 0); gfx_mono_spinctrl_init(&spinner2, SPINTYPE_INTEGER, spinnertitle2, NULL, -60, -41, 0); gfx_mono_spinctrl_init(&spinner3, SPINTYPE_INTEGER, spinnertitle3, NULL, 19999, 20200, 0); // Initialize spincollection gfx_mono_spinctrl_spincollection_init(&spinners); // Add spinners to spincollection gfx_mono_spinctrl_spincollection_add_spinner(&spinner1, &spinners); gfx_mono_spinctrl_spincollection_add_spinner(&spinner2, &spinners); gfx_mono_spinctrl_spincollection_add_spinner(&spinner3, &spinners); // Show spincollection on screen gfx_mono_spinctrl_spincollection_show(&spinners); // Spincollection is now ready to process input from user while(1) { gfx_mono_spinctrl_spincollection_process_key(&spinners, GFX_MONO_SPINCTRL_KEYCODE_DOWN, tmp); delay_s(1); gfx_mono_spinctrl_spincollection_process_key(&spinners, GFX_MONO_SPINCTRL_KEYCODE_ENTER, tmp); delay_s(1); } }
/** * \brief Main entry of example application */ int main(void) { struct gfx_mono_spinctrl spinner1; struct gfx_mono_spinctrl spinner2; struct gfx_mono_spinctrl spinner3; struct gfx_mono_spinctrl_spincollection spinners; int16_t results[GFX_MONO_SPINCTRL_MAX_ELEMENTS_IN_SPINCOLLECTION]; /** * Starts off by initializing the system clock before configuring the * board and the monochrome graphical system. */ board_init(); sysclk_init(); gfx_mono_init(); // Initialize spinners gfx_mono_spinctrl_init(&spinner1, SPINTYPE_STRING, spinnertitle, spinner_choicestrings, 0, 3, 0); gfx_mono_spinctrl_init(&spinner2, SPINTYPE_INTEGER, spinnertitle2, NULL, -60, -41, 0); gfx_mono_spinctrl_init(&spinner3, SPINTYPE_INTEGER, spinnertitle3, NULL, 19999, 20200, 0); // Initialize spincollection gfx_mono_spinctrl_spincollection_init(&spinners); // Add spinners to spincollection gfx_mono_spinctrl_spincollection_add_spinner(&spinner1, &spinners); gfx_mono_spinctrl_spincollection_add_spinner(&spinner2, &spinners); gfx_mono_spinctrl_spincollection_add_spinner(&spinner3, &spinners); // Show spincollection on screen gfx_mono_spinctrl_spincollection_show(&spinners); // Spincollection is now ready to process input from user while(1) { // Intentionally left empty. } }
/** * \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); }
/** * \internal * \brief Test selecting a spinner in a spincollection, changing and saving its * value, then selecting the spinner again, but this time not saving the result. * * This test checks that spinning in a spincollection with three spinners, * selecting a spinner, changing and saving its value and then select and * change its value again, but this time not saving, will result in the saved * result being stored in the results array. * * \param test Current test case. */ static void run_cancel_spinner_spincollection_test(const struct test_case *test) { int16_t actual[3]; int16_t expected[3]; uint8_t actual_status_code; uint8_t expected_status_code; struct gfx_mono_spinctrl spinner; struct gfx_mono_spinctrl spinner2; struct gfx_mono_spinctrl spinner3; struct gfx_mono_spinctrl_spincollection spincollection; expected[0] = 40; expected[1] = 108; expected[2] = 1; expected_status_code = GFX_MONO_SPINCTRL_EVENT_FINISH; // Initialize spinners and spincollection and add spinners to collection gfx_mono_spinctrl_init(&spinner, SPINTYPE_INTEGER, spinnertitle2, NULL, 40, 48, 0); gfx_mono_spinctrl_init(&spinner2, SPINTYPE_INTEGER, spinnertitle3, NULL, 55, 110, 0); gfx_mono_spinctrl_init(&spinner3, SPINTYPE_STRING, spinnertitle, spinner_choicestrings, 0, 3, 0); gfx_mono_spinctrl_spincollection_init(&spincollection); gfx_mono_spinctrl_spincollection_add_spinner(&spinner, &spincollection); gfx_mono_spinctrl_spincollection_add_spinner(&spinner2, &spincollection); gfx_mono_spinctrl_spincollection_add_spinner(&spinner3, &spincollection); // Go down to next spinner gfx_mono_spinctrl_spincollection_process_key(&spincollection, GFX_MONO_SPINCTRL_KEYCODE_DOWN, actual); // Select current spinner gfx_mono_spinctrl_spincollection_process_key(&spincollection, GFX_MONO_SPINCTRL_KEYCODE_ENTER, actual); // Spin spinner gfx_mono_spinctrl_spincollection_process_key(&spincollection, GFX_MONO_SPINCTRL_KEYCODE_DOWN, actual); // Spin spinner gfx_mono_spinctrl_spincollection_process_key(&spincollection, GFX_MONO_SPINCTRL_KEYCODE_DOWN, actual); // Spin spinner gfx_mono_spinctrl_spincollection_process_key(&spincollection, GFX_MONO_SPINCTRL_KEYCODE_DOWN, actual); // Select spinner value gfx_mono_spinctrl_spincollection_process_key(&spincollection, GFX_MONO_SPINCTRL_KEYCODE_ENTER, actual); // Go down to next spinner gfx_mono_spinctrl_spincollection_process_key(&spincollection, GFX_MONO_SPINCTRL_KEYCODE_DOWN, actual); //Select current spinner gfx_mono_spinctrl_spincollection_process_key(&spincollection, GFX_MONO_SPINCTRL_KEYCODE_ENTER, actual); // Spin spinner gfx_mono_spinctrl_spincollection_process_key(&spincollection, GFX_MONO_SPINCTRL_KEYCODE_UP, actual); // Select current value gfx_mono_spinctrl_spincollection_process_key(&spincollection, GFX_MONO_SPINCTRL_KEYCODE_ENTER, actual); // Go up to previous spinner gfx_mono_spinctrl_spincollection_process_key(&spincollection, GFX_MONO_SPINCTRL_KEYCODE_UP, actual); // Select current spinner gfx_mono_spinctrl_spincollection_process_key(&spincollection, GFX_MONO_SPINCTRL_KEYCODE_ENTER, actual); // Spin spinner gfx_mono_spinctrl_spincollection_process_key(&spincollection, GFX_MONO_SPINCTRL_KEYCODE_UP, actual); // Spin spinner gfx_mono_spinctrl_spincollection_process_key(&spincollection, GFX_MONO_SPINCTRL_KEYCODE_UP, actual); // Deselect spinner gfx_mono_spinctrl_spincollection_process_key(&spincollection, GFX_MONO_SPINCTRL_KEYCODE_BACK, actual); // Go down to next spinner gfx_mono_spinctrl_spincollection_process_key(&spincollection, GFX_MONO_SPINCTRL_KEYCODE_DOWN, actual); // Go down to OK button gfx_mono_spinctrl_spincollection_process_key(&spincollection, GFX_MONO_SPINCTRL_KEYCODE_DOWN, actual); // Select OK button actual_status_code = gfx_mono_spinctrl_spincollection_process_key( &spincollection, GFX_MONO_SPINCTRL_KEYCODE_ENTER, actual); test_assert_true(test, actual_status_code == expected_status_code, "Status code mismatch: %d != %d", actual_status_code, expected_status_code); test_assert_true(test, actual[0] == expected[0], "Result mismatch from spinner: 1 %d != %d", actual[0], expected[0]); test_assert_true(test, actual[1] == expected[1], "Result mismatch from spinner 2: %d != %d", actual[1], expected[1]); test_assert_true(test, actual[2] == expected[2], "Result mismatch from spinner 3: %d != %d", actual[2], expected[2]); }
/** * \internal * \brief Test spinning through a spincollection with two spinners * * This test checks that spinning in a spincollection with one integer * spinner and one string spinner gives the correct result. * * \param test Current test case. */ static void run_two_spinners_spincollection_test(const struct test_case *test) { int16_t actual[2]; int16_t expected[2]; uint8_t actual_status_code; uint8_t expected_status_code; struct gfx_mono_spinctrl spinner1; struct gfx_mono_spinctrl spinner2; struct gfx_mono_spinctrl_spincollection spincollection; expected[0] = 3; expected[1] = 2; expected_status_code = GFX_MONO_SPINCTRL_EVENT_FINISH; // Initialize spinners and spincollection and add spinners to collection gfx_mono_spinctrl_init(&spinner1, SPINTYPE_INTEGER, spinnertitle2, NULL, -1, 3, 0); gfx_mono_spinctrl_init(&spinner2, SPINTYPE_STRING, spinnertitle, spinner_choicestrings, 0, 3, 0); gfx_mono_spinctrl_spincollection_init(&spincollection); gfx_mono_spinctrl_spincollection_add_spinner(&spinner1, &spincollection); gfx_mono_spinctrl_spincollection_add_spinner(&spinner2, &spincollection); // Go down to next spinner gfx_mono_spinctrl_spincollection_process_key(&spincollection, GFX_MONO_SPINCTRL_KEYCODE_DOWN, actual); // Select spinner gfx_mono_spinctrl_spincollection_process_key(&spincollection, GFX_MONO_SPINCTRL_KEYCODE_ENTER, actual); // Step up spinner value gfx_mono_spinctrl_spincollection_process_key(&spincollection, GFX_MONO_SPINCTRL_KEYCODE_UP, actual); // Step up spinner value gfx_mono_spinctrl_spincollection_process_key(&spincollection, GFX_MONO_SPINCTRL_KEYCODE_UP, actual); // Select spinner value gfx_mono_spinctrl_spincollection_process_key(&spincollection, GFX_MONO_SPINCTRL_KEYCODE_ENTER, actual); // Go down to OK button gfx_mono_spinctrl_spincollection_process_key(&spincollection, GFX_MONO_SPINCTRL_KEYCODE_DOWN, actual); // Go down (wrap around) to first spinner gfx_mono_spinctrl_spincollection_process_key(&spincollection, GFX_MONO_SPINCTRL_KEYCODE_DOWN, actual); // Select current spinner gfx_mono_spinctrl_spincollection_process_key(&spincollection, GFX_MONO_SPINCTRL_KEYCODE_ENTER, actual); // Step down spinner value gfx_mono_spinctrl_spincollection_process_key(&spincollection, GFX_MONO_SPINCTRL_KEYCODE_DOWN, actual); // Select spinner value gfx_mono_spinctrl_spincollection_process_key(&spincollection, GFX_MONO_SPINCTRL_KEYCODE_ENTER, actual); // Go down to next spinner gfx_mono_spinctrl_spincollection_process_key(&spincollection, GFX_MONO_SPINCTRL_KEYCODE_DOWN, actual); // Go down to OK button gfx_mono_spinctrl_spincollection_process_key(&spincollection, GFX_MONO_SPINCTRL_KEYCODE_DOWN, actual); // Select OK button actual_status_code = gfx_mono_spinctrl_spincollection_process_key( &spincollection, GFX_MONO_SPINCTRL_KEYCODE_ENTER, actual); test_assert_true(test, actual_status_code == expected_status_code, "Status code mismatch: %d != %d", actual_status_code, expected_status_code); test_assert_true(test, actual[0] == expected[0], "Result mismatch from spinner 1: %d != %d", actual[0], expected[0]); test_assert_true(test, actual[1] == expected[1], "Result mismatch from spinner 2: %d != %d", actual[1], expected[1]); }