Fix PlatformIO build; document ESPHome component and ring-buffer driver

- el512_panel.cpp: esp_cpu_get_cycle_count() exists only in ESP-IDF 5;
  use cpu_hal_get_cycle_count() on 4.4 (Arduino 2.x), which broke both
  PlatformIO environments.
- README: ring-buffer refresh, tear-free status, D1 mini ESP32, new layout
  (components/el512, esphome/, home_assistant/), ESPHome setup, Still Alive
  paths, and the Wi-Fi blanking findings with wiring advice.
- docs/README: ring, lookup table, double buffer, health counters; tear-free
  and memory items done; Wi-Fi blanking and boot blanking as open items.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
mangavalkandClaude Opus 5.5 committed 2026-10-18 21:05:06 +02:00
1 parent f3212ea969
commit 6d5e5315f0
3 files changed
+128 -33

No files matched your search

+27 -10
View File
@@ -26,9 +26,20 @@ I2S0 setup (`EL512Panel::startI2S()`), following bitluni's ESP32Lib 8-bit mode:
`tx_right_first`. With this setup each 32-bit DMA word goes out as bytes 2, 3, 0, 1,
so `encodeRow()` stores stream byte i at `i ^ 2`.
- Stream bits 0..3 -> `I2S0O_DATA_OUT16_IDX` + n; BCK -> VCLK (`INVERT_VCLK` flips it).
- Stream: 261 lines × 544 bytes ≈ 142 KB, too big for one DMA block, so it is
allocated as 38 chunks of up to 7 lines (3808 bytes), one descriptor each, looped;
`eof` set once per frame.
- Ring: 8 descriptors of 4 lines (2176 bytes each, 17 KB total), looped, `eof` on
every descriptor. The EOF interrupt (IRAM, so it keeps running during flash writes)
re-encodes the descriptor that just finished with the lines 32 later, so the ring
stays ~1.7 ms ahead of the panel. Each descriptor tracks its own first line, so a
missed interrupt costs one stale chunk instead of shifting the picture.
- Encoding: a 256-entry table turns one framebuffer byte (8 pixels) into its 8 stream
bytes, already in `^ 2` order; a line takes about a microsecond.
- Double buffer: drawing goes into `_fb`; `show()` asks the interrupt to copy it to
the displayed buffer just before it encodes line 0, and waits for that (≤ 1 frame).
- The driver uses ESP-IDF calls only and lives in `components/el512/`; PlatformIO
builds it from there as library `EL512Core` (`lib_extra_dirs`), ESPHome as the
`el512` external component.
- Health counters (`takeStats()`): refills, largest refill gap, swaps, swap timeouts,
TX FIFO underruns. With Wi-Fi on: ~4600 refills/s, max gap < 0.4 ms, no underruns.
## From the datasheet
@@ -84,17 +95,23 @@ Hardware checks:
does not show on HS; on the panel it shuffles pixels in groups of 8 (a 1-pixel
line at x = 0 lands at x = 4).
- [ ] Confirm the column parity: the "checkerboard" and "VID/TVID columns" test images
in `main.cpp` must look as drawn, and the left border must sit on the panel's
in `src/test_images/main.cpp` must look as drawn, and the left border must sit on the panel's
first column.
- [ ] Add the 5 V buffer (74HCT245/74AHCT541) and a pull-down on ENABLE so the panel
stays off while the ESP32 boots without VCLK (Table 1: ENABLE pulled high
internally; Table 5 note 3: VCLK should be kept running).
internally; Table 5 note 3: VCLK should be kept running). The panel blanks a few
times during boot until then.
- [ ] Wi-Fi blanking: with Wi-Fi on (RSSI -90 dB, so full transmit power) the panel
blanks for a moment now and then, mostly at page changes (each reports the new
page to Home Assistant). Gone with `wifi: enable_on_boot: false`; ENABLE/_LOWPWR
were not connected; the health counters stayed clean during 3 blinks in 2 min.
So the signal is disturbed on the wires, not late from the ESP32. Next: all six
J1 GND pins along the signal wires, antenna away from the cable, the 5 V buffer;
`output_power: 14dB` as a quick check.
Software:
- [ ] Tear-free updates: `show()` rewrites the stream while DMA reads it. Encode into
a second buffer and swap descriptors at the per-frame EOF, or encode only during
vertical blanking.
- [x] Tear-free updates: back buffer copied to the displayed buffer at line 0.
- [x] Memory: the full-frame stream (142 KB) is replaced by a 17 KB ring; ~190 KB
internal heap is left with Wi-Fi, the API and the ESPHome pages running.
- [ ] Unit test for `encodeRow()` (see `test/README`).
- [ ] The ~142 KB stream (in 38 chunks) leaves ~190 KB heap; with Wi-Fi on it may
not fit. Fallback: a line ring refilled from the EOF interrupt.