00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 PID = [2098]
00016 VID = [22102]
00017
00018
00019 from ut2XXX_definitions import *
00020
00021 import usb, time, StringIO, sys, os
00022
00023 class UNI_T_DSO:
00024
00025
00026 def __init__(self):
00027
00028
00029 self.ch1_data = {}
00030 self.ch2_data = {}
00031 self.status = {}
00032
00033
00034 self.status["far_mode"] = False
00035 self.status["locked"] = False
00036 self.status["info_data"] = []
00037
00038
00039 self.ch1_data["samples"] = []
00040 self.ch1_data["V_div"] = 0
00041 self.ch1_data["s_div"] = 0
00042 self.ch1_data["couple"] =""
00043 self.ch1_data["active"] = False
00044 self.ch1_data["x_offset"] = 0
00045 self.ch1_data["Bw_limit"] = False
00046 self.ch1_data["header"] = []
00047 self.ch1_data["probe"] = 0
00048 self.ch1_data["probe_index"] = 0
00049 self.ch1_data["changed"] = False
00050 self.ch1_data["s_div_index"] = 0
00051 self.ch1_data["inverted"] = False
00052 self.ch1_data["y_offset"] = 125
00053 self.ch1_data["y_poz"] = 3803
00054
00055
00056 self.ch2_data["samples"] = []
00057 self.ch2_data["V_div"] = 0
00058 self.ch2_data["s_div"] = 0
00059 self.ch2_data["couple"] =""
00060 self.ch2_data["active"] = False
00061 self.ch2_data["x_offset"] = 0
00062 self.ch2_data["Bw_limit"] = False
00063 self.ch2_data["header"] = []
00064 self.ch2_data["probe"] = 0
00065 self.ch2_data["probe_index"] = 0
00066 self.ch2_data["changed"] = False
00067 self.ch2_data["s_div_index"] = 0
00068 self.ch2_data["inverted"] = False
00069 self.ch2_data["y_offset"] = 125
00070 self.ch2_data["y_poz"] = 3803
00071
00072 self.data_old = ()
00073 self.pixmap_data = ()
00074
00075 self.error_message = ""
00076
00077 self.init()
00078
00079 def init(self):
00080
00081 self.load_vid_pid()
00082 self.device = None
00083 self.interface_id = 0
00084 self.endpoints = []
00085 self.find_device()
00086 if not self.device:
00087 print "Error finding device. Exiting."
00088 self.is_present = False
00089 else:
00090 self.is_present = True
00091 self.handle = self.device.open()
00092 self.product = self.handle.getString(self.device.iProduct, 50),
00093 self.manufacturer = self.handle.getString(self.device.iManufacturer, 50)
00094 self.handle.claimInterface(self.interface_id)
00095
00096 self.init_device()
00097
00098 self.data = None
00099
00100 def load_vid_pid(self):
00101 self.path = os.path.dirname(sys.argv[0])
00102 try:
00103 for line in open(os.path.join(self.path,"./vid_pid.txt")):
00104 if len(line.split('#')[0])>0:
00105 line = line.replace('\r','').replace('\n','')
00106 VID.append(int(line.split('#')[0].split(',')[0]))
00107 PID.append(int(line.split('#')[0].split(',')[1]))
00108 except Exception, (s):
00109 print "Exception in reading VID/PID ->",s
00110
00111 print "Loaded VID/PIDS are:"
00112 print "VIDs -> ",VID
00113 print "PIDs -> ",PID
00114
00115
00116
00117 def find_device(self):
00118
00119 busses = usb.busses()
00120
00121 for bus in busses:
00122 devices = bus.devices
00123 for dev in devices:
00124
00125 if dev.idProduct in PID and dev.idVendor in VID:
00126 print "Found UNI-T DSO on USB:"
00127
00128 print " idVendor:",dev.idVendor
00129 print " idProduct:",dev.idProduct
00130
00131 self.device = dev
00132
00133 for config in dev.configurations:
00134 for intf in config.interfaces:
00135
00136 for alt in intf:
00137
00138
00139
00140
00141
00142 for ep in alt.endpoints:
00143 self.endpoints.append(ep.address)
00144
00145
00146
00147
00148
00149
00150 def enter_far_mode(self):
00151 ans = False
00152 try:
00153 self.handle.controlMsg(0x42,0xb1,None,value=0xf0)
00154 ans = True
00155 except Exception, (s):
00156 self.error_message = s
00157 print "Error entering remote control mode."
00158 else:
00159 self.status["far_mode"] = True
00160 return ans
00161
00162
00163 def leave_far_mode(self):
00164 ans = False
00165 try:
00166 self.handle.controlMsg(0x42,0xb1,None,value=0xf1)
00167 ans = True
00168 except Exception, (s):
00169 self.error_message = s
00170 print "Error leaving remote control mode."
00171 else:
00172 self.status["far_mode"] = False
00173 return ans
00174
00175 def get_info_from_device(self):
00176
00177
00178 ans = False
00179 try:
00180 self.handle.controlMsg(0x42,0xb1,None, value=0x2c)
00181 self.handle.controlMsg(0x00,0xb2,None)
00182 self.status["info_data"] = self.handle.controlMsg(0xc2,0xb2, 8)
00183 ans = True
00184 except Exception, (s):
00185 print "Error in get_info_from_device:",s
00186 self.error_message = s
00187 return ans
00188
00189 def send_message(self, message):
00190 ans = False
00191 try:
00192 self.handle.controlMsg(0x42,0xb1,None,value=message)
00193 time.sleep(0.05)
00194 ans = True
00195 except Exception, (s):
00196 print "Error in send_message:",s
00197 return ans
00198
00199 def get_data(self):
00200 for i in range(0,5):
00201 self.handle.controlMsg(0x42,0xb1,None,index=0, value=0xe1)
00202 time.sleep(0.03)
00203 self.handle.controlMsg(0x42,0xb0,None,index=2, value=0x01)
00204
00205 try:
00206 data = self.handle.bulkRead(130,1024,60)
00207 except:
00208
00209 data = self.data
00210 else:
00211 break
00212
00213 self.handle.controlMsg(0x42,0xb0,None,index=0, value=0xdc)
00214
00215
00216 return data
00217
00218 def get_parameters(self):
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232 self.handle.controlMsg(0x42,0xb1,None,index=0, value=0xe3)
00233 time.sleep(0.05)
00234 self.handle.controlMsg(0x42,0xb0,None)
00235 try:
00236 data = self.handle.bulkRead(0x82,512,500)
00237 except:
00238 print "Exception, sending old data."
00239 self.handle.controlMsg(0x42,0xb0,None,index=0, value=0xdc)
00240 data = self.data
00241
00242 self.handle.controlMsg(0x42,0xb0,None,index=0, value=0xdc)
00243 return data
00244
00245 def ping(self):
00246
00247
00248 self.handle.controlMsg(0x42,0xb0,None,index=0, value=0xdc)
00249 time.sleep(0.02)
00250 self.handle.controlMsg(0x42,0xb1,None,index=0, value=0xcc)
00251 time.sleep(0.02)
00252
00253
00254 def close(self):
00255 print "Closing, bye."
00256 self.leave_far_mode()
00257 self.handle.releaseInterface()
00258
00259
00260 def init_device(self):
00261 try:
00262 print self.handle.controlMsg(0xc2,0xb2,8,index=4, value=0x08, timeout=300)
00263 time.sleep(0.02)
00264 except:
00265 pass
00266 self.handle.controlMsg(0x42,0xb1,None,index=0, value=0x2c)
00267 time.sleep(0.02)
00268 self.handle.controlMsg(0x42,0xb1,None,index=0, value=0xdc)
00269 time.sleep(0.02)
00270 self.handle.controlMsg(0x42,0xb1,None,index=0, value=0xcc)
00271 time.sleep(0.02)
00272 self.handle.controlMsg(0x42,0xb1,None,index=0, value=0xcc)
00273 time.sleep(0.02)
00274 self.leave_far_mode()
00275
00276
00277 def print_status(self):
00278 print "Device:",self.product[0]
00279 print "Manufacturer:", self.manufacturer
00280 self.get_waveform()
00281 print "------------------------------"
00282 if self.ch1_data["active"]:
00283 print "Chanel 1: ON"
00284 else:
00285 print "Chanel 1: OFF"
00286 print " X range: ", self.ch1_data["V_div"],"V/div"
00287 print " Coupling:", self.ch1_data["couple"]
00288 print " Y range: ", self.ch1_data["s_div"], "s/div"
00289
00290 if self.ch2_data["active"]:
00291 print "Chanel 2: ON"
00292 else:
00293 print "Chanel 2: OFF"
00294 print " X range: ", self.ch2_data["V_div"],"V/div"
00295 print " Coupling:", self.ch2_data["couple"]
00296 print " Y range: ", self.ch2_data["s_div"], "s/div"
00297
00298
00299 def parse_waveform(self, filename):
00300 self.get_waveform(open(filename).readlines())
00301
00302
00303
00304 def get_waveform(self, extern_data = None):
00305
00306 data = None
00307 if not extern_data:
00308 data = self.get_data()
00309 else:
00310 data = extern_data
00311 print "Data length is:",len(data)
00312
00313
00314 if not data == None and len(data) >= 1024:
00315
00316 if not self.ch1_data["header"] == data[0:32]:
00317 self.ch1_data["changed"] = True
00318
00319
00320
00321
00322
00323 else:
00324 self.ch1_data["changed"] = False
00325
00326 if not self.ch2_data["header"] == data[32:64]:
00327 self.ch2_data["changed"] = True
00328 else:
00329 self.ch2_data["changed"] = False
00330
00331 self.ch1_data["header"] = data[0:32]
00332 self.ch2_data["header"] = data[32:64]
00333
00334
00335 self.ch1_data["V_div"] = Y_RANGE[data[Y_SENSE_CH1]]*(10**(data[Y_PROBE_CH1]))
00336 self.ch1_data["V_div_index"] = data[Y_SENSE_CH1]
00337 self.ch2_data["V_div"] = Y_RANGE[data[Y_SENSE_CH2]]*(10**(data[Y_PROBE_CH2]))
00338 self.ch2_data["V_div_index"] = data[Y_SENSE_CH2]
00339
00340 self.ch1_data["probe"] = 10**(data[Y_PROBE_CH1])
00341 self.ch1_data["probe_index"] = data[Y_PROBE_CH1]
00342 self.ch2_data["probe"] = 10**(data[Y_PROBE_CH2])
00343 self.ch2_data["probe_index"] = data[Y_PROBE_CH2]
00344
00345 self.ch1_data["couple"] = COUPLING[data[COUPLING_CH1]]
00346 self.ch2_data["couple"] = COUPLING[data[COUPLING_CH2]]
00347 self.ch1_data["couple_index"] = data[COUPLING_CH1]
00348 self.ch2_data["couple_index"] = data[COUPLING_CH2]
00349
00350 if len(data) == 1024:
00351 self.ch1_data["samples"] = data[516:766]
00352 self.ch2_data["samples"] = data[770:1020]
00353
00354 elif len(data) == 2560:
00355 self.ch1_data["samples"] = data[516:1266]
00356 self.ch2_data["samples"] = data[1520:2270]
00357
00358 else:
00359 print "Unexcepted length of data sample, no data decoded then."
00360
00361
00362 self.ch1_data["s_div"] = X_RANGE[data[X_SCALE_CH1]]
00363 self.ch1_data["s_div_index"] = data[X_SCALE_CH1]
00364 self.ch2_data["s_div"] = X_RANGE[data[X_SCALE_CH2]]
00365 self.ch2_data["s_div_index"] = data[X_SCALE_CH2]
00366
00367 self.ch1_data["active"] = bool(data[CHANNEL_STATE] & 0x01)
00368 self.ch2_data["active"] = bool(data[CHANNEL_STATE] & 0x02)
00369
00370 self.ch1_data["y_offset"] = 0x7e - data[Y_POS_CH1]
00371
00372 self.ch2_data["y_offset"] = 0x7e - data[Y_POS_CH2]
00373
00374 self.ch1_data["Bw_limit"] = bool(data[BW_LIMIT_CH1])
00375 self.ch2_data["Bw_limit"] = bool(data[BW_LIMIT_CH2])
00376
00377 self.ch1_data["inverted"] = bool(data[INVERTED_CH1])
00378 self.ch2_data["inverted"] = bool(data[INVERTED_CH2])
00379
00380 self.ch1_data["x_offset"] = data[X_CURSOR_CH1]
00381 self.ch2_data["x_offset"] = data[X_CURSOR_CH2]
00382
00383 self.ch1_data["x_poz"] = (data[8] << 8) + data[7]
00384 self.ch2_data["x_poz"] = (data[40] << 8) + data[39]
00385
00386 else:
00387 print time.time(),"Data buffer error"
00388
00389 def test_screenshot(self):
00390 self.get_screenshot()
00391 for i in range(0,len(self.data)):
00392 try:
00393 if self.data_old[i] != self.data[i]:
00394 print "Zmena na", i
00395 except:
00396 pass
00397 self.data_old = self.data
00398
00399 def get_screenshot(self, filename=""):
00400 self.data = ()
00401
00402
00403
00404
00405 ts = time.time()
00406 self.handle.controlMsg(0x42,0xb1,None,index=0, value=0xe2)
00407 time.sleep(0.05)
00408 self.handle.controlMsg(0x42,0xb0,None,index=2, value=0x26)
00409
00410 self.pixmap_data = self.handle.bulkRead(130,38912,1000)
00411 print "Processing time:",time.time() - ts
00412 print "Loaded:",len(self.pixmap_data),"bytes"
00413
00414 pixel_data = []
00415
00416 if len(self.pixmap_data) == 38912:
00417 pixel_data = self.write_pixmap(filename)
00418 else:
00419 print "Too few data for screenshot."
00420 return pixel_data
00421
00422
00423 def write_pixmap(self, filename=""):
00424
00425
00426 bitmap_data = StringIO.StringIO()
00427
00428
00429 width=320; height=240
00430 ftype='P6'
00431 try:
00432 if filename == "":
00433 ppmfile=open('testimage.ppm','wb')
00434 else:
00435 ppmfile=open(filename,'wb')
00436
00437 bitmap_data.write("%s\n" % (ftype))
00438 bitmap_data.write("%d %d\n" % (width, height))
00439 bitmap_data.write("255\n")
00440
00441
00442 for index in range(0,len(self.pixmap_data),2):
00443
00444
00445
00446
00447
00448
00449 color = self.pixmap_data[index+1]
00450 color2 = ((color) & 0x0F)
00451 color1 = ((color) & 0xF0) / 16
00452
00453 color = self.pixmap_data[index]
00454 color4 = ((color) & 0x0F)
00455 color3 = ((color) & 0xF0) / 16
00456
00457
00458 bitmap_data.write("%c%c%c" % self.convert_to_color(color1))
00459
00460
00461 bitmap_data.write("%c%c%c" % self.convert_to_color(color2))
00462
00463
00464 bitmap_data.write("%c%c%c" % self.convert_to_color(color3))
00465
00466
00467 bitmap_data.write("%c%c%c" % self.convert_to_color(color4))
00468
00469 except Exception, (s):
00470 print "Exception in write_pixmap:",filename," -> ",s
00471
00472 finally:
00473 s = bitmap_data.getvalue()
00474 ppmfile.write(s)
00475 bitmap_data.close()
00476 ppmfile.close()
00477 return s
00478
00479
00480 def convert_to_color(self, color):
00481
00482
00483 if color == 0x00:
00484 return (0,0,0)
00485
00486 elif color == 0x01:
00487 return (0,0,64)
00488
00489 elif color == 0x05:
00490 return (0,0,192)
00491
00492 elif color == 0x06:
00493 return (0,224,0)
00494
00495 elif color == 0x07:
00496 return (128,32,0)
00497
00498 elif color == 0x08:
00499 return (0,125,125)
00500
00501 elif color == 0x09:
00502 return (128,32,0)
00503
00504 elif color == 0x0A:
00505 return (125,125,125)
00506
00507 elif color == 0x0b:
00508 return (0,0,128)
00509
00510 elif color == 0x0C:
00511 return (0,192,192)
00512
00513 elif color == 0x0D:
00514 return (255,255,0)
00515
00516 elif color == 0x0E:
00517 return (224,32,0)
00518
00519 elif color == 0x0F:
00520 return (255,255,255)
00521 else:
00522 print "Unsuported color:", color
00523 return (255,255,255)
00524
00525 def test_parameters(self):
00526 data = dso.get_parameters()
00527 if self.data == None:
00528 self.data = data
00529 for i in range(0,150):
00530 if not self.data[i] == data[i]:
00531 print "Change at",i,"value prev./now",self.data[i],"/",data[i]
00532
00533 self.data = data
00534
00535
00536 if __name__ == '__main__':
00537
00538 dso = UNI_T_DSO()
00539 if dso.is_present:
00540 dso.get_info_from_device()
00541 while raw_input("q = konec / quit") != "q":
00542 dso.test_parameters()
00543
00544 dso.leave_far_mode()
00545 dso.ping()
00546
00547 dso.close()
00548 else:
00549 print "Device was not recognized or found."