Source code for command

# Lucas J. Koerner
# 05/2018
# koerner.lucas@stthomas.edu
# University of St. Thomas

# standard library imports
import re

[docs]class Command(object): """ A command to be sent to an instrument .. todo:: * Add a switch to enable or disable the lookup table * defaults for long getters and setters * long getters/setters: need range requirements and names for 2nd and beyond getter inputs Parameters ---------- name : string The name of the command, used as lookup key to the instrument's dictionary of commands ascii_str : string What is sent to the instrument. ascii_str_get : string, optional What is sent to the instrument when getting a value. If not specified 'ascii_str' will be used. getter : Boolean Is this command a getter? getter_type : function, float Converts the instrument returned value to a new type for processing. Example: float setter : Boolean Is this command a setter? limits : list Minimum and maximum allowed values for the set operation. setter_type : function, float Currently not used; may be used to check if set value is the proper type doc : string, optional Documentation for this command; will be printed with help. subsystem : string, optional The subsystem (of the instrument) that this command fits into Used for organization help information. getter_inputs : list (of strings), optional For non-conventional get functions (long getters) that send extra parameters. This is a list of the input parameters that are needed. These are keys to the config dictionary. setter_inputs : list (of strings), optional For non-conventional set functions (long setters) that send extra parameters (beyond 'value'). This is a list of the input parameters that are needed. These are keys to the config dictionary. lookup : dictionary, optional A lookup table for values that can be mapped to more human-readable results. E.g. lookup = `{'SLOW': 0, 'FAST': 1}` The keys are the human-readable names, the dictionary values are what is sent and received from the instrument. is_config : bool, optional is a "configuration" variable that should be measured and logged at the start and end of an experiment. getter_override : function, optional run this upon get setter_override: function runs this upon set returns_image: bool, optional (defaults to False) does this command return an array or image (a value that cannot be stored in the NoSQL database) """ def __init__(self, name, ascii_str='', ascii_str_get='', getter=True, getter_type=float, setter=True, limits=None, setter_type=float, doc='', subsystem=None, getter_inputs=None, setter_inputs=None, lookup={}, is_config=False, getter_override=None, setter_override=None, returns_image=False): self.name = name ascii_str = ascii_str.rstrip() if ascii_str.find('{value}') == -1: # command that is sent over scpi self.ascii_str = ascii_str + ' {value}' else: self.ascii_str = ascii_str if ascii_str_get is None: # for most cases replace the value with ? self.ascii_str_get = self.ascii_str.replace(' {value}', '?') else: self.ascii_str_get = ascii_str_get # put the get command configuration keys into a list self.get_config_keys = re.findall(r'{\s*(.*?)\s*}', self.ascii_str_get) self.set_config_keys = re.findall(r'{\s*(.*?)\s*}', self.ascii_str) # value is special, not a configuration key; it is always required input to setter # (value must be set to None if a "setter" that does not send a value is needed) self.set_config_keys.remove('value') self.get_config_defaults = dict.fromkeys(self.get_config_keys) self.set_config_defaults = dict.fromkeys(self.set_config_keys) self.getter = getter # is this a getter? True or False # getter_type: a function that converts the value retrieved to the anticipated type, # typically a built-in like float, int, etc. but could be a custom function self.getter_type = getter_type self.setter = setter # is this a setter? True or False self.setter_type = setter_type # TODO: checks that the value matches this type # lookup table support (dictionary) self.lookup = lookup # we want to store the acceptable range as the value -- if its lookups convert it if limits is not None: if limits[0] in lookup: for idx, s in enumerate(limits): limits[idx] = lookup[s] self.limits = limits self.doc = doc self.subsystem = subsystem self.getter_inputs = getter_inputs self.setter_inputs = setter_inputs self.is_config = is_config self.getter_override = getter_override self.setter_override = setter_override self.returns_image = returns_image
[docs]class Register(object): """ A register of an integrated circuit to read or set The register is an address value pair and can be R or R/W todo: handle values that are sub-registers or expand over multiple registers (might be another class) Parameters ---------- name : string The name of the register, used as lookup key to the dictionary of registers address : int address value read_write : string 'R' 'R/W', 'W' is_config : boolean if True the register should have a constant value once written if False the chip may update the register (e.g. by ADC readings) and the value could change """ def __init__(self, name, address, read_write='R/W', is_config=True): self.name = name self.address = address self.read_write = read_write self.is_config = is_config self.lookup = {} self.doc = '' self.returns_image = False