xteink-web-emulator

An offline, in-browser emulator for the xteink X3/X4 (ESP32-C3 + e-ink): upload a firmware .bin, run the real machine code client-side, see the screen, press buttons, mount a virtual SD — no server, no proprietary engine.

Status: native and WebAssembly builds provide one xteink machine that selects X3 or X4 at launch. Unmodified canonical firmware auto-detects the selected variant: X3 boots with its UC8253 display and SD card; X4 reaches its SSD1677 driver through a blank protocol stub. A basic static browser UI now loads local firmware, renders the panel, and drives the physical buttons. See ROADMAP.md for architecture and plan.

Quick start (native QEMU)

git clone --recursive https://github.com/crosspoint-reader/crosspoint-reader ../crosspoint-reader
# Build ../crosspoint-reader's PlatformIO `default` environment first.
nix develop
make qemu             # clone espressif/qemu @ pinned commit, apply patch, build (JOBS=2)
make firmware sdimage # 16 MB flash.bin + FAT32 sd.img from the PlatformIO build
make run              # X3 (default)
make run VARIANT=x4   # X4 detection + blank SSD1677 stub

Point at a firmware build with make firmware FIRMWARE_DIR=/path/to/.pio/build/gh_release. make qemu is a long compile on modest hardware — set JOBS to taste.

WebAssembly build

Podman or Docker is required. The build is limited to riscv32-softmmu and the X3/X4 device graph; networking, audio, virtfs, tools, docs, and unrelated boards are disabled.

make qemu-wasm
# dist/wasm/qemu-system-riscv32.{js,wasm,worker.js} + esp32c3-rom.bin

The build runs Node smoke checks when Node is available.

Browser interface

make web
# Open http://127.0.0.1:8000/web/

Choose a CrossPoint firmware .bin — either the ~5 MB release app image (it is merged in-browser with the bundled bootloader and partition table into a 16 MB flash) or a full 16 MB image — select X3 or X4, and boot. The controls map to the device's ADC button ladders and active-low Power GPIO. make web serves the required COOP/COEP headers for Emscripten pthreads; a generic static server without those headers will not work.

Real firmware now boots in WASM: it runs past the earlier allocator and function-pointer signature crashes and initializes the X3 panel (528×792). It still stalls before painting a full home screen (the display generation counter freezes after early init), so end-to-end boot is not complete. X4 remains a white display stub, and browser SD storage is not implemented yet.

Contents

  • qemu/patches/0001-xteink-machine.patch — the xteink,variant=x3|x4 machine and its device models (I²C fingerprints, ADC, GPIO, SPI2, X3 UC8253, X4 panel stub, SD-over-SPI fix), applied onto the pinned espressif/qemu commit by scripts/build-qemu.sh.
  • qemu/patches/0002-qemu-wasm.patch and qemu/wasm/Dockerfile — the pinned qemu-wasm host backend port and minimal Emscripten dependency environment, built by scripts/build-qemu-wasm.sh.
  • flake.nix — the espressif-qemu release binary as the fast generic baseline (nix run .#run-upstream -- flash.bin), plus a devShell with QEMU's full build environment. Makefileqemu, firmware, sdimage, run, chip.
  • scripts/mksd.sh — build the FAT32 SD backing image (local-disk impl of the SD block interface).
  • chip/eink-x3.chip.c — the reverse-engineered X3 e-ink protocol, first written as a Wokwi chip and now the reference for the QEMU display device. make -C chip test runs its host self-check.

Why not Wokwi

Wokwi runs any bin in a browser and we had the e-ink chip working — but its simulation engine is proprietary and gated behind a license/service, so it can't be self-hosted or run airgapped. QEMU is the open path; the e-ink protocol work carried straight over.

S
Description
No description provided
Readme 781 KiB
Languages
JavaScript 43.2%
C 14%
Python 12.7%
CSS 7%
Shell 6.9%
Other 16.2%