Skip to content

Commit

Permalink
Merge pull request #3 from nulinspiratie/feature/signadyne_driver_cla…
Browse files Browse the repository at this point in the history
…ssification

Feature/signadyne driver classification
  • Loading branch information
maij authored Mar 15, 2017
2 parents a8bcc0d + ad86f2b commit ef0daf0
Show file tree
Hide file tree
Showing 8 changed files with 349 additions and 251 deletions.
19 changes: 19 additions & 0 deletions qcodes/instrument_drivers/keysight/M3201A.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# from qcodes import validators as validator
# from functools import partial
#
# from .SD_common.SD_Module import *
from .SD_common.SD_AWG import *


class Keysight_M3201A(SD_AWG):
"""
This is the qcodes driver for the Keysight M3201A AWG PXIe card
Args:
name (str): name for this instrument, passed to the base instrument
chassis (int): chassis number where the device is located
slot (int): slot number where the device is plugged in
"""

def __init__(self, name, chassis=1, slot=7, **kwargs):
super().__init__(name, chassis, slot, channels=4, triggers=8, **kwargs)
Original file line number Diff line number Diff line change
@@ -1,114 +1,45 @@
from qcodes.instrument.base import Instrument
from qcodes import validators as validator
from functools import partial
try:
import signadyne
except ImportError:
raise ImportError('to use the M32 driver install the signadyne module')

from .SD_Module import *

def result_parser(value, name, verbose=False):
"""
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 (str): name of the value to be parsed
verbose (bool): boolean indicating verbose mode
Returns:
value: parsed value, which is the same as value if non-negative
or not a number
class SD_AWG(SD_Module):
"""
if isinstance(value, str) or isinstance(value, bool) or (int(value) >= 0):
if verbose:
print('{}: {}' .format(name, value))
return value
else:
raise Exception('Error in call to Signadyne AWG '
'error code {}'.format(value))
This is the general SD_AWG driver class that implements shared parameters and functionality among all PXIe-based
AWG cards by Keysight. (series M32xxA and M33xxA)
This driver was written to be inherited from by a specific AWG card driver (e.g. M3201A).
class Signadyne_M3201A(Instrument):
"""
This is the qcodes driver for the Signadyne M32/M33xx series of function/arbitrary waveform generators
This driver was written with the M3201A card in mind.
status: beta-version
This driver is written with the M3201A in mind.
Updates might/will be necessary for other versions of Signadyne cards.
Args:
name (str): name for this instrument, passed to the base instrument
chassis (int): chassis number where the device is located
slot (int): slot number where the device is plugged in
This driver makes use of the Python library provided by Keysight as part of the SD1 Software package (v.2.01.00).
"""

def __init__(self, name, chassis=1, slot=7, **kwargs):
super().__init__(name, **kwargs)
def __init__(self, name, chassis, slot, channels, triggers, **kwargs):
super().__init__(name, chassis, slot, **kwargs)

# Create instance of keysight SD_AOU class
self.awg = keysightSD1.SD_AOU()

# Create instance of signadyne SD_AOU class
self.awg = signadyne.SD_AOU()
# Create an instance of keysight SD_Wave class
self.wave = keysightSD1.SD_Wave()

# Create an instance of signadyne SD_Wave class
self.wave = signadyne.SD_Wave()
# store card-specifics
self.channels = channels
self.triggers = triggers

