Files
waveshare-panel/CLAUDE.md
T
growlph a125f45b34 Touchscreen driver POC
Example documentation
2026-05-07 16:28:08 -07:00

80 lines
3.4 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 wiring complete, driver integration in progress
## 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)
- Always does full refresh — partial update removed from 2bpp class
- 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, swap_xy) to be confirmed after first flash
## 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/