Files
planar-EL512.256-H/docs
mangavalkandClaude Opus 5.5 3640c7fb3f 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>
2026-10-05 21:08:36 +02:00
..

Notes

Approach

I2S0 in 8-bit parallel (LCD) mode with a circular DMA descriptor chain. Each DMA byte is one VCLK period:

Bit Signal
0 VID (even columns)
1 TVID (odd columns)
2 HS
3 VS

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

  • Two-bit parallel mode is selected with the mode jumper OFF. Even columns on VID, odd columns on TVID; 256 VCLKs per row.
  • VCLK is active on the rising edge and should be kept running.
  • HS is high while the pixels of a row are clocked in. The number of VCLKs during HS high should be even.
  • The topmost row is the first HS high time ending after the rising edge of VS.

Open items

  • 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 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().