changeset 10:cc106f278d7d

Get identify of components
author Thinker K.F. Li <thinker@branda.to>
date Tue, 24 Feb 2009 13:32:04 +0800
parents 705da39cdf91
children 520f45b72ba7
files include/cmd_proto.h include/jtag.h py_avrjtag/cmd_proto.py py_avrjtag/cp_ping.py py_avrjtag/jtagdev.py py_avrjtag/tms_ptns.py src/avr_jtag.c src/cmd_proto.c src/jtag.c tests/identify.py
diffstat 10 files changed, 218 insertions(+), 136 deletions(-) [+]
line wrap: on
line diff
--- a/include/cmd_proto.h	Sun Feb 22 22:43:26 2009 +0800
+++ b/include/cmd_proto.h	Tue Feb 24 13:32:04 2009 +0800
@@ -21,7 +21,7 @@
     int seq;
     cp_ccode_t code;
     int data_sz;
-    char *data;
+    unsigned char *data;
 } cp_cmd_t;
 
 typedef struct {
@@ -31,7 +31,7 @@
     int seq;
     int cnt;
     int len;
-    char *bufs[2];
+    unsigned char *bufs[2];
 } cmd_proto_t;
 
 extern cmd_proto_t *cmd_proto_new(void);
@@ -40,7 +40,7 @@
 /*
  * \return size of filled command.
  */
-extern int cmd_proto_cmd_fill(char *buf, int seq,
+extern int cmd_proto_cmd_fill(unsigned char *buf, int seq,
 			      cp_ccode_t code, int data_sz);
 extern cp_cmd_t BAD_CMD;
 extern cp_cmd_t CSUM_ERR_CMD;
--- a/include/jtag.h	Sun Feb 22 22:43:26 2009 +0800
+++ b/include/jtag.h	Tue Feb 24 13:32:04 2009 +0800
@@ -13,8 +13,9 @@
 
 extern void jtag_init(void);
 extern void jtag_trst(void);
-extern void jtag_tms(char *buf, int nbits);
-extern void jtag_shift(char *buf, int nbits);
-extern void jtag_shift_inout(char *ibuf, char *obuf, int nbits);
+extern void jtag_tms(unsigned char *buf, int nbits);
+extern void jtag_shift(unsigned char *buf, int nbits);
+extern void jtag_shift_inout(unsigned char *ibuf, unsigned char *obuf,
+			     int nbits);
 
 #endif /* __JTAG_H_ */
--- a/py_avrjtag/cmd_proto.py	Sun Feb 22 22:43:26 2009 +0800
+++ b/py_avrjtag/cmd_proto.py	Tue Feb 24 13:32:04 2009 +0800
@@ -20,6 +20,8 @@
     FRAME_OVERHEAD = 5
     
     def __init__(self, seq=0, code=0, data=''):
+        if len(data) >= 255:
+            raise ValueError, 'data length (%d) >= 255' % (len(data))
         self.seq = seq
         self.code = code
         self.data = data
--- a/py_avrjtag/cp_ping.py	Sun Feb 22 22:43:26 2009 +0800
+++ b/py_avrjtag/cp_ping.py	Tue Feb 24 13:32:04 2009 +0800
@@ -36,7 +36,7 @@
     port = sys.argv[1]
     
     fo = open(port, 'r+b')
-    cmd_str = cp_ping(0, 'hello')
+    cmd_str = cp_ping(20, 'hello')
     fo.write(cmd_str)
     fo.flush()
     
--- a/py_avrjtag/jtagdev.py	Sun Feb 22 22:43:26 2009 +0800
+++ b/py_avrjtag/jtagdev.py	Tue Feb 24 13:32:04 2009 +0800
@@ -2,14 +2,16 @@
 import cmd_proto
 
 class jtagdev(object):
-    ST_REST = 0
+    ST_RESET = 0
     ST_IDLE = 1
     ST_SHIFT_DR = 2
     ST_SHIFT_IR = 3
+    ST_EXIT1_DR = 4
+    ST_EXIT1_IR = 5
     
     def __init__(self, fo):
         self.fo = fo
-        self.state = self.IDLE
+        self.state = self.ST_IDLE
         self.seq = 0
         pass
 
@@ -34,21 +36,41 @@
     def wait_reply(self, tmo=None):
         import select
         
-        if tmo is None:
-            select.select((self.fo,), (), ())
-        else:
-            select.select((self.fo,), (), (), tmo)
+        frame = ''
+        while True:
+            if tmo == None:
+                rlist, wlist, xlist = select.select((self.fo,), (), ())
+            else:
+                rlist, wlist, xlist = select.select((self.fo,), (), (), tmo)
+                pass
+            if not rlist:
+                break
+            frame = frame + self.fo.read()
+            if len(frame) >= 4 and \
+                    len(frame) >= (ord(frame[3]) +
+                                   cmd_proto.cmd.FRAME_OVERHEAD):
+                    break
+            tmo = 0.05
             pass
-        frame = self.fo.read()
+        
+        if not frame:
+            return None
+        
         cmd = cmd_proto.cmd()
-        cmd.from_frame(frame)
+        r = cmd.from_frame(frame)
+        if r:
+            return None
         return cmd
 
     def idle(self):
         self.seq = (self.seq + 1) % 256
         
-        ptn, nbits = tms_ptns.TMS_IDLE_SEQ
-        self.send_tms(ptn, nbits)
+        if self.state == self.ST_RESET:
+            ptn, nbits = tms_ptns.TMS_RESET_2_IDLE
+        else:
+            ptn, nbits = tms_ptns.TMS_IDLE_SEQ
+            pass
+        self._send_tms(ptn, nbits)
         
         self.state = self.ST_IDLE
         pass
@@ -58,11 +80,11 @@
             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)
