def __init__(self, parent: Instrument, name: str, **kwargs): super().__init__(parent, name, **kwargs) self.add_parameter( 'decimation', ManualParameter, vals=vals.Ints(1), initial_value=1, docstring='The sample rate is reduced by the decimation factor ' 'after filtering.') self.add_parameter('coefficients', ManualParameter, vals=vals.Arrays(), docstring='FIR filter coefficients') self.add_parameter('description', ManualParameter, vals=vals.Strings(), docstring='FIR filter description') self.add_parameter( 'mode', ManualParameter, vals=vals.Enum('full', 'valid'), initial_value='full', docstring='Convolution mode. If `valid`, only points where the ' 'filter and signal overlap completely are returned.') self.coefficients.set(np.array([1.]))
def createWaveformReal(self, name, waveform): """ Convenience function to create a waveform in the AWG and then send data to it Args: name(string): name of waveform for internal use by the AWG waveform (float[numpoints]): vector defining the waveform, normalized between -1.0 and 1.0 Compatibility: QWG """ wv_val = vals.Arrays(min_value=-1, max_value=1) wv_val.validate(waveform) maxWaveLen = 2**17 - 4 # FIXME: this is the hardware max waveLen = len(waveform) if waveLen > maxWaveLen: raise ValueError('Waveform length ({}) must be < {}'.format( waveLen, maxWaveLen)) self.newWaveformReal(name, waveLen) self.sendWaveformDataReal(name, waveform)
def _add_codeword_parameters(self, add_extra: bool = True): self.add_parameter( 'cfg_codeword_protocol', # NB: compatible with ZI drivers unit='', label='Codeword protocol', get_cmd=self._get_codeword_protocol, set_cmd=self._set_codeword_protocol, #vals=vals.Enum('MICROWAVE', 'FLUX', 'MICROWAVE_NO_VSM'), docstring=_codeword_protocol_doc + '\nEffective immediately when sent') docst = 'Specifies a waveform for a specific codeword. \n' \ 'The channel number corresponds' \ ' to the channel as indicated on the device (counting from 1).' for j in range(self._dev_desc.numChannels): for cw in range(self._dev_desc.numCodewords): ch = j + 1 parname = 'wave_ch{}_cw{:03}'.format(ch, cw) self.add_parameter( parname, label='Waveform channel {} codeword {:03}'.format(ch, cw), vals=vals.Arrays(min_value=-1, max_value=1), get_cmd=_gen_get_func_2par(self._get_cw_waveform, ch, cw), set_cmd=_gen_set_func_2par(self._set_cw_waveform, ch, cw), # snapshot_exclude=True, docstring=docst)
def __init__(self, parent: "Keysight_P9374A_SingleChannel", number: int, name: str, **kwargs: Any): self._number = number super().__init__(parent, name=name, **kwargs) self.add_parameter( name='npts', unit='', get_cmd=self._get_npts, docstring='number of points in the trace', ) self.add_parameter( name='frequency', unit='Hz', parameter_class=FrequencyData, trace_number=self._number, vals=vals.Arrays(shape=(self.npts.get_latest,)) ) self.add_parameter( name='data', unit='', setpoints=(self.frequency,), parameter_class=TraceData, trace_number=self._number, vals=vals.Arrays(shape=(self.npts.get_latest,), valid_types=(np.floating, np.complexfloating)) ) self.add_parameter( name='s_parameter', unit='', parameter_class=SParameterData, trace_number=self._number, vals=vals.Enum('S11', 'S12', 'S21', 'S22'), get_parser=str )
def _add_codeword_parameters(self): self._params_to_skip_update = [] docst = ('Specifies a waveform for a specific codeword. ' + 'The channel number corresponds' + ' to the channel as indicated on the device (1 is lowest).') for j in range(self.device_descriptor.numChannels): for cw in range(self.device_descriptor.numCodewords): ch = j + 1 parname = 'wave_ch{}_cw{:03}'.format(ch, cw) self.add_parameter( parname, label='Waveform channel {} codeword {:03}'.format(ch, cw), vals=vals.Arrays(min_value=-1, max_value=1), set_cmd=self._gen_ch_cw_set_func(self._set_cw_waveform, ch, cw), get_cmd=self._gen_ch_cw_get_func(self._get_cw_waveform, ch, cw), docstring=docst) self._params_to_skip_update.append(parname)
def add_standard_parameters(self): """ Function to automatically generate the QCC specific functions from the qcodes parameters. The function uses the add_parameter function internally. """ self.parameter_list = self._read_parameters() for parameter in self.parameter_list: name = parameter["name"] del parameter["name"] if ("vals" in parameter): validator = parameter["vals"] try: val_type = validator["type"] if (val_type == "Bool"): parameter["vals"] = vals.Ints(0, 1) parameter['get_parser'] = int elif (val_type == "IntArray"): parameter["vals"] = vals.Arrays() parameter['get_parser'] = lambda v: np.array( v.split(','), dtype=int) elif (val_type == "QECDataType"): # The QECDataType assumes a long array of ints in which groups of 6 datapoints are returned. # In this datatype every row corresponds to a timeslot # every column corresponds to a qubit index. parameter["vals"] = vals.Anything() elif (val_type == "Non_Neg_Number"): if ("range" in validator): val_min = validator["range"][0] val_max = validator["range"][1] else: val_min = 0 val_max = INT32_MAX parameter["vals"] = vals.PermissiveInts( val_min, val_max) parameter['get_parser'] = int parameter['set_parser'] = int else: log.warning("Failed to set the validator for the" + " parameter " + name + ", because of a" + " unknown validator type: '" + val_type + "'") except Exception as e: log.warning( "Failed to set the validator for the parameter " + name + ".(%s)", str(e)) try: log.info("Adding parameter:") for key, value in parameter.items(): log.info("\t", key, value) log.info("\n") self.add_parameter(name, **parameter) except Exception as e: log.warning( "Failed to create the parameter " + name + ", because of a unknown keyword in this" + " parameter.(%s)", str(e))
def add_parameters(self): ####################################################################### # QWG specific ####################################################################### for i in range(self.device_descriptor.numChannels // 2): ch_pair = i * 2 + 1 sfreq_cmd = 'qutech:output{}:frequency'.format(ch_pair) sph_cmd = 'qutech:output{}:phase'.format(ch_pair) # NB: sideband frequency has a resolution of ~0.23 Hz: self.add_parameter('ch_pair{}_sideband_frequency'.format(ch_pair), parameter_class=HandshakeParameter, unit='Hz', label=('Sideband frequency channel ' + 'pair {} (Hz)'.format(i)), get_cmd=sfreq_cmd + '?', set_cmd=sfreq_cmd + ' {}', vals=vals.Numbers(-300e6, 300e6), get_parser=float) self.add_parameter('ch_pair{}_sideband_phase'.format(ch_pair), parameter_class=HandshakeParameter, unit='deg', label=('Sideband phase channel' + ' pair {} (deg)'.format(i)), get_cmd=sph_cmd + '?', set_cmd=sph_cmd + ' {}', vals=vals.Numbers(-180, 360), get_parser=float) self.add_parameter( 'ch_pair{}_transform_matrix'.format(ch_pair), parameter_class=HandshakeParameter, label=('Transformation matrix channel' + 'pair {}'.format(i)), get_cmd=self._gen_ch_get_func(self._getMatrix, ch_pair), set_cmd=self._gen_ch_set_func(self._setMatrix, ch_pair), # NB range is not a hardware limit vals=vals.Arrays(-2, 2, shape=(2, 2))) for i in range(1, self.device_descriptor.numTriggers + 1): triglev_cmd = 'qutech:trigger{}:level'.format(i) # individual trigger level per trigger input: self.add_parameter('tr{}_trigger_level'.format(i), unit='V', label='Trigger level channel {} (V)'.format(i), get_cmd=triglev_cmd + '?', set_cmd=triglev_cmd + ' {}', vals=self.device_descriptor.mvals_trigger_level, get_parser=float) self.add_parameter('run_mode', get_cmd='AWGC:RMO?', set_cmd='AWGC:RMO ' + '{}', vals=vals.Enum('NONE', 'CONt', 'SEQ', 'CODeword')) # NB: setting mode "CON" (valid SCPI abbreviation) reads back as "CONt" # Channel parameters # for ch in range(1, self.device_descriptor.numChannels + 1): amp_cmd = 'SOUR{}:VOLT:LEV:IMM:AMPL'.format(ch) offset_cmd = 'SOUR{}:VOLT:LEV:IMM:OFFS'.format(ch) state_cmd = 'OUTPUT{}:STATE'.format(ch) waveform_cmd = 'SOUR{}:WAV'.format(ch) output_voltage_cmd = 'QUTEch:OUTPut{}:Voltage'.format(ch) dac_temperature_cmd = 'STATus:DAC{}:TEMperature'.format(ch) gain_adjust_cmd = 'DAC{}:GAIn:DRIFt:ADJust'.format(ch) dac_digital_value_cmd = 'DAC{}:DIGitalvalue'.format(ch) # Set channel first to ensure sensible sorting of pars # Compatibility: 5014, QWG self.add_parameter('ch{}_state'.format(ch), label='Status channel {}'.format(ch), get_cmd=state_cmd + '?', set_cmd=state_cmd + ' {}', val_mapping={ True: '1', False: '0' }, vals=vals.Bool()) self.add_parameter( 'ch{}_amp'.format(ch), parameter_class=HandshakeParameter, label='Channel {} Amplitude '.format(ch), unit='Vpp', docstring='Amplitude channel {} (Vpp into 50 Ohm)'.format(ch), get_cmd=amp_cmd + '?', set_cmd=amp_cmd + ' {:.6f}', vals=vals.Numbers(-1.6, 1.6), get_parser=float) self.add_parameter( 'ch{}_offset'.format(ch), # parameter_class=HandshakeParameter, label='Offset channel {}'.format(ch), unit='V', get_cmd=offset_cmd + '?', set_cmd=offset_cmd + ' {:.3f}', vals=vals.Numbers(-.25, .25), get_parser=float) self.add_parameter('ch{}_default_waveform'.format(ch), get_cmd=waveform_cmd + '?', set_cmd=waveform_cmd + ' "{}"', vals=vals.Strings()) self.add_parameter('status_dac{}_temperature'.format(ch), unit='C', label=('DAC {} temperature'.format(ch)), get_cmd=dac_temperature_cmd + '?', get_parser=float, docstring='Reads the temperature of a DAC.\n' \ +'Temperature measurement interval is 10 seconds\n' \ +'Return:\n float with temperature in Celsius') self.add_parameter('output{}_voltage'.format(ch), unit='V', label=('Channel {} voltage output').format(ch), get_cmd=output_voltage_cmd + '?', get_parser=float, docstring='Reads the output voltage of a channel.\n' \ +'Notes:\n Measurement interval is 10 seconds.\n' \ +' The output voltage will only be read if the channel is disabled:\n' \ +' E.g.: qwg.chX_state(False)\n' \ +' If the channel is enabled it will return an low value: >0.1\n' \ +'Return:\n float in voltage') self.add_parameter('dac{}_gain_drift_adjust'.format(ch), unit='', label=('DAC {}, gain drift adjust').format(ch), get_cmd=gain_adjust_cmd + '?', set_cmd=gain_adjust_cmd + ' {}', vals=vals.Ints(0, 4095), get_parser=int, docstring='Gain drift adjust setting of the DAC of a channel.\n' \ +'Used for calibration of the DAC. Do not use to set the gain of a channel!\n' \ +'Notes:\n The gain setting is from 0 to 4095 \n' \ +' Where 0 is 0 V and 4095 is 3.3V \n' \ +'Get Return:\n Setting of the gain in interger (0 - 4095)\n'\ +'Set parameter:\n Integer: Gain of the DAC in , min: 0, max: 4095') self.add_parameter('_dac{}_digital_value'.format(ch), unit='', label=('DAC {}, set digital value').format(ch), set_cmd=dac_digital_value_cmd + ' {}', vals=vals.Ints(0, 4095), docstring='FOR DEVELOPMENT ONLY: Set a digital value directly into the DAC\n' \ +'Used for testing the DACs.\n' \ +'Notes:\n\tThis command will also set the ' \ +'\tinternal correction matrix (Phase and amplitude) of the channel pair to [0,0,0,0], ' \ +'disabling any influence from the wave memory.' \ +'This will also stop the wave the other channel of the pair!\n\n' \ +'Set parameter:\n\tInteger: Value to write to the DAC, min: 0, max: 4095\n' \ +'\tWhere 0 is minimal DAC scale and 4095 is maximal DAC scale \n') self.add_parameter('status_frontIO_temperature', unit='C', label=('FrontIO temperature'), get_cmd='STATus:FrontIO:TEMperature?', get_parser=float, docstring='Reads the temperature of the frontIO.\n' \ +'Temperature measurement interval is 10 seconds\n' \ +'Return:\n float with temperature in Celsius') self.add_parameter('status_fpga_temperature', unit='C', label=('FPGA temperature'), get_cmd='STATus:FPGA:TEMperature?', get_parser=int, docstring='Reads the temperature of the FPGA.\n' \ +'Temperature measurement interval is 10 seconds\n' \ +'Return:\n float with temperature in Celsius') for cw in range(self.device_descriptor.numCodewords): for j in range(self.device_descriptor.numChannels): ch = j + 1 # Codeword 0 corresponds to bitcode 0 cw_cmd = 'sequence:element{:d}:waveform{:d}'.format(cw, ch) self.add_parameter('codeword_{}_ch{}_waveform'.format(cw, ch), get_cmd=cw_cmd + '?', set_cmd=cw_cmd + ' "{:s}"', vals=vals.Strings()) # Waveform parameters self.add_parameter('WlistSize', label='Waveform list size', unit='#', get_cmd='wlist:size?', get_parser=int) self.add_parameter('Wlist', label='Waveform list', get_cmd=self._getWlist) self.add_parameter('get_system_status', unit='JSON', label=('System status'), get_cmd='SYSTem:STAtus?', vals=vals.Strings(), get_parser=self.JSON_parser, docstring='Reads the current system status. E.q. channel ' \ +'status: on or off, overflow, underdrive.\n' \ +'Return:\n JSON object with system status') # Trigger parameters doc_trgs_log_inp = 'Reads the current input values on the all the trigger ' \ +'inputs.\nReturn:\n uint32 where trigger 1 (T1) ' \ +'is on the Least significant bit (LSB), T2 on the second ' \ +'bit after LSB, etc.\n\n For example, if only T3 is ' \ +'connected to a high signal, the return value is: ' \ +'4 (0b0000100)\n\n Note: To convert the return value ' \ +'to a readable ' \ +'binary output use: `print(\"{0:#010b}\".format(qwg.' \ +'triggers_logic_input()))`' self.add_parameter( 'triggers_logic_input', label='Read triggers input value', get_cmd='QUTEch:TRIGgers:LOGIcinput?', get_parser=np.uint32, # Did not convert to readable # string because a uint32 is more # usefull when other logic is needed docstring=doc_trgs_log_inp) self._add_codeword_parameters() self.add_function('deleteWaveformAll', call_cmd='wlist:waveform:delete all') doc_sSG = "Synchronize both sideband frequency" \ + " generators, i.e. restart them with their defined phases." self.add_function('syncSidebandGenerators', call_cmd='QUTEch:OUTPut:SYNCsideband', docstring=doc_sSG)
def __init__(self, parent: "Infiniium", name: str, channel: int, **kwargs: Any): """ Initialize an infiniium channel. """ self._channel = channel super().__init__(parent, name, **kwargs) # display self.display = Parameter( name="display", instrument=self, label=f"Channel {channel} display on/off", set_cmd=f"CHAN{channel}:DISP {{}}", get_cmd=f"CHAN{channel}:DISP?", val_mapping=create_on_off_val_mapping(on_val=1, off_val=0), ) # scaling self.offset = Parameter( name="offset", instrument=self, label=f"Channel {channel} offset", set_cmd=f"CHAN{channel}:OFFS {{}}", unit="V", get_cmd=f"CHAN{channel}:OFFS?", get_parser=float, ) self.range = Parameter( name="range", instrument=self, label=f"Channel {channel} range", unit="V", set_cmd=f"CHAN{channel}:RANG {{}}", get_cmd=f"CHAN{channel}:RANG?", get_parser=float, vals=vals.Numbers(), ) # Trigger level self.trigger_level = Parameter( name="trigger_level", instrument=self, label=f"Channel {channel} trigger level", unit="V", set_cmd=f":TRIG:LEV CHAN{channel},{{}}", get_cmd=f":TRIG:LEV? CHAN{channel}", get_parser=float, vals=vals.Numbers(), ) # Trace data self.time_axis = DSOTimeAxisParam( name="time_axis", instrument=self, label="Time", unit="s", xorigin=0.0, xincrement=0.0, points=1, vals=vals.Arrays(shape=(self.parent.acquire_points, )), snapshot_value=False, ) self.trace = DSOTraceParam( name="trace", instrument=self, label=f"Channel {channel} trace", unit="V", channel=self.channel_name, vals=vals.Arrays(shape=(self.parent.acquire_points, )), snapshot_value=False, ) # Measurement subsystem self.add_submodule("measure", BoundMeasurement(self, "measure"))
def __init__(self, parent: "Infiniium", name: str, channel: int, **kwargs: Any): """ Initialize an infiniium channel. """ self._channel = channel super().__init__(parent, name, **kwargs) # display self.display = Parameter( name="display", instrument=self, label=f"Function {channel} display on/off", set_cmd=f"FUNC{channel}:DISP {{}}", get_cmd=f"FUNC{channel}:DISP?", val_mapping=create_on_off_val_mapping(on_val=1, off_val=0), ) # Retrieve basic settings of the function self.function = Parameter( name="function", instrument=self, label=f"Function {channel} function", get_cmd=self._get_func, vals=vals.Strings(), ) self.source = Parameter( name="source", instrument=self, label=f"Function {channel} source", get_cmd=f"FUNC{channel}?", ) # Trace settings self.points = Parameter( name="points", instrument=self, label=f"Function {channel} points", get_cmd=self._get_points, ) self.frequency_axis = DSOFrequencyAxisParam( name="frequency_axis", instrument=self, label="Frequency", unit="Hz", xorigin=0.0, xincrement=0.0, points=1, vals=vals.Arrays(shape=(self.points, )), snapshot_value=False, ) self.time_axis = DSOTimeAxisParam( name="time_axis", instrument=self, label="Time", unit="s", xorigin=0.0, xincrement=0.0, points=1, vals=vals.Arrays(shape=(self.points, )), snapshot_value=False, ) self.trace = DSOTraceParam( name="trace", instrument=self, label=f"Function {channel} trace", channel=self.channel_name, vals=vals.Arrays(shape=(self.points, )), snapshot_value=False, ) # Measurement subsystem self.add_submodule("measure", BoundMeasurement(self, "measure"))
def add_parameters(self): ####################################################################### # QWG specific ####################################################################### # Channel pair parameters for i in range(self.device_descriptor.numChannels // 2): ch_pair = i * 2 + 1 sfreq_cmd = 'qutech:output{}:frequency'.format(ch_pair) sph_cmd = 'qutech:output{}:phase'.format(ch_pair) # NB: sideband frequency has a resolution of ~0.23 Hz: self.add_parameter('ch_pair{}_sideband_frequency'.format(ch_pair), parameter_class=HandshakeParameter, unit='Hz', label=('Sideband frequency channel ' + 'pair {} (Hz)'.format(i)), get_cmd=sfreq_cmd + '?', set_cmd=sfreq_cmd + ' {}', vals=vals.Numbers(-300e6, 300e6), get_parser=float) self.add_parameter('ch_pair{}_sideband_phase'.format(ch_pair), parameter_class=HandshakeParameter, unit='deg', label=('Sideband phase channel' + ' pair {} (deg)'.format(i)), get_cmd=sph_cmd + '?', set_cmd=sph_cmd + ' {}', vals=vals.Numbers(-180, 360), get_parser=float) self.add_parameter( 'ch_pair{}_transform_matrix'.format(ch_pair), parameter_class=HandshakeParameter, label=('Transformation matrix channel' + 'pair {}'.format(i)), get_cmd=self._gen_ch_get_func(self._getMatrix, ch_pair), set_cmd=self._gen_ch_set_func(self._setMatrix, ch_pair), # NB range is not a hardware limit vals=vals.Arrays(-2, 2, shape=(2, 2))) # Triggers parameter for i in range(1, self.device_descriptor.numTriggers + 1): triglev_cmd = 'qutech:trigger{}:level'.format(i) # individual trigger level per trigger input: self.add_parameter('tr{}_trigger_level'.format(i), unit='V', label='Trigger level channel {} (V)'.format(i), get_cmd=triglev_cmd + '?', set_cmd=triglev_cmd + ' {}', vals=self.device_descriptor.mvals_trigger_level, get_parser=float) self.add_parameter('run_mode', get_cmd='AWGC:RMO?', set_cmd='AWGC:RMO ' + '{}', vals=vals.Enum('NONE', 'CONt', 'SEQ', 'CODeword')) # NB: setting mode "CON" (valid SCPI abbreviation) reads back as "CONt" self.add_parameter('dio_mode', unit='', label='DIO input operation mode', get_cmd='DIO:MODE?', set_cmd='DIO:MODE ' + '{}', vals=vals.Enum('MASTER', 'SLAVE'), val_mapping={'MASTER': 'MASter', 'SLAVE': 'SLAve'}, docstring='Get or set the DIO input operation mode\n' \ 'Paramaters:\n' \ '\tMASTER: Use DIO codeword (lower 14 bits) input '\ 'from its own IORearDIO board' \ '\t\tEnables single-ended and differential inputs\n' \ '\tSLAVE; Use DIO codeword (upper 14 bits) input '\ 'from the connected master IORearDIO board\n' '\t\tDisables SE and DIFF inputs\n' ) self.add_parameter('dio_is_calibrated', unit='', label='DIO calibration status', get_cmd='DIO:CALibrate?', val_mapping={ True: '1', False: '0' }, docstring="""Get DIO calibration status\n Result:\n \tTrue: DIO is calibrated\n \tFalse: DIO is not calibrated""") self.add_parameter('dio_active_index', unit='', label='DIO calibration index', get_cmd='DIO:INDexes:ACTive?', set_cmd='DIO:INDexes:ACTive {}', get_parser=np.uint32, vals=vals.Ints(0, 20), docstring='Get and set DIO calibration index\n' \ 'See dio_calibrate() paramater\n' ) self.add_parameter('dio_suitable_indexes', unit='', label='DIO suitable indexes', get_cmd='DIO:INDexes?', get_parser=self._int_to_array, docstring='Get DIO all suitable indexes\n' \ '\t- The array is ordered by most preferable index first\n' ) self.add_parameter( 'dio_calibrated_inputs', unit='', label='DIO calibrated inputs', get_cmd='DIO:INPutscalibrated?', get_parser=int, docstring='Get all DIO inputs which are calibrated\n') self.add_parameter('dio_lvds', unit='bool', label='LVDS DIO connection detected', get_cmd='DIO:LVDS?', val_mapping={ True: '1', False: '0' }, docstring='Get the DIO LVDS connection status.\n' 'Result:\n' '\tTrue: Cable detected\n' '\tFalse: No cable detected') self.add_parameter( 'dio_interboard', unit='bool', label='DIO interboard detected', get_cmd='DIO:IB?', val_mapping={ True: '1', False: '0' }, docstring='Get the DIO interboard status.\n' 'Result:\n' '\tTrue: To master interboard connection detected\n' '\tFalse: No interboard connection detected') # Channel parameters # for ch in range(1, self.device_descriptor.numChannels + 1): amp_cmd = 'SOUR{}:VOLT:LEV:IMM:AMPL'.format(ch) offset_cmd = 'SOUR{}:VOLT:LEV:IMM:OFFS'.format(ch) state_cmd = 'OUTPUT{}:STATE'.format(ch) waveform_cmd = 'SOUR{}:WAV'.format(ch) output_voltage_cmd = 'QUTEch:OUTPut{}:Voltage'.format(ch) dac_temperature_cmd = 'STATus:DAC{}:TEMperature'.format(ch) gain_adjust_cmd = 'DAC{}:GAIn:DRIFt:ADJust'.format(ch) dac_digital_value_cmd = 'DAC{}:DIGitalvalue'.format(ch) # Set channel first to ensure sensible sorting of pars # Compatibility: 5014, QWG self.add_parameter('ch{}_state'.format(ch), label='Status channel {}'.format(ch), get_cmd=state_cmd + '?', set_cmd=state_cmd + ' {}', val_mapping={ True: '1', False: '0' }, vals=vals.Bool()) self.add_parameter( 'ch{}_amp'.format(ch), parameter_class=HandshakeParameter, label='Channel {} Amplitude '.format(ch), unit='Vpp', docstring='Amplitude channel {} (Vpp into 50 Ohm)'.format(ch), get_cmd=amp_cmd + '?', set_cmd=amp_cmd + ' {:.6f}', vals=vals.Numbers(-1.6, 1.6), get_parser=float) self.add_parameter( 'ch{}_offset'.format(ch), # parameter_class=HandshakeParameter, label='Offset channel {}'.format(ch), unit='V', get_cmd=offset_cmd + '?', set_cmd=offset_cmd + ' {:.3f}', vals=vals.Numbers(-.25, .25), get_parser=float) self.add_parameter('ch{}_default_waveform'.format(ch), get_cmd=waveform_cmd + '?', set_cmd=waveform_cmd + ' "{}"', vals=vals.Strings()) self.add_parameter('status_dac{}_temperature'.format(ch), unit='C', label=('DAC {} temperature'.format(ch)), get_cmd=dac_temperature_cmd + '?', get_parser=float, docstring='Reads the temperature of a DAC.\n' \ +'Temperature measurement interval is 10 seconds\n' \ +'Return:\n float with temperature in Celsius') self.add_parameter('output{}_voltage'.format(ch), unit='V', label=('Channel {} voltage output').format(ch), get_cmd=output_voltage_cmd + '?', get_parser=float, docstring='Reads the output voltage of a channel.\n' \ +'Notes:\n Measurement interval is 10 seconds.\n' \ +' The output voltage will only be read if the channel is disabled:\n' \ +' E.g.: qwg.chX_state(False)\n' \ +' If the channel is enabled it will return an low value: >0.1\n' \ +'Return:\n float in voltage') self.add_parameter('dac{}_gain_drift_adjust'.format(ch), unit='', label=('DAC {}, gain drift adjust').format(ch), get_cmd=gain_adjust_cmd + '?', set_cmd=gain_adjust_cmd + ' {}', vals=vals.Ints(0, 4095), get_parser=int, docstring='Gain drift adjust setting of the DAC of a channel.\n' \ +'Used for calibration of the DAC. Do not use to set the gain of a channel!\n' \ +'Notes:\n The gain setting is from 0 to 4095 \n' \ +' Where 0 is 0 V and 4095 is 3.3V \n' \ +'Get Return:\n Setting of the gain in interger (0 - 4095)\n'\ +'Set parameter:\n Integer: Gain of the DAC in , min: 0, max: 4095') self.add_parameter('_dac{}_digital_value'.format(ch), unit='', label=('DAC {}, set digital value').format(ch), set_cmd=dac_digital_value_cmd + ' {}', vals=vals.Ints(0, 4095), docstring='FOR DEVELOPMENT ONLY: Set a digital value directly into the DAC\n' \ +'Used for testing the DACs.\n' \ +'Notes:\n\tThis command will also set the ' \ +'\tinternal correction matrix (Phase and amplitude) of the channel pair to [0,0,0,0], ' \ +'disabling any influence from the wave memory.' \ +'This will also stop the wave the other channel of the pair!\n\n' \ +'Set parameter:\n\tInteger: Value to write to the DAC, min: 0, max: 4095\n' \ +'\tWhere 0 is minimal DAC scale and 4095 is maximal DAC scale \n') self.add_parameter('ch{}_bit_select'.format(ch), unit='', label=('Channel {}, set bit selection for this channel').format(ch), get_cmd=self._gen_ch_get_func( self._get_bit_select, ch), set_cmd=self._gen_ch_set_func( self._set_bit_select, ch), get_parser=np.uint32, docstring='Codeword bit select for a channel\n' \ +'Set: \n' \ +'\tParamater: Integer, the bit select\n' \ +'\nWhen a bit is enabled (1) in the bitSelect, this bit is used as part of the codeword for that channel. ' \ +' If a bit is disabled (0), it will be ignored.\n' \ +'This can be used to control individual channels with a their own codeword.\n' \ +'Note that codeword 1 will start on the first enabled bit. Bit endianness: LSB, lowest bit right \n' \ +'\nExamples:\n' \ +'\tCh1: 0b000011(0x03); Only the first and second bit will be used as codeword for channel 1.\n'\ +'\tCh2: 0b001100(0x0C); Only the third and forth bit will be used as codeword for channel 2.\n'\ +'\tCh3: 0b110000(0x30); Only the fifth and sixth bit will be used as codeword for channel 3.\n'\ +'\tCh4: 0b110000(0x30); Only the fifth and sixth bit will be used as codeword for channel 4.\n'\ +'The bit select of different channels are only allowed to overlap each other if their least significant bit is the same.\n' \ +'So a bitSelect of ch1: 0b011, and ch2: 0b010 is not allowed. This will be checked on `start()`. Errors are reported by `getError()` or `getErrors()`.' \ +'\n\n Get:\n' \ +'\tResult: Integer that represent the bit select of the channel\n') self.add_parameter( 'ch{}_bit_map'.format(ch), unit='', label='Channel {}, set bit map for this channel'.format(ch), get_cmd=f"DAC{ch}:BITmap?", set_cmd=self._gen_ch_set_func(self._set_bit_map, ch), get_parser=self._int_to_array, docstring='Codeword bit map for a channel\n') # Trigger parameters doc_trgs_log_inp = 'Reads the current input values on the all the trigger ' \ +'inputs for a channel, after the bitSelect.\nReturn:\n uint32 where trigger 1 (T1) ' \ +'is on the Least significant bit (LSB), T2 on the second ' \ +'bit after LSB, etc.\n\n For example, if only T3 is ' \ +'connected to a high signal, the return value is: ' \ +'4 (0b0000100)\n\n Note: To convert the return value ' \ +'to a readable ' \ +'binary output use: `print(\"{0:#010b}\".format(qwg.' \ +'triggers_logic_input()))`' self.add_parameter( 'ch{}_triggers_logic_input'.format(ch), label='Read triggers input value', get_cmd='QUTEch:TRIGgers{}:LOGIcinput?'.format(ch), get_parser=np.uint32, # Did not convert to readable # string because a uint32 is more # usefull when other logic is needed docstring=doc_trgs_log_inp) # Single parameters self.add_parameter('status_frontIO_temperature', unit='C', label='FrontIO temperature', get_cmd='STATus:FrontIO:TEMperature?', get_parser=float, docstring='Reads the temperature of the frontIO.\n' \ +'Temperature measurement interval is 10 seconds\n' \ +'Return:\n float with temperature in Celsius') self.add_parameter('status_fpga_temperature', unit='C', label=('FPGA temperature'), get_cmd='STATus:FPGA:TEMperature?', get_parser=int, docstring='Reads the temperature of the FPGA.\n' \ +'Temperature measurement interval is 10 seconds\n' \ +'Return:\n float with temperature in Celsius') # Paramater for codeword per channel for cw in range(self.device_descriptor.numCodewords): for j in range(self.device_descriptor.numChannels): ch = j + 1 # Codeword 0 corresponds to bitcode 0 cw_cmd = 'sequence:element{:d}:waveform{:d}'.format(cw, ch) self.add_parameter('codeword_{}_ch{}_waveform'.format(cw, ch), get_cmd=cw_cmd + '?', set_cmd=cw_cmd + ' "{:s}"', vals=vals.Strings()) # Waveform parameters self.add_parameter('WlistSize', label='Waveform list size', unit='#', get_cmd='wlist:size?', get_parser=int) self.add_parameter('Wlist', label='Waveform list', get_cmd=self._getWlist) self.add_parameter('get_system_status', unit='JSON', label="System status", get_cmd='SYSTem:STAtus?', vals=vals.Strings(), get_parser=self.JSON_parser, docstring='Reads the current system status. E.q. channel ' \ +'status: on or off, overflow, underdrive.\n' \ +'Return:\n JSON object with system status') self.add_parameter( 'get_max_codeword_bits', unit='', label=('Max codeword bits'), get_cmd=self._nr_cw_bits_cmd, vals=vals.Strings(), get_parser=int, docstring= 'Reads the maximal number of codeword bits for all channels') self.add_parameter('codeword_protocol', unit='', label='Codeword protocol', get_cmd=self._getCodewordProtocol, set_cmd=self._setCodewordProtocol, vals=vals.Enum('MICROWAVE', 'FLUX'), docstring='Reads the current system status. E.q. channel ' \ +'status: on or off, overflow, underdrive.\n' \ +'Return:\n JSON object with system status') self._add_codeword_parameters() self.add_function('deleteWaveformAll', call_cmd='wlist:waveform:delete all') doc_sSG = "Synchronize both sideband frequency" \ + " generators, i.e. restart them with their defined phases." self.add_function('syncSidebandGenerators', call_cmd='QUTEch:OUTPut:SYNCsideband', docstring=doc_sSG)
def _add_awg_parameters(self): # Channel pair parameters for i in range(self._dev_desc.numChannels // 2): ch_pair = i * 2 + 1 self.add_parameter( f'ch_pair{ch_pair}_sideband_frequency', parameter_class=HandshakeParameter, unit='Hz', label=('Sideband frequency channel pair {} (Hz)'.format(i)), get_cmd=_gen_get_func_1par(self.get_sideband_frequency, ch_pair), set_cmd=_gen_set_func_1par(self.set_sideband_frequency, ch_pair), vals=vals.Numbers(-300e6, 300e6), get_parser=float, docstring='Frequency of the sideband modulator\n' 'Resolution: ~0.23 Hz') self.add_parameter( f'ch_pair{ch_pair}_sideband_phase', parameter_class=HandshakeParameter, unit='deg', label=('Sideband phase channel pair {} (deg)'.format(i)), get_cmd=_gen_get_func_1par(self.get_sideband_phase, ch_pair), set_cmd=_gen_set_func_1par(self.set_sideband_phase, ch_pair), vals=vals.Numbers(-180, 360), get_parser=float, docstring='Sideband phase difference between channels') self.add_parameter( f'ch_pair{ch_pair}_transform_matrix', parameter_class=HandshakeParameter, unit='%', label=('Transformation matrix channel pair {}'.format(i)), get_cmd=_gen_get_func_1par(self._get_matrix, ch_pair), set_cmd=_gen_set_func_1par(self._set_matrix, ch_pair), vals=vals.Arrays( -2, 2, shape=(2, 2)), # NB range is not a hardware limit docstring= 'Transformation matrix for mixer correction per channel pair') # Channel parameters for ch in range(1, self._dev_desc.numChannels + 1): self.add_parameter( f'ch{ch}_state', label=f'Output state channel {ch}', get_cmd=_gen_get_func_1par(self.get_output_state, ch), set_cmd=_gen_set_func_1par(self.set_output_state, ch), val_mapping={ True: '1', False: '0' }, vals=vals.Bool(), docstring='Enables or disables the output of channels\n' 'Default: Disabled') self.add_parameter( f'ch{ch}_amp', parameter_class=HandshakeParameter, label=f'Channel {ch} Amplitude ', unit='Vpp', get_cmd=_gen_get_func_1par(self.get_amplitude, ch), set_cmd=_gen_set_func_1par(self.set_amplitude, ch), vals=vals.Numbers(-1.6, 1.6), get_parser=float, docstring=f'Amplitude channel {ch} (Vpp into 50 Ohm)') self.add_parameter( f'ch{ch}_offset', # parameter_class=HandshakeParameter, FIXME: was commented out label=f'Offset channel {ch}', unit='V', get_cmd=_gen_get_func_1par(self.get_offset, ch), set_cmd=_gen_set_func_1par(self.set_offset, ch), vals=vals.Numbers(-.25, .25), get_parser=float, docstring=f'Offset channel {ch}') self.add_parameter( f'ch{ch}_default_waveform', get_cmd=_gen_get_func_1par(self.get_waveform, ch), set_cmd=_gen_set_func_1par(self.set_waveform, ch), # FIXME: docstring vals=vals.Strings()) # end for(ch... # FIXME: enable if/when support for marker/trigger board is added again # Triggers parameter # for trigger in range(1, self._dev_desc.numTriggers+1): # triglev_cmd = f'qutech:trigger{trigger}:level' # # individual trigger level per trigger input: # self.add_parameter( # f'tr{trigger}_trigger_level', # unit='V', # label=f'Trigger level channel {trigger} (V)', # # FIXME # get_cmd=triglev_cmd + '?', # set_cmd=triglev_cmd + ' {}', # vals=self._dev_desc.mvals_trigger_level, # get_parser=float, # snapshot_exclude=True) # # FIXME: docstring # Single parameters self.add_parameter('run_mode', get_cmd=self.get_run_mode, set_cmd=self.set_run_mode, vals=vals.Enum('NONE', 'CONt', 'SEQ', 'CODeword'), docstring=_run_mode_doc + '\n Effective after start command')