|
| 1 | +##################################################################### |
| 2 | +# # |
| 3 | +# /labscript_devices/Windfreak/labscript_devices.py # |
| 4 | +# # |
| 5 | +# Copyright 2022, Monash University and contributors # |
| 6 | +# # |
| 7 | +# This file is part of labscript_devices, in the labscript suite # |
| 8 | +# (see http://labscriptsuite.org), and is licensed under the # |
| 9 | +# Simplified BSD License. See the license.txt file in the root of # |
| 10 | +# the project for the full license. # |
| 11 | +# # |
| 12 | +##################################################################### |
| 13 | + |
| 14 | +from labscript import LabscriptError, set_passed_properties, config, StaticDDS, IntermediateDevice, Device |
| 15 | +from labscript_utils import dedent |
| 16 | + |
| 17 | +import numpy as np |
| 18 | + |
| 19 | +class WindfreakSynth(Device): |
| 20 | + description = 'Windfreak HDPro Synthesizer' |
| 21 | + allowed_children = [StaticDDS] |
| 22 | + # note, box labels 'A', 'B' map to programming channels 0, 1 |
| 23 | + allowed_chans = [0,1] |
| 24 | + |
| 25 | + # define output limitations for the SynthHDPro |
| 26 | + freq_limits = (10e6,24e9) # set in Hz |
| 27 | + freq_res = 1 # number of sig digits after decimal |
| 28 | + amp_limits = (-40.0,20.0) # set in dBm |
| 29 | + amp_res = 2 |
| 30 | + phase_limits = (0.0,360.0) # in deg |
| 31 | + phase_res = 2 |
| 32 | + |
| 33 | + @set_passed_properties(property_names={ |
| 34 | + 'connection_table_properties': [ |
| 35 | + 'com_port', |
| 36 | + 'allowed_chans', |
| 37 | + 'freq_limits', |
| 38 | + 'freq_res', |
| 39 | + 'amp_limits', |
| 40 | + 'amp_res', |
| 41 | + 'phase_limits', |
| 42 | + 'phase_res', |
| 43 | + ] |
| 44 | + }) |
| 45 | + def __init__(self, name, com_port="", **kwargs): |
| 46 | + |
| 47 | + Device.__init__(self, name, None, com_port, **kwargs) |
| 48 | + self.BLACS_connection = com_port |
| 49 | + |
| 50 | + def add_device(self, device): |
| 51 | + Device.add_device(self, device) |
| 52 | + # ensure a valid default value |
| 53 | + device.frequency.default_value = 10e6 |
| 54 | + |
| 55 | + def validate_data(self, data, limits, device): |
| 56 | + if not isinstance(data, np.ndarray): |
| 57 | + data = np.array(data,dtype=np.float64) |
| 58 | + if np.any(data < limits[0]) or np.any(data > limits[1]): |
| 59 | + msg = f'''{device.description} {device.name} can only have frequencies between |
| 60 | + {limits[0]:E}Hz and {limits[1]:E}Hz, {data} given |
| 61 | + ''' |
| 62 | + raise LabscriptError(dedent(msg)) |
| 63 | + return data |
| 64 | + |
| 65 | + def generate_code(self, hdf5_file): |
| 66 | + DDSs = {} |
| 67 | + |
| 68 | + |
| 69 | + for output in self.child_devices: |
| 70 | + |
| 71 | + try: |
| 72 | + prefix, channel = output.connection.split() |
| 73 | + if channel not in self.allowed_chans: |
| 74 | + LabscriptError(f"Channel {channel} must be 0 or 0") |
| 75 | + except: |
| 76 | + msg = f"""{output.description}:{output.name} has invalid connection string. |
| 77 | + Only 'channel 0' or 'channel 1' is allowed. |
| 78 | + """ |
| 79 | + raise LabscriptError(dedent(msg)) |
| 80 | + |
| 81 | + DDSs[channel] = output |
| 82 | + |
| 83 | + for connection in DDSs: |
| 84 | + dds = DDSs[connection] |
| 85 | + dds.frequency.raw_output = self.validate_data(dds.frequency.static_value,self.freq_limits,dds) |
| 86 | + dds.amplitude.raw_output = self.validate_data(dds.amplitude.static_value,self.amp_limits,dds) |
| 87 | + dds.phase.raw_output = self.validate_data(dds.phase.static_value,self.phase_limits,dds) |
| 88 | + |
| 89 | + static_dtypes = [(f'freq{i:d}',np.float64) for i in self.allowed_chans] +\ |
| 90 | + [(f'amp{i:d}',np.float64) for i in self.allowed_chans] +\ |
| 91 | + [(f'phase{i:d}',np.float64) for i in self.allowed_chans] |
| 92 | + static_table = np.zeros(1,dtype=static_dtypes) |
| 93 | + |
| 94 | + for connection in DDSs: |
| 95 | + static_table[f'freq{connection}'] = dds.frequency.raw_output |
| 96 | + static_table[f'amp{connection}'] = dds.amplitude.raw_output |
| 97 | + static_table[f'phase{connection}'] = dds.phase.raw_output |
| 98 | + |
| 99 | + grp = self.init_device_group(hdf5_file) |
| 100 | + grp.create_dataset('STATIC_DATA',compression=config.compression,data=static_table) |
| 101 | + |
0 commit comments