1616import numpy as np
1717
1818
19- class WindfreakSynthWorker (Worker ):
19+ class WindfreakSynthHDWorker (Worker ):
2020
2121 def init (self ):
2222 # hide import of 3rd-party library in here so docs don't need it
@@ -32,12 +32,41 @@ def init(self):
3232 # connect to synth
3333 self .synth = windfreak .SynthHD (self .com_port )
3434 self .valid_modes = self .synth .trigger_modes
35+ self .valid_ref_modes = self .synth .reference_modes
36+ # set reference mode
37+ self .set_reference_mode (self .reference_mode , self .reference_frequency )
3538 # set trigger mode from connection_table_properties
3639 self .set_trigger_mode (self .trigger_mode )
3740
3841 # populate smart chache
3942 self .smart_cache ['STATIC_DATA' ] = self .check_remote_values ()
4043
44+ def set_reference_mode (self , mode , ext_freq ):
45+ """Sets the synth reference mode.
46+
47+ Provides basic error checking that setting is valid.
48+
49+ Args:
50+ mode (str): Valid reference modes are `external`, `internal 27mhz`
51+ and `internal 10mhz`. If mode is external, ext_freq must be provided.
52+ ext_freq (float): Frequency of external reference.
53+ If using internal reference, pass `None`.
54+
55+ Raises:
56+ ValueError: if `mode` is not a valid setting or `ext_ref` not provided
57+ when using an external reference.
58+ """
59+
60+ if mode == 'external' and ext_freq is None :
61+ raise ValueError ('Must specify external reference frequency' )
62+
63+ if mode in self .valid_ref_modes :
64+ self .synth .reference_mode = mode
65+ if mode == 'external' :
66+ self .synth .reference_frequency = ext_freq
67+ else :
68+ raise ValueError (f'{ mode } not in { self .valid_ref_modes } ' )
69+
4170 def set_trigger_mode (self ,mode ):
4271 """Sets the synth trigger mode.
4372
@@ -81,6 +110,16 @@ def program_manual(self, front_panel_values):
81110 return self .check_remote_values ()
82111
83112 def check_remote_value (self ,channel ,typ ):
113+ """Checks the remote value of a parameter for a channel.
114+
115+ Args:
116+ channel (int): Which channel to check. Must be 0 or 1.
117+ typ (str): Which parameter to get. Must be `freq`, `amp`, `phase`
118+ or `gate`.
119+
120+ Raises:
121+ ValueError: If `typ` is not a valid parameter type for the channel.
122+ """
84123
85124 if typ == 'freq' :
86125 return self .synth [channel ].frequency
@@ -91,9 +130,21 @@ def check_remote_value(self,channel,typ):
91130 elif typ == 'gate' :
92131 return self .synth [channel ].rf_enable and self .synth [channel ].pll_enable
93132 else :
94- raise ValueError (type )
133+ raise ValueError (typ )
95134
96135 def program_static_value (self ,channel ,typ ,value ):
136+ """Program a value for the specified parameter of the channel.
137+
138+ Args:
139+ channel (int): Channel to program. Must be 0 or 1.
140+ typ (str): Parameter to program. Must be `freq`, `amp`, `phase`,
141+ or `gate`.
142+ value (float or bool): Value to program. `gate` takes a boolean type,
143+ all others take a float.
144+
145+ Raises:
146+ ValueError: If requested parameter type is not valid.
147+ """
97148
98149 if typ == 'freq' :
99150 self .synth [channel ].frequency = value
@@ -104,11 +155,12 @@ def program_static_value(self,channel,typ,value):
104155 elif typ == 'gate' :
105156 # windfreak API does not like np.bool_
106157 # convert to native python bool
107- if isinstance (value , np .bool_ ): value = value .item ()
158+ if isinstance (value , np .bool_ ):
159+ value = value .item ()
108160 self .synth [channel ].rf_enable = value
109161 self .synth [channel ].pll_enable = value
110162 else :
111- raise ValueError (type )
163+ raise ValueError (typ )
112164
113165 def transition_to_buffered (self , device_name , h5file , initial_values , fresh ):
114166
@@ -122,21 +174,20 @@ def transition_to_buffered(self, device_name, h5file, initial_values, fresh):
122174 static_data = group ['STATIC_DATA' ][:][0 ]
123175
124176 if static_data is not None :
125- data = static_data
126- if fresh or data != self .smart_cache ['STATIC_DATA' ]:
127-
128- # need to infer which channels are programming
129- num_chan = len (data )// len (self .subchnls )
130- channels = [int (name [- 1 ]) for name in data .dtype .names [0 :num_chan ]]
131-
132- for i in channels :
133- for sub in self .subchnls :
134- if initial_values [f'channel { i :d} ' ][sub ] != data [sub + str (i )]:
135- self .program_static_value (i ,sub ,data [sub + str (i )])
136- # update smart cache to reflect programmed values
137- self .smart_cache ['STATIC_DATA' ][f'channel { i :d} ' ][sub ] = data [sub + str (i )]
138- # update final values to reflect programmed values
139- self .final_values [f'channel { i :d} ' ][sub ] = data [sub + str (i )]
177+
178+ # need to infer which channels are programming
179+ num_chan = len (static_data )// len (self .subchnls )
180+ channels = [int (name [- 1 ]) for name in static_data .dtype .names [0 :num_chan ]]
181+
182+ for i in channels :
183+ for sub in self .subchnls :
184+ desired_value = static_data [sub + str (i )]
185+ if self .smart_cache ['STATIC_DATA' ][f'channel { i :d} ' ][sub ] != desired_value or fresh :
186+ self .program_static_value (i ,sub ,desired_value )
187+ # update smart cache to reflect programmed values
188+ self .smart_cache ['STATIC_DATA' ][f'channel { i :d} ' ][sub ] = desired_value
189+ # update final values to reflect programmed values
190+ self .final_values [f'channel { i :d} ' ][sub ] = desired_value
140191
141192 return self .final_values
142193
@@ -161,5 +212,5 @@ def transition_to_manual(self,abort = False):
161212 # If we're aborting the run, reset to original value
162213 self .program_manual (self .initial_values )
163214 # If we're not aborting the run, stick with buffered value. Nothing to do really!
164- # return the current values in the device
215+
165216 return True
0 commit comments