X-Git-Url: https://sigrok.org/gitweb/?p=libsigrokdecode.git;a=blobdiff_plain;f=decoders%2Fnrf24l01%2Fpd.py;h=ae1cb35adf416ce24e47be26c12384a6de0d8ae4;hp=39a6808d8f94dd56768739a00c59b6fd136af017;hb=4539e9ca58966ce3c9cad4801b16c315e86ace01;hpb=0e501c70cf26f208d7e523b7fe737d0e8d565109 diff --git a/decoders/nrf24l01/pd.py b/decoders/nrf24l01/pd.py index 39a6808..ae1cb35 100644 --- a/decoders/nrf24l01/pd.py +++ b/decoders/nrf24l01/pd.py @@ -14,13 +14,12 @@ ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License -## along with this program; if not, write to the Free Software -## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +## along with this program; if not, see . ## import sigrokdecode as srd -class MissingDataError(Exception): +class ChannelError(Exception): pass regs = { @@ -50,26 +49,36 @@ regs = { 0x16: ('RX_PW_P5', 1), 0x17: ('FIFO_STATUS', 1), 0x1c: ('DYNPD', 1), - 0x1d: ('FEATURE', 1) + 0x1d: ('FEATURE', 1), +} + +xn297_regs = { + 0x19: ('DEMOD_CAL', 5), + 0x1e: ('RF_CAL', 7), + 0x1f: ('BB_CAL', 5), } class Decoder(srd.Decoder): api_version = 2 id = 'nrf24l01' - name = 'NRF24L01(+)' + name = 'nRF24L01(+)' longname = 'Nordic Semiconductor nRF24L01/nRF24L01+' - desc = '2.4 GHz transceiver chip.' + desc = '2.4GHz transceiver chip.' license = 'gplv2+' inputs = ['spi'] outputs = ['nrf24l01'] + options = ( + {'id': 'chip', 'desc': 'Chip type', + 'default': 'nrf24l01', 'values': ('nrf24l01', 'xn297')}, + ) annotations = ( - # sent from the host to the chip - ('cmd', 'Commands send to the device.'), - ('tx-data', 'Payload send to the device.'), + # Sent from the host to the chip. + ('cmd', 'Commands sent to the device'), + ('tx-data', 'Payload sent to the device'), - # returned by the chip - ('register', 'Registers read from the device.'), - ('rx-data', 'Payload read from the device.'), + # Returned by the chip. + ('register', 'Registers read from the device'), + ('rx-data', 'Payload read from the device'), ('warning', 'Warnings'), ) @@ -84,11 +93,15 @@ class Decoder(srd.Decoder): ('warnings', 'Warnings', (ann_warn,)), ) - def __init__(self, **kwargs): + def __init__(self): self.next() + self.requirements_met = True + self.cs_was_released = False def start(self): self.out_ann = self.register(srd.OUTPUT_ANN) + if self.options['chip'] == 'xn297': + regs.update(xn297_regs) def warn(self, pos, msg): '''Put a warning message 'msg' at 'pos'.''' @@ -100,17 +113,17 @@ class Decoder(srd.Decoder): def next(self): '''Resets the decoder after a complete command was decoded.''' - # 'True' for the first byte after CS went low + # 'True' for the first byte after CS went low. self.first = True - # the current command, and the minimum and maximum number - # of data bytes to follow + # The current command, and the minimum and maximum number + # of data bytes to follow. self.cmd = None self.min = 0 self.max = 0 - # used to collect the bytes after the command byte - # (and the start/end sample number) + # Used to collect the bytes after the command byte + # (and the start/end sample number). self.mb = [] self.mb_s = -1 self.mb_e = -1 @@ -127,15 +140,15 @@ class Decoder(srd.Decoder): '''Decodes the command byte 'b' at position 'pos' and prepares the decoding of the following data bytes.''' c = self.parse_command(b) - if c == None: + if c is None: self.warn(pos, 'unknown command') return self.cmd, self.dat, self.min, self.max = c if self.cmd in ('W_REGISTER', 'ACTIVATE'): - # don't output anything now, the command is merged with - # the data bytes following it + # Don't output anything now, the command is merged with + # the data bytes following it. self.mb_s = pos[0] else: self.putp(pos, self.ann_cmd, self.format_command()) @@ -144,9 +157,9 @@ class Decoder(srd.Decoder): '''Returns the label for the current command.''' if self.cmd == 'R_REGISTER': reg = regs[self.dat][0] if self.dat in regs else 'unknown register' - return 'Cmd. R_REGISTER "{}"'.format(reg) + return 'Cmd R_REGISTER "{}"'.format(reg) else: - return 'Cmd. {}'.format(self.cmd) + return 'Cmd {}'.format(self.cmd) def parse_command(self, b): '''Parses the command byte. @@ -196,36 +209,40 @@ class Decoder(srd.Decoder): ''' if type(regid) == int: - # get the name of the register + # Get the name of the register. if regid not in regs: self.warn(pos, 'unknown register') return - name = regs[regid][0] else: name = regid - # multi byte register come LSByte first + # Multi byte register come LSByte first. data = reversed(data) if self.cmd == 'W_REGISTER' and ann == self.ann_cmd: - # the 'W_REGISTER' command is merged with the following byte(s) + # The 'W_REGISTER' command is merged with the following byte(s). label = '{}: {}'.format(self.format_command(), name) else: - label = 'Reg. {}'.format(name) + label = 'Reg {}'.format(name) - self.decode_mb_data(pos, ann, data, label) + self.decode_mb_data(pos, ann, data, label, True) - def decode_mb_data(self, pos, ann, data, label, escape_all=True): + def decode_mb_data(self, pos, ann, data, label, always_hex): '''Decodes the data bytes 'data' of a multibyte command at position - 'pos'. The decoded data is prefixed with 'label'. If 'excape_all' is - True, all data bytes are escaped as hex codes.''' + 'pos'. The decoded data is prefixed with 'label'. If 'always_hex' is + True, all bytes are decoded as hex codes, otherwise only non + printable characters are escaped.''' - def escape(b): - c = chr(b) - if escape_all or not str.isprintable(c): - return '\\x{:02X}'.format(b) - return c + if always_hex: + def escape(b): + return '{:02X}'.format(b) + else: + def escape(b): + c = chr(b) + if not str.isprintable(c): + return '\\x{:02X}'.format(b) + return c data = ''.join([escape(b) for b in data]) text = '{} = "{}"'.format(label, data) @@ -236,10 +253,10 @@ class Decoder(srd.Decoder): if self.cmd == 'R_REGISTER': self.decode_register(pos, self.ann_reg, - self.dat, self.miso_bytes()); + self.dat, self.miso_bytes()) elif self.cmd == 'W_REGISTER': self.decode_register(pos, self.ann_cmd, - self.dat, self.mosi_bytes()); + self.dat, self.mosi_bytes()) elif self.cmd == 'R_RX_PAYLOAD': self.decode_mb_data(pos, self.ann_rx, self.miso_bytes(), 'RX payload', False) @@ -260,40 +277,51 @@ class Decoder(srd.Decoder): self.warn(pos, 'wrong data for "ACTIVATE" command') def decode(self, ss, es, data): + if not self.requirements_met: + return + ptype, data1, data2 = data if ptype == 'CS-CHANGE': + if data1 is None: + if data2 is None: + self.requirements_met = False + raise ChannelError('CS# pin required.') + elif data2 == 1: + self.cs_was_released = True + if data1 == 0 and data2 == 1: - # rising edge, the complete command is transmitted, process - # the bytes that were send after the command byte + # Rising edge, the complete command is transmitted, process + # the bytes that were send after the command byte. if self.cmd: - # check if we got the minimum number of data bytes - # after the command byte + # Check if we got the minimum number of data bytes + # after the command byte. if len(self.mb) < self.min: self.warn((ss, ss), 'missing data bytes') elif self.mb: self.finish_command((self.mb_s, self.mb_e)) self.next() - elif ptype == 'DATA': - mosi = data1 - miso = data2 + self.cs_was_released = True + elif ptype == 'DATA' and self.cs_was_released: + mosi, miso = data1, data2 pos = (ss, es) - if miso == None or mosi == None: - raise MissingDataError('Both MISO and MOSI pins required.') + if miso is None or mosi is None: + self.requirements_met = False + raise ChannelError('Both MISO and MOSI pins required.') if self.first: self.first = False - # first MOSI byte is always the command + # First MOSI byte is always the command. self.decode_command(pos, mosi) - # first MISO byte is always the status register + # First MISO byte is always the status register. self.decode_register(pos, self.ann_reg, 'STATUS', [miso]) else: if not self.cmd or len(self.mb) >= self.max: self.warn(pos, 'excess byte') else: - # collect the bytes after the command byte + # Collect the bytes after the command byte. if self.mb_s == -1: self.mb_s = ss self.mb_e = es