Merge pull request #178 from redraw/fix/simulator-watch-rtc-counter

Improved simulator watch RTC counter precision
This commit is contained in:
atax1a
2026-03-19 21:59:24 +00:00
committed by GitHub
+35 -9
View File
@@ -22,6 +22,7 @@
* SOFTWARE.
*/
#include <limits.h>
#include <stdbool.h>
#include "watch_rtc.h"
#include "watch_main_loop.h"
@@ -35,9 +36,10 @@ 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;
#define WATCH_RTC_N_COMP_CB 8
@@ -66,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) {
@@ -82,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);
@@ -164,6 +166,27 @@ void watch_rtc_disable_tick_callback(void) {
watch_rtc_disable_periodic_callback(1);
}
static void _watch_schedule_next_tick(void) {
if (!rtc_enabled) return;
double now = EM_ASM_DOUBLE({ return performance.now(); });
// 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;
// If we're behind, reset timing
if (delay < 0) {
next_tick_time = now + ms;
delay = ms;
}
emscripten_async_call(_watch_increase_counter, NULL, delay);
}
static void _watch_increase_counter(void *userData) {
(void) userData;
@@ -174,6 +197,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) {
@@ -338,17 +364,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) {
// 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
rtc_enabled = true;
next_tick_time = EM_ASM_DOUBLE({ return performance.now(); });
_watch_schedule_next_tick();
} else {
emscripten_clear_interval(counter_interval);
counter_interval = 0;
rtc_enabled = false;
}
}