•
3 min read
Screeny

Screeny is open-source firmware and software that turns a Tidbyt Gen 1 into a 30 fps display for generative art. Instead of rendering frames in the cloud, Screeny renders them on a computer on the local network and streams them straight to the panel. No cloud, no account, no subscription.

patches ──> art pipeline ──> encoder (best of 5 codecs, ≤ 1464 B) ──UDP/WiFi──> firmware ──> HUB75 panel

Firmware

  • no_std Rust on embassy and esp-hal, with the display on one ESP32 core and the network on the other.
  • Refreshes the 64×32 panel at 154 Hz with six bit planes, and dithers temporally to about a thousand levels per channel.
  • Caps brightness so a laptop USB port can power it.
  • Advertises itself over DNS-SD, sets up WiFi from the browser or a phone QR code, and takes over-the-air updates that roll back on their own if they fail.

Protocol

  • One frame, one UDP datagram: an 8-byte header and at most 1,464 bytes of pixels.
  • Nothing is retransmitted, every frame decodes on its own, and the newest frame wins.
  • The sender tries five codecs on every frame — mostly adaptive palettes that shrink until the frame fits — scores each against a model of the panel, and sends the best. A clock frame is about 280 bytes.
  • screeny pipe takes raw RGB frames on stdin, so any program in any language can drive a panel.

Studio

  • A single Rust binary: an axum server with the web UI compiled in, and an MQTT bridge to Home Assistant.
  • Runs as a Home Assistant app, in Docker (amd64 or arm64), or from source. On a Raspberry Pi 4 it uses about half a core and 85 MB of memory.
  • Each patch renders on its own thread, and a patch that stalls is replaced without taking the process down.
  • Patches include clocks inspired by ClockClock 24 and the Vestaboard, a slow-motion flock, metaballs, raymarched solids, and a GPU-rendered procedural world.

The design docs cover the protocol, the architecture, and the research behind each decision. Read the story behind it in the blog post.