"""CircuitPython entrypoint for Waveshare ESP32-S3-RLCD-4.2 migration. Copy this file to CIRCUITPY/code.py after flashing CircuitPython. """ import gc import os import time import board import busio import digitalio from audio_cp import BoardAudio from gif_player import GIFPlayer from rlcd_cp import RLCD # Keep pin choices in one place because CircuitPython board builds differ in # how they expose ESP32-S3 pins. If board.IO## is missing, run `dir(board)` on # the serial console and update these names. PINS = { "display_sck": board.IO11, "display_mosi": board.IO12, "display_cs": board.IO40, "display_dc": board.IO5, "display_rst": board.IO41, "i2c_sda": board.IO13, "i2c_scl": board.IO14, "i2s_bclk": board.IO9, "i2s_lrck": board.IO45, "i2s_dout": board.IO8, "audio_mclk": board.IO16, "audio_amp": board.IO46, } def exists(path): try: os.stat(path) return True except OSError: return False def init_display(): spi = busio.SPI(clock=PINS["display_sck"], MOSI=PINS["display_mosi"]) # Match the working MicroPython code's 20 MHz SPI if the build supports it. while not spi.try_lock(): pass try: spi.configure(baudrate=20000000, phase=0, polarity=0) finally: spi.unlock() display = RLCD( spi, cs=digitalio.DigitalInOut(PINS["display_cs"]), dc=digitalio.DigitalInOut(PINS["display_dc"]), rst=digitalio.DigitalInOut(PINS["display_rst"]), ) return display def init_audio(): i2c = busio.I2C(scl=PINS["i2c_scl"], sda=PINS["i2c_sda"]) return BoardAudio( i2c, bit_clock=PINS["i2s_bclk"], word_select=PINS["i2s_lrck"], data=PINS["i2s_dout"], mclk=PINS["audio_mclk"], amp=PINS["audio_amp"], ) def draw_boot_screen(display, message="CircuitPython RLCD"): display.clear(0) display.text("ESP32-S3-RLCD", 10, 10, 1) display.line(10, 22, 390, 22, 1) display.text_large("CIRCUITPY", 18, 45, scale=3, color=1) display.text(message, 18, 86, 1) display.text("MP3: /demo.mp3", 18, 116, 1) display.text("GIF: /demo.gif", 18, 132, 1) display.text("If visible, ST7305 init works", 18, 170, 1) display.show() def main(): display = init_display() draw_boot_screen(display, "Display initialized") time.sleep(1) # Try GIF first because it verifies display animation support. if exists("/demo.gif"): draw_boot_screen(display, "Playing GIF...") GIFPlayer(display).play("/demo.gif", loops=1) draw_boot_screen(display, "GIF done") gc.collect() # Try MP3 if present. If this fails silently, verify MCLK on IO16 and codec # register sequence against a known-good WAV/tone first. if exists("/demo.mp3"): draw_boot_screen(display, "Playing MP3...") try: audio = init_audio() ok = audio.play_mp3("/demo.mp3", volume=65) draw_boot_screen(display, "MP3 ok" if ok else "MP3 failed") except Exception as exc: draw_boot_screen(display, "MP3 error: " + str(exc)[:28]) while True: time.sleep(5) main()