updated doc for epd
This commit is contained in:
@@ -1,62 +1,71 @@
|
||||
# EPD Reference Driver — GDEY075T7 (UC8179)
|
||||
# EPD Implementation Reference — GDEY075T7 (UC8179)
|
||||
|
||||
## Source
|
||||
|
||||
**Repository:** [ekosboard/firmware](https://github.com/ekosboard/firmware)
|
||||
**File:** [`src/components/EPD/driver/epd_GDEY075T7.c`](https://github.com/ekosboard/firmware/blob/main/src/components/EPD/driver/epd_GDEY075T7.c)
|
||||
This document describes the current working state of the UC8179 E-Paper driver as implemented in `components/EPD/epd.cpp`.
|
||||
|
||||
## Panel Info
|
||||
|
||||
- **Controller:** UC8179
|
||||
- **Panel:** GDEY075T7 (Good Display 7.5" B/W, 800×480)
|
||||
- **Platform:** ESP-IDF (native SPI)
|
||||
- **Grayscale:** 4-level support present but marked as "NOT TESTED"
|
||||
- **Controller:** UC8179 (Good Display)
|
||||
- **Panel:** GDEY075T7 (7.5" B/W, 800×480)
|
||||
- **Platform:** ESP-IDF (Native SPI2 Host)
|
||||
- **Status:** **Fully Operational** (B/W and 4-Level Grayscale)
|
||||
|
||||
## Hardware Interface
|
||||
|
||||
### BUSY Pin Polarity
|
||||
- **Logic:** LOW = Busy, HIGH = Idle
|
||||
- **Wait loop:** `while (gpio_get_level(BUSY) == 0) { vTaskDelay(5); }`
|
||||
|
||||
### SPI Configuration
|
||||
- **Host:** `SPI2_HOST`
|
||||
- **Clock:** `SPI_FREQUENCY` (2MHz typically for EPD)
|
||||
- **Mode:** SPI Mode 0
|
||||
- **Transfer Size:** Chunked into 4096-byte buffers to avoid DMA limits and task watchdogs.
|
||||
|
||||
## Key Implementation Details
|
||||
|
||||
### BUSY Pin Polarity
|
||||
- **Reference driver:** HIGH = Busy, LOW = Idle
|
||||
- **⚠️ Our board is INVERTED:** LOW = Busy, HIGH = Idle
|
||||
- Wait loop polls `gpio_get_level(BUSY) == 0` to detect idle (reference)
|
||||
- Our code uses `== 0` to wait while busy (opposite meaning, same code pattern)
|
||||
### Data Polarity & VCOM (0x50)
|
||||
We use `0x29` for VCOM and Data Interval:
|
||||
- **VBD:** `00` (Floating/Black border?)
|
||||
- **N2OCP:** `1` (Auto-copy NEW data to OLD data after refresh)
|
||||
- **DDX:** `01` (Data Polarity: 0=Black, 1=White)
|
||||
- **Note:** In our 4-gray unpacking, we send `~output_byte`, effectively inverting the logic to match the panel's expectation for the LUTs used by the UC8179.
|
||||
|
||||
### Clear Screen (White)
|
||||
- Writes `0xFF` to **both** old (0x10) and new (0x13) data layers
|
||||
- `0xFF` = White, `0x00` = Black
|
||||
### Refresh Management
|
||||
The driver tracks refresh history to prevent ghosting or panel damage:
|
||||
- **Full Refresh:** Required every 5 fast refreshes or after 24 hours.
|
||||
- **Fast Refresh (B/W):** Optimized waveforms via `0xE5` -> `0x5A`.
|
||||
- **4-Gray Refresh:** Optimized waveforms via `0xE5` -> `0x5F`.
|
||||
|
||||
### Display Image
|
||||
- Writes `0x00` to old data layer (0x10) — assumes previous state was black
|
||||
- Writes actual image data to new data layer (0x13)
|
||||
## Grayscale Mapping (4-Level)
|
||||
|
||||
The input is a packed 2bpp bitmap (4 pixels per byte). We unpack this into two sequential data layers: **Old (0x10)** and **New (0x13)**.
|
||||
|
||||
| Gray Level | Input Bits (2bpp) | Old Layer (0x10) | New Layer (0x13) | Final Value (Inverted) |
|
||||
| :--- | :--- | :--- | :--- | :--- |
|
||||
| **White** | `11` | 1 | 1 | `00` (Low) |
|
||||
| **Gray 1** | `10` | 0 | 1 | `10` |
|
||||
| **Gray 2** | `01` | 1 | 0 | `01` |
|
||||
| **Black** | `00` | 0 | 0 | `11` (High) |
|
||||
|
||||
*Note: The hardware logic for 4-gray on UC8179 drives the pixels based on the difference between the Old and New layers over multiple sub-frames.*
|
||||
|
||||
## Driver State Machine
|
||||
|
||||
### Initialization (Full)
|
||||
1. **Hardware Reset:** RST Low (10ms), RST High (10ms).
|
||||
2. **Power Setting (0x01):** `0x07, 0x07, 0x3f, 0x3f`.
|
||||
3. **Booster Soft Start (0x06):** `0x17, 0x17, 0x28, 0x17`.
|
||||
4. **Power On (0x04):** Wait 100ms + Busy Idle.
|
||||
5. **Panel Setting (0x00):** `0x1F` (800x480, KW Mode).
|
||||
6. **Resolution (0x61):** `800×480`.
|
||||
7. **VCOM (0x50):** `0x29, 0x07`.
|
||||
|
||||
### Fast Mode Adjustments
|
||||
- **Booster (0x06):** `0x27, 0x27, 0x18, 0x17` (Stronger drive for fast transitions).
|
||||
- **Fast Mode Enable (0xE0):** `0x02`.
|
||||
- **Timing (0xE5):** `0x5A` (B/W) or `0x5F` (4-Gray).
|
||||
|
||||
### Sleep Sequence
|
||||
1. `0x50` with `0xF7` — VCOM and data interval setting before sleep
|
||||
2. `0x02` — Power Off
|
||||
3. Wait for BUSY idle
|
||||
4. `0x07` + `0xA5` — Deep Sleep
|
||||
|
||||
### Init Sequence (Full Refresh)
|
||||
1. Hardware reset (RST low 10ms, high 10ms)
|
||||
2. `0x01` — Power Setting: VGH=20V, VGL=-20V, VDH=15V, VDL=-15V, VDHR=4.2V
|
||||
3. `0x06` — Booster Soft Start: 0x17, 0x17, 0x28, 0x17
|
||||
4. `0x04` — Power On + 100ms delay + wait busy
|
||||
5. `0x00` — Panel Setting: `0x1F` (KW B/W mode)
|
||||
6. `0x61` — Resolution: 800×480
|
||||
7. `0x15` — DUSPI disabled
|
||||
8. `0x50` — VCOM: 0x10, 0x07
|
||||
9. `0x60` — TCON: 0x22
|
||||
10. `0xE3` — PWS: 0x22
|
||||
|
||||
### Fast Refresh
|
||||
- `0xE0` → `0x02` (enable fast mode)
|
||||
- `0xE5` → `0x5A` (fast refresh timing)
|
||||
|
||||
### Partial Update
|
||||
- Uses `0x91` (partial in) / `0x92` (partial out) + `0x90` (resolution setting)
|
||||
- Writes `~data` (inverted) to old layer to force transitions
|
||||
- Sets `0x50` → `0x21` (N2OCP disabled) for partial mode
|
||||
|
||||
### 4-Level Grayscale
|
||||
- Requires different booster settings: `0x27, 0x27, 0x18, 0x17`
|
||||
- `0xE5` → `0x5F` for grayscale timing
|
||||
- Data encoding: 2 bits per pixel (0xC0=white, 0x00=black, 0x80=gray1, 0x40=gray2)
|
||||
- Old layer and new layer encode different bit planes, both inverted (`~temp3`)
|
||||
1. **VCOM pre-sleep (0x50):** `0xF7`.
|
||||
2. **Power Off (0x02):** Wait for Busy Idle.
|
||||
3. **Deep Sleep (0x07):** `0xA5` (Check code).
|
||||
|
||||
Reference in New Issue
Block a user