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}