From 7d4a80a29dd7d2bc7954aea8adf19af05213a9d9 Mon Sep 17 00:00:00 2001 From: redraw Date: Wed, 21 Jan 2026 13:52:15 -0300 Subject: [PATCH 1/5] fixed simulator watch rtc counter --- watch-library/simulator/watch/watch_rtc.c | 52 ++++++++++++++++++++--- 1 file changed, 47 insertions(+), 5 deletions(-) diff --git a/watch-library/simulator/watch/watch_rtc.c b/watch-library/simulator/watch/watch_rtc.c index 4927ba14..7e23e6ee 100644 --- a/watch-library/simulator/watch/watch_rtc.c +++ b/watch-library/simulator/watch/watch_rtc.c @@ -38,6 +38,8 @@ static const uint32_t RTC_CNT_TICKS_PER_MINUTE = RTC_CNT_HZ * 60; static uint32_t counter_interval; static uint32_t counter; static uint32_t reference_timestamp; +static double next_tick_time; +static double rtc_start_time; #define WATCH_RTC_N_COMP_CB 8 @@ -109,7 +111,18 @@ unix_timestamp_t watch_rtc_get_unix_time(void) { } rtc_counter_t watch_rtc_get_counter(void) { - return counter; + if (!counter_interval) { + return counter; // RTC not running + } + + // Calculate current counter from high-precision time + double now = EM_ASM_DOUBLE({ return performance.now(); }); + double elapsed_ms = now - rtc_start_time; + + // Convert elapsed time to RTC ticks (RTC_CNT_HZ = 128 Hz) + double elapsed_ticks = (elapsed_ms * RTC_CNT_HZ) / 1000.0; + + return (rtc_counter_t)elapsed_ticks; } uint32_t watch_rtc_get_frequency(void) { @@ -164,6 +177,30 @@ void watch_rtc_disable_tick_callback(void) { watch_rtc_disable_periodic_callback(1); } +static void _watch_increase_counter(void *userData); + +static void _watch_schedule_next_tick(void) { + if (!counter_interval) return; + + double now = EM_ASM_DOUBLE({ return performance.now(); }); + double drift = now - next_tick_time; + + // Target interval in ms + double ms = 1000.0 / (double)RTC_CNT_HZ; + + // Schedule next tick, correcting for drift + next_tick_time += ms; + double delay = next_tick_time - now; + + // Ensure we don't schedule negative or zero delays + if (delay < 0.1) { + delay = 0.1; + next_tick_time = now + delay; + } + + emscripten_async_call(_watch_increase_counter, NULL, (int)delay); +} + static void _watch_increase_counter(void *userData) { (void) userData; @@ -174,6 +211,9 @@ static void _watch_increase_counter(void *userData) { _watch_process_comp_callbacks(); resume_main_loop(); + + // Schedule the next tick with drift correction + _watch_schedule_next_tick(); } static void _watch_process_periodic_callbacks(void) { @@ -343,11 +383,13 @@ void watch_rtc_enable(bool en) } if (en) { - // Very bad way to keep time, but okay way to emulates the hardware. - double ms = 1000.0 / (double)RTC_CNT_HZ; // in msec - counter_interval = emscripten_set_interval(_watch_increase_counter, ms, NULL); + // Use drift-correcting timer instead of fixed setInterval + counter_interval = 1; // Non-zero to indicate enabled + rtc_start_time = EM_ASM_DOUBLE({ return performance.now(); }); + next_tick_time = rtc_start_time; + counter = 0; + _watch_schedule_next_tick(); } else { - emscripten_clear_interval(counter_interval); counter_interval = 0; } } From a3664b0789f98fbef4f32e82decb241fdda25481 Mon Sep 17 00:00:00 2001 From: redraw Date: Thu, 22 Jan 2026 10:29:52 -0300 Subject: [PATCH 2/5] update simulator rtc counter improvements to match real hardware --- watch-library/simulator/watch/watch_rtc.c | 28 +++++------------------ 1 file changed, 6 insertions(+), 22 deletions(-) diff --git a/watch-library/simulator/watch/watch_rtc.c b/watch-library/simulator/watch/watch_rtc.c index 7e23e6ee..ad3e5db3 100644 --- a/watch-library/simulator/watch/watch_rtc.c +++ b/watch-library/simulator/watch/watch_rtc.c @@ -39,7 +39,6 @@ static uint32_t counter_interval; static uint32_t counter; static uint32_t reference_timestamp; static double next_tick_time; -static double rtc_start_time; #define WATCH_RTC_N_COMP_CB 8 @@ -111,18 +110,7 @@ unix_timestamp_t watch_rtc_get_unix_time(void) { } rtc_counter_t watch_rtc_get_counter(void) { - if (!counter_interval) { - return counter; // RTC not running - } - - // Calculate current counter from high-precision time - double now = EM_ASM_DOUBLE({ return performance.now(); }); - double elapsed_ms = now - rtc_start_time; - - // Convert elapsed time to RTC ticks (RTC_CNT_HZ = 128 Hz) - double elapsed_ticks = (elapsed_ms * RTC_CNT_HZ) / 1000.0; - - return (rtc_counter_t)elapsed_ticks; + return counter; } uint32_t watch_rtc_get_frequency(void) { @@ -183,7 +171,6 @@ static void _watch_schedule_next_tick(void) { if (!counter_interval) return; double now = EM_ASM_DOUBLE({ return performance.now(); }); - double drift = now - next_tick_time; // Target interval in ms double ms = 1000.0 / (double)RTC_CNT_HZ; @@ -192,13 +179,12 @@ static void _watch_schedule_next_tick(void) { next_tick_time += ms; double delay = next_tick_time - now; - // Ensure we don't schedule negative or zero delays - if (delay < 0.1) { - delay = 0.1; - next_tick_time = now + delay; + // If we're behind, schedule immediately + if (delay < 0) { + delay = 0; } - emscripten_async_call(_watch_increase_counter, NULL, (int)delay); + emscripten_async_call(_watch_increase_counter, NULL, delay); } static void _watch_increase_counter(void *userData) { @@ -385,9 +371,7 @@ void watch_rtc_enable(bool en) if (en) { // Use drift-correcting timer instead of fixed setInterval counter_interval = 1; // Non-zero to indicate enabled - rtc_start_time = EM_ASM_DOUBLE({ return performance.now(); }); - next_tick_time = rtc_start_time; - counter = 0; + next_tick_time = EM_ASM_DOUBLE({ return performance.now(); }); _watch_schedule_next_tick(); } else { counter_interval = 0; From d653cf6921ba49586a6efe3396d6b6f2eef3b90d Mon Sep 17 00:00:00 2001 From: redraw Date: Thu, 22 Jan 2026 13:18:18 -0300 Subject: [PATCH 3/5] renamed counter_interval to rtc_enabled --- watch-library/simulator/watch/watch_rtc.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/watch-library/simulator/watch/watch_rtc.c b/watch-library/simulator/watch/watch_rtc.c index ad3e5db3..cbda46b0 100644 --- a/watch-library/simulator/watch/watch_rtc.c +++ b/watch-library/simulator/watch/watch_rtc.c @@ -22,6 +22,7 @@ * SOFTWARE. */ #include +#include #include "watch_rtc.h" #include "watch_main_loop.h" @@ -35,7 +36,7 @@ static const uint32_t RTC_CNT_SUBSECOND_MASK = RTC_CNT_HZ - 1; static const uint32_t RTC_CNT_DIV = 7; static const uint32_t RTC_CNT_TICKS_PER_MINUTE = RTC_CNT_HZ * 60; -static uint32_t counter_interval; +static bool rtc_enabled; static uint32_t counter; static uint32_t reference_timestamp; static double next_tick_time; @@ -67,7 +68,7 @@ static void _watch_process_periodic_callbacks(void); static void _watch_process_comp_callbacks(void); bool _watch_rtc_is_enabled(void) { - return counter_interval; + return rtc_enabled; } void _watch_rtc_init(void) { @@ -83,7 +84,7 @@ void _watch_rtc_init(void) { scheduled_comp_counter = 0; counter = 0; - counter_interval = 0; + rtc_enabled = false; watch_rtc_set_date_time(watch_get_init_date_time()); watch_rtc_enable(true); @@ -168,7 +169,7 @@ void watch_rtc_disable_tick_callback(void) { static void _watch_increase_counter(void *userData); static void _watch_schedule_next_tick(void) { - if (!counter_interval) return; + if (!rtc_enabled) return; double now = EM_ASM_DOUBLE({ return performance.now(); }); @@ -364,17 +365,17 @@ void watch_rtc_schedule_next_comp(void) { void watch_rtc_enable(bool en) { // Nothing to do cases - if ((en && counter_interval) || (!en && !counter_interval)) { + if ((en && rtc_enabled) || (!en && !rtc_enabled)) { return; } if (en) { // Use drift-correcting timer instead of fixed setInterval - counter_interval = 1; // Non-zero to indicate enabled + rtc_enabled = true; next_tick_time = EM_ASM_DOUBLE({ return performance.now(); }); _watch_schedule_next_tick(); } else { - counter_interval = 0; + rtc_enabled = false; } } From 22293ed6932119aa428065068f87c59cb58c1b87 Mon Sep 17 00:00:00 2001 From: redraw Date: Thu, 22 Jan 2026 17:31:01 -0300 Subject: [PATCH 4/5] jump counter forward when tab resumes from background --- watch-library/simulator/watch/watch_rtc.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/watch-library/simulator/watch/watch_rtc.c b/watch-library/simulator/watch/watch_rtc.c index cbda46b0..3492032f 100644 --- a/watch-library/simulator/watch/watch_rtc.c +++ b/watch-library/simulator/watch/watch_rtc.c @@ -180,9 +180,12 @@ static void _watch_schedule_next_tick(void) { next_tick_time += ms; double delay = next_tick_time - now; - // If we're behind, schedule immediately + // If we're behind, jump counter forward and reset timing if (delay < 0) { - delay = 0; + uint32_t missed_ticks = (uint32_t)((-delay) / ms); + counter += missed_ticks; + next_tick_time = now + ms; + delay = ms; } emscripten_async_call(_watch_increase_counter, NULL, delay); From aba0aa97ec5b6b9416c80025e2f0a88b3e2684b5 Mon Sep 17 00:00:00 2001 From: redraw Date: Thu, 22 Jan 2026 23:55:55 -0300 Subject: [PATCH 5/5] don't jump missed ticks, forgot callbacks --- watch-library/simulator/watch/watch_rtc.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/watch-library/simulator/watch/watch_rtc.c b/watch-library/simulator/watch/watch_rtc.c index 3492032f..93da5e6b 100644 --- a/watch-library/simulator/watch/watch_rtc.c +++ b/watch-library/simulator/watch/watch_rtc.c @@ -166,8 +166,6 @@ void watch_rtc_disable_tick_callback(void) { watch_rtc_disable_periodic_callback(1); } -static void _watch_increase_counter(void *userData); - static void _watch_schedule_next_tick(void) { if (!rtc_enabled) return; @@ -180,10 +178,8 @@ static void _watch_schedule_next_tick(void) { next_tick_time += ms; double delay = next_tick_time - now; - // If we're behind, jump counter forward and reset timing + // If we're behind, reset timing if (delay < 0) { - uint32_t missed_ticks = (uint32_t)((-delay) / ms); - counter += missed_ticks; next_tick_time = now + ms; delay = ms; }