]> git.earman.xyz Git - sensor-watch.git/commitdiff
movement: first crack at background tasks API
authorJoey Castillo <jose.castillo@gmail.com>
Sat, 23 Oct 2021 21:55:19 +0000 (17:55 -0400)
committerJoey Castillo <jose.castillo@gmail.com>
Sat, 23 Oct 2021 21:55:19 +0000 (17:55 -0400)
movement/movement.c
movement/movement.h
movement/watch_faces/thermistor/thermistor_logging_face.c
movement/watch_faces/thermistor/thermistor_logging_face.h

index e1ab322fd6a5dfc8bf2ae427ac363793577b0e54..5622f17fc99d33c09e0104ba05826606e31bdcc0 100644 (file)
@@ -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() {
index e8bf9247f221673d07c4bca62bcf58934c1820d2..cb162b953629bc2d9571da9c4a063a640acfc6f4 100644 (file)
@@ -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;
 
index 1ff204834292a9068c52f4e0dc340c0fd4776ddb..5351ce8820cce76166202c99372918ce917cd253 100644 (file)
@@ -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;
+}
index 43d441be40fc1cf5be08ba6e527417d97db623aa..ece89396307f2eefcdd1f10b9e70d3e1e27b04c4 100644 (file)
@@ -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_