Source code for qcodes_contrib_drivers.drivers.ERAInstruments.erasynth

"""Driver for the ERASynth/ERASynth+/ERASynth++ signal generators.

Author: Victor Negîrneac, vnegirneac@qblox.com

For official instrument support visit:

- https://erainstruments.com
- https://github.com/erainstruments/

This module provides the following drivers:

- :class:`qcodes_contrib_drivers.drivers.ERAInstruments.ERASynth <qcodes_contrib_drivers.drivers.ERAInstruments.erasynth.ERASynth>`,
- :class:`qcodes_contrib_drivers.drivers.ERAInstruments.ERASynthPlus <qcodes_contrib_drivers.drivers.ERAInstruments.erasynth.ERASynthPlus>`, and
- :class:`qcodes_contrib_drivers.drivers.ERAInstruments.ERASynthPlusPlus <qcodes_contrib_drivers.drivers.ERAInstruments.erasynth.ERASynthPlusPlus>`.
"""
from __future__ import annotations

from typing import Dict, List, Union, Tuple, Optional
import time
import json
import logging

from qcodes import VisaInstrument, Parameter, validators

try:
    import pyvisa
except ModuleNotFoundError as e:
    raise ModuleNotFoundError(
        "ERAInstrument drivers require the `pyvisa` package to be installed.\n"
        "Install it with `pip install pyvisa` and try again."
    ) from e

logger = logging.getLogger(__name__)

BAUDRATE = 115200

_CMD_TO_JSON_MAPPING: Dict[str, str] = {
    # We will treat these differently when confirming the value
    # because the instrument replies with a sentence containing the value.
    # which is much faster than reading the full JSON
    # as fast as possible
    # "P0": "rfoutput",
    # "A": "amplitude",
    # "F": "frequency",
    "P1": "reference_int_ext",
    "P5": "reference_tcxo_ocxo",
    "MS": "modulation_on_off",
    "M2": "modulation_signal_waveform",
    "M1": "modulation_source",
    "M0": "modulation_type",
    "M3": "modulation_freq",
    "M5": "modulation_am_depth",
    "M4": "modulation_fm_deviation",
    "M6": "modulation_pulse_period",
    "M7": "modulation_pulse_width",
    "SS": "sweep_start_stop",
    "S0": "sweep_trigger",
    "S1": "sweep_start",
    "S2": "sweep_stop",
    "S3": "sweep_step",
    "S4": "sweep_dwell",
    "P9": "phase_noise_mode",
    "PEW": "wifi_mode",
    "PES0": "wifi_sta_ssid",
    "PEP0": "wifi_sta_password",
    "PES1": "wifi_ap_ssid",
    "PEP1": "wifi_ap_password",
    "PEI": "wifi_ip_address",
    "PEN": "wifi_subnet_address",
    "PEG": "wifi_gateway_address",
}
"""
A mapping used to read back certain commands to ensure they have been set.
This is necessary due to non-deterministic communication times.
"""

