The keep-still jousting orb: firmware, build/flash, the live console, and how to port to a new board.
src/*.h +
src/main.cpp; the dashboard is a Bun + React app sharing the same src/ tree.
| Path | What |
|---|---|
src/main.cpp | Game loop: 500 Hz sample/detect, state machine, serial protocol |
src/board_config.h | The only file you edit to port. Pins, LED geometry, IMU bus per board |
src/game_config.h | Tunable defaults: threshold, jerk gate, grace, free-fall, escalation |
src/detector.h | Keep-still detector: gravity EMA, hit peak, jerk, free-fall |
src/imu.h | Accel read (MPU6886 / BMI270) |
src/display.h · patterns.h | LED glyphs (+, X, meter bar) and colors |
src/button.h | Single-button gesture grammar (tap / hold / admin) |
src/swarm.h | ESP-NOW swarm (deferred; compiled behind a flag) |
platformio.ini | Build envs and flags |
src/App.tsx · index.ts · index.html | Web-Serial console (React); index.ts is the Bun server |
build.ts · deploy.ts | Static bundle + Vercel deploy scripts |
-e. Default is atom_matrix.
| Env | Flag | What it adds |
|---|---|---|
atom_matrix | -D BOARD_ATOM_MATRIX | Default. Standalone single controller, no radio |
atom_matrix_swarm | -D SWARM_ENABLED | ESP-NOW swarm layer (deferred) |
atom_matrix_selftest | -D SELFTEST_ON_BOOT | Runs still / moving / knock / drop assertions on boot |
pio run -e atom_matrixpio run -e atom_matrix -t uploadpio device monitor -e atom_matrix (115200)pio run -e atom_matrix_selftest -t uploadSet upload_port / monitor_port in platformio.ini to your USB serial device.
S2.0.
| Cmd | Effect |
|---|---|
| f | Inject a synthetic strike (exercises the real detector) |
| a | Arm now (skip grace) |
| r | Reset round |
| k | Acknowledge elimination |
| o | Mark this unit out |
| t | Run the self-test (still / moving / knock / drop) |
| S<g> | Movement threshold in g (e.g. S2.0) |
| J<g/s> | Jerk gate (J0 = off, any movement counts) |
| E<0|1> | Escalation off / on |
Telemetry streams back as T <ms> st=… meter=… hp=… thr=… lines the console graphs live.
| Command | What |
|---|---|
bun install | Install deps |
bun dev | Hot-reload dev server at localhost:3000 |
bun run build | Static bundle (build.ts) |
bun run deploy | Ship to Vercel → joust.nyc |
hitPk ≥ thr, default ~2g. Any real
acceleration counts: a jostle, flinch, walk, or drop.J0, any movement fires. Raise it to require a sharp
jolt and ignore slow shoves.|a| below 0.40g sustained for 60 ms always
registers a drop, even before impact.E1, the threshold ramps from start down to a minimum over
the round so it can't stall; everyone gets touchier as it drags on.board_config.h is the only file you edit to port. Everything else keys off its
BRD_* macros.
[env:…] in platformio.ini with a new -D BOARD_* flag.#elif defined(BOARD_*) block in board_config.h defining the same
macro set: BRD_LED_PIN, LED width/height/count/order, BRD_BTN_PIN, IMU bus
(SDA/SCL/ADDR), buzzer, and the BRD_AX_S* axis-sign remap
if the sensor is mounted rotated.imu.h to read it. BMI270 shares the ATOM's
0x68 I2C address, so mainly the register init differs.For the AtomS3R: point the LED macros at the Grove pin and the 29-LED strip geometry, and select
the BMI270 read path in imu.h. No game-logic changes.
bun run build emits the static bundle; bun run deploy pushes it. The live console is at
joust.nyc/console. Docs redeploy continuously, so they stay in sync with
the firmware.
One firmware, one board file to port. Source and the live console ship alongside this page.