at main
1 folder
13 files
Tune the SSD1681 fast waveform to 5 fps and add 2-bit grayscale rendering
Optimization round on the CoreInk fast-animation mode, all measured on
silicon via the EINKLUT live-tuning command (sweep waveform variants over
serial without reflashing):
- Fast partials run 0x22 = 0x8C: skipping the enable-analog stage (its
HV-ready detection costs ~91 ms even with the rails already up) cuts the
per-update fixed cost to ~94 ms. The stage is mandatory after full
refreshes, whose sequence powers the analog down, so the bank-settle pass
keeps 0xCC and doubles as the analog power-up (fastSettleSequence).
- Built-in waveform is the owner-picked quality-ladder point: 4 drive
frames at +/-17 V source voltage (VCOM/VGH stay on the panel's OTP trim)
plus a 1-frame reinforcement poke, the only ladder variant whose
animation trail self-cleans: 194 ms/update, 5.1 fps (from 503 ms / 1.5
fps at the start of the effort). BUSY poll tightened to 1 ms; the
post-update RAM rewrite proved redundant (read-back-verified) and the
gate-scan-window experiment proved frame period is FR-fixed, so neither
ships.
- ssd1681_lut.h: pure constexpr builders for the 153-byte waveform layout
(fast differential LUT with kick/burst/rest/poke knobs, graded grayscale
LUT, source-voltage register codes), the single source of truth shared
by the controller tables, EINKLUT and EINKGRAY, with a native host test
suite pinning the layout against the datasheet.
- 2-bit grayscale rendering (EpaperPanelDriver::renderGrayImage +
display::renderEpaperGray + EINKGRAY): both RAM planes select one of
four LUT slots per pixel, so graded drive lengths yield 4 tones in one
update or 6 tones (white + 4 grays + black) in two stacked updates —
owner-validated on the panel. The command holds the tones until serial
input (returning lets the FSM repaint and collapse them).
- SSD1681 register read-back (readPanelRegister over the shared SDA line):
the 0x2F Status Bit Read chip-ID bits fingerprint the controller in
silicon, settling that this CoreInk unit carries the D67/SSD1681 panel
revision, and SPIRD now works on e-paper. ANIMTEST gains TAG plus an
on-panel firmware-revision letter so tuning-ladder observers always know
which build/step they are watching.
Claude-Session: https://claude.ai/code/session_01SV58JXhfxhhc9DC6vdjBo4
Tune the SSD1681 fast waveform to 5 fps and add 2-bit grayscale rendering
Optimization round on the CoreInk fast-animation mode, all measured on
silicon via the EINKLUT live-tuning command (sweep waveform variants over
serial without reflashing):
- Fast partials run 0x22 = 0x8C: skipping the enable-analog stage (its
HV-ready detection costs ~91 ms even with the rails already up) cuts the
per-update fixed cost to ~94 ms. The stage is mandatory after full
refreshes, whose sequence powers the analog down, so the bank-settle pass
keeps 0xCC and doubles as the analog power-up (fastSettleSequence).
- Built-in waveform is the owner-picked quality-ladder point: 4 drive
frames at +/-17 V source voltage (VCOM/VGH stay on the panel's OTP trim)
plus a 1-frame reinforcement poke, the only ladder variant whose
animation trail self-cleans: 194 ms/update, 5.1 fps (from 503 ms / 1.5
fps at the start of the effort). BUSY poll tightened to 1 ms; the
post-update RAM rewrite proved redundant (read-back-verified) and the
gate-scan-window experiment proved frame period is FR-fixed, so neither
ships.
- ssd1681_lut.h: pure constexpr builders for the 153-byte waveform layout
(fast differential LUT with kick/burst/rest/poke knobs, graded grayscale
LUT, source-voltage register codes), the single source of truth shared
by the controller tables, EINKLUT and EINKGRAY, with a native host test
suite pinning the layout against the datasheet.
- 2-bit grayscale rendering (EpaperPanelDriver::renderGrayImage +
display::renderEpaperGray + EINKGRAY): both RAM planes select one of
four LUT slots per pixel, so graded drive lengths yield 4 tones in one
update or 6 tones (white + 4 grays + black) in two stacked updates —
owner-validated on the panel. The command holds the tones until serial
input (returning lets the FSM repaint and collapse them).
- SSD1681 register read-back (readPanelRegister over the shared SDA line):
the 0x2F Status Bit Read chip-ID bits fingerprint the controller in
silicon, settling that this CoreInk unit carries the D67/SSD1681 panel
revision, and SPIRD now works on e-paper. ANIMTEST gains TAG plus an
on-panel firmware-revision letter so tuning-ladder observers always know
which build/step they are watching.
Claude-Session: https://claude.ai/code/session_01SV58JXhfxhhc9DC6vdjBo4
Retire LVGL entirely (HAS_LVGL gone)
The T-Deck was the only LVGL device and now renders through the in-house UI
library (verified on hardware), so every #if HAS_LVGL branch is dead. Remove the
framework wholesale:
- Delete src/ui/lvgl/ (25 files: hal, input, screen_manager, theme, demo,
brand_mark, and the per-screen lvgl_*_screen set) and
src/ui/popup/lvgl_popup_adapter.{cpp,h}.
- Delete src/ui/core/render_task.{cpp,h} (the lv_timer_handler worker + LVGL
recursive mutex; every caller was LVGL-gated) and variants/tdeck/lv_conf.h.
- Delete src/hal/common/display_hal_tft.cpp (the HAS_LVGL && ST7789 backend);
the T-Deck now links display_hal_m5.cpp (BL pin >= 0, identical brightness path).
- De-gate ~25 source files: drop the dead HAS_LVGL branch, keep the live
in-house / HAS_KEYBOARD branch.
- Remove the HAS_LVGL macro (variants/tdeck/variant.h and the platform_defaults.h
default) and the lvgl/lvgl @ 9.2.2 lib_dep + LV_CONF flag in tdeck.ini.
- Update docs (groups.dox, building, ui/, design-system) and CLAUDE.md /
copilot-instructions to reflect that LVGL is retired fleet-wide.
Font tooling (scripts/fonts lv_font_conv) and descriptive lineage comments
(e.g. "raster replacement for lv_textarea") are kept. Full fleet builds green;
native 1075/1075; pio check clean; no HAS_LVGL/lvgl runtime reference remains.
Add 11 system-monitor debug commands (NVS/heap/clock/chip/rng/temp/secboot/audio/part/wdt/font)
Maximize observability — each command monitors a subsystem, so a QA test failing
here flags a firmware regression to review. All read-only, DEBUG_SERIAL_BUTTONS-
gated, KEY=value; every raw esp_*/heap_caps_*/nvs_*/partition/chip/secure-boot/
temp call is wrapped in a small src/platform/ facade (abstraction-first).
Firmware: 11 commands (NVS?/HEAP?/CLOCK?/CHIP?/RNG?/TEMP?/SECBOOT?/AUDIO?/PART?/
WDT?/FONT?) + platform facades (system heap/clock/partitions, security_fuses,
nvs stats, temperature [new, SOC-gated], watchdog, speaker codec name, text
renderer atlas stats). Both sticks3_debug (S3) + m5stack_gray_debug (classic
ESP32) -Werror clean; native 1168/1168.
QA: console methods + tests/hardware/test_diagnostics.py (one monitor per command,
incl. a secure-boot-off safety assertion + running-partition check); diagnostics
marker. identify.confirm_mac now tolerates an unreadable MAC on a bridge board
(retry then proceed on the unique USB-bridge serial; abort only on a real
mismatch) — fixes Gray/CP210x --flash.
Validated: Stick S3 11 passed, Gray classic ESP32 11 passed.
Claude-Session: https://claude.ai/code/session_01Y7Cy1HetRp6TZAUAeekN8X