From 333c680c9aa8e9f6e296754e13776719186c4ec0 Mon Sep 17 00:00:00 2001 From: Bitcoin3us <115934595+bitcoin3us@users.noreply.github.com> Date: Wed, 16 Sep 2026 13:52:15 +0100 Subject: [PATCH] task_handler: advance LVGL time from a single elapsed-based source LVGL time ran ~1.8x faster than wall clock on ESP32 builds: _timer_cb added the nominal period on every machine.Timer tick while _task_handler also added the elapsed time on every scheduled pass (plus a third increment covering the FINISHED callbacks). Every lv timer, animation, scroll throw and long-press threshold therefore fired early; a 12 fps lv.timer produced 14 frames per second. Measured on a Waveshare ESP32-S3-Touch-LCD-3.5 (MicroPythonOS 0.18, TaskHandler duration=2): lv.tick_get() advanced 1.834 ms per wall-clock ms when idle. With TaskHandler.disable() (timer path only) the ratio was exactly 1.000, and under load the timer path alone lost ~20% of ticks because scheduled callbacks coalesce. Make _timer_cb the only place ticks are added, and have it add the real elapsed milliseconds since its previous run instead of the nominal period, so LVGL time equals wall time regardless of load. Verified 1.000 idle and under flash-read load; a stalled scheduler now catches up instead of losing time. Co-Authored-By: Claude Fable 5.1 --- .../frozen/other/task_handler.py | 22 +++++++------------ 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/api_drivers/common_api_drivers/frozen/other/task_handler.py b/api_drivers/common_api_drivers/frozen/other/task_handler.py index 99e9f4a1..8248aada 100644 --- a/api_drivers/common_api_drivers/frozen/other/task_handler.py +++ b/api_drivers/common_api_drivers/frozen/other/task_handler.py @@ -57,7 +57,7 @@ def __init__( self._task_handler_ref = self._task_handler self.max_scheduled = max_scheduled - self._start_time = time.ticks_ms() # NOQA + self._last_tick = time.ticks_ms() # NOQA self._timer.init( mode=Timer.PERIODIC, period=self.duration, @@ -126,16 +126,8 @@ def _task_handler(self, _): else: sys.print_exception(err) # NOQA - stop_time = time.ticks_ms() # NOQA - - ticks_diff = time.ticks_diff(stop_time, self._start_time) # NOQA - self._start_time = stop_time - lv.tick_inc(ticks_diff) - if run_update: lv.task_handler() - start_time = time.ticks_ms() # NOQA - for cb, evt, data in self._callbacks: if not evt & TASK_HANDLER_FINISHED: continue @@ -151,10 +143,6 @@ def _task_handler(self, _): else: sys.print_exception(err) # NOQA - stop_time = time.ticks_ms() # NOQA - ticks_diff = time.ticks_diff(stop_time, start_time) # NOQA - lv.tick_inc(ticks_diff) - self._running = False except Exception as e: @@ -164,7 +152,13 @@ def _task_handler(self, _): self.exception_hook(e) def _timer_cb(self, _): - lv.tick_inc(self.duration) + # The only place LVGL time advances. Feed it the real elapsed time + # rather than the nominal period: timer callbacks are delivered via the + # scheduler and coalesce or drop under load, and _task_handler must not + # add ticks of its own or LVGL time runs ~2x faster than wall clock. + now = time.ticks_ms() # NOQA + lv.tick_inc(time.ticks_diff(now, self._last_tick)) # NOQA + self._last_tick = now if self._running: return