Implement I2S0 8-bit LCD-mode DMA refresh

startI2S() sets up I2S0 in 8-bit parallel (LCD) mode at 5 MHz
(PLL_D2 160 MHz / 32, BCK div 1), routes stream bits 0..3 to
VID/TVID/HS/VS via I2S0O_DATA_OUT16+n and BCK to VCLK, and loops
DMA over an 18-descriptor chain of whole lines. stopI2S() stops TX,
returns the pins to GPIO low and frees the chain.

encodeRow() now stores clock c at c ^ 2 to match the 8-bit mode
byte order (bytes 2, 3, 0, 1 per word, as in bitluni's ESP32Lib).

Builds with no warnings; not yet checked on hardware.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
mangavalkandClaude Opus 5.5 committed 2026-10-05 21:08:36 +02:00
1 parent 873bdcd23e
commit 3640c7fb3f
5 files changed
+173 -29

No files matched your search

+19 -4
View File
@@ -15,7 +15,17 @@ is one VCLK period:
| 2 | HS |
| 3 | VS |
The I2S clock output drives VCLK. ENABLE (GPIO 25) and _LOWPWR (GPIO 26) are plain GPIO.
The I2S0 BCK output drives VCLK. ENABLE (GPIO 25) and _LOWPWR (GPIO 26) are plain GPIO.
I2S0 setup (`EL512Panel::startI2S()`), following bitluni's ESP32Lib 8-bit mode:
- Clock: PLL_D2_CLK 160 MHz / `clkm_div_num` 32, `tx_bck_div_num` 1 -> 5 MHz, one byte
per BCK period.
- `lcd_en`, `lcd_tx_wrx2_en`, `tx_bits_mod` 8, `tx_fifo_mod` 1, `tx_chan_mod` 1,
`tx_right_first`. With this setup each 32-bit DMA word goes out as bytes 2, 3, 0, 1,
so `encodeRow()` stores clock c at `c ^ 2`.
- Stream bits 0..3 -> `I2S0O_DATA_OUT16_IDX` + n; BCK -> VCLK (`INVERT_VCLK` flips it).
- 18 descriptors of up to 15 lines (4080 bytes) each, looped; `eof` set once per frame.
## From the datasheet
@@ -28,9 +38,14 @@ The I2S clock output drives VCLK. ENABLE (GPIO 25) and _LOWPWR (GPIO 26) are pla
## Open items
- [ ] Implement `EL512Panel::startI2S()` (I2S0 LCD mode, clock dividers for 5 MHz,
- [x] Implement `EL512Panel::startI2S()` (I2S0 LCD mode, clock dividers for 5 MHz,
GPIO matrix routing, circular `lldesc_t` chain).
- [ ] Handle the 8-bit LCD-mode byte-pair swap in `encodeRow()`.
- [ ] Check VS/HS setup and hold (T4/T5) and VCLK polarity on a scope.
- [x] Handle the 8-bit LCD-mode byte-pair swap in `encodeRow()`.
- [ ] Check on a scope: VCLK is 5 MHz on GPIO 18, HS is 256 clocks high / 16 low
(54.4 us period), VS is one line high per 14.2 ms frame, data changes on the
falling VCLK edge, VS/HS setup and hold (T4/T5). Unconfirmed until then: the
DATA_OUT16 base and the `^ 2` byte order. HS edges sit on word boundaries, so a
wrong order 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).
- [ ] Tear-free updates (double buffer or swap at VS).
- [ ] Unit test for `encodeRow()`.