Files
README.md

cyd_playground #

A simple dashboard generated by an LLM for a CYD. Rest of the read me is what the LLM wrote.

Bare-metal Rust (esp-hal + Embassy) for the ESP32-2432S028R "Cheap Yellow Display", 2-USB revision. Boots to a loading screen until WiFi joins over DHCP (or, with no network configured, to a WiFi picker with an on-screen keyboard), then shows a portrait tile dashboard: the clock (set from timeapi.io, with a WiFi status dot) and current weather from Open-Meteo (refreshed every 15 minutes): the temperature tile carries the day's high and low below the current reading. While music plays, the weather folds into one row and a now-playing tile shows the track (scrolling if long) with a progress bar; it comes from the teal.fm status record in ATPROTO_REPO, read through the Slingshot cache at SLINGSHOT_URL every 15 seconds. Three touch buttons along the bottom: Refresh (fetch weather and now playing, and re-sync the clock now), Light (backlight off; tap anywhere to turn it back on), and Info (IP, SSID, signal, heap, uptime, plus settings: accent, theme, WiFi picker, touch calibration, power off).

One-time setup #

cargo install espup esp-generate espflash --locked
espup install --targets esp32     # installs the Xtensa `esp` toolchain
cp .env.example .env              # then edit with your WiFi credentials

Keep the single quotes in .env; a password containing $, a backtick, or \ is otherwise altered by the shell before it reaches the firmware. A single quote inside the password is written as '\''.

Build, flash, monitor #

source ~/export-esp.sh            # every new terminal
source .env
cargo run --release               # flashes over /dev/cu.usbserial-* and opens the monitor

Ctrl-C leaves the monitor. ESP_LOG in .cargo/esp-config.toml sets the log level. The CH340 USB bridge on this board is only reliable at the default 115200 baud, so a full flash takes about a minute.

If the screen looks wrong #

The background must be black, the clock orange, and text must read normally. If not, see the tuning table at the top of src/board.rs. A blank or noisy screen usually means the other panel controller: cargo run --release --features ili9341.

Touch calibration #

Info → Calibrate shows four crosses; tap each. The fitted values are saved to flash and used at once. Every tap is still logged as touch raw (x, y) -> (px, py) if you want to check them. The defaults live at the top of src/touch.rs.

Joining WiFi from the device #

With SSID empty at build time, or after Info → WiFi, the device scans and lists networks strongest first (* marks a secured one). Tap one, type the password on the keyboard, tap Done. The choice is saved to flash and wins over the env on later boots. On the loading screen a tap anywhere reopens the picker.

Pinout used #

Signal GPIO
Display SCLK / MOSI / MISO 14 / 13 / 12
Display CS / DC 15 / 2
Backlight 21
Touch CLK / MOSI / MISO / CS / IRQ 25 / 32 / 39 / 33 / 36

SD card, RGB LED (4/16/17) and the light sensor (34) are not used yet.

Layout #

  • src/board.rs pin map, display and touch bus bring-up
  • src/ui/mod.rs loading screen, tiles, button bar, off-screen canvas, theme
  • src/ui/keyboard.rs on-screen keyboard component
  • src/ui/wifi_list.rs network picker
  • src/ui/calibrate.rs touch calibration screen and fit
  • src/touch.rs XPT2046 sampling, runtime calibration
  • src/settings.rs flash-saved settings: colors, WiFi credentials, calibration
  • src/clock.rs time sync, counted on the crystal between fetches
  • src/weather.rs Open-Meteo current conditions and today's high / low
  • src/now_playing.rs teal.fm now-playing status record
  • src/wifi.rs command-driven station task: connect, scan, DHCP, status
  • src/bin/main.rs init, then the screen state machine: dashboard, info, picker, keyboard, calibration