mirror of
https://github.com/dustinbrun/JDS6600_python_Influx-DB_logger.git
synced 2025-03-19 18:07:42 +00:00
1894 lines
46 KiB
Python
1894 lines
46 KiB
Python
# jds6600.py
|
|
# library to remote-control a JDS6600 signal generator
|
|
|
|
# Kristoff Bonne (c) 2018
|
|
# published under MIT license. See file "LICENSE" for full license text
|
|
|
|
# Revisions:
|
|
# Version 0.0.1: 2018/01/19: initial release, reading basic parameters
|
|
# version 0.0.2: 2018/01/28: added "measure" menu + support functions, documentation
|
|
# version 0.0.3: 2018/02/07: added "counter" and "sweep" menu
|
|
# version 0.0.4: 2018/02/14: added "pulse" and "burst" menu + code cleanup
|
|
# version 0.0.5: 2018/02/16: added system menu
|
|
# version 0.1.0: 2018/02/17: added arbitrary waveform
|
|
|
|
|
|
import serial
|
|
import binascii
|
|
|
|
|
|
###########
|
|
# Errors #
|
|
###########
|
|
|
|
class UnknownChannelError(ValueError):
|
|
pass
|
|
|
|
class UnexpectedValueError(ValueError):
|
|
pass
|
|
|
|
class UnexpectedReplyError(ValueError):
|
|
pass
|
|
|
|
class FormatError(ValueError):
|
|
pass
|
|
|
|
class WrongMode(RuntimeError):
|
|
# called when commands are issued with the jds6600 not in the correct
|
|
# mode
|
|
pass
|
|
|
|
|
|
#################
|
|
# jds6600 class #
|
|
#################
|
|
|
|
class jds6600:
|
|
'jds6600 top-level class'
|
|
|
|
# serial device (opened during object init))
|
|
ser = None
|
|
|
|
# commands
|
|
DEVICETYPE=0
|
|
SERIALNUMBER=1
|
|
|
|
CHANNELENABLE=20
|
|
WAVEFORM1=21
|
|
WAVEFORM2=22
|
|
FREQUENCY1=23
|
|
FREQUENCY2=24
|
|
AMPLITUDE1=25
|
|
AMPLITUDE2=26
|
|
OFFSET1=27
|
|
OFFSET2=28
|
|
DUTYCYCLE1=29
|
|
DUTYCYCLE2=30
|
|
PHASE=31
|
|
|
|
ACTION=32
|
|
MODE=33
|
|
|
|
MEASURE_COUP=36 # coupling (AC or DC)
|
|
MEASURE_GATE=37 # gatetime
|
|
MEASURE_MODE=38 # mode (Freq or Periode)
|
|
|
|
COUNTER_COUPL=MEASURE_COUP
|
|
COUNTER_RESETCOUNTER=39
|
|
|
|
SWEEP_STARTFREQ=40
|
|
SWEEP_ENDFREQ=41
|
|
SWEEP_TIME=42
|
|
SWEEP_DIRECTION=43
|
|
SWEEP_MODE=44 # mode: linair or Log
|
|
|
|
PULSE_PULSEWIDTH=45
|
|
PULSE_PERIOD=46
|
|
PULSE_OFFSET=47
|
|
PULSE_AMPLITUDE=48
|
|
|
|
BURST_NUMBER=49
|
|
BURST_MODE=50
|
|
|
|
|
|
SYSTEM_SOUND=51
|
|
SYSTEM_BRIGHTNESS=52
|
|
SYSTEM_LANGUAGE=53
|
|
SYSTEM_SYNC=54
|
|
SYSTEM_ARBMAXNUM=55
|
|
|
|
PROFILE_SAVE=70
|
|
PROFILE_LOAD=71
|
|
PROFILE_CLEAR=72
|
|
|
|
COUNTER_DATA_COUNTER=80
|
|
|
|
MEASURE_DATA_FREQ_LOWRES=81 # low resolution freq counter, used for mode "frequency"
|
|
MEASURE_DATA_FREQ_HIGHRES=82 # high resolution freq. counter, usef for mode "period". UI: valid up to 2 Khz
|
|
MEASURE_DATA_PW1=83
|
|
MEASURE_DATA_PW0=84
|
|
MEASURE_DATA_PERIOD=85
|
|
MEASURE_DATA_DUTYCYCLE=86
|
|
MEASURE_DATA_U1=87
|
|
MEASURE_DATA_U2=88
|
|
MEASURE_DATA_U3=89
|
|
|
|
|
|
|
|
|
|
# waveforms: registers 21 (ch1) and 22 (ch2))
|
|
# 0 to 16: predefined waveforms
|
|
__wave=("SINE","SQUARE","PULSE","TRIANGLE","PARTIALSINE","CMOS","DC","HALF-WAVE","FULL-WAVE","POS-LADDER","NEG-LADDER", "NOISE", "EXP-RIZE","EXP-DECAY","MULTI-TONE","SINC","LORENZ")
|
|
# 101 to 160: arbitrary waveforms
|
|
__awave=[]
|
|
for a in range(1,10):
|
|
__awave.append("ARBITRARY0"+str(a))
|
|
for a in range(10,61):
|
|
__awave.append("ARBITRARY"+str(a))
|
|
# end for
|
|
|
|
|
|
# modes: register 33
|
|
# note: use lowest 4 bits for wrting
|
|
# note: use highest 4 bits for reading
|
|
__modes = ((0,"WAVE_CH1"),(0,"WAVE_CH1"),(1,"WAVE_CH2"),(1,"WAVE_CH2"),(2,"SYSTEM"),(2,"SYSTEM"),(-1,""),(-1,""),(4,"MEASURE"),(5,"COUNTER"),(6,"SWEEP_CH1"),(7,"SWEEP_CH2"),(8,"PULSE"),(9,"BURST"))
|
|
|
|
# action: register 32
|
|
__actionlist=(("STOP","0,0,0,0"),("COUNT","1,0,0,0"),("SWEEP","0,1,0,0"),("PULSE","1,0,1,1"),("BURST","1,0,0,1"))
|
|
__action={}
|
|
for (actionname,actioncode) in __actionlist:
|
|
__action[actionname]=actioncode
|
|
# end for
|
|
|
|
|
|
# measure mode parameters
|
|
__measure_coupling=("AC(EXT.IN)","DC(EXT.IN)")
|
|
__measure_mode=("M.FREQ","M.PERIOD")
|
|
|
|
|
|
# sweep parameters
|
|
__sweep_direction=("RISE","FALL","RISE&FALL")
|
|
__sweep_mode=("LINEAR","LOGARITHM")
|
|
|
|
|
|
# burst parameters
|
|
__burst_mode=["MANUAL TRIG.","CH2 TRIG.","EXT.TRIG(AC)","EXT.TRIG(DC)"]
|
|
|
|
# frequency multiplier
|
|
__freqmultiply=(1,1,1,1/1000,1/1000000)
|
|
|
|
|
|
# language
|
|
__system_language=("ENGLISH","CHINESE")
|
|
|
|
###############
|
|
# oonstructor #
|
|
###############
|
|
|
|
def __init__(self,fname):
|
|
jds6600.ser = serial.Serial(
|
|
port= fname,
|
|
baudrate=115200,
|
|
parity=serial.PARITY_NONE,
|
|
stopbits=serial.STOPBITS_ONE,
|
|
bytesize=serial.EIGHTBITS,
|
|
timeout=1 )
|
|
# end constructor
|
|
|
|
|
|
|
|
#####################
|
|
# support functions #
|
|
#####################
|
|
|
|
#####
|
|
# low-level support function
|
|
|
|
# parse data from read command
|
|
def __parsedata(self,reg,data,a):
|
|
if a not in (0,1): raise RuntimeError(a)
|
|
|
|
try:
|
|
(one,two)=data.split("=")
|
|
except ValueError:
|
|
raise FormatError("Parsing Returned data: Invalid format, missing \"=\"")
|
|
|
|
two_b=two.split(".")
|
|
|
|
# reads from register are terminated by a "."
|
|
# reads of arbitrary waveform are not
|
|
if a == 0:
|
|
if len(two_b) < 2:
|
|
raise FormatError("Parsing Returned data: Invalid format, missing \".\"")
|
|
|
|
if len(two_b) > 2:
|
|
raise FormatError("Parsing Returned data: Invalid format, too many \".\"")
|
|
# end if
|
|
|
|
# command to look for;
|
|
# "r" for register read, "b" for arbitrary waveform read
|
|
c = 'r' if a == 0 else 'b'
|
|
|
|
# check if returned data matches reg that was send
|
|
if reg != None:
|
|
if one != ":"+c+reg:
|
|
errmsg="Parsing Return data: send/received reg mismatch: "+data+" / expected :"+c+reg
|
|
raise FormatError(errmsg)
|
|
# end if
|
|
# end if
|
|
|
|
# done: return data: part between "=" and ".", split on ","
|
|
return two_b[0].split(",")
|
|
# end __parsedata
|
|
|
|
# command in textual form
|
|
def __reg2txt(self,reg):
|
|
return "0"+str(reg) if int(reg) < 10 else str(reg)
|
|
# end reg2txt
|
|
|
|
# send read command (for n datapoint)
|
|
def __sendreadcmd(self,reg,n,a):
|
|
if type(n) != int: raise TypeError(n)
|
|
if a not in (0,1): raise ValueError(a)
|
|
|
|
regtxt=self.__reg2txt(reg)
|
|
if (n < 1):
|
|
raise ValueError(n)
|
|
|
|
if a == 0:
|
|
# a (arbitrary waveform) is 0 -> register read
|
|
c='r' # register
|
|
else:
|
|
c='b' # arbitrary waveform
|
|
# for n to 1
|
|
n=1
|
|
# end else - if
|
|
|
|
# "n" in command start with 0 for 1 read-request
|
|
n -= 1
|
|
|
|
if self.ser.is_open == True:
|
|
tosend=":"+c+regtxt+"="+str(n)+"."+chr(0x0a)
|
|
self.ser.write(tosend.encode())
|
|
# end __sendreadcmd
|
|
|
|
|
|
|
|
# get responds of read-request and parse ("n" reads)
|
|
def __getrespondsandparse(self,reg, n, a):
|
|
if type(n) != int: raise ValueError(n)
|
|
if a not in (0,1): raise ValueError(a) # a=0-> register read, a=1 -> arbitrary waveform read
|
|
|
|
ret=[] # return value
|
|
|
|
c = int(reg) # counter
|
|
c_expect=self.__reg2txt(c)
|
|
for l in range(n):
|
|
# get one line responds from serial device
|
|
retserial=self.ser.readline()
|
|
# convert bytearray into string, then strip off terminating \n and \r
|
|
retserial=str(retserial,'utf-8').rstrip()
|
|
|
|
# get parsed data
|
|
# assume all data are single-value fields
|
|
parseddata=self.__parsedata(c_expect,retserial,a)
|
|
|
|
# we receive a list of strings, all containing numeric (integer) values
|
|
|
|
if len(parseddata) == 1:
|
|
# if list with one value, return that value (converted to integer)
|
|
ret.append(int(parseddata[0]))
|
|
else:
|
|
# if list with multiple values, convert all strings to integers and return list
|
|
retlist=[]
|
|
retcount=0
|
|
for data in parseddata:
|
|
if data == "":
|
|
# we should not receive empty datafields, except for after the last element of an arbitrary waveform
|
|
if not ((a == 1) and (retcount == 2048)):
|
|
raise UnexpectedValueError(parseddata)
|
|
else:
|
|
retlist.append(int(data))
|
|
# end else - if
|
|
|
|
retcount += 1
|
|
# end for
|
|
ret.append(retlist)
|
|
# end else - if
|
|
|
|
# increase next expected to-receive data
|
|
c += 1
|
|
c_expect=self.__reg2txt(c)
|
|
# end for
|
|
|
|
# return parsed data
|
|
# if only one element, return that element
|
|
# if multiple elements, return list
|
|
return ret[0] if n == 1 else ret
|
|
# end __get responds and parse 1
|
|
|
|
|
|
# get data
|
|
def __getdata(self,reg, n=1, a=0):
|
|
if type(reg) != int: raise TypeError(reg)
|
|
if type(n) != int: raise TypeError(n)
|
|
|
|
# a is "arbitrary waveform or register"
|
|
# a=0 -> register read
|
|
# a=1 -> arbitrary waveform read
|
|
|
|
# send "read" commandline for "n" lines
|
|
# copy "a" parameter from calling function
|
|
self.__sendreadcmd(reg,n,a)
|
|
|
|
return self.__getrespondsandparse(reg,n,a)
|
|
# end __getdata 1
|
|
|
|
|
|
# send write command and wait for "ok"
|
|
def __sendwritecmd(self,reg, val, a=0):
|
|
# note: a = "arbitrary waveform?": 0 = no (register write), 1 = yes (arb. waveform write)
|
|
# add a "0" to the command if it one single character
|
|
reg=self.__reg2txt(reg)
|
|
|
|
# command to send: "w" for register write, "b" for arbitrary waveform write
|
|
cmd = "w" if a == 0 else "a"
|
|
|
|
if self.ser.is_open == True:
|
|
if type(val) == int: val = str(val)
|
|
if type(val) != str: raise TypeError(val)
|
|
|
|
tosend=":"+cmd+reg+"="+val+"."+chr(0x0a)
|
|
self.ser.write(tosend.encode())
|
|
|
|
# wait for "ok"
|
|
|
|
# get one line responds from serial device
|
|
ret=self.ser.readline()
|
|
# convert bytearray into string, then strip off terminating \n and \r
|
|
ret=str(ret,'utf-8').rstrip()
|
|
|
|
if ret != ":ok":
|
|
raise UnexpectedReplyError(ret)
|
|
# end if
|
|
|
|
#end if
|
|
# end __sendwritecmd
|
|
|
|
|
|
#####
|
|
# high-level support function
|
|
|
|
# set action
|
|
def __setaction(self,action):
|
|
# type check
|
|
if type(action) != str:
|
|
raise TypeError(action)
|
|
# end if
|
|
|
|
try:
|
|
self.__sendwritecmd(jds6600.ACTION,jds6600.__action[action])
|
|
except KeyError:
|
|
errmsg="Unknown Action: "+action
|
|
raise ValueError(errmsg)
|
|
# end try
|
|
|
|
# end set action
|
|
|
|
###################
|
|
# DEBUG functions #
|
|
###################
|
|
|
|
def DEBUG_readregister(self,register,count):
|
|
if self.ser.is_open == True:
|
|
regtxt=self.__reg2txt(register)
|
|
tosend=":r"+regtxt+"="+str(count)+"."+chr(0x0a)
|
|
self.ser.write(tosend.encode())
|
|
|
|
ret=self.ser.readline()
|
|
while ret != b'':
|
|
print(str(ret))
|
|
ret=self.ser.readline()
|
|
# end while
|
|
# end if
|
|
# end readregister
|
|
|
|
def DEBUG_writeregister(self,register,value):
|
|
if self.ser.is_open == True:
|
|
regtxt=self.__reg2txt(register)
|
|
if type(value) == int:
|
|
value=str(value)
|
|
|
|
tosend=":w"+regtxt+"="+value+"."+chr(0x0a)
|
|
self.ser.write(tosend.encode())
|
|
|
|
ret=self.ser.readline()
|
|
while ret != b'':
|
|
print(str(ret))
|
|
ret=self.ser.readline()
|
|
# end while
|
|
# end if
|
|
|
|
# end write register
|
|
|
|
|
|
##############
|
|
# PUBLIC API #
|
|
##############
|
|
|
|
#########################
|
|
# Part 0: API information
|
|
|
|
|
|
# API version
|
|
def getAPIinfo_version(self):
|
|
return 1
|
|
# end getAPIversion
|
|
|
|
# API release number
|
|
def getAPIinfo_release(self):
|
|
return "0.1.0 2018-02-17"
|
|
# end get API release
|
|
|
|
|
|
#############################
|
|
# Part 1: information queries
|
|
|
|
# list of waveforms
|
|
def getinfo_waveformlist(self):
|
|
waveformlist=list(enumerate(jds6600.__wave))
|
|
for aw in (enumerate(jds6600.__awave,101)):
|
|
waveformlist.append(aw)
|
|
# end for
|
|
|
|
return waveformlist
|
|
# end get waveform list
|
|
|
|
|
|
# get list of modes
|
|
def getinfo_modelist(self):
|
|
modelist=[]
|
|
|
|
lastmode=-1
|
|
|
|
# create list of modes, removing dups
|
|
for (modeid,modetxt) in jds6600.__modes:
|
|
# ignore modes with modeid < 0 (unused mode)
|
|
if modeid < 0:
|
|
continue
|
|
# end if
|
|
|
|
if modeid != lastmode:
|
|
modelist.append((modeid,modetxt))
|
|
lastmode = modeid
|
|
# end if
|
|
# end for
|
|
|
|
return modelist
|
|
# end getinfo modelist
|
|
|
|
|
|
##################################
|
|
# Part 2: reading basic parameters
|
|
|
|
# get device type
|
|
def getinfo_devicetype(self):
|
|
return self.__getdata(jds6600.DEVICETYPE)
|
|
# end get device type
|
|
|
|
|
|
# get serial number
|
|
def getinfo_serialnumber(self):
|
|
return self.__getdata(jds6600.SERIALNUMBER)
|
|
# end get serial number
|
|
|
|
|
|
# get channel enable status
|
|
def getchannelenable(self):
|
|
(ch1,ch2)=self.__getdata(jds6600.CHANNELENABLE)
|
|
try:
|
|
return (False,True)[ch1], (False,True)[ch2]
|
|
except IndexError:
|
|
errmsg="Unexpected value received: {},{}".format(ch1,ch2)
|
|
raise UnexpectedValueError(errmsg)
|
|
# end get channel enable status
|
|
|
|
# get waveform
|
|
def getwaveform(self, channel):
|
|
if type(channel) != int: raise TypeError(channel)
|
|
if not (channel in (1,2)): raise ValueError(channel)
|
|
|
|
#WAVEFORM for channel 2 is WAVEFORM1 + 1
|
|
waveform=self.__getdata(jds6600.WAVEFORM1+channel-1)
|
|
|
|
# waveform 0 to 16 are in "wave" list, 101 to 160 are in __awave
|
|
try:
|
|
return (waveform,jds6600.__wave[waveform])
|
|
except IndexError:
|
|
pass
|
|
|
|
try:
|
|
return (waveform,jds6600.__awave[waveform-101])
|
|
except IndexError:
|
|
raise UnexpectedValueError(waveform)
|
|
# end getwaveform
|
|
|
|
# get frequency _with multiplier
|
|
def getfrequency_m(self,channel):
|
|
if type(channel) != int: raise TypeError(channel)
|
|
if not (channel in (1,2)): raise ValueError(channel)
|
|
|
|
(f1,f2)=self.__getdata(jds6600.FREQUENCY1+channel-1)
|
|
|
|
# parse multiplier (value after ",")
|
|
# 0=Hz, 1=KHz,2=MHz, 3=mHz,4=uHz)
|
|
# note f1 is frequency / 100
|
|
try:
|
|
return((f1/100*self.__freqmultiply[f2],f2))
|
|
except IndexError:
|
|
# unexptected value of frequency multiplier
|
|
raise UnexpectedValueError(f2)
|
|
# end elsif
|
|
# end function getfreq
|
|
|
|
# get frequency _no multiplier information
|
|
def getfrequency(self,channel):
|
|
if type(channel) != int: raise TypeError(channel)
|
|
if not (channel in (1,2)): raise ValueError(channel)
|
|
|
|
(f1,f2)=self.__getdata(jds6600.FREQUENCY1+channel-1)
|
|
|
|
# parse multiplier (value after ","): 0=Hz, 1=KHz,2=MHz, 3=mHz,4=uHz)
|
|
# note1: frequency unit is Hz / 100
|
|
# note2: multiplier 1 (khz) and 2 (mhz) only changes the visualisation on the
|
|
# display of the jfs6600. The frequency itself is calculated in
|
|
# the same way as for multiplier 0 (Hz)
|
|
# mulitpliers 3 (mHZ) and 4 (uHz) do change the calculation of the frequency
|
|
try:
|
|
return(f1/100*self.__freqmultiply[f2])
|
|
except IndexError:
|
|
# unexptected value of frequency multiplier
|
|
raise UnexpectedValueError(f2)
|
|
# end elsif
|
|
# end function getfreq
|
|
|
|
|
|
# get amplitude
|
|
def getamplitude(self, channel):
|
|
if type(channel) != int: raise TypeError(channel)
|
|
if not (channel in (1,2)): raise ValueError(channel)
|
|
|
|
amplitude=self.__getdata(jds6600.AMPLITUDE1+channel-1)
|
|
|
|
# amplitude is mV -> so divide by 1000
|
|
return amplitude/1000
|
|
# end getamplitude
|
|
|
|
|
|
# get offset
|
|
def getoffset(self, channel):
|
|
if type(channel) != int: raise TypeError(channel)
|
|
if not (channel in (1,2)): raise ValueError(channel)
|
|
|
|
offset=self.__getdata(jds6600.OFFSET1+channel-1)
|
|
|
|
# offset unit is 10 mV, and then add 1000
|
|
return (offset-1000)/100
|
|
# end getoffset
|
|
|
|
# get dutcycle
|
|
def getdutycycle(self, channel):
|
|
if type(channel) != int: raise TypeError(channel)
|
|
if not (channel in (1,2)): raise ValueError(channel)
|
|
|
|
dutycycle=self.__getdata(jds6600.DUTYCYCLE1+channel-1)
|
|
|
|
# dutycycle unit is 0.1 %, so divide by 10
|
|
return dutycycle/10
|
|
# end getdutycycle
|
|
|
|
|
|
# get phase
|
|
def getphase(self):
|
|
phase=self.__getdata(jds6600.PHASE)
|
|
|
|
# phase unit is 0.1 degrees, so divide by 10
|
|
return phase/10
|
|
# end getphase
|
|
|
|
|
|
##################################
|
|
# Part 3: writing basic parameters
|
|
|
|
|
|
# set channel enable
|
|
def setchannelenable(self,ch1,ch2):
|
|
if type(ch1) != bool: raise TypeError(ch1)
|
|
if type(ch2) != bool: raise TypeError(ch1)
|
|
|
|
# channel 1
|
|
if ch1 == True: enable = "1"
|
|
else: enable = "0" # end else - if
|
|
|
|
if ch2 == True: enable += ",1"
|
|
else: enable += ",0" # end else - if
|
|
|
|
# write command
|
|
self.__sendwritecmd(jds6600.CHANNELENABLE,enable)
|
|
# end set channel enable
|
|
|
|
# set waveform
|
|
def setwaveform(self,channel,waveform):
|
|
if type(channel) != int: raise TypeError(channel)
|
|
if (type(waveform) != int) and (type(waveform) != str): raise TypeError(waveform)
|
|
|
|
if not (channel in (1,2)): raise ValueError(channel)
|
|
|
|
# wzveform can be integer or string
|
|
w=None
|
|
|
|
if type(waveform) == int:
|
|
# waveform is an integer
|
|
if waveform < 101:
|
|
try:
|
|
jds6600.__wave[waveform]
|
|
except IndexError:
|
|
raise ValueError(waveform)
|
|
# end try
|
|
|
|
else:
|
|
try:
|
|
jds6600.__awave[waveform-101]
|
|
except IndexError:
|
|
raise ValueError(waveform)
|
|
# end try
|
|
# end if
|
|
|
|
# ok, it exists!
|
|
w=waveform
|
|
|
|
else:
|
|
# waveform is a string
|
|
|
|
# make everything uppercase
|
|
waveform=waveform.upper()
|
|
# check all waveform descriptions in wave and __awave
|
|
# w is already initialised as "none" above
|
|
|
|
try:
|
|
# try in "wave" list
|
|
w=jds6600.__wave.index(waveform)
|
|
except ValueError:
|
|
pass
|
|
|
|
if w == None:
|
|
#if not found in "wave", try the "awave" list
|
|
try:
|
|
w=jds6600.__awave.index(waveform)+101 # arbitrary waveforms state are index 101
|
|
except ValueError:
|
|
pass
|
|
# end try
|
|
# end if
|
|
|
|
if w == None:
|
|
# not in "wave" and "awave" error
|
|
errmsg="Unknown waveform "+waveform
|
|
raise ValueError (errmsg)
|
|
# end if
|
|
|
|
# ens else - if
|
|
|
|
|
|
self.__sendwritecmd(jds6600.WAVEFORM1+channel-1,w)
|
|
|
|
# end function set waveform
|
|
|
|
|
|
# set frequency (with multiplier)
|
|
def setfrequency(self,channel,freq,multiplier=0):
|
|
if type(channel) != int: raise TypeError(channel)
|
|
if (type(freq) != int) and (type(freq) != float): raise TypeError(freq)
|
|
if type(multiplier) != int: raise TypeError(multiplier)
|
|
|
|
if not (channel in (1,2)): raise ValueError(channel)
|
|
|
|
|
|
if (freq < 0):
|
|
raise ValueError(freq)
|
|
|
|
# do not execute set-frequency when the device is in sweepfrequency mode
|
|
currentmode=self.getmode()
|
|
|
|
if (channel == 1) and (currentmode[1] == "SWEEP_CH1"):
|
|
# for channel 1
|
|
raise WrongMode()
|
|
elif (channel == 2) and (currentmode[1] == "SWEEP_CH2"):
|
|
# for channel 2
|
|
raise WrongMode()
|
|
# end elsif - if
|
|
|
|
|
|
|
|
# freqmultier should be one of the "frequency multiply" values
|
|
try:
|
|
self.__freqmultiply[multiplier]
|
|
except IndexError:
|
|
raise ValueError[multiplier]
|
|
|
|
# frequency limit:
|
|
# 60 Mhz for multiplier 0 (Hz), 1 (KHz) and 2 (MHz)
|
|
# 80 Khz for multiplier 3 (mHz)
|
|
# 80 Hz for multiplier 4 (uHz)
|
|
# trying to configure a higher value can result in incorrect frequencies
|
|
|
|
if multiplier < 3:
|
|
if freq > 60000000:
|
|
errmsg="Maximum frequency using multiplier {} is 60 MHz.".format(multiplier)
|
|
raise ValueError(errmsg)
|
|
# end if
|
|
elif multiplier == 3:
|
|
if freq > 80000:
|
|
errmsg="Maximum frequency using multiplier 3 is 80 KHz."
|
|
raise ValueError(errmsg)
|
|
# end if
|
|
else: # multiplier == 4
|
|
if freq > 80:
|
|
errmsg="Maximum frequency using multiplier 4 is 80 Hz."
|
|
raise ValueError(errmsg)
|
|
# end if
|
|
# end else - elsif - if
|
|
|
|
|
|
|
|
# round to nearest 0.01 value
|
|
freq=int(round(freq*100/jds6600.__freqmultiply[multiplier]))
|
|
value=str(freq)+","+str(multiplier)
|
|
|
|
self.__sendwritecmd(jds6600.FREQUENCY1+channel-1,value)
|
|
# end set frequency (with multiplier)
|
|
|
|
|
|
# set amplitude
|
|
def setamplitude(self, channel, amplitude):
|
|
if type(channel) != int: raise TypeError(channel)
|
|
if (type(amplitude) != int) and (type(amplitude) != float): raise TypeError(amplitude)
|
|
|
|
if not (channel in (1,2)): raise ValueError(channel)
|
|
|
|
# amplitude is between 0 and 20 V
|
|
if not (0 <= amplitude <= 20):
|
|
raise ValueError(amplitude)
|
|
|
|
# round to nearest 0.001 value
|
|
amplitude=int(round(amplitude*1000))
|
|
|
|
self.__sendwritecmd(jds6600.AMPLITUDE1+channel-1,amplitude)
|
|
# end setamplitude
|
|
|
|
|
|
|
|
# set offset
|
|
def setoffset(self, channel, offset):
|
|
if type(channel) != int: raise TypeError(channel)
|
|
if (type(offset) != int) and (type(offset) != float): raise TypeError(offset)
|
|
|
|
if not (channel in (1,2)): raise ValueError(channel)
|
|
|
|
# offset is between -10 and +10 volt
|
|
if not (-10 <= offset <= 10):
|
|
raise ValueError(offset)
|
|
|
|
# note: althou the value-range for offset is able
|
|
# to accomodate an offset between -10 and +10 Volt
|
|
# the actual offset seams to be lmited to -2.5 to +2.5
|
|
|
|
# round to nearest 0.01 value
|
|
offset=int(round(offset*100))+1000
|
|
|
|
self.__sendwritecmd(jds6600.OFFSET1+channel-1, offset)
|
|
# end set offset
|
|
|
|
# set dutcycle
|
|
def setdutycycle(self, channel, dutycycle):
|
|
if type(channel) != int: raise TypeError(channel)
|
|
if (type(dutycycle) != int) and (type(dutycycle) != float): raise TypeError(dutycycle)
|
|
|
|
if not (channel in (1,2)): raise ValueError(channel)
|
|
|
|
# dutycycle is between 0 and 100 %
|
|
if not (0 <= dutycycle <= 100):
|
|
raise ValueError(dutycycle)
|
|
|
|
# round to nearest 0.1 value
|
|
dutycycle=int(round(dutycycle*10))
|
|
|
|
self.__sendwritecmd(jds6600.DUTYCYCLE1+channel-1,dutycycle)
|
|
# end set dutycycle
|
|
|
|
|
|
# set phase
|
|
def setphase(self,phase):
|
|
if (type(phase) != int) and (type(phase) != float):
|
|
raise TypeError(phase)
|
|
|
|
# hase is between -360 and 360
|
|
if not (-360 <= phase <= 360):
|
|
raise ValueError(phase)
|
|
|
|
if phase < 0:
|
|
phase += 3600
|
|
|
|
# round to nearest 0.1 value
|
|
phase=int(round(phase*10))
|
|
|
|
self.__sendwritecmd(jds6600.PHASE,phase)
|
|
# end getphase
|
|
|
|
|
|
#######################
|
|
# Part 4: reading / changing mode
|
|
# get mode
|
|
def getmode(self):
|
|
mode=self.__getdata(jds6600.MODE)
|
|
|
|
|
|
# mode is in the list "modes". mode-name "" means undefinded
|
|
mode=int(mode)>>3
|
|
|
|
try:
|
|
(modeid,modetxt)=jds6600.__modes[mode]
|
|
except IndexError:
|
|
raise UnexpectedValueError(mode)
|
|
|
|
# modeid 3 is not valid and returns an id of -1
|
|
if modeid >= 0:
|
|
return modeid,modetxt
|
|
# end if
|
|
|
|
|
|
# modeid 4
|
|
raise UnexpectedValueError(mode)
|
|
|
|
# end getmode
|
|
|
|
|
|
# set mode
|
|
def setmode(self,mode, nostop=False):
|
|
if (type(mode) != int) and (type(mode) != str): raise TypeError(mode)
|
|
|
|
|
|
modeid=-1
|
|
# if mode is an integer, it should be between 0 and 9
|
|
if type(mode) == int:
|
|
if not (0 <= mode <= 9):
|
|
raise ValueError(mode)
|
|
# end if
|
|
|
|
# modeid 3 / modetxt "" does not exist
|
|
if mode == 3:
|
|
raise ValueError("mode 3 does not exist")
|
|
# end if
|
|
|
|
|
|
# valid modeid
|
|
modeid = mode
|
|
|
|
else:
|
|
# modeid 3 / modetxt "" does not exist
|
|
if mode == "":
|
|
raise ValueError("mode 3 does not exist")
|
|
# end if
|
|
|
|
# mode is string -> check list
|
|
# (note: the modes-list is not enumerated like the other lists, so an "array.index("text")" search is not possible
|
|
for mid,mtxt in jds6600.__modes:
|
|
if mode.upper() == mtxt:
|
|
# found it!!!
|
|
modeid=mid
|
|
break
|
|
# end if
|
|
else:
|
|
# mode not found -> error
|
|
raise ValueError(mode)
|
|
# end for
|
|
# end else - if
|
|
|
|
# before changing mode, disable all actions (unless explicitally asked not to do)
|
|
if nostop == False:
|
|
self.__setaction("STOP")
|
|
# endif
|
|
|
|
# set mode
|
|
self.__sendwritecmd(jds6600.MODE,modeid)
|
|
|
|
# if new mode is "burst", reset burst counter
|
|
if modeid == 9:
|
|
self.burst_resetcounter()
|
|
# end if
|
|
|
|
# end setmode
|
|
|
|
#######################
|
|
# Part 5: functions common for all modes
|
|
def stopallactions(self):
|
|
# just send stop
|
|
self.__setaction("STOP")
|
|
# end stop all actions
|
|
|
|
|
|
#######################
|
|
# Part 6: "measure" mode
|
|
|
|
# get coupling parameter (measure mode)
|
|
def measure_getcoupling(self):
|
|
coupling=self.__getdata(jds6600.MEASURE_COUP)
|
|
|
|
try:
|
|
return (coupling,jds6600.__measure_coupling[coupling])
|
|
except IndexError:
|
|
raise UnexpectedValueError(coupling)
|
|
# end try
|
|
# end get coupling (measure mode)
|
|
|
|
# get gate time (measure mode)
|
|
# get (measure mode)
|
|
def measure_getgate(self):
|
|
gate=self.__getdata(jds6600.MEASURE_GATE)
|
|
|
|
|
|
# gate unit is 0.01 seconds
|
|
return gate / 100
|
|
# end get gate (measure mode)
|
|
|
|
|
|
# get Measure mode (freq or period)
|
|
def measure_getmode(self):
|
|
mode=self.__getdata(jds6600.MEASURE_MODE)
|
|
|
|
try:
|
|
return (mode,jds6600.__measure_mode[mode])
|
|
except IndexError:
|
|
raise UnexpectedValueError(mode)
|
|
# end try
|
|
# end get mode (measure)
|
|
|
|
|
|
|
|
# set measure coupling
|
|
def measure_setcoupling(self,coupling):
|
|
# type checks
|
|
if (type(coupling) != int) and (type(coupling) != str): raise TypeError(coupling)
|
|
|
|
|
|
if type(coupling) == int:
|
|
# coupling is 0 (DC) or 1 (AC)
|
|
if not (coupling in (0,1)):
|
|
raise ValueError(coupling)
|
|
|
|
coupl=coupling
|
|
|
|
else:
|
|
# string based
|
|
|
|
coupling=coupling.upper()
|
|
# spme shortcuts:
|
|
if coupling == "AC": coupling = "AC(EXT.IN)"
|
|
if coupling == "DC": coupling = "DC(EXT.IN)"
|
|
|
|
try:
|
|
coupl=jds6600.__measure_coupling.index(coupling)
|
|
except ValueError:
|
|
errmsg="Unknown measure-mode coupling: "+coupling
|
|
raise ValueError(errmsg)
|
|
# end try
|
|
# end else ) if (type is int or str?)
|
|
|
|
# set mode
|
|
self.__sendwritecmd(jds6600.MEASURE_COUP,coupl)
|
|
|
|
# end set measure_coupling
|
|
|
|
# set gate time (measure mode)
|
|
def measure_setgate(self, gate):
|
|
# check type
|
|
if (type(gate) != int) and (type(gate) != float): raise TypeError(gate)
|
|
|
|
# gate unit is 0.01 and is between 0 and 10
|
|
if not (0 < gate <= 1000):
|
|
raise ValueError(gate)
|
|
|
|
gate = int(round(gate*100))
|
|
|
|
# minimum is 0.01 second
|
|
if gate == 0:
|
|
gate = 0.01
|
|
|
|
# set gate
|
|
self.__sendwritecmd(jds6600.MEASURE_GATE,gate)
|
|
# end get gate (measure mode)
|
|
|
|
|
|
# set measure mode
|
|
def measure_setmode(self,mode):
|
|
# type checks
|
|
if (type(mode) != int) and (type(mode) != str): raise TypeError(mode)
|
|
|
|
|
|
if type(mode) == int:
|
|
# mode is 0 (M.FREQ) or 1 (M.PRERIOD)
|
|
if not (mode in (0,1)):
|
|
raise ValueError(mode)
|
|
|
|
else:
|
|
# string based
|
|
|
|
# make uppercase
|
|
mode=mode.upper()
|
|
|
|
# spme shortcuts:
|
|
if mode== "FREQ": mode = "M.FREQ"
|
|
if mode== "PERIOD": mode = "M.PERIOD"
|
|
|
|
try:
|
|
mode=jds6600.__measure_mode.index(mode)
|
|
except ValueError:
|
|
errmsg="Unknown measure mode: "+mode
|
|
raise ValueError(errmsg)
|
|
# end try
|
|
|
|
# end else ) if (type is int or str?)
|
|
|
|
# set mode
|
|
self.__sendwritecmd(jds6600.MEASURE_MODE,mode)
|
|
|
|
# end set measure_coupling
|
|
|
|
# get Measure freq. (lowres / Freq-mode)
|
|
def measure_getfreq_f(self):
|
|
freq=self.__getdata(jds6600.MEASURE_DATA_FREQ_LOWRES)
|
|
|
|
# unit is 0.1 Hz
|
|
return freq/10
|
|
# end get freq-Lowres (measure)
|
|
|
|
# get Measure freq. (highes / Periode-mode)
|
|
def measure_getfreq_p(self):
|
|
freq=self.__getdata(jds6600.MEASURE_DATA_FREQ_HIGHRES)
|
|
|
|
# unit is 0.001 Hz
|
|
return freq/1000
|
|
# end get freq-Lowres (measure)
|
|
|
|
# get Measure pulsewith +
|
|
def measure_getpw1(self):
|
|
pw=self.__getdata(jds6600.MEASURE_DATA_PW1)
|
|
|
|
# unit is 0.01 microsecond
|
|
return pw/100
|
|
# end get pulsewidth -
|
|
|
|
# get Measure pulsewidth -
|
|
def measure_getpw0(self):
|
|
pw=self.__getdata(jds6600.MEASURE_DATA_PW0)
|
|
|
|
# unit is 0.01 microsecond
|
|
return pw/100
|
|
# end get pulsewidth +
|
|
|
|
# get Measure total period
|
|
def measure_getperiod(self):
|
|
period=self.__getdata(jds6600.MEASURE_DATA_PERIOD)
|
|
|
|
# unit is 0.01 microsecond
|
|
return period/100
|
|
# end get total period
|
|
|
|
# get Measure dutycycle
|
|
def measure_getdutycycle(self):
|
|
dutycycle=self.__getdata(jds6600.MEASURE_DATA_DUTYCYCLE)
|
|
|
|
# unit is 0.1 %
|
|
return dutycycle/10
|
|
# end get freq-Lowres (measure)
|
|
|
|
# get Measure unknown value 1 (related to freq, inverse-related to gatetime)
|
|
def measure_getu1(self):
|
|
# unit is unknown, just return it
|
|
return self.__getdata(jds6600.MEASURE_DATA_U1)
|
|
# end get freq-Lowres (measure)
|
|
|
|
# get Measure unknown value 2 (inverse related to freq)
|
|
def measure_getu2(self):
|
|
# unit is unknown, just return it
|
|
return self.__getdata(jds6600.MEASURE_DATA_U2)
|
|
# end get freq-Lowres (measure)
|
|
|
|
# get Measure unknown value 3 (nverse related to freq)
|
|
def measure_getu3(self):
|
|
# unit is unknown, just return it
|
|
return self.__getdata(jds6600.MEASURE_DATA_U3)
|
|
# end get freq-Lowres (measure)
|
|
|
|
|
|
# get Measure all (all usefull data: freq_f, freq_p, pw1, pw0, period, dutycycle
|
|
def measure_getall(self):
|
|
|
|
# do query for 6 values (start with freq_q)
|
|
(freq_f, freq_p, pw1, pw0, period, dutycycle)=self.__getdata(jds6600.MEASURE_DATA_FREQ_LOWRES,6)
|
|
|
|
# return all
|
|
return (freq_f / 10, freq_p / 1000, pw1/100, pw0/100, period/100, dutycycle/10)
|
|
# end get freq-Lowres (measure)
|
|
|
|
|
|
|
|
#######################
|
|
# Part 7: "Counter" mode
|
|
|
|
# counter getcoupling is the same as measure getcoupling
|
|
def counter_getcoupling(self):
|
|
return self.measure_getcoupling()
|
|
# end counter get coupling
|
|
|
|
# get counter - counter
|
|
def counter_getcounter(self):
|
|
# unit is 1, just return data
|
|
return self.__getdata(jds6600.COUNTER_DATA_COUNTER)
|
|
# end get counter - counter
|
|
|
|
# counter setcoupling is the same as measure setcoupling
|
|
def counter_setcoupling(self,coupling):
|
|
self.measure_setcoupling(coupling)
|
|
# end counter get coupling
|
|
|
|
|
|
# counter - reset counter
|
|
def counter_reset(self):
|
|
# write 0 to register "COUNTER_RESETCOUNTER"
|
|
self.__sendwritecmd(jds6600.COUNTER_RESETCOUNTER,0)
|
|
# end counter reset counter
|
|
|
|
# start counter mode
|
|
def counter_start(self):
|
|
mode=self.getmode()
|
|
|
|
if mode[1] != "COUNTER":
|
|
raise WrongMode()
|
|
# end if
|
|
|
|
# action start BURST mode
|
|
self.__setaction("COUNT")
|
|
# end counter_start
|
|
|
|
|
|
def counter_stop(self):
|
|
# just send stop
|
|
self.__setaction("STOP")
|
|
# end counter_stop
|
|
|
|
|
|
|
|
|
|
|
|
#######################
|
|
# Part 8: "Sweep" mode
|
|
|
|
# note, there are two "setmode" commands to enter "sweep" mode: "sweep_ch1' (mode 6) and "sweep_ch2" (mode 7)
|
|
|
|
def sweep_getstartfreq(self):
|
|
# unit is 0.01Hz -> divide by 100
|
|
return self.__getdata(jds6600.SWEEP_STARTFREQ)/100
|
|
# end get sweep - startfreq
|
|
|
|
def sweep_getendfreq(self):
|
|
# unit is 0.01 Hz -> divide by 100
|
|
return self.__getdata(jds6600.SWEEP_ENDFREQ)/100
|
|
# end get sweep - startfreq
|
|
|
|
def sweep_gettime(self):
|
|
# unit is 0.1 sec -> divide by 10
|
|
return self.__getdata(jds6600.SWEEP_TIME)/10
|
|
# end get sweep - startfreq
|
|
|
|
|
|
# get sweep direction
|
|
def sweep_getdirection(self):
|
|
direction=self.__getdata(jds6600.SWEEP_DIRECTION)
|
|
|
|
try:
|
|
return (direction,jds6600.__sweep_direction[direction])
|
|
except IndexError:
|
|
raise UnexpectedValueError(direction)
|
|
# end try
|
|
# end get direction (sweep)
|
|
|
|
# get sweep mode
|
|
def sweep_getmode(self):
|
|
mode=self.__getdata(jds6600.SWEEP_MODE)
|
|
|
|
try:
|
|
return (mode,jds6600.__sweep_mode[mode])
|
|
except IndexError:
|
|
raise UnexpectedValueError(mode)
|
|
# end try
|
|
# end get mode (measure)
|
|
|
|
def sweep_setstartfreq(self, frequency):
|
|
if (type(frequency) != int) and (type(frequency) != float): raise TypeError(frequency)
|
|
|
|
# frequency should be between 0 and 60 MHz
|
|
if not (0 <= frequency <= 60000000):
|
|
raise ValueError(frequency)
|
|
|
|
# frequency unit is 0.01 Hz
|
|
freq=int(round(frequency*100))
|
|
|
|
self.__sendwritecmd(jds6600.SWEEP_STARTFREQ,freq)
|
|
# end set start freq
|
|
|
|
def sweep_setendfreq(self, frequency):
|
|
if (type(frequency) != int) and (type(frequency) != float): raise TypeError(frequency)
|
|
|
|
# frequency should be between 0 and 60 MHz
|
|
if not (0 <= frequency <= 60000000):
|
|
raise ValueError(frequency)
|
|
|
|
# frequency unit is 0.01 Hz
|
|
freq=int(round(frequency*100))
|
|
|
|
self.__sendwritecmd(jds6600.SWEEP_ENDFREQ,freq)
|
|
# end set end freq
|
|
|
|
|
|
def sweep_settime(self, time):
|
|
if (type(time) != int) and (type(time) != float): raise TypeError(time)
|
|
|
|
# time should be between 0 and 999.9 seconds
|
|
if not (0 < time <= 999.9):
|
|
raise ValueError(time)
|
|
|
|
# time unit is 0.1 second
|
|
t=int(round(time*10))
|
|
|
|
self.__sendwritecmd(jds6600.SWEEP_TIME,t)
|
|
# end set end freq
|
|
|
|
|
|
def sweep_setdirection(self, direction):
|
|
if (type(direction) != int) and (type(direction) != str): raise TypeError(direction)
|
|
|
|
if type(direction) == int:
|
|
# mode is 0 (RISE), 1 (FALL) or 2 (RISE&FALL)
|
|
if not (direction in (0,1,2)):
|
|
raise ValueError(direction)
|
|
|
|
else:
|
|
# string based
|
|
|
|
# make uppercase
|
|
direction=direction.upper()
|
|
|
|
# spme shortcuts:
|
|
if direction == "RISEFALL": direction = "RISE&FALL"
|
|
if direction == "BOTH": direction = "RISE&FALL"
|
|
|
|
try:
|
|
direction=jds6600.__sweep_direction.index(direction)
|
|
except ValueError:
|
|
errmsg="Unknown sweep direction: "+direction
|
|
raise ValueError(errmsg)
|
|
# end else - for
|
|
# end else ) if (type is int or str?)
|
|
|
|
# set mode
|
|
self.__sendwritecmd(jds6600.SWEEP_DIRECTION,direction)
|
|
# end set direction (sweep)
|
|
|
|
|
|
def sweep_setmode(self, mode):
|
|
if (type(mode) != int) and (type(mode) != str): raise TypeError(mode)
|
|
|
|
if type(mode) == int:
|
|
# mode is 0 (LINEAR) or 1 (LOGARITHM))
|
|
if not (mode in (0,1)):
|
|
raise ValueError(mode)
|
|
|
|
else:
|
|
# string based
|
|
|
|
# make uppercase
|
|
mode=mode.upper()
|
|
|
|
# spme shortcuts:
|
|
if mode == "LIN": mode = "LINEAR"
|
|
if mode == "LOG": mode = "LOGARITHM"
|
|
|
|
try:
|
|
mode=jds6600.__sweep_mode.index(mode)
|
|
except ValueError:
|
|
errmsg="Unknown sweep mode: "+mode
|
|
raise ValueError(errmsg)
|
|
# end else - for
|
|
# end else ) if (type is int or str?)
|
|
|
|
# set mode
|
|
self.__sendwritecmd(jds6600.SWEEP_MODE,mode)
|
|
# end set direction (sweep)
|
|
|
|
|
|
|
|
|
|
# get sweep channel
|
|
def sweep_getchannel(self):
|
|
mode=self.getmode()
|
|
|
|
if mode[1] == "SWEEP_CH1":
|
|
return 1
|
|
elif mode[1] == "SWEEP_CH2":
|
|
return 2
|
|
# end if - elif
|
|
|
|
# not channel 1 or channel 2, return 0
|
|
return 0
|
|
# end sweep get_channel
|
|
|
|
# set sweep channel
|
|
def sweep_setchannel(self,channel):
|
|
if type(channel) != int: raise TypeError(channel)
|
|
|
|
# new channel should be 1 or 2
|
|
if not (channel in (1,2)):
|
|
raise ValueError(channel)
|
|
# end if
|
|
|
|
# get current channel (1 or 2, or 0 if not in sweep mode)
|
|
currentchannel=self.sweep_getchannel()
|
|
|
|
# only swich if already in sweep mode
|
|
if currentchannel == 0:
|
|
raise WrongMode()
|
|
#endif
|
|
|
|
# switch if the new channel is different from current channel
|
|
if channel != currentchannel:
|
|
if channel == 1:
|
|
self.setmode("SWEEP_CH1",nostop=True)
|
|
else:
|
|
self.setmode("SWEEP_CH2",nostop=True)
|
|
# end else - if
|
|
# end if
|
|
# end sweep set channel
|
|
|
|
|
|
# start sweep
|
|
def sweep_start(self):
|
|
mode=self.getmode()
|
|
|
|
if (mode[1] != "SWEEP_CH1") and (mode[1] != "SWEEP_CH2"):
|
|
raise WrongMode()
|
|
# end if
|
|
|
|
# action start BURST mode
|
|
self.__setaction("SWEEP")
|
|
# end sweep_start
|
|
|
|
|
|
# stop sweep
|
|
def sweep_stop(self):
|
|
# just send stop
|
|
self.__setaction("STOP")
|
|
# end sweep_start
|
|
|
|
|
|
|
|
##################################
|
|
|
|
|
|
#######################
|
|
# Part 9: PULSE
|
|
|
|
|
|
# get pulsewidth, normalised to s
|
|
def pulse_getpulsewidth(self):
|
|
# pulsewith returns two datafiels, periode + multiplier
|
|
time,multi = self.__getdata(jds6600.PULSE_PULSEWIDTH)
|
|
|
|
if multi==0: return time / 1000000000 # ns
|
|
elif multi == 1: return time / 1000000 # us
|
|
else:
|
|
UnexptectedValue(multi)
|
|
# end else - elsif - if
|
|
# end
|
|
|
|
# get pulsewidth, not normalised
|
|
def pulse_getpulsewidth_m(self):
|
|
# pulsewith returns two datafiels, periode + multiplier
|
|
return self.__getdata(jds6600.PULSE_PULSEWIDTH)
|
|
# end
|
|
|
|
|
|
# get period, normalised to s
|
|
def pulse_getperiod(self):
|
|
# period returns two datafiels, periode + multiplier
|
|
time,multi = self.__getdata(jds6600.PULSE_PERIOD)
|
|
|
|
if multi==0: return time / 1000000000 # ns
|
|
elif multi == 1: return time / 1000000 # us
|
|
else:
|
|
UnexptectedValue(multi)
|
|
# end else - elsif - if
|
|
# end
|
|
|
|
|
|
# get period, not normalised
|
|
def pulse_getperiod_m(self):
|
|
# period returns two datafiels, periode + multiplier
|
|
return self.__getdata(jds6600.PULSE_PERIOD)
|
|
# end
|
|
|
|
# get offset
|
|
def pulse_getoffset(self):
|
|
# unit is %, just return data
|
|
return self.__getdata(jds6600.PULSE_OFFSET)
|
|
# end
|
|
|
|
# get amplitude
|
|
def pulse_getamplitude(self):
|
|
# unit 0.01, divide by 100
|
|
return self.__getdata(jds6600.PULSE_AMPLITUDE)/100
|
|
# end
|
|
|
|
# set pulsewith or period (backend function)
|
|
def __pulse_setpw_period(self, var, data, multiplier, normalised):
|
|
maxval=([4e9,4e9],(4,4000)) # maximum data value
|
|
minval=((30,1),(30e-9,1e-6)) # minimum data value
|
|
multi=(1e9,1e6) # unit is 1ns or 1 us
|
|
data2reg=(jds6600.PULSE_PULSEWIDTH,jds6600.PULSE_PERIOD)
|
|
data2txt=("pulsewidth","period")
|
|
|
|
if (type(var) != int) or ((var != 0) and (var != 1)): raise RuntimeError("error __pulse_setpw_period: var") # var is 0 (for pulsewidth) or 1 (period)
|
|
if (type(data) != int) and (type(data) != float): raise TypeError(period)
|
|
if (type(normalised) != int) or not (normalised in (0,1)): raise RuntimeError("error __pulse_setpw_period: normalised")
|
|
|
|
if type(multiplier) != int: raise TypeError(multiplier)
|
|
|
|
# multiplier should be 0 or 1
|
|
if not (multiplier in (0,1)):
|
|
errmsg="multiplier must be 0 (ns) or 1 (us)"
|
|
raise ValueError(errmsg)
|
|
# end if
|
|
|
|
# data must be between to allocated limits:
|
|
# not normalised: allowed values: 30 to 400000000 (multi=0) / 1 to 4000000000 (multi=1)
|
|
# normalised: allowed values: 30 ns to 4 sec. (multi=0) / 1 us to 4000 sec (multi=2)
|
|
if not (minval[normalised][multiplier] <= data <= maxval[normalised][multiplier]):
|
|
errmsg="{} must be between {} and {}".format(data2txt[var],minval[normalised][multiplier],maxval[normalised][multiplier])
|
|
raise ValueError(errmsg)
|
|
# end if
|
|
|
|
|
|
# convert from s to ns/us, if needed
|
|
if normalised == 1:
|
|
data = str(round(data * multi[multiplier]))+","+str(multiplier)
|
|
else:
|
|
data = str(int(data))+","+str(multiplier)
|
|
# end if
|
|
|
|
# done: now write
|
|
self.__sendwritecmd(data2reg[var],data)
|
|
# end set pw/period, low-level function
|
|
|
|
|
|
# set pw, normalised
|
|
def pulse_setpulsewidth(self,pw,multiplier=0):
|
|
# convert to low-level function
|
|
self.__pulse_setpw_period(0,pw,multiplier,1)
|
|
# end pulse_setpw (normalised)
|
|
|
|
# set pw, not normalised
|
|
def pulse_setpulsewidth_m(self,pw,multiplier):
|
|
# convert to low-level function
|
|
self.__pulse_setpw_period(0,pw,multiplier,0)
|
|
# end pulse_setpw (normalised)
|
|
|
|
# set period, normalised
|
|
def pulse_setperiod(self,pw,multiplier=0):
|
|
# convert to low-level function
|
|
self.__pulse_setpw_period(1,pw,multiplier,1)
|
|
# end pulse_setperiod (normalised)
|
|
|
|
# set period, not normalised
|
|
def pulse_setperiod_m(self,pw,multiplier):
|
|
# convert to low-level function
|
|
self.__pulse_setpw_period(1,pw,multiplier,0)
|
|
# end pulse_setperiod (normalised)
|
|
|
|
|
|
# set pulse offset
|
|
def pulse_setoffset(self,offset):
|
|
if (type(offset) != int) and (type(offset) != float): raise TypeError(offset)
|
|
|
|
# offset is between 0 and 120 %
|
|
if not (0 <= offset <= 120):
|
|
errmsg="Offset must be between 0 and 120 %"
|
|
raise ValueError(errmsg)
|
|
# end if
|
|
|
|
# unit = 1 -> just send
|
|
self.__sendwritecmd(jds6600.PULSE_OFFSET,offset)
|
|
# end off
|
|
|
|
|
|
# set pulse amplitude
|
|
def pulse_setamplitude(self,amplitude):
|
|
if (type(amplitude) != int) and (type(amplitude) != float): raise TypeError(amplitude)
|
|
|
|
# amplitude is between 0 and 10 V
|
|
if not (0 <= amplitude <= 10):
|
|
errmsg="Amplitude must be between 0 and 10 Volt"
|
|
raise ValueError(errmsg)
|
|
# end if
|
|
|
|
# unit is 0.01V
|
|
amplitude=int(round(amplitude*100))
|
|
self.__sendwritecmd(jds6600.PULSE_AMPLITUDE,amplitude)
|
|
# end off
|
|
|
|
|
|
def pulse_start(self):
|
|
mode=self.getmode()
|
|
|
|
if mode[1] != "PULSE":
|
|
raise WrongMode()
|
|
# end if
|
|
|
|
# action start BURST mode
|
|
self.__setaction("PULSE")
|
|
# end pulse_start
|
|
|
|
|
|
def pulse_stop(self):
|
|
# just send stop
|
|
self.__setaction("STOP")
|
|
# end pulse_stop
|
|
|
|
|
|
#######################
|
|
# Part 10: BURST
|
|
|
|
|
|
def burst_getnumberofbursts(self):
|
|
# unit is 1, just return value
|
|
return self.__getdata(jds6600.BURST_NUMBER)
|
|
# end burst get number of bursts
|
|
|
|
def burst_getmode(self):
|
|
mode = self.__getdata(jds6600.BURST_MODE)
|
|
|
|
try:
|
|
return(mode,jds6600.__burst_mode[mode])
|
|
except IndexError:
|
|
raise UnexpectedValue(mode)
|
|
|
|
# end try
|
|
# end burst get mode
|
|
|
|
|
|
def burst_setnumberofbursts(self,burst):
|
|
if type(burst) != int: raise TypeError(burst)
|
|
|
|
# number of burst should be between 1 and 1048575
|
|
if not (1 <= burst <= 1048575):
|
|
errmsg="Number of bursts should be between 1 and 1048575"
|
|
raise ValueError(errmsg)
|
|
# end if
|
|
|
|
# unit is 1, just return value
|
|
self.__sendwritecmd(jds6600.BURST_NUMBER,burst)
|
|
# end burst get number of bursts
|
|
|
|
|
|
def burst_setmode(self,mode):
|
|
if (type(mode) != int) and (type(mode) != str): raise TypeError(mode)
|
|
|
|
if type(mode) == int:
|
|
# mode input is an integer
|
|
# mode should be between 0 and 3
|
|
if not (0 <= mode <= 3):
|
|
errmsg="Burst mode should between 0 and 3"
|
|
raise ValueError(mode)
|
|
# end if
|
|
else:
|
|
# mode input is a string
|
|
|
|
mode=mode.upper()
|
|
|
|
# shortcuts
|
|
if mode == "MANUAL": mode = "MANUAL TRIG."
|
|
if mode == "CH2": mode = "CH2 TRIG."
|
|
if mode == "EXT.AC": mode = "EXT.TRIG(AC)"
|
|
if mode == "EXT.DC": mode = "EXT.TRIG(DC)"
|
|
|
|
try:
|
|
mode=jds6600.__burst_mode.index(mode.upper())
|
|
except ValueError:
|
|
errmsg="Unknown burst mode: "+mode
|
|
raise ValueError(errmsg)
|
|
# end try
|
|
|
|
# end else - if
|
|
|
|
# stop if the burst-mode is running
|
|
self.burst_stop()
|
|
|
|
# write command
|
|
self.__sendwritecmd(jds6600.BURST_MODE,mode)
|
|
|
|
def burst_resetcounter(self):
|
|
# reset counter: same as counter_reset_counter
|
|
self.counter_reset()
|
|
# end reset counter
|
|
|
|
|
|
def burst_start(self):
|
|
mode=self.getmode()
|
|
|
|
if mode[1] != "BURST":
|
|
raise WrongMode()
|
|
# end if
|
|
|
|
# action start BURST mode
|
|
self.__setaction("BURST")
|
|
# end burst_start
|
|
|
|
|
|
def burst_stop(self):
|
|
# just send stop
|
|
self.__setaction("STOP")
|
|
# end burst_start
|
|
|
|
#######################
|
|
# Part 11: SYSTEM
|
|
|
|
########
|
|
# part 11.1: system parameters
|
|
|
|
# NOTE: there is a strange behaviour in some jds6600 devices where that the register to
|
|
# read the sysem-parameters is one higher then the registernumber use to write
|
|
# the parameter-value.
|
|
# This is probably a bug. The bug-fix code to deal with this situation can be
|
|
# be overwriten adding a "bugfix=0" option in the system_get* API-calls
|
|
|
|
# get sound setting
|
|
def system_getsound(self, bugfix=True):
|
|
if bugfix == True:
|
|
sound=self.__getdata(jds6600.SYSTEM_SOUND+1)
|
|
elif bugfix == False:
|
|
sound=self.__getdata(jds6600.SYSTEM_SOUND)
|
|
else: TypeError(bugfix)
|
|
|
|
# we should receive a 0 or 1
|
|
try:
|
|
return (False,True)[sound]
|
|
except IndexError:
|
|
raise UnexpectedValueError(sound)
|
|
#end system_getsound
|
|
|
|
# get brightness setting
|
|
def system_getbrightness(self, bugfix=True):
|
|
if bugfix == True:
|
|
return self.__getdata(jds6600.SYSTEM_BRIGHTNESS+1)
|
|
elif bugfix == False:
|
|
return self.__getdata(jds6600.SYSTEM_BRIGHTNESS)
|
|
else: TypeError(bugfix)
|
|
#end system_getbrightness
|
|
|
|
# get language setting
|
|
def system_getlanguage(self, bugfix=True):
|
|
if bugfix == True:
|
|
language=self.__getdata(jds6600.SYSTEM_LANGUAGE+1)
|
|
elif bugfix == False:
|
|
language=self.__getdata(jds6600.SYSTEM_LANGUAGE)
|
|
else: TypeError(bugfix)
|
|
|
|
# we should receive a 0 or a 1
|
|
try:
|
|
return language,jds6600.__system_language[language]
|
|
except KeyError:
|
|
raise UnexpectedValueError(sound)
|
|
#end system_getlanguage
|
|
|
|
def system_getsync(self, bugfix=True):
|
|
if bugfix == True:
|
|
sync=self.__getdata(jds6600.SYSTEM_SYNC+1)
|
|
elif bugfix == False:
|
|
sync=self.__getdata(jds6600.SYSTEM_SYNC)
|
|
else: TypeError(bugfix)
|
|
|
|
# returns a list of 5 fields: frequency, wave, amplitude, dutycycle and offset
|
|
if len(sync) != 5:
|
|
raise UnexpectedValueError(sync)
|
|
# end if
|
|
|
|
# return data
|
|
ret=[]
|
|
for s in sync:
|
|
if s not in (0,1): raise UnexpectedValueError(sync)
|
|
|
|
ret.append((False,True)[s])
|
|
# end for
|
|
|
|
# return data
|
|
return ret
|
|
# end system_getsync
|
|
|
|
|
|
# get maximum number of arbitrary waveforms
|
|
def system_getarbmaxnum(self, bugfix=True):
|
|
if bugfix == True:
|
|
return self.__getdata(jds6600.SYSTEM_ARBMAXNUM+1)
|
|
elif bugfix == False:
|
|
return self.__getdata(jds6600.SYSTEM_ARBMAXNUM)
|
|
else: TypeError(bugfix)
|
|
#end system_getlanguage
|
|
|
|
|
|
# set system sound
|
|
def system_setsound(self,sound):
|
|
if type(sound) != bool: raise TypeError(sound)
|
|
|
|
if sound == True:
|
|
self.__sendwritecmd(jds6600.SYSTEM_SOUND,1)
|
|
else:
|
|
self.__sendwritecmd(jds6600.SYSTEM_SOUND,0)
|
|
# end set sound
|
|
|
|
# set system brightness
|
|
def system_setbrightness(self,brightness):
|
|
if type(brightness) != int: raise TypeError(brightness)
|
|
|
|
# should be between 1 and 12
|
|
if not(1 <= brightness <= 12):
|
|
raise ValueError(brightness)
|
|
|
|
self.__sendwritecmd(jds6600.SYSTEM_BRIGHTNESS,brightness)
|
|
# end set sound
|
|
|
|
|
|
# set system language
|
|
def system_setlanguage(self,language):
|
|
if (type(language) != int) and (type(language) != str): raise TypeError(language)
|
|
|
|
if type(language) == int:
|
|
# integer
|
|
if language not in (0,1): raise ValueError(sound)
|
|
else:
|
|
# string
|
|
# shortcuts:
|
|
if language == "EN": language = "ENGLISH"
|
|
if language == "CH": language = "CHINESE"
|
|
|
|
try:
|
|
language=jds6600.__system_language.index(language.upper())
|
|
except ValueError:
|
|
errmsg="Unknown language: "+language
|
|
raise ValueError(errmsg)
|
|
# end try
|
|
# end else - if
|
|
|
|
self.__sendwritecmd(jds6600.SYSTEM_LANGUAGE,language)
|
|
|
|
# reinit "mode" to refresh screen for language change to become active
|
|
(mode,modetxt)=self.getmode()
|
|
self.setmode(mode)
|
|
# end set language
|
|
|
|
# set system sync
|
|
def system_setsync(self,freq,wave,ampl,duty,offs):
|
|
|
|
if type(freq) != bool: raise TypeError(freq)
|
|
if type(wave) != bool: raise TypeError(wave)
|
|
if type(ampl) != bool: raise TypeError(ampl)
|
|
if type(duty) != bool: raise TypeError(duty)
|
|
if type(offs) != bool: raise TypeError(offs)
|
|
|
|
# create command to send
|
|
sync=[freq,wave,ampl,duty,offs]
|
|
for i in range(5):
|
|
sync[i] = '1' if sync[i] == True else '0'
|
|
|
|
|
|
# merge all 5 elements in one command, seperated by ","
|
|
self.__sendwritecmd(jds6600.SYSTEM_SYNC,",".join(sync))
|
|
# end set sync
|
|
|
|
# set maximum number of arbitrary waveforms
|
|
def system_setarbmaxnum(self,arbmaxnum):
|
|
if type(arbmaxnum) != int: raise TypeError(arbmaxnum)
|
|
|
|
# abrmaxnum should be between 1 and 60
|
|
if not(1 <= arbmaxnum <= 60):
|
|
raise ValueError(arbmaxnum)
|
|
|
|
self.__sendwritecmd(jds6600.SYSTEM_ARBMAXNUM,arbmaxnum)
|
|
# end set arbmaxnum
|
|
|
|
|
|
|
|
|
|
######
|
|
# part 11.2: save / read / clear profile
|
|
|
|
def system_saveprofile(self,profile):
|
|
if type(profile) != int: raise TypeError(profile)
|
|
|
|
# profile is between 0 and 99
|
|
if not(0 <= profile <= 99): raise ValueError(errmsg)
|
|
|
|
# write profile to "PROFILE_SAVE"
|
|
self.__sendwritecmd(jds6600.PROFILE_SAVE,profile)
|
|
# end profile save
|
|
|
|
def system_loadprofile(self,profile):
|
|
if type(profile) != int: raise TypeError(profile)
|
|
|
|
# profile is between 0 and 99
|
|
if not(0 <= profile <= 99): raise ValueError(errmsg)
|
|
|
|
# write profile to "PROFILE_LOAD"
|
|
self.__sendwritecmd(jds6600.PROFILE_LOAD,profile)
|
|
# end profile load
|
|
|
|
def system_clearprofile(self,profile):
|
|
if type(profile) != int: raise TypeError(profile)
|
|
|
|
# profile is between 0 and 99
|
|
if not(0 <= profile <= 99): raise ValueError(errmsg)
|
|
|
|
# write profile to "PROFILE_CLEAR"
|
|
self.__sendwritecmd(jds6600.PROFILE_CLEAR,profile)
|
|
# end profile clear
|
|
|
|
|
|
|
|
#######################
|
|
# Part 12: Arbitrary waveform operations
|
|
|
|
def arb_getwave(self,waveid):
|
|
if type(waveid) != int: raise TypeError(waveid)
|
|
|
|
# waveid is between 1 and 60
|
|
if not(1 <= waveid <= 60): raise ValueError(waveid)
|
|
|
|
# getdata, reg=waveform id, data = 1, a=1 (register/waveform selector)
|
|
return self.__getdata(waveid,1,a=1)
|
|
# end get arbtrary waveform
|
|
|
|
|
|
def arb_setwave(self,waveid,wave):
|
|
if type(waveid) != int: raise TypeError(waveid)
|
|
if (type(wave) != tuple) and (type(wave) != list): raise TypeError(wave)
|
|
|
|
# waveid is between 1 and 60
|
|
if not(1 <= waveid <= 60): raise ValueError(waveid)
|
|
|
|
# wave should be a list or tuple of 2048 elements, all integers, with a value between 0 and 4095
|
|
if len(wave) != 2048: raise ValueError(wave)
|
|
|
|
tosend=""
|
|
for val in wave:
|
|
if type(val) != int: raise ValueError(wave)
|
|
if not (0 <= val <= 4095): raise ValueError(wave)
|
|
|
|
tosend += (str(val) if tosend=="" else ","+str(val))
|
|
# end for
|
|
|
|
# write waveform, reg=waveform id, data = waveform, a=1 (register/waveform selector)
|
|
self.__sendwritecmd(waveid,tosend,a=1)
|
|
|
|
# end set arbirtary waveform
|
|
|
|
##################################
|
|
|
|
# end class jds6600
|