File Coverage

blib/lib/Lab/Moose/Instrument/SignalRecovery7265.pm
Criterion Covered Total %
statement 32 453 7.0
branch 0 214 0.0
condition 0 111 0.0
subroutine 11 61 18.0
pod 27 46 58.7
total 70 885 7.9


line stmt bran cond sub pod time code
1             package Lab::Moose::Instrument::SignalRecovery7265;
2             $Lab::Moose::Instrument::SignalRecovery7265::VERSION = '3.881';
3             #ABSTRACT: Model 7265 Lock-In Amplifier
4              
5 1     1   2514 use v5.20;
  1         4  
6              
7 1     1   6 use strict;
  1         2  
  1         28  
8 1     1   6 use Moose;
  1         3  
  1         9  
9 1     1   7649 use Moose::Util::TypeConstraints qw/enum/;
  1         3  
  1         12  
10 1     1   552 use MooseX::Params::Validate;
  1         3  
  1         12  
11 1         85 use Lab::Moose::Instrument qw/
12             validated_getter
13             validated_setter
14             validated_no_param_setter
15             setter_params
16 1     1   577 /;
  1         4  
17 1     1   7 use Lab::Moose::Instrument::Cache;
  1         2  
  1         10  
18 1     1   679 use Carp;
  1         3  
  1         73  
19 1     1   9 use namespace::autoclean;
  1         4  
  1         10  
20 1     1   105 use Time::HiRes qw/time usleep/;
  1         3  
  1         18  
21 1     1   167 use Lab::Moose 'linspace';
  1         2  
  1         10  
