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