diff usb488.py @ 69:7386f2888508

Make function more configurable
author Daniel O'Connor <doconnor@gsoft.com.au>
date Wed, 04 Aug 2021 16:07:44 +0930
parents 98b9258c75b6
children
line wrap: on
line diff
--- a/usb488.py	Tue Jan 19 17:32:57 2021 +1030
+++ b/usb488.py	Wed Aug 04 16:07:44 2021 +0930
@@ -99,6 +99,11 @@
 CHECK_CLEAR_STATUS = 6
 GET_CAPABILITIES = 7
 INDICATOR_PULSE = 64
+# USB488
+READ_STATUS_BYTE = 128
+REN_CONTROL = 160
+GO_TO_LOCAL = 161
+LOCAL_LOCKOUT = 162
 
 # Interface capability bits
 IF_CAP_LISTEN_ONLY = 0x01
@@ -108,6 +113,17 @@
 # Device capability bits
 DEV_CAP_TERM_CHAR = 0x01
 
+# USB488 interface capbility bits
+USB488_IFCAP_TRIG = 0x01
+USB488_IFCAP_GO_LOC = 0x02
+USB488_IFCAP_488_2 = 0x04
+
+# USB488 device capbility bits
+USB488_DEVCAP_DT1 = 0x01
+USB488_DEVCAP_RL1 = 0x02
+USB488_DEVCAP_SR1 = 0x04
+USB488_DEVCAP_SCPI = 0x08
+
 # USBTMC status definitions
 STATUS_SUCCESS = 0x01
 STATUS_PENDING = 0x02
@@ -216,7 +232,9 @@
             raise BaseException("Can't find bulk-out endpoint")
 
         self.tag = 1
+        #self.init()
 
+    def init(self):
         # Flush out any pending data
         self.initiateClear()
         # Perform dummy write/read otherwise the next read times out
@@ -239,10 +257,12 @@
 
         return rtn
 
-    def incrtag(self):
+    def gettag(self):
+        tag = self.tag
         self.tag = (self.tag + 1) % 255
         if self.tag == 0:
             self.tag += 1
+        return tag
 
     def write(self, data):
         """Send data (string) to the instrument"""
@@ -254,7 +274,8 @@
         datalen = len(orddata)
 
         # Build the packet
