# CircuitPython migration prototype for Waveshare ESP32-S3-RLCD-4.2 This folder is an initial CircuitPython port attempt for the existing MicroPython ESP32-S3-RLCD project. ## Goal Move the board firmware toward CircuitPython so we can use built-in CircuitPython media modules: - `audiomp3` for MP3 playback over I2S - `gifio` for frame-by-frame GIF decoding The current MicroPython project already has working low-level knowledge for: - ST7305 reflective LCD init and 2x4 packed monochrome framebuffer - ES8311 speaker DAC over I2C + I2S - GPIO46 speaker amp enable - ESP32-S3 board pins ## Current status This is not a full replacement firmware yet. It is a bootable/iterable prototype layout: - `code.py` — demo entrypoint for CircuitPython - `lib/rlcd_cp.py` — custom ST7305/RLCD driver using `busio`/`digitalio` - `lib/audio_cp.py` — ES8311 + I2S MP3 playback helper - `lib/gif_player.py` — GIF-to-RLCD playback helper using `gifio` ## Why a custom display driver is needed Antigravity’s review confirmed the important constraint: ST7305/RLCD is not a normal `displayio` panel here. The existing `rlcd.py` packs pixels into 15,000 bytes where each byte represents a 2×4 pixel block, with vertical inversion. CircuitPython does not appear to have a native `displayio` ST7305 driver for this exact layout, so this port keeps a Python-side canvas and manually packs it before SPI transfer. ## Hardware pins copied from the working MicroPython firmware Display SPI: - SCK: IO11 - MOSI: IO12 - CS: IO40 - DC: IO5 - RST: IO41 Audio/I2C: - I2C SDA: IO13 - I2C SCL: IO14 - I2S BCLK: IO9 - I2S LRCK/WS: IO45 - I2S DOUT: IO8 - MCLK PWM: IO16 - Speaker amp enable: IO46 ## Copy to CIRCUITPY After flashing a compatible CircuitPython build for the ESP32-S3 N16R8-style board: ```bash cp circuitpython/code.py /media/$USER/CIRCUITPY/code.py mkdir -p /media/$USER/CIRCUITPY/lib cp circuitpython/lib/*.py /media/$USER/CIRCUITPY/lib/ ``` Optional test assets: ```bash cp demo.mp3 /media/$USER/CIRCUITPY/demo.mp3 cp demo.gif /media/$USER/CIRCUITPY/demo.gif ``` ## Expected next hardware tests 1. Boot with only `code.py` and libraries copied. 2. Confirm display init + dashboard text appears. 3. Copy a tiny 320px-wide-or-smaller monochrome/low-color GIF and test GIF playback. `gifio` cannot load 400px-wide GIFs on current CircuitPython builds; the prototype centers 320px GIFs on the 400px screen. 4. Copy a short MP3 and test I2S/ES8311 playback. 5. If display is scrambled, compare `pack()` output against MicroPython `rlcd.py` and host `notetaker.py` mapping. ## Known risks - CircuitPython may not expose every `board.IO##` name on the selected build. If so, update `PINS` in `code.py` with the names present in `dir(board)`. - `pwmio.PWMOut` at 12.288 MHz on IO16 may not work on all CircuitPython ESP32-S3 builds. If MCLK fails, MP3 playback may be silent even if I2S is writing. - Pure Python display packing loops may be slow. This prototype favors correctness first; optimize with lookup tables after the first visible frame works. - GIF playback on a 1-bit reflective LCD will be low-framerate and monochrome-thresholded. - CircuitPython SPI configuration is lock-scoped, so `rlcd_cp.py` configures 20 MHz SPI after every lock.