Mercurial > ~darius > hgwebdir.cgi > pyinst
comparison usb488.py @ 65:29bcef559283
Add initiateClear and a few others and use it to clear buffers on setup.
author | Daniel O'Connor <doconnor@gsoft.com.au> |
---|---|
date | Tue, 19 Jan 2021 16:06:29 +1030 |
parents | 4558e5ccd775 |
children | bf411c7f5e78 |
comparison
equal
deleted
inserted
replaced
64:4ca9fdf0795a | 65:29bcef559283 |
---|---|
33 # http://www.home.agilent.com/agilent/redirector.jspx?action=ref&cname=AGILENT_EDITORIAL&ckey=1189335&lc=eng&cc=US&nfr=-35560.0.00 | 33 # http://www.home.agilent.com/agilent/redirector.jspx?action=ref&cname=AGILENT_EDITORIAL&ckey=1189335&lc=eng&cc=US&nfr=-35560.0.00 |
34 # linux-2.6.29.3/drivers/usb/class/usbtmc.c | 34 # linux-2.6.29.3/drivers/usb/class/usbtmc.c |
35 # http://sdpha2.ucsd.edu/Lab_Equip_Manuals/usbtmc_usb488_subclass_1_00.pdf | 35 # http://sdpha2.ucsd.edu/Lab_Equip_Manuals/usbtmc_usb488_subclass_1_00.pdf |
36 # | 36 # |
37 | 37 |
38 import time | |
38 import usb | 39 import usb |
39 from functools import reduce | 40 from functools import reduce |
40 | 41 |
41 # | 42 # |
42 # The usual SCPI commands are wrapped before being sent. | 43 # The usual SCPI commands are wrapped before being sent. |
86 | 87 |
87 # USB488 message IDs | 88 # USB488 message IDs |
88 DEV_DEP_MSG_OUT = 1 | 89 DEV_DEP_MSG_OUT = 1 |
89 REQUEST_DEV_DEP_MSG_IN = 2 | 90 REQUEST_DEV_DEP_MSG_IN = 2 |
90 DEV_DEP_MSG_IN = 2 | 91 DEV_DEP_MSG_IN = 2 |
92 | |
93 # USB TMC control requests | |
94 INITIATE_ABORT_BULK_OUT = 1 | |
95 CHECK_ABORT_BULK_OUT_STATUS = 2 | |
96 INITIATE_ABORT_BULK_IN = 3 | |
97 CHECK_ABORT_BULK_IN_STATUS = 4 | |
98 INITIATE_CLEAR = 5 | |
99 CHECK_CLEAR_STATUS = 6 | |
100 GET_CAPABILITIES = 7 | |
101 INDICATOR_PULSE = 64 | |
102 | |
103 # Interface capability bits | |
104 IF_CAP_LISTEN_ONLY = 0x01 | |
105 IF_CAP_TALK_ONLY = 0x02 | |
106 IF_CAP_HAS_INDICATOR = 0x04 | |
107 | |
108 # Device capability bits | |
109 DEV_CAP_TERM_CHAR = 0x01 | |
110 | |
111 # USBTMC status definitions | |
112 STATUS_SUCCESS = 0x01 | |
113 STATUS_PENDING = 0x02 | |
114 STATUS_FAILED = 0x80 | |
115 STATUS_TRANSFER_NOT_IN_PROGRESS = 0x81 | |
116 STATUS_SPLIT_NOT_IN_PROGRESS = 0x82 | |
117 STATUS_SPLIT_IN_PROGRESS = 0x83 | |
91 | 118 |
92 class USB488Device(object): | 119 class USB488Device(object): |
93 def __init__(self, vendor = None, product = None, serial = None, path = None): | 120 def __init__(self, vendor = None, product = None, serial = None, path = None): |
94 """Search for a USB488 class device, if specified vendor, | 121 """Search for a USB488 class device, if specified vendor, |
95 product, serial and path will refine the search""" | 122 product, serial and path will refine the search""" |
158 except ValueError: | 185 except ValueError: |
159 self.serial = None | 186 self.serial = None |
160 | 187 |
161 # Determine the endpoints for each operation type | 188 # Determine the endpoints for each operation type |
162 self.intrep = self.bulkinep = self.bulkoutep = None | 189 self.intrep = self.bulkinep = self.bulkoutep = None |
163 | 190 |
164 for ep in altif.endpoints: | 191 for ep in altif.endpoints: |
165 if ep.type == usb.ENDPOINT_TYPE_INTERRUPT and \ | 192 if ep.type == usb.ENDPOINT_TYPE_INTERRUPT and \ |
166 ep.address & usb.ENDPOINT_IN == usb.ENDPOINT_IN: | 193 ep.address & usb.ENDPOINT_IN == usb.ENDPOINT_IN: |
167 self.intrep = ep.address | 194 self.intrep = ep.address |
168 | 195 |
175 | 202 |
176 # Required for 488.2 devices, optional otherwise | 203 # Required for 488.2 devices, optional otherwise |
177 if self.intrep == None: | 204 if self.intrep == None: |
178 print("Can't find interrupt endpoint") | 205 print("Can't find interrupt endpoint") |
179 | 206 |
180 # Data from the scope (mandatory) | 207 # Data from the device (mandatory) |
181 if self.bulkinep == None: | 208 if self.bulkinep == None: |
182 raise BaseException("Can't find bulk-in endpoint") | 209 raise BaseException("Can't find bulk-in endpoint") |
183 | 210 |
184 # Data to the scope (mandatory) | 211 # Data to the device (mandatory) |
185 if self.bulkoutep == None: | 212 if self.bulkoutep == None: |
186 raise BaseException("Can't find bulk-out endpoint") | 213 raise BaseException("Can't find bulk-out endpoint") |
187 | 214 |
188 self.tag = 1 | 215 self.tag = 1 |
216 self.initiateClear() | |
189 | 217 |
190 def __str__(self): | 218 def __str__(self): |
191 rtn = "Mfg: %s Prod: %s" % (self.vendname, self.prodname) | 219 rtn = "Mfg: %s Prod: %s" % (self.vendname, self.prodname) |
192 if self.serial != "": | 220 if self.serial != "": |
193 rtn += " S/N: " + self.serial | 221 rtn += " S/N: " + self.serial |
226 # Split it up into maxPacket sized chunks and send.. | 254 # Split it up into maxPacket sized chunks and send.. |
227 while len(pkt) > 0: | 255 while len(pkt) > 0: |
228 chunk = pkt[0:self.maxPacket] | 256 chunk = pkt[0:self.maxPacket] |
229 pkt = pkt[self.maxPacket:] | 257 pkt = pkt[self.maxPacket:] |
230 | 258 |
231 #print "Sending %s bytes of data: %s" % (len(chunk), chunk) | 259 #print("Sending %s bytes of data: %s" % (len(chunk), chunk)) |
232 wrote = self.handle.bulkWrite(self.bulkoutep, chunk) | 260 wrote = self.handle.bulkWrite(self.bulkoutep, chunk) |
233 if wrote != len(chunk): | 261 if wrote != len(chunk): |
234 raise BaseException("Short write, got %d, expected %d" % (wrote, len(chunk))) | 262 raise BaseException("Short write, got %d, expected %d" % (wrote, len(chunk))) |
235 | 263 |
236 def read(self, timeout = None): | 264 def read(self, timeout = None): |
259 | 287 |
260 # Bump tag | 288 # Bump tag |
261 self.incrtag() | 289 self.incrtag() |
262 | 290 |
263 # Send it | 291 # Send it |
264 #print "Sending " + str(pkt) | 292 #print("Sending " + str(pkt)) |
265 wrote = self.handle.bulkWrite(self.bulkoutep, pkt, _timeout) | 293 wrote = self.handle.bulkWrite(self.bulkoutep, pkt, _timeout) |
266 if wrote != len(pkt): | 294 if wrote != len(pkt): |
267 print("Short write, got %d, expected %d" % (wrote, len(pkt))) | 295 print("Short write, got %d, expected %d" % (wrote, len(pkt))) |
268 | 296 |
269 #print "Reading.." | 297 #print("Reading..") |
270 read = self.handle.bulkRead(self.bulkinep, datalen, _timeout) | 298 read = self.handle.bulkRead(self.bulkinep, datalen, _timeout) |
271 #print "Read %s bytes: %s" % (len(read), str(read)) | 299 #print("Read %s bytes: %s" % (len(read), str(read))) |
272 | 300 |
273 if read[0] != DEV_DEP_MSG_IN: | 301 if read[0] != DEV_DEP_MSG_IN: |
274 raise BaseException("Unexpected Msg ID, got %s expected %d" % (read[0], DEV_DEP_MSG_IN)) | 302 raise BaseException("Unexpected Msg ID, got %s expected %d" % (read[0], DEV_DEP_MSG_IN)) |
275 if read[1] != exptag: | 303 if read[1] != exptag: |
276 raise BaseException("Unexpected tag, got %d expected %d" % (read[1], exptag)) | 304 raise BaseException("Unexpected tag, got %d expected %d" % (read[1], exptag)) |
277 if read[2] != ~exptag & 0xff: | 305 if read[2] != ~exptag & 0xff: |
278 raise BaseException("Unexpected tag inverse, got %d expected %d" % (read[1], ~exptag & 0xff)) | 306 raise BaseException("Unexpected tag inverse, got %d expected %d" % (read[1], ~exptag & 0xff)) |
279 | 307 |
280 actualdata = read[4] | read[5] << 8 | read[6] << 16 | read[7] << 24 | 308 actualdata = read[4] | read[5] << 8 | read[6] << 16 | read[7] << 24 |
281 #print "Computed datalen is %d" % (actualdata) | 309 #print("Computed datalen is %d" % (actualdata)) |
282 data += read[12:12 + actualdata] | 310 data += read[12:12 + actualdata] |
283 if read[8] & 0x01: | 311 if read[8] & 0x01: |
284 #print "Breaking out due to EOM" | 312 #print("Breaking out due to EOM") |
285 break | 313 break |
286 | 314 |
287 # Stringify result for easier consumption | 315 # Stringify result for easier consumption |
288 result = reduce(lambda x, y: x+y, list(map(chr, data))) | 316 result = reduce(lambda x, y: x+y, list(map(chr, data))) |
289 # Trim off \n if present | 317 # Trim off \n if present |
305 self.handle.getString(self.dev.iManufacturer, 100) | 333 self.handle.getString(self.dev.iManufacturer, 100) |
306 except USBError as e: | 334 except USBError as e: |
307 return False | 335 return False |
308 | 336 |
309 return True | 337 return True |
310 | 338 |
339 def getCapabilities(self): | |
340 '''Returns interface and device capability bytes (see IF_CAP_* and DEV_CAP_*)''' | |
341 res = self.handle.controlMsg(usb.ENDPOINT_IN | usb.TYPE_CLASS | usb.RECIP_INTERFACE, GET_CAPABILITIES, 0x18) | |
342 return res[4], res[5] | |
343 | |
344 def indicatorPulse(self): | |
345 '''Send an indicator pulse request''' | |
346 res = self.handle.controlMsg(usb.ENDPOINT_IN | usb.TYPE_CLASS | usb.RECIP_INTERFACE, INDICATOR_PULSE, 0x01) | |
347 | |
348 def initiateClear(self): | |
349 '''Send request to clear all transfers and wait until the device reports it is done and clear stalls''' | |
350 res = self.handle.controlMsg(usb.ENDPOINT_IN | usb.TYPE_CLASS | usb.RECIP_INTERFACE, INITIATE_CLEAR, 0x01) | |
351 if res[0] == STATUS_SUCCESS: | |
352 while True: | |
353 res = self.handle.controlMsg(usb.ENDPOINT_IN | usb.TYPE_CLASS | usb.RECIP_INTERFACE, CHECK_CLEAR_STATUS, 0x02) | |
354 if res[0] != STATUS_PENDING: | |
355 break | |
356 time.sleep(0.1) | |
357 self.handle.clearHalt(usb.ENDPOINT_IN | self.bulkinep) | |
358 self.handle.clearHalt(usb.ENDPOINT_OUT | self.bulkoutep) |