diff options
-rw-r--r-- | launcher/launcher.c | 142 | ||||
-rw-r--r-- | launcher/launcher.h | 74 | ||||
-rw-r--r-- | launcher/launcher_config.h | 13 | ||||
-rwxr-xr-x | launcher/make/.gitignore | 1 | ||||
-rwxr-xr-x | launcher/make/Makefile | 26 | ||||
-rw-r--r-- | launcher/widgets/fake_widget.c | 24 | ||||
-rw-r--r-- | launcher/widgets/fake_widget.h | 18 |
7 files changed, 298 insertions, 0 deletions
diff --git a/launcher/launcher.c b/launcher/launcher.c new file mode 100644 index 00000000..1ad0b9da --- /dev/null +++ b/launcher/launcher.c @@ -0,0 +1,142 @@ +#include <stdio.h> +#include <string.h> +#include "watch.h" +#include "launcher.h" +#include "launcher_config.h" + +LauncherState launcher_state; +void * widget_contexts[LAUNCHER_NUM_WIDGETS]; + +void app_init() { + memset(&launcher_state, 0, sizeof(launcher_state)); +} + +void app_wake_from_deep_sleep() { + // This app does not support deep sleep mode. +} + +void app_setup() { + watch_enable_external_interrupts(); + watch_register_interrupt_callback(BTN_MODE, cb_mode_pressed, INTERRUPT_TRIGGER_BOTH); + watch_register_interrupt_callback(BTN_LIGHT, cb_light_pressed, INTERRUPT_TRIGGER_BOTH); + watch_register_interrupt_callback(BTN_ALARM, cb_alarm_pressed, INTERRUPT_TRIGGER_BOTH); + + watch_enable_buzzer(); + watch_enable_leds(); + watch_enable_display(); + + watch_register_tick_callback(cb_tick); + + for(uint8_t i = 0; i < LAUNCHER_NUM_WIDGETS; i++) { + widgets[i].setup(&launcher_state.launcherSettings, widget_contexts[i]); + } +} + +void app_prepare_for_sleep() { +} + +void app_wake_from_sleep() { +} + +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); + launcher_state.widget_changed = false; + } + + // If the LED is off and should be on, turn it on + if (launcher_state.light_ticks > 0 && !launcher_state.led_on) { + watch_set_led_green(); + launcher_state.led_on = true; + } + + // if the LED is on and should be off, turn it off + if (launcher_state.led_on && launcher_state.light_ticks == 0) { + // unless the user is holding down the LIGHT button, in which case, give them more time. + if (watch_get_pin_level(BTN_LIGHT)) { + launcher_state.light_ticks = 3; + } else { + watch_set_led_off(); + launcher_state.led_on = false; + } + } + + if (event) { + event = 0; + bool can_sleep = widgets[launcher_state.current_widget].loop(event, &launcher_state.launcherSettings, widget_contexts[launcher_state.current_widget]); + if (can_sleep) return true; + + event = EVENT_LOOP; + return false; + } + + return true; +} + +void move_to_next_widget() { + launcher_state.widget_changed = true; + widgets[launcher_state.current_widget].enter_background(&launcher_state.launcherSettings, widget_contexts[launcher_state.current_widget]); + launcher_state.current_widget = (launcher_state.current_widget + 1) % LAUNCHER_NUM_WIDGETS; + widgets[launcher_state.current_widget].enter_foreground(&launcher_state.launcherSettings, widget_contexts[launcher_state.current_widget]); +} + +void move_to_first_widget() { + launcher_state.widget_changed = true; + widgets[launcher_state.current_widget].enter_background(&launcher_state.launcherSettings, widget_contexts[launcher_state.current_widget]); + launcher_state.current_widget = 0; + widgets[0].enter_foreground(&launcher_state.launcherSettings, widget_contexts[0]); +} + +void illuminate_led() { + launcher_state.light_ticks = 3; +} + +void cb_light_pressed() { + struct calendar_date_time date_time; + watch_get_date_time(&date_time); + if (launcher_state.light_down_timestamp) { + uint8_t diff = (61 + date_time.time.sec) - launcher_state.light_down_timestamp; + if (diff > 1) event = EVENT_LIGHT_LONG_PRESS; + else event = EVENT_LIGHT_BUTTON_UP; + launcher_state.light_down_timestamp = 0; + } else { + launcher_state.light_down_timestamp = date_time.time.sec + 1; + event = EVENT_LIGHT_BUTTON_DOWN; + } +} + +void cb_mode_pressed() { + struct calendar_date_time date_time; + watch_get_date_time(&date_time); + if (launcher_state.mode_down_timestamp) { + uint8_t diff = (61 + date_time.time.sec) - launcher_state.mode_down_timestamp; + if (diff > 1) event = EVENT_MODE_LONG_PRESS; + else event = EVENT_MODE_BUTTON_UP; + launcher_state.mode_down_timestamp = 0; + } else { + launcher_state.mode_down_timestamp = date_time.time.sec + 1; + event = EVENT_MODE_BUTTON_DOWN; + } +} + +void cb_alarm_pressed() { + struct calendar_date_time date_time; + watch_get_date_time(&date_time); + if (launcher_state.alarm_down_timestamp) { + uint8_t diff = (61 + date_time.time.sec) - launcher_state.alarm_down_timestamp; + if (diff > 1) event = EVENT_ALARM_LONG_PRESS; + else event = EVENT_ALARM_BUTTON_UP; + launcher_state.alarm_down_timestamp = 0; + } else { + launcher_state.alarm_down_timestamp = date_time.time.sec + 1; + event = EVENT_ALARM_BUTTON_DOWN; + } +} + +void cb_tick() { + event = EVENT_TICK; +} diff --git a/launcher/launcher.h b/launcher/launcher.h new file mode 100644 index 00000000..888d1adb --- /dev/null +++ b/launcher/launcher.h @@ -0,0 +1,74 @@ +#ifndef LAUNCHER_H_ +#define LAUNCHER_H_ +#include <stdio.h> +#include <stdbool.h> + +// TODO: none of this is implemented +typedef union { + struct { + uint32_t reserved : 1; + uint32_t clock_mode_24h : 1; // determines whether display should use 12 or 24 hour mode. + 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 plays a song. + uint32_t note_index : 7; // the index of the tone to play, or 0x7F for no tone. + uint32_t snapback_enabled : 1; // if true, snaps back to the main screen after 5 minutes + uint32_t sleep_interval : 3; // 0 to disable sleep, or a number of days to sleep after. + uint32_t sleep_blanks_screen : 1; // blank screen or display "SLEEP" when asleep + uint32_t led_red_color : 8; // for general purpose illumination, the red LED value + uint32_t led_green_color : 8; // for general purpose illumination, the green LED value + } bit; + uint32_t value; +} LauncherSettings; + +typedef enum LauncherEvent { + EVENT_NONE = 0, // There is no event to report. + EVENT_ACTIVATE, // Your widget is entering the foreground. + EVENT_TICK, // Most common event type. Your widget is being called from the tick callback. + EVENT_LOOP, // The app did not sleep, and is going into another invocation of the run loop. + EVENT_LIGHT_BUTTON_DOWN, // The light button has been pressed, but not yet released. + EVENT_LIGHT_BUTTON_UP, // The light button was pressed and released. + EVENT_LIGHT_LONG_PRESS, // The light button was held for >2 seconds, and released. + EVENT_MODE_BUTTON_DOWN, // The mode button has been pressed, but not yet released. + EVENT_MODE_BUTTON_UP, // The mode button was pressed and released. + EVENT_MODE_LONG_PRESS, // The mode button was held for >2 seconds, and released. + EVENT_ALARM_BUTTON_DOWN, // The alarm button has been pressed, but not yet released. + EVENT_ALARM_BUTTON_UP, // The alarm button was pressed and released. + EVENT_ALARM_LONG_PRESS, // The alarm button was held for >2 seconds, and released. +} LauncherEvent; + +typedef void (*launcher_widget_setup)(LauncherSettings *settings, void ** context_ptr); +typedef void (*launcher_widget_enter_foreground)(LauncherSettings *settings, void *context); +typedef bool (*launcher_widget_loop)(LauncherEvent event, LauncherSettings *settings, void *context); +typedef void (*launcher_widget_enter_background)(LauncherSettings *settings, void *context); + +typedef struct WatchWidget { + launcher_widget_setup setup; + launcher_widget_enter_foreground enter_foreground; + launcher_widget_loop loop; + launcher_widget_enter_background enter_background; +} WatchWidget; + +typedef struct LauncherState { + // properties stored in BACKUP register + LauncherSettings launcherSettings; + + // transient properties + int16_t current_widget; + bool widget_changed; + + // LED stuff + uint8_t light_ticks; + bool led_on; + + // button tracking for long press + uint8_t light_down_timestamp; + uint8_t mode_down_timestamp; + uint8_t alarm_down_timestamp; +} LauncherState; + +void cb_mode_pressed(); +void cb_light_pressed(); +void cb_alarm_pressed(); +void cb_tick(); + +#endif // LAUNCHER_H_ diff --git a/launcher/launcher_config.h b/launcher/launcher_config.h new file mode 100644 index 00000000..cb820a7e --- /dev/null +++ b/launcher/launcher_config.h @@ -0,0 +1,13 @@ +#ifndef LAUNCHER_CONFIG_H_ +#define LAUNCHER_CONFIG_H_ + +#include "fake_widget.h" + +#define LAUNCHER_NUM_WIDGETS 1 + +WatchWidget widgets[LAUNCHER_NUM_WIDGETS] = { + fake_widget +}; + + +#endif // LAUNCHER_CONFIG_H_ diff --git a/launcher/make/.gitignore b/launcher/make/.gitignore new file mode 100755 index 00000000..3722ac63 --- /dev/null +++ b/launcher/make/.gitignore @@ -0,0 +1 @@ +build/
diff --git a/launcher/make/Makefile b/launcher/make/Makefile new file mode 100755 index 00000000..dce33f45 --- /dev/null +++ b/launcher/make/Makefile @@ -0,0 +1,26 @@ +# Leave this line at the top of the file; it has all the watch library sources and includes. +TOP = ../.. +include $(TOP)/make.mk + +# If you add any other subdirectories with header files you wish to include, add them after ../ +# Note that you will need to add a backslash at the end of any line you wish to continue, i.e. +# INCLUDES += \ +# -I../ \ +# -I../drivers/ \ +# -I../utils/ +INCLUDES += \ + -I../ \ + -I../widgets/ \ + +# 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. +# SRCS += \ +# ../app.c \ +# ../drivers/bmp280.c \ +# ../utils/temperature.c +SRCS += \ + ../launcher.c \ + ../widgets/fake_widget.c \ + +# Leave this line at the bottom of the file; it has all the targets for making your project. +include $(TOP)/rules.mk diff --git a/launcher/widgets/fake_widget.c b/launcher/widgets/fake_widget.c new file mode 100644 index 00000000..15e3cf2a --- /dev/null +++ b/launcher/widgets/fake_widget.c @@ -0,0 +1,24 @@ +#include "fake_widget.h" + +void fake_widget_setup(LauncherSettings *settings, void ** context_ptr) { + (void) settings; + *context_ptr = NULL; +} + +void fake_widget_enter_foreground(LauncherSettings *settings, void *context) { + (void) settings; + (void) context; +} + +bool fake_widget_loop(LauncherEvent event, LauncherSettings *settings, void *context) { + (void) event; + (void) settings; + (void) context; + + return true; +} + +void fake_widget_enter_background(LauncherSettings *settings, void *context) { + (void) settings; + (void) context; +} diff --git a/launcher/widgets/fake_widget.h b/launcher/widgets/fake_widget.h new file mode 100644 index 00000000..5a4b33db --- /dev/null +++ b/launcher/widgets/fake_widget.h @@ -0,0 +1,18 @@ +#ifndef FAKE_WIDGET_H_ +#define FAKE_WIDGET_H_ + +#include "launcher.h" + +void fake_widget_setup(LauncherSettings *settings, void ** context_ptr); +void fake_widget_enter_foreground(LauncherSettings *settings, void *context); +bool fake_widget_loop(LauncherEvent event, LauncherSettings *settings, void *context); +void fake_widget_enter_background(LauncherSettings *settings, void *context); + +#define fake_widget { \ + fake_widget_setup, \ + fake_widget_enter_foreground, \ + fake_widget_loop, \ + fake_widget_enter_background, \ +} + +#endif // FAKE_WIDGET_H_
\ No newline at end of file |