def _parse_compressed_19bit(self, packet_id, packet): """Parse a 19-bit compressed packet without accelerometer data.""" if bad_data_size(packet, 19, "19-bit compressed data"): return packet_id -= 100 # should get 2 by 4 arrays of uncompressed data deltas = decompress_deltas_19bit(packet) self._update_data_with_deltas(packet_id, deltas)
def _parse_uncompressed(self, packet_id, packet): """Parse a raw uncompressed packet.""" if bad_data_size(packet, 19, "uncompressed data"): return # 4 channels of 24bits self._last_eeg_data[:] = [ int_from_24bits(packet[i:i + 3]) for i in range(0, 12, 3) ] # = np.array([chan_data], dtype=np.float32).T self._update_counts_and_enqueue("EEG", packet_id)
def decompress_deltas_19bit(buffer): """Parse packet deltas from 19-bit compression format.""" if bad_data_size(buffer, 19, "19-byte compressed packet"): raise ValueError("Bad input size for byte conversion.") deltas = np.zeros((2, 4)) # Sample 1 - Channel 1 minibuf = [(buffer[0] >> 5), ((buffer[0] & 0x1F) << 3 & 0xFF) | (buffer[1] >> 5), ((buffer[1] & 0x1F) << 3 & 0xFF) | (buffer[2] >> 5)] deltas[0][0] = int32_from_19bit(minibuf) # Sample 1 - Channel 2 minibuf = [(buffer[2] & 0x1F) >> 2, (buffer[2] << 6 & 0xFF) | (buffer[3] >> 2), (buffer[3] << 6 & 0xFF) | (buffer[4] >> 2)] deltas[0][1] = int32_from_19bit(minibuf) # Sample 1 - Channel 3 minibuf = [((buffer[4] & 0x03) << 1 & 0xFF) | (buffer[5] >> 7), ((buffer[5] & 0x7F) << 1 & 0xFF) | (buffer[6] >> 7), ((buffer[6] & 0x7F) << 1 & 0xFF) | (buffer[7] >> 7)] deltas[0][2] = int32_from_19bit(minibuf) # Sample 1 - Channel 4 minibuf = [((buffer[7] & 0x7F) >> 4), ((buffer[7] & 0x0F) << 4 & 0xFF) | (buffer[8] >> 4), ((buffer[8] & 0x0F) << 4 & 0xFF) | (buffer[9] >> 4)] deltas[0][3] = int32_from_19bit(minibuf) # Sample 2 - Channel 1 minibuf = [((buffer[9] & 0x0F) >> 1), (buffer[9] << 7 & 0xFF) | (buffer[10] >> 1), (buffer[10] << 7 & 0xFF) | (buffer[11] >> 1)] deltas[1][0] = int32_from_19bit(minibuf) # Sample 2 - Channel 2 minibuf = [((buffer[11] & 0x01) << 2 & 0xFF) | (buffer[12] >> 6), (buffer[12] << 2 & 0xFF) | (buffer[13] >> 6), (buffer[13] << 2 & 0xFF) | (buffer[14] >> 6)] deltas[1][1] = int32_from_19bit(minibuf) # Sample 2 - Channel 3 minibuf = [((buffer[14] & 0x38) >> 3), ((buffer[14] & 0x07) << 5 & 0xFF) | ((buffer[15] & 0xF8) >> 3), ((buffer[15] & 0x07) << 5 & 0xFF) | ((buffer[16] & 0xF8) >> 3)] deltas[1][2] = int32_from_19bit(minibuf) # Sample 2 - Channel 4 minibuf = [(buffer[16] & 0x07), buffer[17], buffer[18]] deltas[1][3] = int32_from_19bit(minibuf) return deltas
def int_from_24bits(unpacked): """Convert 24-bit data coded on 3 bytes to a proper integer.""" if bad_data_size(unpacked, 3, "3-byte buffer"): raise ValueError("Bad input size for byte conversion.") # FIXME: quick'n dirty, unpack wants strings later on int_bytes = INT_SIGN_BYTE[unpacked[0] > 127] + struct.pack('3B', *unpacked) # unpack little endian(>) signed integer(i) (-> platform independent) int_unpacked = struct.unpack('>i', int_bytes)[0] return int_unpacked
def decompress_deltas_18bit(buffer): """Parse packet deltas from 18-byte compression format.""" if bad_data_size(buffer, 18, "18-byte compressed packet"): raise ValueError("Bad input size for byte conversion.") deltas = np.zeros((2, 4)) # Sample 1 - Channel 1 minibuf = [(buffer[0] >> 6), ((buffer[0] & 0x3F) << 2 & 0xFF) | (buffer[1] >> 6), ((buffer[1] & 0x3F) << 2 & 0xFF) | (buffer[2] >> 6)] deltas[0][0] = int32_from_18bit(minibuf) # Sample 1 - Channel 2 minibuf = [(buffer[2] & 0x3F) >> 4, (buffer[2] << 4 & 0xFF) | (buffer[3] >> 4), (buffer[3] << 4 & 0xFF) | (buffer[4] >> 4)] deltas[0][1] = int32_from_18bit(minibuf) # Sample 1 - Channel 3 minibuf = [(buffer[4] & 0x0F) >> 2, (buffer[4] << 6 & 0xFF) | (buffer[5] >> 2), (buffer[5] << 6 & 0xFF) | (buffer[6] >> 2)] deltas[0][2] = int32_from_18bit(minibuf) # Sample 1 - Channel 4 minibuf = [(buffer[6] & 0x03), buffer[7], buffer[8]] deltas[0][3] = int32_from_18bit(minibuf) # Sample 2 - Channel 1 minibuf = [(buffer[9] >> 6), ((buffer[9] & 0x3F) << 2 & 0xFF) | (buffer[10] >> 6), ((buffer[10] & 0x3F) << 2 & 0xFF) | (buffer[11] >> 6)] deltas[1][0] = int32_from_18bit(minibuf) # Sample 2 - Channel 2 minibuf = [(buffer[11] & 0x3F) >> 4, (buffer[11] << 4 & 0xFF) | (buffer[12] >> 4), (buffer[12] << 4 & 0xFF) | (buffer[13] >> 4)] deltas[1][1] = int32_from_18bit(minibuf) # Sample 2 - Channel 3 minibuf = [(buffer[13] & 0x0F) >> 2, (buffer[13] << 6 & 0xFF) | (buffer[14] >> 2), (buffer[14] << 6 & 0xFF) | (buffer[15] >> 2)] deltas[1][2] = int32_from_18bit(minibuf) # Sample 2 - Channel 4 minibuf = [(buffer[15] & 0x03), buffer[16], buffer[17]] deltas[1][3] = int32_from_18bit(minibuf) return deltas
def int32_from_18bit(three_byte_buffer): """Convert 18-bit data coded on 3 bytes to a proper integer.""" if bad_data_size(three_byte_buffer, 3, "3-byte buffer"): raise ValueError("Bad input size for byte conversion.") # if LSB is 1, negative number, some hasty unsigned to signed conversion to do if three_byte_buffer[2] & 0x01 > 0: prefix = 0b11111111111111 int32 = ((prefix << 18) | (three_byte_buffer[0] << 16) | (three_byte_buffer[1] << 8) | three_byte_buffer[2]) \ | ~0xFFFFFFFF else: prefix = 0 int32 = (prefix << 18) | (three_byte_buffer[0] << 16) \ | (three_byte_buffer[1] << 8) | three_byte_buffer[2] return int32
def _parse_compressed_18bit(self, packet_id, packet): """ Dealing with "18-bit compression without Accelerometer" """ if bad_data_size(packet, 19, "18-bit compressed data"): return # set appropriate accelerometer byte id_ones = packet_id % 10 - 1 if id_ones in [0, 1, 2]: value = int8_from_byte(packet[18]) self._chunks["accelerometer"][0, id_ones] = value if id_ones == 2: self._update_counts_and_enqueue("accelerometer", packet_id // 10) # deltas: should get 2 by 4 arrays of uncompressed data deltas = decompress_deltas_18bit(packet[:-1]) self._update_data_with_deltas(packet_id, deltas)