Skip to content

Repository files navigation

glint

test

glint turns a supported ESP32 board with an LCD into a small extra display for a computer.

I built it because the usual 3.5" ESP32 panels are sharp enough for status work, but most "USB display" projects either depend on proprietary stacks or stop at a one-off demo. glint treats the panel as a real endpoint: firmware on the board, a macOS host that creates a virtual display, and a Linux host that can drive the same panel from a framebuffer.

Demo

Demo video: coming soon.

I will add a recorded walkthrough here showing the macOS virtual display path, the Linux framebuffer path, and the supported boards in use.

What It Does

  • macOS host: creates a real virtual display through private CoreGraphics API, then streams that display to the panel over USB or Wi-Fi.
  • Linux host: mirrors a framebuffer to the same panel with a pure-Go host that uses usbfs directly and needs no X server.
  • Firmware: receives tiled pixel updates over a USB vendor interface or TCP on Wi-Fi, paints them on the panel, and reports touch events back.

At this size and density it works best as a status panel: a docked terminal, a dashboard, a timer, a monitor widget. Text is good. Gradients and photographs are not the point.

Motivation

I wanted a small display that behaves like part of the machine rather than a screen driven by a custom app. On macOS that meant creating a real display and streaming it. On Linux that meant keeping the wire protocol host-agnostic so a Pi or desktop could drive the same panel without any virtual-display machinery.

What Works Today

Platform Status Notes
macOS supported Swift host, virtual display, USB and Wi-Fi, touch support
Linux supported pure-Go host, usbfs transport, framebuffer mirroring
Windows partial Go host drives the panel over Wi-Fi (measured 27.7 fps); USB needs a WinUSB backend

Supported Boards

I have tested glint on these boards:

Board Panel Link
ESP32-P4-WIFI6-Touch-LCD-3.5 ST7796 SPI, 320x480, FT6336 touch USB high speed, Wi-Fi
Waveshare ESP32-S3-Touch-AMOLED-1.75 CO5300 QSPI, 466x466, CST9217 touch USB full speed, Wi-Fi

Nothing in the host code is specific to those two boards. A board is one header in firmware/main/boards/ plus any panel- or touch-driver support it needs in firmware. The panel size and capabilities come from the handshake, so both hosts stay resolution-agnostic.

Hardware details, flashing notes, board bring-up, and touch mappings live in HARDWARE.md.

Quick Start

  1. Install ESP-IDF v5.5 at ~/esp/esp-idf-v5.5, or set IDF_PATH.
  2. Connect a supported board.
  3. Run:
make setup

make setup finds the board, suggests the matching profile, offers Wi-Fi configuration, builds, flashes, and starts a display session.

If you prefer to do it by hand:

make            # build firmware + macOS host
make flash      # flash the board
make display    # macOS extended desktop on the panel

Platform Guides

Measured Performance

Whole frames of colour bars, no dirty-rect tiling, frame cap lifted — so these are link ceilings rather than what a desktop actually costs.

ESP32-P4 (USB high speed) ESP32-S3 AMOLED (USB full speed)
USB 7.4-7.9 MB/s, 24-26 fps at 320x480 0.46 MB/s, about 1 fps at 466x466
Wi-Fi 0.95-1.9 MB/s, 3-6 fps not measured
Bound by, on USB the ST7796's SPI bus, about 8 MB/s the 1.2 MB/s full-speed USB ceiling
Bound by, on Wi-Fi the radio and its round-trip time

Two things worth knowing about those ranges. On USB neither board is limited by the host: profiling puts 94-100% of each frame in the USB write, with render and encode together under 3 ms. On Wi-Fi the figure halves run to run as the 2.4 GHz band gets busy, and the P4 has no radio of its own — its Wi-Fi is an ESP32-C6 reached over SDIO, which adds a hop.

A desktop is far cheaper than a full frame, because most of it does not change between frames:

Full frame, uncompressed 300 KB
Dirty-tile push, typical desktop 18 KB, 2.4 tiles per frame
Idle desktop most frames send nothing
Flat 64x64 tile, RLE 8192 bytes to 4

Per-platform figures, including a Raspberry Pi driving the same panel, are in the macOS and Linux guides.

Current Limits

  • macOS cannot create a virtual display at the panel's native size, so the default desktop is downscaled 2:1. See NOTES.md.
  • CGVirtualDisplay is private API and can break on a macOS update.
  • HiDPI is ignored for virtual displays.
  • The P4 board's backlight is a plain GPIO, so CMD_BACKLIGHT is effectively on/off there.
  • The Linux USB path is usbfs-based and Linux-only.
  • Screen Recording permission is required on macOS, and the recording indicator stays on for as long as a session runs.
  • On Windows the firmware binds WinUSB, but the Go host has no USB backend for it yet, so Windows drives the panel over Wi-Fi.

Verification

make test runs:

  • Swift unit tests for the shared host logic
  • host-compiled C tests for the firmware RLE decoder
  • go test ./... across the Linux host packages

The Swift, Go, and firmware-side RLE implementations are pinned to the same fixture so they agree byte-for-byte.

Technical Docs

Repository Layout

protocol/protocol.h         wire format source of truth
firmware/                   ESP-IDF firmware
  components/               third-party code, under its own licence
host/Sources/GlintCore/     shared host logic: protocol, tiling, RLE
host/Sources/glint/         macOS host CLI and virtual-display path
linux/                      Linux host and transport code
packaging/                  LaunchAgent and udev rule
tools/                      setup helpers

Install

Releases carry prebuilt hosts and firmware, so trying glint needs no toolchain:

  • glint.exe, glint-pi-arm64, glint-pi-armv6, glint-linux-amd64 — single binaries with no installer and no kernel driver. They drive a panel over Wi-Fi, and over USB on Linux, where the USB path needs the one udev rule in packaging/ so a normal user can open the device.
  • glint-firmware-p4.zip, glint-firmware-amoled.zip — the images plus the exact esptool command. Wi-Fi is off in released firmware; enable it from a source checkout.

The macOS host builds from source, because it links Homebrew's libusb:

brew tap shubham030/glint
brew install glint

Building the firmware, or changing board configuration, still wants a clone and ESP-IDF — see the macOS guide.

License

MIT — see LICENSE. Third-party code keeps its own terms, listed in THIRD-PARTY.md.

About

Turn an ESP32 board with an LCD into a real second display for macOS, Linux or Windows — no driver, no kext, over USB or Wi-Fi.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages