Mercurial > ~darius > hgwebdir.cgi > pyinst
comparison 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 |
comparison
equal
deleted
inserted
replaced
68:f95db5ea2fe1 | 69:7386f2888508 |
---|---|
97 CHECK_ABORT_BULK_IN_STATUS = 4 | 97 CHECK_ABORT_BULK_IN_STATUS = 4 |
98 INITIATE_CLEAR = 5 | 98 INITIATE_CLEAR = 5 |
99 CHECK_CLEAR_STATUS = 6 | 99 CHECK_CLEAR_STATUS = 6 |
100 GET_CAPABILITIES = 7 | 100 GET_CAPABILITIES = 7 |
101 INDICATOR_PULSE = 64 | 101 INDICATOR_PULSE = 64 |
102 # USB488 | |
103 READ_STATUS_BYTE = 128 | |
104 REN_CONTROL = 160 | |
105 GO_TO_LOCAL = 161 | |
106 LOCAL_LOCKOUT = 162 | |
102 | 107 |
103 # Interface capability bits | 108 # Interface capability bits |
104 IF_CAP_LISTEN_ONLY = 0x01 | 109 IF_CAP_LISTEN_ONLY = 0x01 |
105 IF_CAP_TALK_ONLY = 0x02 | 110 IF_CAP_TALK_ONLY = 0x02 |
106 IF_CAP_HAS_INDICATOR = 0x04 | 111 IF_CAP_HAS_INDICATOR = 0x04 |
107 | 112 |
108 # Device capability bits | 113 # Device capability bits |
109 DEV_CAP_TERM_CHAR = 0x01 | 114 DEV_CAP_TERM_CHAR = 0x01 |
115 | |
116 # USB488 interface capbility bits | |
117 USB488_IFCAP_TRIG = 0x01 | |
118 USB488_IFCAP_GO_LOC = 0x02 | |
119 USB488_IFCAP_488_2 = 0x04 | |
120 | |
121 # USB488 device capbility bits | |
122 USB488_DEVCAP_DT1 = 0x01 | |
123 USB488_DEVCAP_RL1 = 0x02 | |
124 USB488_DEVCAP_SR1 = 0x04 | |
125 USB488_DEVCAP_SCPI = 0x08 | |
110 | 126 |
111 # USBTMC status definitions | 127 # USBTMC status definitions |
112 STATUS_SUCCESS = 0x01 | 128 STATUS_SUCCESS = 0x01 |
113 STATUS_PENDING = 0x02 | 129 STATUS_PENDING = 0x02 |
114 STATUS_FAILED = 0x80 | 130 STATUS_FAILED = 0x80 |
214 # Data to the device (mandatory) | 230 # Data to the device (mandatory) |
215 if self.bulkoutep == None: | 231 if self.bulkoutep == None: |
216 raise BaseException("Can't find bulk-out endpoint") | 232 raise BaseException("Can't find bulk-out endpoint") |
217 | 233 |
218 self.tag = 1 | 234 self.tag = 1 |
219 | 235 #self.init() |
236 | |
237 def init(self): | |
220 # Flush out any pending data | 238 # Flush out any pending data |
221 self.initiateClear() | 239 self.initiateClear() |
222 # Perform dummy write/read otherwise the next read times out | 240 # Perform dummy write/read otherwise the next read times out |
223 try: | 241 try: |
224 self.ask('*STB?', timeout = 0.001) | 242 self.ask('*STB?', timeout = 0.001) |
237 if self.serial != "": | 255 if self.serial != "": |
238 rtn += " S/N: " + self.serial | 256 rtn += " S/N: " + self.serial |
239 | 257 |
240 return rtn | 258 return rtn |
241 | 259 |
242 def incrtag(self): | 260 def gettag(self): |
261 tag = self.tag | |
243 self.tag = (self.tag + 1) % 255 | 262 self.tag = (self.tag + 1) % 255 |
244 if self.tag == 0: | 263 if self.tag == 0: |
245 self.tag += 1 | 264 self.tag += 1 |
265 return tag | |
246 | 266 |
247 def write(self, data): | 267 def write(self, data): |
248 """Send data (string) to the instrument""" | 268 """Send data (string) to the instrument""" |
249 | 269 |
250 orddata = list(map(ord, data)) | 270 orddata = list(map(ord, data)) |
252 if orddata[-1] != '\n': | 272 if orddata[-1] != '\n': |
253 orddata += [ord('\n')] | 273 orddata += [ord('\n')] |
254 datalen = len(orddata) | 274 datalen = len(orddata) |
255 | 275 |
256 # Build the packet | 276 # Build the packet |
257 pkt = [ DEV_DEP_MSG_OUT, self.tag, ~self.tag & 0xff, 0x00, | 277 tag = self.gettag() |
278 pkt = [ DEV_DEP_MSG_OUT, tag, ~tag & 0xff, 0x00, | |
258 datalen & 0xff, datalen >> 8 & 0xff, datalen >> 16 & 0xff, | 279 datalen & 0xff, datalen >> 8 & 0xff, datalen >> 16 & 0xff, |
259 datalen >> 24 & 0xff, 1, 0, 0, 0 ] | 280 datalen >> 24 & 0xff, 1, 0, 0, 0 ] |
260 | 281 |
261 # Add the data | 282 # Add the data |
262 pkt = pkt + orddata | 283 pkt = pkt + orddata |
263 | 284 |
264 # Align to 4 bytes | 285 # Align to 4 bytes |
265 alignlen = ((len(pkt) // 4) + 1) * 4 | 286 alignlen = ((len(pkt) // 4) + 1) * 4 |
266 pkt = pkt + [0] * (alignlen - len(pkt)) | 287 pkt = pkt + [0] * (alignlen - len(pkt)) |
267 | 288 |
268 # Bump the tag | |
269 self.incrtag() | |
270 | |
271 # Split it up into maxPacket sized chunks and send.. | 289 # Split it up into maxPacket sized chunks and send.. |
290 # XXX; this is not correct, need a header for each one | |
272 while len(pkt) > 0: | 291 while len(pkt) > 0: |
273 chunk = pkt[0:self.maxPacket] | 292 chunk = pkt[0:self.maxPacket] |
274 pkt = pkt[self.maxPacket:] | 293 pkt = pkt[self.maxPacket:] |
275 | 294 |
276 #print("Sending %s bytes of data: %s" % (len(chunk), chunk)) | 295 #print("Sending %d bytes of data: %s" % (len(chunk), chunk)) |
277 wrote = self.handle.bulkWrite(self.bulkoutep, chunk) | 296 wrote = self.handle.bulkWrite(self.bulkoutep, chunk) |
278 if wrote != len(chunk): | 297 if wrote != len(chunk): |
279 raise BaseException("Short write, got %d, expected %d" % (wrote, len(chunk))) | 298 raise BaseException("Short write, got %d, expected %d" % (wrote, len(chunk))) |
280 | 299 |
281 def read(self, timeout = None): | 300 def read(self, timeout = None): |
282 """Read data from the device, waits for up to timeout seconds for each USB transaction""" | 301 """Read data from the device, waits for up to timeout seconds for each USB transaction""" |
283 | 302 |
284 if timeout == None: | 303 if timeout == None: |
285 timeout = 0.5 | 304 timeout = 1 |
286 | 305 |
287 # Mangle into milliseconds | 306 # Mangle into milliseconds |
288 _timeout = int(timeout * 1000.0) | 307 _timeout = int(timeout * 1000.0) |
289 | 308 |
290 # Maximum we accept at once | 309 # Maximum we accept at once |
293 datalen = 10240 | 312 datalen = 10240 |
294 data = [] | 313 data = [] |
295 | 314 |
296 while True: | 315 while True: |
297 # Ask the device to send us something | 316 # Ask the device to send us something |
298 pkt = [ REQUEST_DEV_DEP_MSG_IN, self.tag, ~self.tag & 0xff, 0x00, | 317 tag = self.gettag() |
318 pkt = [ REQUEST_DEV_DEP_MSG_IN, tag, ~tag & 0xff, 0x00, | |
299 datalen & 0xff, datalen >> 8 & 0xff, datalen >> 16 & 0xff, | 319 datalen & 0xff, datalen >> 8 & 0xff, datalen >> 16 & 0xff, |
300 datalen >> 24 & 0xff, 0, 0, 0, 0] | 320 datalen >> 24 & 0xff, 0, 0, 0, 0] |
301 | |
302 # Expected tag | |
303 exptag = self.tag | |
304 | |
305 # Bump tag | |
306 self.incrtag() | |
307 | 321 |
308 # Send it | 322 # Send it |
309 #print("Sending " + str(pkt)) | 323 #print("Sending " + str(pkt)) |
310 wrote = self.handle.bulkWrite(self.bulkoutep, pkt, _timeout) | 324 wrote = self.handle.bulkWrite(self.bulkoutep, pkt, _timeout) |
311 if wrote != len(pkt): | 325 if wrote != len(pkt): |
315 read = self.handle.bulkRead(self.bulkinep, datalen, _timeout) | 329 read = self.handle.bulkRead(self.bulkinep, datalen, _timeout) |
316 #print("Read %s bytes: %s" % (len(read), str(read))) | 330 #print("Read %s bytes: %s" % (len(read), str(read))) |
317 | 331 |
318 if read[0] != DEV_DEP_MSG_IN: | 332 if read[0] != DEV_DEP_MSG_IN: |
319 raise BaseException("Unexpected Msg ID, got %s expected %d" % (read[0], DEV_DEP_MSG_IN)) | 333 raise BaseException("Unexpected Msg ID, got %s expected %d" % (read[0], DEV_DEP_MSG_IN)) |
320 if read[1] != exptag: | 334 if read[1] != tag: |
321 raise BaseException("Unexpected tag, got %d expected %d" % (read[1], exptag)) | 335 raise BaseException("Unexpected tag, got %d expected %d" % (read[1], tag)) |
322 if read[2] != ~exptag & 0xff: | 336 if read[2] != ~tag & 0xff: |
323 raise BaseException("Unexpected tag inverse, got %d expected %d" % (read[1], ~exptag & 0xff)) | 337 raise BaseException("Unexpected tag inverse, got %d expected %d" % (read[1], ~tag & 0xff)) |
324 | 338 |
325 actualdata = read[4] | read[5] << 8 | read[6] << 16 | read[7] << 24 | 339 actualdata = read[4] | read[5] << 8 | read[6] << 16 | read[7] << 24 |
326 #print("Computed datalen is %d" % (actualdata)) | 340 #print("Computed datalen is %d" % (actualdata)) |
327 data += read[12:12 + actualdata] | 341 data += read[12:12 + actualdata] |
328 if read[8] & 0x01: | 342 if read[8] & 0x01: |
360 return False | 374 return False |
361 | 375 |
362 return True | 376 return True |
363 | 377 |
364 def getCapabilities(self): | 378 def getCapabilities(self): |
365 '''Returns interface and device capability bytes (see IF_CAP_* and DEV_CAP_*)''' | 379 '''Returns interface, device and USB488 capability bytes (see IF_CAP_*, DEV_CAP_*, USB488_IFCAP_* and USB488_DEVCAP_*)''' |
366 res = self.handle.controlMsg(usb.ENDPOINT_IN | usb.TYPE_CLASS | usb.RECIP_INTERFACE, GET_CAPABILITIES, 0x18) | 380 res = self.handle.controlMsg(usb.ENDPOINT_IN | usb.TYPE_CLASS | usb.RECIP_INTERFACE, GET_CAPABILITIES, 0x18) |
367 return res[4], res[5] | 381 return res[4], res[5], res[14], res[15] |
368 | 382 |
369 def indicatorPulse(self): | 383 def indicatorPulse(self): |
370 '''Send an indicator pulse request''' | 384 '''Send an indicator pulse request''' |
371 res = self.handle.controlMsg(usb.ENDPOINT_IN | usb.TYPE_CLASS | usb.RECIP_INTERFACE, INDICATOR_PULSE, 0x01) | 385 res = self.handle.controlMsg(usb.ENDPOINT_IN | usb.TYPE_CLASS | usb.RECIP_INTERFACE, INDICATOR_PULSE, 0x01) |
372 | 386 |
377 while True: | 391 while True: |
378 res = self.handle.controlMsg(usb.ENDPOINT_IN | usb.TYPE_CLASS | usb.RECIP_INTERFACE, CHECK_CLEAR_STATUS, 0x02) | 392 res = self.handle.controlMsg(usb.ENDPOINT_IN | usb.TYPE_CLASS | usb.RECIP_INTERFACE, CHECK_CLEAR_STATUS, 0x02) |
379 if res[0] != STATUS_PENDING: | 393 if res[0] != STATUS_PENDING: |
380 break | 394 break |
381 time.sleep(0.1) | 395 time.sleep(0.1) |
382 self.handle.clearHalt(usb.ENDPOINT_IN | self.bulkinep) | 396 else: |
383 self.handle.clearHalt(usb.ENDPOINT_OUT | self.bulkoutep) | 397 raise BaseException('INITIATE_CLEAR returned 0x%02x' % (res[0])) |
398 self.handle.clearHalt(self.bulkinep) | |
399 self.handle.clearHalt(self.bulkoutep) | |
400 | |
401 def renControl(self): | |
402 '''Send enable remote control message''' | |
403 res = self.handle.controlMsg(usb.ENDPOINT_IN | usb.TYPE_CLASS | usb.RECIP_INTERFACE, REN_CONTROL, 1, 0xff) | |
404 return res[0] | |
405 | |
406 def getStatus(self): | |
407 '''Returns IEEE 488 status byte''' | |
408 tag = self.gettag() | |
409 res = self.handle.controlMsg(usb.ENDPOINT_IN | usb.TYPE_CLASS | usb.RECIP_INTERFACE, READ_STATUS_BYTE, 3, tag) | |
410 if res[1] != tag: | |
411 raise BaseException('Tag mismatch, got 0x%02x, expected 0x%02x' % (res[1], tag)) | |
412 if res[0] != STATUS_SUCCESS: | |
413 raise BaseException('Unit returned invalid USBTMC status: %d' % (res[0],)) | |
414 return res[2] | |
415 | |
416 def abortIO(self, tag, isout): | |
417 if isout: | |
418 req = INITIATE_ABORT_BULK_OUT | |
419 chkreq = CHECK_ABORT_BULK_OUT_STATUS | |
420 ep = self.bulkoutep | |
421 name = 'out' | |
422 else: | |
423 req = INITIATE_ABORT_BULK_IN | |
424 chkreq = CHECK_ABORT_BULK_IN_STATUS | |
425 ep = self.bulkinep | |
426 name = 'in' | |
427 res = self.handle.controlMsg(usb.ENDPOINT_IN | usb.TYPE_CLASS | usb.RECIP_ENDPOINT, | |
428 req, 2, value = tag, index = ep) | |
429 print('Initiate abort returned ' + str(res)) | |
430 while True: | |
431 res = self.handle.controlMsg(usb.ENDPOINT_IN | usb.TYPE_CLASS | usb.RECIP_ENDPOINT, | |
432 chkreq, 8, value = 0x00, index = ep) | |
433 print('Check abort returned ' + str(res)) | |
434 if res[0] == STATUS_PENDING: | |
435 print('Status pending for %s abort' % (name,)) | |
436 time.sleep(1) | |
437 elif res[0] == STATUS_SUCCESS or res[0] == STATUS_TRANSFER_NOT_IN_PROGRESS: | |
438 break | |
439 else: | |
440 raise BaseException('Invalid status reply to check abort %s 0x%02x' % (name, res[0])) |