Pure-Rust, no_std, Embassy-async firmware for the LilyGo T-Encoder-Pro
(ESP32-S3-R8). A clean HAL + driver foundation that brings up every peripheral
with an embedded-graphics demo UI.
- MCU: ESP32-S3-R8 — 16 MB flash, 8 MB octal (OPI) PSRAM, Wi-Fi + BLE.
- Display: CO5300 AMOLED, 390×390, RGB565, QSPI.
- Touch: CHSC5816 capacitive, I2C
0x2E. - Encoder: rotary quadrature (A/B) + push button.
- Buzzer: piezo on LEDC PWM.
- CO5300 QSPI driver with a
DrawTargetframebuffer in PSRAM and dirty-band partial flushing. - Rotary encoder via the PCNT peripheral; button input.
- CHSC5816 touch driver (async, polled point register).
- Buzzer feedback (LEDC).
- Demo UI: encoder moves the selection, button toggles the item, a tap toggles the touched row, the buzzer beeps on each action.
| Crate | Responsibility |
|---|---|
enc-config |
Board constants (pins, dimensions, addresses) |
enc-co5300 |
CO5300 display driver + embedded-graphics framebuffer |
enc-input |
Pure encoder detent logic (host-tested) |
enc-touch |
CHSC5816 async touch driver |
enc-ui |
Pure menu widget + renderer (host-tested) |
enc-app |
Device binary (xtensa-only): boot, tasks, UI loop |
Library crates are no_std and unit-test on the host; enc-app builds only for
xtensa-esp32s3-none-elf.
All cargo commands go through the ./cargo-esp wrapper (loads the ESP Xtensa
toolchain). The device is on /dev/ttyACM0.
# Host-side checks (pure crates)
./cargo-esp clippy --all-targets
./cargo-esp test
cargo-deny check # licenses / bans / advisories / sources
# Build / flash the firmware (run from the enc-app directory)
cd enc-app
../cargo-esp build --release
espflash flash --chip esp32s3 ../target/xtensa-esp32s3-none-elf/release/enc-appPrerequisites: the esp toolchain via espup
(source ~/export-esp.sh), plus espflash (or probe-rs).
Foundation complete and verified on hardware: display, encoder, button, touch,
buzzer, and the integrated demo UI. Clippy-clean (pedantic), host tests pass,
and cargo-deny check is clean. Wi-Fi/BLE is available on the chip but not yet
wired up (it would require a heap via esp-radio/esp-alloc).
MIT