]> git.earman.xyz Git - sensor-watch.git/commitdiff
More efficient display draw for fast_stopwatch_face
authorAlessandro Genova <ales.genova@gmail.com>
Wed, 27 Aug 2025 03:37:53 +0000 (23:37 -0400)
committerAlessandro Genova <ales.genova@gmail.com>
Sat, 3 Jan 2026 01:07:56 +0000 (20:07 -0500)
watch-faces/complication/fast_stopwatch_face.c
watch-faces/complication/fast_stopwatch_face.h

index a4af13f3d4700d6cb3fb76779e9f7aaacf7bc75a..9baad1b73a743aa8b93465ae9c146c1690c794b0 100644 (file)
@@ -25,6 +25,7 @@
 
 #include <stdlib.h>
 #include <string.h>
+#include <limits.h>
 #include "fast_stopwatch_face.h"
 #include "watch.h"
 #include "watch_common_display.h"
@@ -59,27 +60,52 @@ static inline void _button_beep() {
 // This is just for looks, timekeeping is always accurate to 128Hz
 static const uint8_t DISPLAY_RUNNING_RATE = 32;
 
-static const uint32_t TWENTY_FOUR_HOURS = 24 * 60 * 60 * 128;
-
 /// @brief Display minutes, seconds and fractions derived from 128 Hz tick counter
 ///        on the lcd.
 /// @param ticks
-static void _display_elapsed(uint32_t ticks) {
-    ticks = ticks % TWENTY_FOUR_HOURS;
-    char buf[14];
+static void _display_elapsed(fast_stopwatch_state_t *state, uint32_t ticks) {
+    char buf[3];
     uint8_t sec_100 = (ticks & 0x7F) * 100 / 128;
+
+    watch_display_character_lp_seconds('0' + sec_100 / 10, 8);
+    watch_display_character_lp_seconds('0' + sec_100 % 10, 9);
+
     uint32_t seconds = ticks >> 7;
+
+    if (seconds == state->old_display.seconds) {
+        return;
+    }
+
+    state->old_display.seconds = seconds;
+
+    sprintf(buf, "%02lu", seconds % 60);
+    watch_display_text(WATCH_POSITION_MINUTES, buf);
+
     uint32_t minutes = seconds / 60;
-    uint32_t hours = minutes / 60;
+
+    if (minutes == state->old_display.minutes) {
+        return;
+    }
+
+    state->old_display.minutes = minutes;
+
+    sprintf(buf, "%02lu", minutes % 60);
+    watch_display_text(WATCH_POSITION_HOURS, buf);
+
+    uint32_t hours = (minutes / 60) % 24;
+
+    if (hours == state->old_display.hours) {
+        return;
+    }
+
+    state->old_display.hours = hours;
+
     if (hours) {
-        sprintf(buf, "%2u", hours);
+        sprintf(buf, "%2lu", hours);
         watch_display_text(WATCH_POSITION_TOP_RIGHT, buf);
     } else {
         watch_display_text(WATCH_POSITION_TOP_RIGHT, "  ");
     }
-
-    sprintf(buf, "%02lu%02lu%02u", (minutes % 60), (seconds % 60), sec_100);
-    watch_display_text(WATCH_POSITION_BOTTOM, buf);
 }
 
 static void _draw_indicators(fast_stopwatch_state_t *state, movement_event_t event, uint32_t elapsed) {
@@ -255,6 +281,10 @@ void fast_stopwatch_face_setup(uint8_t watch_face_index, void ** context_ptr) {
 
 void fast_stopwatch_face_activate(void *context) {
     fast_stopwatch_state_t *state = (fast_stopwatch_state_t *) context;
+    // force full re-draw
+    state->old_display.seconds = UINT_MAX;
+    state->old_display.minutes = UINT_MAX;
+    state->old_display.hours = UINT_MAX;
     movement_request_tick_frequency(get_refresh_rate(state));
 }
 
@@ -270,7 +300,7 @@ bool fast_stopwatch_face_loop(movement_event_t event, void *context) {
         case EVENT_ACTIVATE:
             watch_display_text_with_fallback(WATCH_POSITION_TOP_LEFT, "STW", "ST");
             _draw_indicators(state, event, elapsed);
-            _display_elapsed(elapsed);
+            _display_elapsed(state, elapsed);
             break;
         case EVENT_ALARM_BUTTON_DOWN:
         case EVENT_LIGHT_BUTTON_DOWN:
@@ -278,7 +308,7 @@ bool fast_stopwatch_face_loop(movement_event_t event, void *context) {
             // Fall into the case below;
         case EVENT_TICK:
             _draw_indicators(state, event, elapsed);
-            _display_elapsed(elapsed);
+            _display_elapsed(state, elapsed);
             break;
         default:
             movement_default_loop_handler(event);
index d99f60853bd43155f2170f4b644075c275914ce7..70c78bef2001ae772c9b637f68af1dfb4ac1f893 100644 (file)
@@ -59,6 +59,11 @@ typedef struct {
     rtc_counter_t lap_counter;   // rtc counter when the stopwatch was lapped
     rtc_counter_t stop_counter;  // rtc counter when the stopwatch was stopped
     uint8_t status;              // the status the stopwatch is in (idle, running, stopped)
+    struct {
+        rtc_counter_t seconds;
+        rtc_counter_t minutes;
+        rtc_counter_t hours;
+    } old_display;               // the digits currently being displayed on screen
 } fast_stopwatch_state_t;
 
 void fast_stopwatch_face_setup(uint8_t watch_face_index, void ** context_ptr);