DreamTeam/thinkgear
Jump to navigation
Jump to search
(some notes ...) want complete packets read from buffer input sequence of buffer "reads" output sequence of synced packets a complete packet will have correct length (and matching checksum - check elsewhere) (how will partial packets be handled?) error checks might anticipate several issues: - transmission (dropped or incomplete packets) - device (scrambled data) - parser logic (anything goes) other non-error conditions might include: - poor signal (electrode contact) - artifact rejection (poor signal, eye blink) - protocol edge cases (data bytes mimic sync, etc) expect varying packet size 4 (empty payload) to 173 bytes (173 is theoretical max, if larger then invalid) how many samples per packet of raw eeg 2 byte value, 1 byte typecode per datarow 3 * 56 samples = 168 byte payload + 2 sync + 1 length + 1 checksum = 172 = at least 10 packets per 512 raw samples expect additional packet(s) for device-processed data (power spectra, 'esense') need to handle time - ie, esense every second may allow interpolating raw sample times inbetween
(some code, not tested ...) syncval = 0xaa syncpos = 0 synclen = 2 synced = False while not synced: buffer = get_next_buffer() if buffer.count(syncval) < 2: continue try: syncpos = buffer.index(syncval) except ValueError: print "no sync wtf???" nextpos = syncpos + 1 if nextpos < len(buffer) && buffer[nextpos] == syncval: synced = True lenpos = syncpos + synclen lenlen = 1 paylen = buffer[syncpos+2] assert paylen < 170 # note 170 is 0xaa - just coincidentally? # now can examine paylen and if necessary handle case where packet is not complete # needs rest of expected "paylen" data + checksum from next buffer expected_len = paylen + 4 lastpos = len(buffer) - 1 if expected_len > lastpos - syncpos: # need rest of packet from next buffer if len(packet) < expected_len: need_len = expected_len - len(packet) buffer = get_next_buffer() packet.extend(buffer[:needlen]) # would be good to store this for the next time, so don't have to re-iterate looking for next sync loadpos = lenpos + lenlen checkpos = loadpos + paylen payload = packet[loadpos:checkpos] # slice so payload is a copy. paycheck = packet[checkpos] assert paycheck == 0xff & ~( sum(payload) & 0xff ) codons = { 0x02: ('POOR_SIGNAL', 1), 0x04: ('ATTENTION', 1), 0x05: ('MEDITATION', 1), 0x16: ('BLINK_EVENT', 1), 0x55: ('EXTENDED_CODE', 1), 0x80: ('RAW_EEG', 2), 0x83: ('ASIC_POWER', 24), 0xaa: ('SYNC', 172) } getdatalen = lambda x, y:y[x][1] ptr = payload codelen = 1 # unless extended code, not handled here. codepos = 0 datalen = 0 def testdatalen(datalen, codetype): if datalen > 1: assert codetype >= 0x80 else: assert codetype < 0x80 nextpos = 0 while nextpos < paylen: codepos = nextpos codetype = ptr[codepos] assert codetype in codons assert codetype != 0x55 # we don't handle extended code bytes. datalen = getdatalen(codetype, codons) nextpos = codepos + codelen datapos = nextpos nextpos = datapos + datalen if nextpos >= paylen: break dataval = ptr[datapos:nextpos] newpos = datapos + datalen
def syncromesh(): buffer = init_buffer() paylen = 0 while True: synced_buffer_portion = discard_until_sync(buffer) expected_paylen = synced_buffer_portion[0] # written by device, packet is 4 bytes larger including 2 sync bytes assert expected_paylen < 170 complete_packet_len = expected_paylen + 1 buflen = len(synced_buffer_portion) if buflen < expected_paylen: # copy remaining buffer packet = synced_buffer_portion[:] # will need to "extend" packet with data from next buffer buffer = get_next_buffer expected_remaining = expected_paylen - buflen packet.extend(buffer[:expected_remaining]) assert len(packet) == expected_ # want function to loop, reading buffer, writing packets # initial state, before loop: # unsynced buffer (contains fractional packet, sync signal, then possibly complete packet/s) # blank packet # So, discard buffer contents before first sync signal # begin loop # at beginning of loop, have blank packet and synced buffer position # write from buffer to packet # until either # A) buffer end reached # B) logical packet content end reached # C) new sync signal detected (either before or at - or after! - logical packet end) What is "logical packet end" ? It is max 171 bytes after sync (total 173 bytes = 2 sync, 1 len, payload max 169 and 1 checksum byte) Precise length should be the data paylen value written by device + 4 if A) buffer end reached then, still in loop, get new buffer, keep writing packet if B) "logical packet end" according to device-written "paylen" byte then, send packet, start new blank packet if C) sync signal detected before "logical packet end" then, handle (apparent) dropped packet and/or logic error - Code this logic last, just flag dropped packet for now Log incomplete packet for analysis separate from "good" data and start new blank packet