[docs] class ERASynthBase(VisaInstrument): r""" A Base class for the ERASynth/ERASynth+/ERASynth++ instruments. Example: .. code-block:: from qcodes import Instrument from qcodes_contrib_drivers.drivers.ERAInstruments import ERASynthPlus # list communication ports ERASynthPlus.print_pyvisa_resources() # Instantiate the instrument lo = ERASynthPlus("ERASynthPlus", 'ASRL/dev/cu.usbmodem14101::INSTR') lo.off() # Turn off the output # print updated snapshot once to make sure the snapshot will be up-to-date # takes a few seconds lo.print_readable_snapshot(update=True) # Configure the local oscillator lo.ref_osc_source("int") # Use internal reference lo.frequency(4.7e9) lo.power(10) # Set the amplitude to 10 dBm lo.on() # Turn on the output .. seealso:: The raw serial commands can be found here: https://github.com/erainstruments/erasynth-docs/blob/master/erasynth-command-list.pdf ``self.visa_handle`` can be used to interact directly with the serial pyvisa communication. """
[docs] @staticmethod def print_pyvisa_resources() -> None: """Utility to list all.""" resource_manager = pyvisa.ResourceManager() print(resource_manager.list_resources())
def _prep_communication(self): """Makes sure the instrument config is compatible with this driver.""" self.debug_messages_en(False) # Print less messages to improve communication self.wifi_off() # print less messages to improve communication
[docs] def __init__(self, name: str, address: str, **kwargs): """ Create an instance of the instrument. Args: name: Instrument name. address: Used to connect to the instrument. Run :meth:`.ERASynthBase.print_pyvisa_resources` to list available list. """ super().__init__(name=name, address=address, terminator="\r\n", **kwargs) # ############################################################################## # Standard LO parameters # ############################################################################## # NB `initial_value` is not used because that would make the initialization slow self.status = Parameter( name="status", instrument=self, val_mapping={False: "0", True: "1"}, get_cmd="RA:rfoutput", set_cmd=self._set_status, ) """Sets the output state (`True`/`False`).""" self.power = Parameter( name="power", instrument=self, label="Power", unit="dBm", vals=validators.Numbers(min_value=-60.0, max_value=20.0), get_cmd="RA:amplitude", get_parser=float, set_parser=lambda power: f"{power:.2f}", set_cmd=self._set_power, ) """Signal power in dBm of the ERASynth signal, 'amplitude' in EraSynth docs.""" self.ref_osc_source = Parameter( name="ref_osc_source", instrument=self, val_mapping={"int": "0", "ext": "1"}, get_cmd=f"RA:{_CMD_TO_JSON_MAPPING['P1']}", set_cmd="P1{}", ) """ Set to external if a 10 MHz reference is connected to the REF input connector. """ # ############################################################################## # ERASynth specific parameters # ############################################################################## self.temperature = Parameter( name="temperature", instrument=self, label="Temperature", unit="\u00B0C", get_cmd="RD:temperature", ) """Temperature of the device.""" self.voltage = Parameter( name="voltage", instrument=self, label="Voltage", unit="V", get_cmd="RD:voltage", ) """The input voltage value from power input of the ERASynth.""" self.current = Parameter( name="current", instrument=self, label="Current", unit="V", get_cmd="RD:current", ) """The current value drawn by the ERASynth.""" self.embedded_version = Parameter( name="embedded_version", instrument=self, label="Embedded version", get_cmd="RD:em", ) """The firmware version of the ERASynth.""" self.wifi_rssi = Parameter( name="wifi_rssi", instrument=self, label="WiFi RSSI", get_cmd="RD:rssi", ) """The Wifi received signal power.""" self.pll_lmx1_status = Parameter( name="pll_lmx1_status", instrument=self, label="PLL LMX1 status", val_mapping={"locked": "1", "unlocked": "0"}, get_cmd="RD:lock_lmx1", ) """PLL lock status of LMX1.""" self.pll_lmx2_status = Parameter( name="pll_lmx2_status", instrument=self, label="PLL LMX2 status", val_mapping={"locked": "1", "unlocked": "0"}, get_cmd="RD:lock_lmx2", ) """PLL lock status of LMX2.""" self.pll_xtal_status = Parameter( name="pll_xtal_status", instrument=self, label="PLL XTAL status", val_mapping={"locked": "1", "unlocked": "0"}, get_cmd="RD:lock_xtal", ) """PLL lock status of XTAL.""" self.modulation_en = Parameter( name="modulation_en", instrument=self, val_mapping={False: "0", True: "1"}, get_cmd=f"RA:{_CMD_TO_JSON_MAPPING['MS']}", set_cmd="MS{}", ) """Modulation on/off.""" self.modulation_signal_waveform = Parameter( name="modulation_signal_waveform", instrument=self, val_mapping={"sine": "0", "triangle": "1", "ramp": "2", "square": "3"}, get_cmd=f"RA:{_CMD_TO_JSON_MAPPING['M2']}", set_cmd="M2{}", ) """Internal modulation waveform.""" self.modulation_source = Parameter( name="modulation_source", instrument=self, val_mapping={"internal": "0", "external": "1", "microphone": "2"}, get_cmd=f"RA:{_CMD_TO_JSON_MAPPING['M1']}", set_cmd="M1{}", ) """Modulation source.""" self.modulation_type = Parameter( name="modulation_type", instrument=self, val_mapping={ "narrowband_fm": "0", "wideband_fm": "1", "am": "2", "pulse": "3", }, get_cmd=f"RA:{_CMD_TO_JSON_MAPPING['M0']}", set_cmd="M0{}", ) """Modulation type.""" self.modulation_freq = Parameter( name="modulation_freq", instrument=self, label="Modulation frequency", unit="Hz", vals=validators.Numbers(min_value=0, max_value=20e9), get_cmd=f"RA:{_CMD_TO_JSON_MAPPING['M3']}", get_parser=int, set_cmd="M3{}", set_parser=lambda freq: str(int(freq)), ) """Internal modulation frequency in Hz.""" self.modulation_am_depth = Parameter( name="modulation_am_depth", instrument=self, label="AM depth", unit="%", vals=validators.Numbers(min_value=0, max_value=100), get_cmd=f"RA:{_CMD_TO_JSON_MAPPING['M5']}", get_parser=int, set_cmd="M5{}", set_parser=lambda depth: str(int(depth)), ) """AM modulation depth.""" self.modulation_fm_deviation = Parameter( name="modulation_fm_deviation", instrument=self, label="FM deviation", unit="Hz", vals=validators.Numbers(min_value=0, max_value=20e9), get_cmd=f"RA:{_CMD_TO_JSON_MAPPING['M4']}", get_parser=int, set_cmd="M4{}", set_parser=lambda freq: str(int(freq)), ) """FM modulation deviation.""" self.modulation_pulse_period = Parameter( name="modulation_pulse_period", instrument=self, label="Pulse period", unit="s", vals=validators.Numbers(min_value=1e-6, max_value=10), get_cmd=f"RA:{_CMD_TO_JSON_MAPPING['M6']}", get_parser=lambda val: int(val) * 1e-6, set_cmd="M6{}", set_parser=lambda period: str(int(period * 1e6)), ) """Pulse period in seconds.""" self.modulation_pulse_width = Parameter( name="modulation_pulse_width", instrument=self, label="Pulse width", unit="s", vals=validators.Numbers(min_value=1e-6, max_value=10), get_cmd=f"RA:{_CMD_TO_JSON_MAPPING['M7']}", get_parser=lambda val: int(val) * 1e-6, set_cmd="M7{}", set_parser=lambda period: str(int(period * 1e6)), ) """Pulse width in s.""" self.sweep_en = Parameter( name="sweep_en", instrument=self, val_mapping={False: "0", True: "1"}, get_cmd=f"RA:{_CMD_TO_JSON_MAPPING['SS']}", set_cmd="SS{}", ) """Sweep on/off.""" self.sweep_trigger = Parameter( name="sweep_trigger", instrument=self, val_mapping={"freerun": "0", "external": "1"}, get_cmd=f"RA:{_CMD_TO_JSON_MAPPING['S0']}", set_cmd="S0{}", ) """Sweep trigger freerun/external.""" self.sweep_dwell = Parameter( name="sweep_dwell", instrument=self, label="Sweep dwell", unit="s", vals=validators.Numbers(min_value=1e-3, max_value=10), get_cmd=f"RA:{_CMD_TO_JSON_MAPPING['S4']}", get_parser=lambda val: int(val) * 1e-3, set_cmd="S4{}", set_parser=lambda period: str(int(period * 1e3)), ) """Sweep dwell time in s. Requires sweep_trigger('freerun').""" self.synthesizer_mode = Parameter( name="synthesizer_mode", instrument=self, val_mapping={"low_spurious": "0", "low_phase_noise": "1"}, get_cmd=f"RA:{_CMD_TO_JSON_MAPPING['P9']}", set_cmd="P9{}", ) """Synthesizer mode, low spurious/low phase noise.""" # WiFi control, NB initial_cache_value is used to avoid overriding these values self.wifi_mode = Parameter( name="wifi_mode", instrument=self, val_mapping={"station": "0", "hotspot": "1", "": ""}, get_cmd=f"RA:{_CMD_TO_JSON_MAPPING['PEW']}", set_cmd="PEW{}", ) """WiFi Mode, station/hotspot.""" self.wifi_station_ssid = Parameter( name="wifi_station_ssid", instrument=self, vals=validators.Strings(), get_cmd=f"RA:{_CMD_TO_JSON_MAPPING['PES0']}", set_cmd="PES0{}", ) """Sets network SSID for WiFi module.""" self.wifi_station_password = Parameter( name="wifi_station_password", instrument=self, vals=validators.Strings(), get_cmd=f"RA:{_CMD_TO_JSON_MAPPING['PEP0']}", set_cmd="PEP0{}", ) """Sets network password for WiFi module.""" self.wifi_hotspot_ssid = Parameter( name="wifi_hotspot_ssid", instrument=self, vals=validators.Strings(), get_cmd=f"RA:{_CMD_TO_JSON_MAPPING['PES1']}", set_cmd="PES1{}", ) """Sets hotspot SSID for WiFi module.""" self.wifi_hotspot_password = Parameter( name="wifi_hotspot_password", instrument=self, vals=validators.Strings(), get_cmd=f"RA:{_CMD_TO_JSON_MAPPING['PEP1']}", set_cmd="PEP1{}", ) """Sets hotspot password for WiFi module.""" self.wifi_ip_address = Parameter( name="wifi_ip_address", instrument=self, vals=validators.Strings(), get_cmd=f"RA:{_CMD_TO_JSON_MAPPING['PEI']}", set_cmd="PEI{}", ) """Sets IP address for WiFi module.""" self.wifi_subnet_address = Parameter( name="wifi_subnet_address", instrument=self, vals=validators.Strings(), get_cmd=f"RA:{_CMD_TO_JSON_MAPPING['PEN']}", set_cmd="PEN{}", ) """Sets Subnet mask for WiFi module.""" self.wifi_gateway_address = Parameter( name="wifi_gateway_address", instrument=self, vals=validators.Strings(), get_cmd=f"RA:{_CMD_TO_JSON_MAPPING['PEG']}", set_cmd="PEG{}", ) """Sets default gateway for WiFi module.""" self.debug_messages_en = Parameter( name="debug_messages_en", instrument=self, vals=validators.Strings(), initial_cache_value=None, val_mapping={True: "1", False: "0"}, set_cmd="PD{}", ) """Enables/disables debug printing on the serial port.""" setattr(self.visa_handle, "baud_rate", BAUDRATE) self.timeout(10) # generous timeout to avoid disrupting measurements self.connect_message() self._prep_communication()
# ################################################################################## # Public methods # ################################################################################## # Standard LO methods
[docs] def on(self) -> None: """ Turns ON the RF output. """ self.status(True)
[docs] def off(self) -> None: """ Turns OFF the RF output. """ self.status(False)
# Custom communication
[docs] def get_idn(self) -> Dict[str, Optional[str]]: models = {"0": "ERASynth", "1": "ERASynth+", "2": "ERASynth++"} d_status = self.get_diagnostic_status() assert isinstance(d_status, Dict) return { "vendor": "ERA Instruments", "model": models[d_status["model"]], "serial": d_status["serial_number"], "firmware": d_status["em"], }
[docs] def clear_read_buffer(self) -> None: """ Clears the read buffer. The instrument often sends information we do not care about in this driver. This function discards the entire read buffer by reading it. """ bytes_in_buffer = lambda: getattr(self.visa_handle, "bytes_in_buffer") while bytes_in_buffer(): self.visa_handle.read_bytes(bytes_in_buffer())
[docs] def ask(self, cmd: str) -> str: """Writes a command to the communication channel of the instrument and return the response. Commands are prefixed with `">"` as required by the ERASynth. NB the read buffer is discarded before and after reading one line. """ self.clear_read_buffer() response = super().ask(f">{cmd}") self.clear_read_buffer() return response
[docs] def ask_raw(self, cmd: str) -> str: """ Detects special commands for which the `get_configuration` will be used. This makes it convenient to not implement individual getters for most commands. """ if cmd[1:].startswith("RA:"): response = self.get_configuration(cmd[1 + len("RA:") :]) elif cmd[1:].startswith("RD:"): response = self.get_diagnostic_status(cmd[1 + len("RD:") :]) else: response = super().ask_raw(cmd) assert isinstance(response, str) return response
[docs] def write(self, cmd: str) -> None: """Writes a command to the communication channel of the instrument. Commands are prefixed with `">"` as required by the ERASynth. NB the read buffer is discarded before and after reading one line. """ self.clear_read_buffer() super().write(f">{cmd}") self.clear_read_buffer()
[docs] def write_raw(self, cmd: str) -> None: """ For some commands we confirm that the value has been set correctly. This is only possible for configurations that can be retrieved from the instrument. """ is_readable_cmd = False for command in _CMD_TO_JSON_MAPPING: if cmd[1:].startswith(command): is_readable_cmd = True break if is_readable_cmd: json_key = _CMD_TO_JSON_MAPPING[command] cmd_arg = cmd[1 + len(command) :] while True: super().write_raw(cmd) self.clear_read_buffer() if self.get_configuration(json_key) == cmd_arg: break else: super().write_raw(cmd)
def _get_json(self, cmd: str, first_key: str) -> str: """ Sends command and reads result until the result looks like a JSON. """ timeout = 10 t_start = time.time() first_key = '{"' + first_key + '"' while True: read_line = self.ask(cmd) # Ensure the line contains the json if first_key in read_line and read_line[-1] == "}": break if time.time() > t_start + timeout: raise TimeoutError( f"Failed to query JSON within {timeout} s. " f"Command {cmd!r} failed." ) return "".join(["{", *read_line.split("{")[1:]]) # ERASynth specific methods
[docs] def get_configuration(self, par_name: Optional[str] = None) -> Union[Dict[str, str], str]: """ Returns the configuration JSON that contains all parameters. """ config_json = json.loads(self._get_json("RA", "rfoutput")) return config_json if par_name is None else config_json[par_name]
[docs] def get_diagnostic_status(self, par_name: Optional[str] = None) -> Union[Dict[str, str], str]: """ Returns the diagnostic JSON. """ config_json = json.loads(self._get_json("RD", "temperature")) return config_json if par_name is None else config_json[par_name]
[docs] def preset(self) -> None: """ Presets the device to known values. .. warning:: After the reset the output is set to power 0.0 dBm @ 1GHz! """ self.write("PP") self._prep_communication()
[docs] def factory_reset(self) -> None: """ Does factory reset on the device. """ self.write("PR") self._prep_communication()
[docs] def esp8266_upload_mode(self) -> None: """Sets the ESP8266 module in upload mode.""" self.write("U")
[docs] def wifi_on(self) -> None: """Turn ESP8266 WiFi module on.""" self.write("PE01")
[docs] def wifi_off(self) -> None: """Turn ESP8266 WiFi module off.""" self.write("PE00")
[docs] def run_self_test(self) -> None: """ Sets all settable parameters to different values. NB serves as self test of the instrument because setting readable parameters is done by setting and confirming the value. """ par_values = list(_SELF_TEST_LIST) if isinstance(self, (ERASynthPlus, ERASynthPlusPlus)): # Only ERASynth+ and ERASynth++ have this functionality par_values += [ ("reference_tcxo_ocxo", "tcxo"), ("reference_tcxo_ocxo", "ocxo"), ] num_tests = len(par_values) for i, (name, val) in enumerate(par_values): print(f"\r[{i+1:2d}/{num_tests}] Running...", end="") self.set(name, val) print("\nDone!")
# ################################################################################## # set commands # ################################################################################## def _set_and_confirm(self, cmd: str, cmd_arg: str, str_back: Optional[str] = None) -> None: """ Because for this command the instrument replies with a text containing the value, we make use of it to ensure we waited enough time for the changes to take effect. """ str_back = cmd_arg if str_back is None else str_back while True: read_line = self.ask(f"{cmd}{cmd_arg}") if str_back in read_line: break def _set_frequency(self, value: str) -> None: self._set_and_confirm(cmd="F", cmd_arg=value) def _set_power(self, value: str) -> None: self._set_and_confirm(cmd="A", cmd_arg=value) def _set_status(self, value: str) -> None: str_back = {"0": "OFF", "1": "ON"}[value] self._set_and_confirm(cmd="P0", cmd_arg=value, str_back=str_back)
def _mk_frequency(self, max_frequency: float) -> Parameter: frequency = Parameter( name="frequency", instrument=self, label="Frequency", unit="Hz", vals=validators.Numbers(min_value=250e3, max_value=max_frequency), get_cmd="RA:frequency", get_parser=int, set_cmd=self._set_frequency, set_parser=lambda freq: str(int(freq)), ) frequency.__doc__ = "The RF Frequency in Hz." return frequency def _mk_sweep_start_frequency(self, max_frequency: float) -> Parameter: sweep_start_frequency = Parameter( name="sweep_start_frequency", instrument=self, label="Sweep start", unit="Hz", vals=validators.Numbers(min_value=250e3, max_value=max_frequency), get_cmd=f"RA:{_CMD_TO_JSON_MAPPING['S1']}", get_parser=int, set_cmd="S1{}", set_parser=lambda freq: str(int(freq)), ) sweep_start_frequency.__doc__ = "Sweep start frequency in Hz." return sweep_start_frequency def _mk_sweep_stop_frequency(self, max_frequency: float) -> Parameter: sweep_stop_frequency = Parameter( name="sweep_stop_frequency", instrument=self, label="Sweep stop", unit="Hz", vals=validators.Numbers(min_value=250e3, max_value=max_frequency), get_cmd=f"RA:{_CMD_TO_JSON_MAPPING['S2']}", get_parser=int, set_cmd="S2{}", set_parser=lambda freq: str(int(freq)), ) sweep_stop_frequency.__doc__ = "Sweep stop frequency in Hz." return sweep_stop_frequency def _mk_sweep_step_frequency(self, max_frequency: float) -> Parameter: sweep_step_frequency = Parameter( name="sweep_step_frequency", instrument=self, label="Sweep step", unit="Hz", vals=validators.Numbers(min_value=0, max_value=max_frequency), get_cmd=f"RA:{_CMD_TO_JSON_MAPPING['S3']}", get_parser=int, set_cmd="S3{}", set_parser=lambda freq: str(int(freq)), ) sweep_step_frequency.__doc__ = "Sweep step frequency in Hz." return sweep_step_frequency
[docs] class ERASynth(ERASynthBase): """ Driver for the ERASynth model instrument. For ERASynth+/ERASynth++ see :class:`.EraSynthPlus`/:class:`.EraSynthPlusPlus` classes. """ def __init__(self, name: str, address: str, **kwargs): super().__init__(name=name, address=address, **kwargs) self.frequency = _mk_frequency(self, max_frequency=6e9) self.sweep_start_frequency = _mk_sweep_start_frequency(self, max_frequency=6e9) self.sweep_stop_frequency = _mk_sweep_stop_frequency(self, max_frequency=6e9) self.sweep_step_frequency = _mk_sweep_step_frequency( self, max_frequency=6e9 - 250e3 ) self.reference_tcxo_ocxo = Parameter( name="reference_tcxo_ocxo", instrument=self, val_mapping={"tcxo": "0", "ocxo": "1"}, get_cmd=f"RA:{_CMD_TO_JSON_MAPPING['P5']}", ) """ NB not tested if this parameter is available for the ERASynth model (<6GHz)! """
[docs] class ERASynthPlus(ERASynthBase): """ Driver for the ERASynth+ model instrument. For ERASynth/ERASynth++ see :class:`.EraSynth`/:class:`.EraSynthPlusPlus` classes. """ def __init__(self, name: str, address: str, **kwargs): super().__init__(name=name, address=address, **kwargs) self.frequency = _mk_frequency(self, max_frequency=15e9) self.sweep_start_frequency = _mk_sweep_start_frequency(self, max_frequency=15e9) self.sweep_stop_frequency = _mk_sweep_stop_frequency(self, max_frequency=15e9) self.sweep_step_frequency = _mk_sweep_step_frequency( self, max_frequency=15e9 - 250e3 ) self.reference_tcxo_ocxo = Parameter( name="reference_tcxo_ocxo", instrument=self, val_mapping={"tcxo": "0", "ocxo": "1"}, get_cmd=f"RA:{_CMD_TO_JSON_MAPPING['P5']}", set_cmd="P5{}", ) """Chooses reference type."""
[docs] class ERASynthPlusPlus(ERASynthBase): """ Driver for the ERASynth++ model instrument. For ERASynth/ERASynth+ see :class:`.EraSynth`/:class:`.EraSynthPlus` classes. """ def __init__(self, name: str, address: str, **kwargs): super().__init__(name=name, address=address, **kwargs) self.frequency = _mk_frequency(self, max_frequency=20e9) self.sweep_start_frequency = _mk_sweep_start_frequency(self, max_frequency=20e9) self.sweep_stop_frequency = _mk_sweep_stop_frequency(self, max_frequency=20e9) self.sweep_step_frequency = _mk_sweep_step_frequency( self, max_frequency=20e9 - 250e3 ) self.reference_tcxo_ocxo = Parameter( name="reference_tcxo_ocxo", instrument=self, val_mapping={"tcxo": "0", "ocxo": "1"}, get_cmd=f"RA:{_CMD_TO_JSON_MAPPING['P5']}", set_cmd="P5{}", ) """Chooses reference type."""
_SELF_TEST_LIST: List[Tuple[str, Union[bool, float, int, str]]] = [ ("frequency", 3.3e9), ("modulation_am_depth", 30), ("modulation_fm_deviation", 1e3), ("modulation_freq", 2e3), ("modulation_pulse_period", 0.003), ("modulation_pulse_width", 0.002), ("power", 0.01), ("power", -0.01), ("sweep_dwell", 0.001), ("sweep_start_frequency", 2e9), ("sweep_step_frequency", 0.5e9), ("sweep_stop_frequency", 6e9), ("status", True), ("status", False), ("modulation_en", True), ("modulation_en", False), ("modulation_signal_waveform", "triangle"), ("modulation_signal_waveform", "ramp"), ("modulation_signal_waveform", "square"), ("modulation_signal_waveform", "sine"), ("modulation_source", "internal"), ("modulation_source", "external"), ("modulation_source", "microphone"), ("modulation_type", "narrowband_fm"), ("modulation_type", "am"), ("modulation_type", "pulse"), ("modulation_type", "wideband_fm"), ("ref_osc_source", "ext"), ("ref_osc_source", "int"), ("synthesizer_mode", "low_phase_noise"), ("synthesizer_mode", "low_spurious"), ("sweep_en", True), ("sweep_en", False), ("sweep_trigger", "freerun"), ("sweep_trigger", "external"), ("wifi_mode", "hotspot"), ("wifi_mode", "station"), ("wifi_station_ssid", "ERA_123"), ("wifi_station_ssid", "ERA"), ("wifi_station_password", "era1234"), ("wifi_station_password", "era19050"), ("wifi_hotspot_ssid", "ERA"), ("wifi_hotspot_ssid", "ERASynth"), ("wifi_hotspot_password", "erainstruments+"), ("wifi_hotspot_password", "erainstruments"), ("wifi_ip_address", "192.168.001.151"), ("wifi_ip_address", "192.168.001.150"), ("wifi_gateway_address", "192.168.001.002"), ("wifi_gateway_address", "192.168.001.001"), ("wifi_subnet_address", "255.255.255.001"), ("wifi_subnet_address", "255.255.255.000"), ] """ A list of `Tuple[<parameter_name, value>]` used for a self-test of the instrument. It is intended to check that read/write parameters are set correctly. """