Signals change during the rising edge of the LPC clock and are stable
during its falling edge. So we sample the data signals on LCLK falling
edge, but use its rising edge times to delimit the fields.
---
 decoders/lpc/pd.py | 117 +++++++++++++++++++++------------------------
 1 file changed, 54 insertions(+), 63 deletions(-)

diff --git a/decoders/lpc/pd.py b/decoders/lpc/pd.py
index 2a88e30..8ab2faf 100644
--- a/decoders/lpc/pd.py
+++ b/decoders/lpc/pd.py
@@ -141,15 +141,15 @@ def __init__(self):
 
     def reset(self):
         self.state = 'IDLE'
-        self.oldlclk = -1
         self.lad = -1
+        self.lad_bits = None
+        self.lframe = -1
         self.addr = 0
         self.cur_nibble = 0
         self.cycle_type = -1
         self.databyte = 0
         self.tarcount = 0
         self.synccount = 0
-        self.oldpins = None
         self.ss_block = self.es_block = None
 
     def start(self):
@@ -158,38 +158,32 @@ def start(self):
     def putb(self, data):
         self.put(self.ss_block, self.es_block, self.out_ann, data)
 
-    def handle_get_start(self, lad, lad_bits, lframe):
+    def handle_get_start(self):
         # LAD[3:0]: START field (1 clock cycle).
 
+        # LFRAME# is de-asserted (high). Last START field was last clock cycle,
+        # we are now reading the CYCTYPE + DIR field.
+        if self.lframe == 1:
+            self.state = 'GET CT/DR'
+            return
+
         # The last value of LAD[3:0] before LFRAME# gets de-asserted is what
         # the peripherals must use. However, the host can keep LFRAME# asserted
         # multiple clocks, and we output all START fields that occur, even
         # though the peripherals are supposed to ignore all but the last one.
         self.es_block = self.samplenum
-        self.putb([1, [fields['START'][lad], 'START', 'St', 'S']])
-        self.ss_block = self.samplenum
-
-        # Output a warning if LAD[3:0] changes while LFRAME# is low.
-        # TODO
-        if (self.lad != -1 and self.lad != lad):
-            self.putb([0, ['LAD[3:0] changed while LFRAME# was asserted']])
-
-        # LFRAME# is asserted (low). Wait until it gets de-asserted again
-        # (the host is allowed to keep it asserted multiple clocks).
-        if lframe != 1:
-            return
-
+        self.putb([1, [fields['START'][self.lad], 'START', 'St', 'S']])
         self.start_field = self.lad
-        self.state = 'GET CT/DR'
+        self.ss_block = self.samplenum
 
-    def handle_get_ct_dr(self, lad, lad_bits):
+    def handle_get_ct_dr(self):
         # LAD[3:0]: Cycle type / direction field (1 clock cycle).
 
-        self.cycle_type = fields['CT_DR'].get(lad, 'Reserved / unknown')
+        self.cycle_type = fields['CT_DR'].get(self.lad, 'Reserved / unknown')
 
         # TODO: Warning/error on invalid cycle types.
         if 'Reserved' in self.cycle_type:
-            self.putb([0, ['Invalid cycle type (%s)' % lad_bits]])
+            self.putb([0, ['Invalid cycle type (%s)' % self.lad_bits]])
 
         self.es_block = self.samplenum
         self.putb([2, ['Cycle type: %s' % self.cycle_type]])
@@ -199,7 +193,7 @@ def handle_get_ct_dr(self, lad, lad_bits):
         self.addr = 0
         self.cur_nibble = 0
 
-    def handle_get_addr(self, lad, lad_bits):
+    def handle_get_addr(self):
         # LAD[3:0]: ADDR field (4/8/0 clock cycles).
 
         # I/O cycles: 4 ADDR clocks. Memory cycles: 8 ADDR clocks.
@@ -213,7 +207,7 @@ def handle_get_addr(self, lad, lad_bits):
 
         # Addresses are driven MSN-first.
         offset = ((addr_nibbles - 1) - self.cur_nibble) * 4
-        self.addr |= (lad << offset)
+        self.addr |= (self.lad << offset)
 
         # Continue if we haven't seen all ADDR cycles, yet.
         if (self.cur_nibble < addr_nibbles - 1):
@@ -228,20 +222,20 @@ def handle_get_addr(self, lad, lad_bits):
         self.state = 'GET TAR'
         self.tar_count = 0
 
-    def handle_get_tar(self, lad, lad_bits):
+    def handle_get_tar(self):
         # LAD[3:0]: First TAR (turn-around) field (2 clock cycles).
 
         self.es_block = self.samplenum
-        self.putb([4, ['TAR, cycle %d: %s' % (self.tarcount, lad_bits)]])
+        self.putb([4, ['TAR, cycle %d: %s' % (self.tarcount, self.lad_bits)]])
         self.ss_block = self.samplenum
 
         # On the first TAR clock cycle LAD[3:0] is driven to 1111 by
         # either the host or peripheral. On the second clock cycle,
         # the host or peripheral tri-states LAD[3:0], but its value
         # should still be 1111, due to pull-ups on the LAD lines.
-        if lad_bits != '1111':
+        if self.lad_bits != '1111':
             self.putb([0, ['TAR, cycle %d: %s (expected 1111)' % \
-                           (self.tarcount, lad_bits)]])
+                           (self.tarcount, self.lad_bits)]])
 
         if (self.tarcount != 1):
             self.tarcount += 1
@@ -250,11 +244,11 @@ def handle_get_tar(self, lad, lad_bits):
         self.tarcount = 0
         self.state = 'GET SYNC'
 
-    def handle_get_sync(self, lad, lad_bits):
+    def handle_get_sync(self):
         # LAD[3:0]: SYNC field (1-n clock cycles).
 
