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

View 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);

View 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);