Files
mcp_screen/circuitpython

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

Antigravitys 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:

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:

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.