]> sigrok.org Git - libsigrokdecode.git/blobdiff - decoders/jtag/jtag.py
srd: JTAG: Also show the bitstrings in hex (for now).
[libsigrokdecode.git] / decoders / jtag / jtag.py
index 828cbef52f68d8439ec1a8d3f24c91f388531929..df16d2b28a2837ae15b496227a555c26d2210146 100644 (file)
@@ -27,7 +27,7 @@ class Decoder(srd.Decoder):
     id = 'jtag'
     name = 'JTAG'
     longname = 'Joint Test Action Group'
-    desc = 'TODO.'
+    desc = 'Protocol for testing, debugging, and flashing ICs.'
     license = 'gplv2+'
     inputs = ['logic']
     outputs = ['jtag']
@@ -36,17 +36,21 @@ class Decoder(srd.Decoder):
         {'id': 'tdo',  'name': 'TDO',  'desc': 'Test data output'},
         {'id': 'tck',  'name': 'TCK',  'desc': 'Test clock'},
         {'id': 'tms',  'name': 'TMS',  'desc': 'Test mode select'},
-        {'id': 'trst', 'name': 'TRST', 'desc': 'Test reset'},
     ]
-    optional_probes = [] # TODO? SRST?
+    optional_probes = [
+        # {'id': 'trst', 'name': 'TRST#', 'desc': 'Test reset'},
+        # {'id': 'srst', 'name': 'SRST#', 'desc': 'System reset'},
+    ]
     options = {}
     annotations = [
         ['ASCII', 'TODO: description'],
     ]
 
     def __init__(self, **kwargs):
-        self.state = 'TEST-LOGIC-RESET'
-        self.oldpins = (-1, -1, -1, -1, -1)
+        # self.state = 'TEST-LOGIC-RESET'
+        self.state = 'RUN-TEST/IDLE'
+        self.oldstate = None
+        self.oldpins = (-1, -1, -1, -1)
         self.oldtck = -1
         self.bits_tdi = []
         self.bits_tdo = []
@@ -59,6 +63,8 @@ class Decoder(srd.Decoder):
         pass
 
     def advance_state_machine(self, tms):
+        self.oldstate = self.state
+
         # Intro "tree"
         if self.state == 'TEST-LOGIC-RESET':
             self.state = 'TEST-LOGIC-RESET' if (tms) else 'RUN-TEST/IDLE'
@@ -100,35 +106,45 @@ class Decoder(srd.Decoder):
         else:
             raise Exception('Invalid state: %s' % self.state)
 
-    def handle_rising_tck_edge(self, tdi, tdo, tck, tms, trst):
-        # In SHIFT-DR/SHIFT-IR (on rising TCK edges) we collect TDI values.
-        if self.state in ('SHIFT-DR', 'SHIFT-IR'):
-            self.bits_tdi.append(tdi)
-
-        # Output all TDI bits.
-        elif self.state in ('EXIT1-DR', 'EXIT1-IR'):
-            s = self.state[-2:] + ' TDI: ' + ''.join(map(str, self.bits_tdi))
-            s += ', ' + str(len(self.bits_tdi)) + ' bits'
-            self.put(self.ss, self.es, self.out_ann, [0, [s]])
-            self.bits_tdi = []
-
+    def handle_rising_tck_edge(self, tdi, tdo, tck, tms):
         # Rising TCK edges always advance the state machine.
         self.advance_state_machine(tms)
 
         # Output the state we just switched to.
         self.put(self.ss, self.es, self.out_ann,
                  [0, ['New state: %s' % self.state]])
+        self.put(self.ss, self.es, self.out_proto,
+                 ['NEW STATE', self.state])
+
+        # If we went from SHIFT-IR to SHIFT-IR, or SHIFT-DR to SHIFT-DR,
+        # collect the current TDI/TDO values (upon rising TCK edge).
+        if self.state.startswith('SHIFT-') and self.oldstate == self.state:
+            self.bits_tdi.insert(0, tdi)
+            self.bits_tdo.insert(0, tdo)
+            # TODO: ANN/PROTO output.
+            # self.put(self.ss, self.es, self.out_ann,
+            #          [0, ['TDI add: ' + str(tdi)]])
+            # self.put(self.ss, self.es, self.out_ann,
+            #          [0, ['TDO add: ' + str(tdo)]])
+
+        # Output all TDI/TDO bits if we just switched from SHIFT-* to EXIT1-*.
+        if self.oldstate.startswith('SHIFT-') and \
+           self.state.startswith('EXIT1-'):
+
+            t = self.state[-2:] + ' TDI'
+            b = ''.join(map(str, self.bits_tdi))
+            h = ' (0x%x' % int('0b' + b, 2) + ')'
+            s = t + ': ' + b + h + ', ' + str(len(self.bits_tdi)) + ' bits'
+            self.put(self.ss, self.es, self.out_ann, [0, [s]])
+            self.put(self.ss, self.es, self.out_proto, [t, b])
+            self.bits_tdi = []
 
-    def handle_falling_tck_edge(self, tdi, tdo, tck, tms, trst):
-        # In SHIFT-DR/SHIFT-IR (on falling TCK edges) we collect TDO values.
-        if self.state in ('SHIFT-DR', 'SHIFT-IR'):
-            self.bits_tdo.append(tdo)
-
-        # Output all TDO bits.
-        if self.state in ('EXIT1-DR', 'EXIT1-IR'):
-            s = self.state[-2:] + ' TDO: ' + ''.join(map(str, self.bits_tdo))
-            s += ', ' + str(len(self.bits_tdo)) + ' bits'
+            t = self.state[-2:] + ' TDO'
+            b = ''.join(map(str, self.bits_tdo))
+            h = ' (0x%x' % int('0b' + b, 2) + ')'
+            s = t + ': ' + b + h + ', ' + str(len(self.bits_tdo)) + ' bits'
             self.put(self.ss, self.es, self.out_ann, [0, [s]])
+            self.put(self.ss, self.es, self.out_proto, [t, b])
             self.bits_tdo = []
 
     def decode(self, ss, es, data):
@@ -142,8 +158,8 @@ class Decoder(srd.Decoder):
             self.oldpins = pins
 
             # Get individual pin values into local variables.
-            # TODO: Handle optional pins.
-            (tdi, tdo, tck, tms, trst) = pins
+            # TODO: Handle optional pins (TRST, SRST).
+            (tdi, tdo, tck, tms) = pins
 
             # We only care about TCK edges (either rising or falling).
             if (self.oldtck == tck):
@@ -152,10 +168,12 @@ class Decoder(srd.Decoder):
             # Store start/end sample for later usage.
             self.ss, self.es = ss, es
 
+            # self.put(self.ss, self.es, self.out_ann,
+            #     [0, ['tdi:%s, tdo:%s, tck:%s, tms:%s' \
+            #          % (tdi, tdo, tck, tms)]])
+
             if (self.oldtck == 0 and tck == 1):
-                self.handle_rising_tck_edge(tdi, tdo, tck, tms, trst)
-            elif (self.oldtck == 1 and tck == 0):
-                self.handle_falling_tck_edge(tdi, tdo, tck, tms, trst)
+                self.handle_rising_tck_edge(tdi, tdo, tck, tms)
 
             self.oldtck = tck