rusty_tip/nanonis/client/pll.rs
1use super::NanonisClient;
2use crate::error::NanonisError;
3use crate::types::NanonisValue;
4
5impl NanonisClient {
6 /// Set the amplitude controller setpoint for a PLL modulator.
7 ///
8 /// Sets the amplitude controller setpoint value for the specified PLL modulator.
9 /// This controls the target oscillation amplitude for the phase-locked loop.
10 ///
11 /// # Arguments
12 /// * `modulator_index` - PLL modulator index (starts from 1)
13 /// * `setpoint_m` - Amplitude setpoint in meters
14 ///
15 /// # Errors
16 /// Returns `NanonisError` if communication fails or invalid modulator index.
17 ///
18 /// # Examples
19 /// ```no_run
20 /// use rusty_tip::NanonisClient;
21 ///
22 /// let mut client = NanonisClient::new("127.0.0.1", 6501)?;
23 ///
24 /// // Set amplitude setpoint for first PLL to 1 nanometer
25 /// client.pll_amp_ctrl_setpnt_set(1, 1e-9)?;
26 ///
27 /// // Set amplitude setpoint for second PLL to 500 picometers
28 /// client.pll_amp_ctrl_setpnt_set(2, 500e-12)?;
29 /// # Ok::<(), Box<dyn std::error::Error>>(())
30 /// ```
31 pub fn pll_amp_ctrl_setpnt_set(
32 &mut self,
33 modulator_index: i32,
34 setpoint_m: f32,
35 ) -> Result<(), NanonisError> {
36 self.quick_send(
37 "PLL.AmpCtrlSetpntSet",
38 vec![
39 NanonisValue::I32(modulator_index),
40 NanonisValue::F32(setpoint_m),
41 ],
42 vec!["i", "f"],
43 vec![],
44 )?;
45 Ok(())
46 }
47
48 /// Get the amplitude controller setpoint for a PLL modulator.
49 ///
50 /// Returns the current amplitude controller setpoint value for the specified
51 /// PLL modulator.
52 ///
53 /// # Arguments
54 /// * `modulator_index` - PLL modulator index (starts from 1)
55 ///
56 /// # Returns
57 /// * `f32` - Current amplitude setpoint in meters
58 ///
59 /// # Errors
60 /// Returns `NanonisError` if communication fails or invalid modulator index.
61 ///
62 /// # Examples
63 /// ```no_run
64 /// use rusty_tip::NanonisClient;
65 ///
66 /// let mut client = NanonisClient::new("127.0.0.1", 6501)?;
67 ///
68 /// // Get current amplitude setpoint for first PLL
69 /// let setpoint = client.pll_amp_ctrl_setpnt_get(1)?;
70 /// println!("Current amplitude setpoint: {:.2e} m", setpoint);
71 ///
72 /// // Check if setpoint is within expected range
73 /// if setpoint > 1e-9 {
74 /// println!("Amplitude setpoint is greater than 1 nm");
75 /// }
76 /// # Ok::<(), Box<dyn std::error::Error>>(())
77 /// ```
78 pub fn pll_amp_ctrl_setpnt_get(&mut self, modulator_index: i32) -> Result<f32, NanonisError> {
79 let response = self.quick_send(
80 "PLL.AmpCtrlSetpntGet",
81 vec![NanonisValue::I32(modulator_index)],
82 vec!["i"],
83 vec!["f"],
84 )?;
85
86 match response.first() {
87 Some(NanonisValue::F32(setpoint)) => Ok(*setpoint),
88 _ => Err(NanonisError::SerializationError(
89 "Expected f32 amplitude setpoint".to_string(),
90 )),
91 }
92 }
93
94 /// Set the amplitude controller on/off status for a PLL modulator.
95 ///
96 /// Switches the amplitude controller for the specified PLL modulator on or off.
97 /// When enabled, the amplitude controller actively maintains the oscillation
98 /// amplitude at the setpoint value.
99 ///
100 /// # Arguments
101 /// * `modulator_index` - PLL modulator index (starts from 1)
102 /// * `status` - true to turn on, false to turn off
103 ///
104 /// # Errors
105 /// Returns `NanonisError` if communication fails or invalid modulator index.
106 ///
107 /// # Examples
108 /// ```no_run
109 /// use rusty_tip::NanonisClient;
110 ///
111 /// let mut client = NanonisClient::new("127.0.0.1", 6501)?;
112 ///
113 /// // Turn on amplitude controller for first PLL
114 /// client.pll_amp_ctrl_on_off_set(1, true)?;
115 ///
116 /// // Turn off amplitude controller for second PLL
117 /// client.pll_amp_ctrl_on_off_set(2, false)?;
118 /// # Ok::<(), Box<dyn std::error::Error>>(())
119 /// ```
120 pub fn pll_amp_ctrl_on_off_set(
121 &mut self,
122 modulator_index: i32,
123 status: bool,
124 ) -> Result<(), NanonisError> {
125 let status_u32 = if status { 1u32 } else { 0u32 };
126
127 self.quick_send(
128 "PLL.AmpCtrlOnOffSet",
129 vec![
130 NanonisValue::I32(modulator_index),
131 NanonisValue::U32(status_u32),
132 ],
133 vec!["i", "I"],
134 vec![],
135 )?;
136 Ok(())
137 }
138
139 /// Get the amplitude controller on/off status for a PLL modulator.
140 ///
141 /// Returns the current on/off status of the amplitude controller for the
142 /// specified PLL modulator.
143 ///
144 /// # Arguments
145 /// * `modulator_index` - PLL modulator index (starts from 1)
146 ///
147 /// # Returns
148 /// * `bool` - true if controller is on, false if off
149 ///
150 /// # Errors
151 /// Returns `NanonisError` if communication fails or invalid modulator index.
152 ///
153 /// # Examples
154 /// ```no_run
155 /// use rusty_tip::NanonisClient;
156 ///
157 /// let mut client = NanonisClient::new("127.0.0.1", 6501)?;
158 ///
159 /// // Check amplitude controller status for first PLL
160 /// let is_on = client.pll_amp_ctrl_on_off_get(1)?;
161 /// if is_on {
162 /// println!("Amplitude controller is active");
163 /// } else {
164 /// println!("Amplitude controller is inactive");
165 /// }
166 ///
167 /// // Enable controller if it's off
168 /// if !is_on {
169 /// client.pll_amp_ctrl_on_off_set(1, true)?;
170 /// }
171 /// # Ok::<(), Box<dyn std::error::Error>>(())
172 /// ```
173 pub fn pll_amp_ctrl_on_off_get(&mut self, modulator_index: i32) -> Result<bool, NanonisError> {
174 let response = self.quick_send(
175 "PLL.AmpCtrlOnOffGet",
176 vec![NanonisValue::I32(modulator_index)],
177 vec!["i"],
178 vec!["I"],
179 )?;
180
181 match response.first() {
182 Some(NanonisValue::U32(status)) => Ok(*status != 0),
183 _ => Err(NanonisError::InvalidResponse(
184 "Expected u32 amplitude controller status".to_string(),
185 )),
186 }
187 }
188
189 /// Set the amplitude controller gain parameters for a PLL modulator.
190 ///
191 /// Sets the proportional gain and time constant for the amplitude controller
192 /// of the specified PLL modulator. These parameters control the response
193 /// characteristics of the amplitude control loop.
194 ///
195 /// # Arguments
196 /// * `modulator_index` - PLL modulator index (starts from 1)
197 /// * `p_gain_v_div_m` - Proportional gain in V/m
198 /// * `time_constant_s` - Time constant in seconds
199 ///
200 /// # Errors
201 /// Returns `NanonisError` if communication fails or invalid modulator index.
202 ///
203 /// # Examples
204 /// ```no_run
205 /// use rusty_tip::NanonisClient;
206 ///
207 /// let mut client = NanonisClient::new("127.0.0.1", 6501)?;
208 ///
209 /// // Set moderate gain and fast response for first PLL
210 /// client.pll_amp_ctrl_gain_set(1, 1e6, 0.01)?;
211 ///
212 /// // Set higher gain and slower response for second PLL
213 /// client.pll_amp_ctrl_gain_set(2, 5e6, 0.1)?;
214 /// # Ok::<(), Box<dyn std::error::Error>>(())
215 /// ```
216 pub fn pll_amp_ctrl_gain_set(
217 &mut self,
218 modulator_index: i32,
219 p_gain_v_div_m: f32,
220 time_constant_s: f32,
221 ) -> Result<(), NanonisError> {
222 self.quick_send(
223 "PLL.AmpCtrlGainSet",
224 vec![
225 NanonisValue::I32(modulator_index),
226 NanonisValue::F32(p_gain_v_div_m),
227 NanonisValue::F32(time_constant_s),
228 ],
229 vec!["i", "f", "f"],
230 vec![],
231 )?;
232 Ok(())
233 }
234
235 /// Get the amplitude controller gain parameters for a PLL modulator.
236 ///
237 /// Returns the current proportional gain and time constant settings for the
238 /// amplitude controller of the specified PLL modulator.
239 ///
240 /// # Arguments
241 /// * `modulator_index` - PLL modulator index (starts from 1)
242 ///
243 /// # Returns
244 /// * `(f32, f32)` - Tuple of (proportional gain in V/m, time constant in seconds)
245 ///
246 /// # Errors
247 /// Returns `NanonisError` if communication fails or invalid modulator index.
248 ///
249 /// # Examples
250 /// ```no_run
251 /// use rusty_tip::NanonisClient;
252 ///
253 /// let mut client = NanonisClient::new("127.0.0.1", 6501)?;
254 ///
255 /// // Get current gain parameters for first PLL
256 /// let (p_gain, time_const) = client.pll_amp_ctrl_gain_get(1)?;
257 /// println!("P gain: {:.2e} V/m, Time constant: {:.3} s", p_gain, time_const);
258 ///
259 /// // Check if parameters are within acceptable range
260 /// if p_gain < 1e5 {
261 /// println!("Warning: Low proportional gain");
262 /// }
263 /// if time_const > 1.0 {
264 /// println!("Warning: Slow time constant");
265 /// }
266 /// # Ok::<(), Box<dyn std::error::Error>>(())
267 /// ```
268 pub fn pll_amp_ctrl_gain_get(
269 &mut self,
270 modulator_index: i32,
271 ) -> Result<(f32, f32), NanonisError> {
272 let response = self.quick_send(
273 "PLL.AmpCtrlGainGet",
274 vec![NanonisValue::I32(modulator_index)],
275 vec!["i"],
276 vec!["f", "f"],
277 )?;
278
279 match (response.first(), response.get(1)) {
280 (Some(NanonisValue::F32(p_gain)), Some(NanonisValue::F32(time_const))) => {
281 Ok((*p_gain, *time_const))
282 }
283 _ => Err(NanonisError::InvalidResponse(
284 "Expected f32 gain parameters (p_gain, time_constant)".to_string(),
285 )),
286 }
287 }
288}