Source code for qcodes_contrib_drivers.drivers.Keysight.SD_common.SD_Module

import warnings
import os
from typing import Any, Callable, Dict, List, Optional, Union
from qcodes.instrument.base import Instrument

try:
    import keysightSD1
except ImportError:
    raise ImportError('to use the Keysight SD drivers install the keysightSD1 module '
                      '(http://www.keysight.com/main/software.jspx?ckey=2784055)')

# check whether SD1 version 2.x or 3.x
is_sd1_3x = 'SD_SandBoxRegister' in dir(keysightSD1)


[docs] def result_parser(value: Any, name: str = 'result', verbose: bool = False) -> Any: """ This method is used for parsing the result in the get-methods. For values that are non-negative, the value is simply returned. Negative values indicate an error, so an error is raised with a reference to the error code. The parser also can print to the result to the shell if verbose is 1. Args: value: the value to be parsed name: name of the value to be parsed verbose: boolean indicating verbose mode Returns: parsed value, which is the same as value if non-negative or not a number """ if isinstance(value, int) and (int(value) < 0): error_message = keysightSD1.SD_Error.getErrorMessage(value) call_message = f' ({name})' if name != 'result' else '' raise Exception(f'Error in call to module ({value}): ' f'{error_message}{call_message}') else: if verbose: print(f'{name}: {value}') return value
[docs] class SD_Module(Instrument): """ This is the general SD_Module driver class that implements shared parameters and functionality among all PXIe-based digitizer/awg/combo cards by Keysight. This driver was written to be inherited from by either the SD_AWG, SD_DIG or SD_Combo class, depending on the functionality of the card. Specifically, this driver was written with the M3201A and M3300A cards in mind. This driver makes use of the Python library provided by Keysight as part of the SD1 Software package (v.2.01.00). Args: name: an identifier for this instrument, particularly for attaching it to a Station. chassis: identification of the chassis. slot: slot of the module in the chassis. """ def __init__(self, name: str, chassis: int, slot: int, module_class: Callable = keysightSD1.SD_Module, **kwargs) -> None: super().__init__(name, **kwargs) # Create instance of keysight module class self.SD_module = module_class() # Open the device, using the specified chassis and slot number self.module_name = self.SD_module.getProductNameBySlot(chassis, slot) result_parser(self.module_name, f'getProductNameBySlot({chassis}, {slot})') result_code = self.SD_module.openWithSlot(self.module_name, chassis, slot) result_parser(result_code, f'openWithSlot({self.module_name}, {chassis}, {slot})') self.add_parameter('module_count', label='module count', get_cmd=self.get_module_count, docstring='The number of Keysight modules ' 'installed in the system') self.add_parameter('product_name', label='product name', get_cmd=self.get_product_name, docstring='The product name of the device') self.add_parameter('serial_number', label='serial number', get_cmd=self.get_serial_number, docstring='The serial number of the device') self.add_parameter('chassis_number', label='chassis number', get_cmd=self.get_chassis, docstring='The chassis number where the device is ' 'located') self.add_parameter('slot_number', label='slot number', get_cmd=self.get_slot, docstring='The slot number where the device is ' 'located') self.add_parameter('status', label='status', get_cmd=self.get_status, docstring='The status of the device') self.add_parameter('firmware_version', label='firmware version', get_cmd=self.get_firmware_version, docstring='The firmware version of the device') self.add_parameter('hardware_version', label='hardware version', get_cmd=self.get_hardware_version, docstring='The hardware version of the device') self.add_parameter('instrument_type', label='type', get_cmd=self.get_type, docstring='The type of the device') self.add_parameter('open', label='open', get_cmd=self.get_open, docstring='Indicating if device is open, ' 'True (open) or False (closed)') self.add_parameter('temperature', label='temperature', get_cmd=self.get_temperature, docstring='Module temperature') # # Get-commands #
[docs] def get_idn(self) -> Dict[str, Optional[str]]: """Returns IDN of module""" return dict(vendor='Keysight', model=self.get_product_name(), serial=self.get_serial_number(), firmware=self.get_firmware_version(), )
[docs] def get_module_count(self, verbose: bool = False) -> int: """Returns the number of SD modules installed in the system""" value = self.SD_module.moduleCount() value_name = 'module_count' return result_parser(value, value_name, verbose)
[docs] def get_product_name(self, verbose: bool = False) -> str: """Returns the product name of the device""" value = self.SD_module.getProductName() value_name = 'product_name' return result_parser(value, value_name, verbose)
[docs] def get_serial_number(self, verbose: bool = False) -> str: """Returns the serial number of the device""" value = self.SD_module.getSerialNumber() value_name = 'serial_number' return result_parser(value, value_name, verbose)
[docs] def get_chassis(self, verbose: bool = False) -> int: """Returns the chassis number where the device is located""" value = self.SD_module.getChassis() value_name = 'chassis_number' return result_parser(value, value_name, verbose)
[docs] def get_slot(self, verbose: bool = False) -> int: """Returns the slot number where the device is located""" value = self.SD_module.getSlot() value_name = 'slot_number' return result_parser(value, value_name, verbose)
[docs] def get_status(self, verbose: bool = False) -> int: """Returns the status of the device""" value = self.SD_module.getStatus() value_name = 'status' return result_parser(value, value_name, verbose)
[docs] def get_firmware_version(self, verbose: bool = False) -> str: """Returns the firmware version of the device""" value = self.SD_module.getFirmwareVersion() value_name = 'firmware_version' return result_parser(value, value_name, verbose)
[docs] def get_hardware_version(self, verbose: bool = False) -> str: """Returns the hardware version of the device""" value = self.SD_module.getHardwareVersion() value_name = 'hardware_version' return result_parser(value, value_name, verbose)
[docs] def get_type(self, verbose: bool = False) -> int: """Returns the type of the device""" value = self.SD_module.getType() value_name = 'type' return result_parser(value, value_name, verbose)
[docs] def get_open(self, verbose: bool = False) -> bool: """Returns whether the device is open (True) or not (False)""" value = self.SD_module.isOpen() value_name = 'open' return result_parser(value, value_name, verbose)
[docs] def get_pxi_trigger(self, pxi_trigger: int, verbose: bool = False) -> int: """ Returns the digital value of the specified PXI trigger Args: pxi_trigger: PXI trigger number (4000 + Trigger No.) verbose: boolean indicating verbose mode Returns: Digital value with negated logic, 0 (ON) or 1 (OFF), or negative numbers for errors """ value = self.SD_module.PXItriggerRead(pxi_trigger) value_name = f'pxi_trigger number {pxi_trigger}' return result_parser(value, value_name, verbose)
# # Set-commands #
[docs] def set_pxi_trigger(self, value: int, pxi_trigger: int, verbose: bool = False) -> None: """ Sets the digital value of the specified PXI trigger Args: pxi_trigger: PXI trigger number (4000 + Trigger No.) value: Digital value with negated logic, 0 (ON) or 1 (OFF) verbose: boolean indicating verbose mode """ result = self.SD_module.PXItriggerWrite(pxi_trigger, value) value_name = f'set pxi_trigger {pxi_trigger} to {value}' result_parser(result, value_name, verbose)
# # FPGA related functions #
[docs] def get_fpga_pc_port(self, port: int, data_size: int, address: int, address_mode: int, access_mode: int, verbose: bool = False) -> Any: """ Reads data at the PCport FPGA Block Args: port: PCport number data_size: number of 32-bit words to read (maximum is 128 words) address: address that wil appear at the PCport interface address_mode: auto-increment (0), or fixed (1) access_mode: non-dma (0), or dma (1) verbose: boolean indicating verbose mode Returns: register data. """ data = self.SD_module.FPGAreadPCport(port, data_size, address, address_mode, access_mode) value_name = f'data at PCport {port}' return result_parser(data, value_name, verbose)
[docs] def set_fpga_pc_port(self, port: int, data: List[int], address: int, address_mode: int, access_mode: int, verbose: bool = False) -> None: """ Writes data at the PCport FPGA Block Args: port: PCport number data: array of integers containing the data address: address that will appear at the PCport interface address_mode: auto-increment (0), or fixed (1) access_mode: non-dma (0), or dma (1) verbose: boolean indicating verbose mode """ result = self.SD_module.FPGAwritePCport(port, data, address, address_mode, access_mode) value_name = f'set fpga PCport {port} to data:{data}, ' \ f'address:{address}, address_mode:{address_mode}, ' \ f'access_mode:{access_mode}' result_parser(result, value_name, verbose)
[docs] def load_fpga_image(self, filename: str) -> None: """ Loads FPGA binary image in module. Args: filename: name of the FPGA image. """ if not os.path.exists(filename): raise Exception(f'FPGA bitstream {filename} not found') result_parser(self.SD_module.FPGAload(filename), f'loading FPGA bitstream: {filename}')
# # HVI related functions #
[docs] def set_hvi_register(self, register: Union[int, str], value: int, verbose: bool = False) -> None: """ Sets value of specified HVI register. Args: register: register to set. value: new value. verbose: boolean indicating verbose mode """ if type(register) == int: result = self.SD_module.writeRegisterByNumber(register, value) else: result = self.SD_module.writeRegisterByName(register, value) value_name = f'set HVI register {register}:{value}' result_parser(result, value_name, verbose)
[docs] def get_hvi_register(self, register: Union[int, str], verbose: bool = False) -> int: """ Returns value of specified HVI register. Args: register: register to read. verbose: boolean indicating verbose mode Returns: register value. """ if type(register) == int: error, result = self.SD_module.readRegisterByNumber(register) else: error, result = self.SD_module.readRegisterByName(register) value_name = f'get HVI register {register}' result_parser(error, value_name, verbose) return result
# # The methods below are not used for setting or getting parameters, # but can be used in the test functions of the test suite e.g. The main # reason they are defined is to make this driver more complete #
[docs] def get_product_name_by_slot(self, chassis: int, slot: int, verbose: bool = False) -> str: value = self.SD_module.getProductNameBySlot(chassis, slot) value_name = 'product_name' return result_parser(value, value_name, verbose)
[docs] def get_product_name_by_index(self, index: Any, verbose: bool = False) -> str: value = self.SD_module.getProductNameByIndex(index) value_name = 'product_name' return result_parser(value, value_name, verbose)
[docs] def get_serial_number_by_slot(self, chassis: int, slot: int, verbose: bool = False) -> str: warnings.warn('Returns faulty serial number due to error in Keysight ' 'lib v.2.01.00', UserWarning) value = self.SD_module.getSerialNumberBySlot(chassis, slot) value_name = 'serial_number' return result_parser(value, value_name, verbose)
[docs] def get_serial_number_by_index(self, index: Any, verbose: bool = False) -> str: warnings.warn('Returns faulty serial number due to error in Keysight ' 'lib v.2.01.00', UserWarning) value = self.SD_module.getSerialNumberByIndex(index) value_name = 'serial_number' return result_parser(value, value_name, verbose)
[docs] def get_type_by_slot(self, chassis: int, slot: int, verbose: bool = False) -> int: value = self.SD_module.getTypeBySlot(chassis, slot) value_name = 'type' return result_parser(value, value_name, verbose)
[docs] def get_type_by_index(self, index: Any, verbose: bool = False) -> int: value = self.SD_module.getTypeByIndex(index) value_name = 'type' return result_parser(value, value_name, verbose)
[docs] def get_temperature(self) -> float: return self.SD_module.getTemperature()
# # The methods below are useful for controlling the device, but are not # used for setting or getting parameters #
[docs] def close(self) -> None: """ Closes the hardware device and frees resources. If you want to open the instrument again, you have to initialize a new instrument object """ # Note: module keeps track of open/close state. So, keep the reference. self.SD_module.close() super().close()
# only closes the hardware device, does not delete the current instrument # object
[docs] def close_soft(self) -> None: self.SD_module.close()
[docs] def open_with_serial_number(self, name: str, serial_number: int) -> Any: result = self.SD_module.openWithSerialNumber(name, serial_number) return result_parser(result, f'openWithSerialNumber({name}, {serial_number})')
[docs] def open_with_slot(self, name: str, chassis: int, slot: int) -> Any: result = self.SD_module.openWithSlot(name, chassis, slot) return result_parser(result, f'openWithSlot({name}, {chassis}, {slot})')
[docs] def run_self_test(self) -> int: value = self.SD_module.runSelfTest() print(f'Did self test and got result: {value}') return value