Files
waveshare-panel/CLAUDE.md
T

89 lines
4.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Waveshare 2.9" E-Paper LVGL Project
## Goal Summary
- Waveshare 2.9" Touch ePaper HAT driving LVGL UI via ESPHome on ESP32
- 2-bit grayscale display support implemented via custom ESPHome component
- Touchscreen integration in progress
## Hardware
- ESP32-WROOM-32 (nodemcu-32s board)
- Waveshare 2.9inch Touch ePaper HAT (296x128, SSD1680 display, GT1151 touchscreen)
### Pin Mapping
| Function | ESP Pin | HAT Pin |
|--- |--- |--- |
| Display SCLK | GPIO18 | Pin23/GPIO11/SPI0_SCLK |
| Display MOSI | GPIO23 | Pin19/GPIO10/SPI0_MOSI |
| Display CS | GPIO19 | Pin24/GPIO8/SPI0_CE0 |
| Display DC | GPIO17 | Pin22/GPIO25 |
| Display BUSY | GPIO4 | Pin24/GPIO24 |
| Display RST | GPIO5 | Pin11/GPIO17/SPI1_CE1 |
| Touch SDA | GPIO21 | Pin3/GPIO2/I2C1_SDA |
| Touch SCL | GPIO22 | Pin5/GPIO3/I2C1_SCL |
| Touch RST | GPIO15 | Pin13/GPIO27 |
| Touch INT | GPIO16 | Pin15/GPIO22 |
Note: GPIO15 (Touch RST) is an ESP32 strapping pin, but only affects boot log
output (LOW silences it). No impact on UART download mode or OTA flashing.
## Software
- ESPHome 2026.1.0
- Framework: esp-idf
- Project directory: ~/Projects/waveshare-panel
## Current Status
- 2-bit grayscale fully working via custom component `waveshare_epaper_2bit`
- LVGL rendering working, 4-shade colorspace confirmed
- Bayer ordered dithering implemented for gradient smoothing
- Touchscreen working: polling mode, mirror_x + mirror_y transforms confirmed correct
- LVGL touch input and button state working end-to-end
- **Active: LVGL layout work**
## Display Refresh Pattern
Two-tier refresh wired to `lvgl.on_draw_end` via two `mode: restart` scripts:
- **Partial** (`refresh_display`, 60ms): calls `display_partial()` — fast 1-bit, non-blocking, immediate interaction feedback
- **Full** (`full_refresh_display`, 10s): calls `component.update: display0``display()` — full 2-bit grayscale quality restore after idle
60ms was empirically tuned: 80ms felt sluggish, 40ms intermittently raced. `component.update: display0` only pushes the frame buffer to hardware and does not re-trigger `on_draw_end`.
## Grayscale Implementation
Custom component model name: `2.90inv2-r2-2bpp`
Key implementation details:
- Gray4 waveform LUT loaded via register 0x32 on every display() call
- Activation uses 0xC7 (custom LUT), not 0xF7 (which reloads OTP LUT)
- `display()` = full 2-bit grayscale refresh; `display_partial()` = fast 1-bit partial refresh
- Second bitplane buffer (`buffer2_`) allocated in `initialize()`
Confirmed bitplane table for this panel with Gray4 LUT:
| 0x24 | 0x26 | Result |
|------|------|------------|
| 0 | 0 | White |
| 1 | 0 | Light grey |
| 0 | 1 | Dark grey |
| 1 | 1 | Black |
Color convention: 0xFFFFFF=white, 0x000000=black (no inversion).
LVGL 4-shade palette: 0xFFFFFF, 0xAAAAAA, 0x555555, 0x000000
Dithering: 4×4 Bayer ordered dither, bias = bayer*2 - 15 (±15 range).
Amplitude chosen to keep 0xAAAAAA and 0x555555 as solid fills.
## Touchscreen
- Controller: ICNT86X (I2C address 0x48; 0x30 also ACKs, likely DFU/bootloader interface)
- Custom component: `custom_components/icnt86x/` (ESPHome has no native ICNT86X driver)
- Touch count at register 0x1001, touch data at 0x1002 (7 bytes/point), clear by writing 0x00 to 0x1001
- Waveshare's own driver inverts both axes: X = 295 - raw_x, Y = 127 - raw_y
- INT pulse is very brief (sub-ms); component works in polling mode regardless
- Coordinate transform: mirror_x + mirror_y confirmed correct; swap_xy not needed
## Relevant Files
- Custom component: `custom_components/waveshare_epaper_2bit/`
- `__init__.py` — CODEOWNERS only
- `display.py` — component schema and model registration
- `waveshare_epaper_2bit.cpp` — driver implementation
- `waveshare_epaper_2bit.h` — header
- Main config: `waveshare-test.yaml` (pin table here is source of truth)
- Build cache: `.esphome/build/waveshare-epaper-test/src/esphome/components/`
- ESPHome source (venv): ~/Code/esphome-2026.1.0/