]> git.earman.xyz Git - sensor-watch.git/commitdiff
Movement: allow scheduling precisely timed background tasks (resolves #28)
authorJoey Castillo <joeycastillo@utexas.edu>
Mon, 20 Dec 2021 18:35:37 +0000 (12:35 -0600)
committerJoey Castillo <joeycastillo@utexas.edu>
Mon, 20 Dec 2021 18:37:11 +0000 (12:37 -0600)
movement/movement.c
movement/movement.h

index cdd4ff069c0aa76525b2144f8cd800c2bd026282..783c666c8e772c07ad0173501f8e827cf21317af 100644 (file)
@@ -7,6 +7,7 @@
 
 movement_state_t movement_state;
 void * watch_face_contexts[MOVEMENT_NUM_FACES];
+watch_date_time scheduled_tasks[MOVEMENT_NUM_FACES];
 const int32_t movement_le_inactivity_deadlines[8] = {INT_MAX, 3600, 7200, 21600, 43200, 86400, 172800, 604800};
 const int16_t movement_timeout_inactivity_deadlines[4] = {60, 120, 300, 1800};
 movement_event_t event;
@@ -99,6 +100,29 @@ static void _movement_handle_background_tasks(void) {
     movement_state.needs_background_tasks_handled = false;
 }
 
+static void _movement_handle_scheduled_tasks(void) {
+    watch_date_time date_time = watch_rtc_get_date_time();
+    uint8_t num_active_tasks = 0;
+
+    for(uint8_t i = 0; i < MOVEMENT_NUM_FACES; i++) {
+        if (scheduled_tasks[i].reg) {
+            if (scheduled_tasks[i].reg == date_time.reg) {
+                scheduled_tasks[i].reg = 0;
+                movement_event_t background_event = { EVENT_BACKGROUND_TASK, 0 };
+                watch_faces[i].loop(background_event, &movement_state.settings, watch_face_contexts[i]);
+            } else {
+                num_active_tasks++;
+            }
+        }
+    }
+
+    if (num_active_tasks == 0) {
+        movement_state.has_scheduled_background_task = false;
+    } else {
+        _movement_reset_inactivity_countdown();
+    }
+}
+
 void movement_request_tick_frequency(uint8_t freq) {
     if (freq == 128) return; // Movement uses the 128 Hz tick internally
     RTC->MODE2.INTENCLR.reg = 0xFE; // disable all callbacks except the 128 Hz one
@@ -125,6 +149,14 @@ void movement_move_to_next_face(void) {
     movement_move_to_face((movement_state.current_watch_face + 1) % MOVEMENT_NUM_FACES);
 }
 
+void movement_schedule_background_task(watch_date_time date_time) {
+    watch_date_time now = watch_rtc_get_date_time();
+    if (date_time.reg > now.reg) {
+        movement_state.has_scheduled_background_task = true;
+        scheduled_tasks[movement_state.current_watch_face].reg = date_time.reg;
+    }
+}
+
 void movement_play_signal(void) {
     watch_buzzer_play_note(BUZZER_NOTE_C8, 75);
     watch_buzzer_play_note(BUZZER_NOTE_REST, 100);
@@ -161,6 +193,7 @@ void app_setup(void) {
     if (is_first_launch) {
         for(uint8_t i = 0; i < MOVEMENT_NUM_FACES; i++) {
             watch_face_contexts[i] = NULL;
+            scheduled_tasks[i].reg = 0;
             is_first_launch = false;
         }
 
@@ -230,6 +263,9 @@ bool app_loop(void) {
     // 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 a scheduled background task, handle that here:
+    if (event.event_type == EVENT_TICK && movement_state.has_scheduled_background_task) _movement_handle_scheduled_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;
index 62e4120b7e157624cf141eb3fce9f43966062597..b99f4e8b4c2029b5b70e0dae8a11dd1f2f04a4b8 100644 (file)
@@ -2,6 +2,7 @@
 #define MOVEMENT_H_
 #include <stdio.h>
 #include <stdbool.h>
+#include "watch.h"
 
 // Movement Preferences
 // These four 32-bit structs store information about the wearer and their preferences. Tentatively, the plan is
@@ -228,6 +229,7 @@ typedef struct {
 
     // background task handling
     bool needs_background_tasks_handled;
+    bool has_scheduled_background_task;
 
     // low energy mode countdown
     int32_t le_mode_ticks;
@@ -244,8 +246,15 @@ typedef struct {
 void movement_move_to_face(uint8_t watch_face_index);
 void movement_move_to_next_face(void);
 void movement_illuminate_led(void);
+
+// note: requesting a tick frequency of 0 will break any scheduled background tasks.
+// this will be fixed in a future refactor of the tick mechanism.
 void movement_request_tick_frequency(uint8_t freq);
 
+// note: watch faces can only schedule a background task when in the foreground, since
+// movement will associate the scheduled task with the currently active face.
+void movement_schedule_background_task(watch_date_time date_time);
+
 void movement_play_signal(void);
 void movement_play_alarm(void);