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