Skip to main content

nanonis_rs/client/lockin/
mod.rs

1mod types;
2pub use types::*;
3
4use super::NanonisClient;
5use crate::error::NanonisError;
6use crate::types::NanonisValue;
7
8impl NanonisClient {
9    // ==================== Modulator Methods ====================
10
11    /// Turn the specified Lock-In modulator on or off.
12    ///
13    /// # Arguments
14    /// * `modulator_num` - Modulator number (1-8)
15    /// * `on` - `true` to turn on, `false` to turn off
16    ///
17    /// # Errors
18    /// Returns `NanonisError` if communication fails.
19    ///
20    /// # Examples
21    /// ```no_run
22    /// use nanonis_rs::NanonisClient;
23    ///
24    /// let mut client = NanonisClient::new("127.0.0.1", 6501)?;
25    /// client.lockin_mod_on_off_set(1, true)?; // Turn on modulator 1
26    /// # Ok::<(), Box<dyn std::error::Error>>(())
27    /// ```
28    pub fn lockin_mod_on_off_set(
29        &mut self,
30        modulator_num: i32,
31        on: bool,
32    ) -> Result<(), NanonisError> {
33        let on_flag = if on { 1u32 } else { 0u32 };
34        self.quick_send(
35            "LockIn.ModOnOffSet",
36            vec![NanonisValue::I32(modulator_num), NanonisValue::U32(on_flag)],
37            vec!["i", "I"],
38            vec![],
39        )?;
40        Ok(())
41    }
42
43    /// Get the on/off status of the specified Lock-In modulator.
44    ///
45    /// # Arguments
46    /// * `modulator_num` - Modulator number (1-8)
47    ///
48    /// # Returns
49    /// `true` if modulator is on, `false` if off.
50    ///
51    /// # Errors
52    /// Returns `NanonisError` if communication fails.
53    ///
54    /// # Examples
55    /// ```no_run
56    /// use nanonis_rs::NanonisClient;
57    ///
58    /// let mut client = NanonisClient::new("127.0.0.1", 6501)?;
59    /// let is_on = client.lockin_mod_on_off_get(1)?;
60    /// println!("Modulator 1 is {}", if is_on { "on" } else { "off" });
61    /// # Ok::<(), Box<dyn std::error::Error>>(())
62    /// ```
63    pub fn lockin_mod_on_off_get(&mut self, modulator_num: i32) -> Result<bool, NanonisError> {
64        let result = self.quick_send(
65            "LockIn.ModOnOffGet",
66            vec![NanonisValue::I32(modulator_num)],
67            vec!["i"],
68            vec!["I"],
69        )?;
70        if let Some(val) = result.first() {
71            Ok(val.as_u32()? != 0)
72        } else {
73            Err(NanonisError::Protocol("Invalid response".to_string()))
74        }
75    }
76
77    /// Set the modulated signal of the specified Lock-In modulator.
78    ///
79    /// # Arguments
80    /// * `modulator_num` - Modulator number (1-8)
81    /// * `signal_index` - Signal index (0-127)
82    ///
83    /// # Errors
84    /// Returns `NanonisError` if communication fails.
85    ///
86    /// # Examples
87    /// ```no_run
88    /// use nanonis_rs::NanonisClient;
89    ///
90    /// let mut client = NanonisClient::new("127.0.0.1", 6501)?;
91    /// client.lockin_mod_signal_set(1, 14)?; // Set modulator 1 to signal 14
92    /// # Ok::<(), Box<dyn std::error::Error>>(())
93    /// ```
94    pub fn lockin_mod_signal_set(
95        &mut self,
96        modulator_num: i32,
97        signal_index: i32,
98    ) -> Result<(), NanonisError> {
99        self.quick_send(
100            "LockIn.ModSignalSet",
101            vec![
102                NanonisValue::I32(modulator_num),
103                NanonisValue::I32(signal_index),
104            ],
105            vec!["i", "i"],
106            vec![],
107        )?;
108        Ok(())
109    }
110
111    /// Get the modulated signal index of the specified Lock-In modulator.
112    ///
113    /// # Arguments
114    /// * `modulator_num` - Modulator number (1-8)
115    ///
116    /// # Returns
117    /// Signal index (0-127).
118    ///
119    /// # Errors
120    /// Returns `NanonisError` if communication fails.
121    pub fn lockin_mod_signal_get(&mut self, modulator_num: i32) -> Result<i32, NanonisError> {
122        let result = self.quick_send(
123            "LockIn.ModSignalGet",
124            vec![NanonisValue::I32(modulator_num)],
125            vec!["i"],
126            vec!["i"],
127        )?;
128        if let Some(val) = result.first() {
129            Ok(val.as_i32()?)
130        } else {
131            Err(NanonisError::Protocol("Invalid response".to_string()))
132        }
133    }
134
135    /// Set the phase register index of the specified Lock-In modulator.
136    ///
137    /// # Arguments
138    /// * `modulator_num` - Modulator number (1-8)
139    /// * `phase_register_index` - Phase register index (1-8)
140    ///
141    /// # Errors
142    /// Returns `NanonisError` if communication fails.
143    ///
144    /// # Examples
145    /// ```no_run
146    /// use nanonis_rs::NanonisClient;
147    ///
148    /// let mut client = NanonisClient::new("127.0.0.1", 6501)?;
149    /// client.lockin_mod_phas_reg_set(1, 1)?; // Assign modulator 1 to phase register 1
150    /// # Ok::<(), Box<dyn std::error::Error>>(())
151    /// ```
152    pub fn lockin_mod_phas_reg_set(
153        &mut self,
154        modulator_num: i32,
155        phase_register_index: i32,
156    ) -> Result<(), NanonisError> {
157        self.quick_send(
158            "LockIn.ModPhasRegSet",
159            vec![
160                NanonisValue::I32(modulator_num),
161                NanonisValue::I32(phase_register_index),
162            ],
163            vec!["i", "i"],
164            vec![],
165        )?;
166        Ok(())
167    }
168
169    /// Get the phase register index of the specified Lock-In modulator.
170    ///
171    /// # Arguments
172    /// * `modulator_num` - Modulator number (1-8)
173    ///
174    /// # Returns
175    /// Phase register index (1-8).
176    pub fn lockin_mod_phas_reg_get(&mut self, modulator_num: i32) -> Result<i32, NanonisError> {
177        let result = self.quick_send(
178            "LockIn.ModPhasRegGet",
179            vec![NanonisValue::I32(modulator_num)],
180            vec!["i"],
181            vec!["i"],
182        )?;
183        if let Some(val) = result.first() {
184            Ok(val.as_i32()?)
185        } else {
186            Err(NanonisError::Protocol("Invalid response".to_string()))
187        }
188    }
189
190    /// Set the harmonic of the specified Lock-In modulator.
191    ///
192    /// # Arguments
193    /// * `modulator_num` - Modulator number (1-8)
194    /// * `harmonic` - Harmonic number (1 = base frequency)
195    ///
196    /// # Errors
197    /// Returns `NanonisError` if communication fails.
198    pub fn lockin_mod_harmonic_set(
199        &mut self,
200        modulator_num: i32,
201        harmonic: i32,
202    ) -> Result<(), NanonisError> {
203        self.quick_send(
204            "LockIn.ModHarmonicSet",
205            vec![
206                NanonisValue::I32(modulator_num),
207                NanonisValue::I32(harmonic),
208            ],
209            vec!["i", "i"],
210            vec![],
211        )?;
212        Ok(())
213    }
214
215    /// Get the harmonic of the specified Lock-In modulator.
216    ///
217    /// # Arguments
218    /// * `modulator_num` - Modulator number (1-8)
219    ///
220    /// # Returns
221    /// Harmonic number (1 = base frequency).
222    pub fn lockin_mod_harmonic_get(&mut self, modulator_num: i32) -> Result<i32, NanonisError> {
223        let result = self.quick_send(
224            "LockIn.ModHarmonicGet",
225            vec![NanonisValue::I32(modulator_num)],
226            vec!["i"],
227            vec!["i"],
228        )?;
229        if let Some(val) = result.first() {
230            Ok(val.as_i32()?)
231        } else {
232            Err(NanonisError::Protocol("Invalid response".to_string()))
233        }
234    }
235
236    /// Set the modulation phase offset of the specified Lock-In modulator.
237    ///
238    /// # Arguments
239    /// * `modulator_num` - Modulator number (1-8)
240    /// * `phase_deg` - Phase offset in degrees
241    ///
242    /// # Errors
243    /// Returns `NanonisError` if communication fails.
244    pub fn lockin_mod_phas_set(
245        &mut self,
246        modulator_num: i32,
247        phase_deg: f32,
248    ) -> Result<(), NanonisError> {
249        self.quick_send(
250            "LockIn.ModPhasSet",
251            vec![
252                NanonisValue::I32(modulator_num),
253                NanonisValue::F32(phase_deg),
254            ],
255            vec!["i", "f"],
256            vec![],
257        )?;
258        Ok(())
259    }
260
261    /// Get the modulation phase offset of the specified Lock-In modulator.
262    ///
263    /// # Arguments
264    /// * `modulator_num` - Modulator number (1-8)
265    ///
266    /// # Returns
267    /// Phase offset in degrees.
268    pub fn lockin_mod_phas_get(&mut self, modulator_num: i32) -> Result<f32, NanonisError> {
269        let result = self.quick_send(
270            "LockIn.ModPhasGet",
271            vec![NanonisValue::I32(modulator_num)],
272            vec!["i"],
273            vec!["f"],
274        )?;
275        if let Some(val) = result.first() {
276            Ok(val.as_f32()?)
277        } else {
278            Err(NanonisError::Protocol("Invalid response".to_string()))
279        }
280    }
281
282    /// Set the modulation amplitude of the specified Lock-In modulator.
283    ///
284    /// # Arguments
285    /// * `modulator_num` - Modulator number (1-8)
286    /// * `amplitude` - Modulation amplitude
287    ///
288    /// # Errors
289    /// Returns `NanonisError` if communication fails.
290    pub fn lockin_mod_amp_set(
291        &mut self,
292        modulator_num: i32,
293        amplitude: f32,
294    ) -> Result<(), NanonisError> {
295        self.quick_send(
296            "LockIn.ModAmpSet",
297            vec![
298                NanonisValue::I32(modulator_num),
299                NanonisValue::F32(amplitude),
300            ],
301            vec!["i", "f"],
302            vec![],
303        )?;
304        Ok(())
305    }
306
307    /// Get the modulation amplitude of the specified Lock-In modulator.
308    ///
309    /// # Arguments
310    /// * `modulator_num` - Modulator number (1-8)
311    ///
312    /// # Returns
313    /// Modulation amplitude.
314    pub fn lockin_mod_amp_get(&mut self, modulator_num: i32) -> Result<f32, NanonisError> {
315        let result = self.quick_send(
316            "LockIn.ModAmpGet",
317            vec![NanonisValue::I32(modulator_num)],
318            vec!["i"],
319            vec!["f"],
320        )?;
321        if let Some(val) = result.first() {
322            Ok(val.as_f32()?)
323        } else {
324            Err(NanonisError::Protocol("Invalid response".to_string()))
325        }
326    }
327
328    /// Set the frequency of the specified Lock-In phase register/modulator.
329    ///
330    /// # Arguments
331    /// * `modulator_num` - Phase register/modulator number (1-8)
332    /// * `frequency_hz` - Frequency in Hz
333    ///
334    /// # Errors
335    /// Returns `NanonisError` if communication fails.
336    ///
337    /// # Examples
338    /// ```no_run
339    /// use nanonis_rs::NanonisClient;
340    ///
341    /// let mut client = NanonisClient::new("127.0.0.1", 6501)?;
342    /// client.lockin_mod_phas_freq_set(1, 1000.0)?; // Set 1kHz
343    /// # Ok::<(), Box<dyn std::error::Error>>(())
344    /// ```
345    pub fn lockin_mod_phas_freq_set(
346        &mut self,
347        modulator_num: i32,
348        frequency_hz: f64,
349    ) -> Result<(), NanonisError> {
350        self.quick_send(
351            "LockIn.ModPhasFreqSet",
352            vec![
353                NanonisValue::I32(modulator_num),
354                NanonisValue::F64(frequency_hz),
355            ],
356            vec!["i", "d"],
357            vec![],
358        )?;
359        Ok(())
360    }
361
362    /// Get the frequency of the specified Lock-In phase register/modulator.
363    ///
364    /// # Arguments
365    /// * `modulator_num` - Phase register/modulator number (1-8)
366    ///
367    /// # Returns
368    /// Frequency in Hz.
369    pub fn lockin_mod_phas_freq_get(&mut self, modulator_num: i32) -> Result<f64, NanonisError> {
370        let result = self.quick_send(
371            "LockIn.ModPhasFreqGet",
372            vec![NanonisValue::I32(modulator_num)],
373            vec!["i"],
374            vec!["d"],
375        )?;
376        if let Some(val) = result.first() {
377            Ok(val.as_f64()?)
378        } else {
379            Err(NanonisError::Protocol("Invalid response".to_string()))
380        }
381    }
382
383    // ==================== Demodulator Methods ====================
384
385    /// Set the demodulated signal of the specified Lock-In demodulator.
386    ///
387    /// # Arguments
388    /// * `demodulator_num` - Demodulator number (1-8)
389    /// * `signal_index` - Signal index (0-127)
390    ///
391    /// # Errors
392    /// Returns `NanonisError` if communication fails.
393    pub fn lockin_demod_signal_set(
394        &mut self,
395        demodulator_num: i32,
396        signal_index: i32,
397    ) -> Result<(), NanonisError> {
398        self.quick_send(
399            "LockIn.DemodSignalSet",
400            vec![
401                NanonisValue::I32(demodulator_num),
402                NanonisValue::I32(signal_index),
403            ],
404            vec!["i", "i"],
405            vec![],
406        )?;
407        Ok(())
408    }
409
410    /// Get the demodulated signal index of the specified Lock-In demodulator.
411    ///
412    /// # Arguments
413    /// * `demodulator_num` - Demodulator number (1-8)
414    ///
415    /// # Returns
416    /// Signal index (0-127).
417    pub fn lockin_demod_signal_get(&mut self, demodulator_num: i32) -> Result<i32, NanonisError> {
418        let result = self.quick_send(
419            "LockIn.DemodSignalGet",
420            vec![NanonisValue::I32(demodulator_num)],
421            vec!["i"],
422            vec!["i"],
423        )?;
424        if let Some(val) = result.first() {
425            Ok(val.as_i32()?)
426        } else {
427            Err(NanonisError::Protocol("Invalid response".to_string()))
428        }
429    }
430
431    /// Set the harmonic of the specified Lock-In demodulator.
432    ///
433    /// # Arguments
434    /// * `demodulator_num` - Demodulator number (1-8)
435    /// * `harmonic` - Harmonic number (1 = base frequency)
436    pub fn lockin_demod_harmonic_set(
437        &mut self,
438        demodulator_num: i32,
439        harmonic: i32,
440    ) -> Result<(), NanonisError> {
441        self.quick_send(
442            "LockIn.DemodHarmonicSet",
443            vec![
444                NanonisValue::I32(demodulator_num),
445                NanonisValue::I32(harmonic),
446            ],
447            vec!["i", "i"],
448            vec![],
449        )?;
450        Ok(())
451    }
452
453    /// Get the harmonic of the specified Lock-In demodulator.
454    ///
455    /// # Arguments
456    /// * `demodulator_num` - Demodulator number (1-8)
457    ///
458    /// # Returns
459    /// Harmonic number (1 = base frequency).
460    pub fn lockin_demod_harmonic_get(&mut self, demodulator_num: i32) -> Result<i32, NanonisError> {
461        let result = self.quick_send(
462            "LockIn.DemodHarmonicGet",
463            vec![NanonisValue::I32(demodulator_num)],
464            vec!["i"],
465            vec!["i"],
466        )?;
467        if let Some(val) = result.first() {
468            Ok(val.as_i32()?)
469        } else {
470            Err(NanonisError::Protocol("Invalid response".to_string()))
471        }
472    }
473
474    /// Set the high-pass filter properties for the specified demodulator.
475    ///
476    /// # Arguments
477    /// * `demodulator_num` - Demodulator number (1-8)
478    /// * `filter_order` - Filter order (-1=no change, 0=off, 1-8=active)
479    /// * `cutoff_hz` - Cutoff frequency in Hz (0=no change)
480    pub fn lockin_demod_hp_filter_set(
481        &mut self,
482        demodulator_num: i32,
483        filter_order: i32,
484        cutoff_hz: f32,
485    ) -> Result<(), NanonisError> {
486        self.quick_send(
487            "LockIn.DemodHPFilterSet",
488            vec![
489                NanonisValue::I32(demodulator_num),
490                NanonisValue::I32(filter_order),
491                NanonisValue::F32(cutoff_hz),
492            ],
493            vec!["i", "i", "f"],
494            vec![],
495        )?;
496        Ok(())
497    }
498
499    /// Get the high-pass filter properties for the specified demodulator.
500    ///
501    /// # Arguments
502    /// * `demodulator_num` - Demodulator number (1-8)
503    ///
504    /// # Returns
505    /// A [`FilterConfig`] with order and cutoff frequency.
506    pub fn lockin_demod_hp_filter_get(
507        &mut self,
508        demodulator_num: i32,
509    ) -> Result<FilterConfig, NanonisError> {
510        let result = self.quick_send(
511            "LockIn.DemodHPFilterGet",
512            vec![NanonisValue::I32(demodulator_num)],
513            vec!["i"],
514            vec!["i", "f"],
515        )?;
516        if result.len() >= 2 {
517            Ok(FilterConfig {
518                order: result[0].as_i32()?,
519                cutoff_hz: result[1].as_f32()?,
520            })
521        } else {
522            Err(NanonisError::Protocol("Invalid response".to_string()))
523        }
524    }
525
526    /// Set the low-pass filter properties for the specified demodulator.
527    ///
528    /// # Arguments
529    /// * `demodulator_num` - Demodulator number (1-8)
530    /// * `filter_order` - Filter order (-1=no change, 0=off, 1-8=active)
531    /// * `cutoff_hz` - Cutoff frequency in Hz (0=no change)
532    pub fn lockin_demod_lp_filter_set(
533        &mut self,
534        demodulator_num: i32,
535        filter_order: i32,
536        cutoff_hz: f32,
537    ) -> Result<(), NanonisError> {
538        self.quick_send(
539            "LockIn.DemodLPFilterSet",
540            vec![
541                NanonisValue::I32(demodulator_num),
542                NanonisValue::I32(filter_order),
543                NanonisValue::F32(cutoff_hz),
544            ],
545            vec!["i", "i", "f"],
546            vec![],
547        )?;
548        Ok(())
549    }
550
551    /// Get the low-pass filter properties for the specified demodulator.
552    ///
553    /// # Arguments
554    /// * `demodulator_num` - Demodulator number (1-8)
555    ///
556    /// # Returns
557    /// A [`FilterConfig`] with order and cutoff frequency.
558    pub fn lockin_demod_lp_filter_get(
559        &mut self,
560        demodulator_num: i32,
561    ) -> Result<FilterConfig, NanonisError> {
562        let result = self.quick_send(
563            "LockIn.DemodLPFilterGet",
564            vec![NanonisValue::I32(demodulator_num)],
565            vec!["i"],
566            vec!["i", "f"],
567        )?;
568        if result.len() >= 2 {
569            Ok(FilterConfig {
570                order: result[0].as_i32()?,
571                cutoff_hz: result[1].as_f32()?,
572            })
573        } else {
574            Err(NanonisError::Protocol("Invalid response".to_string()))
575        }
576    }
577
578    /// Set the phase register index of the specified Lock-In demodulator.
579    ///
580    /// # Arguments
581    /// * `demodulator_num` - Demodulator number (1-8)
582    /// * `phase_register_index` - Phase register index (1-8)
583    pub fn lockin_demod_phas_reg_set(
584        &mut self,
585        demodulator_num: i32,
586        phase_register_index: i32,
587    ) -> Result<(), NanonisError> {
588        self.quick_send(
589            "LockIn.DemodPhasRegSet",
590            vec![
591                NanonisValue::I32(demodulator_num),
592                NanonisValue::I32(phase_register_index),
593            ],
594            vec!["i", "i"],
595            vec![],
596        )?;
597        Ok(())
598    }
599
600    /// Get the phase register index of the specified Lock-In demodulator.
601    ///
602    /// # Arguments
603    /// * `demodulator_num` - Demodulator number (1-8)
604    ///
605    /// # Returns
606    /// Phase register index (1-8).
607    pub fn lockin_demod_phas_reg_get(&mut self, demodulator_num: i32) -> Result<i32, NanonisError> {
608        let result = self.quick_send(
609            "LockIn.DemodPhasRegGet",
610            vec![NanonisValue::I32(demodulator_num)],
611            vec!["i"],
612            vec!["i"],
613        )?;
614        if let Some(val) = result.first() {
615            Ok(val.as_i32()?)
616        } else {
617            Err(NanonisError::Protocol("Invalid response".to_string()))
618        }
619    }
620
621    /// Set the reference phase of the specified Lock-In demodulator.
622    ///
623    /// # Arguments
624    /// * `demodulator_num` - Demodulator number (1-8)
625    /// * `phase_deg` - Reference phase in degrees
626    pub fn lockin_demod_phas_set(
627        &mut self,
628        demodulator_num: i32,
629        phase_deg: f32,
630    ) -> Result<(), NanonisError> {
631        self.quick_send(
632            "LockIn.DemodPhasSet",
633            vec![
634                NanonisValue::I32(demodulator_num),
635                NanonisValue::F32(phase_deg),
636            ],
637            vec!["i", "f"],
638            vec![],
639        )?;
640        Ok(())
641    }
642
643    /// Get the reference phase of the specified Lock-In demodulator.
644    ///
645    /// # Arguments
646    /// * `demodulator_num` - Demodulator number (1-8)
647    ///
648    /// # Returns
649    /// Reference phase in degrees.
650    pub fn lockin_demod_phas_get(&mut self, demodulator_num: i32) -> Result<f32, NanonisError> {
651        let result = self.quick_send(
652            "LockIn.DemodPhasGet",
653            vec![NanonisValue::I32(demodulator_num)],
654            vec!["i"],
655            vec!["f"],
656        )?;
657        if let Some(val) = result.first() {
658            Ok(val.as_f32()?)
659        } else {
660            Err(NanonisError::Protocol("Invalid response".to_string()))
661        }
662    }
663
664    /// Set the sync filter on/off for the specified demodulator.
665    ///
666    /// The synchronous filter suppresses harmonic components very well
667    /// but only updates after each period of the demodulation frequency.
668    ///
669    /// # Arguments
670    /// * `demodulator_num` - Demodulator number (1-8)
671    /// * `on` - `true` to enable sync filter, `false` to disable
672    pub fn lockin_demod_sync_filter_set(
673        &mut self,
674        demodulator_num: i32,
675        on: bool,
676    ) -> Result<(), NanonisError> {
677        let on_flag = if on { 1u32 } else { 0u32 };
678        self.quick_send(
679            "LockIn.DemodSyncFilterSet",
680            vec![
681                NanonisValue::I32(demodulator_num),
682                NanonisValue::U32(on_flag),
683            ],
684            vec!["i", "I"],
685            vec![],
686        )?;
687        Ok(())
688    }
689
690    /// Get the sync filter status for the specified demodulator.
691    ///
692    /// # Arguments
693    /// * `demodulator_num` - Demodulator number (1-8)
694    ///
695    /// # Returns
696    /// `true` if sync filter is on.
697    pub fn lockin_demod_sync_filter_get(
698        &mut self,
699        demodulator_num: i32,
700    ) -> Result<bool, NanonisError> {
701        let result = self.quick_send(
702            "LockIn.DemodSyncFilterGet",
703            vec![NanonisValue::I32(demodulator_num)],
704            vec!["i"],
705            vec!["I"],
706        )?;
707        if let Some(val) = result.first() {
708            Ok(val.as_u32()? != 0)
709        } else {
710            Err(NanonisError::Protocol("Invalid response".to_string()))
711        }
712    }
713
714    /// Set the RT signals mode for the specified demodulator.
715    ///
716    /// # Arguments
717    /// * `demodulator_num` - Demodulator number (1-8)
718    /// * `mode` - [`RTSignalMode::XY`] or [`RTSignalMode::RPhi`]
719    pub fn lockin_demod_rt_signals_set(
720        &mut self,
721        demodulator_num: i32,
722        mode: RTSignalMode,
723    ) -> Result<(), NanonisError> {
724        self.quick_send(
725            "LockIn.DemodRTSignalsSet",
726            vec![
727                NanonisValue::I32(demodulator_num),
728                NanonisValue::U32(mode.into()),
729            ],
730            vec!["i", "I"],
731            vec![],
732        )?;
733        Ok(())
734    }
735
736    /// Get the RT signals mode for the specified demodulator.
737    ///
738    /// # Arguments
739    /// * `demodulator_num` - Demodulator number (1-8)
740    ///
741    /// # Returns
742    /// The [`RTSignalMode`] (X/Y or R/phi).
743    pub fn lockin_demod_rt_signals_get(
744        &mut self,
745        demodulator_num: i32,
746    ) -> Result<RTSignalMode, NanonisError> {
747        let result = self.quick_send(
748            "LockIn.DemodRTSignalsGet",
749            vec![NanonisValue::I32(demodulator_num)],
750            vec!["i"],
751            vec!["I"],
752        )?;
753        if let Some(val) = result.first() {
754            RTSignalMode::try_from(val.as_u32()?)
755        } else {
756            Err(NanonisError::Protocol("Invalid response".to_string()))
757        }
758    }
759}