X-Git-Url: https://sigrok.org/gitweb/?a=blobdiff_plain;f=decoders%2Fsle44xx%2Fpd.py;h=775ee3c8a8fb78c9d29aa826a683e480e5da1885;hb=e4f70391abbb153364a534d45a59026961ce1b1f;hp=1c0cdb4c9e1901bef21630900d349e3b31567edb;hpb=5c47b179b3e1e90b79478a9feca18990c481d014;p=libsigrokdecode.git diff --git a/decoders/sle44xx/pd.py b/decoders/sle44xx/pd.py index 1c0cdb4..775ee3c 100644 --- a/decoders/sle44xx/pd.py +++ b/decoders/sle44xx/pd.py @@ -17,19 +17,35 @@ ## along with this program; if not, see . ## +from common.srdhelper import bitpack_lsb import sigrokdecode as srd class Pin: RST, CLK, IO, = range(3) -# CMD: [annotation-type-index, long annotation, short annotation] +class Ann: + BIT, ATR, CMD, DATA, RESET, = range(5) + +class Bin: + SEND_DATA, = range(1) + +# CMD: [annotation class index, annotation texts for zoom levels] proto = { - 'RESET': [0, 'Reset', 'R'], - 'ATR': [1, 'ATR', 'ATR'], - 'CMD': [2, 'Command', 'C'], - 'DATA': [3, 'Data', 'D'], + 'BIT': [Ann.BIT, '{bit}',], + 'ATR': [Ann.ATR, 'Answer To Reset: {data:02x}', 'ATR: {data:02x}', '{data:02x}',], + 'CMD': [Ann.CMD, 'Command: {data:02x}', 'Cmd: {data:02x}', '{data:02x}',], + 'DATA': [Ann.DATA, 'Data: {data:02x}', '{data:02x}',], + 'RESET': [Ann.RESET, 'Reset', 'R',], } +def lookup_proto_ann_txt(cmd, variables): + ann = proto.get(cmd, None) + if ann is None: + return None, [] + cls, texts = ann[0], ann[1:] + texts = [t.format(**variables) for t in texts] + return cls, texts + class Decoder(srd.Decoder): api_version = 3 id = 'sle44xx' @@ -46,16 +62,16 @@ class Decoder(srd.Decoder): {'id': 'io', 'name': 'I/O', 'desc': 'I/O data line'}, ) annotations = ( - ('reset', 'Reset'), + ('bit', 'Bit'), ('atr', 'ATR'), ('cmd', 'Command'), ('data', 'Data exchange'), - ('bit', 'Bit'), + ('reset', 'Reset'), ) annotation_rows = ( - ('bits', 'Bits', (4,)), - ('fields', 'Fields', (1, 2, 3)), - ('interrupts', 'Interrupts', (0,)), + ('bits', 'Bits', (Ann.BIT,)), + ('fields', 'Fields', (Ann.ATR, Ann.CMD, Ann.DATA)), + ('interrupts', 'Interrupts', (Ann.RESET,)), ) binary = ( ('send-data', 'Send data'), @@ -66,10 +82,8 @@ class Decoder(srd.Decoder): def reset(self): self.ss = self.es = self.ss_byte = -1 - self.bitcount = 0 - self.databyte = 0 self.bits = [] - self.cmd = 'RESET' + self.cmd = None def metadata(self, key, value): if key == srd.SRD_CONF_SAMPLERATE: @@ -87,58 +101,64 @@ class Decoder(srd.Decoder): def handle_reset(self, pins): self.ss, self.es = self.samplenum, self.samplenum - cmd = 'RESET' # No need to set the global self.cmd as this command is atomic - self.putx([proto[cmd][0], proto[cmd][1:]]) - self.bitcount = self.databyte = 0 + self.cmd = 'RESET' + cls, texts = lookup_proto_ann_txt(self.cmd, {}) + self.putx([cls, texts]) self.bits = [] - self.cmd = 'ATR' # Next data bytes will be ATR + # Next data bytes will be Answer To Reset. + self.cmd = 'ATR' def handle_command(self, pins): rst, clk, io = pins self.ss, self.es = self.samplenum, self.samplenum + # XXX Is the comment inverted? # If I/O is rising -> command START # if I/O is falling -> command STOP and response data incoming - self.cmd = 'CMD' if (io == 0) else 'DATA' - self.bitcount = self.databyte = 0 + self.cmd = 'CMD' if io == 0 else 'DATA' self.bits = [] # Gather 8 bits of data def handle_data(self, pins): rst, clk, io = pins - # Data is transmitted LSB-first. - self.databyte |= (io << self.bitcount) - - # Remember the start of the first data/address bit. - if self.bitcount == 0: + # Remember the start of the first data/address bit. Collect + # bits in LSB first order. "Estimate" the bit's width at first, + # update end times as better data becomes available. + # TODO This estimation logic is imprecise and fragile. A single + # slightly stretched clock period throws off the following bit + # annotation. Better look for more reliable conditions. Available + # documentation suggests bit values are valid during high CLK. + if not self.bits: self.ss_byte = self.samplenum - - # Store individual bits and their start/end samplenumbers. - # In the list, index 0 represents the LSB (SLE44xx transmits LSB-first). - self.bits.insert(0, [io, self.samplenum, self.samplenum]) - if self.bitcount > 0: - self.bits[1][2] = self.samplenum - if self.bitcount == 7: - self.bitwidth = self.bits[1][2] - self.bits[2][2] - self.bits[0][2] += self.bitwidth - - # Return if we haven't collected all 8 bits, yet. - if self.bitcount < 7: - self.bitcount += 1 + bit_val = io + bit_ss = self.samplenum + bit_es = bit_ss # self.bitwidth is not known yet. + if self.bits: + self.bits[-1][2] = bit_ss + self.bits.append([bit_val, bit_ss, bit_es]) + if len(self.bits) < 8: return + bitwidth = self.bits[-1][1] - self.bits[-2][1] + self.bits[-1][2] += bitwidth - self.ss, self.es = self.ss_byte, self.samplenum + self.bitwidth + # Get the data byte value, and byte's ss/es. + databyte = bitpack_lsb(self.bits, 0) + self.ss_byte = self.bits[0][1] + self.es_byte = self.bits[-1][2] - self.putb([0, bytes([self.databyte])]) + self.ss, self.es = self.ss_byte, self.es_byte + self.putb([Bin.SEND_DATA, bytes([databyte])]) - for bit in self.bits: - self.put(bit[1], bit[2], self.out_ann, [4, ['%d' % bit[0]]]) + # TODO Present bit values earlier. As soon as their es is known. + for bit_val, bit_ss, bit_es in self.bits: + cls, texts = lookup_proto_ann_txt('BIT', {'bit': bit_val}) + self.put(bit_ss, bit_es, self.out_ann, [cls, texts]) - self.putx([proto[self.cmd][0], ['%s: %02X' % (proto[self.cmd][1], self.databyte), - '%s: %02X' % (proto[self.cmd][2], self.databyte), '%02X' % self.databyte]]) + cls, texts = lookup_proto_ann_txt(self.cmd, {'data': databyte}) + if cls: + self.putx([cls, texts]) # Done with this packet. - self.bitcount = self.databyte = 0 self.bits = [] def decode(self): @@ -146,6 +166,7 @@ class Decoder(srd.Decoder): # Signal conditions tracked by the protocol decoder: # - RESET condition (R): RST = rising # - Incoming data (D): RST = low, CLK = rising. + # TODO Add "RST low, CLK fall" for "end of DATA" here? # - Command mode START: CLK = high, I/O = falling. # - Command mode STOP: CLK = high, I/O = rising. (COND_RESET, COND_DATA, COND_CMD_START, COND_CMD_STOP,) = range(4)