# Open the device, using the specified chassis and slot number
awg_name = self.awg.getProductNameBySlot(chassis, slot)
if isinstance(awg_name, str):
result_code = self.awg.openWithSlot(awg_name, chassis, slot)
if result_code <= 0:
raise Exception('Could not open Signadyne AWG '
raise Exception('Could not open SD_AWG '
'error code {}'.format(result_code))
else:
raise Exception('Signadyne AWG not found at '
raise Exception('No SD_AWG found at '
'chassis {}, slot {}'.format(chassis, slot))

self.add_parameter('module_count',
label='module count',
get_cmd=self.get_module_count,
docstring='The number of Signadyne 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('trigger_io',
label='trigger io',
get_cmd=self.get_trigger_io,
Expand All @@ -128,15 +59,15 @@ def __init__(self, name, chassis=1, slot=7, **kwargs):
get_cmd=self.get_clock_sync_frequency,
docstring='The frequency of the internal CLKsync in Hz')

for i in [0, 1, 2, 3, 4, 5, 6, 7]:
for i in range(triggers):
self.add_parameter('pxi_trigger_number_{}'.format(i),
label='pxi trigger number {}'.format(i),
get_cmd=partial(self.get_pxi_trigger, pxi_trigger=(4000 + i)),
set_cmd=partial(self.set_pxi_trigger, pxi_trigger=(4000 + i)),
docstring='The digital value of pxi trigger no. {}, 0 (ON) of 1 (OFF)'.format(i),
vals=validator.Enum(0, 1))

for i in [0, 1, 2, 3]:
for i in range(channels):
self.add_parameter('frequency_channel_{}'.format(i),
label='frequency channel {}'.format(i),
unit='Hz',
Expand Down Expand Up @@ -166,72 +97,12 @@ def __init__(self, name, chassis=1, slot=7, **kwargs):
label='wave shape channel {}'.format(i),
set_cmd=partial(self.set_channel_wave_shape, channel_number=i),
docstring='The output waveform type of channel {}'.format(i),
vals=validator.Enum(-1, 1, 2, 4, 5, 6, 8))
vals=validator.Enum(-1, 0, 1, 2, 4, 5, 6, 8))

#
# Get-commands
#

def get_module_count(self, verbose=False):
"""Returns the number of Signadyne modules installed in the system"""
value = self.awg.moduleCount()
value_name = 'module_count'
return result_parser(value, value_name, verbose)

def get_product_name(self, verbose=False):
"""Returns the product name of the device"""
value = self.awg.getProductName()
value_name = 'product_name'
return result_parser(value, value_name, verbose)

def get_serial_number(self, verbose=False):
"""Returns the serial number of the device"""
value = self.awg.getSerialNumber()
value_name = 'serial_number'
return result_parser(value, value_name, verbose)

def get_chassis(self, verbose=False):
"""Returns the chassis number where the device is located"""
value = self.awg.getChassis()
value_name = 'chassis_number'
return result_parser(value, value_name, verbose)

def get_slot(self, verbose=False):
"""Returns the slot number where the device is located"""
value = self.awg.getSlot()
value_name = 'slot_number'
return result_parser(value, value_name, verbose)

def get_status(self, verbose=False):
"""Returns the status of the device"""
value = self.awg.getStatus()
value_name = 'status'
return result_parser(value, value_name, verbose)

def get_firmware_version(self, verbose=False):
"""Returns the firmware version of the device"""
value = self.awg.getFirmwareVersion()
value_name = 'firmware_version'
return result_parser(value, value_name, verbose)

def get_hardware_version(self, verbose=False):
"""Returns the hardware version of the device"""
value = self.awg.getHardwareVersion()
value_name = 'hardware_version'
return result_parser(value, value_name, verbose)

def get_type(self, verbose=False):
"""Returns the type of the device"""
value = self.awg.getType()
value_name = 'type'
return result_parser(value, value_name, verbose)

def get_open(self, verbose=False):
"""Returns whether the device is open (True) or not (False)"""
value = self.awg.isOpen()
value_name = 'open'
return result_parser(value, value_name, verbose)

def get_pxi_trigger(self, pxi_trigger, verbose=False):
"""
Returns the digital value of the specified PXI trigger
Expand Down Expand Up @@ -347,7 +218,8 @@ def set_channel_offset(self, offset, channel_number):
def set_channel_wave_shape(self, wave_shape, channel_number):
"""
Sets output waveform type for the specified channel.
No Signal : -1
HiZ : -1 (only available for M3202A)
No Signal : 0
Sinusoidal : 1
Triangular : 2
Square : 4
Expand Down Expand Up @@ -385,41 +257,21 @@ def set_trigger_io(self, value):
# The methods below are useful for controlling the device, but are not used for setting or getting parameters
#

# closes the hardware device and also throws away the current instrument object
# if you want to open the instrument again, you have to initialize a new instrument object
def close(self):
self.awg.close()
super().close()

# only closes the hardware device, does not delete the current instrument object
def close_soft(self):
self.awg.close()

def off(self):
"""
Stops the AWGs and sets the waveform of all channels to 'No Signal'
"""

for i in [0, 1, 2, 3]:
for i in range(self.channels):
awg_response = self.awg.AWGstop(i)
if isinstance(awg_response, int) and awg_response < 0:
raise Exception('Error in call to Signadyne AWG '
'error code {}'.format(awg_response))
channel_response = self.awg.channelWaveShape(i, -1)
channel_response = self.awg.channelWaveShape(i, 0)
if isinstance(channel_response, int) and channel_response < 0:
raise Exception('Error in call to Signadyne AWG '
'error code {}'.format(channel_response))

def open_with_serial_number(self, name, serial_number):
self.awg.openWithSerialNumber(name, serial_number)

def open_with_slot(self, name, chassis, slot):
self.awg.openWithSlot(name, chassis, slot)

def run_self_test(self):
value = self.awg.runSelfTest()
print('Did self test and got result: {}'.format(value))

def reset_clock_phase(self, trigger_behaviour, trigger_source):
"""
Sets the module in a sync state, waiting for the first trigger to reset the phase
Expand Down Expand Up @@ -885,74 +737,3 @@ def get_waveform_type(self, waveform, verbose=False):
value = waveform.getType()
value_name = 'waveform_type'
return result_parser(value, value_name, verbose)


#
# 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
#

def get_product_name_by_slot(self, chassis, slot, verbose=False):
value = self.awg.getProductNameBySlot(chassis, slot)
value_name = 'product_name'
return result_parser(value, value_name, verbose)

def get_product_name_by_index(self, index, verbose=False):
value = self.awg.getProductNameByIndex(index)
value_name = 'product_name'
return result_parser(value, value_name, verbose)

def get_serial_number_by_slot(self, chassis, slot, verbose=False):
value = self.awg.getSerialNumberBySlot(chassis, slot)
value_name = 'serial_number'
return result_parser(value, value_name, verbose)

def get_serial_number_by_index(self, index, verbose=False):
value = self.awg.getSerialNumberByIndex(index)
value_name = 'serial_number'
return result_parser(value, value_name, verbose)

# method below is commented out because it is missing from the dll provided by Signadyne
# def get_type_by_slot(self, chassis, slot, verbose=False):
# value = self.awg.getTypeBySlot(chassis, slot)
# value_name = 'type'
# return result_parser(value, value_name, verbose)

# method below is commented out because it is missing from the dll provided by Signadyne
# def get_type_by_index(self, index, verbose=False):
# value = self.awg.getTypeByIndex(index)
# value_name = 'type'
# return result_parser(value, value_name, verbose)

# method below is commented out because it is missing from the dll provided by Signadyne
# def get_awg_running(self, verbose=0, awg_number):
# """
# Returns whether the AWG is running or stopped
#
# Args:
# awg_number (int): AWG number
#
# Returns:
# value (int): 1 if the AWG is running, 0 if it is stopped
# """
# value =
# if verbose:
# print('slot_number: %s' % value)
# return value

# method below is commented out because it is missing from the dll provided by Signadyne
# def get_awg_waveform_number_playing(self, verbose=0, awg_number=0):
# """
# Returns the waveformNumber of the waveform which is currently being generated.
#
# Args:
# awg_number (int): AWG number
#
# Returns:
# value (int): Waveform identifier,
# or negative numbers for errors
# """
# value = self.awg.AWG
# if verbose:
# print('pxi_trigger number %s: %s' % (pxi_trigger, value))
# return value
Loading

0 comments on commit ef0daf0

Please sign in to comment.