Add a slow display refresh mode to fast_stopwatch

This commit is contained in:
Alessandro Genova
2025-08-26 23:56:50 -04:00
parent 7d0f4d1a33
commit edd3a5c3b4
2 changed files with 33 additions and 11 deletions
+28 -7
View File
@@ -31,6 +31,7 @@
#include "watch_common_display.h" #include "watch_common_display.h"
#include "watch_utility.h" #include "watch_utility.h"
#include "watch_rtc.h" #include "watch_rtc.h"
#include "slcd.h"
/* /*
This watch face implements the original F-91W stopwatch functionality This watch face implements the original F-91W stopwatch functionality
@@ -59,16 +60,23 @@ static inline void _button_beep() {
// How quickly should the elapsing time be displayed? // How quickly should the elapsing time be displayed?
// 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 uint8_t DISPLAY_RUNNING_RATE_SLOW = 2;
/// @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(fast_stopwatch_state_t *state, uint32_t ticks) { static void _display_elapsed(fast_stopwatch_state_t *state, uint32_t ticks) {
char buf[3]; char buf[3];
if (state->slow_refresh && (state->status == SW_STATUS_RUNNING || state->status == SW_STATUS_IDLE)) {
watch_display_character_lp_seconds(' ', 8);
watch_display_character_lp_seconds(' ', 9);
} else {
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, 8);
watch_display_character_lp_seconds('0' + sec_100 % 10, 9); watch_display_character_lp_seconds('0' + sec_100 % 10, 9);
}
uint32_t seconds = ticks >> 7; uint32_t seconds = ticks >> 7;
@@ -157,7 +165,11 @@ static void _draw_indicators(fast_stopwatch_state_t *state, movement_event_t eve
static uint8_t get_refresh_rate(fast_stopwatch_state_t *state) { static uint8_t get_refresh_rate(fast_stopwatch_state_t *state) {
switch (state->status) { switch (state->status) {
case SW_STATUS_RUNNING: case SW_STATUS_RUNNING:
if (state->slow_refresh) {
return DISPLAY_RUNNING_RATE_SLOW;
} else {
return DISPLAY_RUNNING_RATE; return DISPLAY_RUNNING_RATE;
}
case SW_STATUS_RUNNING_LAPPING: case SW_STATUS_RUNNING_LAPPING:
return 2; return 2;
case SW_STATUS_STOPPED: case SW_STATUS_STOPPED:
@@ -174,7 +186,10 @@ static void state_transition(fast_stopwatch_state_t *state, rtc_counter_t counte
case EVENT_ALARM_BUTTON_DOWN: case EVENT_ALARM_BUTTON_DOWN:
state->status = SW_STATUS_RUNNING; state->status = SW_STATUS_RUNNING;
state->start_counter = counter; state->start_counter = counter;
movement_request_tick_frequency(DISPLAY_RUNNING_RATE); movement_request_tick_frequency(get_refresh_rate(state));
return;
case EVENT_LIGHT_LONG_PRESS:
state->slow_refresh = !state->slow_refresh;
return; return;
default: default:
return; return;
@@ -185,12 +200,12 @@ static void state_transition(fast_stopwatch_state_t *state, rtc_counter_t counte
case EVENT_ALARM_BUTTON_DOWN: case EVENT_ALARM_BUTTON_DOWN:
state->status = SW_STATUS_STOPPED; state->status = SW_STATUS_STOPPED;
state->stop_counter = counter; state->stop_counter = counter;
movement_request_tick_frequency(1); movement_request_tick_frequency(get_refresh_rate(state));
return; return;
case EVENT_LIGHT_BUTTON_DOWN: case EVENT_LIGHT_BUTTON_DOWN:
state->status = SW_STATUS_RUNNING_LAPPING; state->status = SW_STATUS_RUNNING_LAPPING;
state->lap_counter = counter; state->lap_counter = counter;
movement_request_tick_frequency(2); movement_request_tick_frequency(get_refresh_rate(state));
return; return;
default: default:
return; return;
@@ -201,12 +216,17 @@ static void state_transition(fast_stopwatch_state_t *state, rtc_counter_t counte
case EVENT_ALARM_BUTTON_DOWN: case EVENT_ALARM_BUTTON_DOWN:
state->status = SW_STATUS_STOPPED_LAPPING; state->status = SW_STATUS_STOPPED_LAPPING;
state->stop_counter = counter; state->stop_counter = counter;
movement_request_tick_frequency(1); movement_request_tick_frequency(get_refresh_rate(state));
return; return;
case EVENT_LIGHT_BUTTON_DOWN: case EVENT_LIGHT_BUTTON_DOWN:
state->status = SW_STATUS_RUNNING; state->status = SW_STATUS_RUNNING;
state->lap_counter = counter; state->lap_counter = counter;
movement_request_tick_frequency(DISPLAY_RUNNING_RATE); movement_request_tick_frequency(get_refresh_rate(state));
return;
case EVENT_LIGHT_LONG_PRESS:
state->status = SW_STATUS_RUNNING;
state->slow_refresh = !state->slow_refresh;
movement_request_tick_frequency(get_refresh_rate(state));
return; return;
default: default:
return; return;
@@ -218,7 +238,7 @@ static void state_transition(fast_stopwatch_state_t *state, rtc_counter_t counte
state->status = SW_STATUS_RUNNING_LAPPING; state->status = SW_STATUS_RUNNING_LAPPING;
state->start_counter = counter - state->stop_counter + state->start_counter; state->start_counter = counter - state->stop_counter + state->start_counter;
state->lap_counter = counter - state->stop_counter + state->lap_counter; state->lap_counter = counter - state->stop_counter + state->lap_counter;
movement_request_tick_frequency(2); movement_request_tick_frequency(get_refresh_rate(state));
return; return;
case EVENT_LIGHT_BUTTON_DOWN: case EVENT_LIGHT_BUTTON_DOWN:
state->status = SW_STATUS_STOPPED; state->status = SW_STATUS_STOPPED;
@@ -232,7 +252,7 @@ static void state_transition(fast_stopwatch_state_t *state, rtc_counter_t counte
case EVENT_ALARM_BUTTON_DOWN: case EVENT_ALARM_BUTTON_DOWN:
state->status = SW_STATUS_RUNNING; state->status = SW_STATUS_RUNNING;
state->start_counter = counter - state->stop_counter + state->start_counter; state->start_counter = counter - state->stop_counter + state->start_counter;
movement_request_tick_frequency(DISPLAY_RUNNING_RATE); movement_request_tick_frequency(get_refresh_rate(state));
return; return;
case EVENT_LIGHT_BUTTON_DOWN: case EVENT_LIGHT_BUTTON_DOWN:
state->status = SW_STATUS_IDLE; state->status = SW_STATUS_IDLE;
@@ -304,6 +324,7 @@ bool fast_stopwatch_face_loop(movement_event_t event, void *context) {
break; break;
case EVENT_ALARM_BUTTON_DOWN: case EVENT_ALARM_BUTTON_DOWN:
case EVENT_LIGHT_BUTTON_DOWN: case EVENT_LIGHT_BUTTON_DOWN:
case EVENT_LIGHT_LONG_PRESS:
_button_beep(); _button_beep();
// Fall into the case below; // Fall into the case below;
case EVENT_TICK: case EVENT_TICK:
@@ -59,6 +59,7 @@ 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)
bool slow_refresh; // update the display slowly (same 128Hz timekeeping accuracy)
struct { struct {
rtc_counter_t seconds; rtc_counter_t seconds;
rtc_counter_t minutes; rtc_counter_t minutes;