Source code for qcodes.instrument_drivers.Keysight.KtM960x

import ctypes
from functools import partial
from typing import TYPE_CHECKING

import qcodes.validators as vals
from qcodes.instrument import Instrument, InstrumentBaseKWArgs
from qcodes.parameters import (
    MultiParameter,
    Parameter,
    ParamRawDataType,
    create_on_off_val_mapping,
)

from .KtM960xDefs import *  # noqa F403

if TYPE_CHECKING:
    from typing_extensions import Unpack


class Measure(MultiParameter):
    def __init__(self, name: str, instrument: "KeysightM960x") -> None:
        super().__init__(
            name=name,
            names=("voltage", "current", "resistance", "status", "timestamp", "source"),
            shapes=((), (), (), (), (), ()),
            units=("V", "A", "Ohm", "", "", ""),
            instrument=instrument,
            labels="Measurement Data",
            docstring="param that returns measurement values",
        )
        self.instrument: KeysightM960x

    def get_raw(self) -> tuple[ParamRawDataType, ...]:
        return self.instrument._measure()


[docs] class KeysightM960x(Instrument): """ Provide a wrapper for the Keysight KtM960x DAC. This driver provides an interface into the IVI-C driver provided by Keysight. The .dll is installed by default into C:\\Program Files\\IVI Foundation\\IVI\\Bin\\KtM960x_64.dll but a different path can be supplied to the constructor """ _default_buf_size = 256 def __init__( self, name: str, address: str, options: str = "", dll_path: str = r"C:\Program Files\IVI Foundation\IVI\Bin\KtM960x_64.dll", **kwargs: "Unpack[InstrumentBaseKWArgs]", ) -> None: super().__init__(name, **kwargs) self._address = bytes(address, "ascii") self._options = bytes(options, "ascii") self._session = ctypes.c_int(0) self._dll_loc = dll_path self._dll = ctypes.cdll.LoadLibrary(self._dll_loc) self.output: Parameter = self.add_parameter( "output", label="Source Output Enable", get_cmd=partial(self._get_vi_bool, KTM960X_ATTR_OUTPUT_ENABLED), set_cmd=partial(self._set_vi_bool, KTM960X_ATTR_OUTPUT_ENABLED), val_mapping=create_on_off_val_mapping(on_val=True, off_val=False), ) """Parameter output""" self.voltage_level: Parameter = self.add_parameter( "voltage_level", label="Source Voltage Level", unit="Volt", get_cmd=partial(self._get_vi_real64, KTM960X_ATTR_OUTPUT_VOLTAGE_LEVEL), set_cmd=partial(self._set_vi_real64, KTM960X_ATTR_OUTPUT_VOLTAGE_LEVEL), vals=vals.Numbers(-210, 210), ) """Parameter voltage_level""" self.current_range: Parameter = self.add_parameter( "current_range", label="Output Current Range", unit="Amp", vals=vals.Numbers(1e-9, 300e-3), get_cmd=partial(self._get_vi_real64, KTM960X_ATTR_OUTPUT_CURRENT_RANGE), set_cmd=partial(self._set_vi_real64, KTM960X_ATTR_OUTPUT_CURRENT_RANGE), ) """Parameter current_range""" self.measure_current_range: Parameter = self.add_parameter( "measure_current_range", label="Current Measurement Range", unit="Amp", get_cmd=partial( self._get_vi_real64, KTM960X_ATTR_MEASUREMENT_CURRENT_RANGE ), set_cmd=partial( self._set_vi_real64, KTM960X_ATTR_MEASUREMENT_CURRENT_RANGE ), vals=vals.Numbers(1e-9, 300e-3), ) """Parameter measure_current_range""" self.measure_current_time: Parameter = self.add_parameter( "measure_current_time", label="Current Measurement Integration Time", unit="Seconds", get_cmd=partial( self._get_vi_real64, KTM960X_ATTR_MEASUREMENT_CURRENT_APERTURE ), set_cmd=partial( self._set_vi_real64, KTM960X_ATTR_MEASUREMENT_CURRENT_APERTURE ), vals=vals.Numbers(800e-9, 2), ) """Parameter measure_current_time""" self.measure_data: Measure = self.add_parameter( "measure_data", parameter_class=Measure ) """Parameter measure_data""" self._get_driver_desc = partial( self._get_vi_string, KTM960X_ATTR_SPECIFIC_DRIVER_DESCRIPTION ) self._get_driver_prefix = partial( self._get_vi_string, KTM960X_ATTR_SPECIFIC_DRIVER_PREFIX ) self._get_driver_revision = partial( self._get_vi_string, KTM960X_ATTR_SPECIFIC_DRIVER_REVISION ) self._get_firmware_revision = partial( self._get_vi_string, KTM960X_ATTR_INSTRUMENT_FIRMWARE_REVISION ) self._get_model = partial(self._get_vi_string, KTM960X_ATTR_INSTRUMENT_MODEL) self._get_serial_number = partial( self._get_vi_string, KTM960X_ATTR_MODULE_SERIAL_NUMBER ) self._get_manufacturer = partial( self._get_vi_string, KTM960X_ATTR_INSTRUMENT_MANUFACTURER ) self._connect() self.connect_message() def _connect(self) -> None: status = self._dll.KtM960x_InitWithOptions( self._address, 1, 1, self._options, ctypes.byref(self._session) ) if status: raise SystemError(f"connection to device failed! error: {status}")
[docs] def get_idn(self) -> dict[str, str | None]: """Generates the ``*IDN`` dictionary for qcodes""" id_dict: dict[str, str | None] = { "firmware": self._get_firmware_revision(), "model": self._get_model(), "serial": self._get_serial_number(), "vendor": self._get_manufacturer(), "driver desc": self._get_driver_desc(), "driver prefix": self._get_driver_prefix(), "driver revision": self._get_driver_revision(), } return id_dict
def _measure(self) -> tuple[ParamRawDataType, ...]: # Setup the output self._set_vi_int( KTM960X_ATTR_OUTPUT_PRIORITY_MODE, KTM960X_VAL_PRIORITY_MODE_VOLTAGE ) self._set_vi_int( KTM960X_ATTR_OUTPUT_OPERATION_MODE, KTM960X_VAL_OUTPUT_OPERATION_MODE_STANDARD, ) self._set_vi_int( KTM960X_ATTR_MEASUREMENT_ACQUISITION_MODE, KTM960X_VAL_ACQUISITION_MODE_NORMAL, ) ch_num_buf = (ctypes.c_int32 * 1)() val_buf = (ctypes.c_double * 1024)() actual_size = ctypes.c_int32(0) ch_num_buf[0] = 1 status = self._dll.KtM960x_MeasurementMeasure( self._session, KTM960X_VAL_MEASUREMENT_TYPE_ALL, 1, ch_num_buf, 1024, val_buf, ctypes.byref(actual_size), ) if status: raise ValueError(f"Driver error: {status}") # This might be a bit slow? # Returned as [voltage, current, resistance, status, # timestamp, and source] v = list(val_buf)[0 : actual_size.value] # 'voltage': v[0], 'current': v[1], 'resistance': v[2], 'status': v[3], # 'timestamp': v[4], 'source': v[5] return v[0], v[1], v[2], v[3], v[4], v[5] # Query the driver for errors
[docs] def get_errors(self) -> dict[int, str]: error_code = ctypes.c_int(-1) error_message = ctypes.create_string_buffer(256) error_dict = dict() while error_code.value != 0: status = self._dll.KtM960x_error_query( self._session, ctypes.byref(error_code), error_message ) assert status == 0 error_dict[error_code.value] = error_message.value.decode("utf-8") return error_dict
# Generic functions for reading/writing different attributes def _get_vi_string(self, attr: int) -> str: s = ctypes.create_string_buffer(self._default_buf_size) status = self._dll.KtM960x_GetAttributeViString( self._session, b"", attr, self._default_buf_size, s ) if status: raise ValueError(f"Driver error: {status}") return s.value.decode("utf-8") def _get_vi_bool(self, attr: int) -> bool: s = ctypes.c_uint16(0) status = self._dll.KtM960x_GetAttributeViBoolean( self._session, b"", attr, ctypes.byref(s) ) if status: raise ValueError(f"Driver error: {status}") return bool(s) def _set_vi_bool(self, attr: int, value: bool) -> None: v = ctypes.c_uint16(1) if value else ctypes.c_uint16(0) status = self._dll.KtM960x_SetAttributeViBoolean(self._session, b"", attr, v) if status: raise ValueError(f"Driver error: {status}") def _get_vi_real64(self, attr: int) -> float: s = ctypes.c_double(0) status = self._dll.KtM960x_GetAttributeViReal64( self._session, b"", attr, ctypes.byref(s) ) if status: raise ValueError(f"Driver error: {status}") return float(s.value) def _set_vi_real64(self, attr: int, value: float) -> None: v = ctypes.c_double(value) status = self._dll.KtM960x_SetAttributeViReal64(self._session, b"", attr, v) if status: raise ValueError(f"Driver error: {status}") def _set_vi_int(self, attr: int, value: int) -> None: v = ctypes.c_int32(value) status = self._dll.KtM960x_SetAttributeViInt32(self._session, b"", attr, v) if status: raise ValueError(f"Driver error: {status}") def _get_vi_int(self, attr: int) -> int: v = ctypes.c_int32(0) status = self._dll.KtM960x_GetAttributeViInt32( self._session, b"", attr, ctypes.byref(v) ) if status: raise ValueError(f"Driver error: {status}") return int(v.value)
[docs] def close(self) -> None: self._dll.KtM960x_close(self._session) super().close()
KtM960x = KeysightM960x "Alias for backwards compatibility"