summaryrefslogtreecommitdiff
path: root/decoders
diff options
context:
space:
mode:
authorUwe Hermann <uwe@hermann-uwe.de>2012-06-28 21:43:12 +0200
committerUwe Hermann <uwe@hermann-uwe.de>2012-07-04 01:03:13 +0200
commit48eee789a15ebd4c26d469a29dd79e7971f031fe (patch)
tree0ce5b787b9a753228b9243a31a169d52824ce09b /decoders
parent44f7ba18ee64fc89d0f69619076ff28a8bc6b31a (diff)
downloadlibsigrokdecode-48eee789a15ebd4c26d469a29dd79e7971f031fe.tar.gz
libsigrokdecode-48eee789a15ebd4c26d469a29dd79e7971f031fe.zip
srd: i2cfilter: Output actual I2C packets.
Change this PD from an I2C->databytes converter/filter to an actual pure I2C filter in the sense that both input and output is a valid I2C protocol stream. Also, change the EDID decoder accordingly, to use the new i2cfilter output.
Diffstat (limited to 'decoders')
-rw-r--r--decoders/edid/edid.py8
-rw-r--r--decoders/i2cfilter/__init__.py14
-rw-r--r--decoders/i2cfilter/i2cfilter.py78
3 files changed, 59 insertions, 41 deletions
diff --git a/decoders/edid/edid.py b/decoders/edid/edid.py
index 21ab008..a03fe67 100644
--- a/decoders/edid/edid.py
+++ b/decoders/edid/edid.py
@@ -105,8 +105,12 @@ class Decoder(srd.Decoder):
pass
def decode(self, ss, es, data):
- if type(data) != int:
- raise Exception('malformed ddc2 input: expected 1 byte')
+ cmd, data = data
+
+ # We only care about actual data bytes that are read (for now).
+ if cmd != 'DATA READ':
+ return
+
self.cnt += 1
self.sn.append([ss, es])
self.cache.append(data)
diff --git a/decoders/i2cfilter/__init__.py b/decoders/i2cfilter/__init__.py
index e9a9ab6..6443f5b 100644
--- a/decoders/i2cfilter/__init__.py
+++ b/decoders/i2cfilter/__init__.py
@@ -20,15 +20,15 @@
'''
Generic I2C filtering protocol decoder.
-Takes input from the I2C protocol decoder and filters out traffic from/to
-a single address on the I2C bus.
+Takes input from the I2C protocol decoder and removes all traffic
+except that from/to the specified slave address and/or direction.
-It then outputs the filtered data one byte at a time as OUTPUT_PROTO up the
-protocol decoder stack. No annotations are output.
+It then outputs the filtered data again as OUTPUT_PROTO of type/format 'i2c'
+(up the protocol decoder stack). No annotations are output.
-The I2C address to filter out should be passed in as an option 'address', as
-an integer. A specific read or write operation can be selected with the
-'direction' option, which should be 'read' or 'write'.
+The I2C slave address to filter out should be passed in as an option
+'address', as an integer. A specific read or write operation can be selected
+with the 'direction' option, which should be 'read', 'write', or 'both'.
Both of these are optional; if no options are specified the entire payload
of the I2C session will be output.
diff --git a/decoders/i2cfilter/i2cfilter.py b/decoders/i2cfilter/i2cfilter.py
index 64010cb..9c9c43a 100644
--- a/decoders/i2cfilter/i2cfilter.py
+++ b/decoders/i2cfilter/i2cfilter.py
@@ -2,6 +2,7 @@
## This file is part of the sigrok project.
##
## Copyright (C) 2012 Bert Vermeulen <bert@biot.com>
+## Copyright (C) 2012 Uwe Hermann <uwe@hermann-uwe.de>
##
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
@@ -19,6 +20,8 @@
# Generic I2C filtering protocol decoder
+# TODO: Support for filtering out multiple slave/direction pairs?
+
import sigrokdecode as srd
class Decoder(srd.Decoder):
@@ -29,57 +32,68 @@ class Decoder(srd.Decoder):
desc = 'Filter out addresses/directions in an I2C stream.'
license = 'gplv3+'
inputs = ['i2c']
- outputs = []
+ outputs = ['i2c']
probes = []
optional_probes = []
options = {
'address': ['Address to filter out of the I2C stream', 0],
- 'direction': ['Direction to filter (read/write)', '']
+ 'direction': ['Direction to filter (read/write/both)', 'both']
}
annotations = []
def __init__(self, **kwargs):
self.state = None
+ self.curslave = -1
+ self.curdirection = None
+ self.packets = [] # Local cache of I2C packets
def start(self, metadata):
- self.out_proto = self.add(srd.OUTPUT_PROTO, 'i2cdata')
- if self.options['direction'] not in ('', 'read', 'write'):
- raise Exception('Invalid direction: expected "read" or "write"')
+ self.out_proto = self.add(srd.OUTPUT_PROTO, 'i2c')
+ if self.options['address'] not in range(0, 127 + 1):
+ raise Exception('Invalid slave (must be 0..127).')
+ if self.options['direction'] not in ('both', 'read', 'write'):
+ raise Exception('Invalid direction (valid: read/write/both).')
def report(self):
pass
+ # Grab I2C packets into a local cache, until an I2C STOP condition
+ # packet comes along. At some point before that STOP condition, there
+ # will have been an ADDRESS READ or ADDRESS WRITE which contains the
+ # I2C address of the slave that the master wants to talk to.
+ # If that slave shall be filtered, output the cache (all packets from
+ # START to STOP) as proto 'i2c', otherwise drop it.
def decode(self, ss, es, data):
- try:
- cmd, data = data
- except Exception as e:
- raise Exception('Malformed I2C input: %s' % str(e)) from e
- # Whichever state we're in, these always reset the state machine.
- # This should make it easier to deal with corrupt data etc.
- if cmd in ('START', 'START REPEAT'):
- self.state = 'start'
- return
- if cmd == 'STOP':
- self.state = None
- return
- if cmd in ('ACK', 'NACK'):
- # Don't care, we just want data.
- return
+ cmd, databyte = data
+
+ # Add the I2C packet to our local cache.
+ self.packets.append([ss, es, data])
- if self.state == 'start':
- # Start of a transfer, see if we want this one.
- if cmd == 'ADDRESS READ' and self.options['direction'] == 'write':
+ if cmd in ('ADDRESS READ', 'ADDRESS WRITE'):
+ self.curslave = databyte
+ self.curdirection = cmd[8:].lower()
+ elif cmd in ('STOP', 'START REPEAT'):
+ # If this chunk was not for the correct slave, drop it.
+ if self.options['address'] == 0:
+ pass
+ elif self.curslave != self.options['address']:
+ self.packets = []
return
- elif cmd == 'ADDRESS WRITE' and self.options['direction'] == 'read':
+
+ # If this chunk was not in the right direction, drop it.
+ if self.options['direction'] == 'both':
+ pass
+ elif self.options['direction'] != self.curdirection:
+ self.packets = []
return
- elif cmd in ('ADDRESS READ', 'ADDRESS WRITE'):
- if self.options['address'] in (0, data):
- # We want this tranfer.
- self.state = 'transfer'
- elif self.state == 'transfer':
- if cmd in ('DATA READ', 'DATA WRITE'):
- self.put(ss, es, self.out_proto, data)
+
+ # TODO: START->STOP chunks with both read and write (Repeat START)
+ # Otherwise, send out the whole chunk of I2C packets.
+ for p in self.packets:
+ self.put(p[0], p[1], self.out_proto, p[2])
+
+ self.packets = []
else:
- raise Exception('Invalid state: %s' % self.state)
+ pass # Do nothing, only add the I2C packet to our cache.