decodeRaw
Decode one stream packet, emitting a positional layout per sample: [ch_0 … ch_{A-1}, (accX, accY, accZ if accel), (gyroX, gyroY, gyroZ if gyro), sampleIndex, dummyFlag, battery], where dummy (gap-fill) samples use channelCount leading zeros and dummyFlag = 1. IMU values are raw int16 counts. Its sampleIndex column is a Float, exact only up to 2^24 — long recordings must take the index from decode instead.
Footer, from the end of the packet: [gyro 6]? [accel 6]? [contact c] [timestamp 4] [sampleSize 1].
Sample numbering and gap-fill:
normal mode: missing indices up to MAX_FILLED_GAP_SECONDS of signal become dummies; a longer jump resyncs the cursor without dummies, a packet only partly behind the cursor appends at it; both count in DecodeState.counterJumps. A packet wholly behind it is dropped, decoding to nothing (DecodeState.stalePackets); a counter that moved back and stays there resyncs the cursor to it (see takePacket). The counter is unsigned 32-bit.
impedance mode: no gap-fill — the counter skips a whole measurement sweep between values on purpose. Value
jof a packet withSvalues is numbered with the ADC sample it was taken at,timestamp − (S−1−j)·25·A, and contact reads all-true (the lead-off bits mean nothing while the device drives the impedance current).
The trailing sampleSize byte is only the delta offset in normal mode; the firmware sends 0 in impedance mode, so impedance samples are strided by 3·A from the config.