summaryrefslogtreecommitdiff
path: root/decoders
diff options
context:
space:
mode:
Diffstat (limited to 'decoders')
-rw-r--r--decoders/i2c/pd.py46
1 files changed, 38 insertions, 8 deletions
diff --git a/decoders/i2c/pd.py b/decoders/i2c/pd.py
index 7309226..36c8d1e 100644
--- a/decoders/i2c/pd.py
+++ b/decoders/i2c/pd.py
@@ -113,6 +113,7 @@ class Decoder(srd.Decoder):
self.bitcount = 0
self.databyte = 0
self.is_write = None
+ self.rem_addr_bytes = None
self.is_repeat_start = False
self.state = 'FIND START'
self.pdu_start = None
@@ -150,6 +151,7 @@ class Decoder(srd.Decoder):
self.bitcount = self.databyte = 0
self.is_repeat_start = True
self.is_write = None
+ self.rem_addr_bytes = None
self.data_bits = []
# Gather 8 bits of data plus the ACK/NACK bit.
@@ -181,10 +183,31 @@ class Decoder(srd.Decoder):
d = self.databyte
if self.state == 'FIND ADDRESS':
- # The READ/WRITE bit is only in address bytes, not data bytes.
- self.is_write = False if (self.databyte & 1) else True
- if self.options['address_format'] == 'shifted':
- d = d >> 1
+ # The READ/WRITE bit is only in the first address byte, not
+ # in data bytes. Address bit pattern 0b1111_0xxx means that
+ # this is a 10bit slave address, another byte follows. Get
+ # the R/W direction and the address bytes count from the
+ # first byte in the I2C transfer.
+ addr_byte = d
+ if self.rem_addr_bytes is None:
+ if (addr_byte & 0xf8) == 0xf0:
+ self.rem_addr_bytes = 2
+ self.slave_addr_7 = None
+ self.slave_addr_10 = addr_byte & 0x06
+ self.slave_addr_10 <<= 7
+ else:
+ self.rem_addr_bytes = 1
+ self.slave_addr_7 = addr_byte >> 1
+ self.slave_addr_10 = None
+ is_seven = self.slave_addr_7 is not None
+ if self.is_write is None:
+ read_bit = bool(addr_byte & 1)
+ shift_seven = self.options['address_format'] == 'shifted'
+ if is_seven and shift_seven:
+ d = d >> 1
+ self.is_write = False if read_bit else True
+ else:
+ self.slave_addr_10 |= addr_byte
bin_class = -1
if self.state == 'FIND ADDRESS' and self.is_write:
@@ -210,7 +233,7 @@ class Decoder(srd.Decoder):
for bit in self.data_bits:
self.put(bit[1], bit[2], self.out_ann, [5, ['%d' % bit[0]]])
- if cmd.startswith('ADDRESS'):
+ if cmd.startswith('ADDRESS') and is_seven:
self.ss, self.es = self.samplenum, self.samplenum + self.bitwidth
w = ['Write', 'Wr', 'W'] if self.is_write else ['Read', 'Rd', 'R']
self.putx([proto[cmd][0], w])
@@ -230,9 +253,16 @@ class Decoder(srd.Decoder):
cmd = 'NACK' if (sda == 1) else 'ACK'
self.putp([cmd, None])
self.putx([proto[cmd][0], proto[cmd][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'
+ # Slave addresses can span one or two bytes, before data bytes
+ # follow. There can be an arbitrary number of data bytes. Stick
+ # with getting more address bytes if applicable, or enter or
+ # remain in the data phase of the transfer otherwise.
+ if self.rem_addr_bytes:
+ self.rem_addr_bytes -= 1
+ if self.rem_addr_bytes:
+ self.state = 'FIND ADDRESS'
+ else:
+ self.state = 'FIND DATA'
def handle_stop(self, pins):
# Meta bitrate