Data & Protocol
Two layers: the raw formats the firmware transmits, and UF1, the interchange format the tools consume. Know both and you can parse the data directly or write an adapter for your own tool.
The adapter model
Section titled “The adapter model”Firmware → raw binary (BLE GATT / base serial) → Adapter → UF1 UDP → ToolsThe firmware does not send UF1. It emits raw binary — GATT notifications over BLE, or unframed serial from the base. A small adapter reads that and emits UF1 over UDP. Any software that reads a device’s raw format and outputs valid UF1 is a conforming adapter — that’s how third-party sensors join the ecosystem. Existing adapters: the Android app (BLE → UF1) and the gesture-lab host (base serial → UF1).
Raw format 1 — base station serial
Section titled “Raw format 1 — base station serial”The base forwards the direct radio over USB serial, unframed. 921 600 baud. Sync: [0] 0x4F [1] 0xD5 [2] rssi [3…] nRF24 payload (length = payload byte [1]).
The nRF24 payload — 62 bytes (v3_1), big-endian:
| Off | Field | Notes |
|---|---|---|
| 0 | packet_id | rolling 0–128 |
| 1 | packet_len | total length — use as boundary, don’t hardcode 62 |
| 2–5 | unit_id | u32 device ID |
| 6 | packet_type | EMG count = packet_type − 80 (valid range 80–120) |
| 8 | battery | raw → mV = 2000 + raw × 10 |
| 11 | adc_data_id | 8-bit sample counter, wraps at 256 |
| 12–27 | emg | 8 × int16 |
| 28–35 | fft | 4 bins (unsigned) |
| 36–43 | quat | w,x,y,z — ±32000 = ±1.0 |
| 44–49 | acc | ax,ay,az — 16384 LSB/g (±2 g) |
| 50–55 | euler or gyro | shipped fw: euler (dropped); gyro fw: gx,gy,gz ±500 dps |
| 56–61 | mag | mx,my,mz |
The base path is the only one carrying the FFT bins in every packet.
Raw format 2 — BLE GATT
Section titled “Raw format 2 — BLE GATT”Raw binary GATT notifications, little-endian, with a format byte at position 0 that selects the profile (auto-chosen by negotiated MTU):
| Byte | Profile | Min MTU | Contents |
|---|---|---|---|
| 0x01 | S1 (low-MTU fallback) | 20 | EMG + QUAT combined |
| 0x02 | S2 EMG | 53 | 24 raw EMG samples |
| 0x03 | S2 aux | 27 | IMU + MAG + QUAT |
No FFT over BLE (compute it receive-side). Cheap CSR8510- / HM-10-class dongles can’t reach MTU ≥ 53 → no full-stream S2.
UF1 — the interchange format
Section titled “UF1 — the interchange format”Little-endian, one frame per UDP datagram, port 26750. Frame = 24-byte header + TLV blocks (+ optional CRC32). Header: magic “UD”, version 2, device_id, seq (per device), t_us (µs receive-time). Blocks are type · len · value — skip unknown types by len:
| Type | Block | Contents |
|---|---|---|
| 0x01 | EMG_RAW | channel_count, samples/ch, int16 samples |
| 0x02 | EMG_FFT4 | 4 × int16 bins |
| 0x03 | IMU_6DOF | ax,ay,az,gx,gy,gz |
| 0x04 | MAG_3 | mx,my,mz |
| 0x05 | QUAT | w,x,y,z (±32000 = ±1.0) |
| 0x06 | STATUS | sample counter, rate, battery %, RSSI, mode |
| 0x07 | DEVICE_NAME | UTF-8 label |
Timing: t_us (wall-clock rx) aligns across devices; t_src_sample in STATUS (the device’s own sample counter) gives intra-device sample precision. Frames co-emitted from one raw packet share t_src_sample. This is what makes multi-device recordings time-alignable.
EMG ~1150 Hz (8 samples/frame → ~144 fps) · IMU & quaternion ~50 Hz · FFT 4 bins.
Full spec and reference adapters → uf1-tools.