More efficient display draw for fast_stopwatch_face

This commit is contained in:
Alessandro Genova
2025-08-26 23:37:53 -04:00
parent 5293b7983c
commit 7d0f4d1a33
2 changed files with 47 additions and 12 deletions
+42 -12
View File
@@ -25,6 +25,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <limits.h>
#include "fast_stopwatch_face.h" #include "fast_stopwatch_face.h"
#include "watch.h" #include "watch.h"
#include "watch_common_display.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 // This is just for looks, timekeeping is always accurate to 128Hz
static const uint8_t DISPLAY_RUNNING_RATE = 32; 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 /// @brief Display minutes, seconds and fractions derived from 128 Hz tick counter
/// on the lcd. /// on the lcd.
/// @param ticks /// @param ticks
static void _display_elapsed(uint32_t ticks) { static void _display_elapsed(fast_stopwatch_state_t *state, uint32_t ticks) {
ticks = ticks % TWENTY_FOUR_HOURS; char buf[3];
char buf[14];
uint8_t sec_100 = (ticks & 0x7F) * 100 / 128; 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; 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 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) { if (hours) {
sprintf(buf, "%2u", hours); sprintf(buf, "%2lu", hours);
watch_display_text(WATCH_POSITION_TOP_RIGHT, buf); watch_display_text(WATCH_POSITION_TOP_RIGHT, buf);
} else { } else {
watch_display_text(WATCH_POSITION_TOP_RIGHT, " "); 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) { 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) { void fast_stopwatch_face_activate(void *context) {
fast_stopwatch_state_t *state = (fast_stopwatch_state_t *) 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)); 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: case EVENT_ACTIVATE:
watch_display_text_with_fallback(WATCH_POSITION_TOP_LEFT, "STW", "ST"); watch_display_text_with_fallback(WATCH_POSITION_TOP_LEFT, "STW", "ST");
_draw_indicators(state, event, elapsed); _draw_indicators(state, event, elapsed);
_display_elapsed(elapsed); _display_elapsed(state, elapsed);
break; break;
case EVENT_ALARM_BUTTON_DOWN: case EVENT_ALARM_BUTTON_DOWN:
case EVENT_LIGHT_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; // Fall into the case below;
case EVENT_TICK: case EVENT_TICK:
_draw_indicators(state, event, elapsed); _draw_indicators(state, event, elapsed);
_display_elapsed(elapsed); _display_elapsed(state, elapsed);
break; break;
default: default:
movement_default_loop_handler(event); movement_default_loop_handler(event);
@@ -59,6 +59,11 @@ typedef struct {
rtc_counter_t lap_counter; // rtc counter when the stopwatch was lapped rtc_counter_t lap_counter; // rtc counter when the stopwatch was lapped
rtc_counter_t stop_counter; // rtc counter when the stopwatch was stopped rtc_counter_t stop_counter; // rtc counter when the stopwatch was stopped
uint8_t status; // the status the stopwatch is in (idle, running, 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; } fast_stopwatch_state_t;
void fast_stopwatch_face_setup(uint8_t watch_face_index, void ** context_ptr); void fast_stopwatch_face_setup(uint8_t watch_face_index, void ** context_ptr);