##
import sigrokdecode as srd
+from collections import namedtuple
+from common.srdhelper import SrdIntEnum
from .lists import *
-ANN_STROBE, ANN_SINGLE_READ, ANN_SINGLE_WRITE, ANN_BURST_READ, \
- ANN_BURST_WRITE, ANN_STATUS_READ, ANN_STATUS, ANN_WARN = range(8)
+Ann = SrdIntEnum.from_str('Ann', 'STROBE SINGLE_READ SINGLE_WRITE BURST_READ \
+ BURST_WRITE STATUS_READ STATUS WARN')
+
+Pos = namedtuple('Pos', ['ss', 'es'])
+Data = namedtuple('Data', ['mosi', 'miso'])
class Decoder(srd.Decoder):
api_version = 3
('single_write', 'Single register write'),
('burst_read', 'Burst register read'),
('burst_write', 'Burst register write'),
- ('status', 'Status register'),
+ ('status_read', 'Status read'),
+ ('status_reg', 'Status register'),
('warning', 'Warning'),
)
annotation_rows = (
- ('cmd', 'Commands', (ANN_STROBE,)),
- ('data', 'Data', (ANN_SINGLE_READ, ANN_SINGLE_WRITE, ANN_BURST_READ,
- ANN_BURST_WRITE, ANN_STATUS_READ)),
- ('status', 'Status register', (ANN_STATUS,)),
- ('warnings', 'Warnings', (ANN_WARN,)),
+ ('cmds', 'Commands', (Ann.STROBE,)),
+ ('data', 'Data', (Ann.prefixes('SINGLE_ BURST_ STATUS_'))),
+ ('status', 'Status register', (Ann.STATUS,)),
+ ('warnings', 'Warnings', (Ann.WARN,)),
)
def __init__(self):
def warn(self, pos, msg):
'''Put a warning message 'msg' at 'pos'.'''
- self.put(pos[0], pos[1], self.out_ann, [ANN_WARN, [msg]])
+ self.put(pos.ss, pos.es, self.out_ann, [Ann.WARN, [msg]])
def putp(self, pos, ann, msg):
'''Put an annotation message 'msg' at 'pos'.'''
- self.put(pos[0], pos[1], self.out_ann, [ann, [msg]])
+ self.put(pos.ss, pos.es, self.out_ann, [ann, [msg]])
def putp2(self, pos, ann, msg1, msg2):
'''Put an annotation message 'msg' at 'pos'.'''
- self.put(pos[0], pos[1], self.out_ann, [ann, [msg1, msg2]])
+ self.put(pos.ss, pos.es, self.out_ann, [ann, [msg1, msg2]])
def next(self):
'''Resets the decoder after a complete command was decoded.'''
def mosi_bytes(self):
'''Returns the collected MOSI bytes of a multi byte command.'''
- return [b[0] for b in self.mb]
+ return [b.mosi for b in self.mb]
def miso_bytes(self):
'''Returns the collected MISO bytes of a multi byte command.'''
- return [b[1] for b in self.mb]
+ return [b.miso for b in self.mb]
def decode_command(self, pos, b):
'''Decodes the command byte 'b' at position 'pos' and prepares
self.cmd, self.dat, self.min, self.max = c
- if self.cmd in ('STROBE_CMD',):
- self.putp(pos, ANN_STROBE, self.format_command())
+ if self.cmd == 'Strobe':
+ self.putp(pos, Ann.STROBE, self.format_command())
else:
# Don't output anything now, the command is merged with
# the data bytes following it.
- self.ss_mb = pos[0]
+ self.ss_mb = pos.ss
def format_command(self):
'''Returns the label for the current command.'''
- if self.cmd == 'SINGLE_READ':
- return 'Read'
- if self.cmd == 'BURST_READ':
- return 'Burst read'
- if self.cmd == 'SINGLE_WRITE':
- return 'Write'
- if self.cmd == 'BURST_WRITE':
- return 'Burst write'
- if self.cmd == 'STATUS_READ':
- return 'Status read'
- if self.cmd == 'STROBE_CMD':
+ if self.cmd in ('Read', 'Burst read', 'Write', 'Burst write', 'Status read'):
+ return self.cmd
+ if self.cmd == 'Strobe':
reg = strobes.get(self.dat, 'unknown strobe')
- return 'STROBE "{}"'.format(reg)
+ return '{} {}'.format(self.cmd, reg)
else:
return 'TODO Cmd {}'.format(self.cmd)
addr = b & 0x3F
if (addr < 0x30) or (addr == 0x3E) or (addr == 0x3F):
if (b & 0xC0) == 0x00:
- return ('SINGLE_WRITE', addr, 1, 1)
+ return ('Write', addr, 1, 1)
if (b & 0xC0) == 0x40:
- return ('BURST_WRITE', addr, 1, 99999)
+ return ('Burst write', addr, 1, 99999)
if (b & 0xC0) == 0x80:
- return ('SINGLE_READ', addr, 1, 1)
+ return ('Read', addr, 1, 1)
if (b & 0xC0) == 0xC0:
- return ('BURST_READ', addr, 1, 99999)
+ return ('Burst read', addr, 1, 99999)
else:
self.warn(pos, 'unknown address/command combination')
else:
if (b & 0x40) == 0x00:
- return ('STROBE_CMD', addr, 0, 0)
+ return ('Strobe', addr, 0, 0)
if (b & 0xC0) == 0xC0:
- return ('STATUS_READ', addr, 1, 99999)
+ return ('Status read', addr, 1, 99999)
else:
self.warn(pos, 'unknown address/command combination')
- def decode_register(self, pos, ann, regid, data):
+ def decode_reg(self, pos, ann, regid, data):
'''Decodes a register.
pos -- start and end sample numbers of the register
if regid not in regs:
self.warn(pos, 'unknown register')
return
- name = '{} (0x{:02X})'.format(regs[regid], regid)
+ name = '{} ({:02X})'.format(regs[regid], regid)
else:
name = regid
- if regid == 'STATUS' and ann == ANN_STATUS:
+ if regid == 'STATUS' and ann == Ann.STATUS:
label = 'Status'
self.decode_status_reg(pos, ann, data, label)
else:
- if self.cmd in ('SINGLE_WRITE', 'SINGLE_READ', 'STATUS_READ', 'BURST_READ', 'BURST_WRITE'):
+ if self.cmd in ('Write', 'Read', 'Status read', 'Burst read', 'Burst write'):
label = '{}: {}'.format(self.format_command(), name)
else:
label = 'Reg ({}) {}'.format(self.cmd, name)
longtext_state = 'STATE is {}, '.format(status_reg_states[state])
# bits 3:0 --> FIFO_BYTES_AVAILABLE
fifo_bytes = status & 0x0F
- if self.cmd in ('SINGLE_READ', 'STATUS_READ', 'BURST_READ'):
+ if self.cmd in ('Single read', 'Status read', 'Burst read'):
longtext_fifo = '{} bytes available in RX FIFO'.format(fifo_bytes)
else:
longtext_fifo = '{} bytes free in TX FIFO'.format(fifo_bytes)
- text = '{} = "0x{:02X}"'.format(label, status)
+ text = '{} = {:02X}'.format(label, status)
longtext = ''.join([text, '; ', longtext_chiprdy, longtext_state, longtext_fifo])
self.putp2(pos, ann, longtext, text)
return '{:02X}'.format(b)
data = ' '.join([escape(b) for b in data])
- text = '{} = "0x{}"'.format(label, data)
+ text = '{} = {}'.format(label, data)
self.putp(pos, ann, text)
def finish_command(self, pos):
'''Decodes the remaining data bytes at position 'pos'.'''
- if self.cmd == 'SINGLE_WRITE':
- self.decode_register(pos, ANN_SINGLE_WRITE,
- self.dat, self.mosi_bytes())
- elif self.cmd == 'BURST_WRITE':
- self.decode_register(pos, ANN_BURST_WRITE,
- self.dat, self.mosi_bytes())
- elif self.cmd == 'SINGLE_READ':
- self.decode_register(pos, ANN_SINGLE_READ,
- self.dat, self.miso_bytes())
- elif self.cmd == 'BURST_READ':
- self.decode_register(pos, ANN_BURST_READ,
- self.dat, self.miso_bytes())
- elif self.cmd == 'STROBE_CMD':
- self.decode_register(pos, ANN_STROBE,
- self.dat, self.mosi_bytes())
- elif self.cmd == 'STATUS_READ':
- self.decode_register(pos, ANN_STATUS_READ,
- self.dat, self.miso_bytes())
+ if self.cmd == 'Write':
+ self.decode_reg(pos, Ann.SINGLE_WRITE, self.dat, self.mosi_bytes())
+ elif self.cmd == 'Burst write':
+ self.decode_reg(pos, Ann.BURST_WRITE, self.dat, self.mosi_bytes())
+ elif self.cmd == 'Read':
+ self.decode_reg(pos, Ann.SINGLE_READ, self.dat, self.miso_bytes())
+ elif self.cmd == 'Burst read':
+ self.decode_reg(pos, Ann.BURST_READ, self.dat, self.miso_bytes())
+ elif self.cmd == 'Strobe':
+ self.decode_reg(pos, Ann.STROBE, self.dat, self.mosi_bytes())
+ elif self.cmd == 'Status read':
+ self.decode_reg(pos, Ann.STATUS_READ, self.dat, self.miso_bytes())
else:
self.warn(pos, 'unhandled command')
if len(self.mb) < self.min:
self.warn((ss, ss), 'missing data bytes')
elif self.mb:
- self.finish_command((self.ss_mb, self.es_mb))
+ self.finish_command(Pos(self.ss_mb, self.es_mb))
self.next()
self.cs_was_released = True
elif ptype == 'DATA' and self.cs_was_released:
mosi, miso = data1, data2
- pos = (ss, es)
+ pos = Pos(ss, es)
if miso is None or mosi is None:
self.requirements_met = False
# First MOSI byte is always the command.
self.decode_command(pos, mosi)
# First MISO byte is always the status register.
- self.decode_register(pos, ANN_STATUS, 'STATUS', [miso])
+ self.decode_reg(pos, Ann.STATUS, 'STATUS', [miso])
else:
if not self.cmd or len(self.mb) >= self.max:
self.warn(pos, 'excess byte')
if self.ss_mb == -1:
self.ss_mb = ss
self.es_mb = es
- self.mb.append((mosi, miso))
+ self.mb.append(Data(mosi, miso))