@@ -54,7 +54,7 @@ class AD9959DDSSweeper(IntermediateDevice):
5454 }
5555 )
5656
57- def __init__ (self , name , parent_device , com_port ,
57+ def __init__ (self , name , parent_device , com_port , dynamic_channels ,
5858 pico_board = 'pico1' , sweep_mode = 0 ,
5959 ref_clock_external = 0 , ref_clock_frequency = 125e6 , pll_mult = 4 , ** kwargs ):
6060 '''Labscript device class for AD9959 eval board controlled by a Raspberry Pi Pico running the DDS Sweeper firmware (https://github.com/QTC-UMD/dds-sweeper).
@@ -67,6 +67,8 @@ def __init__(self, name, parent_device, com_port,
6767 Pseudoclock clockline used to clock DDS parameter changes.
6868 com_port (str): COM port assigned to the AD9959DDSSweeper by the OS.
6969 On Windows, takes the form of `COMd` where `d` is an integer.
70+ dynamic_channels (int): number of dynamic DDS channels that will be added.
71+ This must be specified in the constructor so that update rates can be calculated correctly.
7072 pico_board (str): The version of pico board used, pico1 or pico2.
7173 sweep_mode (int):
7274 The DDS Sweeper firmware can set the DDS outputs in either fixed steps or sweeps of the amplitude, frequency, or phase.
@@ -75,7 +77,6 @@ def __init__(self, name, parent_device, com_port,
7577 ref_clock_frequency (float): Frequency of the reference clock. If ref_clock_external is 0, the Pi Pico system clock will be set to this frequency. If the PLL is used, ref_clock_frequency * pll_mult must be between 100 MHz and 500 MHz. If the PLL is not used, ref_clock_frequency must be less than 500 MHz.
7678 pll_mult: the AD9959 has a PLL to multiply the reference clock frequency. Allowed values are 1 or 4-20.
7779 '''
78- IntermediateDevice .__init__ (self , name , parent_device , ** kwargs )
7980 self .BLACS_connection = '%s' % com_port
8081
8182 if pico_board in self .allowed_boards :
@@ -97,27 +98,55 @@ def __init__(self, name, parent_device, com_port,
9798 self .dds_clock = ref_clock_frequency * pll_mult
9899 self .clk_scale = 2 ** 32 / self .dds_clock
99100
101+ # Store number of dynamic channels
102+ if dynamic_channels > 4 :
103+ raise ValueError ('AD9959DDSSweeper only supports up to 4 total channels, dynamic channels must be 4 or less.' )
104+ self .dynamic_channels = dynamic_channels
105+
106+ IntermediateDevice .__init__ (self , name , parent_device , ** kwargs )
107+
100108 @property
101109 def clock_limit (self ):
102110 '''Dynamically computs clock limit based off of number of dynamic
103111 channels and reference clock frequency.'''
104- num_dyn_chans = sum (isinstance (child , DDS ) for child in self .child_devices )
105- if num_dyn_chans == 0 :
106- # Set to worst case
107- # 4 channels, step mode, default 125 MHz pico ref clk
108- return 100000
112+ if self .dynamic_channels == 0 :
113+ # No clock limit
114+ return None
109115
110116 if self .sweep_mode > 0 :
111117 mode = 'sweeps'
112118 else :
113119 mode = 'steps'
114120 try :
115- cycles_per_instruction = self .cycles_per_instruction_map [mode ][num_dyn_chans - 1 ]
121+ cycles_per_instruction = self .cycles_per_instruction_map [mode ][self . dynamic_channels - 1 ]
116122 except (KeyError , IndexError ):
117- raise LabscriptError (f'Unsupported mode or number of channels: { mode } , { num_dyn_chans } ' )
123+ raise LabscriptError (f'Unsupported mode or number of channels: { mode } , { self . dynamic_channels } ' )
118124
119125 return self .ref_clock_frequency / cycles_per_instruction
120-
126+
127+ def add_device (self , device ):
128+ """Confirms channel specified is valid before adding
129+
130+ Validity checks include channel name and static/dynamic status.
131+ Dynamic channels must be specified before static channels.
132+ Args:
133+ device(): Device to attach. Must be a DDS or a StaticDDS.
134+ Allowed connections are a string of the form `channel X`.
135+ """
136+ conn = device .connection
137+ chan = int (conn .split ('channel ' )[- 1 ])
138+
139+ if isinstance (device , StaticDDS ):
140+ if chan < self .dynamic_channels :
141+ raise LabscriptError (f'Channel { chan } configured as dynamic channel, can not create StaticDDS.' )
142+ elif chan >= 4 :
143+ raise LabscriptError ('AD9959DDSSweeper only supports 4 channels' )
144+ elif isinstance (device , DDS ):
145+ if chan >= self .dynamic_channels :
146+ raise LabscriptError (f'Channel { chan } not configured as dynamic channel, can not create DDS.' )
147+
148+ super ().add_device (device )
149+
121150 def get_default_unit_conversion_classes (self , device ):
122151 """Child devices call this during their __init__ (with themselves
123152 as the argument) to check if there are certain unit calibration
0 commit comments