changeset 8:074e860d7d31

jtagdev is a desktop client to communicate with jtag device through Arduino.
author Thinker K.F. Li <thinker@branda.to>
date Sun, 22 Feb 2009 22:30:20 +0800
parents 61f27549de57
children 705da39cdf91
files py_avrjtag/cmd_proto.py py_avrjtag/jtagdev.py
diffstat 2 files changed, 168 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/py_avrjtag/cmd_proto.py	Sun Feb 22 14:20:57 2009 +0800
+++ b/py_avrjtag/cmd_proto.py	Sun Feb 22 22:30:20 2009 +0800
@@ -66,3 +66,6 @@
             (self.__class__.__name__, self.seq, self.code, repr(self.data))
     pass
 
+def prepend_nbits(nbits, data):
+    r = chr(nbits & 0xff) + chr(nbits >> 8) + data
+    return r
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/py_avrjtag/jtagdev.py	Sun Feb 22 22:30:20 2009 +0800
@@ -0,0 +1,165 @@
+import tms_ptns
+import cmd_proto
+
+class jtagdev(object):
+    ST_REST = 0
+    ST_IDLE = 1
+    ST_SHIFT_DR = 2
+    ST_SHIFT_IR = 3
+    
+    def __init__(self, fo):
+        self.fo = fo
+        self.state = self.IDLE
+        self.seq = 0
+        pass
+
+    def _send_cmd(self, code, data):
+        cmd = cmd_proto.cmd(self.seq, code, data)
+        frame = cmd.to_frame()
+
+        self.fo.write(frame)
+        self.fo.flush()
+        pass
+
+    def _send_nbits_data_cmd(self, code, nbits, data):
+        nbits_data = cmd_proto.prepend_nbits(nbits, data)
+        self._send_cmd(code, nbits_data)
+        pass
+
+    def _send_tms(self, ptn, nbits):
+        self._send_nbits_data_cmd(cmd_proto.CPCMD_SHIFT_TMS,
+                                  nbits, ptn)
+        pass
+
+    def wait_reply(self, tmo=None):
+        import select
+        
+        if tmo is None:
+            select.select((self.fo,), (), ())
+        else:
+            select.select((self.fo,), (), (), tmo)
+            pass
+        frame = self.fo.read()
+        cmd = cmd_proto.cmd()
+        cmd.from_frame(frame)
+        return cmd
+
+    def idle(self):
+        self.seq = (self.seq + 1) % 256
+        
+        ptn, nbits = tms_ptns.TMS_IDLE_SEQ
+        self.send_tms(ptn, nbits)
+        
+        self.state = self.ST_IDLE
+        pass
+
+    def go_shift_IR(self):
+        if self.state == self.ST_SHIFT_IR:
+            return
+        
+        if self.state == self.ST_IDLE:
+            ptn, ptn_nbits = tms_ptns.TMS_CAP_IR
+            self.send_tms(ptn, nbits)
+        elif self.state == self.ST_SHIFT_DR:
+            ptn, ptn_nbits = tms_ptns.TMS_SHIFT_DR_2_CAP_IR
+            self.send_tms(ptn, nbits)
+        else:
+            raise RuntimeError, 'Transite to shift IR state from invalid state'
+        self.state = self.ST_SHIFT_IR
+        pass
+
+    def go_shift_DR(self):
+        if self.state == self.ST_SHIFT_DR:
+            return
+        
+        if self.state == self.ST_IDLE:
+            ptn, ptn_nbits = tms_ptns.TMS_CAP_DR
+            self.send_tms(ptn, nbits)
+        elif self.state == self.ST_SHIFT_IR:
+            ptn, ptn_nbits = tms_ptns.TMS_SHIFT_IR_2_CAP_DR
+            self.send_tms(ptn, nbits)
+        else:
+            raise RuntimeError, 'Transite to shift DR state from invalid state'
+            pass
+        self.state = self.ST_SHIFT_DR
+        pass
+
+    def shift_IR(self, data, nbits):
+        self.seq = (self.seq + 1) % 256
+
+        if self.state != self.ST_SHIFT_IR:
+            raise RuntimeError, 'Invalid state'
+
+        self._send_nbits_data_cmd(cmd_proto.CPCMD_SHIFT_TDI,
+                                  nbits, data)
+        pass
+
+    def shift_DR(self, data, nbits):
+        self.seq = (self.seq + 1) % 256
+
+        if self.state != self.ST_SHIFT_DR:
+            raise RuntimeError, 'Invalid state'
+
+        self._send_nbits_data_cmd(cmd_proto.CPCMD_SHIFT_TDI,
+                                  nbits, data)
+        pass
+
+    def shift_DR_n_out(self, data, nbits):
+        self.seq = (self.seq + 1) % 256
+
+        if self.state != self.ST_SHIFT_DR:
+            raise RuntimeError, 'Invalid state'
+
+        self._send_nbits_data_cmd(cmd_proto.CPCMD_SHIFT_TDI_TDO,
+                                  nbits, data)
+        pass
+
+    def reset(self):
+        self._send_cmd(cmd_proto.CPCMD_TRST, '')
+        self.state = self.ST_RESET
+        pass
+    pass
+
+def _extract_nbits_data(nbits_data):
+    nbits = ord(nbits_data[0]) | (ord(nbits_data[1] << 8))
+    return nbits, nbits_data[2:]
+
+def _get_bit(data, bit_idx):
+    byte_off = bit_idx / 8
+    bit_off = bit_idx % 8
+    return (ord(data[byte_off]) >> bit_off) & 0x1
+
+def identify_components(dev):
+    dev.go_shift_IR()
+    reply = dev.wait_reply()
+    if reply.code != cmd_proto.CPCMD_ACK:
+        raise RutimeError, 'invliad reply code 0x%02x' % (reply.code)
+
+    dev.go_shift_DR()
+    dev.shift_DR('\xff' * 253, 253 * 8)
+    reply = dev.wait_reply()
+    if reply.code != cmd_proto.CPCMD_DATA:
+        raise RutimeError, 'invliad reply code 0x%02x' % (reply.code)
+
+    nbits, data = _extract_nbits_data(reply.data)
+    
+    components = []
+    i = 0
+    while i < nbits:
+        bit = _get_bit(data, i)
+        if bit == 0:
+            components.append(0)
+            i = i + 1
+        else:
+            comp_id = 0
+            for j in range(32):
+                bit = _get_bit(data, i + j)
+                comp_id = comp_id | (bit << j)
+                pass
+            if comp_id == 0xffffffff:
+                break
+            components.append(comp_id)
+            i = i + 32
+            pass
+        pass
+    return components