Skip to content

feat: partial refresh support via py-opendisplay 7.11.1#57

Merged
g4bri3lDev merged 1 commit into
feat/clean-portfrom
feat/partial-refresh
Jul 6, 2026
Merged

feat: partial refresh support via py-opendisplay 7.11.1#57
g4bri3lDev merged 1 commit into
feat/clean-portfrom
feat/partial-refresh

Conversation

@g4bri3lDev

Copy link
Copy Markdown
Member

Summary

Implements partial refresh for upload_image and drawcustom, superseding the approach in #47 now that py-opendisplay ships native support (thanks @jonasniesner for the groundwork — the per-entry state pattern follows your PR).

  • refresh_mode/refresh_type: partial diffs against the entry's PartialState and updates flicker-free via 0x76; full/fast re-baseline the state (doubling as the periodic deghosting refresh). Legacy numeric 2/3 map to partial.
  • All panel handling is in the library: automatic fallback to full upload (unsupported panel, etag mismatch, firmware NACK), automatic full-frame region expansion on partial_update_support: 2 panels (Partial refresh (0x76) erases all content outside the rect on EP426 — white-fill at partial START relies on panel-LUT behavior that EP426 doesn't have Firmware#80) — no compute_partial_region monkeypatch, no separate partial_full mode — and identical frames skip the BLE transfer entirely.
  • Requirement bump to py-opendisplay==7.11.1: brings partial support (#116), the streaming-only compression gate fixes (#114, also applied to this repo's prepare_image gate), and epaper-dithering 5.0.8 — without which drawcustom's default tone=auto renders bilevel text frames all-black (NaN collapse, epaper-dithering#51).
  • UI: selector option is "Partial"; the flicker-free behavior and fallback semantics are explained in the field descriptions.

Hardware verification (EN05, EP426 800×480 MONO, fw 2.0, partial_update_support: 2, via a live HA dev instance)

  • drawcustom scenario suite over BLE, camera-verified: timestamp ticks over a dithered gray field (3 cycles, zero degradation), inverted status bar appear/replace, progress bar updates, and an identical-payload call correctly logging No pixels changed; skipping upload with no transfer. Etag chain unbroken across 7 operations; ~2.3 KB compressed wire per full-frame partial.
  • Known cosmetic caveat: large solid black fills written across successive partials can show slightly different black densities (partial-waveform lighter blacks). Text is unaffected; an occasional full refresh restores uniform blacks — which the state handling makes cheap.

Notes

  • full remains the default; partial-by-default with a configurable every-N deghost full could be a follow-up.
  • State is in-memory per entry: first upload after an HA restart is a full refresh, then partials resume. PartialState.to_bytes() persistence via a Store is possible later.

🤖 Generated with Claude Code

Adds "partial" as a refresh mode for upload_image and drawcustom. A
PartialState per config entry tracks the last uploaded frame + etag;
partial refreshes diff against it and update flicker-free via the 0x76
protocol, while full/fast refreshes re-baseline the state so the next
partial diffs against the frame actually on the panel.

All panel handling lives in the library: automatic fallback to a full
upload when partial is not possible, automatic full-frame region
expansion on panels that require it (partial_update_support=2,
OpenDisplay/Firmware#80), and identical frames skip the transfer
entirely. Legacy numeric refresh_type 2/3 map to partial.

Also fixes the compression gate for streaming-decompression-only
configs (bit 0x01 without ZIP): such panels uploaded every frame
uncompressed. Requires py-opendisplay 7.11.1 (partial support,
compression gates, and the epaper-dithering 5.0.8 tone=auto NaN fix
without which bilevel drawcustom frames render all-black).
@g4bri3lDev g4bri3lDev merged commit 350bf04 into feat/clean-port Jul 6, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant