diff options
author | Joey Castillo <jose.castillo@gmail.com> | 2021-10-03 18:49:21 -0400 |
---|---|---|
committer | Joey Castillo <jose.castillo@gmail.com> | 2021-10-03 19:08:40 -0400 |
commit | 27df51d40a29baea8c50a25ed2345b1293a5089c (patch) | |
tree | 024de64122e4a5d239acc6bd52565b5a1fa5f161 | |
parent | 8d5280a34f1159d8af0277ba04b7e1cb9c8bd7ac (diff) | |
download | Sensor-Watch-27df51d40a29baea8c50a25ed2345b1293a5089c.tar.gz Sensor-Watch-27df51d40a29baea8c50a25ed2345b1293a5089c.tar.bz2 Sensor-Watch-27df51d40a29baea8c50a25ed2345b1293a5089c.zip |
launcher app with clock and preferences menu
-rw-r--r-- | launcher/launcher.c | 41 | ||||
-rw-r--r-- | launcher/launcher.h | 14 | ||||
-rw-r--r-- | launcher/launcher_config.h | 6 | ||||
-rwxr-xr-x | launcher/make/Makefile | 4 | ||||
-rw-r--r-- | launcher/widgets/clock/simple_clock_widget.c | 86 | ||||
-rw-r--r-- | launcher/widgets/clock/simple_clock_widget.h | 20 | ||||
-rw-r--r-- | launcher/widgets/fake_widget_1.c | 10 | ||||
-rw-r--r-- | launcher/widgets/fake_widget_1.h | 3 | ||||
-rw-r--r-- | launcher/widgets/fake_widget_2.c | 8 | ||||
-rw-r--r-- | launcher/widgets/fake_widget_2.h | 3 | ||||
-rw-r--r-- | launcher/widgets/settings/preferences_widget.c | 121 | ||||
-rw-r--r-- | launcher/widgets/settings/preferences_widget.h | 18 |
12 files changed, 304 insertions, 30 deletions
diff --git a/launcher/launcher.c b/launcher/launcher.c index ff10cf6e..8dc38199 100644 --- a/launcher/launcher.c +++ b/launcher/launcher.c @@ -13,7 +13,10 @@ void cb_alarm_pressed(); void cb_tick(); void launcher_request_tick_frequency(uint8_t freq) { + // FIXME: there is an issue where after changing tick frequencies on a widget switch, something glitchy happens on the next one. watch_rtc_disable_all_periodic_callbacks(); + launcher_state.subsecond = 0; + launcher_state.tick_frequency = freq; watch_rtc_register_periodic_callback(cb_tick, freq); } @@ -21,26 +24,24 @@ void launcher_illuminate_led() { launcher_state.light_ticks = 3; } -void launcher_move_to_next_widget() { +void launcher_move_to_widget(uint8_t widget_index) { launcher_state.widget_changed = true; widgets[launcher_state.current_widget].resign(&launcher_state.launcher_settings, widget_contexts[launcher_state.current_widget]); - launcher_state.current_widget = (launcher_state.current_widget + 1) % LAUNCHER_NUM_WIDGETS; + launcher_state.current_widget = widget_index; + watch_clear_display(); widgets[launcher_state.current_widget].activate(&launcher_state.launcher_settings, widget_contexts[launcher_state.current_widget]); - watch_display_string(widgets[launcher_state.current_widget].widget_name, 0); + widgets[launcher_state.current_widget].loop(EVENT_ACTIVATE, &launcher_state.launcher_settings, launcher_state.subsecond, widget_contexts[launcher_state.current_widget]); } -void launcher_move_to_first_widget() { - launcher_state.widget_changed = true; - widgets[launcher_state.current_widget].resign(&launcher_state.launcher_settings, widget_contexts[launcher_state.current_widget]); - launcher_state.current_widget = 0; - widgets[0].activate(&launcher_state.launcher_settings, widget_contexts[0]); - watch_display_string(widgets[launcher_state.current_widget].widget_name, 0); +void launcher_move_to_next_widget() { + launcher_move_to_widget((launcher_state.current_widget + 1) % LAUNCHER_NUM_WIDGETS); } void app_init() { memset(&launcher_state, 0, sizeof(launcher_state)); launcher_state.launcher_settings.bit.led_green_color = 0xF; - launcher_state.launcher_settings.bit.led_red_color = 0x0; + watch_date_time date_time = watch_rtc_get_date_time(); + watch_rtc_set_date_time(date_time); } void app_wake_from_deep_sleep() { @@ -60,10 +61,10 @@ void app_setup() { launcher_request_tick_frequency(1); for(uint8_t i = 0; i < LAUNCHER_NUM_WIDGETS; i++) { - widgets[i].setup(&launcher_state.launcher_settings, widget_contexts[i]); + widgets[i].setup(&launcher_state.launcher_settings, &widget_contexts[i]); } - launcher_move_to_first_widget(); + launcher_move_to_widget(0); } void app_prepare_for_sleep() { @@ -77,8 +78,8 @@ LauncherEvent event; bool app_loop() { // play a beep if the widget has changed in response to a user's press of the MODE button if (launcher_state.widget_changed) { - // low note for nonzero case, high note for return to clock - watch_buzzer_play_note(launcher_state.current_widget ? BUZZER_NOTE_C7 : BUZZER_NOTE_C8, 100); + // low note for nonzero case, high note for return to widget 0 + watch_buzzer_play_note(launcher_state.current_widget ? BUZZER_NOTE_C7 : BUZZER_NOTE_C8, 50); launcher_state.widget_changed = false; } @@ -102,7 +103,7 @@ bool app_loop() { } if (event) { - widgets[launcher_state.current_widget].loop(event, &launcher_state.launcher_settings, widget_contexts[launcher_state.current_widget]); + widgets[launcher_state.current_widget].loop(event, &launcher_state.launcher_settings, launcher_state.subsecond, widget_contexts[launcher_state.current_widget]); event = 0; } @@ -139,5 +140,13 @@ void cb_alarm_pressed() { void cb_tick() { event = EVENT_TICK; - if (launcher_state.light_ticks) launcher_state.light_ticks--; + watch_date_time date_time = watch_rtc_get_date_time(); + if (date_time.unit.second != launcher_state.last_second) { + if (launcher_state.light_ticks) launcher_state.light_ticks--; + + launcher_state.last_second = date_time.unit.second; + launcher_state.subsecond = 0; + } else { + launcher_state.subsecond++; + } } diff --git a/launcher/launcher.h b/launcher/launcher.h index 7a794545..e49575e7 100644 --- a/launcher/launcher.h +++ b/launcher/launcher.h @@ -6,12 +6,13 @@ // TODO: none of this is implemented typedef union { struct { + uint32_t reserved : 3; uint32_t clock_mode_24h : 1; // determines whether clock should use 12 or 24 hour mode. + uint32_t button_should_sound : 1; // if true, pressing a button emits a sound. uint32_t signal_should_sound : 1; // if true, a double beep is played at the top of each hour. uint32_t alarm_should_sound : 1; // if true, the alarm interrupt can match a time and play a song. uint32_t alarm_minute : 6; // the minute of the alarm we want to match uint32_t alarm_hour : 5; // the second of the alarm we want to match - uint32_t note_index : 4; // the index of the tone to play on button press, or 0xF for no tone. uint32_t screensaver_interval : 3; // 0 to disable screensaver, or a screensaver activation interval. uint32_t led_duration : 3; // how many seconds to shine the LED for, or 0 to disable it. uint32_t led_red_color : 4; // for general purpose illumination, the red LED value (0-15) @@ -37,11 +38,10 @@ typedef enum LauncherEvent { typedef void (*launcher_widget_setup)(LauncherSettings *settings, void ** context_ptr); typedef void (*launcher_widget_activate)(LauncherSettings *settings, void *context); -typedef void (*launcher_widget_loop)(LauncherEvent event, LauncherSettings *settings, void *context); +typedef void (*launcher_widget_loop)(LauncherEvent event, LauncherSettings *settings, uint8_t subsecond, void *context); typedef void (*launcher_widget_resign)(LauncherSettings *settings, void *context); typedef struct WatchWidget { - char widget_name[11]; launcher_widget_setup setup; launcher_widget_activate activate; launcher_widget_loop loop; @@ -64,10 +64,16 @@ typedef struct LauncherState { uint8_t light_down_timestamp; uint8_t mode_down_timestamp; uint8_t alarm_down_timestamp; + + // stuff for subsecond tracking + uint8_t tick_frequency; + uint8_t last_second; + uint8_t subsecond; } LauncherState; +void launcher_move_to_widget(uint8_t widget_index); void launcher_move_to_next_widget(); -void launcher_move_to_first_widget(); void launcher_illuminate_led(); +void launcher_request_tick_frequency(uint8_t freq); #endif // LAUNCHER_H_ diff --git a/launcher/launcher_config.h b/launcher/launcher_config.h index db9d1be1..9bc43c47 100644 --- a/launcher/launcher_config.h +++ b/launcher/launcher_config.h @@ -1,12 +1,16 @@ #ifndef LAUNCHER_CONFIG_H_ #define LAUNCHER_CONFIG_H_ +#include "simple_clock_widget.h" +#include "preferences_widget.h" #include "fake_widget_1.h" #include "fake_widget_2.h" -#define LAUNCHER_NUM_WIDGETS 2 +#define LAUNCHER_NUM_WIDGETS 4 WatchWidget widgets[LAUNCHER_NUM_WIDGETS] = { + simple_clock_widget, + preferences_widget, fake_widget_1, fake_widget_2, }; diff --git a/launcher/make/Makefile b/launcher/make/Makefile index f02c1853..4fba0351 100755 --- a/launcher/make/Makefile +++ b/launcher/make/Makefile @@ -11,6 +11,8 @@ include $(TOP)/make.mk INCLUDES += \ -I../ \ -I../widgets/ \ + -I../widgets/clock/ \ + -I../widgets/settings/ \ # If you add any other source files you wish to compile, add them after ../app.c # Note that you will need to add a backslash at the end of any line you wish to continue, i.e. @@ -20,6 +22,8 @@ INCLUDES += \ # ../utils/temperature.c SRCS += \ ../launcher.c \ + ../widgets/clock/simple_clock_widget.c \ + ../widgets/settings/preferences_widget.c \ ../widgets/fake_widget_1.c \ ../widgets/fake_widget_2.c \ diff --git a/launcher/widgets/clock/simple_clock_widget.c b/launcher/widgets/clock/simple_clock_widget.c new file mode 100644 index 00000000..51c6c9c6 --- /dev/null +++ b/launcher/widgets/clock/simple_clock_widget.c @@ -0,0 +1,86 @@ +#include <stdlib.h> +#include "simple_clock_widget.h" +#include "watch.h" + +void simple_clock_widget_setup(LauncherSettings *settings, void ** context_ptr) { + (void) settings; + // the only context we need is the timestamp of the previous tick. + *context_ptr = malloc(sizeof(uint32_t)); +} + +void simple_clock_widget_activate(LauncherSettings *settings, void *context) { + if (settings->bit.clock_mode_24h) { + watch_set_indicator(WATCH_INDICATOR_24H); + } + watch_set_colon(); + // this ensures that none of the timestamp fields will match, so we can re-render them all. + *((uint32_t *)context) = 0xFFFFFFFF; +} + +void simple_clock_widget_loop(LauncherEvent event, LauncherSettings *settings, uint8_t subsecond, void *context) { + printf("simple_clock_widget_loop\n"); + (void) subsecond; + const char weekdays[7][3] = {"SA", "SU", "MO", "TU", "WE", "TH", "FR"}; + char buf[11]; + uint8_t pos; + + watch_date_time date_time; + uint32_t previous_date_time; + switch (event) { + case EVENT_TICK: + case EVENT_ACTIVATE: + date_time = watch_rtc_get_date_time(); + previous_date_time = *((uint32_t *)context); + *((uint32_t *)context) = date_time.reg; + + if (date_time.reg >> 6 == previous_date_time >> 6) { + // everything before seconds is the same, don't waste cycles setting those segments. + pos = 8; + sprintf(buf, "%02d", date_time.unit.second); + } else if (date_time.reg >> 12 == previous_date_time >> 12) { + // everything before minutes is the same. + pos = 6; + sprintf(buf, "%02d%02d", date_time.unit.minute, date_time.unit.second); + } else { + // other stuff changed; let's do it all. + if (!settings->bit.clock_mode_24h) { + // if we are in 12 hour mode, do some cleanup. + if (date_time.unit.hour < 12) { + watch_clear_indicator(WATCH_INDICATOR_PM); + } else { + watch_set_indicator(WATCH_INDICATOR_PM); + } + date_time.unit.hour %= 12; + if (date_time.unit.hour == 0) date_time.unit.hour = 12; + } + pos = 0; + sprintf(buf, "%s%2d%2d%02d%02d", weekdays[simple_clock_widget_get_weekday(date_time.unit.year, date_time.unit.month, date_time.unit.day)], date_time.unit.day, date_time.unit.hour, date_time.unit.minute, date_time.unit.second); + } + watch_display_string(buf, pos); + break; + case EVENT_MODE_BUTTON_UP: + launcher_move_to_next_widget(); + return; + case EVENT_LIGHT_BUTTON_UP: + launcher_illuminate_led(); + break; + case EVENT_ALARM_BUTTON_UP: + break; + default: + break; + } +} + +void simple_clock_widget_resign(LauncherSettings *settings, void *context) { + (void) settings; + (void) context; +} + +uint8_t simple_clock_widget_get_weekday(uint16_t year, uint16_t month, uint16_t day) { + year += 20; + if (month <= 2) { + month += 12; + year--; + } + return (day + 13 * (month + 1) / 5 + year + year / 4 + 525) % 7; +} diff --git a/launcher/widgets/clock/simple_clock_widget.h b/launcher/widgets/clock/simple_clock_widget.h new file mode 100644 index 00000000..459721b9 --- /dev/null +++ b/launcher/widgets/clock/simple_clock_widget.h @@ -0,0 +1,20 @@ +#ifndef SIMPLE_CLOCK_WIDGET_H_ +#define SIMPLE_CLOCK_WIDGET_H_ + +#include "launcher.h" + +void simple_clock_widget_setup(LauncherSettings *settings, void ** context_ptr); +void simple_clock_widget_activate(LauncherSettings *settings, void *context); +void simple_clock_widget_loop(LauncherEvent event, LauncherSettings *settings, uint8_t subsecond, void *context); +void simple_clock_widget_resign(LauncherSettings *settings, void *context); + +uint8_t simple_clock_widget_get_weekday(uint16_t day, uint16_t month, uint16_t year); + +#define simple_clock_widget { \ + simple_clock_widget_setup, \ + simple_clock_widget_activate, \ + simple_clock_widget_loop, \ + simple_clock_widget_resign, \ +} + +#endif // FAKE_WIDGET_H_
\ No newline at end of file diff --git a/launcher/widgets/fake_widget_1.c b/launcher/widgets/fake_widget_1.c index aa4af2c2..15ffcbd2 100644 --- a/launcher/widgets/fake_widget_1.c +++ b/launcher/widgets/fake_widget_1.c @@ -1,8 +1,9 @@ #include "fake_widget_1.h" +#include "watch.h" void fake_widget_1_setup(LauncherSettings *settings, void ** context_ptr) { (void) settings; - // *context_ptr = NULL; + *context_ptr = NULL; } void fake_widget_1_activate(LauncherSettings *settings, void *context) { @@ -10,14 +11,17 @@ void fake_widget_1_activate(LauncherSettings *settings, void *context) { (void) context; } -void fake_widget_1_loop(LauncherEvent event, LauncherSettings *settings, void *context) { +void fake_widget_1_loop(LauncherEvent event, LauncherSettings *settings, uint8_t subsecond, void *context) { + printf("fake_widget_1_loop\n"); (void) settings; + (void) subsecond; (void) context; + watch_display_string("W1 d get01", 0); switch (event) { case EVENT_MODE_BUTTON_UP: launcher_move_to_next_widget(); - break; + return; case EVENT_LIGHT_BUTTON_UP: launcher_illuminate_led(); break; diff --git a/launcher/widgets/fake_widget_1.h b/launcher/widgets/fake_widget_1.h index 00db80cb..18180156 100644 --- a/launcher/widgets/fake_widget_1.h +++ b/launcher/widgets/fake_widget_1.h @@ -5,11 +5,10 @@ void fake_widget_1_setup(LauncherSettings *settings, void ** context_ptr); void fake_widget_1_activate(LauncherSettings *settings, void *context); -void fake_widget_1_loop(LauncherEvent event, LauncherSettings *settings, void *context); +void fake_widget_1_loop(LauncherEvent event, LauncherSettings *settings, uint8_t subsecond, void *context); void fake_widget_1_resign(LauncherSettings *settings, void *context); #define fake_widget_1 { \ - "W1 d get01", \ fake_widget_1_setup, \ fake_widget_1_activate, \ fake_widget_1_loop, \ diff --git a/launcher/widgets/fake_widget_2.c b/launcher/widgets/fake_widget_2.c index 4ce00ce2..f3ffc14b 100644 --- a/launcher/widgets/fake_widget_2.c +++ b/launcher/widgets/fake_widget_2.c @@ -1,4 +1,5 @@ #include "fake_widget_2.h" +#include "watch.h" void fake_widget_2_setup(LauncherSettings *settings, void ** context_ptr) { (void) settings; @@ -10,14 +11,17 @@ void fake_widget_2_activate(LauncherSettings *settings, void *context) { (void) context; } -void fake_widget_2_loop(LauncherEvent event, LauncherSettings *settings, void *context) { +void fake_widget_2_loop(LauncherEvent event, LauncherSettings *settings, uint8_t subsecond, void *context) { + printf("fake_widget_2_loop\n"); (void) settings; + (void) subsecond; (void) context; + watch_display_string("W1 d get02", 0); switch (event) { case EVENT_MODE_BUTTON_UP: launcher_move_to_next_widget(); - break; + return; case EVENT_LIGHT_BUTTON_UP: launcher_illuminate_led(); break; diff --git a/launcher/widgets/fake_widget_2.h b/launcher/widgets/fake_widget_2.h index 31bf30bc..1f6bd503 100644 --- a/launcher/widgets/fake_widget_2.h +++ b/launcher/widgets/fake_widget_2.h @@ -5,11 +5,10 @@ void fake_widget_2_setup(LauncherSettings *settings, void ** context_ptr); void fake_widget_2_activate(LauncherSettings *settings, void *context); -void fake_widget_2_loop(LauncherEvent event, LauncherSettings *settings, void *context); +void fake_widget_2_loop(LauncherEvent event, LauncherSettings *settings, uint8_t subsecond, void *context); void fake_widget_2_resign(LauncherSettings *settings, void *context); #define fake_widget_2 { \ - "W1 d get02", \ fake_widget_2_setup, \ fake_widget_2_activate, \ fake_widget_2_loop, \ diff --git a/launcher/widgets/settings/preferences_widget.c b/launcher/widgets/settings/preferences_widget.c new file mode 100644 index 00000000..5877c237 --- /dev/null +++ b/launcher/widgets/settings/preferences_widget.c @@ -0,0 +1,121 @@ +#include <stdlib.h> +#include "preferences_widget.h" +#include "watch.h" + +#define PREFERENCES_WIDGET_NUM_PREFEFENCES (5) +const char preferences_widget_titles[PREFERENCES_WIDGET_NUM_PREFEFENCES][11] = {"CL", "Bt Beep", "SC", "Lt grn", "Lt red"}; + +void preferences_widget_setup(LauncherSettings *settings, void ** context_ptr) { + (void) settings; + *context_ptr = malloc(sizeof(uint8_t)); +} + +void preferences_widget_activate(LauncherSettings *settings, void *context) { + (void) settings; + *((uint8_t *)context) = 0; + launcher_request_tick_frequency(4); // we need to manually blink some pixels +} + +void preferences_widget_loop(LauncherEvent event, LauncherSettings *settings, uint8_t subsecond, void *context) { + (void) settings; + (void) context; + printf("preferences_widget_loop\n"); + uint8_t current_page = *((uint8_t *)context); + switch (event) { + case EVENT_MODE_BUTTON_UP: + launcher_move_to_next_widget(); + return; + case EVENT_LIGHT_BUTTON_UP: + current_page = (current_page + 1) % PREFERENCES_WIDGET_NUM_PREFEFENCES; + *((uint8_t *)context) = current_page; + break; + case EVENT_ALARM_BUTTON_UP: + switch (current_page) { + case 0: + settings->bit.clock_mode_24h = !(settings->bit.clock_mode_24h); + break; + case 1: + settings->bit.button_should_sound = !(settings->bit.button_should_sound); + break; + case 2: + settings->bit.screensaver_interval = settings->bit.screensaver_interval + 1; + break; + case 3: + settings->bit.led_green_color = settings->bit.led_green_color + 1; + break; + case 4: + settings->bit.led_red_color = settings->bit.led_red_color + 1; + break; + } + break; + default: + break; + } + + watch_clear_display(); + watch_display_string((char *)preferences_widget_titles[current_page], 0); + if (current_page > 2) { + // this is a hack, launcher should be able to illumate with a custom color. + launcher_illuminate_led(); + watch_set_led_color(settings->bit.led_red_color ? (0xF | settings->bit.led_red_color << 4) : 0, + settings->bit.led_green_color ? (0xF | settings->bit.led_green_color << 4) : 0); + } else { + watch_set_led_off(); + } + + if (subsecond % 2) return; + char buf[3]; + switch (current_page) { + case 0: + if (settings->bit.clock_mode_24h) watch_display_string("24h", 4); + else watch_display_string("12h", 4); + break; + case 1: + if (settings->bit.button_should_sound) watch_display_string("y", 9); + else watch_display_string("n", 9); + break; + case 2: + switch (settings->bit.screensaver_interval) { + case 0: + watch_display_string("never", 4); + break; + case 1: + watch_display_string("1 hour", 4); + break; + case 2: + watch_display_string("2 hour", 4); + break; + case 3: + watch_display_string("6 hour", 4); + break; + case 4: + watch_display_string("12 hr", 4); + break; + case 5: + watch_display_string(" 1 day", 4); + break; + case 6: + watch_display_string(" 2 day", 4); + break; + case 7: + watch_display_string(" 7 day", 4); + break; + } + break; + case 3: + sprintf(buf, "%2d", settings->bit.led_green_color); + watch_display_string(buf, 8); + break; + case 4: + sprintf(buf, "%2d", settings->bit.led_red_color); + watch_display_string(buf, 8); + break; + } +} + +void preferences_widget_resign(LauncherSettings *settings, void *context) { + (void) settings; + (void) context; + watch_set_led_off(); + launcher_request_tick_frequency(1); +} diff --git a/launcher/widgets/settings/preferences_widget.h b/launcher/widgets/settings/preferences_widget.h new file mode 100644 index 00000000..fcbcd0d6 --- /dev/null +++ b/launcher/widgets/settings/preferences_widget.h @@ -0,0 +1,18 @@ +#ifndef PREFERENCES_WIDGET_H_ +#define PREFERENCES_WIDGET_H_ + +#include "launcher.h" + +void preferences_widget_setup(LauncherSettings *settings, void ** context_ptr); +void preferences_widget_activate(LauncherSettings *settings, void *context); +void preferences_widget_loop(LauncherEvent event, LauncherSettings *settings, uint8_t subsecond, void *context); +void preferences_widget_resign(LauncherSettings *settings, void *context); + +#define preferences_widget { \ + preferences_widget_setup, \ + preferences_widget_activate, \ + preferences_widget_loop, \ + preferences_widget_resign, \ +} + +#endif // PREFERENCES_WIDGET_H_
\ No newline at end of file |