-        self.sync_val = lad_bits
-        self.cycle_type = fields['SYNC'].get(lad, 'Reserved / unknown')
+        self.sync_val = self.lad_bits
+        self.cycle_type = fields['SYNC'].get(self.lad, 'Reserved / unknown')
 
         # TODO: Warnings if reserved value are seen?
         if 'Reserved' in self.cycle_type:
@@ -270,14 +264,14 @@ def handle_get_sync(self, lad, lad_bits):
         self.cycle_count = 0
         self.state = 'GET DATA'
 
-    def handle_get_data(self, lad, lad_bits):
+    def handle_get_data(self):
         # LAD[3:0]: DATA field (2 clock cycles).
 
         # Data is driven LSN-first.
         if (self.cycle_count == 0):
-            self.databyte = lad
+            self.databyte = self.lad
         elif (self.cycle_count == 1):
-            self.databyte |= (lad << 4)
+            self.databyte |= (self.lad << 4)
         else:
             raise Exception('Invalid cycle_count: %d' % self.cycle_count)
 
@@ -292,20 +286,20 @@ def handle_get_data(self, lad, lad_bits):
         self.cycle_count = 0
         self.state = 'GET TAR2'
 
-    def handle_get_tar2(self, lad, lad_bits):
+    def handle_get_tar2(self):
         # LAD[3:0]: Second TAR field (2 clock cycles).
 
         self.es_block = self.samplenum
-        self.putb([7, ['TAR, cycle %d: %s' % (self.tarcount, lad_bits)]])
+        self.putb([7, ['TAR, cycle %d: %s' % (self.tarcount, self.lad_bits)]])
         self.ss_block = self.samplenum
 
         # On the first TAR clock cycle LAD[3:0] is driven to 1111 by
         # either the host or peripheral. On the second clock cycle,
         # the host or peripheral tri-states LAD[3:0], but its value
         # should still be 1111, due to pull-ups on the LAD lines.
-        if lad_bits != '1111':
+        if self.lad_bits != '1111':
             self.putb([0, ['Warning: TAR, cycle %d: %s (expected 1111)'
-                           % (self.tarcount, lad_bits)]])
+                           % (self.tarcount, self.lad_bits)]])
 
         if (self.tarcount != 1):
             self.tarcount += 1
@@ -315,51 +309,48 @@ def handle_get_tar2(self, lad, lad_bits):
         self.state = 'IDLE'
 
     def decode(self):
-        conditions = [{i: 'e'} for i in range(6)]
+        conditions = {1: 'e'} # LCLK edge
         while True:
             pins = self.wait(conditions)
 
-            # Store current pin values for the next round.
-            self.oldpins = pins
-
             # Get individual pin values into local variables.
             (lframe, lclk, lad0, lad1, lad2, lad3) = pins[:6]
             (lreset, ldrq, serirq, clkrun, lpme, lpcpd, lsmi) = pins[6:]
 
-            # Only look at the signals upon rising LCLK edges. The LPC clock
-            # is the same as the PCI clock (which is sampled at rising edges).
-            if not (self.oldlclk == 0 and lclk == 1):
-                self.oldlclk = lclk
+            # Signals change during the rising edge of the LPC clock and are
+            # stable during its falling edge. So we sample the LAD[3:0] data
+            # and LFRAME# on the falling edge, but use the rising edges time
+            # to delimit the fields.
+            if lclk == 0:
+                # Store LAD and LFRAME# to use them on next LCLK rising edge
+                self.lad = (lad3 << 3) | (lad2 << 2) | (lad1 << 1) | lad0
+                self.lad_bits = '{:04b}'.format(self.lad)
+                self.lframe = lframe
+                # self.putb([0, ['LAD: %s' % self.lad_bits]])
                 continue
 
-            # Store LAD[3:0] bit values (one nibble) in local variables.
-            # Most (but not all) states need this.
-            if self.state != 'IDLE':
-                lad = (lad3 << 3) | (lad2 << 2) | (lad1 << 1) | lad0
-                lad_bits = '{:04b}'.format(lad)
-                # self.putb([0, ['LAD: %s' % lad_bits]])
-
             # TODO: Only memory read/write is currently supported/tested.
 
             # State machine
             if self.state == 'IDLE':
                 # A valid LPC cycle starts with LFRAME# being asserted (low).
-                if lframe != 0:
+                if self.lframe != 0:
+                    self.ss_block = self.samplenum
                     continue
-                self.ss_block = self.samplenum
                 self.state = 'GET START'
-                self.lad = -1
-            elif self.state == 'GET START':
-                self.handle_get_start(lad, lad_bits, lframe)
-            elif self.state == 'GET CT/DR':
-                self.handle_get_ct_dr(lad, lad_bits)
+                # FALLTHROUGH
+            if self.state == 'GET START':
+                self.handle_get_start()
+                # FALLTHROUGH
+            if self.state == 'GET CT/DR':
+                self.handle_get_ct_dr()
             elif self.state == 'GET ADDR':
-                self.handle_get_addr(lad, lad_bits)
+                self.handle_get_addr()
             elif self.state == 'GET TAR':
-                self.handle_get_tar(lad, lad_bits)
+                self.handle_get_tar()
             elif self.state == 'GET SYNC':
-                self.handle_get_sync(lad, lad_bits)
+                self.handle_get_sync()
             elif self.state == 'GET DATA':
-                self.handle_get_data(lad, lad_bits)
+                self.handle_get_data()
             elif self.state == 'GET TAR2':
-                self.handle_get_tar2(lad, lad_bits)
+                self.handle_get_tar2()
-- 
2.30.2


_______________________________________________
sigrok-devel mailing list
sigrok-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/sigrok-devel

Reply via email to