+            ptn, ptn_nbits = tms_ptns.TMS_SHIFT_IR
+            self._send_tms(ptn, ptn_nbits)
+        elif self.state == self.ST_EXIT1_DR:
+            ptn, ptn_nbits = tms_ptns.TMS_EXIT1_DR_2_SHIFT_IR
+            self._send_tms(ptn, ptn_nbits)
         else:
             raise RuntimeError, 'Transite to shift IR state from invalid state'
         self.state = self.ST_SHIFT_IR
@@ -73,11 +95,11 @@
             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)
+            ptn, ptn_nbits = tms_ptns.TMS_SHIFT_DR
+            self._send_tms(ptn, ptn_nbits)
+        elif self.state == self.ST_EXIT1_IR:
+            ptn, ptn_nbits = tms_ptns.TMS_EXIT1_IR_2_SHIFT_DR
+            self._send_tms(ptn, ptn_nbits)
         else:
             raise RuntimeError, 'Transite to shift DR state from invalid state'
             pass
@@ -92,6 +114,7 @@
 
         self._send_nbits_data_cmd(cmd_proto.CPCMD_SHIFT_TDI,
                                   nbits, data)
+        self.state = self.ST_EXIT1_IR
         pass
 
     def shift_DR(self, data, nbits):
@@ -102,6 +125,7 @@
 
         self._send_nbits_data_cmd(cmd_proto.CPCMD_SHIFT_TDI,
                                   nbits, data)
+        self.state = self.ST_EXIT1_DR
         pass
 
     def shift_DR_n_out(self, data, nbits):
@@ -112,6 +136,7 @@
 
         self._send_nbits_data_cmd(cmd_proto.CPCMD_SHIFT_TDI_TDO,
                                   nbits, data)
+        self.state = self.ST_EXIT1_DR
         pass
 
     def reset(self):
@@ -121,7 +146,7 @@
     pass
 
 def _extract_nbits_data(nbits_data):
-    nbits = ord(nbits_data[0]) | (ord(nbits_data[1] << 8))
+    nbits = ord(nbits_data[0]) | (ord(nbits_data[1]) << 8)
     return nbits, nbits_data[2:]
 
 def _get_bit(data, bit_idx):
@@ -133,13 +158,24 @@
     dev.go_shift_IR()
     reply = dev.wait_reply()
     if reply.code != cmd_proto.CPCMD_ACK:
-        raise RutimeError, 'invliad reply code 0x%02x' % (reply.code)
+        raise RuntimeError, 'invalid reply code 0x%02x' % (reply.code)
+    
+    dev.shift_IR('\x02', 4)
+    reply = dev.wait_reply()
+    if reply.code != cmd_proto.CPCMD_ACK:
+        raise RuntimeError, 'invalid 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_ACK:
+        raise RuntimeError, 'invalid reply code 0x%02x' % (reply.code)
+    
+    dev.shift_DR_n_out('\xff' * 252, 252 * 8)
+    reply = dev.wait_reply()
+    if not reply:
+        raise RuntimeError, 'Invalid replied message'
     if reply.code != cmd_proto.CPCMD_DATA:
