class Driver(BaseDriver): support_models = [ 'M3202A', ] quants = [ QReal('Amplitude', value=1, unit='V', ch=0), #DC WaveShape QReal('Offset', value=0, unit='V', ch=0), #Function Generators(FGs) mode QReal('Frequency', unit='Hz', ch=0), QReal('Phase', value=0, unit='deg', ch=0), QOption('WaveShape', ch=0, value='HIZ', options=[('HIZ', -1), ('NoSignal', 0), ('Sin', 1), ('Triangular', 2), ('Square', 4), ('DC', 5), ('AWG', 6), ('PartnerCH', 8)]), #clock QReal('clockFrequency', unit='Hz'), QReal('clockSyncFrequency', unit='Hz'), # 板卡向外输出的时钟,默认状态关闭 QOption('clockIO', value='OFF', options=[('OFF', 0), ('ON', 1)]), QOption('triggerIO', value='SyncIN', options=[('noSyncOUT', (0, 0)), ('SyncOUT', (0, 1)), ('noSyncIN', (1, 0)), ('SyncIN', (1, 1))]), QOption('triggerMode', value='ExternalCycle', ch=0, options=[('Auto', 0), ('SWtri', 1), ('SWtriCycle', 5), ('External', 2), ('ExternalCycle', 6)]), QOption('triExtSource', value='EXTERN', ch=0, options=[('EXTERN', 0), ('PXI0', 4000), ('PXI1', 4001), ('PXI2', 4002), ('PXI3', 4003), ('PXI4', 4004), ('PXI5', 4005), ('PXI6', 4006), ('PXI7', 4007)]), QOption('triggerBehavior', value='RISE', ch=0, options=[('NONE', 0), ('HIGH', 1), ('LOW', 2), ('RISE', 3), ('FALL', 4)]), # Defines the delay between the trigger and the waveform launch in tens of ns QInteger( 'startDelay', value=0, unit='ns', ch=0, ), # Number of times the waveform is repeated once launched (negative means infinite) QInteger( 'cycles', value=0, ch=0, ), # Waveform prescaler value, to reduce the effective sampling rate QInteger( 'prescaler', value=0, ch=0, ), QOption('Output', ch=0, value='Close', options=[('Stop', 0), ('Run', 1), ('Pause', 2), ('Resume', 3), ('Close', -1)]), QList('WList', value=[]), QList('SList', value=[], ch=0), ] #CHs : 仪器通道 # CHs=[0,1,2,3] CHs = [1, 2, 3, 4] # config : 用来存储参数配置,防止由于多通道引起的混乱 config = {} def __init__(self, **kw): BaseDriver.__init__(self, **kw) self.chassis = kw['CHASSIS'] self.slot = kw['SLOT'] def newcfg(self): self.config = {} for q in self.quants: _cfg = {q.name: {}} if q.ch is not None: for i in self.CHs: _cfg[q.name].update( {i: { 'value': q.value, 'unit': q.unit }}) else: _cfg[q.name].update({0: {'value': q.value, 'unit': q.unit}}) self.config.update(_cfg) log.info('new config!') def loadcfg(self, file=None): if file == None: file = self.caches_file with open(file, 'r', encoding='utf-8') as f: self.config = yaml.load(f) log.info('load config: %s', file) def savecfg(self, file=None): if file == None: file = self.caches_file with open(file, 'w', encoding='utf-8') as f: yaml.dump(self.config, f) log.info('save config: %s', file) def performOpen(self): #SD_AOU module self.AWG = inspur_sd.SD_AOU() self.model = self.AWG.getProductNameBySlot(self.chassis, self.slot) moduleID = self.AWG.openWithSlot(self.model, self.chassis, self.slot) if moduleID < 0: print("Module open error:", moduleID) self.caches_file = caches_dir() / (self.model + '_config_caches.yaml') try: self.loadcfg() except Exception: log.exception(Exception) self.newcfg() self.savecfg() def performClose(self): """Perform the close instrument connection operation""" # refer labber driver keysight_pxi_awg.py # do not check for error if close was called with an error try: # print('0') # print('3') # print('13') self.setValue('clockIO', 'OFF') # print('2') # clear old waveforms and stop awg self.waveformFlush() # print('4') for ch in self.CHs: # print('5') self.closeCh(ch) # close instrument # self.AWG.close() # print('6') self.savecfg() # print('7') except Exception: # print('1') # never return error here pass def closeCh(self, ch=0): # print('8') self.AWG.AWGstop(ch) # print('9') self.AWG.AWGflush(ch) # print('10') self.config['SList'][ch]['value'] = [] # print('11') self.AWG.channelWaveShape(ch, -1) # print('12') self.config['WaveShape'][ch]['value'] = 'HIZ' self.config['Output'][ch]['value'] = 'Close' def performSetValue(self, quant, value, ch=0, **kw): _cfg = {} if quant.name == 'Amplitude': self.AWG.channelAmplitude(ch, value) elif quant.name == 'Offset': self.AWG.channelOffset(ch, value) elif quant.name == 'Frequency': self.AWG.channelFrequency(ch, value) elif quant.name == 'Phase': self.phaseReset(ch) self.AWG.channelPhase(ch, value) elif quant.name == 'WaveShape': options = dict(quant.options) self.AWG.channelWaveShape(ch, options[value]) elif quant.name == 'clockFrequency': mode = kw.get('mode', 1) self.AWG.clockSetFrequency(value, mode) ch = 0 elif quant.name == 'clockIO': options = dict(quant.options) self.AWG.clockIOconfig(options[value]) ch = 0 elif quant.name == 'triggerIO': options = dict(quant.options) self.AWG.triggerIOconfigV5(*options[value]) ch = 0 elif quant.name == 'Output': if value == 'Stop': self.AWG.AWGstop(ch) elif value == 'Run': self.AWG.AWGstart(ch) elif value == 'Pause': self.AWG.AWGpause(ch) elif value == 'Resume': self.AWG.AWGresume(ch) elif value == 'Close': self.closeCh(ch) elif quant.name == 'clockSyncFrequency': print("clockSyncFrequency can't be set") return _cfg['value'] = value self.config[quant.name][ch].update(_cfg) def performGetValue(self, quant, ch=0, **kw): _cfg = {} if quant.name == 'clockFrequency': value = self.AWG.clockGetFrequency() ch = 0 _cfg['value'] = value elif quant.name == 'clockSyncFrequency': value = self.AWG.clockGetSyncFrequency() ch = 0 _cfg['value'] = value elif quant.name in ['clockIO', 'triggerIO']: ch = 0 self.config[quant.name][ch].update(_cfg) return self.config[quant.name][ch]['value'] def phaseReset(self, ch=0): self.AWG.channelPhaseReset(ch) _cfg = {'value': 0} self.config['Phase'][ch].update(_cfg) def clockResetPhase(self): # self.AWG.clockResetPhase(triggerBehavior, triggerSource, skew = 0.0) pass def newWaveform(self, file_arrayA, arrayB=None, waveformType=0): '''Memory usage: Waveforms created with New are stored in the PC RAM, not in the module onboard RAM. Therefore, the limitation in the number of waveforms and their sizes is given by the amount of PC RAM.''' # waveformType 0: Analog 16Bits, Analog normalized waveforms (-1..1) defined with doubles # please refer AWG Waveform types about others wave = inspur_sd.SD_Wave() if isinstance(file_arrayA, str): wave.newFromFile(file_arrayA) return wave else: # 5: DigitalType, Digital waveforms defined with integers if waveformType == 5: wave.newFromArrayInteger(waveformType, file_arrayA, arrayB) else: wave.newFromArrayDouble(waveformType, file_arrayA, arrayB) return wave def waveformLoad(self, waveform, num, paddingMode=0): '''num: waveform_num, 在板上内存的波形编号''' if num in self.config['WList'][0]['value']: self.AWG.waveformReLoad(waveform, num, paddingMode) else: # This function replaces a waveform located in the module onboard RAM. # The size of the newwaveform must be smaller than or equal to the existing waveform. self.AWG.waveformLoad(waveform, num, paddingMode) self.config['WList'][0]['value'].append(num) # def waveformReLoad(self, waveform, num, paddingMode = 0): # '''This function replaces a waveform located in the module onboard RAM. # The size of the newwaveform must be smaller than or equal to the existing waveform.''' # self.AWG.waveformReLoad(waveform, num, paddingMode) def waveformFlush(self): '''This function deletes all the waveforms from the module onboard RAM and flushes all the AWG queues''' # print('14') self.AWG.waveformFlush() # print('15') self.config['WList'][0]['value'] = [] # print('16') # self.config['SList'][0]['value']=[] # print('17') def AWGflush(self, ch=0): '''This function empties the queue of the selected Arbitrary Waveform Generator, Waveforms are not removed from the module onboard RAM.''' self.AWG.AWGflush(ch) self.config['SList'][0]['value'] = [] def _getParams(self, ch): triggerModeIndex = self.getValue('triggerMode', ch=ch) triggerModeOptions = self.quantities['triggerMode'].options triggerMode = dict(triggerModeOptions)[triggerModeIndex] if triggerModeIndex in ['External', 'ExternalCycle']: triExtSourceIndex = self.getValue('triExtSource', ch=ch) triExtSourceOptions = self.quantities['triExtSource'].options triExtSource = dict(triExtSourceOptions)[triExtSourceIndex] if triExtSourceIndex in ['EXTERN']: # 若未设置过,则从config读取默认配置;若已设置,则结果不变 triggerIO = self.getValue('triggerIO') self.setValue('triggerIO', triggerIO) triggerBehaviorIndex = self.getValue('triggerBehavior', ch=ch) triggerBehaviorOptions = self.quantities['triggerBehavior'].options triggerBehavior = dict( triggerBehaviorOptions)[triggerBehaviorIndex] self.AWG.AWGtriggerExternalConfig(ch, triExtSource, triggerBehavior) startDelay = self.getValue('startDelay', ch=ch) cycles = self.getValue('cycles', ch=ch) prescaler = self.getValue('prescaler', ch=ch) return triggerMode, startDelay, cycles, prescaler def AWGqueueWaveform(self, ch=0, waveform_num=0): self.setValue('WaveShape', 'AWG', ch=ch) Amplitude = self.getValue('Amplitude', ch=ch) self.setValue('Amplitude', Amplitude, ch=ch) triggerMode, startDelay, cycles, prescaler = self._getParams(ch) self.AWG.AWGqueueWaveform(ch, waveform_num, triggerMode, startDelay, cycles, prescaler) self.config['SList'][ch]['value'].append(waveform_num) def AWGrun(self, file_arrayA, arrayB=None, ch=0, waveformType=0, paddingMode=0): '''从文件或序列快速产生波形''' print('0') self.setValue('WaveShape', 'AWG', ch=ch) print('1') Amplitude = self.getValue('Amplitude', ch=ch) print('2') self.setValue('Amplitude', Amplitude, ch=ch) print('3') triggerMode, startDelay, cycles, prescaler = self._getParams(ch) print('4') if isinstance(file_arrayA, str): # AWGFromFile 有bug self.AWG.AWGFromFile(ch, file_arrayA, triggerMode, startDelay, cycles, prescaler, paddingMode) else: print('5') self.AWG.AWGfromArray(ch, triggerMode, startDelay, cycles, prescaler, waveformType, file_arrayA, arrayB, paddingMode) print('6') self.config['Output'][ch]['value'] = 'Run' print('7')
class Driver(BaseDriver): support_models = ['AWG70001A', 'AWG70002A'] quants = [ # Sample Rate set_cmd is block cmd # QReal('Sample Rate', unit='S/s', set_cmd='CLOC:SRAT %(value).10e; *WAI;', get_cmd='CLOC:SRAT?'), QOption('Run Mode', value='CONT', ch=1, set_cmd='SOUR%(ch)d:RMOD %(option)s', get_cmd='SOUR%(ch)d:RMOD?', options=[('Continuous', 'CONT'), ('Triggered', 'TRIG'), ('TContinuous', 'TCON')]), QOption('Clock Source', value='INT', set_cmd='CLOC:SOUR %(option)s', get_cmd='CLOC:SOUR?', options=[('Internal', 'INT'), ('External', 'EXT'), ('Efixed', 'EFIX'), ('Evariable', 'EVAR')]), # QOption('Reference Source', set_cmd='SOUR:ROSC:SOUR %(option)s', get_cmd='SOUR:ROSC:SOUR?', # options = [('Internal', 'INT'), ('External', 'EXT')]), QReal('Multiplier Rate ', value=1, set_cmd='CLOC:EREF:MULT %(value)d', get_cmd='CLOC:EREF:MULT?'), QReal('Divider Rate ', value=1, set_cmd='CLOC:EREF:DIV %(value)d', get_cmd='CLOC:EREF:DIV?'), # 以下四种只在 output path 为 Direct 时有效 # Vpp range: 250-500mVpp QReal('Vpp', unit='Vpp', ch=1, set_cmd='SOUR%(ch)d:VOLT %(value)f%(unit)s', get_cmd='SOUR%(ch)d:VOLT?'), QReal('Offset', unit='V', ch=1, set_cmd='SOUR%(ch)d:VOLT:OFFS %(value)f%(unit)s', get_cmd='SOUR%(ch)d:VOLT:OFFS?'), QReal('Volt Low', unit='V', ch=1, set_cmd='SOUR%(ch)d:VOLT:LOW %(value)f%(unit)s', get_cmd='SOUR%(ch)d:VOLT:LOW?'), QReal('Volt High', unit='V', ch=1, set_cmd='SOUR%(ch)d:VOLT:HIGH %(value)f%(unit)s', get_cmd='SOUR%(ch)d:VOLT:HIGH?'), # output delay in time QReal('timeDelay', unit='s', ch=1, set_cmd='SOUR%(ch)d:DEL:ADJ %(value)f%(unit)s', get_cmd='SOUR%(ch)d:DEL:ADJ?'), # output delay in point QReal('timeDelay', unit='point', ch=1, set_cmd='SOUR%(ch)d:DEL:POIN %(value)d', get_cmd='SOUR%(ch)d:DELy:POIN?'), QOption('Run', value='Play', set_cmd='AWGC:%(option)s; *WAI;', get_cmd='AWGC:RST?', options=[('Play', 'RUN'), ('Stop', 'STOP')]), QOption('Output', ch=1, set_cmd='OUTP%(ch)d %(option)s', get_cmd='OUTP%(ch)d?', options=[('ON', 1), ('OFF', 0), (1, 'ON'), (0, 'OFF')]), QList('WList'), QList('SList'), # INSTrument MODE : AWG or FG QOption('instMode', value='AWG', set_cmd='INST:MODE %(option)s', get_cmd='INST:MODE?', options=[ ('AWG', 'AWG'), ('FG', 'FGEN'), ]), QOption('FG Type', ch=1, value='Sin', set_cmd='FGEN:CHAN%(ch)d:TYPE %(option)s', get_cmd='FGEN:CHAN%(ch)d:TYPE?', options=[ ('Sin', 'SINE'), ('Square', 'SQU'), ('Triangle', 'TRI'), ('Noise', 'NOIS'), ('DC', 'DC'), ('Gaussian', 'GAUS'), ('ExpRise', 'EXPR'), ('ExpDecay', 'EXPD'), ('None', 'NONE'), ]), QReal('FG Amplitude', ch=1, value=0.5, unit='V', set_cmd='FGEN:CHAN%(ch)d:AMPL:VOLT %(value)f%(unit)s', get_cmd='FGEN:CHAN%(ch)d:AMPL:VOLT?'), #FG Offset -150mV~150mV, min Unit 1mV QReal('FG Offset', ch=1, value=0, unit='V', set_cmd='FGEN:CHAN%(ch)d:OFFS %(value)f%(unit)s', get_cmd='FGEN:CHAN%(ch)d:OFFS?'), QReal('FG Phase', ch=1, value=0, unit='deg', set_cmd='FGEN:CHAN%(ch)d:PHAS %(value)f', get_cmd='FGEN:CHAN%(ch)d:PHAS?'), QReal('FG Frequency', ch=1, value=1e6, unit='Hz', set_cmd='FGEN:CHAN%(ch)d:FREQ %(value)f%(unit)s', get_cmd='FGEN:CHAN%(ch)d:FREQ?'), QReal( 'FG Period', ch=1, unit='s', # 周期与频率绑定,无法设置周期,但可读 set_cmd='', get_cmd='FGEN:CHAN%(ch)d:PER?'), # DC Level Range: –250 mV to 250 mV QReal('FG DC', ch=1, value=0, unit='V', set_cmd='FGEN:CHAN%(ch)d:DCL %(value)f%(unit)s', get_cmd='FGEN:CHAN%(ch)d:DCL?'), QReal('FG High', ch=1, value=0.25, unit='V', set_cmd='FGEN:CHAN%(ch)d:HIGH %(value)f%(unit)s', get_cmd='FGEN:CHAN%(ch)d:HIGH?'), QReal('FG Low', ch=1, value=-0.25, unit='V', set_cmd='FGEN:CHAN%(ch)d:LOW %(value)f%(unit)s', get_cmd='FGEN:CHAN%(ch)d:LOW?'), #coupling mode: DIR, DCAM, AC QOption('FG Path', ch=1, value='Direct', set_cmd='FGEN:CHAN%(ch)d:PATH %(option)s', get_cmd='FGEN:CHAN%(ch)d:PATH?', options=[ ('Direct', 'DIR'), ('DCAmplified', 'DCAM'), ('AC', 'AC'), ]), ] def performOpen(self): self.waveform_list = self.get_waveform_list() try: #没有sequence模块的仪器会产生一个错误 self.sequence_list = self.get_sequence_list() except: self.sequence_list = None def performSetValue(self, quant, value, **kw): if quant.name == '': return else: return BaseDriver.performSetValue(self, quant, value, **kw) def performGetValue(self, quant, **kw): if quant.name == 'WList': self.waveform_list = self.get_waveform_list() return self.waveform_list elif quant.name == 'SList': self.sequence_list = self.get_sequence_list() return self.sequence_list else: return BaseDriver.performGetValue(self, quant, **kw) def get_waveform_list(self): return self.query('WLIS:LIST?').strip("\"\n' ").split(',') def get_sequence_list(self): ret = [] slist_size = int(self.query("SLIS:SIZE?")) for i in range(slist_size): ret.append(self.query("SLIS:NAME? %d" % i).strip("\"\n '")) return ret def create_waveform(self, name, length, format='REAL'): '''format: REAL or IQ''' if name in self.waveform_list: return self.write('WLIS:WAV:NEW "%s",%d,%s;*WAI;' % (name, length, format)) self.waveform_list = self.get_waveform_list() def remove_waveform(self, name=None, all=False): if all: self.write('WLIS:WAV:DEL ALL; *WAI;') self.waveform_list.clear() elif name not in self.waveform_list: return else: self.write('WLIS:WAV:DEL "%s"; *WAI;' % name) self.waveform_list = self.get_waveform_list() def get_waveform_length(self, name): size = int(self.query('WLIS:WAV:LENGTH? "%s"' % name)) return size def use_waveform(self, name, ch=1, type=None): '''type: I or Q''' if type is not None: self.write('SOUR%d:CASS:WAV "%s",%s' % (ch, name, type)) else: self.write('SOUR%d:CASS:WAV "%s"' % (ch, name)) self.write('*WAI;') # 关于RUN的设置和状态询问,建议使用Quantity:Run的方法 def run_state(self): return int(self.query('AWGC:RST?')) def run(self): self.write('AWGC:RUN') self.write('*WAI') def stop(self): self.write('AWGC:STOP') # 关于Output的设置和状态询问,建议使用Quantity:Output的方法 def output_on(self, ch=1): self.write('OUTP%d:STAT 1' % ch) def output_off(self, ch=1): self.write('OUTP%d:STAT 0' % ch) def get_current_asset(self, ch=1): current_type = self.query('SOUR%d:CASS:TYPE?' % ch) current_asset = self.query('SOUR%d:CASS?' % ch) return current_type, current_asset def update_waveform(self, points, name='ABS', IQ='I', start=0, size=None): w_type = self.query('WLIS:WAV:TYPE? "%s"' % name).strip() if w_type == 'REAL': self._update_waveform_float(points, name, IQ, start, size) elif w_type == 'IQ': self._update_waveform_float(points[0], name, 'I', start, size) self._update_waveform_float(points[1], name, 'Q', start, size) self.write('*WAI;') # else: # self._update_waveform_int(points, name, start, size) # def _update_waveform_int(self, points, name='ABS', start=0, size=None): # """ # points : a 1D numpy.array which values between -1 and 1. # """ # message = 'WLIST:WAVEFORM:DATA "%s",%d,' % (name, start) # if size is not None: # message = message + ('%d,' % size) # points = points.clip(-1,1) # values = (points * 0x1fff).astype(int) + 0x1fff # self.write_binary_values(message, values, datatype=u'H', # is_big_endian=False, # termination=None, encoding=None) def _update_waveform_float(self, points, name='ABS', IQ='I', start=0, size=None): message = 'WLIST:WAVEFORM:DATA:%s "%s",%d,' % (IQ, name, start) if size is not None: message = message + ('%d,' % size) values = points.clip(-1, 1) self.write_binary_values(message, values, datatype=u'f', is_big_endian=False, termination=None, encoding=None) # def update_marker(self, name, mk1, mk2=None, mk3=None, mk4=None, start=0, size=None): # def format_marker_data(markers, bits): # values = 0 # for i, v in markers: # v = 0 if v is None else np.asarray(v) # values += v << bits[i] # return values # # if self.model in ['AWG5014C']: # values = format_marker_data([mk1, mk2], [5,6]) # elif self.model in ['AWG5208']: # values = format_marker_data([mk1, mk2, mk3, mk4], [7,6,5,4]) # if size is None: # message = 'WLIST:WAVEFORM:MARKER:DATA "%s",%d,' % (name, start) # else: # message = 'WLIST:WAVEFORM:MARKER:DATA "%s",%d,%d,' % (name, start, size) # self.write_binary_values(message, values, datatype=u'B', # is_big_endian=False, # termination=None, encoding=None) def create_sequence(self, name, steps, tracks=1): if name in self.sequence_list: return self.write('SLIS:SEQ:NEW "%s", %d, %d; *WAI;' % (name, steps, tracks)) self.sequence_list = self.get_sequence_list() def remove_sequence(self, name=None, all=False): if all: self.write('SLIS:SEQ:DEL ALL; *WAI;') self.sequence_list.clear() elif name not in self.sequence_list: return else: self.write('SLIS:SEQ:DEL "%s"; *WAI;' % name) self.sequence_list = self.get_sequence_list() # # def set_sequence_step(self, name, sub_name, step, wait='OFF', goto='NEXT', repeat=1, jump=None): # """set a step of sequence # # name: sequence name # sub_name: subsequence name or list of waveforms for every tracks # wait: ATRigger | BTRigger | ITRigger | OFF # goto: <NR1> | LAST | FIRSt | NEXT | END # repeat: ONCE | INFinite | <NR1> # jump: a tuple (jump_input, jump_to) # jump_input: ATRigger | BTRigger | OFF | ITRigger # jump_to: <NR1> | NEXT | FIRSt | LAST | END # """ # if isinstance(sub_name, str): # self.write('SLIS:SEQ:STEP%d:TASS:SEQ "%s","%s"' % (step, name, sub_name)) # else: # for i, wav in enumerate(sub_name): # self.write('SLIS:SEQ:STEP%d:TASS%d:WAV "%s","%s"' % (step, i+1, name, wav)) # self.write('SLIS:SEQ:STEP%d:WINP "%s", %s' % (step, name, wait)) # self.write('SLIS:SEQ:STEP%d:GOTO "%s", %s' % (step, name, goto)) # self.write('SLIS:SEQ:STEP%d:RCO "%s", %s' % (step, name, repeat)) # if jump is not None: # self.write('SLIS:SEQ:STEP%d:EJIN "%s", %s' % (step, name, jump[0])) # self.write('SLIS:SEQ:STEP%d:EJUM "%s", %s' % (step, name, jump[1])) def use_sequence(self, name, ch=1, track=1, type=None): '''type: I or Q''' if type is not None: self.write('SOUR%d:CASS:SEQ "%s", %d, %s' % (ch, name, track, type)) else: self.write('SOUR%d:CASS:SEQ "%s", %d' % (ch, name, track)) self.write('*WAI;')
class Driver(BaseDriver): support_models = ['AWG5014C', 'AWG5208'] quants = [ QReal('Sample Rate', unit='S/s', set_cmd='SOUR:FREQ %(value)f', get_cmd='SOUR:FREQ?'), QOption('Run Mode', set_cmd='AWGC:RMOD %(option)s', get_cmd='AWGC:RMOD?', options=[('Continuous', 'CONT'), ('Triggered', 'TRIG'), ('Gated', 'GAT'), ('Sequence', 'SEQ')]), QOption('Clock Source', set_cmd='AWGC:CLOC:SOUR %(option)s', get_cmd='AWGC:CLOC:SOUR?', options=[('Internal', 'INT'), ('External', 'EXT')]), QOption('Reference Source', set_cmd='SOUR:ROSC:SOUR %(option)s', get_cmd='SOUR:ROSC:SOUR?', options=[('Internal', 'INT'), ('External', 'EXT')]), QReal('Vpp', unit='V', ch=1, set_cmd='SOUR%(ch)d:VOLT %(value)f', get_cmd='SOUR%(ch)d:VOLT?'), QReal('Offset', unit='V', ch=1, set_cmd='SOUR%(ch)d:VOLT:OFFS %(value)f', get_cmd='SOUR%(ch)d:VOLT:OFFS?'), QReal('Volt Low', unit='V', ch=1, set_cmd='SOUR%(ch)d:VOLT:LOW %(value)f', get_cmd='SOUR%(ch)d:VOLT:LOW?'), QReal('Volt High', unit='V', ch=1, set_cmd='SOUR%(ch)d:VOLT:HIGH %(value)f', get_cmd='SOUR%(ch)d:VOLT:HIGH?'), QReal('Force Jump', unit='Step', ch=1, set_cmd=' SOURCE%(ch)d:JUMP:FORCE %(value)f'), # output delay in time QReal('timeDelay', unit='s', ch=1, set_cmd='SOUR%(ch)d:DEL:ADJ %(value)f%(unit)s', get_cmd='SOUR%(ch)d:DEL:ADJ?'), # output delay in point QReal('pointDelay', unit='point', ch=1, set_cmd='SOUR%(ch)d:DEL:POIN %(value)d', get_cmd='SOUR%(ch)d:DEL:POIN?'), QList('WList'), QList('SList'), ] def performOpen(self): self.waveform_list = self.get_waveform_list() try: #没有sequence模块的仪器会产生一个错误 self.sequence_list = self.get_sequence_list() except: self.sequence_list = None def performSetValue(self, quant, value, **kw): if quant.name == '': return else: return BaseDriver.performSetValue(self, quant, value, **kw) def performGetValue(self, quant, **kw): if quant.name == 'WList': quant.value = self.waveform_list return self.waveform_list elif quant.name == 'SList': quant.value = self.sequence_list return self.sequence_list else: return BaseDriver.performGetValue(self, quant, **kw) def get_waveform_list(self): if self.model in ['AWG5208']: return self.query('WLIS:LIST?').strip("\"\n' ").split(',') elif self.model in ['AWG5014C']: ret = [] wlist_size = int(self.query("WLIS:SIZE?")) for i in range(wlist_size): ret.append(self.query("WLIS:NAME? %d" % i).strip("\"\n '")) return ret else: return [] def get_sequence_list(self): if self.model in ['AWG5208']: ret = [] slist_size = int(self.query("SLIS:SIZE?")) for i in range(slist_size): ret.append( self.query("SLIS:NAME? %d" % (i + 1)).strip("\"\n '")) return ret else: return [] def create_waveform(self, name, length, format=None): ''' format: REAL, INT or IQ ''' if name in self.waveform_list: return if format is None: if self.model in ['AWG5208']: format = 'REAL' else: format = 'INT' self.write('WLIS:WAV:NEW "%s",%d,%s;' % (name, length, format)) self.waveform_list.append(name) def remove_waveform(self, name): if name not in self.waveform_list: return self.waveform_list.remove(name) self.write(':WLIS:WAV:DEL "%s"; *CLS' % name) def clear_waveform_list(self): wavs_to_delete = self.waveform_list.copy() for name in wavs_to_delete: self.remove_waveform(name) def use_waveform(self, name, ch=1): self.write('SOURCE%d:WAVEFORM "%s"' % (ch, name)) def run_state(self): return int(self.query('AWGC:RST?')) def run(self): self.write('AWGC:RUN') self.write('*WAI') def stop(self): self.write('AWGC:STOP') def output_on(self, ch=1): self.write('OUTP%d:STAT 1' % ch) def output_off(self, ch=1): self.write('OUTP%d:STAT 0' % ch) def get_current_waveforms(self): current_waveforms = [] current_waveform_size = 0 for i in [1, 2, 3, 4]: wn = self.query('SOUR%d:WAV?' % i)[1:-2] current_waveforms.append(wn) if wn != '' and current_waveform_size == 0: current_waveform_size = self.query_ascii_values( 'WLIS:WAV:LENGTH? "%s"' % wn, 'd')[0] return current_waveform_size, current_waveforms def update_waveform(self, points, name='ABS', IQ='I', start=0, size=None): w_type = self.query('WLISt:WAVeform:TYPE? "%s"' % name).strip() if w_type == 'REAL': self._update_waveform_float(points, name, IQ, start, size) elif w_type == 'IQ': self._update_waveform_float(points[0], name, 'I', start, size) self._update_waveform_float(points[1], name, 'Q', start, size) else: self._update_waveform_int(points, name, start, size) def _update_waveform_int(self, points, name='ABS', start=0, size=None): """ points : a 1D numpy.array which values between -1 and 1. """ message = 'WLIST:WAVEFORM:DATA "%s",%d,' % (name, start) if size is not None: message = message + ('%d,' % size) points = points.clip(-1, 1) values = (points * 0x1fff).astype(int) + 0x1fff self.write_binary_values(message, values, datatype=u'H', is_big_endian=False, termination=None, encoding=None) self.query('*OPC?') def _update_waveform_float(self, points, name='ABS', IQ='I', start=0, size=None): if self.model == 'AWG5208': message = 'WLIST:WAVEFORM:DATA:%s "%s",%d,' % (IQ, name, start) else: message = 'WLIST:WAVEFORM:DATA "%s",%d,' % (name, start) if size is not None: message = message + ('%d,' % size) values = points.clip(-1, 1) self.write_binary_values(message, values, datatype=u'f', is_big_endian=False, termination=None, encoding=None) self.query('*OPC?') def update_marker(self, name, mk1=None, mk2=None, mk3=None, mk4=None, start=0, size=None): def format_marker_data(markers, bits): values = 0 for i, v in enumerate(markers): v = 0 if v is None else np.asarray(v, dtype=int) values += v << bits[i] return values if self.model in ['AWG5014C']: values = format_marker_data([mk1, mk2], [6, 7]) elif self.model in ['AWG5208']: values = format_marker_data([mk1, mk2, mk3, mk4], [7, 6, 5, 4]) if size is None: message = 'WLIST:WAVEFORM:MARKER:DATA "%s",%d,' % (name, start) else: message = 'WLIST:WAVEFORM:MARKER:DATA "%s",%d,%d,' % (name, start, size) self.write_binary_values(message, values, datatype=u'B', is_big_endian=False, termination=None, encoding=None) self.query('*OPC?') def create_sequence(self, name, steps, tracks): if name in self.sequence_list: return self.write('SLIS:SEQ:NEW "%s", %d, %d' % (name, steps, tracks)) self.sequence_list.append(name) def remove_sequence(self, name): if name not in self.sequence_list: return self.sequence_list.remove(name) self.write('SLIS:SEQ:DEL "%s"' % name) def clear_sequence_list(self): self.write('SLIS:SEQ:DEL ALL') self.sequence_list.clear() def set_sequence_step(self, name, sub_name, step, wait='OFF', goto='NEXT', repeat=1, jump=None): """set a step of sequence name: sequence name sub_name: subsequence name or list of waveforms for every tracks wait: ATRigger | BTRigger | ITRigger | OFF goto: <NR1> | LAST | FIRSt | NEXT | END repeat: ONCE | INFinite | <NR1> jump: a tuple (jump_input, jump_to) jump_input: ATRigger | BTRigger | OFF | ITRigger jump_to: <NR1> | NEXT | FIRSt | LAST | END """ if isinstance(sub_name, str): self.write('SLIS:SEQ:STEP%d:TASS:SEQ "%s","%s"' % (step, name, sub_name)) else: for i, wav in enumerate(sub_name): self.write('SLIS:SEQ:STEP%d:TASS%d:WAV "%s","%s"' % (step, i + 1, name, wav)) self.write('SLIS:SEQ:STEP%d:WINP "%s", %s' % (step, name, wait)) self.write('SLIS:SEQ:STEP%d:GOTO "%s", %s' % (step, name, goto)) self.write('SLIS:SEQ:STEP%d:RCO "%s", %s' % (step, name, repeat)) if jump is not None: self.write('SLIS:SEQ:STEP%d:EJIN "%s", %s' % (step, name, jump[0])) self.write('SLIS:SEQ:STEP%d:EJUM "%s", %s' % (step, name, jump[1])) def set_seq(self, wave_name, step, track, seq_name=None, tag=None, wait='ATR', goto='NEXT', repeat='1', eventinput='OFF', eventjump='NEXT'): """set a step of sequence seq_name: sequence name wave_name: subsequence name or list of waveforms for every tracks wait: ATRigger | BTRigger | ITRigger | OFF goto: <NR1> | LAST | FIRSt | NEXT | END repeat: ONCE | INFinite | <NR1> eventinput: jump_input: ATRigger | BTRigger | OFF | ITRigger eventjump: jump_to: <NR1> | NEXT | FIRSt | LAST | END """ if tag == 'subseq': self.write('SLISt:SEQ:STEP%d:TASSet%d:SEQ "%s","%s"' % (step, track, seq_name, wave_name)) else: for i, wav in enumerate(wave_name, start=2): step = i if i == 2: self.write('SLIS:SEQ:STEP%d:TASS%d:WAV "%s","%s"' % (1, track, seq_name, wav)) self.write('SLIS:SEQ:STEP%d:WINP "%s", %s' % (1, seq_name, 'BTR')) self.write('SLIS:SEQ:STEP%d:GOTO "%s", %s' % (1, seq_name, goto)) self.write('SLIS:SEQ:STEP%d:RCO "%s", %s' % (1, seq_name, repeat)) self.write('SLIS:SEQ:STEP%d:EJIN "%s", %s' % (1, seq_name, eventinput)) self.write('SLIS:SEQ:STEP%d:EJUM "%s", %s' % (1, seq_name, eventjump)) self.write('SLIS:SEQ:STEP%d:TASS%d:WAV "%s","%s"' % (step, track, seq_name, wav)) self.write('SLIS:SEQ:STEP%d:WINP "%s", %s' % (step, seq_name, wait)) self.write('SLIS:SEQ:STEP%d:GOTO "%s", %s' % (step, seq_name, goto)) self.write('SLIS:SEQ:STEP%d:RCO "%s", %s' % (step, seq_name, repeat)) self.write('SLIS:SEQ:STEP%d:EJIN "%s", %s' % (step, seq_name, eventinput)) self.write('SLIS:SEQ:STEP%d:EJUM "%s", %s' % (step, seq_name, eventjump)) if i == len(wave_name) + 1: if len(wave_name) % 64 != 0: num = (len(wave_name) // 64 + 1) * 64 - len(wave_name) + 5 else: num = 5 self.write('SLIS:SEQ:STEP%d:RCO "%s", %s' % (step, seq_name, num)) self.write('SLIS:SEQ:STEP%d:GOTO "%s", %s' % (step, seq_name, 'FIRST')) def use_sequence(self, name, channels=[1, 2]): for i, ch in enumerate(channels): self.write('SOUR%d:CASS:SEQ "%s", %d' % (ch, name, i + 1)) self.write('*WAI')
class Driver(BaseDriver): support_models = ['AWG70001A', 'AWG70002A'] quants = [ QReal('Sample Rate', unit='S/s', set_cmd='CLOC:SRAT %(value).10e', get_cmd='CLOC:SRAT?'), QOption('Run Mode', value='CONT', ch=1, set_cmd='SOUR%(ch)d:RMOD %(option)s', get_cmd='SOUR%(ch)d:RMOD?', options=[('Continuous', 'CONT'), ('Triggered', 'TRIG'), ('TContinuous', 'TCON')]), QOption('Clock Source', value='INT', set_cmd='CLOC:SOUR %(option)s', get_cmd='CLOC:SOUR?', options=[('Internal', 'INT'), ('External', 'EXT'), ('Efixed', 'EFIX'), ('Evariable', 'EVAR')]), # QOption('Reference Source', set_cmd='SOUR:ROSC:SOUR %(option)s', get_cmd='SOUR:ROSC:SOUR?', # options = [('Internal', 'INT'), ('External', 'EXT')]), QReal('Multiplier Rate ', value=1, set_cmd='CLOC:EREF:MULT %(value)d', get_cmd='CLOC:EREF:MULT?'), QReal('Divider Rate ', value=1, set_cmd='CLOC:EREF:DIV %(value)d', get_cmd='CLOC:EREF:DIV?'), QReal('Amplitude', unit='V', ch=1, set_cmd='SOUR%(ch)d:VOLT %(value)f%(unit)s', get_cmd='SOUR%(ch)d:VOLT?'), QReal('Offset', unit='V', ch=1, set_cmd='SOUR%(ch)d:VOLT:OFFS %(value)f%(unit)s', get_cmd='SOUR%(ch)d:VOLT:OFFS?'), QReal('Volt Low', unit='V', ch=1, set_cmd='SOUR%(ch)d:VOLT:LOW %(value)f%(unit)s', get_cmd='SOUR%(ch)d:VOLT:LOW?'), QReal('Volt High', unit='V', ch=1, set_cmd='SOUR%(ch)d:VOLT:HIGH %(value)f%(unit)s', get_cmd='SOUR%(ch)d:VOLT:HIGH?'), # output delay in time QReal('timeDelay', unit='s', ch=1, set_cmd='SOUR%(ch)d:DEL:ADJ %(value)f%(unit)s', get_cmd='SOUR%(ch)d:DEL:ADJ?'), # output delay in point QReal('timeDelay', unit='point', ch=1, set_cmd='SOUR%(ch)d:DEL:POIN %(value)d', get_cmd='SOUR%(ch)d:DELy:POIN?'), QOption('Output', ch=1, set_cmd='OUTP%(ch)d %(option)d', get_cmd='OUTP%(ch)d?', options=[('ON', 1), ('OFF', 0), (1, 1), (0, 0)]), QList('WList'), QList('SList'), ] def performOpen(self): self.waveform_list = self.get_waveform_list() try: #没有sequence模块的仪器会产生一个错误 self.sequence_list = self.get_sequence_list() except: self.sequence_list = None def performSetValue(self, quant, value, **kw): if quant.name == '': return else: return BaseDriver.performSetValue(self, quant, value, **kw) def performGetValue(self, quant, **kw): if quant.name == 'WList': self.waveform_list = self.get_waveform_list() return self.waveform_list elif quant.name == 'SList': self.sequence_list = self.get_sequence_list() return self.sequence_list else: return BaseDriver.performGetValue(self, quant, **kw) def get_waveform_list(self): return self.query('WLIS:LIST?').strip("\"\n' ").split(',') def get_sequence_list(self): ret = [] slist_size = int(self.query("SLIS:SIZE?")) for i in range(slist_size): ret.append(self.query("SLIS:NAME? %d" % i).strip("\"\n '")) return ret def create_waveform(self, name, length, format='REAL'): '''format: REAL or IQ''' if name in self.waveform_list: return self.write('WLIS:WAV:NEW "%s",%d,%s;' % (name, length, format)) self.waveform_list = self.get_waveform_list() def remove_waveform(self, name=None, all=False): if all: self.write('WLIS:WAV:DEL ALL; *CLS') self.waveform_list.clear() elif name not in self.waveform_list: return else: self.write('WLIS:WAV:DEL "%s"; *CLS' % name) self.waveform_list = self.get_waveform_list() def use_waveform(self, name, ch=1, type=None): '''type: I or Q''' if type is not None: self.write('SOUR%d:CASS:WAV "%s",%s' % (ch, name, type)) else: self.write('SOUR%d:CASS:WAV "%s"' % (ch, name)) def run_state(self): return int(self.query('AWGC:RST?')) def run(self): self.write('AWGC:RUN') self.write('*WAI') def stop(self): self.write('AWGC:STOP') def get_current_asset(self, ch=1): current_type = self.query('SOUR%d:CASS:TYPE?' % ch) current_asset = self.query('SOUR%d:CASS?' % ch) return current_type, current_asset def update_waveform(self, points, name='ABS', IQ='I', start=0, size=None): w_type = self.query('WLISt:WAV:TYPE? "%s"' % name).strip() if w_type == 'REAL': self._update_waveform_float(points, name, IQ, start, size) elif w_type == 'IQ': self._update_waveform_float(points[0], name, 'I', start, size) self._update_waveform_float(points[1], name, 'Q', start, size) # else: # self._update_waveform_int(points, name, start, size) # def _update_waveform_int(self, points, name='ABS', start=0, size=None): # """ # points : a 1D numpy.array which values between -1 and 1. # """ # message = 'WLIST:WAVEFORM:DATA "%s",%d,' % (name, start) # if size is not None: # message = message + ('%d,' % size) # points = points.clip(-1,1) # values = (points * 0x1fff).astype(int) + 0x1fff # self.write_binary_values(message, values, datatype=u'H', # is_big_endian=False, # termination=None, encoding=None) def _update_waveform_float(self, points, name='ABS', IQ='I', start=0, size=None): message = 'WLIST:WAVEFORM:DATA:%s "%s",%d,' % (IQ, name, start) if size is not None: message = message + ('%d,' % size) values = points.clip(-1, 1) self.write_binary_values(message, values, datatype=u'f', is_big_endian=False, termination=None, encoding=None) # def update_marker(self, name, mk1, mk2=None, mk3=None, mk4=None, start=0, size=None): # def format_marker_data(markers, bits): # values = 0 # for i, v in markers: # v = 0 if v is None else np.asarray(v) # values += v << bits[i] # return values # # if self.model in ['AWG5014C']: # values = format_marker_data([mk1, mk2], [5,6]) # elif self.model in ['AWG5208']: # values = format_marker_data([mk1, mk2, mk3, mk4], [7,6,5,4]) # if size is None: # message = 'WLIST:WAVEFORM:MARKER:DATA "%s",%d,' % (name, start) # else: # message = 'WLIST:WAVEFORM:MARKER:DATA "%s",%d,%d,' % (name, start, size) # self.write_binary_values(message, values, datatype=u'B', # is_big_endian=False, # termination=None, encoding=None) def create_sequence(self, name, steps, tracks=1): if name in self.sequence_list: return self.write('SLIS:SEQ:NEW "%s", %d, %d' % (name, steps, tracks)) self.sequence_list = self.get_sequence_list() def remove_sequence(self, name=None, all=False): if all: self.write('SLIS:SEQ:DEL ALL; *CLS') self.sequence_list.clear() elif name not in self.sequence_list: return else: self.write('SLIS:SEQ:DEL "%s"' % name) self.sequence_list = self.get_sequence_list() # # def set_sequence_step(self, name, sub_name, step, wait='OFF', goto='NEXT', repeat=1, jump=None): # """set a step of sequence # # name: sequence name # sub_name: subsequence name or list of waveforms for every tracks # wait: ATRigger | BTRigger | ITRigger | OFF # goto: <NR1> | LAST | FIRSt | NEXT | END # repeat: ONCE | INFinite | <NR1> # jump: a tuple (jump_input, jump_to) # jump_input: ATRigger | BTRigger | OFF | ITRigger # jump_to: <NR1> | NEXT | FIRSt | LAST | END # """ # if isinstance(sub_name, str): # self.write('SLIS:SEQ:STEP%d:TASS:SEQ "%s","%s"' % (step, name, sub_name)) # else: # for i, wav in enumerate(sub_name): # self.write('SLIS:SEQ:STEP%d:TASS%d:WAV "%s","%s"' % (step, i+1, name, wav)) # self.write('SLIS:SEQ:STEP%d:WINP "%s", %s' % (step, name, wait)) # self.write('SLIS:SEQ:STEP%d:GOTO "%s", %s' % (step, name, goto)) # self.write('SLIS:SEQ:STEP%d:RCO "%s", %s' % (step, name, repeat)) # if jump is not None: # self.write('SLIS:SEQ:STEP%d:EJIN "%s", %s' % (step, name, jump[0])) # self.write('SLIS:SEQ:STEP%d:EJUM "%s", %s' % (step, name, jump[1])) def use_sequence(self, name, ch=1, track=1, type=None): '''type: I or Q''' if type is not None: self.write('SOUR%d:CASS:SEQ "%s", %d, %s' % (ch, name, track, type)) else: self.write('SOUR%d:CASS:SEQ "%s", %d' % (ch, name, track))