arch one firmware, two targets
the same code that ships on the device
posse is a MeshCore application written in C++ against a small hardware abstraction layer:
screen, keyboard, gps, compass, radio,
board. On hardware those are an ST7789, an STC8H-branded keypad coprocessor, a GNSS
receiver, a QMC6309 magnetometer and a Semtech LR1110. In the browser they are eight imported
functions.
C++ UI and mesh logic, drawn into a 240×320 RGB565 canvas with Adafruit GFX.
Compiled to a freestanding WebAssembly module exporting fw_init, fw_loop, fw_key, fw_radio_rx.
TypeScript instantiates one module per device and owns time, position, GPS and the air between them.
Nothing about the UI is reimplemented for the web. When you press right on an emulated device,
the same handleKey that runs on the M9 switches the tab, and the pixels you see are the
bytes the real display controller would have received.
engine the world
virtual time, and the air
The engine steps a single virtual clock. Every 20 ms each device's fw_loop runs; every
second it is handed a GPS fix; whenever a device transmits, the frame is put in flight with an
airtime computed from the LoRa symbol formula — the same one the firmware uses to decide when the
channel is clear.
When a frame lands, every other device is tested against it. Received power is log-distance path loss with a per-pair shadowing term, compared against a thermal noise floor for the bandwidth plus the demodulation threshold for the spreading factor. Frames overlapping in time collide unless one arrives capture-dB stronger and first. Half-duplex is respected: a device that is transmitting hears nothing.
target the real device
what the emulator cannot tell you
The emulator models the protocol and the link budget, not the physics of a specific afternoon. It does not know about a body standing between two antennas, a metal art car, 40 °C in a pocket, or the way a GNSS fix behaves under a shade structure. It also assumes every device hears the same channel; real radios differ.
What it is good for is everything upstream of that: does the UI make sense at arm's length, how often should a device beacon, how many hops does a crew need, and what happens to a field of twenty radios all beaconing at SF10.
Hardware notes for the ThinkNode M9 — pin map, the USB pad trap that clamps the keyboard bus, the keypad coprocessor's register map and key codes — live with the firmware, assembled from four independent ports because Elecrow publishes no schematic.
try it