digilent 0.17.4__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,2809 @@
1
+ import datetime
2
+ import logging
3
+ import re
4
+ import struct
5
+
6
+ from navdict import navdict
7
+
8
+ from egse.device import DeviceInterface
9
+ from egse.digilent.measurpoint.digilent_devif import DigilentEthernetInterface
10
+ from egse.mixin import dynamic_command, CommandType, add_lf, DynamicCommandMixin
11
+ from egse.setup import load_setup, Setup
12
+
13
+ logger = logging.getLogger("egse.digilent.digilent")
14
+
15
+
16
+ class ScanRecord:
17
+ def __init__(self, timestamp_s: int, timestamp_ms: int, scan_index: int, num_values: int, values: list[float]):
18
+ """Initialisation of a scan record.
19
+
20
+ Depending on the configuration of the channel(s), the values are expressed in °C, Ω, or V.
21
+
22
+ Args:
23
+ timestamp_s (int): Timestamp of the scan records, defined as the number of seconds that have elapsed since
24
+ Coordinated Universal Time (UTC).
25
+ timestamp_ms (int): Number of milliseconds after `timestamp_s` at which the sample was acquired.
26
+ scan_index (int): Index of the scan record in the circular buffer.
27
+ num_values (int): Number of single-precision values that follow in the record.
28
+ values (list[float]): Variable size array with a value from each channel that was specified in the channel
29
+ list.
30
+ """
31
+
32
+ self._timestamp_s = timestamp_s
33
+ self._timestamp_ms = timestamp_ms
34
+ self._scan_index = scan_index
35
+ self._num_values = num_values
36
+ self._values = values
37
+
38
+ @property
39
+ def timestamp(self) -> float:
40
+ """Returns the timestamp of the scan records, defined as the number of seconds that have elapsed since UTC.
41
+
42
+ Returns:
43
+ Timestamp of the scan records, defined as the number of seconds that have elapsed since UTC.
44
+ """
45
+
46
+ return self._timestamp_s + self._timestamp_ms / 1000
47
+
48
+ @property
49
+ def timestamp_s(self) -> int:
50
+ """Returns the timestamp of the scan recordsm defined as the number of seconds that have elapsed since UTC.
51
+
52
+ Returns:
53
+ Timestamp of the scan recordsm defined as the number of seconds that have elapsed since UTC.
54
+ """
55
+
56
+ return self._timestamp_s
57
+
58
+ @property
59
+ def timestamp_ms(self) -> int:
60
+ """Returns the number of milliseconds after `timestamp_s` at which the sample was acquired.
61
+
62
+ Returns:
63
+ Number of milliseconds after `timestamp_s` at which the sample was acquired.
64
+ """
65
+
66
+ return self._timestamp_ms
67
+
68
+ @property
69
+ def scan_index(self) -> int:
70
+ """Returns the index of the scan record in the circular buffer.
71
+
72
+ Returns:
73
+ Index of the scan record in the circular buffer.
74
+ """
75
+
76
+ return self._scan_index
77
+
78
+ @property
79
+ def num_values(self):
80
+ """Returns the number of single-precision values that follow in the record.
81
+
82
+ Returns:
83
+ Number of single-precision values that follow in the record.
84
+ """
85
+
86
+ return self._num_values
87
+
88
+ def get_values(self):
89
+ """Returns the array with a value from each channel that was specified in the channel list.
90
+
91
+ Depending on the configuration of the channel(s), the values are expressed in °C, Ω, or V.
92
+
93
+ Returns:
94
+ Variable size array with a value from each channel that was specified in the channel list.
95
+ """
96
+
97
+ return self._values
98
+
99
+ def get_value(self, index: int):
100
+ """Returns the value at the specified index.
101
+
102
+ Note that the index does not necessarily correspond to the channel index.
103
+
104
+ Depending on the configuration of the channel(s), the value is expressed in °C, Ω, or V.
105
+
106
+ Args:
107
+ index (int): Index of the value to return.
108
+
109
+ Returns:
110
+ Value at the specified index.
111
+ """
112
+ return self._values[index]
113
+
114
+ def get_datetime(self) -> tuple[datetime.datetime, str, str]:
115
+ """Returns the datetime, date, and time of the scan record.
116
+
117
+ Returns:
118
+ Tuple containing the datetime of the scan record, the date (format: %Y%m%d), and the time (format: %H:%M:%S).
119
+ """
120
+
121
+ dt = datetime.datetime.fromtimestamp(self.timestamp, datetime.UTC)
122
+
123
+ return dt, dt.strftime("%Y%m%d"), dt.strftime("%H:%M:%S")
124
+
125
+ def __repr__(self) -> str:
126
+ """Returns a string representation of the scan record.
127
+
128
+ Returns:
129
+ String representation of the scan record.
130
+ """
131
+
132
+ _, date, time = self.get_datetime()
133
+
134
+ response = "ScanRecord:\n"
135
+ response += f" Timestamp [s] (raw): {self._timestamp_s} (0x{self._timestamp_s:08x})\n"
136
+ response += f" Timestamp [ms]: {self._timestamp_ms} (0x{self._timestamp_ms:08x})\n"
137
+ response += f" Date: {date}\n"
138
+ response += f" Time: {time}\n"
139
+ response += f" Datetime: {datetime.datetime.fromtimestamp(self.timestamp, datetime.UTC)}\n"
140
+ response += f" Scan index: {self._scan_index}\n"
141
+ response += f" Number of values: {self._num_values}\n"
142
+
143
+ if self.num_values == 1:
144
+ response += f" Value: {self._values[0]}\n"
145
+ else:
146
+ response += f" Values: {self._values}\n"
147
+
148
+ return response
149
+
150
+ def __str__(self) -> str:
151
+ """Returns a printable string representation of the scan record.
152
+
153
+ Returns:
154
+ Printable string representation of the scan record.
155
+ """
156
+
157
+ return self.__repr__()
158
+
159
+
160
+ class ScanRecords:
161
+ def __init__(self, scan_records: list[ScanRecord]):
162
+ """Initialisation of a collection of scan records.
163
+
164
+ Args:
165
+ scan_records (list[ScanRecord]): List of scan records.
166
+ """
167
+
168
+ self._scan_records = scan_records
169
+
170
+ def get_num_scan_records(self) -> int:
171
+ """Returns the number of scan records in the collection."""
172
+ return len(self._scan_records)
173
+
174
+ def get_scan_record(self, index: int) -> ScanRecord:
175
+ """Returns the scan record at the specified index.
176
+
177
+ Note that the index does not necessarily correspond to the index in the circular buffer.
178
+
179
+ Args:
180
+ index (int): Index of the scan record to return.
181
+
182
+ Returns:
183
+ Scan record at the specified index.
184
+ """
185
+
186
+ return self._scan_records[index]
187
+
188
+ def __repr__(self):
189
+ """Returns a string representation of the collection of scan records.
190
+
191
+ Returns:
192
+ String representation of the collection of scan records.
193
+ """
194
+
195
+ response = ""
196
+
197
+ for index, scan_record in enumerate(self._scan_records):
198
+ _, date, time = scan_record.get_datetime()
199
+
200
+ response += f"ScanRecord {index}:\n"
201
+ response += f" Timestamp [s] (raw): {scan_record.timestamp_s} (0x{scan_record.timestamp_s:08x})\n"
202
+ response += f" Timestamp [ms]: {scan_record.timestamp_ms} (0x{scan_record.timestamp_ms:08x})\n"
203
+ response += f" Date: {date}\n"
204
+ response += f" Time: {time}\n"
205
+ response += (
206
+ f" Datetime: {datetime.datetime.fromtimestamp(scan_record.timestamp, datetime.UTC)}\n"
207
+ )
208
+ response += f" Scan index: {scan_record.scan_index}\n"
209
+ response += f" Number of values: {scan_record.num_values}\n"
210
+
211
+ if scan_record.num_values == 1:
212
+ response += f" Value: {scan_record.get_value(0)}\n\n"
213
+ else:
214
+ response += f" Values: {scan_record.get_values()}\n\n"
215
+
216
+ return response
217
+
218
+ def __str__(self):
219
+ """Returns a printable string representation of the collection of scan records.
220
+
221
+ Returns:
222
+ Printable string representation of the collection of scan records.
223
+ """
224
+
225
+ return self.__repr__()
226
+
227
+
228
+ def split_result_on_comma(response: str) -> tuple[str, ...]:
229
+ """Splits the given response string on commas.
230
+
231
+ Args:
232
+ response (str): Response string to split.
233
+
234
+ Returns:
235
+ Tuple of strings split on commas.
236
+ """
237
+
238
+ return tuple(response.split(","))
239
+
240
+
241
+ def int_to_bool(response: str) -> bool:
242
+ """Converts the given response string to a boolean.
243
+
244
+ Args:
245
+ response (str): Response string to convert.
246
+
247
+ Returns:
248
+ bool: Boolean value converted from the response string.
249
+ """
250
+
251
+ return bool(int(response))
252
+
253
+
254
+ def to_int(response: str) -> int:
255
+ """Converts the given response string to an integer.
256
+
257
+ Args:
258
+ response (str): Response string to convert.
259
+
260
+ Returns:
261
+ Integer value converted from the response string.
262
+ """
263
+
264
+ return int(response)
265
+
266
+
267
+ def to_float(response: str) -> float:
268
+ """Converts the given response string to a float.
269
+
270
+ Args:
271
+ response (str): Response string to convert.
272
+
273
+ Returns:
274
+ Float value converted from the response string.
275
+ """
276
+
277
+ return float(response)
278
+
279
+
280
+ def split_on_comma_to_int(response: str) -> tuple[int, ...]:
281
+ """Splits the given response string on commas.
282
+
283
+ Args:
284
+ response (str): Response string to split.
285
+
286
+ Returns:
287
+ Tuple of integers split on commas.
288
+ """
289
+
290
+ response = split_result_on_comma(response)
291
+
292
+ return tuple(int(x) for x in response)
293
+
294
+
295
+ def format_to_time(response: str) -> str:
296
+ """Converts the given response string to time.
297
+
298
+ Args:
299
+ response (str): Response string to convert.
300
+
301
+ Returns:
302
+ Time string converted from the response string.
303
+ """
304
+
305
+ hours, minutes, seconds = split_result_on_comma(response)
306
+
307
+ return f"{hours.zfill(2)}:{minutes.zfill(2)}:{seconds.zfill(2)}"
308
+
309
+
310
+ def to_date(response: str) -> datetime.datetime:
311
+ """Converts the given response string to a date.
312
+
313
+ Args:
314
+ response (str): Response string to convert.
315
+
316
+ Returns:
317
+ Date string converted from the response string.
318
+ """
319
+
320
+ return datetime.datetime.strptime(response, "%Y,%m,%d")
321
+
322
+
323
+ def parse_error(response: str) -> tuple[int, str]:
324
+ """Converts the given response string of a tuple of an error code and the corresponding error message.
325
+
326
+ Args:
327
+ response (str): Response string to convert
328
+
329
+ Returns:
330
+ Tuple of an error code and the corresponding error message.
331
+ """
332
+ code, description = split_result_on_comma(response)
333
+
334
+ return int(code), description
335
+
336
+
337
+ def parse_single_measurement(response: bytes) -> tuple[float, ...]:
338
+ """Converts the given response bytes to a float.
339
+
340
+ Args:
341
+ response (bytes): Response bytes to convert.
342
+
343
+ Returns:
344
+ Depending on the configuration of the channel(s), the values are expressed in °C, Ω, or V.
345
+
346
+ """
347
+
348
+ endian_char = ">"
349
+ offset = 0
350
+
351
+ binary_data = response[3:-1]
352
+
353
+ values = []
354
+
355
+ while offset + 4 <= len(binary_data):
356
+ # Unpack float values
357
+
358
+ value = struct.unpack_from(f"{endian_char}f", binary_data, offset)[0]
359
+ offset += 4
360
+
361
+ values.append(value)
362
+
363
+ return tuple(values)
364
+
365
+
366
+ def parse_scan_records(response: bytes) -> ScanRecords:
367
+ """Converts the given response bytes to a collection of scan records.
368
+
369
+ Args:
370
+ response (bytes): Response bytes to convert.
371
+
372
+ Returns:
373
+ Collection of scan records.
374
+ """
375
+
376
+ # Skip the header
377
+
378
+ if response.startswith(b"#"):
379
+ header_end = 6
380
+ binary_data = response[header_end:-1] # -1 to skip trailing newline
381
+ else:
382
+ binary_data = response
383
+
384
+ endian_char = ">"
385
+ offset = 0
386
+ record_num = 1
387
+
388
+ scan_records = []
389
+
390
+ while offset + 16 <= len(binary_data):
391
+ # Unpack header (4 unsigned longs)
392
+ header = struct.unpack_from(f">IIII", binary_data, offset)
393
+ timestamp_s, timestamp_ms, scan_index, num_values = header
394
+
395
+ offset += 16
396
+
397
+ # Unpack float values
398
+
399
+ values = []
400
+
401
+ if 0 < num_values < 100: # Sanity check
402
+ for i in range(num_values):
403
+ if offset + 4 <= len(binary_data):
404
+ value = struct.unpack_from(f"{endian_char}f", binary_data, offset)[0]
405
+ offset += 4
406
+
407
+ values.append(value)
408
+ else:
409
+ break
410
+
411
+ scan_record = ScanRecord(timestamp_s, timestamp_ms, scan_index, num_values, values)
412
+ scan_records.append(scan_record)
413
+
414
+ record_num += 1
415
+
416
+ return ScanRecords(scan_records)
417
+
418
+
419
+ def get_channel_list(channel_list: str) -> list[str]:
420
+ """Generates a list of channel names from a given channel list.
421
+
422
+ The "names" of the channels are the indices of the channels, as strings.
423
+
424
+ Args:
425
+ channel_list: a channel list as understood by the SCPI commands of DAQ6510.
426
+
427
+ Returns:
428
+ List of channel names.
429
+ """
430
+
431
+ match = re.match(r"\(@(.*)\)", channel_list)
432
+ group = match.groups()[0]
433
+
434
+ parts = group.replace(" ", "").split(",")
435
+ names = []
436
+ for part in parts:
437
+ if ":" in part:
438
+ channels = part.split(":")
439
+ names.extend(str(ch) for ch in range(int(channels[0]), int(channels[1]) + 1))
440
+ else:
441
+ names.append(part)
442
+
443
+ return names
444
+
445
+
446
+ class DigilentInterface(DeviceInterface):
447
+ """Base class for Digilent TEMPpoint, VOLTpoint, and MEASURpoint instruments."""
448
+
449
+ def __init__(self):
450
+ super().__init__()
451
+
452
+ self.channel_lists = navdict()
453
+ self.channels = navdict()
454
+
455
+ def config_channels(self, setup: Setup = None):
456
+ """Reads the channel configuration from the setup + apply it to the device.
457
+
458
+ Args
459
+ setup (Setup): Setup from which load read the channel configuration.
460
+ """
461
+
462
+ self.channel_lists = navdict()
463
+ self.channels = navdict()
464
+
465
+ setup = setup or load_setup()
466
+
467
+ try:
468
+ channel_config = setup.gse.dt8874
469
+
470
+ if "RTD" in channel_config:
471
+ self.channels["RTD"] = navdict()
472
+ self.channel_lists["RTD"] = navdict()
473
+
474
+ for rtd_type in channel_config.RTD:
475
+ if rtd_type != "channels":
476
+ channels = channel_config.RTD[rtd_type].channels
477
+
478
+ self.channels.RTD[rtd_type] = channels
479
+ self.channel_lists.RTD[rtd_type] = get_channel_list(channels)
480
+
481
+ self.set_rtd_temperature_channels(rtd_type=rtd_type, channels=channels)
482
+
483
+ if "THERMOCOUPLE" in channel_config:
484
+ self.channels["THERMOCOUPLE"] = navdict()
485
+ self.channel_lists["THERMOCOUPLE"] = navdict()
486
+
487
+ for tc_type in channel_config.THERMOCOUPLE:
488
+ if tc_type != "channels":
489
+ channels = channel_config.THERMOCOUPLE[tc_type].channels
490
+
491
+ self.channels.RTD[tc_type] = channels
492
+ self.channel_lists.RTD[tc_type] = get_channel_list(channels)
493
+
494
+ self.set_thermocouple_temperature_channels(rtd_type=tc_type, channels=channels)
495
+
496
+ if "RESISTANCE" in channel_config:
497
+ channels = channel_config.RESISTANCE.channels
498
+
499
+ self.channels["RESISTANCE"] = channels
500
+ self.channel_lists["RESISTANCE"] = get_channel_list(channels)
501
+
502
+ self.set_resistance_channels(channels=channels)
503
+
504
+ if "VOLTAGE" in channel_config:
505
+ channels = channel_config.VOLTAGE.channels
506
+
507
+ self.channels["VOLTAGE"] = channels
508
+ self.channel_lists["VOLTAGE"] = get_channel_list(channels)
509
+
510
+ self.set_voltage_channels(channels=channels)
511
+
512
+ if "VOLTAGE_RANGE" in channel_config:
513
+ channels = channel_config.VOLTAGE_RANGE.channels
514
+
515
+ self.channels["VOLTAGE_RANGE"] = channels
516
+ self.channel_lists["VOLTAGE_RANGE"] = get_channel_list(channels)
517
+
518
+ self.set_voltage_range_channels(channels=channels)
519
+
520
+ if len(self.channel_lists) == 0:
521
+ logger.warning("No channels configured, check the log messages.")
522
+ except AttributeError:
523
+ logger.warning(f"Couldn't configure the channels, check the log messages.")
524
+
525
+ @dynamic_command(
526
+ cmd_type=CommandType.WRITE,
527
+ cmd_string="*CLS",
528
+ process_cmd_string=add_lf,
529
+ )
530
+ def clear_status(self) -> None:
531
+ """Clears all event registers summarised in the Status Byte (STB) register.
532
+
533
+ All queues that are summarised in the Status Byte (STB) register, except the output queue, are emptied. The
534
+ device is forced into the operation complete idle state.
535
+ """
536
+
537
+ pass
538
+
539
+ @dynamic_command(
540
+ cmd_type=CommandType.WRITE,
541
+ cmd_string="*ESE",
542
+ process_cmd_string=add_lf,
543
+ )
544
+ def std_event_status_enable_register(self, bits: int) -> None:
545
+ """Enables specified bits in the Standard Event Status Enable register.
546
+
547
+ The bits in the Standard Event Status Enable register are:
548
+
549
+ | Bit | Binary weight | Description |
550
+ | --- | --- | --- |
551
+ | 0 | 1 | OPC (Operation complete) |
552
+ | 1 | 2 | RQC (Request control) |
553
+ | 2 | 4 | QYE (Query error) |
554
+ | 3 | 8 | DDE (Device-dependent error) |
555
+ | 4 | 16 | E (Execution error) |
556
+ | 5 | 32 | CME (Command error) |
557
+ | 6 | 64 | NU (Not used) |
558
+ | 7 | 128 | PON (Power on) |
559
+
560
+ Refer to IEEE Std 488.2-1992, Sect. 11.5.1.3, for more information.
561
+
562
+ This is a password-protected command.
563
+
564
+ Args:
565
+ bits (int): Integer value expressed in base 2 (binary) that represents the weighted bit value of the
566
+ Standard Event Status Enable register and the binary-weighted decimal value for each bit.
567
+
568
+ Examples:
569
+ The following command enables bits 0, 2, 3, 4, 5, and 7 of the Standard Event Status Enable register:
570
+ > *ESE 189
571
+ """
572
+
573
+ pass
574
+
575
+ @dynamic_command(
576
+ cmd_type=CommandType.TRANSACTION,
577
+ cmd_string="*ESE?",
578
+ process_cmd_string=add_lf,
579
+ process_response=to_int,
580
+ )
581
+ def get_std_event_status_enable_register(self) -> int:
582
+ """Returns the current value of the Standard Event Status Enable register.
583
+
584
+ The bits in the Standard Event Status Enable register are:
585
+
586
+ | Bit | Binary weight | Description |
587
+ | --- | --- | --- |
588
+ | 0 | 1 | OPC (Operation complete) |
589
+ | 1 | 2 | RQC (Request control) |
590
+ | 2 | 4 | QYE (Query error) |
591
+ | 3 | 8 | DDE (Device-dependent error) |
592
+ | 4 | 16 | E (Execution error) |
593
+ | 5 | 32 | CME (Command error) |
594
+ | 6 | 64 | NU (Not used) |
595
+ | 7 | 128 | PON (Power on) |
596
+
597
+ Refer to IEEE Std 488.2-1992, Sect. 11.4.2.3.2, and IEEE Std 488.2, Sect. 8.7.1, for more information.
598
+
599
+ Returns:
600
+ Integer value expressed in base 2 (binary) that represents the weighted bit value of the Standard Event
601
+ Status Enable register and the binary-weighted decimal value for each bit. Values range from 0 to 255.
602
+
603
+ Examples:
604
+ The following command queries the Standard Event Status Enable register:
605
+
606
+ > *ESE?
607
+ < 189
608
+
609
+ This value indicates that bits 0, 2, 3, 4, 5, and 7 of the Standard Event Status Enable register are enabled.
610
+ """
611
+
612
+ pass
613
+
614
+ @dynamic_command(
615
+ cmd_type=CommandType.TRANSACTION,
616
+ cmd_string="*ESR?",
617
+ process_cmd_string=add_lf,
618
+ process_response=to_int,
619
+ )
620
+ def get_std_event_status_register(self) -> int:
621
+ """Returns the current value of the Standard Event Status register.
622
+
623
+ The bits in the Standard Event Status register are:
624
+
625
+ | Bit | Binary weight | Description |
626
+ | --- | --- | --- |
627
+ | 0 | 1 | OPC (Operation complete) |
628
+ | 1 | 2 | RQC (Request control) |
629
+ | 2 | 4 | QYE (Query error) |
630
+ | 3 | 8 | DDE (Device-dependent error) |
631
+ | 4 | 16 | E (Execution error) |
632
+ | 5 | 32 | CME (Command error) |
633
+ | 6 | 64 | NU (Not used) |
634
+ | 7 | 128 | PON (Power on) |
635
+
636
+ Bits in the Standard Event Status register should be unmasked by settings the corresponding bit in the Standard
637
+ Status Enable register. On power-up, the Standard Event Status Enable register is zero; therefore, all bits in
638
+ the Standard Event Status register are masked.
639
+
640
+
641
+ Returns:
642
+ Integer value expressed in base 2 (binary) that represents the weighted bit value of the Standard Event
643
+ Status register and the binary-weighted decimal value for each bit. Values range from 0 to 255.
644
+
645
+ Examples:
646
+ The following example unmasks all error bits in the Standard Event Status register:
647
+
648
+ > *ESE?; *ESE 255; *ESE?
649
+ < 0; ;255
650
+
651
+ Then, an illegal command it sent and the Standard Event Status register is queried; a value of 32 is
652
+ returned, indicating that bit 5 (Command error) of the Standard Event Status register was set:
653
+
654
+ > *bad
655
+ > *ESR?
656
+ < 32
657
+
658
+ In the following example, the scan rate is set to an illegal value; a value of 16 is returned, indicating
659
+ that bit 4 (Execution error) of the Standard Event Status register was set:
660
+
661
+ > :CONF:SCAN:RATe:HZ 50
662
+ > *ESR?
663
+ < 16
664
+ """
665
+
666
+ pass
667
+
668
+ @dynamic_command(
669
+ cmd_type=CommandType.TRANSACTION,
670
+ cmd_string="*IDN?",
671
+ process_cmd_string=add_lf,
672
+ process_response=split_result_on_comma,
673
+ )
674
+ def get_id(self) -> tuple[str, str, str, str]:
675
+ """Returns the unique identifier of your TEMPpoint, VOLTpoint, or MEASURpoint LXI instrument.
676
+
677
+ Refer to IEEE 488.2-1992, Sects. 6.5.7.5 snd 10.14, for more information.
678
+
679
+ Returns:
680
+ Manufacturer: Defines the manufacturer of the instrument (Data Translation).
681
+ Model: Identifies the model of the instrument.
682
+ Serial number: Identifies the serial number of the instrument.
683
+ Firmware revision: Identifies the version of the firmware that is loaded on the instrument.
684
+
685
+ Examples:
686
+ > *IDN?
687
+ < Data Translation,DT8874-08T-00R-08V,201129241,2.2.0.0
688
+ This response indicates that Data Translation is the manufacturer of the device, DT8874-08T-00R-08V is the
689
+ model of the instrument (where 08T indicates that the instrument contains 8 thermocouple channels, 00R
690
+ indicates that the instrument contains 0 RTD channels, and 08V indicates that the instrument contains 8
691
+ voltage channels), 201129241 is the serial number of the instrument, and 2.2.0.0 is the version of the
692
+ firmware.
693
+ """
694
+
695
+ pass
696
+
697
+ @dynamic_command(
698
+ cmd_string="*RST",
699
+ cmd_type=CommandType.WRITE,
700
+ process_cmd_string=add_lf,
701
+ )
702
+ def reset(self) -> None:
703
+ """Resets the instrument.
704
+
705
+ Clears the Standard Event Status register, message queue, error queue, and Status Byte register, and stops any scans that are in progress.
706
+
707
+ This command has no effect on the instrument's password or password enable/disable state.
708
+
709
+ Refer to IEE 388.2-1992, Sect. 10.32, for more information.
710
+ """
711
+
712
+ pass
713
+
714
+ @dynamic_command(
715
+ cmd_type=CommandType.TRANSACTION,
716
+ cmd_string="*STB?",
717
+ process_cmd_string=add_lf,
718
+ process_response=to_int,
719
+ )
720
+ def get_status_byte_register(self) -> int:
721
+ """Returns the current value of the Status Byte register.
722
+
723
+ The weighted sum of the bit values of hte Status Byte register is returned, ranging from 0 to 255. The
724
+ following bits, described in 1999 SCPI Syntax & Stype, Sect. 9, are supported:
725
+
726
+ | Bit | Binary weight | Description |
727
+ | --- | --- | --- |
728
+ | 7 | 128 | Summary of device-dependent Operation Status register |
729
+ | 5 | 32 | Event Status Bit Summary (ESB); "1" = ESR is non-zero, "0" otherwise |
730
+ | 4 | 16 | Message Available Queue Summary (MAV); "1" = message queue not empty |
731
+ | 2 | 4 | Error/Event Queue Summary; "1" = error queue not empty |
732
+
733
+ Refer to IEE 388.2-1992, Sect. 10.36, for more information.
734
+
735
+ Examples:
736
+ The following example shows a query that is correct and causes no errors:
737
+
738
+ > *IDN?;*ESR?;*STB?
739
+ < Data Translation,DT8874-08T-00R-08V,-1,1.2;16
740
+
741
+ This example shows an illegal command being sent, and the status of the Status Byte register and the error
742
+ queue:
743
+
744
+ > bad
745
+ > *STB?
746
+ < 16
747
+
748
+ A value of 36 indicates that bit 5 (Standard Event Status Bit Summary) and 2 (Error/Event Queue Summary) of
749
+ the Status Byte register are set.
750
+
751
+ The following example shows the status of the Event Status register:
752
+
753
+ > *ESR?
754
+ < 32
755
+
756
+ A value of 32 indicates that bit 5 (Command Error) of the Event Status register is set. The following
757
+ updates the status of the Status Byte register:
758
+
759
+ > *STB?
760
+ < 4
761
+
762
+ A value of 4 indicates that bit 2 (Error/Event Queue Summary) of the Status Byte register is set. The
763
+ following shows the error codes that are returned and updates that status of the Status Byte register:
764
+
765
+ > :SYST:ERR?
766
+ < -110,"Command header error;bad"
767
+ > :SYST:ERR?
768
+ < 0;"No error"
769
+ > *STB?
770
+ < 0
771
+ """
772
+
773
+ pass
774
+
775
+ @dynamic_command(
776
+ cmd_string="STATus:OPERation:CONDition?",
777
+ cmd_type=CommandType.TRANSACTION,
778
+ process_cmd_string=add_lf,
779
+ process_response=to_int,
780
+ )
781
+ def get_operation_condition(self) -> int:
782
+ """Returns the current value of the Operation Status register.
783
+
784
+ It is a 14-bit value, for which only the following bits can be set to "1":
785
+
786
+ - Bit 4 (binary weight: 16):
787
+ - If this bit is 1:
788
+ - Bit 5 is 1: Waiting for trigger,
789
+ - Bit 5 is 0: Scanning in progress,
790
+ - If this bit is 0:
791
+ - Bit 5 is 0: Scanning is stopped.
792
+ - Bit 5 (binary weight: 32):
793
+ - If this bit is 1:
794
+ - Bit 4 is 1: Waiting for trigger,
795
+ - If this bit is 0:
796
+ - Bit 4 is 1: Scanning in progress,
797
+ - Bit 4 is 0: Scanning is stopped.
798
+
799
+ Examples:
800
+ The following example shows the status of the Operation Status register and the Status Byte register when a
801
+ scan is in progress and a software trigger is used:
802
+
803
+ > :STAT:OPER:COND?
804
+ < 16
805
+ > *STB?
806
+ < 128
807
+
808
+ A value of 16 indicates that bit 4 (Scan status) of the Operation Status register is set to 1. A value of
809
+ 128 indicates that bit 7 (Operation Status Register Summary) of the Status Byte register is set to 1.
810
+
811
+ The following example shows the status of the Operation Status register and the Status Byte register when
812
+ a scan is in progress and the instrument is waiting for an external digital trigger:
813
+
814
+ > :STAT:OPER:COND?
815
+ < 48
816
+ > *STB?
817
+ < 128
818
+
819
+ A value of 48 indicates that bit (Scan Status) and bit 5 (Trigger Status) of the Operation Status are set
820
+ to 1. A value of 128 indicates that bit 7 (Operation Status Register Summary) of the Status Byte register
821
+ is set to 1.
822
+
823
+ The following example shows the status of the Operation Status register and the Status Byte register when
824
+ the instrument is idle:
825
+
826
+ > :STAT:OPER:COND?
827
+ < 0
828
+ > *STB?
829
+ """
830
+ pass
831
+
832
+ @dynamic_command(
833
+ cmd_string=":STATus:SCAn?",
834
+ cmd_type=CommandType.TRANSACTION,
835
+ process_cmd_string=add_lf,
836
+ process_response=split_on_comma_to_int,
837
+ )
838
+ def get_scan_record_status(self) -> tuple[int, int]:
839
+ """Returns the indices of the chronologically oldest and most recent scan records in the instrument's FIFO.
840
+
841
+ If the circular buffer is empty (because a scan has not been started, or started and stopped), both indices
842
+ will be 0. Otherwise, the indices will be non-zero.
843
+
844
+ Returns:
845
+ Index of the chronologically oldest scan record in the instrument's circular buffer.
846
+ Index of the chronologically most recent scan record in the instrument's circular buffer.
847
+
848
+ Examples:
849
+ The following example shows that starting index (1001) and ending index (1050) when the circular buffer
850
+ consists of scan records 1001 to 1050:
851
+
852
+ > :STAT:SCAn?
853
+ < 1001,1050
854
+ """
855
+
856
+ pass
857
+
858
+ @dynamic_command(
859
+ cmd_string=":SYSTem:CALibrate",
860
+ cmd_type=CommandType.WRITE,
861
+ process_cmd_string=add_lf,
862
+ )
863
+ def auto_calibrate(self) -> None:
864
+ """Auto-calibrates (auto-zeroes) all analogue input channels on the instrument.
865
+
866
+ This is a password-protected command.
867
+
868
+ Examples:
869
+ This command auto-zeroes all analogue input channels on the instrument:
870
+
871
+ > :SYST:CAL
872
+ """
873
+
874
+ pass
875
+
876
+ @dynamic_command(
877
+ cmd_string=":SYSTem:DATE?",
878
+ cmd_type=CommandType.TRANSACTION,
879
+ process_cmd_string=add_lf,
880
+ process_response=to_date,
881
+ )
882
+ def get_date(self) -> datetime.datetime:
883
+ """Returns the current date of the instrument.
884
+
885
+ This date is updated automatically by an SNTP (Simple Network Time Protol) server.
886
+
887
+ Returns:
888
+ Year.
889
+ Month, in the range 1 to 12.
890
+ Day, in the range 1 to 31
891
+
892
+ Examples:
893
+ This response indicates that the data of the instrument is January 15th, 2008:
894
+
895
+ > :SYST:DATE?
896
+ < 2008,1,15
897
+ """
898
+
899
+ pass
900
+
901
+ @dynamic_command(
902
+ cmd_string=":SYSTem:ERRor?",
903
+ cmd_type=CommandType.TRANSACTION,
904
+ process_cmd_string=add_lf,
905
+ process_response=parse_error,
906
+ )
907
+ def get_error(self) -> tuple[int, str]:
908
+ """Reads an error message from the error queue and then removes it from the queue.
909
+
910
+ Potential errors are:
911
+ - No error (0): Normal operation; no error occurred.
912
+ - Command error (-100): A command is missing a parameter, or the command contains too many parameters or
913
+ too many dimensions.
914
+ - Syntax error (-110): An unrecognised command or data type was encountered (e.g. a string was received when
915
+ the instrument does not accept strings).
916
+ - Data type error (-104): A data element different from the one allowed was encountered (e.g. numeric data
917
+ was expected but string data was encountered).
918
+ - Command header error (-110): The command header is invalid.
919
+ - Unexpected number of parameters (-115): The number of parameters received does not correspond to the number
920
+ of parameters expected by the command.
921
+ - Numeric data error (-120): The value of a parameter overflowed, has the wrong dimensions, or contains an
922
+ invalid value.
923
+ - Invalid suffix (-131): The suffix does not follow the syntax described in IEEE 488.2, Sect. 7.7.3.2, or
924
+ the suffix is inappropriate for this instrument.
925
+ - Execution error (-200): A <PROGRAM DATA> element following a header was evaluated by the instrument as
926
+ outside its legal input range or is otherwise inconsistent with the instrument's
927
+ capabilities. A valid programme message could not be executed properly due to
928
+ some condition of the instrument.
929
+ - Command protected (-203): This is a password-protected command. Password protection is currently
930
+ disabled. To use this command you must enable password protection.
931
+ - Settings conflict (-221): The specified channels of the instrument do not support the requested operation,
932
+ or an invalid current password was entered. E.g. this error is returned if you
933
+ try to configure a thermocouple type for channels that do not support
934
+ temperature, or try to configure a voltage range that is not supported by the
935
+ channel.
936
+ - Data out of range (-222): A legal programme data element was parsed but could not be executed because the
937
+ interpreted value was outside the legal range for the instrument.
938
+ - Programme currently running (-284): Certain operations dealing with programmes are illegal while the
939
+ instrument is in the middle of executing a programme.
940
+ programme is running (e.g. you cannot configure/re-configure an
941
+ operation while a scan is in progress).
942
+ - Queue overflow (-350): The error queue is full; subsequent errors cannot be added to the queue. You must
943
+ clear the queue.
944
+ - Query interrupted (-410): THe query did not complete.
945
+
946
+ The error queue is a FIFO with a capacity of 32 error messages. By querying the error count before and after
947
+ an SCPI commands (in a single command string), you can unambiguously determine whether the command that you
948
+ issued caused an error.
949
+
950
+ When the queue is full, subsequent errors cannot be added to the queue.
951
+
952
+ Refer ro 1999 SCPI Command Reference, Sect. 21.8, for more information.
953
+
954
+ Returns:
955
+ Error/Event number: Unique integer in the range of -32 768 to 32 767. A value of 0 indicates that no
956
+ error or event has occurred.
957
+ Error/Event description: Quoted string that contains a description of the error that was read from the
958
+ Error/Event Queue.
959
+
960
+ Examples:
961
+ The following shows the responses to this query after an invalid command is sent to the instrument:
962
+
963
+ > :BADc
964
+ > :SYST:ERR?
965
+ < -110,"Command header error;:BADc"
966
+ > :SYST:ERR?
967
+ < 0,"No error"
968
+ """
969
+
970
+ pass
971
+
972
+ @dynamic_command(
973
+ cmd_string=":SYSTem:ERRor:COUNt?",
974
+ cmd_type=CommandType.TRANSACTION,
975
+ process_cmd_string=add_lf,
976
+ process_response=to_int,
977
+ )
978
+ def get_num_errors(self) -> int:
979
+ """Queries the error queue, returns the number of unread items and returns the count.
980
+
981
+ The error queue is a FIFO with a capacity of 32 error messages. By querying the error count before and after
982
+ an SCPI commands (in a single command string), you can unambiguously determine whether the command that you
983
+ issued caused an error.
984
+
985
+ Returns:
986
+ Number of unread items in the error queue. A value of 0 indicates that the queue is empty.
987
+
988
+ Examples:
989
+ The following shows how to query the number of error in the error queue, both before and after the
990
+ INITialize command:
991
+
992
+ > :SYST:ERR:COUN?;:INIT;:SYST:ERR:COUN?
993
+ < 0
994
+ """
995
+
996
+ pass
997
+
998
+ @dynamic_command(
999
+ cmd_string=":SYSTem:PRESet",
1000
+ cmd_type=CommandType.WRITE,
1001
+ process_cmd_string=add_lf,
1002
+ )
1003
+ def reset_lan(self) -> None:
1004
+ """Sets the LAN configuration to its default values.
1005
+
1006
+ The effect of this command is the same as pushing the LAN reset switch on the rear panel of the instrument.
1007
+ """
1008
+
1009
+ pass
1010
+
1011
+ @dynamic_command(
1012
+ cmd_string=":SYSTem:COMMunicate:NETwork:IPADdress?",
1013
+ cmd_type=CommandType.TRANSACTION,
1014
+ process_cmd_string=add_lf,
1015
+ )
1016
+ def get_ip_address(self) -> str:
1017
+ """Returns the static IP address that is currently used by the instrument on the network.
1018
+
1019
+ Returns:
1020
+ Static IP address that is currently used by the instrument on the network.
1021
+ """
1022
+
1023
+ # FIXME This actually returns the IP address of my laptop, rather than the instrument
1024
+
1025
+ pass
1026
+
1027
+ @dynamic_command(
1028
+ cmd_string=":SYSTem:COMMunicate:NETwork:MASk?",
1029
+ cmd_type=CommandType.TRANSACTION,
1030
+ process_cmd_string=add_lf,
1031
+ )
1032
+ def get_lan_ip_subnet_mask(self) -> str:
1033
+ """Returns the static IP subnet mask that is currently used by the instrument on the network.
1034
+
1035
+ Returns:
1036
+ Static IP subnet mask that is currently used by the instrument on the network.
1037
+
1038
+ Examples:
1039
+ > :SYST:COMM:NET:MAS?
1040
+ < 255.255.255.0
1041
+ """
1042
+
1043
+ pass
1044
+
1045
+ @dynamic_command(
1046
+ cmd_string=":SYSTem:PASSword:CDISable ${password}",
1047
+ cmd_type=CommandType.WRITE,
1048
+ process_cmd_string=add_lf,
1049
+ )
1050
+ def disable_pwd_protected_cmds(self, password: str) -> None:
1051
+ """Disables the use of commands and queries that are password-protected.
1052
+
1053
+ On power-up, all password-protected commands are disabled. If the instrument is powered down, you must enable
1054
+ the password-protected commands when the instrument is powered up again, if you want to configure or operate
1055
+ the instrument.
1056
+
1057
+ When the SCPI password-protected commands and queries are disabled, the instrument generates the following
1058
+ error if any of these commands is issued: –203, Command protected.
1059
+
1060
+ Args:
1061
+ password (str): Password that is stored in permanent memory on the instrument.
1062
+ """
1063
+
1064
+ pass
1065
+
1066
+ @dynamic_command(
1067
+ cmd_string=":SYSTem:PASSword:CENable ${password}",
1068
+ cmd_type=CommandType.WRITE,
1069
+ process_cmd_string=add_lf,
1070
+ )
1071
+ def enable_pwd_protected_cmds(self, password: str) -> None:
1072
+ """Enables the use of commands and queries that are password-protected.
1073
+
1074
+ On power-up, all password-protected commands are disabled. If the instrument is powered down, you must enable
1075
+ the password-protected commands when the instrument is powered up again, if you want to configure or operate
1076
+ the instrument.
1077
+
1078
+ When the SCPI password-protected commands and queries are disabled, the instrument generates the following
1079
+ error if any of these commands is issued: –203, Command protected.
1080
+
1081
+ Args:
1082
+ password (str): Password that is stored in permanent memory on the instrument.
1083
+ """
1084
+
1085
+ pass
1086
+
1087
+ @dynamic_command(
1088
+ cmd_string=":SYSTem:PASSword:CENable:STATe?",
1089
+ cmd_type=CommandType.TRANSACTION,
1090
+ process_cmd_string=add_lf,
1091
+ process_response=int_to_bool,
1092
+ )
1093
+ def is_pwd_protected_cmds_enabled(self) -> bool:
1094
+ """Returns whether password-protected commands are enabled.
1095
+
1096
+ Returns:
1097
+ True if password-protected commands are enabled; False otherwise.
1098
+
1099
+ Examples:
1100
+ In the following example, the state is 1, indicating that password-protected commands are enabled:
1101
+
1102
+ > :SYST:PASS:CEN:STAT?
1103
+ < 1
1104
+ """
1105
+
1106
+ pass
1107
+
1108
+ @dynamic_command(
1109
+ cmd_string=":SYSTem:PASSword:NEW ${old_password},${new_password}",
1110
+ cmd_type=CommandType.WRITE,
1111
+ process_cmd_string=add_lf,
1112
+ )
1113
+ def set_pwd(self, old_password: str, new_password: str) -> None:
1114
+ """Changes the existing password to a new password.
1115
+
1116
+ The new password becomes effective immediately. The instrument does not need to be re-booted. The new password
1117
+ is reflected in the LAN configuration webpage for the instrument.
1118
+
1119
+ The new password is enforced when any attempt is made to configure the instrument using SCPI commands, the
1120
+ instrument's webpages, or the IVI-COM driver.
1121
+
1122
+ Args:
1123
+ old_password (str): Current password.
1124
+ new_password (str): New password that will overwrite the current password and be saved in permanent memory
1125
+ on the instrument.
1126
+ """
1127
+
1128
+ pass
1129
+
1130
+ @dynamic_command(
1131
+ cmd_string=":SYSTem:VERSion?",
1132
+ cmd_type=CommandType.TRANSACTION,
1133
+ process_cmd_string=add_lf,
1134
+ )
1135
+ def get_scpi_version(self) -> str:
1136
+ """Returns the SCPI version to which the instrument complies.
1137
+
1138
+ Returns:
1139
+ <Year of the version.<Revision number for that year>
1140
+
1141
+ Examples:
1142
+ In this example, the version is year 1999 and the SCPI revision is 0:
1143
+
1144
+ > :SYST:VERS?
1145
+ < 1999.0
1146
+ """
1147
+
1148
+ pass
1149
+
1150
+ @dynamic_command(
1151
+ cmd_string=":SYSTem:BOArd?",
1152
+ cmd_type=CommandType.TRANSACTION,
1153
+ process_cmd_string=add_lf,
1154
+ process_response=to_int,
1155
+ )
1156
+ def get_num_boards(self) -> int:
1157
+ """Returns the number of boards that are installed in the instrument.
1158
+
1159
+ Returns:
1160
+ Number of boards installed in the instrument. This value can range from 0 to 6.
1161
+
1162
+ Examples:
1163
+ In this case, 6 boards are installed:
1164
+
1165
+ > :SYST:BOA?
1166
+ < 6
1167
+ """
1168
+
1169
+ pass
1170
+
1171
+ @dynamic_command(
1172
+ cmd_string=":SYSTem:BOArd:MOdel? ${board_number}",
1173
+ cmd_type=CommandType.TRANSACTION,
1174
+ process_cmd_string=add_lf,
1175
+ )
1176
+ def get_board_model(self, board_number: int) -> int:
1177
+ """Returns the model of a specific board installed in the instrument.
1178
+
1179
+ The following values are supported:
1180
+
1181
+ - 0 -> DT8871 (thermocouple board),
1182
+ - 1 -> DT8871U (thermocouple board),
1183
+ - 2 -> DT8873-100V (voltage board with a fixed range of +/- 100V) -> Replaced by DT8873-MULTI,
1184
+ - 3 -> DT8873-10V (voltage board with a fixed range of +/- 10V) -> Replaced by DT8873-MULTI,
1185
+ - 4 -> DT8873-400V (voltage board with a fixed range of +/- 400V) -> Replaced by DT8873-MULTI,
1186
+ - 5 -> DT8872 (RTD board),
1187
+ - 7 -> DT8873-MULTI (voltage board that supports programmable voltage ranges of +/-10V and +/-60V).
1188
+
1189
+ Args:
1190
+ board_number (int): Board number to query. This value can range from 1 to 6.
1191
+
1192
+ Returns:
1193
+ Model of the specified board in the instrument.
1194
+
1195
+ Examples:
1196
+ The following example returns the model of board number 3 in a MEASURpoint instrument. In this case, the
1197
+ model is 5, representing the DT8872 RTD board.
1198
+
1199
+ > :SYST:BOA:MOD? 3
1200
+ < 5
1201
+ """
1202
+
1203
+ pass
1204
+
1205
+ @dynamic_command(
1206
+ cmd_string=":SYSTem:BOArd:MOdel:NAMe? ${board_number}",
1207
+ cmd_type=CommandType.TRANSACTION,
1208
+ process_cmd_string=add_lf,
1209
+ )
1210
+ def get_board_name(self, board_number: int) -> str:
1211
+ """Returns the name of a specific board that is installed in the instrument.
1212
+
1213
+ Args:
1214
+ board_number (int): Board number to query. This value can range from 1 to 6.
1215
+
1216
+ Returns:
1217
+ Name of the specified board in the instrument.
1218
+
1219
+ Examples:
1220
+ The following example returns the name of board number 3 in a MEASURpoint instrument. In this case, the
1221
+ name is "DT8872" (an RTD board).
1222
+
1223
+ > :SYST:BOA:MOD:NAM? 3
1224
+ < DT8872
1225
+ """
1226
+
1227
+ pass
1228
+
1229
+ @dynamic_command(
1230
+ cmd_string=":SYSTem:BOArd:RANGe? ${board_number}",
1231
+ cmd_type=CommandType.TRANSACTION,
1232
+ process_cmd_string=add_lf,
1233
+ )
1234
+ def get_voltage_range(self, board_number: int) -> tuple[float, float]:
1235
+ """Returns the minimum and maximum voltages that are supported by a specific board in the instrument.
1236
+
1237
+ Args:
1238
+ board_number (int): Board number to query. This value can range from 1 to 6.
1239
+
1240
+ Returns:
1241
+ Tuple of the minimum and maximum voltages supported by the specified board [V].
1242
+
1243
+ Examples:
1244
+ The following example returns the minimum and maximum voltages that are supported by a DT8873-MULTI board
1245
+ (board 1 in this case):
1246
+
1247
+ > :SYST:BOA:RANG? 1
1248
+ < -60.000, 60.000
1249
+
1250
+ This example returns the minimum and maximum voltages that are supported by a DT8872 RTD board (board 1 in
1251
+ this case):
1252
+
1253
+ > :SYST:BOA:RANG? 1
1254
+ < -1.250, 1.250
1255
+ """
1256
+
1257
+ pass
1258
+
1259
+ @dynamic_command(
1260
+ cmd_string=":SYSTem:CHANnel?",
1261
+ cmd_type=CommandType.TRANSACTION,
1262
+ process_cmd_string=add_lf,
1263
+ )
1264
+ def get_input_channels(self) -> str:
1265
+ """Returns a list of all analogue input channels that are supported on the instrument.
1266
+
1267
+ If no analogue input channels are supported on the instrument, an empty list (@) is returned.
1268
+
1269
+ Returns:
1270
+ List of all analogue input channels that are supported on the instrument.
1271
+
1272
+ Examples:
1273
+ The following example returns the list of supported analogue input channels on an instrument, in this case,
1274
+ 24 channels (0 to 23):
1275
+
1276
+ > :SYST:CHAN?
1277
+ < @0:23
1278
+ """
1279
+
1280
+ pass
1281
+
1282
+ @dynamic_command(
1283
+ cmd_string=":SYSTem:CHANnel:RTD?",
1284
+ cmd_type=CommandType.TRANSACTION,
1285
+ process_cmd_string=add_lf,
1286
+ )
1287
+ def get_rtd_channels(self) -> str:
1288
+ """Returns a list of all analogue input channels that support RTDs on the instrument.
1289
+
1290
+ If no channels support RTDs on the instrument, an empty list (@) is returned.
1291
+
1292
+ Returns:
1293
+ List of all analogue input channels that support RTDs on the instrument.
1294
+
1295
+ Examples:
1296
+ The following example returns the list of analogue input channels on the instrument, as well as the channels
1297
+ that support RTDs. In this case, all 48 channels (0 to 47) support RTDs:
1298
+
1299
+ > :SYST:CHAN?
1300
+ < @0:47
1301
+ > :SYST:CHAN:RTD?
1302
+ < @0:47
1303
+
1304
+ In the following example, only channels 8 to 15 of the available 48 channels support RTDs:
1305
+
1306
+ > :SYST:CHAN?
1307
+ < @0:47
1308
+ > :SYST:CHAN:RTD?
1309
+ < @8:15
1310
+ """
1311
+
1312
+ pass
1313
+
1314
+ @dynamic_command(
1315
+ cmd_string=":SYSTem:CHANnel:TCouple?",
1316
+ cmd_type=CommandType.TRANSACTION,
1317
+ process_cmd_string=add_lf,
1318
+ )
1319
+ def get_thermocouple_channels(self) -> str:
1320
+ """Returns a list of all analogue input channels that support thermocouples on the instrument.
1321
+
1322
+ If no channels support thermocouples on the instrument, an empty list (@) is returned.
1323
+
1324
+ Returns:
1325
+ List of all analogue input channels that support thermocouples on the instrument.
1326
+
1327
+ Examples:
1328
+ The following example returns the list of analogue input channels on the instrument, as well as the channels
1329
+ that support thermocouples. In this case, all 48 channels (0 to 47) support thermocouples:
1330
+
1331
+ > :SYST:CHAN?
1332
+ < @0:47
1333
+ > :SYST:CHAN:TC?
1334
+ < @0:47
1335
+
1336
+ In the following example, only channels 0 to 15 of the available 48 channels support thermocouples:
1337
+
1338
+ > :SYST:CHAN?
1339
+ < @0:47
1340
+ > :SYST:CHAN:TC?
1341
+ < @0:15
1342
+ """
1343
+
1344
+ pass
1345
+
1346
+ @dynamic_command(
1347
+ cmd_string=":SYSTem:CHANnel:VOLTage:RANGe?",
1348
+ cmd_type=CommandType.TRANSACTION,
1349
+ process_cmd_string=add_lf,
1350
+ )
1351
+ def get_voltage_range_channels(self) -> str:
1352
+ """Returns a list of analogue input channels that support programmable voltage ranges on the instrument.
1353
+
1354
+ If no channels support programmable voltage ranges on the instrument, an empty list (@) is returned.
1355
+
1356
+ Returns:
1357
+ List of all analogue input channels that support programmable voltage ranges on the instrument.
1358
+
1359
+ Examples:
1360
+ The following example returns which channels support programmable voltage ranges; in this case, channels 0
1361
+ to 7 support thermocouples, while channels 8 to 15 support RTDs, and channels 16 to 23 support programmable
1362
+ voltage ranges:
1363
+ > *IDN?
1364
+ < Data Translation,DT7774-08T-08R-08V,-1,1.8,0.0
1365
+ > :SYSTem:CHANnel?
1366
+ < (@0:23)
1367
+ >:SYSTem:CHANnel:RTD?
1368
+ < (@8:15)
1369
+ > :SYSTem:CHANnel:TC?
1370
+ < (@0:7)
1371
+ > :SYSTem:CHANnel:VOLTage:RANGe?
1372
+ < (@16:23)
1373
+ """
1374
+
1375
+ pass
1376
+
1377
+ @dynamic_command(
1378
+ cmd_string=":SYSTem:DINput?",
1379
+ cmd_type=CommandType.TRANSACTION,
1380
+ process_cmd_string=add_lf,
1381
+ process_response=to_int,
1382
+ )
1383
+ def get_num_digital_input_lines(self) -> int:
1384
+ """Returns the number of digital input lines that are supported by the instrument.
1385
+
1386
+ Returns:
1387
+ Number of digital input lines that are supported by the instrument.
1388
+
1389
+ Examples:
1390
+ The following example returns the number of digital input lines supported by the instrument:
1391
+
1392
+ > :SYSTem:DINput?
1393
+ < 8
1394
+ """
1395
+
1396
+ pass
1397
+
1398
+ @dynamic_command(
1399
+ cmd_string=":SYSTem:DINput?",
1400
+ cmd_type=CommandType.TRANSACTION,
1401
+ process_cmd_string=add_lf,
1402
+ process_response=to_int,
1403
+ )
1404
+ def get_num_digital_output_lines(self) -> int:
1405
+ """Returns the number of digital output lines that are supported by the instrument.
1406
+
1407
+ Returns:
1408
+ Number of digital output lines that are supported by the instrument.
1409
+
1410
+ Examples:
1411
+ The following example returns the number of digital output lines supported by the instrument:
1412
+
1413
+ > :SYSTem:DOUTput?
1414
+ < 8
1415
+ """
1416
+
1417
+ pass
1418
+
1419
+ @dynamic_command(
1420
+ cmd_string=":SYSTem:SCAn:RATe:MAXimum:SEC?",
1421
+ cmd_type=CommandType.TRANSACTION,
1422
+ process_cmd_string=add_lf,
1423
+ process_response=to_float,
1424
+ )
1425
+ def get_max_scan_rate(self) -> float:
1426
+ """Returns the maximum scan rate in s.
1427
+
1428
+ Returns:
1429
+ Maximum scan rate [s].
1430
+
1431
+ Examples:
1432
+ The following example returns the maximum scan rate that is supported by the instrument, in seconds:
1433
+
1434
+ > :SYST:SCA:MAX:SEC?
1435
+ < 0.10000
1436
+ """
1437
+
1438
+ pass
1439
+
1440
+ @dynamic_command(
1441
+ cmd_string=":SYSTem:SCAn:RATe:MAXimum:HZ?",
1442
+ cmd_type=CommandType.TRANSACTION,
1443
+ process_cmd_string=add_lf,
1444
+ process_response=to_float,
1445
+ )
1446
+ def get_max_scan_frequency(self) -> float:
1447
+ """Returns the maximum frequency rate in Hz.
1448
+
1449
+ Returns:
1450
+ Maximum frequency rate [s].
1451
+
1452
+ Examples:
1453
+ The following example returns the maximum scan rate that is supported by the instrument, in Hz:
1454
+
1455
+ > :SYST:SCA:MAX:HZ?
1456
+ < 10.00000
1457
+ """
1458
+
1459
+ pass
1460
+
1461
+ @dynamic_command(
1462
+ cmd_string=":SYSTem:SCAn:RATe:MINimum:SEC?",
1463
+ cmd_type=CommandType.TRANSACTION,
1464
+ process_cmd_string=add_lf,
1465
+ process_response=to_float,
1466
+ )
1467
+ def get_min_scan_rate(self) -> float:
1468
+ """Returns the minimum scan rate in s.
1469
+
1470
+ Returns:
1471
+ Minimum scan rate [s].
1472
+
1473
+ Examples:
1474
+ The following example returns the minimum scan rate that is supported by the instrument, in seconds:
1475
+
1476
+ > :SYST:SCA:MIN:SEC?
1477
+ < 6553.5
1478
+ """
1479
+
1480
+ pass
1481
+
1482
+ @dynamic_command(
1483
+ cmd_string=":SYSTem:SCAn:RATe:MINimum:HZ?",
1484
+ cmd_type=CommandType.TRANSACTION,
1485
+ process_cmd_string=add_lf,
1486
+ process_response=to_float,
1487
+ )
1488
+ def get_min_scan_frequency(self) -> float:
1489
+ """Returns the minimum frequency rate in Hz.
1490
+
1491
+ Returns:
1492
+ Minimum frequency rate [s].
1493
+
1494
+ Examples:
1495
+ The following example returns the minimum scan rate that is supported by the instrument, in Hz:
1496
+
1497
+ > :SYST:SCA:MIN:HZ?
1498
+ < 1.525e-4
1499
+ """
1500
+
1501
+ pass
1502
+
1503
+ @dynamic_command(
1504
+ cmd_string=":SYSTem:TIME?",
1505
+ cmd_type=CommandType.TRANSACTION,
1506
+ process_cmd_string=add_lf,
1507
+ process_response=format_to_time,
1508
+ )
1509
+ def get_time(self) -> tuple[int, int, int]:
1510
+ """Returns the current time used by the instrument.
1511
+
1512
+ This date is updated automatically by an SNTP server.
1513
+
1514
+ Returns:
1515
+ Tuple of (hour, minute, second)
1516
+
1517
+ Examples:
1518
+ This response indicates that the current time of the instrument is 15:31:45 (15 is the hour, 31 is the
1519
+ number of minutes, and 45 is the number of seconds):
1520
+
1521
+ > :SYST:TIME?
1522
+ < 15:31:45
1523
+ """
1524
+
1525
+ pass
1526
+
1527
+ @dynamic_command(
1528
+ cmd_string=":SYSTem:TZONe?",
1529
+ cmd_type=CommandType.TRANSACTION,
1530
+ process_cmd_string=add_lf,
1531
+ )
1532
+ def get_timezone(self) -> tuple[int, int]:
1533
+ """Returns the timezone that is currently used by the instrument, as an offset from GMT.
1534
+
1535
+ Returns:
1536
+ Tuple of (number of hours offset from GMT, number of minutes offset from GMT) that shows the offset of the
1537
+ current time relative to GMT.
1538
+
1539
+ Examples:
1540
+ This response indicates that the current timezone of the instrument if four hours and 30 minutes ahead of
1541
+ GMT:
1542
+
1543
+ > :SYST:TZON?
1544
+ < 4, -45
1545
+ """
1546
+
1547
+ # TODO
1548
+
1549
+ pass
1550
+
1551
+ @dynamic_command(
1552
+ cmd_string=":SYSTem:TZONe ${hour},${minute}",
1553
+ cmd_type=CommandType.WRITE,
1554
+ process_cmd_string=add_lf,
1555
+ )
1556
+ def set_timezone(self, hour: int, minute: int = 0) -> None:
1557
+ """Sets the timezone currently used by the instrument as an offset from GMT.
1558
+
1559
+ The specified hour and minute are added to the UTC time that is maintained by the instrument.
1560
+
1561
+ This is a password-protected command.
1562
+
1563
+ Args:
1564
+ hour (int): Current hour relative to UTC.
1565
+ minute (int): Current minute relative to UTC.
1566
+
1567
+ Examples:
1568
+ This command sets the current timezone used by the instrument to four hours and 30 minutes ahead of GMT:
1569
+
1570
+ > :SYST:TZON 4,-45
1571
+ """
1572
+
1573
+ pass
1574
+
1575
+ # CONFigure Sub-System Commands
1576
+
1577
+ @dynamic_command(
1578
+ cmd_string=":CONFigure:RESistance ${channels}",
1579
+ cmd_type=CommandType.WRITE,
1580
+ process_cmd_string=add_lf,
1581
+ )
1582
+ def set_resistance_channels(self, channels: str = "(@0:47)"):
1583
+ """Configures specified channels for resistance measurements.
1584
+
1585
+ This can only be applied to channels that support resistance measurements. This command affects the
1586
+ configuration of the specified channels only.
1587
+
1588
+ The number of channels that you can specify depends on the configuration of your instrument.
1589
+
1590
+ This is a password-protected command.
1591
+
1592
+ Refer to 1999 SCPI Command Reference, Sect. 3.1 and 3.7.2, and 1999 SCPI Syntax & Style, Sect. 8.3.2, for more
1593
+ information.
1594
+
1595
+ Args:
1596
+ channels (str): List of channels to configure for resistance measurements.
1597
+
1598
+ Examples:
1599
+ The following command configures analogue input channels 0, 3 to 7, and 47 on the instrument for resistance
1600
+ measurements:
1601
+
1602
+ > :CONF:RES (@0,3:7,47)
1603
+
1604
+ This command configures all analogue input channels on the instrument for resistance measurements:
1605
+
1606
+ > :CONF:RES
1607
+
1608
+ This command configures analogue input channels 1, 2, and 8 to 46 on the instrument for resistance
1609
+ measurements:
1610
+
1611
+ > :CONF:RES (@1,2,8:46)
1612
+ """
1613
+
1614
+ pass
1615
+
1616
+ @dynamic_command(
1617
+ cmd_string=":CONFigure:TEMPerature:RTD ${rtd_type},${channels}",
1618
+ cmd_type=CommandType.WRITE,
1619
+ process_cmd_string=add_lf,
1620
+ )
1621
+ def set_rtd_temperature_channels(self, rtd_type: str, channels: str = "(@0:47)"):
1622
+ """Configures specified channels on the instrument for RTD temperature measurements.
1623
+
1624
+ Allowed RTD types are:
1625
+ - For 2- or 4-wire European RTDs:
1626
+ - PT100
1627
+ - PT500
1628
+ - PT1000
1629
+ - For 2- or 4-wire American RTDs:
1630
+ - A_PT100
1631
+ - A_PT500
1632
+ - A_PT1000
1633
+ - For 3-wire European RTDs:
1634
+ - PT100_3
1635
+ - PT500_3
1636
+ - PT1000_3
1637
+ - For 3-wire American RTDs:
1638
+ - A_PT100_3
1639
+ - A_PT500_3
1640
+ - A_PT1000_3
1641
+ - DEFault
1642
+
1643
+ This commands affects the configuration of the specified channels only.
1644
+
1645
+ The number of channels that you can specify depends on the configuration of your instrument.
1646
+
1647
+ This is a password-protected command.
1648
+
1649
+ Args:
1650
+ rtd_type (str): RTD type to be used for the temperature measurements.
1651
+ channels (str): List of channels to configure for RTD temperature measurements.
1652
+
1653
+ Examples:
1654
+ This example configures analogue input channel 8 to use a PT1000 2- or 4-wire European RTF:
1655
+
1656
+ > :CONF:TEMP:RTD PT1000, (@8)
1657
+ > *STB?
1658
+ < 0
1659
+
1660
+ The following example tries to configure all analogue input channels on the instrument to use a PT100
1661
+ 2- or 4-wire European RTD. However, in this example, no channels support RTD input; therefore an
1662
+ Execution Error occurs. If bit 4 (E) of the Standard Event Status Enable register is enable, an
1663
+ Execution Error sets but 4 (E) of the Standard Event Status register. This, in turn, will set bits 2 and 5
1664
+ of the Status Byte register:
1665
+
1666
+ > *ESE 189
1667
+ > ESR?
1668
+ < 0
1669
+ > :CONF:TEMP:RTP PT100
1670
+ > *STB?
1671
+ < 36
1672
+ > ESR?
1673
+ < 16
1674
+ > :SYST;ERR?
1675
+ < -200, "Execution error;CONF:TEMP:RTD invalid"
1676
+ > *STB?
1677
+ < 0
1678
+ """
1679
+
1680
+ pass
1681
+
1682
+ @dynamic_command(
1683
+ cmd_string=":CONFigure:TEMPerature:TCouple ${tc_type}, ${channels}",
1684
+ cmd_type=CommandType.WRITE,
1685
+ process_cmd_string=add_lf,
1686
+ )
1687
+ def set_thermocouple_temperature_channels(self, tc_type: str, channels: str = "(@0:47)"):
1688
+ """Configures specified channels on the instrument for thermocouple temperature measurements.
1689
+
1690
+ Allowed thermocouple types are:
1691
+ - J (Iron/Constantan)
1692
+ - K (Nickel-Chromium / Nickel-Alumel)
1693
+ - B (Platinum Rhodium -30% / Platinum Rhodium -6%)
1694
+ - E (Nickel-Chromium/Constantan)
1695
+ - N (Nicrosil/Nisil)
1696
+ - R (Platinum Rhodium -13% / Platinum)
1697
+ - S (Platinum Rhodium -10% / Platinum)
1698
+ - T (Copper/Constantan)
1699
+ - DEFault
1700
+
1701
+ This commands affects the configuration of the specified channels only.
1702
+
1703
+ The number of channels that you can specify depends on the configuration of your instrument.
1704
+
1705
+ This is a password-protected command.
1706
+
1707
+ Args:
1708
+ tc_type (str): Thermocouple type to be used for the temperature measurements.
1709
+ channels (str): List of channels to configure for thermocouple temperature measurements.
1710
+
1711
+ Examples:
1712
+ This example configures analogue input channel 3 to use a K-type thermocouple:
1713
+
1714
+ > :CONF:TEMP:TCouple K, (@3)
1715
+ > *STB?
1716
+ < 0
1717
+
1718
+ The following example tries to configure the analogue input channels to use an S-type thermocouple. In
1719
+ this example, the instrument does not support thermocouple channels; therefore, an Execution Error occurs.
1720
+ If bit 4 (E) of the Standard Event Status Enable register is enable, an Execution Error sets but 4 (E) of
1721
+ the Standard Event Status register. This, in turn, will set bits 2 and 5 of the Status Byte register:
1722
+
1723
+ > *ESE 189
1724
+ > ESR?
1725
+ < 0
1726
+ > :CONF:TEMP:TC S
1727
+ > *STB?
1728
+ < 36
1729
+ > ESR?
1730
+ < 16
1731
+ > :SYST;ERR?
1732
+ < -200, "Execution error;CONF:TEMP:TC invalid"
1733
+ > *STB?
1734
+ < 0
1735
+ """
1736
+
1737
+ pass
1738
+
1739
+ @dynamic_command(
1740
+ cmd_string=":CONFigure:VOLTage ${channels}",
1741
+ cmd_type=CommandType.WRITE,
1742
+ process_cmd_string=add_lf,
1743
+ )
1744
+ def set_voltage_channels(self, channels: str = "(@0:47)"):
1745
+ """Configures specified RTD and thermocouple channels on the instrument for voltage measurements.
1746
+
1747
+ This commands affects the configuration of the specified channels only.
1748
+
1749
+ The number of channels that you can specify depends on the configuration of your instrument.
1750
+
1751
+ This is a password-protected command.
1752
+
1753
+ Args:
1754
+ channels (str): List of channels to configure for voltage measurements.
1755
+
1756
+ Examples:
1757
+ The following example configures analogue input channels 0, 3 to 7, and 47 for voltage measurements:
1758
+
1759
+ > :CONF:VOLT (@0,3:7,47)
1760
+
1761
+ This example configures all analogue input channels on the instrument for voltage measurements:
1762
+
1763
+ > :CONF:VOLT
1764
+
1765
+ This example configures analogue input channels 1, 2, and 8 to 46 for voltage measurements:
1766
+
1767
+ > :CONF:VOLT (@1,2,8:46)
1768
+ """
1769
+
1770
+ pass
1771
+
1772
+ @dynamic_command(
1773
+ cmd_string=":CONFigure:VOLTage:RANGe ${voltage_range},${channels}",
1774
+ cmd_type=CommandType.WRITE,
1775
+ process_cmd_string=add_lf,
1776
+ )
1777
+ def set_voltage_range_channels(self, voltage_range: str = "DEFault", channels: str = "(@0:47)"):
1778
+ """Configures the voltages range for specified channels on the instrument.
1779
+
1780
+ Allowed voltage ranges are:
1781
+ - BIP100MV: Specifies an input voltage range of +/-0.1V,
1782
+ - BIP1V: Specifies an input voltage range of +/-1V,
1783
+ - BIP10V: Specifies an input voltage range of +/-10V,
1784
+ - BIP100V: Specifies an input voltage range of +/-100V,
1785
+ - BIP400V: Specifies an input voltage range of +/-400V,
1786
+ - BIP60V: Specifies an input voltage range of +/-60V,
1787
+ - DEFault: Selects the default voltage range of +/-10V.
1788
+
1789
+ This commands affects the configuration of the specified channels only.
1790
+
1791
+ The number of channels that you can specify depends on the configuration of your instrument.
1792
+
1793
+ This is a password-protected command.
1794
+
1795
+ Args:
1796
+ voltage_range (str): Voltage range to be used for the voltage measurements.
1797
+ channels (str): List of channels to configure for voltage measurements.
1798
+
1799
+ Examples:
1800
+ The following example returns the configuration of all channels on a MEASURpoint instrument; In this case,
1801
+ all channels on the instrument can be programmed for thermocouple measurements:
1802
+
1803
+ > :CONF:?
1804
+ < V,J,J,V,J,V,J,J,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V
1805
+
1806
+ This example configures all channels for a type J thermocouple, and then reconfigures channels 0, 3, and 5
1807
+ for voltage inputs. In the first query, the configuration of channels 0 and 7 is returned. In the second
1808
+ query, the configuration of channels 0 through 7 is returned:
1809
+
1810
+ > :CONF:TEMP:TC J
1811
+ > :CONF:VOLT (@0,3,5)
1812
+ > :CONF? (@0,7)
1813
+ < V,J
1814
+ > :CONFigure? (@0:7)
1815
+ < V,J,J,V,J,V,J,J
1816
+
1817
+ The following example returns the configuration of all channels on a MEASURpoint instrument; in this case,
1818
+ all channels on the instrument can be programmed for thermocouple measurements:
1819
+
1820
+ > :CONF?
1821
+ < V,J,J,V,J,V,J,J,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V,V
1822
+
1823
+ This example configures all channels for a type J thermocouple, and then reconfigures channels 0, 3, and 5
1824
+ for voltage inputs. In the first query, the configuration of channels 0 and 7 is returned. In the second
1825
+ query, the configuration of channels 0 through 7 is returned:
1826
+
1827
+ > :CONF:TEMP:TC J
1828
+ > :CONF:VOLT (@0,3,5)
1829
+ > :CONF? (@0,7)
1830
+ < V,J
1831
+ > :CONFigure? (@0:7)
1832
+ < V,J,J,V,J,V,J,J
1833
+
1834
+ In this example, the configuration of channels 0 through 7 of a MEASURpoint instrument that supports
1835
+ programmable voltage ranges is returned:
1836
+ > :CONF? (@0:7)
1837
+ < BIP10V,BIP10V,BIP60V,BIP60V,BIP60V,BIP60V,BIP60V,BIP60V
1838
+ """
1839
+
1840
+ # TODO Only for VOLTpoint + MEASURpoint
1841
+ pass
1842
+
1843
+ @dynamic_command(
1844
+ cmd_string=":CONFigure? ${channels}",
1845
+ cmd_type=CommandType.TRANSACTION,
1846
+ process_cmd_string=add_lf,
1847
+ )
1848
+ def get_channel_config(self, channels: str = "(@0:47)"):
1849
+ """Returns the configuration of the specified channels on the instrument.
1850
+
1851
+ Returns up to 48 fields of comma-separated values. Each field contains the configuration of a channel:
1852
+ - For each thermocouple input, one of the following thermocouple value is returned: J, K, R, S, T, B, E, N.
1853
+ - For each RTD input, one of the following RTD value is returned: PT100, PT500, PT1000, A_PT100, A_PT500,
1854
+ A_PT1000, PT100_3, PT500_3, PT1000_3, A_PT100_3, A_PT500_3, A_PT1000_3.
1855
+ - For each voltage input, OHM is returned.
1856
+
1857
+ This is a password-protected command.
1858
+
1859
+ Args:
1860
+ channels (str): List of channels to configure for voltage measurements.
1861
+
1862
+ Returns:
1863
+ Up to 48 fields of comma-separated values. Each field contains the configuration of a channel.
1864
+
1865
+ Examples:
1866
+ The following examples set the filter type and then return the current filter configuration:
1867
+
1868
+ > :CONF:FILT AVG
1869
+ > :CONF:FILT?
1870
+ < AVG
1871
+
1872
+ >:CONF:FILT RAW
1873
+ > :CONF:FILT?
1874
+ < RAW
1875
+ """
1876
+
1877
+ pass
1878
+
1879
+ @dynamic_command(
1880
+ cmd_string=":CONFigure:FILTer ${filter_type}",
1881
+ cmd_type=CommandType.WRITE,
1882
+ process_cmd_string=add_lf,
1883
+ )
1884
+ def set_filter_type(self, filter_type: str) -> BaseException:
1885
+ """Configures the filter type used for single-value and continuous analogue input operations.
1886
+
1887
+ Allowed filter types are:
1888
+ - RAW: No filtering. Provides fast response times, but the data may be difficult to interpret. Use when
1889
+ you want to filter the data yourself.
1890
+ - AVG: Moving average. Provides a compromise of filter functionality and response time. Can be used in
1891
+ any application.
1892
+
1893
+ Args:
1894
+ filter_type (str): Filter type to be used for the analogue input operations.
1895
+ """
1896
+
1897
+ pass
1898
+
1899
+ @dynamic_command(
1900
+ cmd_string=":CONFigure:FILTer?",
1901
+ cmd_type=CommandType.TRANSACTION,
1902
+ process_cmd_string=add_lf,
1903
+ )
1904
+ def get_filter_type(self) -> str:
1905
+ """Returns the currently configured filter type for the instrument.
1906
+
1907
+ Allowed filter types are:
1908
+ - RAW: No filtering. Provides fast response times, but the data may be difficult to interpret. Use when
1909
+ you want to filter the data yourself.
1910
+ - AVG: Moving average. Provides a compromise of filter functionality and response time. Can be used in
1911
+ any application.
1912
+
1913
+ This is a password-protected command.
1914
+
1915
+ Returns:
1916
+ Currently configured filter type.
1917
+
1918
+ Examples:
1919
+ The following examples set the filter type, and then return the current configuration of the filter type:
1920
+
1921
+ > :CONF:FILT AVG
1922
+ > :CONF:FILT?
1923
+ < AVG
1924
+
1925
+ > :CONF:FILT RAW
1926
+ > :CONF:FILT?
1927
+ < RAW
1928
+ """
1929
+
1930
+ pass
1931
+
1932
+ @dynamic_command(
1933
+ cmd_string=":CONFigure:SCAn:BUFfer?",
1934
+ cmd_type=CommandType.TRANSACTION,
1935
+ process_cmd_string=add_lf,
1936
+ process_response=to_int,
1937
+ )
1938
+ def get_scan_circular_buffer_size(self) -> int:
1939
+ """Returns the size of the circular buffer that is used to store the scan data.
1940
+
1941
+ Returns:
1942
+ Size of the circular buffer that is used to store the scan data [bytes].
1943
+
1944
+ Examples:
1945
+ The following example returns the size of the circular buffer that is used to store scan data on the
1946
+ instrument:
1947
+
1948
+ > :CONFigure:SCAn:BUFfer?
1949
+ < 1048576
1950
+ > :CONFigure:SCAn:BUF:LEN?
1951
+ < 1048576
1952
+ > :CONFigure:SCAn:BUFfer?
1953
+ < 1048576
1954
+ > :CONFigure:SCAn:BUF?
1955
+ < 1048576
1956
+ """
1957
+
1958
+ pass
1959
+
1960
+ @dynamic_command(
1961
+ cmd_string=":CONFigure:SCAn:CJC ${cjc}",
1962
+ cmd_type=CommandType.WRITE,
1963
+ process_cmd_string=add_lf,
1964
+ )
1965
+ def set_scan_cjc(self, cjc: str | int) -> None:
1966
+ """Enable the capacity of returning CJC data in the analogue input data stream.
1967
+
1968
+ Allowed values are:
1969
+ - ON or any non-zero numerical value: Return CJC data in the analogue input stream.
1970
+ - OFF, 0, or DEFault: Don't return CJC in the analogue input stream.
1971
+
1972
+ This is a password-protected command.
1973
+
1974
+ Args:
1975
+ cjc (str): Enable the capacity of returning CJC data in the analogue input data stream.
1976
+
1977
+ Examples:
1978
+ Any of the following commands disables the capability of returning CJC data in the analogue input data
1979
+ stream:
1980
+ > :CONF:SCAn:CJC;:CONF:SCAn:CJC?
1981
+ < 0
1982
+ > :CONF:SCAn:CJC OFF;:CONF:SCAn:CJC?
1983
+ < 0
1984
+ > :CONF:SCAn:CJC DEF;:CONF:SCAn:CJC?
1985
+ < 0
1986
+ > :CONF:SCAn:CJC 0;:CONF:SCAn:CJC?
1987
+ < 0
1988
+ > :CONF:SCAn:CJC ON;:CONF:SCAn:CJC?
1989
+ < 1
1990
+ > :CONF:SCAn:CJC 1;:CONF:SCAn:CJC?
1991
+ < 1
1992
+ > :CONF:SCAn:CJC 34;:CONF:SCAn:CJC?
1993
+ < 1
1994
+ """
1995
+
1996
+ pass
1997
+
1998
+ @dynamic_command(
1999
+ cmd_string=":CONFigure:SCAn:CJC?",
2000
+ cmd_type=CommandType.TRANSACTION,
2001
+ process_cmd_string=add_lf,
2002
+ process_response=to_int,
2003
+ )
2004
+ def get_scan_cjc(self) -> int:
2005
+ """Returns the currently configured CJC data in the analogue input data stream.
2006
+
2007
+ Allowed values are:
2008
+ - 1: Return CJC data in the analogue input stream.
2009
+ - 0: Don't return CJC in the analogue input stream.
2010
+
2011
+ Refer to 1999 SCPI Syntax & Style, Sect. 7.3 for more information.
2012
+
2013
+ Returns:
2014
+ If the capability of returning CJC data in the analogue input data stream is enabled, a value of 1 is
2015
+ returned. If the capability of returning CJC data in the analogue input data stream is disabled, a value
2016
+ of 0 is returned.
2017
+
2018
+ Examples:
2019
+ Any of the following commands disables the capability of returning CJC data in the analogue input data
2020
+ stream:
2021
+ > :CONF:SCAn:CJC;:CONF:SCAn:CJC?
2022
+ < 0
2023
+ > :CONF:SCAn:CJC OFF;:CONF:SCAn:CJC?
2024
+ < 0
2025
+ > :CONF:SCAn:CJC DEF;:CONF:SCAn:CJC?
2026
+ < 0
2027
+ > :CONF:SCAn:CJC 0;:CONF:SCAn:CJC?
2028
+ < 0
2029
+ > :CONF:SCAn:CJC ON;:CONF:SCAn:CJC?
2030
+ < 1
2031
+ > :CONF:SCAn:CJC 1;:CONF:SCAn:CJC?
2032
+ < 1
2033
+ > :CONF:SCAn:CJC 34;:CONF:SCAn:CJC?
2034
+ < 1
2035
+ """
2036
+
2037
+ pass
2038
+
2039
+ @dynamic_command(
2040
+ cmd_string=":CONFigure:SCAn:LISt ${channels}",
2041
+ cmd_type=CommandType.WRITE,
2042
+ process_cmd_string=add_lf,
2043
+ )
2044
+ def set_scan_list(self, channels: str = "(@0:47)") -> None:
2045
+ """Enables a list of channels to scan on the instrument.
2046
+
2047
+ This is a password-protected command.
2048
+
2049
+ Refer to 1999 SCPI Syntax & Style, Sect. 8.3.2, for more information.
2050
+
2051
+ Args:
2052
+ channels (str): List of channels to scan on the instrument.
2053
+
2054
+ Examples:
2055
+ This example enables channels 0, 4, 5, and 7 and then returns the list of enabled channels; note that while
2056
+ this command tries to enable channel 5 twice, it is enabled only once:
2057
+
2058
+ > :CONF:SCAn:LISt (@5,4,7,0,5)
2059
+ > :CONF:SCAn:LISt?
2060
+ < (@0,4:5,7)
2061
+
2062
+ This example disables all channels; the list of enabled channels is empty:
2063
+ > :CONF:SCAn:LISt
2064
+ > :CONF:SCAn:LISt?
2065
+ < (@)
2066
+ This command enables channels 0, 4, 5, and 7 and returns the list of enabled channels:
2067
+ > :CONF:SCAn:LISt (@5,4,7,0)
2068
+ > :CONF:SCAn:LISt?
2069
+ < (@0,4:5,7)
2070
+
2071
+ This command enables channels 0, 4, 5, 6, and 7 and returns the list of enabled channels:
2072
+ > :CONF:SCAn:LISt (@5,4,7,6,0)
2073
+ > :CONF:SCAn:LISt?
2074
+ < (@0,4:7)
2075
+ """
2076
+
2077
+ pass
2078
+
2079
+ @dynamic_command(
2080
+ cmd_string=":CONFigure:SCAn:LISt?",
2081
+ cmd_type=CommandType.TRANSACTION,
2082
+ process_cmd_string=add_lf,
2083
+ )
2084
+ def get_scan_list(self) -> str:
2085
+ """Returns the list of channels that are enabled for scanning on the instrument.
2086
+
2087
+ Returns:
2088
+ List of channels that are enabled for scanning on the instrument.
2089
+
2090
+ Examples:
2091
+ The following example enables channels 0, 4, 5, and 7 and then returns the list of enabled channels; note
2092
+ that while this command tries to enable channel 5 twice, it is enabled only once:
2093
+ > :CONF:SCAn:LISt (@5,4,7,0,5)
2094
+ > :CONF:SCAn:LISt?
2095
+ < (@0,4:5,7)
2096
+
2097
+ This example disables all channels; the list of enabled channels is empty:
2098
+ > :CONF:SCAn:LISt;:CONF:SCAN:LISt?
2099
+ < (@)
2100
+
2101
+ This example enables channels 0, 4, 5, and 7 and then returns the list of enabled channels:
2102
+ > :CONF:SCAn:LISt (@5,4,7,0)
2103
+ > :CONF:SCAn:LISt?
2104
+ < (@0,4:5,7)
2105
+
2106
+ This example enables channels 0, 4, 5, 6, and 7 and then returns the list of enabled channels:
2107
+ > :CONF:SCAn:LISt (@5,4,7,6,0)
2108
+ > :CONF:SCAn:LISt?
2109
+ < (@0,4:7)
2110
+ """
2111
+
2112
+ pass
2113
+
2114
+ @dynamic_command(
2115
+ cmd_string=":CONFigure:SCAn:RATe:SEC ${rate}",
2116
+ cmd_type=CommandType.WRITE,
2117
+ process_cmd_string=add_lf,
2118
+ )
2119
+ def set_scan_rate(self, rate: float) -> None:
2120
+ """Configures the time period of each scan.
2121
+
2122
+ This is a password-protected command.
2123
+
2124
+ Args:
2125
+ rate (float): Time period of each scan [s].
2126
+
2127
+ Examples:
2128
+
2129
+ """
2130
+
2131
+ pass
2132
+
2133
+ @dynamic_command(
2134
+ cmd_string=":CONFigure:SCAn:RATe:HZ ${frequency}",
2135
+ cmd_type=CommandType.WRITE,
2136
+ process_cmd_string=add_lf,
2137
+ )
2138
+ def set_scan_frequency(self, frequency: float) -> None:
2139
+ """Configures the time period of each scan.
2140
+
2141
+ This is a password-protected command.
2142
+
2143
+ Args:
2144
+ frequency (float): Scan frequency [Hz].
2145
+
2146
+ Examples:
2147
+ The following command tries to set the scan frequency to 3Hz, but the actual scan frequency is set to 3.3Hz,
2148
+ which corresponds to a scan rate of 0.3s:
2149
+
2150
+ > :CONF:SCAn:RATe:HZ 3
2151
+ > :CONF:SCAn:RATe:HZ?
2152
+ < 3.333333
2153
+ > :CONF:SCAN:RATe?
2154
+ < 0.300000
2155
+
2156
+ The following command sets the scan frequency to 2Hz, which corresponds to a scan rate of 0.5s; the actual
2157
+ scan frequency is set to the same value, since 2 is an exact divisor of 10.0Hz:
2158
+
2159
+ > :CONF:SCAn:RATe 0.5
2160
+ > :CONF:SCAn:RATe:HZ?
2161
+ < 2.000000
2162
+ > :CONF:SCAN:RATe?
2163
+ < 0.500000
2164
+
2165
+ In this example, an invalid scan frequency is specified, and an Execution Error occurs. If bit 4 (E) of
2166
+ the Standard Event Status Enable register is enabled, an Execution Error sets bit 4 (E) of the Standard
2167
+ Event Status register. This, in turn, sets bits 2 and 5 of the Status Byte register:
2168
+
2169
+ > :CONF:SCAn:RATe:HZ 200
2170
+ > *STB?
2171
+ < 36
2172
+ > *ESR?
2173
+ < 16
2174
+ > *STB?
2175
+ < 4
2176
+ > :SYST:ERR?
2177
+ < -222,"Data out of range; CONF:SCAn:RATe"
2178
+ > *STB?
2179
+ < 0
2180
+ """
2181
+
2182
+ pass
2183
+
2184
+ @dynamic_command(
2185
+ cmd_string=":CONFigure:SCAn:RATe:SEC?",
2186
+ cmd_type=CommandType.TRANSACTION,
2187
+ process_cmd_string=add_lf,
2188
+ process_response=to_float,
2189
+ )
2190
+ def get_scan_rate(self) -> float:
2191
+ """Returns the time period of each scan [s]."""
2192
+ pass
2193
+
2194
+ @dynamic_command(
2195
+ cmd_string=":CONFigure:SCAn:RATe:HZ?",
2196
+ cmd_type=CommandType.TRANSACTION,
2197
+ process_cmd_string=add_lf,
2198
+ process_response=to_float,
2199
+ )
2200
+ def get_scan_frequency(self) -> float:
2201
+ """Returns the scan frequency [Hz].
2202
+
2203
+
2204
+ Examples:
2205
+ The following command tries to set the scan frequency to 3Hz, but the actual scan frequency is set to 3.3Hz,
2206
+ which corresponds to a scan rate of 0.3s:
2207
+
2208
+ > :CONF:SCAn:RATe:HZ 3
2209
+ > :CONF:SCAn:RATe:HZ?
2210
+ < 3.333333
2211
+ > :CONF:SCAN:RATe?
2212
+ < 0.300000
2213
+
2214
+ The following command sets the scan frequency to 2 Hz, which corresponds to a scan rate of 0.5 s; the
2215
+ actual scan frequency is set to the same value, since 2 is an exact divisor of 10.0 Hz:
2216
+
2217
+ > :CONF:SCAn:RATe 0.5
2218
+ > :CONF:SCAn:RATe:HZ?
2219
+ < 2.000000
2220
+ > :CONF:SCAN:RATe?
2221
+ < 0.500000
2222
+
2223
+ In this example, an invalid scan frequency is specified and an Execution Error occurs. If bit 4 (E) of the
2224
+ Standard Event Status Enable register is enabled, an Execution Error sets bit 4 (E) of the Standard Event
2225
+ Status register. This, in turn, sets bits 2 and 5 of the Status Byte register:
2226
+
2227
+ > :CONF:SCAn:RATe:HZ 200
2228
+ > *STB?
2229
+ < 36
2230
+ > *ESR?
2231
+ < 16
2232
+ > *STB?
2233
+ < 4
2234
+ > :SYST:ERR?
2235
+ < -222,"Data out of range; CONF:SCAn:RATe"
2236
+ > *STB?
2237
+ < 0
2238
+ """
2239
+
2240
+ pass
2241
+
2242
+ @dynamic_command(
2243
+ cmd_string=":CONFigure:TRIGger:SOURce ${source}",
2244
+ cmd_type=CommandType.WRITE,
2245
+ process_cmd_string=add_lf,
2246
+ )
2247
+ def set_trigger_source(self, source: str) -> None:
2248
+ """Configures the trigger source used to start the analogue input operation.
2249
+
2250
+ This is a password-protected command.
2251
+
2252
+ Allowed sources are:
2253
+ - IMMediate or DEFault: Specifies a software trigger.
2254
+ - DIN0: Specifies an external, digital trigger on DIN0.
2255
+
2256
+ Args:
2257
+ source (str): Trigger used to start the analogue input operation.
2258
+
2259
+ Examples:
2260
+ The following command sets the trigger source to the external, digital trigger:
2261
+
2262
+ > :CONF:TRIG DIN0
2263
+ """
2264
+
2265
+ pass
2266
+
2267
+ @dynamic_command(
2268
+ cmd_string=":CONFigure:TRIGger:SOURce?",
2269
+ cmd_type=CommandType.TRANSACTION,
2270
+ process_cmd_string=add_lf,
2271
+ )
2272
+ def get_trigger_source(self) -> str:
2273
+ """Returns the currently configured trigger source used to start the analogue input operation.
2274
+
2275
+ Allowed sources are:
2276
+ - IMMediate or DEFault: Specifies a software trigger.
2277
+ - DIN0: Specifies an external, digital trigger on DIN0.
2278
+
2279
+ Returns:
2280
+ Currently configured trigger source used to start the analogue input operation.
2281
+
2282
+ Examples:
2283
+ The following returns the currently configured trigger source of the instrument; in this case, an external
2284
+ digital trigger is configured:
2285
+
2286
+ > :CONF:TRIG?
2287
+ < DIN0
2288
+ """
2289
+
2290
+ pass
2291
+
2292
+ # MEASure Sub-System Commands
2293
+
2294
+ @dynamic_command(
2295
+ cmd_type=CommandType.TRANSACTION,
2296
+ cmd_string="MEASure:RESistance? ${channels}",
2297
+ process_cmd_string=add_lf,
2298
+ process_response=parse_single_measurement,
2299
+ )
2300
+ def get_resistance(self, channels: str = "(@0:47)") -> tuple[float, ...]:
2301
+ """Configures and returns the resistance measurement values for the specified channels.
2302
+
2303
+ This is a password-protected command.
2304
+
2305
+ Examples:
2306
+ The following example configures analogue input channels 0 for a resistance measurement and reads the
2307
+ resistance value from this channel:
2308
+
2309
+ > :MEAS:RES? (@0)
2310
+ < 2331344488fe4f0a
2311
+
2312
+ where:
2313
+ - 23 = '#' denotes the start of the block response
2314
+ - 31 = '1' is the length of the decimal number for the block length
2315
+ - 34 = '4' is the block length (that is 4-bytes per channel)
2316
+ - 4488fe4f = 1095.947 ohms; this is the resistance measurement value from channel 0
2317
+ - 0a = carriage return; this is the standard ASCII terminator
2318
+
2319
+ Args:
2320
+ channels (str): List of channels to configure for resistance measurements.
2321
+
2322
+ Returns:
2323
+ Data block of up to 48 single-precision, floating point values, where each value corresponds to a channel
2324
+ in the given list of channels [Ohm].
2325
+ """
2326
+
2327
+ pass
2328
+
2329
+ @dynamic_command(
2330
+ cmd_type=CommandType.TRANSACTION,
2331
+ cmd_string="MEASure:TEMPerature:RTD? ${rtd_type},${channels}",
2332
+ process_cmd_string=add_lf,
2333
+ process_response=parse_single_measurement,
2334
+ )
2335
+ def get_rtd_temperature(self, rtd_type: str, channels: str = "(@0:47)") -> tuple[float, ...]:
2336
+ """Configures and returns the RTD temperature measurement values for the specified channels.
2337
+
2338
+ This is a password-protected command.
2339
+
2340
+ Allowed RTD types are:
2341
+ - For 2- or 4-wire European RTDs:
2342
+ - PT100
2343
+ - PT500
2344
+ - PT1000
2345
+ - For 2- or 4-wire American RTDs:
2346
+ - A_PT100
2347
+ - A_PT500
2348
+ - A_PT1000
2349
+ - For 3-wire European RTDs:
2350
+ - PT100_3
2351
+ - PT500_3
2352
+ - PT1000_3
2353
+ - For 3-wire American RTDs:
2354
+ - A_PT100_3
2355
+ - A_PT500_3
2356
+ - A_PT1000_3
2357
+ - DEFault
2358
+
2359
+ Args:
2360
+ rtd_type (str): RTD type to be used for the temperature measurement.
2361
+ channels (str): List of channels to configure for RTD temperature measurement.
2362
+
2363
+ Returns:
2364
+ Data block of up to 48 single-precision, floating point values, where each value corresponds to a channel
2365
+ in the given list of channels [°C].
2366
+
2367
+ Examples:
2368
+ The following example configures analogue input channels 0, 1, 7 for the default sensor and transducer type
2369
+ for the instrument and then reads the temperature from these channels:
2370
+
2371
+ > :MEAS:TEMP:RTD? DEF,(@0,1,7)
2372
+ < 23323132c7ad9c0041bd99b647c34f800a
2373
+
2374
+ where:
2375
+ - 23 = '#' denotes the start of the block response
2376
+ - 32 = '2' is the length of the decimal number for the block length
2377
+ - 3132 = '12' is the block length (that is 4-bytes per channel times 3)
2378
+ - c7ad9c00 = –88888° C; this is the measurement value from channel 0, indicating that the value is too
2379
+ low and out of range
2380
+ - 41bd99b6 = 27.7° C; this is the measurement value from channel 1
2381
+ - 47c34f80 = 99999° C; this is the measurement value from channel 7
2382
+ - 0a = carriage return; this is the standard ASCII terminator
2383
+ """
2384
+
2385
+ pass
2386
+
2387
+ @dynamic_command(
2388
+ cmd_type=CommandType.TRANSACTION,
2389
+ cmd_string="MEASure:TEMPerature:TCouple?,${channels}",
2390
+ process_cmd_string=add_lf,
2391
+ process_response=parse_single_measurement,
2392
+ )
2393
+ def get_thermocouple_temperature(self, tc_type: str, channels: str = "(@0:47)") -> tuple[float, ...]:
2394
+ """Configures and returns the RTD temperature measurement values for the specified channels.
2395
+
2396
+ This is a password-protected command.
2397
+
2398
+ Allowed thermocouple types are:
2399
+ - J (Iron/Constantan)
2400
+ - K (Nickel-Chromium / Nickel-Alumel)
2401
+ - B (Platinum Rhodium -30% / Platinum Rhodium -6%)
2402
+ - E (Nickel-Chromium/Constantan)
2403
+ - N (Nicrosil/Nisil)
2404
+ - R (Platinum Rhodium -13% / Platinum)
2405
+ - S (Platinum Rhodium -10% / Platinum)
2406
+ - T (Copper/Constantan)
2407
+ - DEFault
2408
+
2409
+ Args:
2410
+ tc_type (str): Thermocouple type to be used for the temperature measurements.
2411
+ channels (str): List of channels to configure for RTD temperature measurement.
2412
+
2413
+ Returns:
2414
+ Data block of up to 48 single-precision, floating point values, where each value corresponds to a channel
2415
+ in the given list of channels [°C].
2416
+
2417
+ Examples:
2418
+ The following example configures analogue input channels 0, 1, 7 for the default sensor and transducer type
2419
+ for the instrument and then reads the temperature from these channels:
2420
+
2421
+ > :MEAS:TEMP:TC? DEF,(@0,1,7)
2422
+ < 23323132c7ad9c0041bd99b647c34f800a
2423
+
2424
+ where:
2425
+ - 23 = '#' denotes the start of the block response
2426
+ - 32 = '2' is the length of the decimal number for the block length
2427
+ - 3132 = '12' is the block length (that is 4-bytes per channel times 3)
2428
+ - c7ad9c00 = –88888° C; this is the measurement value from channel 0, indicating that the value is too
2429
+ low and out of range
2430
+ - 41bd99b6 = 27.7° C; this is the measurement value from channel 1
2431
+ - 47c34f80 = 99999° C; this is the measurement value from channel 7, indicating that an open
2432
+ thermocouple exists on that channel
2433
+ - 0a = carriage return; this is the standard ASCII terminator
2434
+ """
2435
+
2436
+ pass
2437
+
2438
+ @dynamic_command(
2439
+ cmd_type=CommandType.TRANSACTION,
2440
+ cmd_string="MEASure:VOLTage? ${channels}",
2441
+ process_cmd_string=add_lf,
2442
+ process_response=parse_single_measurement,
2443
+ )
2444
+ def get_voltage(self, channels: str = "(@0:47)") -> tuple[float, ...]:
2445
+ """Configures and returns the voltage measurement values for the specified channels.
2446
+
2447
+ This is a password-protected command.
2448
+
2449
+ Args:
2450
+ channels (str): List of channels to configure for RTD temperature measurement.
2451
+
2452
+ Returns:
2453
+ Data block of up to 48 single-precision, floating point values, where each value corresponds to a channel
2454
+ in the given list of channels [V].
2455
+
2456
+ Examples:
2457
+ The following example configures analogue input channels 0, 1, 7 for voltage measurements and then reads
2458
+ the values from these channels:
2459
+
2460
+ > :MEAS:VOLT? (@0,1,7)
2461
+ < 233231323f0f8aec3edefa51bf2844b80a
2462
+
2463
+ where:
2464
+ - 23 = '#' denotes the start of the block response
2465
+ - 32 = '2' is the length of the decimal number for the block length
2466
+ - 3132 = '12' is the block length (that is 4-bytes per channel times 3)
2467
+ - 3f0f8aec = 0.56071 V; this is the measurement value from channel 0
2468
+ - 3edefa51 = 0.43550 V; this is the measurement value from channel 1
2469
+ - bf2844b8 = –0.65729 V; this is the measurement value from channel 7
2470
+ - 0a = carriage return; this is the standard ASCII terminator
2471
+ """
2472
+
2473
+ # INITiate Sub-System Command
2474
+
2475
+ @dynamic_command(
2476
+ cmd_string=":INITiate",
2477
+ cmd_type=CommandType.WRITE,
2478
+ process_cmd_string=add_lf,
2479
+ )
2480
+ def init_scan(self) -> None:
2481
+ """Initiates a continuous scan operation on an instrument.
2482
+
2483
+ The continuous scan operation uses the configured channels, scan list, scan rate, and trigger source.
2484
+
2485
+ This is a password-protected command.
2486
+
2487
+ Examples:
2488
+ The following example configures the instrument to scan channels 0 to 5 at approximately 2Hz when an
2489
+ external digital trigger is detected, and queries the Operation Status register to verify that a scan
2490
+ operation is not in process:
2491
+
2492
+ > :CONF:SCA:LIS?
2493
+ < (@)
2494
+ >:CONF:SCA:LIS (@0:5)
2495
+ >:CONF:TRIG IMM
2496
+ > :CONF:SCA:RAT:HZ 2
2497
+ > :CONF:SCA:RAT:HZ?
2498
+ < 1.875000
2499
+ > :STAT:OPER:COND?
2500
+ < 0
2501
+
2502
+ The scan is then initiated, and bit 7 of the Status Byte register and the Operation Status register are
2503
+ queried to determine the status of the scan and whether the instrument has detected the trigger:
2504
+
2505
+ > :INIT
2506
+ > *STB?
2507
+ < 128
2508
+ > :STAT:OPER:COND?
2509
+ < 48
2510
+
2511
+ In this case, the scan has started, and the instrument is waiting for the trigger. The next query confirms
2512
+ that the trigger occurred and the instrument is scanning:
2513
+
2514
+ > *STB?
2515
+ < 128
2516
+ > :STAT:OPER:COND?
2517
+ < 16
2518
+
2519
+ The scan is then stopped and bit 7 of the Status Byte register and the Operation Status register are cleared:
2520
+
2521
+ > :ABOR
2522
+ > :STAT:OPER:COND?
2523
+ < 0
2524
+ > *STB?
2525
+ < 0
2526
+ """
2527
+
2528
+ pass
2529
+
2530
+ # ABORt Sub-System Command
2531
+
2532
+ @dynamic_command(
2533
+ cmd_string=":ABORt",
2534
+ cmd_type=CommandType.WRITE,
2535
+ process_cmd_string=add_lf,
2536
+ )
2537
+ def abort_scan(self) -> None:
2538
+ """Stops a scan operation on the instrument.
2539
+
2540
+ If a scan is in progress, it will be stopped, regardless of whether the specified trigger occurred.
2541
+
2542
+ This is a password-protected command.
2543
+
2544
+ Examples:
2545
+ The following example configures the instrument to scan channels 0 to 5 at approximately 2Hz when a
2546
+ software trigger is detected and queries the Operation Status register to verify that scans are stopped:
2547
+
2548
+ > :CONF:SCA:LIS?
2549
+ < (@)
2550
+ > :CONF:SCA:LIS (@0:5)
2551
+ > :CONF:TRIG IMM
2552
+ > :CONF:SCA:RAT:HZ 2
2553
+ > :CONF:SCA:RAT:HZ?
2554
+ < 1.875000
2555
+ > :STAT:OPER:COND?
2556
+ < 0
2557
+
2558
+ The scan is then started, and bit 7 of the Status Byte register the Operation Status register are queried
2559
+ to determine the status of the scan:
2560
+
2561
+ > :INIT
2562
+ > *STB?
2563
+ < 128
2564
+ > :STAT:OPER:COND?
2565
+ < 16
2566
+
2567
+ The scan is then stopped and bit 7 of the Status Byte register and the Operation Status register are cleared:
2568
+
2569
+ > :ABOR
2570
+ > :STAT:OPER:COND?
2571
+ < 0
2572
+ > *STB?
2573
+ < 0
2574
+ """
2575
+
2576
+ pass
2577
+
2578
+ # FETCh Sub-System Command
2579
+
2580
+ @dynamic_command(
2581
+ cmd_string=":FETCh? ${index}, ${num_scans}",
2582
+ cmd_type=CommandType.TRANSACTION,
2583
+ process_cmd_string=add_lf,
2584
+ process_response=parse_scan_records,
2585
+ )
2586
+ def fetch_data(self, index: int, num_scans: int) -> list[ScanRecord]:
2587
+ """Returns time-stamped, sequenced measurements from the circular buffer on the instrument, as scan records.
2588
+
2589
+ This only applies to the scans that were started with the INITiate command (`init_scan`).
2590
+
2591
+ Args:
2592
+ index (int): Index of the san record (offset in the circular buffer) from which to retrieve data. To read the first scan records, specify `1`.
2593
+ num_scans (int): Number of scan records to retrieve from the circular buffer.
2594
+
2595
+ Returns:
2596
+ A list of scan records, each containing the time-stamped, sequenced measurements.
2597
+
2598
+ Examples:
2599
+ The following example returns scan records, starting with index 0, on an instrument that has one channel
2600
+ (channel 0) enabled in the scan list:
2601
+
2602
+ > :FETC? 0
2603
+ <
2604
+ 23 ASCII # char that starts the IEEE block
2605
+ 34 ASCII 4, meaning that the next 4 chars are the length of the IEEE block
2606
+ 32303430 ASCII character 2040, representing the length of the entire IEEE block
2607
+
2608
+ 4a806d65 Scan record time stamp, in seconds
2609
+ 00000000 Scan record time stamp, in milliseconds
2610
+ 00000001 Scan record scan number (1)
2611
+ 00000001 Scan record number of values; 1 floating point value per scan
2612
+ 3a86c3ff Value of chan 0 in floating-point 6.5565103e-4
2613
+
2614
+ 4a806d65 Time stamp of next record, in seconds
2615
+ 00000064 Time stamp, in milliseconds
2616
+ 00000002 Scan number (2)
2617
+ 00000001 Number of values (1)
2618
+ 3a9a4bff Value of chan 0
2619
+
2620
+ 4a806d65 Timestamp of next record, in seconds
2621
+ 000000c8 Time stamp, in milliseconds
2622
+ 00000003 Scan number (3)
2623
+ 00000001 Number of values (1)
2624
+ 3ac543ff Value of chan 0
2625
+ .
2626
+ .
2627
+ .
2628
+ 4a806d6c Timestamp of next record, in seconds
2629
+ 00000064 Time stamp, in milliseconds
2630
+ 00000048 Scan number (48)
2631
+ 00000001 Number of values (1)
2632
+ 3a5ea800 Value of chan 0
2633
+
2634
+ This example returns two scan records (5 and 6) from an instrument that is scanning one channel:
2635
+
2636
+ > STATus:SCAn?
2637
+ < 1,1083
2638
+ > FETCh? 5, 2 (fetch records 5 and 6)
2639
+ 23 ASCII # char that starts the IEEE block
2640
+ 34 ASCII 4, meaning that the next 4 chars are the length of the IEEE block
2641
+ 30303430 ASCII character 0040, the length of the entire IEEE block (10 4-byte fields)
2642
+ 4a807ad3 Time stamp, in seconds
2643
+ 00000190 Time stamp, in milliseconds
2644
+ 00000005 Scan number (5)
2645
+ 00000001 Number of values (1)
2646
+ 3984cfff Value of channel
2647
+ 4a807ad3 Time stamp of next record, in seconds
2648
+ 000001f4 Time stamp, in milliseconds
2649
+ 00000006 Scan number (6)
2650
+ 00000001 Number of values (1)
2651
+ 393b7fff Value of channel 6
2652
+ 0a Carriage Return. This is the standard SCPI Terminator.
2653
+ """
2654
+
2655
+ pass
2656
+
2657
+ # Digital INPut Sub-System Command
2658
+
2659
+ @dynamic_command(
2660
+ cmd_string=":INPut:STATe?",
2661
+ cmd_type=CommandType.TRANSACTION,
2662
+ process_cmd_string=add_lf,
2663
+ process_response=to_int,
2664
+ )
2665
+ def get_digital_input_state(self) -> int:
2666
+ """Returns the current state of the digital input port on the instrument.
2667
+
2668
+ Refer to the 1999 SCPI Data Exchange Format, Sect. 3.4.6, for more information on the data format.
2669
+
2670
+ Returns: Weighted bit value of the digital input port, where the value of bit 0 (digital input 0) corresponds
2671
+ to a decimal value of 1 (2**0) if the bit is set, and the value of bit 7 (digital input 7)
2672
+ corresponds to a decimal value of 128 (2**7) if the bit is set. Values range from 0 to 255.
2673
+
2674
+ Examples:
2675
+ This response indicates that digital input lines 1 and 7 (bits 1 and 7) of the digital input port are
2676
+ set:
2677
+
2678
+ > :INPut:STATe?
2679
+ < 130
2680
+ """
2681
+
2682
+ pass
2683
+
2684
+ # Digital OUTPut Sub-System Commands
2685
+
2686
+ @dynamic_command(
2687
+ cmd_string=":OUTPut:STATe?",
2688
+ cmd_type=CommandType.TRANSACTION,
2689
+ process_cmd_string=add_lf,
2690
+ process_response=to_int,
2691
+ )
2692
+ def get_digital_output_state(self):
2693
+ """Returns the current state of the digital output port on the instrument.
2694
+
2695
+ Refer to the 1999 SCPI Data Exchange Format, Sect. 3.4.6, for more information on the data format.
2696
+
2697
+ Returns: Weighted bit value of the digital output port, where the value of bit 0 (digital input 0) corresponds
2698
+ to a decimal value of 1 (2**0) if the bit is set, and the value of bit 7 (digital input 7)
2699
+ corresponds to a decimal value of 128 (2**7) if the bit is set. Values range from 0 to 255.
2700
+
2701
+ Examples:
2702
+ This response indicates that digital input lines 1 and 7 (bits 1 and 7) of the digital input port are
2703
+ set:
2704
+
2705
+ > :OUTPut:STATe?
2706
+ < 130
2707
+ """
2708
+
2709
+ pass
2710
+
2711
+ @dynamic_command(
2712
+ cmd_string=":OUTPut:STATe ${state}",
2713
+ cmd_type=CommandType.WRITE,
2714
+ process_cmd_string=add_lf,
2715
+ )
2716
+ def set_digital_output_state(self, state: int):
2717
+ """Sets the state of the digital output port on the instrument.
2718
+
2719
+ This is a password-protected command.
2720
+
2721
+ Refer to the 1999 SCPI Data Exchange Format, Sect. 3.4.6, for more information on the data format.
2722
+
2723
+ Args:
2724
+ state (int): Weighted bit value of the digital output port, where the value of bit 0 (digital input 0)
2725
+ corresponds to a decimal value of 1 (2**0) if the bit is set, and the value of bit 7
2726
+ (digital input 7) corresponds to a decimal value of 128 (2**7) if the bit is set. Values
2727
+ range from 0 to 255.
2728
+
2729
+ Examples:
2730
+ This command sets digital output lines 0 and 7 (bits 0 and 7) to 1, and all other digital output lines
2731
+ (bits) to 0:
2732
+
2733
+ > :OUTPut:STATe 129
2734
+ """
2735
+
2736
+ pass
2737
+
2738
+
2739
+ class DigilentController(DigilentInterface, DynamicCommandMixin):
2740
+ def __init__(self):
2741
+ """Initialisation of a Digilent controller."""
2742
+
2743
+ super().__init__()
2744
+
2745
+ # Define device interface in the sub-class
2746
+
2747
+ self.transport: DigilentEthernetInterface | None = None
2748
+
2749
+ # noinspection PyMethodMayBeStatic
2750
+ def is_simulator(self):
2751
+ return False
2752
+
2753
+ def is_connected(self):
2754
+ """Checks whether the connection to the Digilent MEASURpoint is open.
2755
+
2756
+ Returns:
2757
+ True if the connection to the Digilent MEASURpoint is open; False otherwise.
2758
+ """
2759
+
2760
+ return self.transport.is_connected()
2761
+
2762
+ def connect(self):
2763
+ """Opens the connection to the Digilent MEASURpoint.
2764
+
2765
+ Raises:
2766
+ Dt8874Error: When the connection could not be opened.
2767
+ """
2768
+
2769
+ self.transport.connect()
2770
+
2771
+ def disconnect(self):
2772
+ """Closes the connection to the Digilent MEASURpoint.
2773
+
2774
+ Raises:
2775
+ Dt8874Error: When the connection could not be closed.
2776
+ """
2777
+
2778
+ self.transport.disconnect()
2779
+
2780
+ def reconnect(self):
2781
+ """Re-connects to the Digilent MEASURpoint."""
2782
+
2783
+ self.transport.reconnect()
2784
+
2785
+
2786
+ class DigilentSimulator(DigilentInterface):
2787
+ def __init__(self):
2788
+ """Initialisation of a Digilent simulator."""
2789
+
2790
+ super().__init__()
2791
+
2792
+ self._is_connected = True
2793
+
2794
+ # noinspection PyMethodMayBeStatic
2795
+ def is_simulator(self):
2796
+ return True
2797
+
2798
+ # noinspection PyMethodMayBeStatic
2799
+ def is_connected(self):
2800
+ return self._is_connected
2801
+
2802
+ def connect(self):
2803
+ self._is_connected = True
2804
+
2805
+ def disconnect(self):
2806
+ self._is_connected = False
2807
+
2808
+ def reconnect(self):
2809
+ self._is_connected = True