82 lines
3.2 KiB
Markdown
82 lines
3.2 KiB
Markdown
# TRK1 Binary Telemetry — Version 1
|
||
|
||
The binary stream is the shared transport and storage representation for USB,
|
||
BLE, and any later nonvolatile buffer. All multibyte integers and IEEE-754
|
||
float32 values are little-endian. Frames are self-identifying and may be split or
|
||
combined by an underlying byte transport.
|
||
|
||
## Frame header (36 bytes)
|
||
|
||
| Offset | Size | Field |
|
||
| ---: | ---: | --- |
|
||
| 0 | 4 | ASCII magic `TRK1` |
|
||
| 4 | 1 | Wire version (`1`) |
|
||
| 5 | 1 | Packet type: metadata `1`, samples `2` |
|
||
| 6 | 1 | Header size (`36`) |
|
||
| 7 | 1 | Record size (`0` or `20`) |
|
||
| 8 | 1 | Record count (`0` or 1–8) |
|
||
| 9 | 1 | Packet flags |
|
||
| 10 | 2 | Payload size |
|
||
| 12 | 4 | Monotonic packet sequence |
|
||
| 16 | 8 | Base ESP timer timestamp in microseconds |
|
||
| 24 | 4 | Cumulative samples lost to read failure, queue overflow, or output failure |
|
||
| 28 | 4 | Cumulative acquisition-loop overruns |
|
||
| 32 | 4 | IEEE CRC-32 |
|
||
|
||
CRC uses polynomial `0xEDB88320`, initial value `0xFFFFFFFF`, and final XOR
|
||
`0xFFFFFFFF`. It covers header bytes 4–31 followed by the complete payload. The
|
||
magic and stored CRC field are excluded.
|
||
|
||
Packet flag bit 0 means at least one sample timestamp delta saturated.
|
||
|
||
## Sample record (20 bytes)
|
||
|
||
| Offset | Size | Field |
|
||
| ---: | ---: | --- |
|
||
| 0 | 4 | Sample sequence |
|
||
| 4 | 2 | Timestamp delta from the preceding record, in 10 us units |
|
||
| 6 | 2 | Enclosure accel X raw (`int16`) |
|
||
| 8 | 2 | Enclosure accel Y raw (`int16`) |
|
||
| 10 | 2 | Enclosure accel Z raw (`int16`) |
|
||
| 12 | 2 | Enclosure gyro X raw (`int16`) |
|
||
| 14 | 2 | Enclosure gyro Y raw (`int16`) |
|
||
| 16 | 2 | Enclosure gyro Z raw (`int16`) |
|
||
| 18 | 1 | Raw ADXL345 `INT_SOURCE` |
|
||
| 19 | 1 | Raw L3G4200D `STATUS_REG` |
|
||
|
||
The first record has delta zero and uses the frame's base timestamp. Each later
|
||
timestamp is reconstructed by cumulatively adding its delta. A delta that cannot
|
||
fit is stored as `0xFFFF` and sets packet flag bit 0. Sample sequence gaps remain
|
||
detectable independently.
|
||
|
||
Mapped raw counts are authoritative. The original sensor-native axes can be
|
||
reconstructed because the mappings are lossless:
|
||
|
||
```text
|
||
accel native = (-enclosure_y, enclosure_x, enclosure_z)
|
||
gyro native = ( enclosure_x, enclosure_y, enclosure_z)
|
||
```
|
||
|
||
## Metadata payload (48 bytes)
|
||
|
||
Metadata frames repeat approximately every five seconds so a receiver may attach
|
||
midstream. The payload contains:
|
||
|
||
- Sample rate, accelerometer range, gyroscope range, and mapping/calibration flags
|
||
- Three accel offset float32 values
|
||
- Three accel counts/g float32 values
|
||
- Three gyro bias float32 values
|
||
- Nominal gyro mdps/LSB float32 value
|
||
|
||
A byte-stream receiver may begin inside an incomplete frame. It discards bytes
|
||
until a magic/header/CRC combination validates. Host tools report any rejection
|
||
before that first valid frame separately from CRC failures after synchronization.
|
||
|
||
## Buffering
|
||
|
||
Acquisition runs in a dedicated higher-priority task and writes complete samples
|
||
to a 128-entry RAM queue. The lower-priority output task batches up to eight
|
||
records per frame. At 100 Hz this queue represents about 1.28 seconds of
|
||
decoupling from a blocked transport. Queue overflow never overwrites an older
|
||
sample silently: sequence gaps and the cumulative lost-sample counter expose it.
|