From 8475ffcd7aaebcbf17c7188ef96ce01a9730e9b3 Mon Sep 17 00:00:00 2001 From: Joey Castillo Date: Sat, 23 Oct 2021 17:55:19 -0400 Subject: movement: first crack at background tasks API --- movement/movement.c | 31 +++++++++++++++++----- movement/movement.h | 3 +++ .../thermistor/thermistor_logging_face.c | 17 +++++++----- .../thermistor/thermistor_logging_face.h | 3 ++- 4 files changed, 41 insertions(+), 13 deletions(-) diff --git a/movement/movement.c b/movement/movement.c index e1ab322f..5622f17f 100644 --- a/movement/movement.c +++ b/movement/movement.c @@ -23,6 +23,18 @@ static inline void _movement_reset_inactivity_countdown() { movement_state.timeout_ticks = movement_timeout_inactivity_deadlines[movement_state.settings.bit.to_interval]; } +void _movement_handle_background_tasks() { + for(uint8_t i = 0; i < MOVEMENT_NUM_FACES; i++) { + // For each face, if the watch face wants a background task... + if (watch_faces[i].wants_background_task != NULL && watch_faces[i].wants_background_task(&movement_state.settings, watch_face_contexts[i])) { + // ...we give it one. pretty straightforward! + movement_event_t background_event = { EVENT_BACKGROUND_TASK, 0 }; + watch_faces[i].loop(background_event, &movement_state.settings, watch_face_contexts[i]); + } + } + movement_state.needs_background_tasks_handled = false; +} + void movement_request_tick_frequency(uint8_t freq) { watch_rtc_disable_all_periodic_callbacks(); movement_state.subsecond = 0; @@ -68,10 +80,15 @@ void app_setup() { watch_face_contexts[i] = NULL; is_first_launch = false; } + + // set up the 1 minute alarm (for background tasks and low power updates) + watch_date_time alarm_time; + alarm_time.reg = 0; + alarm_time.unit.second = 59; // after a match, the alarm fires at the next rising edge of CLK_RTC_CNT, so 59 seconds lets us update at :00 + watch_rtc_register_alarm_callback(cb_alarm_fired, alarm_time, ALARM_MATCH_SS); } if (movement_state.le_mode_ticks != -1) { watch_disable_extwake_interrupt(BTN_ALARM); - watch_rtc_disable_alarm_callback(); watch_enable_external_interrupts(); watch_register_interrupt_callback(BTN_MODE, cb_mode_btn_interrupt, INTERRUPT_TRIGGER_BOTH); @@ -131,13 +148,12 @@ bool app_loop() { event.event_type = EVENT_TIMEOUT; } + // handle background tasks, if the alarm handler told us we need to + if (movement_state.needs_background_tasks_handled) _movement_handle_background_tasks(); + // if we have timed out of our low energy mode countdown, enter low energy mode. if (movement_state.le_mode_ticks == 0) { movement_state.le_mode_ticks = -1; - watch_date_time alarm_time; - alarm_time.reg = 0; - alarm_time.unit.second = 59; // after a match, the alarm fires at the next rising edge of CLK_RTC_CNT, so 59 seconds lets us update at :00 - watch_rtc_register_alarm_callback(cb_alarm_fired, alarm_time, ALARM_MATCH_SS); watch_register_extwake_callback(BTN_ALARM, cb_alarm_btn_extwake, true); event.event_type = EVENT_NONE; event.subsecond = 0; @@ -145,6 +161,9 @@ bool app_loop() { // this is a little mini-runloop. // as long as le_mode_ticks is -1 (i.e. we are in low energy mode), we wake up here, update the screen, and go right back to sleep. while (movement_state.le_mode_ticks == -1) { + // we also have to handle background tasks here in the mini-runloop + if (movement_state.needs_background_tasks_handled) _movement_handle_background_tasks(); + event.event_type = EVENT_LOW_ENERGY_UPDATE; watch_faces[movement_state.current_watch_face].loop(event, &movement_state.settings, watch_face_contexts[movement_state.current_watch_face]); watch_enter_sleep_mode(); @@ -202,7 +221,7 @@ void cb_alarm_btn_extwake() { } void cb_alarm_fired() { - event.event_type = EVENT_LOW_ENERGY_UPDATE; + movement_state.needs_background_tasks_handled = true; } void cb_tick() { diff --git a/movement/movement.h b/movement/movement.h index e8bf9247..cb162b95 100644 --- a/movement/movement.h +++ b/movement/movement.h @@ -167,6 +167,9 @@ typedef struct { uint8_t mode_down_timestamp; uint8_t alarm_down_timestamp; + // background task handling + bool needs_background_tasks_handled; + // low energy mode countdown int32_t le_mode_ticks; diff --git a/movement/watch_faces/thermistor/thermistor_logging_face.c b/movement/watch_faces/thermistor/thermistor_logging_face.c index 1ff20483..5351ce88 100644 --- a/movement/watch_faces/thermistor/thermistor_logging_face.c +++ b/movement/watch_faces/thermistor/thermistor_logging_face.c @@ -63,7 +63,6 @@ void thermistor_logging_face_activate(movement_settings_t *settings, void *conte bool thermistor_logging_face_loop(movement_event_t event, movement_settings_t *settings, void *context) { thermistor_logger_state_t *logger_state = (thermistor_logger_state_t *)context; - watch_date_time date_time = watch_rtc_get_date_time(); switch (event.event_type) { case EVENT_TIMEOUT: movement_move_to_face(0); @@ -90,11 +89,9 @@ bool thermistor_logging_face_loop(movement_event_t event, movement_settings_t *s if (logger_state->ts_ticks && --logger_state->ts_ticks == 0) { _thermistor_logging_face_update_display(logger_state, settings->bit.use_imperial_units, settings->bit.clock_mode_24h); } - // this is just temporary for testing: log a data point every 30 seconds. - if (date_time.unit.second % 30 == 0 && !logger_state->ts_ticks) { - _thermistor_logging_face_log_data(logger_state); - _thermistor_logging_face_update_display(logger_state, settings->bit.use_imperial_units, settings->bit.clock_mode_24h); - } + break; + case EVENT_BACKGROUND_TASK: + _thermistor_logging_face_log_data(logger_state); break; default: break; @@ -107,3 +104,11 @@ void thermistor_logging_face_resign(movement_settings_t *settings, void *context (void) settings; (void) context; } + +bool thermistor_logging_face_wants_background_task(movement_settings_t *settings, void *context) { + (void) settings; + (void) context; + // this will get called at the top of each minute, so all we check is if we're at the top of the hour as well. + // if we are, we ask for a background task. + return watch_rtc_get_date_time().unit.minute == 0; +} diff --git a/movement/watch_faces/thermistor/thermistor_logging_face.h b/movement/watch_faces/thermistor/thermistor_logging_face.h index 43d441be..ece89396 100644 --- a/movement/watch_faces/thermistor/thermistor_logging_face.h +++ b/movement/watch_faces/thermistor/thermistor_logging_face.h @@ -22,13 +22,14 @@ void thermistor_logging_face_setup(movement_settings_t *settings, void ** contex void thermistor_logging_face_activate(movement_settings_t *settings, void *context); bool thermistor_logging_face_loop(movement_event_t event, movement_settings_t *settings, void *context); void thermistor_logging_face_resign(movement_settings_t *settings, void *context); +bool thermistor_logging_face_wants_background_task(movement_settings_t *settings, void *context); static const watch_face_t thermistor_logging_face = { thermistor_logging_face_setup, thermistor_logging_face_activate, thermistor_logging_face_loop, thermistor_logging_face_resign, - NULL + thermistor_logging_face_wants_background_task }; #endif // THERMISTOR_LOGGING_FACE_H_ -- cgit v1.2.3