PacketCodec

Wire codec for BrainAccess stream packets and the channel-config blob.

The decoder is dependency-free and side-effect-free apart from advancing DecodeState.

Properties

Link copied to clipboard

ADC conversions the firmware spends on each channel per impedance measurement (5 settling + 20 measured). In impedance mode the device counter advances this many samples per active channel between two values.

Link copied to clipboard

Longest run of missing samples the decoder fills with dummies, in seconds of signal at the stream's rate. A longer jump is more likely a counter discontinuity than a real gap, so the cursor resyncs to the wire instead without dummies and DecodeState.counterJumps counts it.

Functions

Link copied to clipboard

Convert a 24-bit integer to 32-bit, preserving sign.

Link copied to clipboard
fun decode(packet: ByteArray, config: DeviceConfig, state: DecodeState, contactOut: (BooleanArray) -> Unit? = null, hardware: DeviceHardware = DeviceHardware.legacyDefault(config.model), digitalInput: Boolean = false, out: (EegFrame) -> Unit): Boolean

Decode one stream packet into typed EegFrames, advancing state. hardware decides the footer layout (accelerometer / gyroscope blocks present or not); it defaults to the V2 board of the config's model, which is every device without a readable Model Number. Returns true on success, false if the packet was malformed. See decodeRaw for the positional output.

Link copied to clipboard
fun decodeRaw(packet: ByteArray, config: DeviceConfig, state: DecodeState, contactOut: (BooleanArray) -> Unit? = null, hardware: DeviceHardware = DeviceHardware.legacyDefault(config.model), out: (values: FloatArray, isDummy: Boolean) -> Unit): Boolean

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.

Link copied to clipboard

Encode a DeviceConfig into the channel-config characteristic blob, the layout the firmware parses: