'''
OUTPUT_PYTHON format:
-[<data>] where <data> is the payload contained between the LFAST header and
-the LFAST stop bit. It's an array of bytes.
+[ss, es, data] where data is a data byte of the LFAST payload. All bytes of
+the payload are sent at once, each with its start and end sample.
'''
# See tc27xD_um_v2.2.pdf, Table 20-10
payload_sizes = {
0b000: '8 bit',
- 0b001: '32 bit',
- 0b010: '64 bit',
- 0b011: '96 bit',
- 0b100: '128 bit',
- 0b101: '256 bit',
- 0b110: '512 bit',
- 0b111: '288 bit'
+ 0b001: '32 bit / 4 byte',
+ 0b010: '64 bit / 8 byte',
+ 0b011: '96 bit / 12 byte',
+ 0b100: '128 bit / 16 byte',
+ 0b101: '256 bit / 32 byte',
+ 0b110: '512 bit / 64 byte',
+ 0b111: '288 bit / 36 byte'
}
# See tc27xD_um_v2.2.pdf, Table 20-10
# See tc27xD_um_v2.2.pdf, Table 20-11
channel_types = {
- 0b0000: 'Interface Control / PING (32 bit)',
+ 0b0000: 'Interface Control / PING',
0b0001: 'Unsolicited Status (32 bit)',
0b0010: 'Slave Interface Control / Read',
0b0011: 'CTS Transfer',
def __init__(self):
decimal.getcontext().rounding = decimal.ROUND_HALF_UP
+ self.bit_len = 0xFFFFFFFF
self.reset()
def reset(self):
+ self.prev_bit_len = self.bit_len
self.ss = self.es = 0
self.ss_payload = self.es_payload = 0
+ self.ss_byte = 0
self.bits = []
self.payload = []
self.payload_size = 0 # Expected number of bytes, as read from header
self.bit_len = 0 # Length of one bit time, in samples
- self.timeout = 0 # desired timeout for next edge, in samples
+ self.timeout = 0 # Desired timeout for next edge, in samples
self.ch_type_id = 0 # ID of channel type
self.state = state_sync
self.put_ann(self.ss_sync, self.es_bit, ann_sync, ['Sync OK'])
else:
self.put_ann(self.ss_sync, self.es_bit, ann_warning, ['Wrong Sync Value: {:02X}'.format(value)])
+ self.reset()
- self.bits = []
- self.state = state_header
+ # Only continue if we didn't just reset
+ if self.ss > 0:
+ self.bits = []
+ self.state = state_header
+ self.timeout = int(9.4 * self.bit_len)
def handle_header(self):
if len(self.bits) == 1:
value = bitpack(self.bits)
ss = self.ss_header
- es = ss + 3 * bit_len
+ es = ss + 3 * bit_len
size_id = (value & 0xE0) >> 5
size = payload_sizes.get(size_id)
- self.payload_size = payload_byte_sizes.get(size_id)
+ self.payload_size = payload_byte_sizes.get(size_id)
self.put_ann(int(ss), int(es), ann_header_pl_size, [size])
ss = es
- es = ss + 4 * bit_len
+ es = ss + 4 * bit_len
self.ch_type_id = (value & 0x1E) >> 1
ch_type = channel_types.get(self.ch_type_id)
self.put_ann(int(ss), int(es), ann_header_ch_type, [ch_type])
ss = es
- es = ss + bit_len
- cts = value & 0x01
+ es = ss + bit_len
+ cts = value & 0x01
self.put_ann(int(ss), int(es), ann_header_cts, ['{}'.format(cts)])
self.bits = []
self.state = state_payload
+ self.timeout = int(9.4 * self.bit_len)
def handle_payload(self):
+ self.timeout = int((self.payload_size - len(self.payload)) * 8 * self.bit_len)
+
if len(self.bits) == 1:
self.ss_byte = self.ss_bit
if self.ss_payload == 0:
if len(self.bits) == 8:
value = bitpack(self.bits)
value_hex = '{:02X}'.format(value)
-
+
# Control transfers have no SIPI payload, show them as control transfers
- # Check the channel_types list for the meaning of the magic values
+ # Check the channel_types list for the meaning of the magic values
if (self.ch_type_id >= 0b0100) and (self.ch_type_id <= 0b1011):
self.put_ann(self.ss_byte, self.es_bit, ann_payload, [value_hex])
else:
self.put_ann(self.ss_byte, self.es_bit, ann_control_data, [value_hex])
self.bits = []
- self.payload.append(value)
self.es_payload = self.es_bit
-
- self.timeout = int((self.payload_size - len(self.payload)) * 8 * self.bit_len)
-
- if (len(self.payload) == self.payload_size):
- self.timeout = int(1.4 * self.bit_len)
- self.bits = []
- self.state = state_sleepbit
+ self.payload.append((self.ss_byte, self.es_payload, value))
+
+ if (len(self.payload) == self.payload_size):
+ self.timeout = int(1.4 * self.bit_len)
+ self.state = state_sleepbit
def handle_sleepbit(self):
if len(self.bits) == 0:
self.put_ann(self.ss_bit, self.es_bit, ann_sleepbit, ['No LVDS sleep mode request', 'No sleep', 'N'])
# We only send the payload out if this is an actual data transfer;
- # check the channel_types list for the meaning of the magic values
+ # check the channel_types list for the meaning of the magic values
if (self.ch_type_id >= 0b0100) and (self.ch_type_id <= 0b1011):
if len(self.payload) > 0:
self.put_payload()
- self.reset()
-
def decode(self):
while True:
if self.timeout == 0:
# If this is the first edge, we only update ss
if self.ss == 0:
self.ss = self.samplenum
+ # Let's set the timeout for the sync pattern as well
+ self.timeout = int(16.2 * self.prev_bit_len)
continue
-
+
self.es = self.samplenum
- if int(self.es - self.ss) == 0:
- continue
-
# Check for the sleep bit if this is a timeout condition
- if (self.timeout > 0) and (self.es - self.ss == self.timeout):
+ if (len(self.matched) == 2) and self.matched[1]:
rising_edge = ~rising_edge
- if self.state == state_sleepbit:
+ if self.state == state_sync:
+ self.reset()
+ continue
+ elif self.state == state_sleepbit:
+ self.ss_bit += self.bit_len
+ self.es_bit = self.ss_bit + self.bit_len
self.handle_sleepbit()
+ self.reset()
+ continue
+
+ # Shouldn't happen but we check just in case
+ if int(self.es - self.ss) == 0:
+ continue
# We use the first bit to deduce the bit length
if self.bit_len == 0:
# Determine number of bits covered by this edge
bit_count = (self.es - self.ss) / self.bit_len
bit_count = int(decimal.Decimal(bit_count).to_integral_value())
-
+
if bit_count == 0:
self.put_ann(self.ss, self.es, ann_warning, ['Bit time too short'])
self.reset()
continue
-
+
bit_value = '0' if rising_edge else '1'
divided_len = (self.es - self.ss) / bit_count
self.handle_payload()
elif self.state == state_sleepbit:
self.handle_sleepbit()
- break
+ self.reset()
+
+ if self.ss == 0:
+ break # Because reset() was called, invalidating everything
# Only update ss if we didn't just perform a reset
if self.ss > 0:
self.ss = self.samplenum
+
+ # If we got here when a timeout occurred, we have processed all null
+ # bits that we could and should reset now to find the next packet
+ if (len(self.matched) == 2) and self.matched[1]:
+ self.reset()