-        pkt = [ DEV_DEP_MSG_OUT, self.tag, ~self.tag & 0xff, 0x00,
+        tag = self.gettag()
+        pkt = [ DEV_DEP_MSG_OUT, tag, ~tag & 0xff, 0x00,
                 datalen & 0xff, datalen >> 8 & 0xff, datalen >> 16 & 0xff,
                 datalen >> 24 & 0xff, 1, 0, 0, 0 ]
 
@@ -265,15 +286,13 @@
         alignlen = ((len(pkt) // 4) + 1) * 4
         pkt = pkt + [0] * (alignlen - len(pkt))
 
-        # Bump the tag
-        self.incrtag()
-
         # Split it up into maxPacket sized chunks and send..
+        # XXX; this is not correct, need a header for each one
         while len(pkt) > 0:
             chunk = pkt[0:self.maxPacket]
             pkt = pkt[self.maxPacket:]
 
-            #print("Sending %s bytes of data: %s" % (len(chunk), chunk))
+            #print("Sending %d bytes of data: %s" % (len(chunk), chunk))
             wrote = self.handle.bulkWrite(self.bulkoutep, chunk)
             if wrote != len(chunk):
                 raise BaseException("Short write, got %d, expected %d" % (wrote, len(chunk)))
@@ -282,7 +301,7 @@
         """Read data from the device, waits for up to timeout seconds for each USB transaction"""
 
         if timeout == None:
-            timeout = 0.5
+            timeout = 1
 
         # Mangle into milliseconds
         _timeout = int(timeout * 1000.0)
@@ -295,16 +314,11 @@
         
         while True:
             # Ask the device to send us something
-            pkt = [ REQUEST_DEV_DEP_MSG_IN, self.tag, ~self.tag & 0xff, 0x00,
+            tag = self.gettag()
+            pkt = [ REQUEST_DEV_DEP_MSG_IN, tag, ~tag & 0xff, 0x00,
                     datalen & 0xff, datalen >> 8 & 0xff, datalen >> 16 & 0xff,
                     datalen >> 24 & 0xff, 0, 0, 0, 0]
 
-            # Expected tag
-            exptag = self.tag
-            
-            # Bump tag
-            self.incrtag()
-
             # Send it
             #print("Sending " + str(pkt))
             wrote = self.handle.bulkWrite(self.bulkoutep, pkt, _timeout)
@@ -317,10 +331,10 @@
 
             if read[0] != DEV_DEP_MSG_IN:
                 raise BaseException("Unexpected Msg ID, got %s expected %d" % (read[0], DEV_DEP_MSG_IN))
-            if read[1] != exptag:
-                raise BaseException("Unexpected tag, got %d expected %d" % (read[1], exptag))
-            if read[2] != ~exptag & 0xff:
-                raise BaseException("Unexpected tag inverse, got %d expected %d" % (read[1], ~exptag & 0xff))
+            if read[1] != tag:
+                raise BaseException("Unexpected tag, got %d expected %d" % (read[1], tag))
+            if read[2] != ~tag & 0xff:
+                raise BaseException("Unexpected tag inverse, got %d expected %d" % (read[1], ~tag & 0xff))
 
             actualdata = read[4] | read[5] << 8 | read[6] << 16 | read[7] << 24
             #print("Computed datalen is %d" % (actualdata))
@@ -362,9 +376,9 @@
         return True
 
     def getCapabilities(self):
-        '''Returns interface and device capability bytes (see IF_CAP_* and DEV_CAP_*)'''
+        '''Returns interface, device and USB488 capability bytes (see IF_CAP_*, DEV_CAP_*, USB488_IFCAP_* and USB488_DEVCAP_*)'''
         res = self.handle.controlMsg(usb.ENDPOINT_IN | usb.TYPE_CLASS | usb.RECIP_INTERFACE, GET_CAPABILITIES, 0x18)
-        return res[4], res[5]
+        return res[4], res[5], res[14], res[15]
 
     def indicatorPulse(self):
         '''Send an indicator pulse request'''
@@ -379,5 +393,48 @@
                 if res[0] != STATUS_PENDING:
                     break
                 time.sleep(0.1)
-        self.handle.clearHalt(usb.ENDPOINT_IN | self.bulkinep)
-        self.handle.clearHalt(usb.ENDPOINT_OUT | self.bulkoutep)
+        else:
+            raise BaseException('INITIATE_CLEAR returned 0x%02x' % (res[0]))
+        self.handle.clearHalt(self.bulkinep)
+        self.handle.clearHalt(self.bulkoutep)
+
+    def renControl(self):
+        '''Send enable remote control message'''
+        res = self.handle.controlMsg(usb.ENDPOINT_IN | usb.TYPE_CLASS | usb.RECIP_INTERFACE, REN_CONTROL, 1, 0xff)
+        return res[0]
+
+    def getStatus(self):
+        '''Returns IEEE 488 status byte'''
+        tag = self.gettag()
+        res = self.handle.controlMsg(usb.ENDPOINT_IN | usb.TYPE_CLASS | usb.RECIP_INTERFACE, READ_STATUS_BYTE, 3, tag)
+        if res[1] != tag:
+            raise BaseException('Tag mismatch, got 0x%02x, expected 0x%02x' % (res[1], tag))
+        if res[0] != STATUS_SUCCESS:
+            raise BaseException('Unit returned invalid USBTMC status: %d' % (res[0],))
+        return res[2]
+
+    def abortIO(self, tag, isout):
+        if isout:
+            req = INITIATE_ABORT_BULK_OUT
+            chkreq = CHECK_ABORT_BULK_OUT_STATUS
+            ep = self.bulkoutep
+            name = 'out'
+        else:
+            req = INITIATE_ABORT_BULK_IN
+            chkreq = CHECK_ABORT_BULK_IN_STATUS
+            ep = self.bulkinep
+            name = 'in'
+        res = self.handle.controlMsg(usb.ENDPOINT_IN | usb.TYPE_CLASS | usb.RECIP_ENDPOINT,
+                                req, 2, value = tag, index = ep)
+        print('Initiate abort returned ' + str(res))
+        while True:
+            res = self.handle.controlMsg(usb.ENDPOINT_IN | usb.TYPE_CLASS | usb.RECIP_ENDPOINT,
+                                         chkreq, 8, value = 0x00, index = ep)
+            print('Check abort returned ' + str(res))
+            if res[0] == STATUS_PENDING:
+                print('Status pending for %s abort' % (name,))
+                time.sleep(1)
+            elif res[0] == STATUS_SUCCESS or res[0] == STATUS_TRANSFER_NOT_IN_PROGRESS:
+                break
+            else:
+                raise BaseException('Invalid status reply to check abort %s 0x%02x' % (name, res[0]))