Public Access
Fix VCLK at half rate; chunk the DMA stream; cycle test images
PCNT measurement showed I2S0 BCK (VCLK) rising once per two bytes in 8-bit LCD mode, so the panel saw every other byte. Each VCLK is now two identical bytes at a 10 MHz byte rate (VCLK 5 MHz). The doubled ~142 KB stream is allocated as 38 per-descriptor chunks. The test sketch now cycles through 12 labelled test images. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
e5b8dd9c50
commit
df78b5e72c
6 files changed
+235
-91
No files matched your search
+31
-22
@@ -5,8 +5,9 @@
|
||||
|
||||
## Approach
|
||||
|
||||
I2S0 in 8-bit parallel (LCD) mode with a circular DMA descriptor chain. Each DMA byte
|
||||
is one VCLK period:
|
||||
I2S0 in 8-bit parallel (LCD) mode with a circular DMA descriptor chain. BCK rises once
|
||||
per two DMA bytes (measured with PCNT: 2.5 MHz BCK at a 5 MHz byte rate), so each VCLK
|
||||
period is two identical bytes:
|
||||
|
||||
| Bit | Signal |
|
||||
|-----|--------|
|
||||
@@ -19,13 +20,15 @@ The I2S0 BCK output drives VCLK. ENABLE (GPIO 25) and _LOWPWR (GPIO 26) are plai
|
||||
|
||||
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.
|
||||
- Clock: PLL_D2_CLK 160 MHz / `clkm_div_num` 16, `tx_bck_div_num` 1 -> 10 MHz byte
|
||||
rate, 5 MHz BCK (two bytes 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`.
|
||||
so `encodeRow()` stores stream byte i at `i ^ 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.
|
||||
- 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.
|
||||
|
||||
## From the datasheet
|
||||
|
||||
@@ -53,26 +56,32 @@ other doc, comment or the plan.
|
||||
|
||||
Done:
|
||||
|
||||
- [x] Implement `EL512Panel::startI2S()` (I2S0 LCD mode, 5 MHz from PLL_D2 / 32,
|
||||
GPIO matrix routing, circular `lldesc_t` chain).
|
||||
- [x] Handle the 8-bit LCD-mode byte-pair swap in `encodeRow()` (clock c at `c ^ 2`).
|
||||
- [x] Implement `EL512Panel::startI2S()` (I2S0 LCD mode, GPIO matrix routing,
|
||||
circular `lldesc_t` chain).
|
||||
- [x] Handle the 8-bit LCD-mode byte-pair swap in `encodeRow()` (byte i at `i ^ 2`).
|
||||
- [x] Map x = 0 (datasheet column 1, odd) to TVID, not VID.
|
||||
- [x] VCLK rate: PCNT showed BCK at half the byte rate (panel saw every other byte,
|
||||
image squeezed and repeated). Fixed with two bytes per VCLK at a 10 MHz byte
|
||||
rate; PCNT now reads VCLK 5.0 MHz, VS 70 Hz.
|
||||
- [x] I2S0 data signal base `I2S0O_DATA_OUT16_IDX`: GPIO 19/21/22/23 all toggle.
|
||||
- [x] Panel shows a correct image in two-bit mode.
|
||||
|
||||
Hardware checks (need the panel and a scope or logic analyser):
|
||||
Hardware checks:
|
||||
|
||||
- [ ] Self test first (Table 3): remove PS1 jumper 1, power up; all pixels except the
|
||||
first half of the top row should light. Refit jumper 1, remove jumper 2.
|
||||
- [ ] Scope: VCLK 5 MHz on GPIO 18; HS 256 clocks high / 16 low (54.4 µs, T6-T8);
|
||||
VS one line high per 14.2 ms frame (70.4 Hz); data changing on the falling VCLK
|
||||
edge with >= 8 ns setup/hold (Table 6); T1 220.8 µs, T4/T5 as in `encodeRow()`.
|
||||
If data changes on the rising edge, set `INVERT_VCLK`.
|
||||
- [ ] Confirm the I2S0 data signal base (`I2S0O_DATA_OUT16_IDX`): if GPIO 19/21/22/23
|
||||
stay idle, try `I2S0O_DATA_OUT8_IDX`.
|
||||
- [ ] Self test (Table 3): remove PS1 jumper 1, power up; all pixels except the
|
||||
first half of the top row should light. Refit jumper 1.
|
||||
- [ ] HS reads ~18,030 Hz on PCNT where 5 MHz / 272 = 18,382 Hz is expected (~2% low)
|
||||
while VCLK reads 5.0 MHz. Frame rate is still ~70 Hz; cause unknown, check on a
|
||||
scope (HS 256 clocks high / 16 low, T6-T8).
|
||||
- [ ] Scope: data changing away from the rising VCLK edge with >= 8 ns setup/hold
|
||||
(Table 6); which BCK edge lines up with the byte-pair boundary is unverified. If
|
||||
pixels look shifted or noisy, set `INVERT_VCLK`.
|
||||
- [ ] Confirm 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).
|
||||
- [ ] Confirm the column parity: the checkerboard in `main.cpp` must look identical to
|
||||
the framebuffer, and the left border must sit on the panel's first column.
|
||||
- [ ] 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
|
||||
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).
|
||||
@@ -83,5 +92,5 @@ Software:
|
||||
a second buffer and swap descriptors at the per-frame EOF, or encode only during
|
||||
vertical blanking.
|
||||
- [ ] Unit test for `encodeRow()` (see `test/README`).
|
||||
- [ ] The 71 KB stream is one contiguous DMA allocation; with Wi-Fi on it may not fit.
|
||||
Fallback: per-line buffers or a line ring refilled from the EOF interrupt.
|
||||
- [ ] 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.
|
||||
Reference in new issue
Block a user