22              
23             extends 'Lab::Moose::Instrument';
24              
25             has max_units => (
26             is => 'ro',
27             isa => 'Num',
28             default => 1,
29             );
30              
31             has min_units => (
32             is => 'ro',
33             isa => 'Num',
34             default => 0,
35             );
36              
37             has max_units_per_second => (
38             is => 'ro',
39             isa => 'Num',
40             default => 1,
41             );
42              
43             has max_units_per_step => (
44             is => 'ro',
45             isa => 'Num',
46             default => 0.01,
47             );
48              
49             has source_level_timestamp => (
50             is => 'rw',
51             isa => 'Num',
52             init_arg => undef
53             );
54              
55             sub BUILD {
56 0     0 0   my $self = shift;
57 0           $self->get_id();
58             }
59              
60              
61             sub reset {
62 0     0 0   my $self = shift;
63 0           $self->write(command => "ADF 1");
64             }
65              
66             cache id => (getter => 'get_id');
67              
68             sub get_id {
69 0     0 0   my $self = shift;
70 0           return $self->cached_id($self->query( command => "ID" ));
71             }
72              
73             # ------------------ SIGNAL CHANNEL -------------------------
74              
75              
76             cache imode => (getter => 'get_imode');
77              
78             sub set_imode { # basic setting
79 0     0 1   my ( $self, $value, %args ) = validated_setter( \@_,
80             value => { isa => 'Int' }
81             );
82              
83 0 0 0       if ( defined $value and ( $value == 0 || $value == 1 || $value == 2 ) ) {
      0        
84 0           $self->write(command => sprintf("IMODE %d", $value));
85 0           $self->cached_imode($value);
86             } else {
87 0           croak "\nSIGNAL RECOVERY 7265:\nunexpected value for IMODE in sub set_imode. Expected values are:\n 0 --> Current Mode OFF\n 1 --> High Bandwidth Current Mode\n 2 --> Low Noise Current Mode\n";
88             }
89             }
90              
91             sub get_imode {
92 0     0 0   my ( $self, %args ) = validated_getter( \@_ );
93              
94 0           return $self->cached_imode($self->query(command => "IMODE", %args ));
95             }
96              
97              
98             cache vmode => (getter => 'get_vmode');
99              
100             sub set_vmode {
101 0     0 1   my ( $self, $value, %args ) = validated_setter( \@_,
102             value => { isa => 'Int' }
103             );
104              
105 0 0 0       if ( defined $value
      0        
106             and ( $value == 0 || $value == 1 || $value == 2 || $value == 3 ) ) {
107 0           $self->write(command => sprintf( "VMODE %d", $value ));
108 0           $self->cached_vmode($value);
109             } else {
110 0           croak "\nSIGNAL RECOVERY 726x:\nunexpected value for VMODE in sub set_vmode. Expected values are:\n 0 --> Both inputs grounded (testmode)\n 1 --> A input only\n 2 --> -B input only\n 3 --> A-B differential mode\n";
111             }
112             }
113              
114             sub get_vmode {
115 0     0 0   my ( $self, %args ) = validated_getter( \@_ );
116              
117 0           return $self->cached_vmode($self->query(command => "VMODE", %args ));
118             }
119              
120              
121             cache fet => (getter => 'get_fet');
122              
123             sub set_fet {
124 0     0 1   my ( $self, $value, %args ) = validated_setter( \@_,
125             value => { isa => 'Int' }
126             );
127              
128 0 0 0       if ( defined $value and ( $value == 0 || $value == 1 ) ) {
      0        
129 0           $self->write(command => sprintf( "FET %d", $value ));
130 0           $self->cached_fet($value);
131             } else {
132 0           croak "\nSIGNAL RECOVERY 726x:\nunexpected value in sub set_fet. Expected values are:\n 0 --> Bipolar device, 10 kOhm input impedance, 2nV/sqrt(Hz) voltage noise at 1 kHz\n 1 --> FET, 10 MOhm input impedance, 5nV/sqrt(Hz) voltage noise at 1 kHz\n";
133             }
134             }
135              
136             sub get_fet {
137 0     0 0   my ( $self, %args ) = validated_getter( \@_ );
138              
139 0           return $self->cached_fet($self->query(command => "FET", %args ));
140             }
141              
142              
143             cache float => (getter => 'get_float');
144              
145             sub set_float {
146 0     0 1   my ( $self, $value, %args ) = validated_setter( \@_,
147             value => { isa => 'Int' }
148             );
149              
150 0 0 0       if ( defined $value and ( $value == 0 || $value == 1 ) ) {
      0        
151 0           $self->write(command => sprintf( "FLOAT %d", $value ));
152 0           $self->cached_float($value);
153             } else {
154 0           croak "\nSIGNAL RECOVERY 726x:\nunexpected value in sub set_float. Expected values are:\n 0 --> input conector shield set to GROUND\n 1 --> input conector shield set to FLOAT\n";
155             }
156             }
157              
158             sub get_float {
159 0     0 0   my ( $self, %args ) = validated_getter( \@_ );
160              
161 0           return $self->cached_float($self->query(command => "FLOAT", %args ));
162             }
163              
164              
165             cache cp => (getter => 'get_cp');
166              
167             sub set_cp {
168 0     0 1   my ( $self, $value, %args ) = validated_setter( \@_,
169             value => { isa => 'Int' }
170             );
171              
172 0 0 0       if ( defined $value and ( $value == 0 || $value == 1 ) ) {
      0        
173 0           $self->write(command => sprintf( "CP %d", $value ));
174 0           $self->cached_cp($value);
175             } else {
176 0           croak "\nSIGNAL RECOVERY 726x:\nunexpected value in sub set_cp. Expected values are:\n 0 --> input coupling mode AC\n 1 --> input coupling mode DC\n";
177             }
178             }
179              
180             sub get_cp {
181 0     0 0   my ( $self, %args ) = validated_getter( \@_ );
182              
183 0           return $self->cached_cp($self->query(command => "CP", %args ));
184             }
185              
186              
187             cache sen => (getter => 'get_sen');
188              
189             sub set_sen {
190 0     0 1   my ( $self, $value, %args ) = validated_setter( \@_ );
191              
192 0           my @matrix = (
193             {
194             2e-9 => 1,
195             5e-9 => 2,
196             10e-9 => 3,
197             2e-8 => 4,
198             5e-8 => 5,
199             10e-8 => 6,
200             2e-7 => 7,
201             5e-7 => 8,
202             10e-7 => 9,
203             2e-6 => 10,
204             5e-6 => 11,
205             10e-6 => 12,
206             2e-5 => 13,
207             5e-5 => 14,
208             10e-5 => 15,
209             2e-4 => 16,
210             5e-4 => 17,
211             10e-4 => 18,
212             2e-3 => 19,
213             5e-3 => 20,
214             10e-3 => 21,
215             2e-2 => 22,
216             5e-2 => 23,
217             10e-2 => 24,
218             2e-1 => 25,
219             5e-1 => 26,
220             10e-1 => 27
221             },
222             {
223             2e-15 => 1,
224             5e-15 => 2,
225             10e-15 => 3,
226             2e-14 => 4,
227             5e-14 => 5,
228             10e-14 => 6,
229             2e-13 => 7,
230             5e-13 => 8,
231             10e-13 => 9,
232             2e-12 => 10,
233             5e-12 => 11,
234             10e-12 => 12,
235             2e-11 => 13,
236             5e-11 => 14,
237             10e-11 => 15,
238             2e-10 => 16,
239             5e-10 => 17,
240             10e-10 => 18,
241             2e-9 => 19,
242             5e-9 => 20,
243             10e-9 => 21,
244             2e-8 => 22,
245             5e-8 => 23,
246             10e-8 => 24,
247             2e-7 => 25,
248             5e-7 => 26,
249             10e-7 => 27
250             },
251             {
252             2e-15 => 7,
253             5e-15 => 8,
254             10e-15 => 9,
255             2e-14 => 10,
256             5e-14 => 11,
257             10e-14 => 12,
258             2e-13 => 13,
259             5e-13 => 14,
260             10e-13 => 15,
261             2e-12 => 16,
262             5e-12 => 17,
263             10e-12 => 18,
264             2e-11 => 19,
265             5e-11 => 20,
266             10e-11 => 21,
267             2e-10 => 22,
268             5e-10 => 23,
269             10e-10 => 24,
270             2e-9 => 25,
271             5e-9 => 26,
272             10e-9 => 27
273             }
274             );
275              
276 0           my $imode = $self->cached_imode();
277              
278             # SENSITIVITY (IMODE == 0) --> 2nV, 5nV, 10nV, 20nV, 50nV, 100nV, 200nV, 500nV, 1uV, 2uV, 5uV, 10uV, 20uV, 50uV, 100uV, 200uV, 500uV, 1mV, 2mV, 5mV, 10mV, 20mV, 50mV, 100mV, 200mV, 500mV, 1V\n
279             # SENSITIVITY (IMODE == 1) --> 2fA, 5fA, 10fA, 20fA, 50fA, 100fA, 200fA, 500fA, 1pA, 2pA, 5pA, 10pA, 20pA, 50pA, 100pA, 200pA, 500pA, 1nA, 2nA, 5nA, 10nA, 20nA, 50nA, 100nA, 200nA, 500nA, 1uA\n
280             # SENSITIVITY (IMODE == 2) --> 2fA, 5fA, 10fA, 20fA, 50fA, 100fA, 200fA, 500fA, 1pA, 2pA, 5pA, 10pA, 20pA, 50pA, 100pA, 200pA, 500pA, 1nA, 2nA, 5nA, 10nA\n
281              
282 0 0         if ( index( $value, "f" ) >= 0 ) {
    0          
    0          
    0          
    0          
283 0           $value *= 1e-15;
284             }
285             elsif ( index( $value, "p" ) >= 0 ) {
286 0           $value *= 1e-12;
287             }
288             elsif ( index( $value, "n" ) >= 0 ) {
289 0           $value *= 1e-9;
290             }
291             elsif ( index( $value, "u" ) >= 0 ) {
292 0           $value *= 1e-6;
293             }
294             elsif ( index( $value, "m" ) >= 0 ) {
295 0           $value *= 1e-3;
296             }
297              
298 0 0         if ( exists $matrix[$imode]->{$value} ) {
    0          
299 0           $self->write(command => sprintf( "SEN %d", $matrix[$imode]->{$value} ));
300 0           $self->cached_sen($matrix[$imode]->{$value})
301             }
302             elsif ( $value == "AUTO" ) {
303 0           $self->write(command => "AS");
304             }
305              
306             else {
307 0           croak "\nSIGNAL RECOVERY 726x:\nunexpected value for SENSITIVITY in sub set_sen. Expected values are: \n\n SENSITIVITY (IMODE == 0) --> 2nV, 5nV, 10nV, 20nV, 50nV, 100nV, 200nV, 500nV, 1uV, 2uV, 5uV, 10uV, 20uV, 50uV, 100uV, 200uV, 500uV, 1mV, 2mV, 5mV, 10mV, 20mV, 50mV, 100mV, 200mV, 500mV, 1V\n\n SENSITIVITY (IMODE == 1) --> 2fA, 5fA, 10fA, 20fA, 50fA, 100fA, 200fA, 500fA, 1pA, 2pA, 5pA, 10pA, 20pA, 50pA, 100pA, 200pA, 500pA, 1nA, 2nA, 5nA, 10nA, 20nA, 50nA, 100nA, 200nA, 500nA, 1uA\n\n SENSITIVITY (IMODE == 2) --> 2fA, 5fA, 10fA, 20fA, 50fA, 100fA, 200fA, 500fA, 1pA, 2pA, 5pA, 10pA, 20pA, 50pA, 100pA, 200pA, 500pA, 1nA, 2nA, 5nA, 10nA\n";
308             }
309             }
310              
311             sub get_sen {
312 0     0 0   my ( $self, %args ) = validated_getter( \@_ );
313              
314 0           my @matrix_reverse = (
315             [
316             2e-9, 5e-9, 10e-9, 2e-8, 5e-8, 10e-8, 2e-7, 5e-7,
317             10e-7, 2e-6, 5e-6, 10e-6, 2e-5, 5e-5, 10e-5, 2e-4,
318             5e-4, 10e-4, 2e-3, 5e-3, 10e-3, 2e-2, 5e-2, 10e-2,
319             2e-1, 5e-1, 10e-1
320             ],
321             [
322             2e-15, 5e-15, 10e-15, 2e-14, 5e-14, 10e-14, 2e-13, 5e-13,
323             10e-13, 2e-12, 5e-12, 10e-12, 2e-11, 5e-11, 10e-11, 2e-10,
324             5e-10, 10e-10, 2e-9, 5e-9, 10e-9, 2e-8, 5e-8, 10e-8,
325             2e-7, 5e-7, 10e-7
326             ],
327             [
328             2e-15, 5e-15, 10e-15, 2e-14, 5e-14, 10e-14, 2e-13, 5e-13,
329             10e-13, 2e-12, 5e-12, 10e-12, 2e-11, 5e-11, 10e-11, 2e-10,
330             5e-10, 10e-10, 2e-9, 5e-9, 10e-9
331             ]
332             );
333              
334 0           my $imode = $self->get_imode();
335              
336 0           return $matrix_reverse[$imode][ $self->cached_sen($self->query(command =>"SEN", %args)) - 1 ];
337             }
338              
339              
340             sub auto_sen {
341 0     0 1   my ( $self, $value, %args ) = validated_setter( \@_,
342             value => {isa => 'Num'}
343             );
344              
345 0           my @matrix = (
346             {
347             2e-9 => 1,
348             5e-9 => 2,
349             10e-9 => 3,
350             2e-8 => 4,
351             5e-8 => 5,
352             10e-8 => 6,
353             2e-7 => 7,
354             5e-7 => 8,
355             10e-7 => 9,
356             2e-6 => 10,
357             5e-6 => 11,
358             10e-6 => 12,
359             2e-5 => 13,
360             5e-5 => 14,
361             10e-5 => 15,
362             2e-4 => 16,
363             5e-4 => 17,
364             10e-4 => 18,
365             2e-3 => 19,
366             5e-3 => 20,
367             10e-3 => 21,
368             2e-2 => 22,
369             5e-2 => 23,
370             10e-2 => 24,
371             2e-1 => 25,
372             5e-1 => 26,
373             10e-1 => 27
374             },
375             {
376             2e-15 => 1,
377             5e-15 => 2,
378             10e-15 => 3,
379             2e-14 => 4,
380             5e-14 => 5,
381             10e-14 => 6,
382             2e-13 => 7,
383             5e-13 => 8,
384             10e-13 => 9,
385             2e-12 => 10,
386             5e-12 => 11,
387             10e-12 => 12,
388             2e-11 => 13,
389             5e-11 => 14,
390             10e-11 => 15,
391             2e-10 => 16,
392             5e-10 => 17,
393             10e-10 => 18,
394             2e-9 => 19,
395             5e-9 => 20,
396             10e-9 => 21,
397             2e-8 => 22,
398             5e-8 => 23,
399             10e-8 => 24,
400             2e-7 => 25,
401             5e-7 => 26,
402             10e-7 => 27
403             },
404             {
405             2e-15 => 7,
406             5e-15 => 8,
407             10e-15 => 9,
408             2e-14 => 10,
409             5e-14 => 11,
410             10e-14 => 12,
411             2e-13 => 13,
412             5e-13 => 14,
413             10e-13 => 15,
414             2e-12 => 16,
415             5e-12 => 17,
416             10e-12 => 18,
417             2e-11 => 19,
418             5e-11 => 20,
419             10e-11 => 21,
420             2e-10 => 22,
421             5e-10 => 23,
422             10e-10 => 24,
423             2e-9 => 25,
424             5e-9 => 26,
425             10e-9 => 27
426             }
427             );
428              
429 0           my $imode = $self->cached_imode();
430              
431             # SENSITIVITY (IMODE == 0) --> 2nV, 5nV, 10nV, 20nV, 50nV, 100nV, 200nV, 500nV, 1uV, 2uV, 5uV, 10uV, 20uV, 50uV, 100uV, 200uV, 500uV, 1mV, 2mV, 5mV, 10mV, 20mV, 50mV, 100mV, 200mV, 500mV, 1V\n
432             # SENSITIVITY (IMODE == 1) --> 2fA, 5fA, 10fA, 20fA, 50fA, 100fA, 200fA, 500fA, 1pA, 2pA, 5pA, 10pA, 20pA, 50pA, 100pA, 200pA, 500pA, 1nA, 2nA, 5nA, 10nA, 20nA, 50nA, 100nA, 200nA, 500nA, 1uA\n
433             # SENSITIVITY (IMODE == 2) --> 2fA, 5fA, 10fA, 20fA, 50fA, 100fA, 200fA, 500fA, 1pA, 2pA, 5pA, 10pA, 20pA, 50pA, 100pA, 200pA, 500pA, 1nA, 2nA, 5nA, 10nA\n
434              
435 0           my @vals = sort { $a <=> $b } keys(%{$matrix[$imode]});
  0            
  0            
436              
437 0 0         if ($value < 3*$vals[0]) {
    0          
438 0           $self->set_sen(value => $vals[0]);
439             }
440             elsif ($value >= 3*$vals[-1]) {
441 0           $self->set_sen(value => $vals[-1]);
442             } else {
443 0           foreach (0..$#vals-1) {
444 0 0 0       if ($value >= 3*$vals[$_] && $value < 3*$vals[$_+1]) {
445 0           $self->set_sen(value => $vals[$_+1]);
446             }
447              
448             }
449             }
450             }
451              
452              
453             cache acgain => (getter => 'get_acgain');
454              
455             sub set_acgain {
456 0     0 1   my ( $self, $value, %args ) = validated_setter( \@_,
457             value => { isa => 'Int' | 'Str'}
458             );
459              
460             # AC-GAIN == 0 --> 0 dB gain of the signal channel amplifier\n
461             # AC-GAIN == 1 --> 10 dB gain of the signal channel amplifier\n
462             # ...
463             # AC-GAIN == 9 --> 90 dB gain of the signal channel amplifier\n
464              
465 0 0 0       if ( defined $value
    0 0        
      0        
466             and int($value) == $value
467             and $value <= 9
468             and $value >= 0 ) {
469              
470 0           $self->write(command => sprintf( "ACGAIN %d", $value ));
471 0           $self->cached_acgain($value);
472             }
473             elsif ( $value eq "AUTO" ) {
474 0           $self->write(command => "AUTOMATIC 1");
475 0           $self->cached_acgain("AUTO");
476             }
477             else {
478 0           croak "\nSIGNAL RECOVERY 726x:\nunexpected value for AC-GAIN in sub set_acgain. Expected values are:\n AC-GAIN == 0 --> 0 dB gain of the signal channel amplifier\n AC-GAIN == 1 --> 10 dB gain of the signal channel amplifier\n ...\n AC-GAIN == 9 --> 90 dB gain of the signal channel amplifier\n";
479             }
480             }
481              
482             sub get_acgain {
483 0     0 0   my ( $self, %args ) = validated_getter( \@_ );
484              
485 0           return $self->cached_acgain($self->query(command => "ACGAIN", %args ));
486             }
487              
488              
489             cache linefilter => (getter => 'get_linefilter');
490              
491             sub set_linefilter {
492 0     0 1   my ( $self, $value, %args ) = validated_setter( \@_,
493             value => { isa => 'Int'},
494             linefrequency => { isa => enum([qw/50Hz 60Hz/])}
495             );
496              
497 0           my $linefrq = delete $args{linefrequeny};
498              
499 0 0         if ( not defined $linefrq ) { $linefrq = 1; } # 1-->50Hz
  0 0          
    0          
500 0           elsif ( $linefrq eq "50Hz" ) { $linefrq = 1; }
501 0           elsif ( $linefrq eq "60Hz" ) { $linefrq = 0; } # 0 --> 60Hz
502              
503             # LINE-FILTER == 0 --> OFF\n
504             # LINE-FILTER == 1 --> enable 50Hz/60Hz notch filter\n
505             # LINE-FILTER == 2 --> enable 100Hz/120Hz notch filter\n
506             # LINE-FILTER == 3 --> enable 50Hz/60Hz and 100Hz/120Hz notch filter\n
507              
508 0 0 0       if ( defined $value
      0        
509             and ( $value == 0 || $value == 1 || $value == 2 || $value == 3 ) ) {
510              
511 0           $self->write(command => sprintf( "LF %d, %d", $value, $linefrq ));
512 0           $self->cached_linefilter($value);
513             }
514             else {
515 0           croak "\nSIGNAL RECOVERY 726x:\nunexpected value for FILTER in sub set_linefilter. Expected values are:\n LINE-FILTER == 0 --> OFF\n LINE-FILTER == 1 --> enable 50Hz/60Hz notch filter\n LINE-FILTER == 2 --> enable 100Hz/120Hz notch filter\n LINE-FILTER == 3 --> enable 50Hz/60Hz and 100Hz/120Hz notch filter\n";
516             }
517             }
518              
519             sub get_linefilter {
520 0     0 0   my ( $self, %args ) = validated_getter( \@_ );
521              
522 0           return $self->cached_linefilter($self->query(command => "LF", %args ));
523             }
524              
525             # ------------------REFERENCE CHANNEL ---------------------------
526              
527              
528             cache refchannel => (getter => 'get_refchannel');
529              
530             sub set_refchannel {
531 0     0 1   my ( $self, $value, %args ) = validated_setter( \@_,
532             value => { isa => enum(["INT", "EXT LOGIC", "EXT"])}
533             );
534              
535             # INT --> internal reference input mode\n
536             # EXT LOGIC --> external rear panel TTL input\n
537             # EXT --> external front panel analog input\n
538              
539 0           $self->cached_refchannel($value); # Save the String value to the cache
540              
541 0 0         if ( $value eq "INT" ) { $value = 0; }
  0 0          
    0          
542 0           elsif ( $value eq "EXT LOGIC" ) { $value = 1; }
543 0           elsif ( $value eq "EXT" ) { $value = 2; }
544             else {
545 0           croak "\nSIGNAL RECOVERY 726x:\nunexpected value for REFERENCE CHANEL in sub set_refchennel. Expected values are:\n INT --> internal reference input mode\n EXT LOGIC --> external rear panel TTL input\n EXT --> external front panel analog input\n";
546             }
547              
548 0           $self->write(command => sprintf( "IE %d", $value ));
549             }
550              
551             sub get_refchannel {
552 0     0 0   my ( $self, %args ) = validated_getter( \@_ );
553              
554 0           my $result = $self->query(command => "IE", %args );
555              
556 0 0         if ( $result == 0 ) {
    0          
    0          
557 0           return $self->cached_refchannel('INT');
558             }
559             elsif ( $result == 1 ) {
560 0           return $self->cached_refchannel('EXT LOGIC');
561             }
562             elsif ( $result == 2 ) {
563 0           return $self->cached_refchannel('EXT');
564             }
565             }
566              
567              
568             sub autophase {
569 0     0 1   my ( $self, %args ) = validated_getter( \@_ );
570 0           $self->write(command => "AQN");
571 0           usleep( 5 * $self->get_tc() * 1e6 );
572             }
573              
574              
575             cache refpha => (getter => 'get_refpha');
576              
577             sub set_refpha {
578 0     0 1   my ( $self, $value, %args ) = validated_setter( \@_,
579             value => { isa => 'Num'}
580             );
581              
582 0 0 0       if ( $value >= -360 && $value <= 360 ) {
583 0           $self->write(command => sprintf( "REFP %d", $value * 1e3 ));
584 0           $self->cached_refpha($value);
585             }
586             else {
587 0           croak "\nSIGNAL RECOVERY 726x:\nunexpected value for REFERENCE PHASE in sub set_phase. Expected values must be in the range -360..360";
588             }
589             }
590              
591             sub get_refpha {
592 0     0 0   my ( $self, %args ) = validated_getter( \@_ );
593              
594 0           my $val = $self->query(command => "REFP.", %args );
595              
596             # Trailing zero byte if phase is zero. Device bug??
597 0           $val =~ s/\0//;
598              
599 0           return $self->cached_refpha($val);
600             }
601              
602             # Basically a linear_step_sweep - but for the phase
603             sub set_phase {
604 0     0 1   my ( $self, %args ) = validated_no_param_setter( \@_,
605             value => { isa => 'Num' },
606             verbose => { isa => 'Bool', default => 1 },
607             step => { isa => 'Num', default => 1},
608             rate => { isa => 'Num', default => 30},
609             );
610 0           my $to = delete $args{value};
611 0           my $verbose = delete $args{verbose};
612 0           my $step = delete $args{step};
613 0           my $rate = delete $args{rate};
614              
615 0 0 0       if ( $to >= -360 && $to <= 360 ) {
616 0           my $from = $self->cached_refpha();
617 0           my $last_timestamp = time();
618 0           my $distance = abs( $to - $from );
619              
620             # Enforce step size and rate.
621 0 0         if ( $step < 1e-3 ) {
622 0           croak "step size must be >= 0.001 degrees";
623             }
624              
625 0 0         if ( $rate < 1e-3 ) {
626 0           croak "rate must be >= 0.001 degrees/second";
627             }
628              
629 0           my @steps = linspace(
630             from => $from, to => $to, step => $step,
631             exclude_from => 1
632             );
633              
634 0           my $time_per_step;
635 0 0         if ( $distance < $step ) {
636 0           $time_per_step = $distance / $rate;
637             }
638             else {
639 0           $time_per_step = $step / $rate;
640             }
641              
642 0           usleep(10);
643 0           my $time = time();
644              
645 0 0         if ( $time < $last_timestamp ) {
646              
647             # should never happen
648 0           croak "time error";
649             }
650              
651             # Do we have to wait to enforce the maximum rate or can we start right now?
652 0           my $waiting_time = $time_per_step - ( $time - $last_timestamp );
653 0 0         if ( $waiting_time > 0 ) {
654 0           usleep( 1e6 * $waiting_time );
655             }
656 0           $self->set_refpha( value => shift @steps, %args );
657              
658             # enable autoflush
659 0           my $autoflush = STDOUT->autoflush();
660 0           for my $step (@steps) {
661 0           usleep( 1e6 * $time_per_step );
662              
663             # YokogawaGS200 has 5 + 1/2 digits precision
664 0 0         if ($verbose) {
665 0           printf(
666             "Sweeping to %.5g: Setting level to %.5e \r", $to,
667             $step
668             );
669             }
670 0           $self->set_refpha( value => $step, %args );
671             }
672 0 0         if ($verbose) {
673 0           print " " x 70 . "\r";
674             }
675              
676             # reset autoflush to previous value
677 0           STDOUT->autoflush($autoflush);
678             }
679             else {
680 0           croak "\nSIGNAL RECOVERY 726x:\nunexpected value for REFERENCE PHASE in sub set_phase. Expected values must be in the range -360..360";
681             }
682             }
683              
684             # ----------------- SIGNAL CHANNEL OUTPUT FILTERS ---------------
685              
686              
687             cache ouputfilter_slope => (getter => 'get_ouputfilter_slope');
688              
689             sub set_outputfilter_slope {
690 0     0 1   my ( $self, $value, %args ) = validated_setter( \@_,
691             value => { isa => enum([qw/6dB 12dB 18dB 24dB/])}
692             );
693              
694             # 6dB --> 6dB/octave slope of output filter\n
695             # 12dB --> 12dB/octave slope of output filter\n
696             # 18dB --> 18dB/octave slope of output filter\n
697             # 24dB --> 24dB/octave slope of output filter\n
698              
699 0           $self->cached_ouputfilter_slope($value); # Save the String value to the cache
700              
701 0 0         if ( $value eq "6dB" ) { $value = 0; }
  0 0          
    0          
    0          
702 0           elsif ( $value eq "12dB" ) { $value = 1; }
703 0           elsif ( $value eq "18dB" ) { $value = 2; }
704 0           elsif ( $value eq "24dB" ) { $value = 3; }
705             else {
706 0           croak "\nSIGNAL RECOVERY 726x:\nunexpected value for SLOPE in sub set_ouputfilter_slope. Expected values are:\n 6dB --> 6dB/octave slope of output filter\n 12dB --> 12dB/octave slope of output filter\n 18dB --> 18dB/octave slope of output filter\n 24dB --> 24dB/octave slope of output filter\n";
707             }
708              
709 0           $self->write(command => sprintf( "SLOPE %d", $value ));
710             }
711              
712             sub get_ouputfilter_slope {
713 0     0 0   my ( $self, %args ) = validated_getter( \@_ );
714              
715 0           my $result = $self->query( command => "SLOPE", %args );
716              
717 0 0         if ( $result == 0 ) {
    0          
    0          
    0          
718 0           return '6dB';
719             }
720             elsif ( $result == 1 ) {
721 0           return '12dB';
722             }
723             elsif ( $result == 2 ) {
724 0           return '18dB';
725             }
726             elsif ( $result == 3 ) {
727 0           return '24dB';
728             }
729              
730 0           return $self->cached_ouputfilter_slope($result);
731             }
732              
733              
734             cache tc => (getter => 'get_tc');
735              
736             sub set_tc {
737 0     0 1   my ( $self, $value, %args ) = validated_setter( \@_,
738             value => { isa => enum([qw/
739             10us 20us 40us 80us 160us 320us 640us
740             5ms 10ms 20ms 50ms 100ms 200ms 500ms
741             1 2 5 10 20 50 100 200 500
742             1ks 2ks 5ks 10ks 20ks 50ks 100ks
743             /])}
744             );
745              
746             # Filter Time Constant: 10us, 20us, 40us, 80us, 160us, 320us, 640us, 5ms, 10ms, 20ms, 50ms, 100ms, 200ms, 500ms, 1s, 2s, 5s, 10s, 20s, 50s, 100s, 200s, 500s, 1ks, 2ks, 5ks, 10ks, 20ks, 50ks, 100ks\n
747              
748 0           my %list = (
749             10e-6 => 0,
750             20e-6 => 1,
751             40e-6 => 2,
752             80e-6 => 3,
753             160e-6 => 4,
754             320e-6 => 5,
755             640e-6 => 6,
756             5e-3 => 7,
757             10e-3 => 8,
758             20e-3 => 9,
759             50e-3 => 10,
760             100e-3 => 11,
761             200e-3 => 12,
762             500e-3 => 13,
763             1 => 14,
764             2 => 15,
765             5 => 16,
766             10 => 17,
767             20 => 18,
768             50 => 19,
769             100 => 20,
770             200 => 21,
771             500 => 22,
772             1e3 => 23,
773             2e3 => 24,
774             5e3 => 25,
775             10e3 => 26,
776             20e3 => 27,
777             50e3 => 28,
778             100e3 => 29
779             );
780              
781 0 0         if ( $value =~ /\b(\d+\.?[\d+]?)us?\b/ ) {
    0          
    0          
782 0           $value = $1 * 1e-6;
783             }
784             elsif ( $value =~ /\b(\d+\.?[\d+]?)ms?\b/ ) {
785 0           $value = $1 * 1e-3;
786             }
787             elsif ( $value =~ /\b(\d+\.?[\d+]?)ks?\b/ ) {
788 0           $value = $1 * 1000;
789             }
790              
791 0           $self->cached_tc($value);
792 0           $self->write(command => sprintf( "TC %d", $list{$value} ));
793             }
794              
795             sub get_tc {
796 0     0 0   my ( $self, %args ) = validated_getter( \@_ );
797              
798 0           my @list = (
799             10e-6, 20e-6, 40e-6, 80e-6, 160e-6, 320e-6, 640e-6, 5e-3,
800             10e-3, 20e-3, 50e-3, 100e-3, 200e-3, 500e-3, 1, 2,
801             5, 10, 20, 50, 100, 200, 500, 1e3,
802             2e3, 5e3, 10e3, 20e3, 50e3, 100e3
803             );
804              
805 0           my $tc = $self->query(command => "TC", %args );
806              
807 0           return $self->cached_tc($list[$tc]);
808             }
809              
810             # ---------------- SIGNAL CHANNEL OUTPUT AMPLIFIERS --------------
811              
812              
813             cache offset => (getter => 'get_offset');
814              
815             sub set_offset {
816 0     0 1   my ( $self, %args ) = validated_no_param_setter( \@_,
817             X => {isa => 'Num'},
818             Y => {isa => 'Num'}
819             );
820              
821 0           my $x_value = delete $args{X};
822 0           my $y_value = delete $args{Y};
823              
824 0           my @offset;
825              
826 0 0 0       if ( $x_value >= -300 || $x_value <= 300 ) {
827 0           $self->write(command => sprintf( "XOF 1 %d", $x_value * 100 ));
828 0           my @temp = split( /,/, $self->query(command => "XOF") );
829 0           $offset[0] = $temp[1] / 100;
830 0 0         if ( $offset[0] != $x_value ) {
831 0           croak "\nSIGNAL RECOVERY 726x:\ncouldn't set X chanel output offset";
832             }
833             }
834              
835 0 0 0       if ( $y_value >= -300 || $y_value <= 300 ) {
836 0           $self->write(command => sprintf( "YOF 1 %d", $y_value * 100 ));
837 0           my @temp = split( /,/, $self->query(command => "YOF") );
838 0           $offset[1] = $temp[1] / 100;
839 0 0         if ( $offset[1] != $y_value ) {
840 0           croak "\nSIGNAL RECOVERY 726x:\ncouldn't set Y chanel output offset";
841             }
842             }
843              
844 0 0         if ( $x_value eq 'OFF' ) {
845 0           $self->write(command => "XOF 0");
846 0           my @temp = split( /,/, $self->query(command => "XOF") );
847 0           $offset[0] = $temp[0];
848 0 0         if ( $offset[0] != 0 ) {
849 0           croak "\nSIGNAL RECOVERY 726x:\ncouldn't set X chanel output offset";
850             }
851             }
852              
853 0 0         if ( $y_value eq 'OFF' ) {
854 0           $self->write(command => "YOF 0");
855 0           my @temp = split( /,/, $self->query(command => "YOF") );
856 0           $offset[1] = $temp[0];
857 0 0         if ( $offset[1] != 0 ) {
858 0           croak "\nSIGNAL RECOVERY 726x:\ncouldn't set Y chanel output offset";
859             }
860             }
861              
862 0 0         if ( $x_value eq 'AUTO' ) {
863 0           $self->write(command => "AXO");
864 0           my @temp = split( /,/, $self->query(command => "XOF") );
865 0           $offset[0] = $temp[1];
866 0           @temp = split( /,/, $self->query(command => "YOF") );
867 0           $offset[1] = $temp[1];
868             }
869              
870 0           $self->cached_offset(\@offset);
871             }
872              
873             sub get_offset {
874 0     0 0   my ( $self, %args ) = validated_getter( \@_ );
875              
876 0           my @offset;
877 0           my @temp = split( /,/, $self->query(command => "XOF") );
878 0           $offset[0] = $temp[1];
879 0           @temp = split( /,/, $self->query(command => "YOF") );
880 0           $offset[1] = $temp[1];
881              
882 0           return $self->cached_offset(\@offset);
883             }
884              
885             # -------------- INTERNAL OSCILLATOR ------------------------------
886              
887              
888             cache source_level => (getter => 'get_source_level');
889              
890             sub source_level {
891 0     0 1   my ( $self, $value, %args ) = validated_setter( \@_ );
892              
893 0           my $id = $self->cached_id();
894              
895 0 0         if ( index( $value, "u" ) >= 0 ) {
    0          
896 0           $value = int($value) * 1e-6;
897             }
898             elsif ( index( $value, "m" ) >= 0 ) {
899 0           $value = int($value) * 1e-3;
900             }
901              
902 0 0 0       if ( $value >= 0 && $value <= 5 ) {
903 0 0         if ( $id == 7260 ) {
    0          
904 0           $self->write( command => sprintf( "OA %d", sprintf( "%d", $value * 1e3 ) ) );
905             }
906             elsif ( $id == 7265 ) {
907 0           $self->write( command => sprintf( "OA %d", sprintf( "%d", $value * 1e6 ) ) );
908             }
909 0           $self->cached_source_level($value);
910              
911             }
912             else {
913 0           croak "\nSIGNAL RECOVERY 726x:\n\nSIGNAL RECOVERY 726x:\nunexpected value for OSCILLATOR OUTPUT in sub source_level. Expected values must be in the range 0..5V.";
914             }
915             }
916              
917             sub get_source_level {
918 0     0 0   my ( $self, %args ) = validated_getter( \@_ );
919              
920 0           my $id = $self->cached_id();
921              
922 0 0         if ( $id == 7260 ) {
    0          
923 0           return $self->cached_source_level($self->query( command => "OA", %args ) / 1e3);
924             }
925             elsif ( $id == 7265 ) {
926 0           return $self->cached_source_level($self->query( command => "OA", %args ) / 1e6);
927             }
928             }
929              
930             sub set_level {
931 0     0 0   my ( $self, $value, %args ) = validated_setter(
932             \@_,
933             value => { isa => 'Num' },
934             );
935              
936 0           $self->linear_step_sweep( to => $value, verbose => 0, %args );
937             }
938              
939              
940             cache frq => (getter => 'get_frq');
941              
942             sub set_frq {
943 0     0 1   my ( $self, $value, %args ) = validated_setter( \@_,
944             value => { isa => 'Num' }
945             );
946              
947 0 0 0       if ( $value > 0 && $value <= 259000 ) {
948 0           $self->write( command => sprintf( "OF %d", $value * 1e3) );
949 0           $self->cached_frq($value);
950             }
951             else {
952 0           croak "\nSIGNAL RECOVERY 726x:\n\nSIGNAL RECOVERY 726x:\nunexpected value for OSCILLATOR FREQUENCY in sub set_frq. Expected values must be in the range 0..250kHz";
953             }
954             }
955              
956             sub get_frq {
957 0     0 0   my ( $self, %args ) = validated_getter( \@_ );
958              
959 0           return $self->cached_frq($self->query( command => "OF", %args ) / 1e3);
960             }
961              
962             # --------------- INSTRUMENT OUTPUTS ------------------------------
963              
964              
965             cache value => (getter => 'get_value', isa => 'HashRef');
966              
967             sub get_value {
968 0     0 1   my ( $self, %args ) = validated_no_param_setter( \@_,
969             channel => {isa => enum([qw/X Y MAG PHA XY MP ALL/])},
970             read_mode => {isa => 'Str', default => ''}
971             );
972              
973 0           my $chan = delete $args{channel};
974 0           my $rmode = delete $args{read_mode};
975 0           my $result;
976              
977             # $channel can be:\n X --> X channel output\n Y --> Y channel output\n MAG --> Magnitude\n PHA --> Signale phase\n XY --> X and Y channel output\n MP --> Magnitude and signal Phase\n ALL --> X,Y, Magnitude and signal Phase\n
978 0 0         if ( $chan eq 'X' ) {
    0          
    0          
    0          
    0          
    0          
    0          
979              
980 0 0 0       if ( $rmode eq 'cache'
981 0           and defined ${$self->cached_value()}{X} ) {
982 0           return ${$self->cached_value()}{X};
  0            
983             }
984              
985 0           $result = $self->query( command => "X.", %args );
986 0           $result =~ s/\x00//g;
987 0           $self->cached_value({X => $result});
988 0           return $result;
989             }
990             elsif ( $chan eq "Y" ) {
991              
992 0 0 0       if ( $rmode eq 'cache'
993 0           and defined ${$self->cached_value()}{Y} ) {
994 0           return ${$self->cached_value()}{Y};
  0            
995             }
996              
997 0           $result = $self->query( command => "Y.", %args );
998 0           $result =~ s/\x00//g;
999 0           $self->cached_value({Y => $result});
1000 0           return $result;
1001             }
1002             elsif ( $chan eq "MAG" ) {
1003              
1004 0 0 0       if ( $rmode eq 'cache'
1005 0           and defined ${$self->cached_value()}{MAG} ) {
1006 0           return ${$self->cached_value()}{MAG};
  0            
1007             }
1008              
1009 0           $result = $self->query( command => "MAG.", %args );
1010 0           $result =~ s/\x00//g;
1011 0           $self->cached_value({MAG => $result});
1012 0           return $result;
1013             }
1014             elsif ( $chan eq "PHA" ) {
1015              
1016 0 0 0       if ( $rmode eq 'cache'
1017 0           and defined ${$self->cached_value()}{PHA} ) {
1018 0           return ${$self->cached_value()}{PHA};
  0            
1019             }
1020              
1021 0           $result = $self->query( command => "PHA.", %args );
1022 0           $result =~ s/\x00//g;
1023 0           $self->cached_value({PHA => $result});
1024 0           return $result;
1025             }
1026             elsif ( $chan eq "XY" ) {
1027              
1028 0 0 0       if ( $rmode eq 'cache'
      0        
1029 0           and defined ${$self->cached_value()}{X}
1030 0           and defined ${$self->cached_value()}{Y} ) {
1031 0           return [${$self->cached_value()}{X},${$self->cached_value()}{Y}];
  0            
  0            
1032             }
1033              
1034 0           $result = $self->query( command => "XY.", %args );
1035 0           $result =~ s/\x00//g;
1036              
1037 0           my @temp = split( ",", $result );
1038              
1039 0           $self->cached_value({XY => [$temp[0], $temp[1]]});
1040              
1041 0           return [$temp[0], $temp[1]];
1042             }
1043             elsif ( $chan eq "MP" ) {
1044              
1045 0 0 0       if ( $rmode eq 'cache'
      0        
1046             and defined $self->{cached_value()}{MAG}
1047             and defined $self->{cached_value()}{PHA} ) {
1048 0           return $self->cached_value();
1049             }
1050              
1051 0           $result = $self->query( command => "MP.", %args );
1052 0           $result =~ s/\x00//g;
1053              
1054 0           my @temp = split( ",", $result );
1055              
1056 0           $self->cached_value({MP => [$temp[0], $temp[1]]});
1057              
1058 0           return [$temp[0], $temp[1]];
1059             }
1060             elsif ( $chan eq "ALL" ) {
1061              
1062 0 0 0       if ( $rmode eq 'cache'
      0        
      0        
      0        
1063             and defined $self->{cached_value()}{X}
1064             and defined $self->{cached_value()}{Y}
1065             and defined $self->{cached_value()}{MAG}
1066             and defined $self->{cached_value()}{PHA} ) {
1067 0           return $self->cached_value();
1068             }
1069              
1070 0           $result = $self->query( command => "XY.", %args ) . ","
1071             . $self->query( command => "MP.", %args );
1072 0           $result =~ s/\x00//g;
1073              
1074 0           my @temp = split( ",", $result );
1075              
1076 0           $self->cached_value({ALL => [$temp[0], $temp[1], $temp[2], $temp[3]]});
1077              
1078 0           return [$temp[0], $temp[1], $temp[2], $temp[3]];
1079             }
1080             }
1081              
1082              
1083             sub config_measurement {
1084 0     0 1   my ( $self, %args ) = validated_no_param_setter( \@_,
1085             channel => {isa => enum([qw/X Y MAG PHA XY MP ALL X- Y- MAG- PHA -XY- MP- ALL-/])},
1086             nop => {isa => 'Int'},
1087             interval => {isa => 'Num'},
1088             trigger => {isa => enum([qw/INT EXT/]), optional => 1, default => 'INT'}
1089             );
1090              
1091 0           my $chan = delete $args{channel};
1092 0           my $np = delete $args{nop};
1093 0           my $int = delete $args{interval};
1094 0           my $trg = delete $args{trigger};
1095              
1096              
1097 0           print "--------------------------------------\n";
1098 0           print "SignalRECOVERY sub config_measurement:\n";
1099              
1100 0           $self->_clear_buffer();
1101              
1102             # select which data to store in buffer
1103 0 0         if ( $chan eq "X" ) { $chan = 17; }
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
1104 0           elsif ( $chan eq "Y" ) { $chan = 18; }
1105 0           elsif ( $chan eq "XY" ) { $chan = 19; }
1106 0           elsif ( $chan eq "MAG" ) { $chan = 20; }
1107 0           elsif ( $chan eq "PHA" ) { $chan = 24; }
1108 0           elsif ( $chan eq "MP" ) { $chan = 28; }
1109 0           elsif ( $chan eq "ALL" ) { $chan = 31; }
1110             elsif ( $chan eq "X-" ) {
1111 0           $chan = 1;
1112             } # only X channel; Sensitivity not logged --> floating point read out not possible!
1113             elsif ( $chan eq "Y-" ) {
1114 0           $chan = 2;
1115             } # only Y channel; Sensitivity not logged --> floating point read out not possible!
1116             elsif ( $chan eq "XY-" ) {
1117 0           $chan = 3;
1118             } # only XY channel; Sensitivity not logged --> floating point read out not possible!
1119             elsif ( $chan eq "MAG-" ) {
1120 0           $chan = 4;
1121             } # only MAG channel; Sensitivity not logged --> floating point read out not possible!
1122             elsif ( $chan eq "PHA-" ) {
1123 0           $chan = 8;
1124             } # only PHA channel; Sensitivity not logged --> floating point read out not possible!
1125             elsif ( $chan eq "MP-" ) {
1126 0           $chan = 12;
1127             } # only MP channel; Sensitivity not logged --> floating point read out not possible!
1128             elsif ( $chan eq "ALL-" ) {
1129 0           $chan = 15;
1130             } # only XYMP channel; Sensitivity not logged --> floating point read out not possible!
1131              
1132 0           $self->_set_buffer_datachannels($chan);
1133              
1134 0           print "SIGNAL RECOVERY 726x: set channels: "
1135             . $self->_set_buffer_datachannels($chan);
1136              
1137             # set buffer size
1138 0           print "SIGNAL RECOVERY 726x: set buffer length: "
1139             . $self->_set_buffer_length($np);
1140              
1141             # set measurement interval
1142 0 0         if ( not defined $int ) {
1143 0           $int = $self->set_tc();
1144             }
1145 0           print "SIGNAL RECOVERY 726x: set storage interval: "
1146             . $self->_set_buffer_storageinterval($int) . "\n";
1147              
1148 0 0         if ( $trg eq "EXT" ) {
1149 0           $self->write(command => "TDT");
1150 0           usleep(1e6);
1151             }
1152              
1153 0           print "SignalRecovery config_measurement complete\n";
1154 0           print "--------------------------------------\n";
1155             }
1156              
1157              
1158             sub get_data {
1159 0     0 1   my ( $self, %args ) = validated_no_param_setter( \@_,
1160             sensitivity => {isa => 'Num'},
1161             timeout => {isa => 'Num', optional => 1, default => 100} # it takes approx. 4ms per datapoint; 25k-Points --> 100sec
1162             );
1163              
1164 0           my $SEN = delete $args{sensitivity};
1165 0           my $tmt = delete $args{timeout};
1166              
1167 0           my @dummy;
1168             my @data;
1169 0           my %channel_list = (
1170             1 => "0",
1171             2 => "1",
1172             3 => "0,1",
1173             4 => "2",
1174             8 => "3",
1175             12 => "2,3",
1176             15 => "0,1,2,3",
1177             17 => "0",
1178             18 => "1",
1179             19 => "0,1",
1180             20 => "2",
1181             24 => "3",
1182             28 => "2,3",
1183             31 => "0,1,2,3"
1184             );
1185              
1186 0           my @channels = split( ",", $channel_list{ int( $self->query(command => "CBD", timeout => $tmt) ) } );
1187              
1188             #if ($channels == 17) { $channels = 1; }
1189             #elsif ($channels == 19) { $channels = 2; }
1190             #elsif ($channels == 31) { $channels = 4; }
1191              
1192 0           $self->wait(); # wait until active sweep has been finished
1193              
1194 0           foreach my $i (@channels) {
1195 0 0 0       if ( defined $SEN and $SEN >= 2e-15 and $SEN <= 1 ) {
      0        
1196 0           $self->write( command => sprintf( "DC %d", $i ) );
1197 0           my @temp;
1198             my $data;
1199              
1200 0           while (1) {
1201 0           eval { $self->read(timeout => $tmt)*$SEN*0.01 };
  0            
1202 0 0         if ( $@ =~ /(Error while reading:)/ ) { last; }
  0            
1203 0           push( @temp, $data );
1204             }
1205 0           push( @data, \@temp );
1206              
1207             }
1208             else {
1209 0           $self->write( command => sprintf( "DC. %d", $i ) );
1210 0           my @temp;
1211             my $data;
1212              
1213 0           while (1) {
1214 0           eval { $data = $self->read(timeout => $tmt) };
  0            
1215 0 0         if ( $@ =~ /(Error while reading:)/ ) { last; }
  0            
1216 0           push( @temp, $data );
1217             }
1218 0           push( @data, \@temp );
1219             }
1220              
1221             }
1222              
1223 0           return @data;
1224             }
1225              
1226              
1227             sub trg {
1228 0     0 1   my ( $self, %args ) = validated_no_param_setter( \@_ );
1229 0           $self->write(command => "TD");
1230             }
1231              
1232              
1233             sub abort {
1234 0     0 1   my ( $self, %args ) = validated_no_param_setter( \@_ );
1235 0           $self->write(command => "HC");
1236             }
1237              
1238              
1239             sub active {
1240 0     0 1   my ( $self, %args ) = validated_getter( \@_ );
1241              
1242 0           my @status = split( ",", $self->query(command => "M") );
1243 0 0         if ( $status[0] == 0 ) {
1244 0           return 0;
1245             }
1246             else {
1247 0           return 1;
1248             }
1249             }
1250              
1251              
1252             sub wait {
1253 0     0 1   my ( $self, %args ) = validated_getter( \@_ );
1254              
1255 0           while (1) {
1256 0           usleep(1e3);
1257 0           my @status = split( ",", $self->query(command => "M") );
1258 0 0         if ( $status[0] == 0 ) { last; }
  0            
1259             }
1260 0           return 0;
1261             }
1262              
1263             # --------------- DISPLAY ------------------------------
1264              
1265              
1266             sub display_on {
1267 0     0 1   my ( $self, %args ) = validated_no_param_setter( \@_ );
1268 0           $self->write(command => "LTS 1");
1269             }
1270              
1271              
1272             sub display_off {
1273 0     0 1   my ( $self, %args ) = validated_no_param_setter( \@_ );
1274 0           $self->write(command => "LTS 0");
1275             }
1276              
1277             # --------------- OUTPUT DATA CURVE BUFFER -------------------------
1278              
1279             sub _clear_buffer {
1280 0     0     my ( $self, %args ) = validated_no_param_setter( \@_ );
1281 0           $self->write(command => "NC");
1282             }
1283              
1284             sub _set_buffer_datachannels {
1285 0     0     my ( $self, $value, %args ) = validated_setter( \@_,
1286             value => {optional => 1}
1287             );
1288 0 0         if ( not defined $value ) {
1289 0           return $self->query(command => "CBD");
1290             }
1291              
1292 0           $self->write( command => sprintf( "CBD %d", $value ) );
1293 0           return $self->query(command => "CBD");
1294             }
1295              
1296             sub _set_buffer_length {
1297 0     0     my ( $self, %args ) = validated_no_param_setter( \@_,
1298             nop => {optional => 1}
1299             );
1300              
1301 0           my $noop = delete $args{nop};
1302              
1303 0 0         if ( not defined $noop ) {
1304 0           return $self->query(command => "LEN");
1305             }
1306              
1307             # get number of channels to be stored
1308 0           my $channels = $self->query(command => "CBD");
1309 0 0         if ( $channels == 17 ) { $channels = 2; }
  0 0          
    0          
1310 0           elsif ( $channels == 19 ) { $channels = 3; }
1311 0           elsif ( $channels == 31 ) { $channels = 5; }
1312              
1313             # check buffer size
1314 0 0         if ( $noop > int( 32000 / $channels ) ) {
1315 0           croak "\nSIGNAL RECOVERY 726x:\n\nSIGNAL RECOVERY 726x:\ncan't init BUFFER. Buffersize is too small for the given NUMBER OF POINTS and NUMBER OF CHANNELS to store.\n POINTS x (CHANNELS+1) cant exceed 32000.\n";
1316             }
1317              
1318 0           $self->write( command => sprintf( "LEN %d", $noop ) );
1319 0           return my $return = $self->query(command => "LEN");
1320             }
1321              
1322             sub _set_buffer_storageinterval {
1323 0     0     my ( $self, $value, %args ) = validated_setter( \@_,
1324             value => {isa => 'Num', optional => 1}
1325             );
1326              
1327 0 0         if ( not defined $value ) {
1328 0           return $self->query(command => "STR") / 1e3;
1329             }
1330              
1331 0 0 0       if ( $value < 5e-3 or $value > 1e6 ) {
1332 0           croak "\nSIGNAL RECOVERY 726x:\nunexpected value for INTERVAL in sub set_buffer_interval. Expected values are between 5ms...1E6s with a resolution of 5ms.";
1333             }
1334              
1335 0           $self->write( command => sprintf( "STR %d", $value * 1e3 ) );
1336              
1337 0           return $self->query(command => "STR") / 1e3;
1338             }
1339              
1340             with qw(
1341             Lab::Moose::Instrument::LinearStepSweep
1342             );
1343              
1344             __PACKAGE__->meta()->make_immutable();
1345              
1346             1;
1347              
1348             __END__
1349              
1350             =pod
1351              
1352             =encoding UTF-8
1353              
1354             =head1 NAME
1355              
1356             Lab::Moose::Instrument::SignalRecovery7265 - Model 7265 Lock-In Amplifier
1357              
1358             =head1 VERSION
1359              
1360             version 3.881
1361              
1362             =head1 SYNOPSIS
1363              
1364             use Lab::Moose;
1365              
1366             # Constructor
1367             my $SR = instrument(
1368             type => 'SignalRecovery7265',
1369             connection_type => 'LinuxGPIB',
1370             min_units => 0,
1371             max_units => 1,
1372             max_units_per_step => 0.001,
1373             max_units_per_second => 1
1374             );
1375              
1376             =over 4
1377              
1378             =item * C<max_units>
1379              
1380             =item * C<min_units>
1381              
1382             =item * C<max_units_per_step>
1383              
1384             =item * C<max_units_per_second>
1385              
1386             =back
1387              
1388             =head2 set_imode
1389              
1390             $SR->set_imode(value => $imode);
1391              
1392             Set input amplifier mode; valid arguments for imode are:
1393              
1394             $imode == 0 --> Current Mode OFF
1395             $imode == 1 --> High Bandwidth Current Mode
1396             $imode == 2 --> Low Noise Current Mode
1397              
1398             =head2 set_vmode
1399              
1400             $SR->set_vmode(value => $vmode);
1401              
1402             Set input channel and/or differental mode; valid arguments for vmode are:
1403              
1404             $vmode == 0 --> Both inputs grounded (testmode)
1405             $vmode == 1 --> A input only
1406             $vmode == 2 --> -B input only
1407             $vmode == 3 --> A-B differential mode
1408              
1409             =head2 set_fet
1410              
1411             $SR->set_fet(value => $fet);
1412              
1413             Set input impedance and noise via selection of the initial stage transistor;
1414             valid values for fet are:
1415              
1416             $fet == 0 --> Bipolar device, 10 kOhm input impedance, 2nV/sqrt(Hz) voltage noise at 1 kHz
1417             $fet == 1 --> FET, 10 MOhm input impedance, 5nV/sqrt(Hz) voltage noise at 1 kHz
1418              
1419             =head2 set_float
1420              
1421             $SR->set_float(value => $float);
1422              
1423             Switch ground reference of the input connector on or off; valid values for float are:
1424              
1425             $float == 0 --> input conector shield set to GROUND
1426             $float == 1 --> input conector shield set to FLOAT
1427              
1428             =head2 set_cp
1429              
1430             $SR->set_cp(value => $cp);
1431              
1432             Set input coupling to ac or dc; valid values are:
1433              
1434             $cp == 0 --> input coupling mode AC\n
1435             $cp == 1 --> input coupling mode DC\n
1436              
1437             =head2 set_sen
1438              
1439             $SR->set_sen(value => $value);
1440              
1441             Set input sensitivity; valid values are:
1442              
1443             SENSITIVITY (IMODE == 0) --> 2nV, 5nV, 10nV, 20nV, 50nV, 100nV, 200nV, 500nV, 1uV, 2uV, 5uV, 10uV, 20uV, 50uV, 100uV, 200uV, 500uV, 1mV, 2mV, 5mV, 10mV, 20mV, 50mV, 100mV, 200mV, 500mV, 1V\n
1444             SENSITIVITY (IMODE == 1) --> 2fA, 5fA, 10fA, 20fA, 50fA, 100fA, 200fA, 500fA, 1pA, 2pA, 5pA, 10pA, 20pA, 50pA, 100pA, 200pA, 500pA, 1nA, 2nA, 5nA, 10nA, 20nA, 50nA, 100nA, 200nA, 500nA, 1uA\n
1445             SENSITIVITY (IMODE == 2) --> 2fA, 5fA, 10fA, 20fA, 50fA, 100fA, 200fA, 500fA, 1pA, 2pA, 5pA, 10pA, 20pA, 50pA, 100pA, 200pA, 500pA, 1nA, 2nA, 5nA, 10nA\n
1446              
1447             Every value can be entered via string, for example
1448              
1449             $SR->set_sen(value => '100nV');
1450              
1451             =head2 auto_sen
1452              
1453             $SR->auto_sen(value => $amplitude);
1454              
1455             Adjust the Lock-Ins sensitivity based on a specified amplitude value $amplitude.
1456             This function will select a sensitivity, that covers the given amplitude the best.
1457              
1458             =head2 set_acgain
1459              
1460             $SR->set_acgain(value => $acgain);
1461              
1462             Preset Signal RECOVERY 7260 / 7265 Lock-in Amplifier
1463              
1464             =over 4
1465              
1466             =item $acgain
1467              
1468             AC-GAIN == 0 --> 0 dB gain of the signal channel amplifier\n
1469             AC-GAIN == 1 --> 10 dB gain of the signal channel amplifier\n
1470             ...
1471             AC-GAIN == 9 --> 90 dB gain of the signal channel amplifier\n
1472              
1473             =back
1474              
1475             =head2 set_linefilter
1476              
1477             $SR->set_linefilter(value => $linefilter);
1478              
1479             Preset Signal Recovery 7260 / 7265 Lock-in Amplifier
1480              
1481             =over 4
1482              
1483             =item $linefilter
1484              
1485             LINE-FILTER == 0 --> OFF\n
1486             LINE-FILTER == 1 --> enable 50Hz/60Hz notch filter\n
1487             LINE-FILTER == 2 --> enable 100Hz/120Hz notch filter\n
1488             LINE-FILTER == 3 --> enable 50Hz/60Hz and 100Hz/120Hz notch filter\n
1489              
1490             =back
1491              
1492             =head2 set_refchannel
1493              
1494             $SR->set_refchannel(value => $refchannel);
1495              
1496             Preset Signal Recovery 7260 / 7265 Lock-in Amplifier
1497              
1498             =over 4
1499              
1500             =item $refchannel
1501              
1502             REF-CHANNEL == 'INT' --> internal reference input mode\n
1503             REF-CHANNEL == 'EXT LOGIC' --> external rear panel TTL input\n
1504             REF-CHANNEL == 'EXT' --> external front panel analog input\n
1505              
1506             =back
1507              
1508             =head2 autophase
1509              
1510             $SR->autophase();
1511              
1512             Trigger an autophase procedure
1513              
1514             =head2 set_refpha/set_phase
1515              
1516             $SR->set_refpha(value => $phase);
1517             $SR->set_phase(value => $phase);
1518              
1519             Preset Signal Recovery 7260 / 7265 Lock-in Amplifier
1520              
1521             =over 4
1522              
1523             =item $phase
1524              
1525             REFERENCE PHASE can be between 0 ... 360°
1526              
1527             =back
1528              
1529             Use C<set_refpha> to instantly set the Lock-Ins phase, use C<set_phase> for a
1530             linear step sweep to the desired phase. Like the L<Lab::Moose::Instrument::LinearStepSweep>
1531             class, optional arguments for C<set_phase> are
1532              
1533             =over 4
1534              
1535             =item $verbose
1536              
1537             Default = true. Set to false if you don't want the sweeping process to be
1538             printed on-screen.
1539              
1540             =item $step
1541              
1542             Default = 1 [°]. Adjust the step size in degrees, can't be smaller than 0.001°.
1543              
1544             =item $rate
1545              
1546             Default = 30 [°/s]. Adjust the sweep rate in degrees per second, can't be
1547             smaller than 0.001°/s.
1548              
1549             =back
1550              
1551             Note that C<set_phase> is used in phase sweeps.
1552              
1553             =head2 set_outputfilter_slope
1554              
1555             $SR->set_outputfilter_slope(value => $slope);
1556              
1557             Preset Signal Recovery 7260 / 7265 Lock-in Amplifier
1558              
1559             =over 4
1560              
1561             =item $slope
1562              
1563             6dB --> 6dB/octave slope of output filter\n
1564             12dB --> 12dB/octave slope of output filter\n
1565             18dB --> 18dB/octave slope of output filter\n
1566             24dB --> 24dB/octave slope of output filter\n
1567              
1568             =back
1569              
1570             =head2 set_tc
1571              
1572             $SR->set_tc(value => $tc);
1573              
1574             Preset the output(signal channel) low pass filters time constant tc of the Signal Recovery 7260 / 7265 Lock-in Amplifier
1575              
1576             =over 4
1577              
1578             =item $tc
1579              
1580             Filter Time Constant:
1581             10us, 20us, 40us, 80us, 160us, 320us, 640us, 5ms, 10ms, 20ms, 50ms, 100ms, 200ms, 500ms, 1s, 2s, 5s, 10s, 20s, 50s, 100s, 200s, 500s, 1ks, 2ks, 5ks, 10ks, 20ks, 50ks, 100ks\n
1582              
1583             =back
1584              
1585             =head2 set_offset
1586              
1587             $SR->set_offset(X => $x_offset, Y => $y_offset);
1588              
1589             =over 4
1590              
1591             =item $x_offset/$y_offset
1592              
1593             -300 to 300 --> Set the offset
1594             OFF --> disable the offset
1595             AUTO --> automatically set offset
1596              
1597             =back
1598              
1599             =head2 source_level
1600              
1601             $SR->source_level(value => $level);
1602              
1603             Preset the oscillator output voltage of the Signal Recovery 7260 / 7265 Lock-in Amplifier
1604              
1605             =over 4
1606              
1607             =item $level
1608              
1609             OSCILLATOR OUTPUT VOLTAGE can be between 0 ... 5V in steps of 1mV (Signal Recovery 7260) and 1uV (Signal Recovery 7265)
1610              
1611             =back
1612              
1613             Use source_level(value => $level)) to jump to a desired amplitude, use set_level(value => $level) to slowly sweep to that amplitude.
1614              
1615             =head2 set_frq
1616              
1617             $SR->set_frq(value => $frequency);
1618              
1619             Preset the oscillator frequency of the Signal Recovery 7260 / 7265 Lock-in Amplifier
1620              
1621             =over 4
1622              
1623             =item $frequency
1624              
1625             OSCILLATOR FREQUENCY can be between 0 ... 259kHz
1626              
1627             =back
1628              
1629             =head2 get_value
1630              
1631             WORK IN PROGRESS... This subroutines still has some bugs, please beware
1632              
1633             $value=$SR->get_value(channel => $channel);
1634              
1635             Makes a measurement using the actual settings.
1636             The CHANNELS defined by $channel are returned as floating point values.
1637             If more than one value is requested, they will be returned as an array.
1638              
1639             =over 4
1640              
1641             =item $channel
1642              
1643             CHANNEL can be:
1644              
1645             in floating point notation:
1646              
1647             -----------------------------
1648              
1649             'X' --> X channel output\n
1650             'Y' --> Y channel output\n
1651             'MAG' --> Magnitude\n
1652             'PHA' --> Signale phase\n
1653             'XY' --> X and Y channel output\n
1654             'MP' --> Magnitude and signal Phase\n
1655             'ALL' --> X,Y, Magnitude and signal Phase\n
1656              
1657             =back
1658              
1659             =head2 config_measurement
1660              
1661             $SR->config_measurement(
1662             channel => $channel,
1663             nop => $number_of_points,
1664             interval => $interval,
1665             trigger => $trigger
1666             );
1667              
1668             Preset the Signal Recovery 7260 / 7265 Lock-in Amplifier for a TRIGGERED measurement.
1669              
1670             =over 4
1671              
1672             =item $channel
1673              
1674             CHANNEL can be:
1675              
1676             in floating point notation:
1677              
1678             -----------------------------
1679              
1680             'X' --> X channel output\n
1681             'Y' --> Y channel output\n
1682             'MAG' --> Magnitude\n
1683             'PHA' --> Signale phase\n
1684             'XY' --> X and Y channel output\n
1685             'MP' --> Magnitude and signal Phase\n
1686             'ALL' --> X,Y, Magnitude and signal Phase\n
1687              
1688             .
1689              
1690             in percent of full range notation:
1691              
1692             ------------------------------------
1693              
1694             'X-' --> X channel output\n
1695             'Y-' --> Y channel output\n
1696             'MAG-' --> Magnitude\n
1697             'PHA-' --> Signale phase\n
1698             'XY-' --> X and Y channel output\n
1699             'MP-' --> Magnitude and signal Phase\n
1700             'ALL-' --> X,Y, Magnitude and signal Phase\n
1701              
1702             =item $number_of_points
1703              
1704             Preset the NUMBER OF POINTS to be taken for one measurement trace.
1705             The single measured points will be stored in the internal memory of the Lock-in Amplifier.
1706             For the Signal Recovery 7260 / 7265 Lock-in Amplifier the internal memory is limited to 32.000 values.
1707              
1708             --> If you request data for the channels X and Y in floating point notation, for each datapoint three values have to be stored in memory (X,Y and Sensitivity).
1709             --> So you can store effectivly 32.000/3 = 10666 datapoints.
1710             --> You can force the instrument not to store additionally the current value of the Sensitivity setting by appending a '-' when you select the channels, eg. 'XY-' instead of simply 'XY'.
1711             --> Now you will recieve only values between -30000 ... + 30000 from the Lock-in, which is called the full range notation.
1712             --> You can calculate the measurement value by ($value/100)*Sensitivity. This is easy if you used only a single setting for Sensitivity during the measurement, and it's very hard if you changed the Sensitivity several times during the measurment or even used the auto-range function.
1713              
1714             =item $interval
1715              
1716             Preset the STORAGE INTERVAL in which datavalues will be stored during the measurement.
1717             Note: the storage interval is independent from the low pass filters time constant tc.
1718              
1719             =item $trigger
1720              
1721             Optional value. Presets the source where the trigger signal is expected.
1722             'EXT' --> external trigger source
1723             'INT' --> internal trigger source
1724              
1725             DEF is 'INT'. If no value is given, DEF will be selected.
1726              
1727             =back
1728              
1729             =head2 get_data
1730              
1731             @data = $SR->get_data(
1732             sensitivity => $sensitivity,
1733             timeout => $timeout
1734             );
1735              
1736             Reads all recorded values from the internal buffer and returns them as an (2-dim) array of floatingpoint values.
1737              
1738             Example:
1739              
1740             requested channels: X --> $SR->get_data(); returns an 1-dim array containing the X-trace as floatingpoint-values
1741             requested channels: XY --> $SR->get_data(); returns an 2-dim array:
1742             --> @data[0] contains an 1-dim array containing the X-trace as floatingpoint-values
1743             --> @data[1] contains an 1-dim array containing the Y-trace as floatingpoint-values
1744              
1745             Note: Reading the buffer will not start before all predevined measurement values have been recorded.
1746             The LabVisa-script cannot be continued until all requested readings have been recieved.
1747              
1748             =over 4
1749              
1750             =item $sensitivity
1751              
1752             SENSITIVITY is an optional parameter.
1753             When it is defined, it will be assumed that the data recieved from the Lock-in are in full range notation.
1754             The return values will be calculated by $value = ($value/100)*$sensitivity.
1755              
1756             =item $timeout
1757              
1758             TIMEOUT is another optional parameter.
1759             Since it takes approximately 4ms per datapoint, with 25k-Points a default timeout of 100s should be sufficient.
1760              
1761             =back
1762              
1763             =head2 trg
1764              
1765             $SR->trg();
1766              
1767             Sends a trigger signal via the GPIB-BUS to start the predefined measurement.
1768             The LabVisa-script can immediatally be continued, e.g. to start another triggered measurement using a second Signal Recovery 7260 / 7265 Lock-in Amplifier.
1769              
1770             =head2 abort
1771              
1772             $SR->abort();
1773              
1774             Aborts current (triggered) measurement.
1775              
1776             =head2 active
1777              
1778             $SR->active();
1779              
1780             Returns '1' if current (triggered) measurement is still running and '0' if current (triggered) measurement has been finished.
1781              
1782             =head2 wait
1783              
1784             $SR->wait();
1785              
1786             Waits until current (triggered) measurement has been finished.
1787              
1788             =head2 display_on
1789              
1790             $SR->display_on();
1791              
1792             =head2 display_off
1793              
1794             $SR->display_off();
1795              
1796             =head1 CAVEATS/BUGS
1797              
1798             probably many
1799              
1800             =head1 SEE ALSO
1801              
1802             =over 4
1803              
1804             =item L<Lab::Moose::Instrument>
1805              
1806             =back
1807              
1808             =head1 COPYRIGHT AND LICENSE
1809              
1810             This software is copyright (c) 2023 by the Lab::Measurement team; in detail:
1811              
1812             Copyright 2021 Andreas K. Huettel, Fabian Weinelt, Simon Reinhardt
1813             2022 Jonas Schambeck
1814              
1815              
1816             This is free software; you can redistribute it and/or modify it under
1817             the same terms as the Perl 5 programming language system itself.
1818              
1819             =cut