wip: late-night untested launcher app musings
This commit is contained in:
parent
15ae7ab84b
commit
624ff19580
142
launcher/launcher.c
Normal file
142
launcher/launcher.c
Normal file
@ -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;
|
||||||
|
}
|
74
launcher/launcher.h
Normal file
74
launcher/launcher.h
Normal file
@ -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_
|
13
launcher/launcher_config.h
Normal file
13
launcher/launcher_config.h
Normal file
@ -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_
|
1
launcher/make/.gitignore
vendored
Executable file
1
launcher/make/.gitignore
vendored
Executable file
@ -0,0 +1 @@
|
|||||||
|
build/
|
26
launcher/make/Makefile
Executable file
26
launcher/make/Makefile
Executable file
@ -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
|
24
launcher/widgets/fake_widget.c
Normal file
24
launcher/widgets/fake_widget.c
Normal file
@ -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;
|
||||||
|
}
|
18
launcher/widgets/fake_widget.h
Normal file
18
launcher/widgets/fake_widget.h
Normal file
@ -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_
|
Loading…
x
Reference in New Issue
Block a user