nanonis_rs/client/user_out/mod.rs
1mod types;
2pub use types::*;
3
4use super::NanonisClient;
5use crate::error::NanonisError;
6
7impl NanonisClient {
8 /// Set the mode (User Output, Monitor, Calculated signal) of the selected user output channel.
9 ///
10 /// # Arguments
11 /// * `output_index` - Output to be used (1 to number of available outputs)
12 /// * `output_mode` - Output mode to set
13 ///
14 /// # Errors
15 /// Returns `NanonisError` if:
16 /// - Invalid output index is provided
17 /// - Communication timeout or protocol error
18 ///
19 /// # Examples
20 /// ```no_run
21 /// use nanonis_rs::{NanonisClient, user_out::OutputMode};
22 ///
23 /// let mut client = NanonisClient::new("127.0.0.1", 6501)?;
24 ///
25 /// // Set output 1 to Monitor mode
26 /// client.user_out_mode_set(1, OutputMode::Monitor)?;
27 /// # Ok::<(), Box<dyn std::error::Error>>(())
28 /// ```
29 pub fn user_out_mode_set(
30 &mut self,
31 output_index: i32,
32 output_mode: OutputMode,
33 ) -> Result<(), NanonisError> {
34 self.quick_send(
35 "UserOut.ModeSet",
36 vec![output_index.into(), output_mode.into()],
37 vec!["i", "H"],
38 vec![],
39 )?;
40 Ok(())
41 }
42
43 /// Get the mode (User Output, Monitor, Calculated signal) of the selected user output channel.
44 ///
45 /// # Arguments
46 /// * `output_index` - Output to query (1 to number of available outputs)
47 ///
48 /// # Returns
49 /// The current output mode (UserOutput, Monitor, CalcSignal, or Override)
50 ///
51 /// # Errors
52 /// Returns `NanonisError` if communication fails or invalid response received.
53 ///
54 /// # Examples
55 /// ```no_run
56 /// use nanonis_rs::NanonisClient;
57 ///
58 /// let mut client = NanonisClient::new("127.0.0.1", 6501)?;
59 ///
60 /// let mode = client.user_out_mode_get(1)?;
61 /// println!("Output 1 mode: {:?}", mode);
62 /// # Ok::<(), Box<dyn std::error::Error>>(())
63 /// ```
64 pub fn user_out_mode_get(&mut self, output_index: i32) -> Result<OutputMode, NanonisError> {
65 let result = self.quick_send(
66 "UserOut.ModeGet",
67 vec![output_index.into()],
68 vec!["i"],
69 vec!["H"],
70 )?;
71 match result.first() {
72 Some(value) => {
73 let mode_val = value.as_u16()?;
74 OutputMode::try_from(mode_val)
75 }
76 None => Err(NanonisError::Protocol(
77 "No output mode value returned".to_string(),
78 )),
79 }
80 }
81
82 /// Set the monitor channel of the selected output channel.
83 ///
84 /// # Arguments
85 /// * `output_index` - Output to configure (1 to number of available outputs)
86 /// * `monitor_channel_index` - Index of the channel to monitor (0-127)
87 ///
88 /// # Errors
89 /// Returns `NanonisError` if invalid indices provided or communication fails.
90 ///
91 /// # Examples
92 /// ```no_run
93 /// use nanonis_rs::NanonisClient;
94 ///
95 /// let mut client = NanonisClient::new("127.0.0.1", 6501)?;
96 ///
97 /// // Set output 1 to monitor channel 5
98 /// client.user_out_monitor_ch_set(1, 5)?;
99 /// # Ok::<(), Box<dyn std::error::Error>>(())
100 /// ```
101 pub fn user_out_monitor_ch_set(
102 &mut self,
103 output_index: i32,
104 monitor_channel_index: i32,
105 ) -> Result<(), NanonisError> {
106 self.quick_send(
107 "UserOut.MonitorChSet",
108 vec![output_index.into(), monitor_channel_index.into()],
109 vec!["i", "i"],
110 vec![],
111 )?;
112 Ok(())
113 }
114
115 /// Get the monitor channel of the selected output channel.
116 ///
117 /// # Arguments
118 /// * `output_index` - Output to query (1 to number of available outputs)
119 ///
120 /// # Returns
121 /// The monitor channel index (0-127)
122 ///
123 /// # Errors
124 /// Returns `NanonisError` if communication fails or invalid response received.
125 ///
126 /// # Examples
127 /// ```no_run
128 /// use nanonis_rs::NanonisClient;
129 ///
130 /// let mut client = NanonisClient::new("127.0.0.1", 6501)?;
131 ///
132 /// let channel = client.user_out_monitor_ch_get(1)?;
133 /// println!("Output 1 is monitoring channel {}", channel);
134 /// # Ok::<(), Box<dyn std::error::Error>>(())
135 /// ```
136 pub fn user_out_monitor_ch_get(&mut self, output_index: i32) -> Result<i32, NanonisError> {
137 let result = self.quick_send(
138 "UserOut.MonitorChGet",
139 vec![output_index.into()],
140 vec!["i"],
141 vec!["i"],
142 )?;
143 match result.first() {
144 Some(value) => Ok(value.as_i32()?),
145 None => Err(NanonisError::Protocol(
146 "No monitor channel value returned".to_string(),
147 )),
148 }
149 }
150
151 /// Set the value of the selected user output channel.
152 ///
153 /// # Arguments
154 /// * `output_index` - Output to set (1 to number of available outputs)
155 /// * `output_value` - Value to apply in physical units
156 ///
157 /// # Errors
158 /// Returns `NanonisError` if invalid output index or communication fails.
159 ///
160 /// # Examples
161 /// ```no_run
162 /// use nanonis_rs::NanonisClient;
163 ///
164 /// let mut client = NanonisClient::new("127.0.0.1", 6501)?;
165 ///
166 /// // Set output 1 to 2.5V (or appropriate physical unit)
167 /// client.user_out_val_set(1, 2.5)?;
168 /// # Ok::<(), Box<dyn std::error::Error>>(())
169 /// ```
170 pub fn user_out_val_set(
171 &mut self,
172 output_index: i32,
173 output_value: f32,
174 ) -> Result<(), NanonisError> {
175 self.quick_send(
176 "UserOut.ValSet",
177 vec![output_index.into(), output_value.into()],
178 vec!["i", "f"],
179 vec![],
180 )?;
181 Ok(())
182 }
183
184 /// Set the calibration of the selected user output or monitor channel.
185 ///
186 /// # Arguments
187 /// * `output_index` - Output to configure (1 to number of available outputs)
188 /// * `calibration_per_volt` - Calibration factor per volt
189 /// * `offset_in_physical_units` - Offset in physical units
190 ///
191 /// # Errors
192 /// Returns `NanonisError` if invalid parameters or communication fails.
193 ///
194 /// # Examples
195 /// ```no_run
196 /// use nanonis_rs::NanonisClient;
197 ///
198 /// let mut client = NanonisClient::new("127.0.0.1", 6501)?;
199 ///
200 /// // Set calibration for output 1: 10 units/V with 0.5 unit offset
201 /// client.user_out_calibr_set(1, 10.0, 0.5)?;
202 /// # Ok::<(), Box<dyn std::error::Error>>(())
203 /// ```
204 pub fn user_out_calibr_set(
205 &mut self,
206 output_index: i32,
207 calibration_per_volt: f32,
208 offset_in_physical_units: f32,
209 ) -> Result<(), NanonisError> {
210 self.quick_send(
211 "UserOut.CalibrSet",
212 vec![
213 output_index.into(),
214 calibration_per_volt.into(),
215 offset_in_physical_units.into(),
216 ],
217 vec!["i", "f", "f"],
218 vec![],
219 )?;
220 Ok(())
221 }
222
223 /// Set the Calculated Signal name of the selected output channel.
224 ///
225 /// # Arguments
226 /// * `output_index` - Output to configure (1 to number of available outputs)
227 /// * `calculated_signal_name` - Name of the calculated signal
228 ///
229 /// # Errors
230 /// Returns `NanonisError` if invalid output index or communication fails.
231 ///
232 /// # Examples
233 /// ```no_run
234 /// use nanonis_rs::NanonisClient;
235 ///
236 /// let mut client = NanonisClient::new("127.0.0.1", 6501)?;
237 ///
238 /// client.user_out_calc_signal_name_set(1, "MyCalcSignal".to_string())?;
239 /// # Ok::<(), Box<dyn std::error::Error>>(())
240 /// ```
241 pub fn user_out_calc_signal_name_set(
242 &mut self,
243 output_index: i32,
244 calculated_signal_name: String,
245 ) -> Result<(), NanonisError> {
246 self.quick_send(
247 "UserOut.CalcSignalNameSet",
248 vec![output_index.into(), calculated_signal_name.into()],
249 vec!["i", "+*c"],
250 vec![],
251 )?;
252 Ok(())
253 }
254
255 /// Get the Calculated Signal name of the selected output channel.
256 ///
257 /// # Arguments
258 /// * `output_index` - Output to query (1 to number of available outputs)
259 ///
260 /// # Returns
261 /// The calculated signal name
262 ///
263 /// # Errors
264 /// Returns `NanonisError` if communication fails or invalid response received.
265 ///
266 /// # Examples
267 /// ```no_run
268 /// use nanonis_rs::NanonisClient;
269 ///
270 /// let mut client = NanonisClient::new("127.0.0.1", 6501)?;
271 ///
272 /// let name = client.user_out_calc_signal_name_get(1)?;
273 /// println!("Calculated signal name: {}", name);
274 /// # Ok::<(), Box<dyn std::error::Error>>(())
275 /// ```
276 pub fn user_out_calc_signal_name_get(
277 &mut self,
278 output_index: i32,
279 ) -> Result<String, NanonisError> {
280 let result = self.quick_send(
281 "UserOut.CalcSignalNameGet",
282 vec![output_index.into()],
283 vec!["i"],
284 vec!["i", "*-c"],
285 )?;
286 if result.len() >= 2 {
287 Ok(result[1].as_string()?.to_string())
288 } else {
289 Err(NanonisError::Protocol(
290 "Invalid calc signal name response".to_string(),
291 ))
292 }
293 }
294
295 /// Set the configuration of the Calculated Signal for the selected output channel.
296 ///
297 /// The configuration is a math operation between 2 signals, or the logarithmic value of one signal.
298 ///
299 /// # Arguments
300 /// * `output_index` - Output to configure (1 to number of available outputs)
301 /// * `config` - Calculated signal configuration
302 ///
303 /// # Errors
304 /// Returns `NanonisError` if invalid parameters or communication fails.
305 ///
306 /// # Examples
307 /// ```no_run
308 /// use nanonis_rs::{NanonisClient, user_out::{CalcSignalConfig, CalcOperation}};
309 ///
310 /// let mut client = NanonisClient::new("127.0.0.1", 6501)?;
311 ///
312 /// // Configure output 1 to add signals 5 and 10
313 /// let config = CalcSignalConfig::new(5, CalcOperation::Add, 10);
314 /// client.user_out_calc_signal_config_set(1, config)?;
315 /// # Ok::<(), Box<dyn std::error::Error>>(())
316 /// ```
317 pub fn user_out_calc_signal_config_set(
318 &mut self,
319 output_index: i32,
320 config: CalcSignalConfig,
321 ) -> Result<(), NanonisError> {
322 self.quick_send(
323 "UserOut.CalcSignalConfigSet",
324 vec![
325 output_index.into(),
326 config.signal_1.into(),
327 config.operation.into(),
328 config.signal_2.into(),
329 ],
330 vec!["i", "H", "H", "H"],
331 vec![],
332 )?;
333 Ok(())
334 }
335
336 /// Get the configuration of the Calculated Signal for the selected output channel.
337 ///
338 /// # Arguments
339 /// * `output_index` - Output to query (1 to number of available outputs)
340 ///
341 /// # Returns
342 /// The calculated signal configuration
343 ///
344 /// # Errors
345 /// Returns `NanonisError` if communication fails or invalid response received.
346 ///
347 /// # Examples
348 /// ```no_run
349 /// use nanonis_rs::NanonisClient;
350 ///
351 /// let mut client = NanonisClient::new("127.0.0.1", 6501)?;
352 ///
353 /// let config = client.user_out_calc_signal_config_get(1)?;
354 /// println!("Signal 1: {}, Operation: {:?}, Signal 2: {}",
355 /// config.signal_1, config.operation, config.signal_2);
356 /// # Ok::<(), Box<dyn std::error::Error>>(())
357 /// ```
358 pub fn user_out_calc_signal_config_get(
359 &mut self,
360 output_index: i32,
361 ) -> Result<CalcSignalConfig, NanonisError> {
362 let result = self.quick_send(
363 "UserOut.CalcSignalConfigGet",
364 vec![output_index.into()],
365 vec!["i"],
366 vec!["H", "H", "H"],
367 )?;
368 if result.len() >= 3 {
369 let signal_1 = result[0].as_u16()?;
370 let operation = CalcOperation::try_from(result[1].as_u16()?)?;
371 let signal_2 = result[2].as_u16()?;
372 Ok(CalcSignalConfig::new(signal_1, operation, signal_2))
373 } else {
374 Err(NanonisError::Protocol(
375 "Invalid calc signal config response".to_string(),
376 ))
377 }
378 }
379
380 /// Set the physical limits (in calibrated units) of the selected output channel.
381 ///
382 /// # Arguments
383 /// * `output_index` - Output to configure (1 to number of available outputs)
384 /// * `upper_limit` - Upper physical limit of the user output
385 /// * `lower_limit` - Lower physical limit of the user output
386 /// * `raw_limits` - Whether to set physical limits (false) or raw limits (true)
387 ///
388 /// # Errors
389 /// Returns `NanonisError` if invalid parameters or communication fails.
390 ///
391 /// # Examples
392 /// ```no_run
393 /// use nanonis_rs::NanonisClient;
394 ///
395 /// let mut client = NanonisClient::new("127.0.0.1", 6501)?;
396 ///
397 /// // Set physical limits: -10V to +10V
398 /// client.user_out_limits_set(1, 10.0, -10.0, false)?;
399 /// # Ok::<(), Box<dyn std::error::Error>>(())
400 /// ```
401 pub fn user_out_limits_set(
402 &mut self,
403 output_index: i32,
404 upper_limit: f32,
405 lower_limit: f32,
406 raw_limits: bool,
407 ) -> Result<(), NanonisError> {
408 let raw_flag = if raw_limits { 1u32 } else { 0u32 };
409 self.quick_send(
410 "UserOut.LimitsSet",
411 vec![
412 output_index.into(),
413 upper_limit.into(),
414 lower_limit.into(),
415 raw_flag.into(),
416 ],
417 vec!["i", "f", "f", "I"],
418 vec![],
419 )?;
420 Ok(())
421 }
422
423 /// Get the physical limits (in calibrated units) of the selected output channel.
424 ///
425 /// # Arguments
426 /// * `output_index` - Output to query (1 to number of available outputs)
427 /// * `raw_limits` - Whether to get physical limits (false) or raw limits (true)
428 ///
429 /// # Returns
430 /// A tuple containing (upper_limit, lower_limit)
431 ///
432 /// # Errors
433 /// Returns `NanonisError` if communication fails or invalid response received.
434 ///
435 /// # Examples
436 /// ```no_run
437 /// use nanonis_rs::NanonisClient;
438 ///
439 /// let mut client = NanonisClient::new("127.0.0.1", 6501)?;
440 ///
441 /// let (upper, lower) = client.user_out_limits_get(1, false)?;
442 /// println!("Limits: {} to {}", lower, upper);
443 /// # Ok::<(), Box<dyn std::error::Error>>(())
444 /// ```
445 pub fn user_out_limits_get(
446 &mut self,
447 output_index: i32,
448 raw_limits: bool,
449 ) -> Result<(f32, f32), NanonisError> {
450 let raw_flag = if raw_limits { 1u32 } else { 0u32 };
451 let result = self.quick_send(
452 "UserOut.LimitsGet",
453 vec![output_index.into(), raw_flag.into()],
454 vec!["i", "I"],
455 vec!["f", "f"],
456 )?;
457 if result.len() >= 2 {
458 let upper_limit = result[0].as_f32()?;
459 let lower_limit = result[1].as_f32()?;
460 Ok((upper_limit, lower_limit))
461 } else {
462 Err(NanonisError::Protocol(
463 "Invalid limits response".to_string(),
464 ))
465 }
466 }
467}