X-Git-Url: https://sigrok.org/gitweb/?a=blobdiff_plain;f=decoders%2Fi2c%2Fi2c.py;h=5f67d3576ab49d70eb0dbc15e107de67b3d8edea;hb=271acd3bde96474c7ed5f822d470f555af8e7d93;hp=b1c4a8acaf3080258cdbd186a5d5769cd641f2ee;hpb=156509ca42f0df2380c9f205f9aad337e1a07802;p=libsigrokdecode.git diff --git a/decoders/i2c/i2c.py b/decoders/i2c/i2c.py index b1c4a8a..5f67d35 100644 --- a/decoders/i2c/i2c.py +++ b/decoders/i2c/i2c.py @@ -33,12 +33,12 @@ import sigrokdecode as srd # Annotation feed formats -ANN_SHIFTED = 0 +ANN_SHIFTED = 0 ANN_SHIFTED_SHORT = 1 -ANN_RAW = 2 +ANN_RAW = 2 # Values are verbose and short annotation, respectively. -protocol = { +proto = { 'START': ['START', 'S'], 'START REPEAT': ['START REPEAT', 'Sr'], 'STOP': ['STOP', 'P'], @@ -50,18 +50,12 @@ protocol = { 'DATA WRITE': ['DATA WRITE', 'DW'], } -# States -FIND_START = 0 -FIND_ADDRESS = 1 -FIND_DATA = 2 - class Decoder(srd.Decoder): api_version = 1 id = 'i2c' name = 'I2C' longname = 'Inter-Integrated Circuit' desc = 'I2C is a two-wire, multi-master, serial bus.' - longdesc = '...' license = 'gplv2+' inputs = ['logic'] outputs = ['i2c'] @@ -91,7 +85,7 @@ class Decoder(srd.Decoder): self.databyte = 0 self.wr = -1 self.is_repeat_start = 0 - self.state = FIND_START + self.state = 'FIND START' self.oldscl = None self.oldsda = None @@ -124,11 +118,11 @@ class Decoder(srd.Decoder): self.startsample = self.samplenum cmd = 'START REPEAT' if (self.is_repeat_start == 1) else 'START' - self.put(self.out_proto, [cmd, None, None]) - self.put(self.out_ann, [ANN_SHIFTED, [protocol[cmd][0]]]) - self.put(self.out_ann, [ANN_SHIFTED_SHORT, [protocol[cmd][1]]]) + self.put(self.out_proto, [cmd, None]) + self.put(self.out_ann, [ANN_SHIFTED, [proto[cmd][0]]]) + self.put(self.out_ann, [ANN_SHIFTED_SHORT, [proto[cmd][1]]]) - self.state = FIND_ADDRESS + self.state = 'FIND ADDRESS' self.bitcount = self.databyte = 0 self.is_repeat_start = 1 self.wr = -1 @@ -144,62 +138,58 @@ class Decoder(srd.Decoder): # Return if we haven't collected all 8 + 1 bits, yet. self.bitcount += 1 - if self.bitcount != 9: + if self.bitcount != 8: return + # We triggered on the ACK/NACK bit, but won't report that until later. + self.startsample -= 1 + # Send raw output annotation before we start shifting out - # read/write and ack/nack bits. + # read/write and ACK/NACK bits. self.put(self.out_ann, [ANN_RAW, ['0x%.2x' % self.databyte]]) - # We received 8 address/data bits and the ACK/NACK bit. - self.databyte >>= 1 # Shift out unwanted ACK/NACK bit here. - - if self.state == FIND_ADDRESS: + if self.state == 'FIND ADDRESS': # The READ/WRITE bit is only in address bytes, not data bytes. self.wr = 0 if (self.databyte & 1) else 1 d = self.databyte >> 1 - elif self.state == FIND_DATA: + elif self.state == 'FIND DATA': d = self.databyte - else: - # TODO: Error? - pass - # Last bit that came in was the ACK/NACK bit (1 = NACK). - ack_bit = 'NACK' if (sda == 1) else 'ACK' - - if self.state == FIND_ADDRESS and self.wr == 1: + if self.state == 'FIND ADDRESS' and self.wr == 1: cmd = 'ADDRESS WRITE' - elif self.state == FIND_ADDRESS and self.wr == 0: + elif self.state == 'FIND ADDRESS' and self.wr == 0: cmd = 'ADDRESS READ' - elif self.state == FIND_DATA and self.wr == 1: + elif self.state == 'FIND DATA' and self.wr == 1: cmd = 'DATA WRITE' - elif self.state == FIND_DATA and self.wr == 0: + elif self.state == 'FIND DATA' and self.wr == 0: cmd = 'DATA READ' - self.put(self.out_proto, [cmd, d, ack_bit]) - self.put(self.out_ann, [ANN_SHIFTED, - [protocol[cmd][0], '0x%02x' % d, protocol[ack_bit][0]]]) - self.put(self.out_ann, [ANN_SHIFTED_SHORT, - [protocol[cmd][1], '0x%02x' % d, protocol[ack_bit][1]]]) + self.put(self.out_proto, [cmd, d]) + self.put(self.out_ann, [ANN_SHIFTED, [proto[cmd][0], '0x%02x' % d]]) + self.put(self.out_ann, [ANN_SHIFTED_SHORT, [proto[cmd][1], '0x%02x' % d]]) - self.bitcount = self.databyte = 0 + # Done with this packet. self.startsample = -1 + self.bitcount = self.databyte = 0 + self.state = 'FIND ACK' - if self.state == FIND_ADDRESS: - self.state = FIND_DATA - elif self.state == FIND_DATA: - # There could be multiple data bytes in a row. - # So, either find a STOP condition or another data byte next. - pass + def get_ack(self, scl, sda): + self.startsample = self.samplenum + ack_bit = 'NACK' if (sda == 1) else 'ACK' + self.put(self.out_proto, [ack_bit, None]) + self.put(self.out_ann, [ANN_SHIFTED, [proto[ack_bit][0]]]) + self.put(self.out_ann, [ANN_SHIFTED_SHORT, [proto[ack_bit][1]]]) + # There could be multiple data bytes in a row, so either find + # another data byte or a STOP condition next. + self.state = 'FIND DATA' def found_stop(self, scl, sda): self.startsample = self.samplenum + self.put(self.out_proto, ['STOP', None]) + self.put(self.out_ann, [ANN_SHIFTED, [proto['STOP'][0]]]) + self.put(self.out_ann, [ANN_SHIFTED_SHORT, [proto['STOP'][1]]]) - self.put(self.out_proto, ['STOP', None, None]) - self.put(self.out_ann, [ANN_SHIFTED, [protocol['STOP'][0]]]) - self.put(self.out_ann, [ANN_SHIFTED_SHORT, [protocol['STOP'][1]]]) - - self.state = FIND_START + self.state = 'FIND START' self.is_repeat_start = 0 self.wr = -1 @@ -208,8 +198,7 @@ class Decoder(srd.Decoder): super(Decoder, self).put(self.startsample, self.samplenum, output_id, data) def decode(self, ss, es, data): - for samplenum, (scl, sda) in data: - self.samplenum = samplenum + for (self.samplenum, (scl, sda)) in data: # First sample: Save SCL/SDA value. if self.oldscl == None: @@ -220,19 +209,22 @@ class Decoder(srd.Decoder): # TODO: Wait until the bus is idle (SDA = SCL = 1) first? # State machine. - if self.state == FIND_START: + if self.state == 'FIND START': if self.is_start_condition(scl, sda): self.found_start(scl, sda) - elif self.state == FIND_ADDRESS: + elif self.state == 'FIND ADDRESS': if self.is_data_bit(scl, sda): self.found_address_or_data(scl, sda) - elif self.state == FIND_DATA: + elif self.state == 'FIND DATA': if self.is_data_bit(scl, sda): self.found_address_or_data(scl, sda) elif self.is_start_condition(scl, sda): self.found_start(scl, sda) elif self.is_stop_condition(scl, sda): self.found_stop(scl, sda) + elif self.state == 'FIND ACK': + if self.is_data_bit(scl, sda): + self.get_ack(scl, sda) else: raise Exception('Invalid state %d' % self.STATE)