Stop the constant repaint that made the left-edge artefacts permanent
The artefacts went from occasional to continuous, and the cause was my own
mitigation for them.
lv_obj_set_local_style_prop() does NOT skip identical values -- it calls
lv_obj_refresh_style() unconditionally, which invalidates the object. A
comment in ui_set_stale() claimed the opposite and that assumption spread.
ui_update_thermostat() is called once a second by the control task and was
writing seven style properties every time, so the panel was redrawing
something forever, and glitched lines were being regenerated as fast as
anything could clear them.
Two full-screen invalidates made it worse still: one after every HA poll,
one 600ms after every touch. The premise was that LVGL never reinvalidates
pixels it does not know are wrong, so repainting would clean them up. But
the README already had the answer -- the corruption scales with how much is
written, because LVGL's PSRAM writes compete with the panel's DMA reads out
of the same PSRAM. A full repaint is 768KB of exactly the contention that
causes the problem. Both are removed.
What is left is the thing that actually helps: write less.
- ui_update_thermostat() returns without taking the lock when nothing
moved, and otherwise touches only the widgets whose values changed.
- ui_set_stale() is guarded on the previous value.
- Condition and trend icons only get a colour write when the glyph itself
changed.
Also raises the bounce buffer from 16 to 20 scanlines. The comment saying
20 "fails to allocate once WiFi is up" was true when display_init() ran
after wifi_init_sta(); it does not any more. display_alloc() takes the
buffers from a virgin heap with ~200KB free, so the extra 12.8KB is
affordable, and each larger chunk buys the refill ISR more time to fetch the
next one before the LCD needs it. That attacks the mechanism rather than the
symptom. ~24KB internal heap remains once WiFi is up; the "Free internal
heap" log line is the thing to watch if it needs to come back down.
Both gotchas are now in the README so the next person does not reach for a
repaint again.
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
1 parent
3aabcac90a
commit
7a58f9838a
5 files changed
+212
-129
No files matched your search
+11
-12
@@ -289,20 +289,19 @@ static void ha_task(void *arg)
|
||||
lvgl_port_resume();
|
||||
|
||||
/*
|
||||
* Repaint everything after every fetch window.
|
||||
* No full-screen invalidate here, deliberately.
|
||||
*
|
||||
* The known left-edge artefacts (see README) happen when WiFi
|
||||
* interrupt load starves the bounce-refill ISR, and once bad pixels
|
||||
* are on screen LVGL has no idea they are wrong -- it never
|
||||
* reinvalidates them, so they sit there indefinitely. A full
|
||||
* invalidate after each poll bounds their lifetime at one poll
|
||||
* interval. Mitigation, not cure: it cannot prevent the glitch,
|
||||
* only clean up after it.
|
||||
* There used to be one, on the theory that repainting would clean up
|
||||
* glitched pixels LVGL does not know are wrong. It made things
|
||||
* materially worse, and the README already said why: the corruption
|
||||
* scales with how much is written, because LVGL's writes into PSRAM
|
||||
* compete with the panel's own DMA reads out of it. A full repaint is
|
||||
* 768KB of exactly that contention -- the largest possible dose of
|
||||
* the cause, applied as a cure.
|
||||
*
|
||||
* Redraw as little as possible is the actual lever. See ui_update*(),
|
||||
* which now write nothing when nothing changed.
|
||||
*/
|
||||
if (lvgl_port_lock(100)) {
|
||||
lv_obj_invalidate(lv_screen_active());
|
||||
lvgl_port_unlock();
|
||||
}
|
||||
|
||||
poll_count++;
|
||||
|
||||
|
||||
Reference in new issue
Block a user