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 | 