-        raise RutimeError, 'invliad reply code 0x%02x' % (reply.code)
+        raise RuntimeError, 'invalid replied code 0x%02x %s' % (reply.code, repr(reply))
 
     nbits, data = _extract_nbits_data(reply.data)
     
--- a/py_avrjtag/tms_ptns.py	Sun Feb 22 22:43:26 2009 +0800
+++ b/py_avrjtag/tms_ptns.py	Tue Feb 24 13:32:04 2009 +0800
@@ -1,12 +1,22 @@
-TMS_IDLE_SEQ = ('\x7f', 8)
-TMS_CAP_DR = ('\x1', 2)
-TMS_CAP_IR = ('\x3', 3)
-TMS_SHIFT_2_IDLE = ('\x3', 3)
+TMS_IDLE_SEQ = ('\x1f', 6)
+TMS_RESET_SEQ = ('\x1f', 5)
+TMS_RESET_2_IDLE = ('\x00', 1)
+
+TMS_CAP_DR = ('\x01', 2)
+TMS_CAP_IR = ('\x03', 3)
+TMS_SHIFT_2_IDLE = ('\x03', 3)
 TMS_SHIFT_DR_2_IDLE = TMS_SHIFT_2_IDLE
 TMS_SHIFT_IR_2_IDLE = TMS_SHIFT_2_IDLE
-TMS_SHIFT_2_PAUSE = ('\x1', 2)
-TMS_SHIFT_DR_2_PAUSE = TMS_SHIFT_2_PAUSE
-TMS_SHIFT_IR_2_PAUSE = TMS_SHIFT_2_PAUSE
-TMS_SHIFT_IR_2_CAP_DR = ('\x7', 4)
-TMS_SHIFT_DR_2_CAP_IR = ('\xf', 5)
+TMS_SHIFT_DR_2_CAP_IR = ('\x0f', 5)
+TMS_SHIFT_IR_2_CAP_DR = ('\x07', 4)
 
+TMS_SHIFT_DR = ('\x01', 3)
+TMS_SHIFT_IR = ('\x03', 4)
+TMS_EXIT1_2_IDLE = ('\x01', 2)
+TMS_EXIT1_DR_2_IDLE = TMS_EXIT1_2_IDLE
+TMS_EXIT1_IR_2_IDLE = TMS_EXIT1_2_IDLE
+TMS_EXIT1_2_PAUSE = ('\x00', 1)
+TMS_EXIT1_DR_2_PAUSE = TMS_EXIT1_2_PAUSE
+TMS_EXIT1_IR_2_PAUSE = TMS_EXIT1_2_PAUSE
+TMS_EXIT1_IR_2_SHIFT_DR = ('\x03', 3)
+TMS_EXIT1_DR_2_SHIFT_IR = ('\x07', 4)
--- a/src/avr_jtag.c	Sun Feb 22 22:43:26 2009 +0800
+++ b/src/avr_jtag.c	Tue Feb 24 13:32:04 2009 +0800
@@ -8,7 +8,7 @@
 
 #define BAUD_RATE 420000
 
-static char client_buf[256 + CP_CMD_OVERHEAD];
+static unsigned char client_buf[256 + CP_CMD_OVERHEAD];
 
 static
 void ack(int seq) {
@@ -22,7 +22,7 @@
 }
 
 static
-void nak(int seq, const char *msg) {
+void nak(int seq, const unsigned char *msg) {
     int i;
     int sz;
     
@@ -34,37 +34,23 @@
 }
 
 static
-void send_client(const char *buf, int bsz) {
+void send_client(const unsigned char *buf, int bsz) {
     int i;
     
     for(i = 0; i < bsz; i++)
 	uart_putc(buf[i]);
 }
 
-void flash_init(void) {
-    pin_mode(&PORTB, PINB4, PM_OUTPUT);
-    pin_mode(&PORTB, PINB5, PM_OUTPUT);
-    pin_lo(PORTB, PINB4);
-    pin_lo(PORTB, PINB5);
-}
-
-void flash_led(void) {
-    pin_hi(PORTB, PINB4);
-    _delay_ms(50);
-    pin_lo(PORTB, PINB4);
-}
-
-#define GET_DATA_BITS(data) ((data)[0] | ((data)[1] << 8))
+#define GET_DATA_BITS(data) (((unsigned int)(data)[0]) |	\
+			     ((unsigned int)(data)[1] << 8))
 
 int main(int argc, char * const argv[]) {
     cp_cmd_t *cmd;
     cmd_proto_t *cp;
-    int c, nbits;
+    int c;
+    unsigned int nbits;
     int bsz;
-    static char buf[16];
-    
-    flash_init();
-    flash_led();
+    static unsigned char buf[16];
     
     uart_init(BAUD_RATE);
     jtag_init();
--- a/src/cmd_proto.c	Sun Feb 22 22:43:26 2009 +0800
+++ b/src/cmd_proto.c	Tue Feb 24 13:32:04 2009 +0800
@@ -120,7 +120,8 @@
     return cmd;
 }
 
-int cmd_proto_cmd_fill(char *buf, int seq, cp_ccode_t code, int data_sz) {
+int cmd_proto_cmd_fill(unsigned char *buf, int seq,
+		       cp_ccode_t code, int data_sz) {
     int i, last = data_sz + CP_CMD_HEAD_SZ;
     int csum = 0;
     
--- a/src/jtag.c	Sun Feb 22 22:43:26 2009 +0800
+++ b/src/jtag.c	Tue Feb 24 13:32:04 2009 +0800
@@ -4,16 +4,18 @@
 #include "avriotools.h"
 
 /* It is supposed to work at 1Mbps */
-#define CLK_DELAY()
+#define CLK_DELAY() _delay_us(1)
 
 void jtag_init(void) {
     pin_mode(&JTAG_PORT, JTAG_TCK, PM_OUTPUT);
     pin_mode(&JTAG_PORT, JTAG_TMS, PM_OUTPUT);
     pin_mode(&JTAG_PORT, JTAG_TDI, PM_OUTPUT);
     pin_mode(&JTAG_PORT, JTAG_TDO, PM_INPUT);
+    pin_mode(&JTAG_PORT, JTAG_TRST, PM_OUTPUT);
     pin_lo(JTAG_PORT, JTAG_TCK);
     pin_lo(JTAG_PORT, JTAG_TMS);
     pin_lo(JTAG_PORT, JTAG_TDI);
+    pin_hi(JTAG_PORT, JTAG_TRST);
 }
 
 #define TCK_LO() pin_lo(JTAG_PORT, JTAG_TCK)
@@ -27,13 +29,30 @@
 	CLK_DELAY();				\
 	TCK_HI();				\
 	CLK_DELAY();				\
+	TCK_LO();				\
     } while(0)
 #define GET_TDO() (JTAG_PIN & _BV(JTAG_TDO))
+#define SEND_GET_BIT(pin, bit, out)		\
+    do {					\
+	if(bit)					\
+	    pin_hi(JTAG_PORT, pin);		\
+	else					\
+	    pin_lo(JTAG_PORT, pin);		\
+	CLK_DELAY();				\
+	TCK_HI();				\
+	CLK_DELAY();				\
+	out = GET_TDO();			\
+	TCK_LO();				\
+    } while(0)
 
 void jtag_trst(void) {
-    SEND_BIT(JTAG_TRST, 1);
-    TCK_LO();
     pin_lo(JTAG_PORT, JTAG_TRST);
+    SEND_BIT(JTAG_TMS, 1);
+    SEND_BIT(JTAG_TMS, 1);
+    SEND_BIT(JTAG_TMS, 1);
+    SEND_BIT(JTAG_TMS, 1);
+    SEND_BIT(JTAG_TMS, 1);
+    pin_hi(JTAG_PORT, JTAG_TRST);
 }
 
 /*!
@@ -41,47 +60,41 @@
  * shift state.  The state machine transite to shift state when shifting
  * starts.
  */
-void jtag_tms(char *buf, int nbits) {
+void jtag_tms(unsigned char *buf, int nbits) {
     int i;
     int nbytes, byte;
     int byteoff, bitoff;
     int bit;
     
+    pin_hi(JTAG_PORT, JTAG_TDI);
+
     nbytes = nbits / 8;
     for(i = 0; i < nbytes; i++) {
 	byte = buf[i];
 	
 	bit = byte & 0x01;
 	SEND_BIT(JTAG_TMS, bit);
-	TCK_LO();
 	
 	bit = byte & 0x02;
 	SEND_BIT(JTAG_TMS, bit);
-	TCK_LO();
 	
 	bit = byte & 0x04;
 	SEND_BIT(JTAG_TMS, bit);
-	TCK_LO();
 	
 	bit = byte & 0x08;
 	SEND_BIT(JTAG_TMS, bit);
-	TCK_LO();
 	
 	bit = byte & 0x10;
 	SEND_BIT(JTAG_TMS, bit);
-	TCK_LO();
 	
 	bit = byte & 0x20;
 	SEND_BIT(JTAG_TMS, bit);
-	TCK_LO();
 	
 	bit = byte & 0x40;
 	SEND_BIT(JTAG_TMS, bit);
-	TCK_LO();
 	
 	bit = byte & 0x80;
 	SEND_BIT(JTAG_TMS, bit);
-	TCK_LO();
     }
     
     byte = buf[i];
@@ -89,175 +102,170 @@
     for(i = 0; i < nbits; i++) {
 	bit = byte & (1 << i);
 	SEND_BIT(JTAG_TMS, bit);
-	TCK_LO();
     }
 }
 
-void jtag_shift(char *buf, int nbits) {
+void jtag_shift(unsigned char *buf, int nbits) {
     int i;
+    int nbits_1;
     int nbytes, byte;
     int byteoff, bitoff;
-    int bit;
+    int bit, remain;
+
+    if(nbits == 0)
+	return;
     
     /* Transite to shift state.
      * \sa jtag_tms()
      */
     pin_lo(JTAG_PORT, JTAG_TMS);
 
-    nbytes = nbits / 8;
+    nbits_1 = nbits - 1;
+    nbytes = nbits_1 / 8;
     for(i = 0; i < nbytes; i++) {
 	byte = buf[i];
 	
 	bit = byte & 0x01;
 	SEND_BIT(JTAG_TDI, bit);
-	TCK_LO();
 	
 	bit = byte & 0x02;
 	SEND_BIT(JTAG_TDI, bit);
-	TCK_LO();
 	
 	bit = byte & 0x04;
 	SEND_BIT(JTAG_TDI, bit);
-	TCK_LO();
 	
 	bit = byte & 0x08;
 	SEND_BIT(JTAG_TDI, bit);
-	TCK_LO();
 	
 	bit = byte & 0x10;
 	SEND_BIT(JTAG_TDI, bit);
-	TCK_LO();
 	
 	bit = byte & 0x20;
 	SEND_BIT(JTAG_TDI, bit);
-	TCK_LO();
 	
 	bit = byte & 0x40;
 	SEND_BIT(JTAG_TDI, bit);
-	TCK_LO();
 	
 	bit = byte & 0x80;
 	SEND_BIT(JTAG_TDI, bit);
-	TCK_LO();
     }
     
-    nbits %= 8;
-    if(nbits) {
-	byte = buf[i];
-	for(i = 0; i < nbits; i++) {
-	    bit = byte & (1 << i);
-	    SEND_BIT(JTAG_TDI, bit);
-	    TCK_LO();
-	}
+    remain = nbits_1 % 8;
+    byte = buf[i];
+    for(i = 0; i < remain; i++) {
+	bit = byte & (1 << i);
+	SEND_BIT(JTAG_TDI, bit);
     }
+
+    byte = buf[nbits / 8];
+    bit = byte & (1 << (nbits_1 % 8));
+    
+    pin_hi(JTAG_PORT, JTAG_TMS);
+    SEND_BIT(JTAG_TDI, bit);
 }
 
-void jtag_shift_inout(char *ibuf, char *obuf, int nbits) {
+void jtag_shift_inout(unsigned char *ibuf, unsigned char *obuf, int nbits) {
     int i, j;
+    int nbits_1;
     int nbytes, byte, obyte;
     int tdo;
     int byteoff, bitoff;
-    int bit;
+    int bit, remain;
+    
+    if(nbits == 0)
+	return;
     
     /* Transite to shift state.
      * \sa jtag_tms()
      */
     pin_lo(JTAG_PORT, JTAG_TMS);
 
-    nbytes = nbits / 8;
+    nbits_1 = nbits - 1;
+    nbytes = nbits_1 / 8;
     for(i = 0; i < nbytes; i++) {
 	byte = ibuf[i];
 	obyte = 0;
 	
 	bit = byte & 0x01;
-	SEND_BIT(JTAG_TDI, bit);
-	tdo = GET_TDO();
+	SEND_GET_BIT(JTAG_TDI, bit, tdo);
 	if(tdo)
 	    obyte |= 0x01;
 	else
 	    obyte &= ~0x01;
-	TCK_LO();
 	
 	bit = byte & 0x02;
-	SEND_BIT(JTAG_TDI, bit);
+	SEND_GET_BIT(JTAG_TDI, bit, tdo);
 	tdo = GET_TDO();
 	if(tdo)
 	    obyte |= 0x02;
 	else
 	    obyte &= ~0x02;
-	TCK_LO();
 	
 	bit = byte & 0x04;
-	SEND_BIT(JTAG_TDI, bit);
-	tdo = GET_TDO();
+	SEND_GET_BIT(JTAG_TDI, bit, tdo);
 	if(tdo)
 	    obyte |= 0x04;
 	else
 	    obyte &= ~0x04;
-	TCK_LO();
 	
 	bit = byte & 0x08;
-	SEND_BIT(JTAG_TDI, bit);
-	tdo = GET_TDO();
+	SEND_GET_BIT(JTAG_TDI, bit, tdo);
 	if(tdo)
 	    obyte |= 0x08;
 	else
 	    obyte &= ~0x08;
-	TCK_LO();
 	
 	bit = byte & 0x10;
-	SEND_BIT(JTAG_TDI, bit);
-	tdo = GET_TDO();
+	SEND_GET_BIT(JTAG_TDI, bit, tdo);
 	if(tdo)
 	    obyte |= 0x10;
 	else
 	    obyte &= ~0x10;
-	TCK_LO();
 	
 	bit = byte & 0x20;
-	SEND_BIT(JTAG_TDI, bit);
-	tdo = GET_TDO();
+	SEND_GET_BIT(JTAG_TDI, bit, tdo);
 	if(tdo)
 	    obyte |= 0x20;
 	else
 	    obyte &= ~0x20;
-	TCK_LO();
 	
 	bit = byte & 0x40;
-	SEND_BIT(JTAG_TDI, bit);
-	tdo = GET_TDO();
+	SEND_GET_BIT(JTAG_TDI, bit, tdo);
 	if(tdo)
 	    obyte |= 0x40;
 	else
 	    obyte &= ~0x40;
-	TCK_LO();
 	
 	bit = byte & 0x80;
-	SEND_BIT(JTAG_TDI, bit);
-	tdo = GET_TDO();
+	SEND_GET_BIT(JTAG_TDI, bit, tdo);
 	if(tdo)
 	    obyte |= 0x80;
 	else
 	    obyte &= ~0x80;
-	TCK_LO();
 
 	obuf[i] = obyte;
     }
     
-    nbits %= 8;
-    if(nbits) {
-	byte = ibuf[i];
-	obyte = 0;
-	for(j = 0; j < nbits; j++) {
-	    bit = byte & (1 << j);
-	    SEND_BIT(JTAG_TDI, bit);
-	    tdo = GET_TDO();
-	    if(tdo)
-		obyte |= 1 << j;
-	    else
-		obyte &= ~(1 << j);
-	    TCK_LO();
-	}
-	obuf[i] = obyte;
+    remain = nbits_1 % 8;
+    byte = ibuf[i];
+    obyte = 0;
+    for(j = 0; j < remain; j++) {
+	bit = byte & (1 << j);
+	SEND_GET_BIT(JTAG_TDI, bit, tdo);
+	if(tdo)
+	    obyte |= 1 << j;
+	else
+	    obyte &= ~(1 << j);
     }
+    obuf[i] = obyte;
+
+    byte = ibuf[nbits / 8];
+    bit = byte & (1 << (nbits_1 % 8));
+
+    pin_hi(JTAG_PORT, JTAG_TMS);
+    SEND_GET_BIT(JTAG_TDI, bit, tdo);
+    if(tdo)
+	obuf[nbits / 8] |= 1 << j;
+    else
+	obuf[nbits / 8] &= ~(1 << j);
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/identify.py	Tue Feb 24 13:32:04 2009 +0800
@@ -0,0 +1,38 @@
+import sys
+import os
+import fcntl
+import jtagdev
+
+if len(sys.argv) != 2:
+    print >>sys.stderr, 'Usage: %s <UART Port>' % (sys.argv[0])
+    sys.exit(1)
+uart_fname = sys.argv[1]
+
+try:
+    uart_fo = file(uart_fname, 'r+b')
+except IOError, e:
+    print e
+    sys.exit(1)
+    pass
+
+flags = fcntl.fcntl(uart_fo, fcntl.F_GETFL)
+fcntl.fcntl(uart_fo, fcntl.F_SETFL, os.O_NONBLOCK | flags)
+
+dev = jtagdev.jtagdev(uart_fo)
+
+print 'Reset:',
+dev.reset()
+reply = dev.wait_reply()
+print reply
+
+print 'Go idle:',
+dev.idle()
+reply = dev.wait_reply()
+print reply
+
+print 'Identify components:',
+components = jtagdev.identify_components(dev)
+for comp in components:
+    print '%08x' % (comp)
+    pass
+