ariel-tcu 0.17.0__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.
egse/ariel/tcu/tcu.py ADDED
@@ -0,0 +1,1118 @@
1
+ """Ariel Telescope Control Unit (TCU) commanding.
2
+
3
+ Commanding is done by communicating with the TCU Arduino via a serial port (with the PySerial package).
4
+
5
+ We discern between the following types of commands:
6
+ - General commands;
7
+ - M2MD commands (on a per-axis basis);
8
+ - Thermal Monitoring System (TSM) commands;
9
+ - HK commands.
10
+
11
+ Reference documents:
12
+ - RD01: TCU User Manual (ARIEL-IEEC-PL-TN-002), v1.2
13
+ - RD02: ARIEL TCU Data Handling (ARIEL-IEEC-PL-TN-007), v1.0
14
+ - RD03: TCU code provided by Vladimiro Noce (priv. comm.)
15
+ - RD04: ARIEL Telescope Control Unit Design Description Document (ARIEL-IEEC-PL-DD-001), v1.10
16
+ - RD05: ARIEL TCU FW Architecture Design(ARIEL-IEEC-PL-DD-002), v1.5
17
+ """
18
+
19
+ import logging
20
+ from serial.tools import list_ports
21
+
22
+ from egse.ariel.tcu import PROXY_TIMEOUT, SERVICE_TYPE, TcuMode
23
+ from egse.ariel.tcu.tcu_cmd_utils import (
24
+ set_tcu_mode,
25
+ tcu_simulated,
26
+ restart_links_period_latch,
27
+ set_restart_links_period,
28
+ CommandAddress,
29
+ ope_mng_command,
30
+ ope_mng_event_clear_protect_flag,
31
+ ope_mng_event_clear,
32
+ ope_mng_status,
33
+ ope_mng_event_reg,
34
+ get_acq_curr_off_corr,
35
+ set_acq_curr_off_corr,
36
+ get_acq_curr_gain_corr,
37
+ set_acq_curr_gain_corr,
38
+ acq_axis_a_curr_read,
39
+ acq_axis_b_curr_read,
40
+ acq_ave_lpf_en,
41
+ acq_ovc_cfg_filter,
42
+ acq_avc_filt_time,
43
+ acq_average_type,
44
+ acq_spk_filt_counter_lim,
45
+ acq_spk_filt_incr_thr,
46
+ get_prof_gen_axis_step,
47
+ set_prof_gen_axis_step,
48
+ get_prof_gen_axis_speed,
49
+ set_prof_gen_axis_speed,
50
+ get_prof_gen_axis_state_start,
51
+ set_prof_gen_axis_state_start,
52
+ sw_rs_xx_sw_rise,
53
+ sw_rs_xx_sw_fall,
54
+ set_tsm_current_value,
55
+ set_tsm_current_offset,
56
+ set_tsm_adc_hpf_register,
57
+ set_tsm_adc_ofc_register,
58
+ set_tsm_adc_fsc_register,
59
+ tsm_adc_command,
60
+ tsm_adc_calibration,
61
+ tsm_adc_value_xx_currentn,
62
+ tsm_adc_value_xx_biasn,
63
+ tsm_adc_value_xx_currentp,
64
+ tsm_adc_value_xx_biasp,
65
+ tcu_firmware_id,
66
+ get_tcu_mode,
67
+ tcu_status,
68
+ get_restart_links_period,
69
+ tsm_latch,
70
+ get_tsm_current_value,
71
+ get_tsm_current_offset,
72
+ tsm_adc_id_register,
73
+ tsm_adc_configuration_register,
74
+ get_tsm_adc_ofc_register,
75
+ get_tsm_adc_fsc_register,
76
+ tsm_adc_command_latch,
77
+ tsm_acq_counter,
78
+ get_tsm_adc_hpf_register,
79
+ tsm_adc_register_latch,
80
+ vhk_psu_vmotor,
81
+ vhk_psu_vhi,
82
+ vhk_psu_vlow,
83
+ vhk_psu_vmedp,
84
+ vhk_psu_vmedn,
85
+ ihk_psu_vmedn,
86
+ ihk_psu_vlow,
87
+ ihk_psu_vmedp,
88
+ ihk_psu_vhi,
89
+ ihk_psu_vmotor,
90
+ thk_psu_first,
91
+ thk_m2md_first,
92
+ thk_psu_second,
93
+ thk_m2md_second,
94
+ thk_cts_q1,
95
+ thk_cts_q2,
96
+ thk_cts_q3,
97
+ thk_cts_q4,
98
+ thk_cts_fpga,
99
+ thk_cts_ads1282,
100
+ vhk_ths_ret,
101
+ hk_acq_counter,
102
+ )
103
+
104
+ from egse.device import DeviceInterface
105
+ from egse.mixin import dynamic_command, CommandType, DynamicCommandMixin
106
+ from egse.proxy import DynamicProxy
107
+ from egse.ariel.tcu.tcu_devif import TcuDeviceInterface
108
+ from egse.registry.client import RegistryClient
109
+ from egse.zmq_ser import connect_address
110
+
111
+ logger = logging.getLogger("egse.ariel.tcu")
112
+
113
+
114
+ def get_all_serial_ports() -> list:
115
+ """Returns a list of all available serial ports.
116
+
117
+ Returns:
118
+ List of all available serial ports.
119
+ """
120
+
121
+ ports = list_ports.comports()
122
+
123
+ for port in ports:
124
+ print(port)
125
+
126
+ return ports
127
+
128
+
129
+ class TcuInterface(DeviceInterface):
130
+ # General commands
131
+
132
+ @dynamic_command(cmd_type=CommandType.TRANSACTION, cmd_string_func=tcu_firmware_id)
133
+ def tcu_firmware_id(self):
134
+ """Selects the Instrument Control Unit (ICU) channel and returns the firmware version.
135
+
136
+ Returns:
137
+ Firmware version of the Ariel TCU.
138
+ """
139
+
140
+ pass
141
+
142
+ @dynamic_command(cmd_type=CommandType.TRANSACTION, cmd_string_func=get_tcu_mode)
143
+ def get_tcu_mode(self):
144
+ """Returns the current mode of the Ariel TCU.
145
+
146
+ Possible modes are:
147
+ - IDLE (0x0000): Waiting for commands, minimum power consumption
148
+ - BASE (0x0001): HK + TSM Circuitry on
149
+ - CALIBRATION (0x0003): HK + TSM + M2MD circuitry on
150
+
151
+ Returns:
152
+ Current mode of the Ariel TCU.
153
+ """
154
+
155
+ pass
156
+
157
+ @dynamic_command(cmd_type=CommandType.TRANSACTION, cmd_string_func=set_tcu_mode)
158
+ def set_tcu_mode(self, tcu_mode: TcuMode | int = TcuMode.IDLE):
159
+ """Selects the Ariel TCU working mode.
160
+
161
+ Args:
162
+ tcu_mode (TcuMode | int): Ariel TCU working mode:
163
+ - IDLE (0x0000): Waiting for commands, minimum power consumption
164
+ - BASE (0x0001): HK + TSM Circuitry on
165
+ - CALIBRATION (0x0003): HK + TSM + M2MD circuitry on
166
+ """
167
+
168
+ pass
169
+
170
+ @dynamic_command(cmd_type=CommandType.TRANSACTION, cmd_string_func=tcu_status)
171
+ def tcu_status(self):
172
+ """Returns the TCU status.
173
+
174
+ The TCU status is a bit word that indicates the current state of the TCU. The meaning of a bit being set
175
+ to one is as follows:
176
+
177
+ - bit 0: main link enabled
178
+ - bit 1: secondary link enabled
179
+ - bit 2: TSM enabled
180
+ - bit3: M2MD enabled
181
+ - bit 4: TSM in simulated mode
182
+ - bit 5: M2MD in simulated mode
183
+ - bit 6: HK in simulated mode
184
+ - bit 7: M2MD axis 1 enabled
185
+ - bit 8: M2MD axis 2 enabled
186
+ - bit 9: M2MD axis 3 enabled
187
+ - bit 10: TSM initialised
188
+ - bit 11: ADS_MFLAG active
189
+ - bit 12: ADS_REGISTERS_ERROR active
190
+
191
+ Returns:
192
+ Bit word that indicated the current state of the TCU.
193
+ """
194
+
195
+ pass
196
+
197
+ @dynamic_command(cmd_type=CommandType.TRANSACTION, cmd_string_func=tcu_simulated)
198
+ def tcu_simulated(self, cargo2: int):
199
+ """Changes a TCU sub-system in simulated mode.
200
+
201
+ This is only possible in IDLE mode.
202
+
203
+ The cargo2 parameter denotes which sub-system to change to simulated mode. The meaning of a bit being set to
204
+ one is as follows:
205
+
206
+ - bit 0: TBD
207
+ - bit 1: TBD
208
+ - bit 2: TBD
209
+ - bit 3: TBD
210
+ - bit 4: Put the TSM in simulated mode
211
+ - bit 5: Put the M2MD in simulated mode
212
+ - bit 6: Put the HK in simulated mode
213
+
214
+ Args:
215
+ cargo2 (int): Cargo 2 part of the command string.
216
+ """
217
+ pass
218
+
219
+ @dynamic_command(cmd_type=CommandType.TRANSACTION, cmd_string_func=restart_links_period_latch)
220
+ def restart_links_period_latch(self, cargo2: int):
221
+ """Re-starts the link period latch.
222
+
223
+ This is only possible in IDLE mode.
224
+
225
+
226
+ Note that a read does not disarm the latch.
227
+
228
+ Args:
229
+ cargo2 (int): Cargo 2 part of the command string.
230
+ """
231
+
232
+ pass
233
+
234
+ @dynamic_command(cmd_type=CommandType.TRANSACTION, cmd_string_func=get_restart_links_period)
235
+ def get_restart_links_period(self):
236
+ pass
237
+
238
+ @dynamic_command(cmd_type=CommandType.TRANSACTION, cmd_string_func=set_restart_links_period)
239
+ def set_restart_links_period(self, link_period: int = 0xFFFF):
240
+ """Re-start both links if no message is received after the given link period +1s.
241
+
242
+ Args:
243
+ link_period (int): 1s after this time duration, both links will be re-started if no message is received.
244
+ """
245
+ pass
246
+
247
+ # M2MD commands
248
+
249
+ @dynamic_command(cmd_type=CommandType.TRANSACTION, cmd_string_func=ope_mng_command)
250
+ def ope_mng_command(self, axis: CommandAddress | str | int, cargo2: int = 0x0002):
251
+ """Commands the action to the SENER motor driver IP core for the given M2MD axis.
252
+
253
+ The cargo2 parameter denotes the action to be performed. The meaning of a bit being set to
254
+ one is as follows:
255
+
256
+ - bit 0: Activate motion
257
+ - bit 1: Stop motion
258
+
259
+ Args:
260
+ axis (CommandAddress): Axis to which the command is sent.
261
+ cargo2 (int): Cargo 2 part of the command string.
262
+ """
263
+
264
+ pass
265
+
266
+ @dynamic_command(cmd_type=CommandType.TRANSACTION, cmd_string_func=ope_mng_event_clear_protect_flag)
267
+ def ope_mng_event_clear_protect_flag(self, axis: CommandAddress | str | int, cargo2: int = 0xAAAA):
268
+ """Clears the event register protection flag.
269
+
270
+ Args:
271
+ axis (CommandAddress): Axis to which the command is sent.
272
+ cargo2 (int): Cargo 2 part of the command string.
273
+ """
274
+
275
+ pass
276
+
277
+ @dynamic_command(cmd_type=CommandType.TRANSACTION, cmd_string_func=ope_mng_event_clear)
278
+ def ope_mng_event_clear(self, axis: CommandAddress | str | int, cargo2: int = 0x0001):
279
+ """Clears the event register for the given M2MD axis.
280
+
281
+ Args:
282
+ axis (CommandAddress): Axis to which the command is sent.
283
+ cargo2 (int): Cargo 2 part of the command string.
284
+ """
285
+
286
+ pass
287
+
288
+ @dynamic_command(cmd_type=CommandType.TRANSACTION, cmd_string_func=ope_mng_status)
289
+ def ope_mng_status(self, axis: CommandAddress | str | int):
290
+ """Returns the current status of the motor for the given M2MD axis.
291
+
292
+ Args:
293
+ axis (CommandAddress): Axis to which the command is sent.
294
+
295
+ Returns:
296
+ Current status of the motor for the given M2MD axis. Bit 0 being set to one means that the motor is
297
+ in stand-by mode; bit 1 being set to one means that the motor is in operation state.
298
+ """
299
+
300
+ pass
301
+
302
+ @dynamic_command(cmd_type=CommandType.TRANSACTION, cmd_string_func=ope_mng_event_reg)
303
+ def ope_mng_event_reg(self, axis: CommandAddress | str | int):
304
+ """Returns the list of all events since wake-up or the last clear event.
305
+
306
+ Args:
307
+ axis (CommandAddress): Axis to which the command is sent.
308
+
309
+ Returns:
310
+ List of all events since wake-up or the last clear event.
311
+ """
312
+
313
+ pass
314
+
315
+ @dynamic_command(cmd_type=CommandType.TRANSACTION, cmd_string_func=get_acq_curr_off_corr)
316
+ def get_acq_curr_off_corr(self, axis: CommandAddress | str | int):
317
+ pass
318
+
319
+ @dynamic_command(cmd_type=CommandType.TRANSACTION, cmd_string_func=set_acq_curr_off_corr)
320
+ def set_acq_curr_off_corr(self, axis: CommandAddress | str | int, cargo2: int = 0x03FB):
321
+ pass
322
+
323
+ @dynamic_command(cmd_type=CommandType.TRANSACTION, cmd_string_func=get_acq_curr_gain_corr)
324
+ def get_acq_curr_gain_corr(self, axis: CommandAddress | str | int):
325
+ pass
326
+
327
+ @dynamic_command(cmd_type=CommandType.TRANSACTION, cmd_string_func=set_acq_curr_gain_corr)
328
+ def set_acq_curr_gain_corr(self, axis: CommandAddress | str | int, cargo2: int = 0x074C):
329
+ pass
330
+
331
+ @dynamic_command(cmd_type=CommandType.TRANSACTION, cmd_string_func=acq_axis_a_curr_read)
332
+ def acq_axis_a_curr_read(self, axis: CommandAddress | str | int):
333
+ pass
334
+
335
+ @dynamic_command(cmd_type=CommandType.TRANSACTION, cmd_string_func=acq_axis_b_curr_read)
336
+ def acq_axis_b_curr_read(self, axis: CommandAddress | str | int):
337
+ pass
338
+
339
+ @dynamic_command(cmd_type=CommandType.TRANSACTION, cmd_string_func=acq_ave_lpf_en)
340
+ def acq_ave_lpf_en(self, axis: CommandAddress | str | int, cargo2: int = 0x0001):
341
+ pass
342
+
343
+ @dynamic_command(cmd_type=CommandType.TRANSACTION, cmd_string_func=acq_ovc_cfg_filter)
344
+ def acq_ovc_cfg_filter(self, axis: CommandAddress | str | int, cargo2: int = 0):
345
+ pass
346
+
347
+ @dynamic_command(cmd_type=CommandType.TRANSACTION, cmd_string_func=acq_avc_filt_time)
348
+ def acq_avc_filt_time(self, axis: CommandAddress | str | int, cargo2: int = 0):
349
+ pass
350
+
351
+ @dynamic_command(cmd_type=CommandType.TRANSACTION, cmd_string_func=acq_average_type)
352
+ def acq_average_type(self, axis: CommandAddress | str | int, cargo2: int = 0x0000):
353
+ pass
354
+
355
+ @dynamic_command(cmd_type=CommandType.TRANSACTION, cmd_string_func=acq_spk_filt_counter_lim)
356
+ def acq_spk_filt_counter_lim(self, axis: CommandAddress | str | int, cargo2: int = 0x0001):
357
+ pass
358
+
359
+ @dynamic_command(cmd_type=CommandType.TRANSACTION, cmd_string_func=acq_spk_filt_incr_thr)
360
+ def acq_spk_filt_incr_thr(self, axis: CommandAddress | str | int, cargo2: int = 0x04C0):
361
+ pass
362
+
363
+ @dynamic_command(cmd_type=CommandType.TRANSACTION, cmd_string_func=get_prof_gen_axis_step)
364
+ def get_prof_gen_axis_step(self, axis: CommandAddress | str | int):
365
+ pass
366
+
367
+ @dynamic_command(cmd_type=CommandType.TRANSACTION, cmd_string_func=set_prof_gen_axis_step)
368
+ def set_prof_gen_axis_step(self, axis: CommandAddress | str | int, cargo2: int = 0x0480):
369
+ """Axis position command for the given M2MD axis.
370
+
371
+ The cargo2 parameter denotes the desired positioning. The meaning of its constituent bits is as follows:
372
+
373
+ - bits 0-14: Number of steps to be carried out
374
+ - bit 15: Direction of motion (0: counterclockwise, 1: clockwise)
375
+
376
+ Args:
377
+ axis (CommandAddress | str | int): Axis to which the command is sent.
378
+ cargo2 (int): Cargo 2 part of the command string.
379
+ """
380
+
381
+ pass
382
+
383
+ @dynamic_command(cmd_type=CommandType.TRANSACTION, cmd_string_func=get_prof_gen_axis_speed)
384
+ def get_prof_gen_axis_speed(self, axis: CommandAddress | str | int):
385
+ """Returns the axis writing speed for the given M2MD axis.
386
+
387
+ Args:
388
+ axis (CommandAddress | str | int): Axis to which the command is sent.
389
+ """
390
+ pass
391
+
392
+ @dynamic_command(cmd_type=CommandType.TRANSACTION, cmd_string_func=set_prof_gen_axis_speed)
393
+ def set_prof_gen_axis_speed(self, axis: CommandAddress | str | int, cargo2: int = 0x0177):
394
+ """Axis velocity command for the given M2MD axis.
395
+
396
+ The cargo2 parameter denotes the desired velocity.
397
+
398
+ Args:
399
+ axis (CommandAddress | str | int): Axis to which the command is sent.
400
+ cargo2 (int): Cargo 2 part of the command string.
401
+ """
402
+
403
+ pass
404
+
405
+ @dynamic_command(cmd_type=CommandType.TRANSACTION, cmd_string_func=get_prof_gen_axis_state_start)
406
+ def get_prof_gen_axis_state_start(self, axis: CommandAddress | str | int):
407
+ pass
408
+
409
+ @dynamic_command(cmd_type=CommandType.TRANSACTION, cmd_string_func=set_prof_gen_axis_state_start)
410
+ def set_prof_gen_axis_state_start(self, axis: CommandAddress | str | int, cargo2: int = 0):
411
+ """Changes the starting point of the magnetic state for the given M2MD axis.
412
+
413
+
414
+ Args:
415
+ axis (CommandAddress | str | int): Axis to which the command is sent.
416
+ cargo2 (int): Cargo 2 part of the command string.
417
+ """
418
+
419
+ pass
420
+
421
+ @dynamic_command(cmd_type=CommandType.TRANSACTION, cmd_string_func=sw_rs_xx_sw_rise)
422
+ def sw_rs_xx_sw_rise(self, axis: CommandAddress | str | int, position: int = 1):
423
+ """Position switch rise.
424
+
425
+ Args:
426
+ axis (CommandAddress | str | int): Axis to which the command is sent.
427
+ position (int): Position of the SW_RS_XX_SW_RISE command.
428
+
429
+ Returns:
430
+ Relative position measured when the rising edge of the given switch is detected.
431
+ """
432
+
433
+ pass
434
+
435
+ @dynamic_command(cmd_type=CommandType.TRANSACTION, cmd_string_func=sw_rs_xx_sw_fall)
436
+ def sw_rs_xx_sw_fall(self, axis: CommandAddress | str | int, position: int = 1):
437
+ """Position switch fall.
438
+
439
+ Args:
440
+ axis (CommandAddress | str | int): Axis to which the command is sent.
441
+ position (int): Position of the SW_RS_XX_SW_FALL command.
442
+
443
+ Returns:
444
+ Relative position measured when the falling edge of the given switch is detected.
445
+ """
446
+
447
+ pass
448
+
449
+ # TSM commands
450
+
451
+ @dynamic_command(cmd_type=CommandType.TRANSACTION, cmd_string_func=tsm_latch)
452
+ def tsm_latch(self, cargo1: str | int, cargo2: int = 0):
453
+ """Latches to allow the modification of the operation management register.
454
+
455
+ Args:
456
+ cargo1 (str | int): Cargo 1 part of the command string.
457
+ cargo2 (int): Cargo 2 part of the command string.
458
+ """
459
+
460
+ pass
461
+
462
+ @dynamic_command(cmd_type=CommandType.TRANSACTION, cmd_string_func=get_tsm_current_value)
463
+ def get_tsm_current_value(self):
464
+ """Returns the TSM current.
465
+
466
+ Returns:
467
+ TSM current.
468
+ """
469
+ pass
470
+
471
+ @dynamic_command(cmd_type=CommandType.TRANSACTION, cmd_string_func=set_tsm_current_value)
472
+ def set_tsm_current_value(self, cargo1: int = 0, cargo2: int = 0):
473
+ """Sets the TSM current value.
474
+
475
+ Args:
476
+ cargo1 (int): Cargo 1 part of the command string.
477
+ cargo2 (int): Cargo 2 part of the command string.
478
+ """
479
+
480
+ pass
481
+
482
+ @dynamic_command(cmd_type=CommandType.TRANSACTION, cmd_string_func=get_tsm_current_offset)
483
+ def get_tsm_current_offset(self):
484
+ """Returns the TSM current offset.
485
+
486
+ Returns:
487
+ TSM current offset.
488
+ """
489
+
490
+ pass
491
+
492
+ @dynamic_command(cmd_type=CommandType.TRANSACTION, cmd_string_func=set_tsm_current_offset)
493
+ def set_tsm_current_offset(self, cargo1: int = 0, cargo2: int = 0):
494
+ """Sets the TSM current offset.
495
+
496
+ Args:
497
+ cargo1 (int): Cargo 1 part of the command string.
498
+ cargo2 (int): Cargo 2 part of the command string.
499
+ """
500
+
501
+ pass
502
+
503
+ @dynamic_command(cmd_type=CommandType.TRANSACTION, cmd_string_func=tsm_adc_register_latch)
504
+ def tsm_adc_register_latch(self, cargo1: int = 0, cargo2: int = 0):
505
+ """Re-starts the TSM ADC register latch.
506
+
507
+ Args:
508
+ cargo1 (int): Cargo 1 part of the command string.
509
+ cargo2 (int): Cargo 2 part of the command string.
510
+ """
511
+
512
+ pass
513
+
514
+ @dynamic_command(cmd_type=CommandType.TRANSACTION, cmd_string_func=tsm_adc_id_register)
515
+ def tsm_adc_id_register(self):
516
+ """Returns the content of the TSM ADC identifier register.
517
+
518
+ Returns:
519
+ Content of the TSM ADC identifier register.
520
+ """
521
+
522
+ pass
523
+
524
+ @dynamic_command(cmd_type=CommandType.TRANSACTION, cmd_string_func=tsm_adc_configuration_register)
525
+ def tsm_adc_configuration_register(self):
526
+ """Returns the content of the TSM ADC configuration register.
527
+
528
+ Returns:
529
+ Content of the TSM ADC configuration register.
530
+ """
531
+
532
+ pass
533
+
534
+ @dynamic_command(cmd_type=CommandType.TRANSACTION, cmd_string_func=get_tsm_adc_hpf_register)
535
+ def get_tsm_adc_hpf_register(self):
536
+ """Returns the content of the high-pass corner frequency register.
537
+
538
+ Returns:
539
+ Content of the high-pass corner frequency register.
540
+ """
541
+
542
+ pass
543
+
544
+ @dynamic_command(cmd_type=CommandType.TRANSACTION, cmd_string_func=set_tsm_adc_hpf_register)
545
+ def set_tsm_adc_hpf_register(self, cargo1: int = 0, cargo2: int = 0):
546
+ pass
547
+
548
+ @dynamic_command(cmd_type=CommandType.TRANSACTION, cmd_string_func=get_tsm_adc_ofc_register)
549
+ def get_tsm_adc_ofc_register(self):
550
+ """Returns the content of the offset calibration register.
551
+
552
+ Returns:
553
+ Content of the offset calibration register.
554
+ """
555
+
556
+ pass
557
+
558
+ @dynamic_command(cmd_type=CommandType.TRANSACTION, cmd_string_func=set_tsm_adc_ofc_register)
559
+ def set_tsm_adc_ofc_register(self, cargo1: int = 0, cargo2: int = 0):
560
+ pass
561
+
562
+ @dynamic_command(cmd_type=CommandType.TRANSACTION, cmd_string_func=get_tsm_adc_fsc_register)
563
+ def get_tsm_adc_fsc_register(self):
564
+ """Returns the content of the full-scale calibration register.
565
+
566
+ Returns:
567
+ Content of the full-scale calibration register.
568
+ """
569
+
570
+ pass
571
+
572
+ @dynamic_command(cmd_type=CommandType.TRANSACTION, cmd_string_func=set_tsm_adc_fsc_register)
573
+ def set_tsm_adc_fsc_register(self, cargo1: int = 0, cargo2: int = 0):
574
+ pass
575
+
576
+ @dynamic_command(cmd_type=CommandType.TRANSACTION, cmd_string_func=tsm_adc_command_latch)
577
+ def tsm_adc_command_latch(self, cargo1: int = 0, cargo2: int = 0):
578
+ pass
579
+
580
+ @dynamic_command(cmd_type=CommandType.TRANSACTION, cmd_string_func=tsm_adc_command)
581
+ def tsm_adc_command(self, cargo1: int = 0, cargo2: int = 0):
582
+ pass
583
+
584
+ @dynamic_command(cmd_type=CommandType.TRANSACTION, cmd_string_func=tsm_adc_calibration)
585
+ def tsm_adc_calibration(self, cargo1: int = 0, cargo2: int = 0):
586
+ pass
587
+
588
+ @dynamic_command(cmd_type=CommandType.TRANSACTION, cmd_string_func=tsm_adc_value_xx_currentn)
589
+ def tsm_adc_value_xx_currentn(self, probe: int = 1):
590
+ """Returns the negative current to polarise the given thermistor.
591
+
592
+ Args:
593
+ probe (int): Thermistor identifier.
594
+
595
+ Returns:
596
+ Negative current to polarise the given thermistor.
597
+ """
598
+
599
+ pass
600
+
601
+ @dynamic_command(cmd_type=CommandType.TRANSACTION, cmd_string_func=tsm_adc_value_xx_biasn)
602
+ def tsm_adc_value_xx_biasn(self, probe: int = 1):
603
+ """Returns the voltage measured on the given thermistor biased with negative current.
604
+
605
+ Args:
606
+ probe (int): Thermistor identifier.
607
+
608
+ Returns:
609
+ Voltage on the thermistor biased with the negative current.
610
+ """
611
+
612
+ pass
613
+
614
+ @dynamic_command(cmd_type=CommandType.TRANSACTION, cmd_string_func=tsm_adc_value_xx_currentp)
615
+ def tsm_adc_value_xx_currentp(self, probe: int = 1):
616
+ """Returns the positive current to polarise the given thermistor.
617
+
618
+ Args:
619
+ probe (int): Thermistor identifier.
620
+
621
+ Returns:
622
+ Positive current to polarise the given thermistor.
623
+ """
624
+
625
+ pass
626
+
627
+ @dynamic_command(cmd_type=CommandType.TRANSACTION, cmd_string_func=tsm_adc_value_xx_biasp)
628
+ def tsm_adc_value_xx_biasp(self, probe: int = 1):
629
+ """Returns the voltage measured on the given thermistor biased with positive current.
630
+
631
+ Args:
632
+ probe (int): Thermistor identifier.
633
+
634
+ Returns:
635
+ Voltage on the thermistor biased with the positive current.
636
+ """
637
+
638
+ pass
639
+
640
+ @dynamic_command(cmd_type=CommandType.TRANSACTION, cmd_string_func=tsm_acq_counter)
641
+ def tsm_acq_counter(self):
642
+ """Reads the number of ADC measurement sequences that have been made.
643
+
644
+ Returns:
645
+ Number of ADC measurement sequences that have been made.
646
+ """
647
+
648
+ pass
649
+
650
+ # HK commands
651
+
652
+ @dynamic_command(cmd_type=CommandType.TRANSACTION, cmd_string_func=vhk_psu_vmotor)
653
+ def vhk_psu_vmotor(self):
654
+ """Returns the HK PSU motor voltage value.
655
+
656
+ Returns:
657
+ HK PSU motor voltage value.
658
+ """
659
+
660
+ pass
661
+
662
+ @dynamic_command(cmd_type=CommandType.TRANSACTION, cmd_string_func=vhk_psu_vhi)
663
+ def vhk_psu_vhi(self):
664
+ """Returns the HK PSU high voltage value.
665
+
666
+ Returns:
667
+ HK PSU motor high voltage value.
668
+ """
669
+
670
+ pass
671
+
672
+ @dynamic_command(cmd_type=CommandType.TRANSACTION, cmd_string_func=vhk_psu_vlow)
673
+ def vhk_psu_vlow(self):
674
+ """Returns the HK PSU low voltage value.
675
+
676
+ Returns:
677
+ HK PSU motor low voltage value.
678
+ """
679
+
680
+ pass
681
+
682
+ @dynamic_command(cmd_type=CommandType.TRANSACTION, cmd_string_func=vhk_psu_vmedp)
683
+ def vhk_psu_vmedp(self):
684
+ """Returns the HK PSU medium positive voltage value.
685
+
686
+ Returns:
687
+ HK PSU medium positive voltage value.
688
+ """
689
+
690
+ pass
691
+
692
+ @dynamic_command(cmd_type=CommandType.TRANSACTION, cmd_string_func=vhk_psu_vmedn)
693
+ def vhk_psu_vmedn(self):
694
+ """Returns the HK PSU medium negative voltage value.
695
+
696
+ Returns:
697
+ HK PSU medium negative voltage value.
698
+ """
699
+
700
+ pass
701
+
702
+ @dynamic_command(cmd_type=CommandType.TRANSACTION, cmd_string_func=ihk_psu_vmedn)
703
+ def ihk_psu_vmedn(self):
704
+ """Returns the HK PSU medium negative current value.
705
+
706
+ Returns:
707
+ HK PSU medium negative current value.
708
+ """
709
+
710
+ pass
711
+
712
+ @dynamic_command(cmd_type=CommandType.TRANSACTION, cmd_string_func=ihk_psu_vmedp)
713
+ def ihk_psu_vmedp(self):
714
+ """Returns the HK PSU medium positive current value.
715
+
716
+ Returns:
717
+ HK PSU medium positive current value.
718
+ """
719
+
720
+ pass
721
+
722
+ @dynamic_command(cmd_type=CommandType.TRANSACTION, cmd_string_func=ihk_psu_vlow)
723
+ def ihk_psu_vlow(self):
724
+ """Returns the HK PSU low current value.
725
+
726
+ Returns:
727
+ HK PSU low current value.
728
+ """
729
+
730
+ pass
731
+
732
+ @dynamic_command(cmd_type=CommandType.TRANSACTION, cmd_string_func=ihk_psu_vhi)
733
+ def ihk_psu_vhi(self):
734
+ """Returns the HK PSU high current value.
735
+
736
+ Returns:
737
+ HK PSU high current value.
738
+ """
739
+
740
+ pass
741
+
742
+ @dynamic_command(cmd_type=CommandType.TRANSACTION, cmd_string_func=ihk_psu_vmotor)
743
+ def ihk_psu_vmotor(self):
744
+ """Returns the HK PSU motor current value.
745
+
746
+ Returns:
747
+ HK PSU motor current value.
748
+ """
749
+
750
+ pass
751
+
752
+ @dynamic_command(cmd_type=CommandType.TRANSACTION, cmd_string_func=thk_psu_first)
753
+ def thk_psu_first(self):
754
+ """Returns the HK PSU temperature zone 1.
755
+
756
+ Returns:
757
+ HK PSU temperature zone 1.
758
+ """
759
+
760
+ pass
761
+
762
+ @dynamic_command(cmd_type=CommandType.TRANSACTION, cmd_string_func=thk_m2md_first)
763
+ def thk_m2md_first(self):
764
+ """Returns the HK M2MD temperature zone 1.
765
+
766
+ Returns:
767
+ HK M2MD temperature zone 1.
768
+ """
769
+
770
+ pass
771
+
772
+ @dynamic_command(cmd_type=CommandType.TRANSACTION, cmd_string_func=thk_psu_second)
773
+ def thk_psu_second(self):
774
+ """Returns the HK M2MD temperature zone 2.
775
+
776
+ Returns:
777
+ HK M2MD temperature zone 2.
778
+ """
779
+
780
+ pass
781
+
782
+ @dynamic_command(cmd_type=CommandType.TRANSACTION, cmd_string_func=thk_m2md_second)
783
+ def thk_m2md_second(self):
784
+ """Returns the HK M2MD temperature zone 2.
785
+
786
+ Returns:
787
+ HK M2MD temperature zone 2.
788
+ """
789
+
790
+ pass
791
+
792
+ @dynamic_command(cmd_type=CommandType.TRANSACTION, cmd_string_func=thk_cts_q1)
793
+ def thk_cts_q1(self):
794
+ """Returns the HK CTS temperature first quarter.
795
+
796
+ Returns:
797
+ HK CTS temperature first quarter.
798
+ """
799
+
800
+ pass
801
+
802
+ @dynamic_command(cmd_type=CommandType.TRANSACTION, cmd_string_func=thk_cts_q2)
803
+ def thk_cts_q2(self):
804
+ """Returns the HK CTS temperature second quarter.
805
+
806
+ Returns:
807
+ HK CTS temperature second quarter.
808
+ """
809
+
810
+ pass
811
+
812
+ @dynamic_command(cmd_type=CommandType.TRANSACTION, cmd_string_func=thk_cts_q3)
813
+ def thk_cts_q3(self):
814
+ """Returns the HK CTS temperature third quarter.
815
+
816
+ Returns:
817
+ HK CTS temperature third quarter.
818
+ """
819
+
820
+ pass
821
+
822
+ @dynamic_command(cmd_type=CommandType.TRANSACTION, cmd_string_func=thk_cts_q4)
823
+ def thk_cts_q4(self):
824
+ """Returns the HK CTS temperature fourth quarter.
825
+
826
+ Returns:
827
+ HK CTS temperature fourth quarter.
828
+ """
829
+
830
+ pass
831
+
832
+ @dynamic_command(cmd_type=CommandType.TRANSACTION, cmd_string_func=thk_cts_fpga)
833
+ def thk_cts_fpga(self):
834
+ """Returns the HK CTS temperature FPGA.
835
+
836
+ Returns:
837
+ HK CTS temperature FPGA.
838
+ """
839
+
840
+ pass
841
+
842
+ @dynamic_command(cmd_type=CommandType.TRANSACTION, cmd_string_func=thk_cts_ads1282)
843
+ def thk_cts_ads1282(self):
844
+ """Returns the HK CTS temperature ADS1282.
845
+
846
+ Returns:
847
+ HK CTS temperature ADS1282.
848
+ """
849
+
850
+ pass
851
+
852
+ @dynamic_command(cmd_type=CommandType.TRANSACTION, cmd_string_func=vhk_ths_ret)
853
+ def vhk_ths_ret(self):
854
+ """Returns the HK CTS thermistors return voltage.
855
+
856
+ Returns:
857
+ HK CTS thermistors return voltage.
858
+ """
859
+
860
+ pass
861
+
862
+ @dynamic_command(cmd_type=CommandType.TRANSACTION, cmd_string_func=hk_acq_counter)
863
+ def hk_acq_counter(self):
864
+ """Returns the running counter that indicates the number of HK measurement sequences that have been made.
865
+
866
+ Returns:
867
+ Free running counter that indicates the number of HK measurement sequences that have been made.
868
+ """
869
+
870
+ pass
871
+
872
+
873
+ class TcuController(TcuInterface, DynamicCommandMixin):
874
+ def __init__(self):
875
+ """Initialisation of an Ariel TCU controller."""
876
+
877
+ super().__init__()
878
+ self.transport = self.tcu = TcuDeviceInterface()
879
+
880
+ # noinspection PyMethodMayBeStatic
881
+ def is_simulator(self):
882
+ return False
883
+
884
+ def is_connected(self):
885
+ """Checks whether the serial port to the TCU Arduino is open.
886
+
887
+ Returns:
888
+ True if the serial port to the TCU Arduino is open; False otherwise.
889
+ """
890
+
891
+ return self.tcu.is_connected()
892
+
893
+ def connect(self):
894
+ """Opens the serial port to the TCU Arduino.
895
+
896
+ Raises:
897
+ TcuError: When the serial port could not be opened.
898
+ """
899
+
900
+ self.tcu.connect()
901
+
902
+ def disconnect(self):
903
+ """Closes the serial port to the TCU Arduino.
904
+
905
+ Raises:
906
+ TcuError: When the serial port could not be closed.
907
+ """
908
+
909
+ self.tcu.disconnect()
910
+
911
+ def reconnect(self):
912
+ """Re-connects to the Ariel TCU Arduino."""
913
+
914
+ self.tcu.reconnect()
915
+
916
+
917
+ class TcuSimulator(TcuInterface):
918
+ VHK_PSU_MOTOR = 0x0080
919
+ VHK_PSU_VHI = 0x0280
920
+ VHK_PSU_VLOW = 0x0480
921
+ VHK_PSU_VMEDP = 0x0680
922
+ VHK_PSU_VMEDN = 0x0880
923
+ IHK_PSU_VMEDN = 0x0A80
924
+ IHK_PSU_VMEDP = 0x0A80
925
+ IHK_PSU_VLOW = 0x0A80
926
+ IHK_PSU_VHI = 0x0A80
927
+ IHK_PSU_VMOTOR = 0x0A80
928
+ THK_PSU_FIRST = 0x0A80
929
+ THK_M2MD_FIRST = 0x0A80
930
+ THK_PSU_SECOND = 0x0C80
931
+ THK_M2MD_SECOND = 0x0C80
932
+ THK_CTS_Q1 = 0x0A80
933
+ THK_CTS_Q2 = 0x0C80
934
+ THK_CTS_Q3 = 0x0C80
935
+ THK_CTS_Q4 = 0x0C80
936
+ THK_CTS_FPGA = 0x0A80
937
+ THK_CTS_ADS1282 = 0x0C80
938
+ VHK_THS_RET = 0x0E80
939
+ HK_ACQ_COUNTER = 0x002A
940
+
941
+ def __init__(self):
942
+ """Initialisation of an Ariel TCU simulator."""
943
+
944
+ super().__init__()
945
+
946
+ self._is_connected = True
947
+
948
+ self.tcu_mode = TcuMode.IDLE.value
949
+ self.restart_links_period = 0
950
+ self.acq_curr_off_corr_list = [None, 0, 0, 0]
951
+ self.acq_curr_gain_corr_list = [None, 0, 0, 0]
952
+
953
+ self.acq_axis_a_curr_read_list = [0, 1, 2, 3]
954
+ self.acq_axis_b_curr_read_list = [0, 4, 5, 6]
955
+
956
+ self.prof_gen_axis_step_list = [None, 7, 8, 9]
957
+ self.prof_gen_axis_speed_list = [None, 10, 11, 12]
958
+ self.prof_gen_axis_state_start_list = [None, 13, 14, 14]
959
+
960
+ # noinspection PyMethodMayBeStatic
961
+ def is_simulator(self):
962
+ return True
963
+
964
+ # noinspection PyMethodMayBeStatic
965
+ def is_connected(self):
966
+ return self._is_connected
967
+
968
+ def connect(self):
969
+ self._is_connected = True
970
+
971
+ def disconnect(self):
972
+ self._is_connected = False
973
+
974
+ def reconnect(self):
975
+ self._is_connected = True
976
+
977
+ def tcu_firmware_id(self):
978
+ return "TCU Simulator"
979
+
980
+ def get_tcu_mode(self):
981
+ return self.tcu_mode
982
+
983
+ def set_tcu_mode(self, tcu_mode: TcuMode | int = TcuMode.IDLE):
984
+ if isinstance(tcu_mode, TcuMode):
985
+ self.tcu_mode = tcu_mode.value
986
+
987
+ elif isinstance(tcu_mode, int):
988
+ self.tcu_mode = tcu_mode
989
+
990
+ def set_restart_links_period(self, link_period: int = 0xFFFF):
991
+ self.restart_links_period = link_period
992
+
993
+ def get_restart_links_period(self):
994
+ return self.restart_links_period
995
+
996
+ def get_acq_curr_off_corr(self, axis: CommandAddress | str | int):
997
+ return self.acq_curr_off_corr_list[int(axis)]
998
+
999
+ def set_acq_curr_off_corr(self, axis: CommandAddress | str | int, cargo2: int = 0x03FB):
1000
+ self.acq_curr_off_corr_list[int(axis)] = cargo2
1001
+
1002
+ def get_acq_curr_gain_corr(self, axis: CommandAddress | str | int):
1003
+ return self.acq_curr_gain_corr_list[int(axis)]
1004
+
1005
+ def set_acq_curr_gain_corr(self, axis: CommandAddress | str | int, cargo2: int = 0x074C):
1006
+ self.acq_curr_gain_corr_list[int(axis)] = cargo2
1007
+
1008
+ def acq_axis_a_curr_read(self, axis: CommandAddress | str | int):
1009
+ return self.acq_axis_a_curr_read_list[int(axis)]
1010
+
1011
+ def acq_axis_b_curr_read(self, axis: CommandAddress | str | int):
1012
+ return self.acq_axis_b_curr_read_list[int(axis)]
1013
+
1014
+ def get_prof_gen_axis_step(self, axis: CommandAddress | str | int):
1015
+ return self.prof_gen_axis_step_list[int(axis)]
1016
+
1017
+ def set_prof_gen_axis_step(self, axis: CommandAddress | str | int, cargo2: int = 0x0480):
1018
+ self.prof_gen_axis_step_list[int(axis)] = cargo2
1019
+
1020
+ def get_prof_gen_axis_speed(self, axis: CommandAddress | str | int):
1021
+ return self.prof_gen_axis_speed_list[int(axis)]
1022
+
1023
+ def set_prof_gen_axis_speed(self, axis: CommandAddress | str | int, cargo2: int = 0x1777):
1024
+ self.prof_gen_axis_speed_list[int(axis)] = cargo2
1025
+
1026
+ def get_prof_gen_axis_state_start(self, axis: CommandAddress | str | int):
1027
+ return self.prof_gen_axis_state_start_list[int(axis)]
1028
+
1029
+ def set_prof_gen_axis_state_start(self, axis: CommandAddress | str | int, cargo2: int = 0):
1030
+ self.prof_gen_axis_state_start_list[int(axis)] = cargo2
1031
+
1032
+ def vhk_psu_vmotor(self):
1033
+ return TcuSimulator.VHK_PSU_MOTOR
1034
+
1035
+ def vhk_psu_vhi(self):
1036
+ return TcuSimulator.VHK_PSU_VHI
1037
+
1038
+ def vhk_psu_vlow(self):
1039
+ return TcuSimulator.VHK_PSU_VLOW
1040
+
1041
+ def vhk_psu_vmedp(self):
1042
+ return TcuSimulator.VHK_PSU_VMEDP
1043
+
1044
+ def vhk_psu_vmedn(self):
1045
+ return TcuSimulator.VHK_PSU_VMEDN
1046
+
1047
+ def ihk_psu_vmedn(self):
1048
+ return TcuSimulator.IHK_PSU_VMEDN
1049
+
1050
+ def ihk_psu_vmedp(self):
1051
+ return TcuSimulator.IHK_PSU_VMEDP
1052
+
1053
+ def ihk_psu_vlow(self):
1054
+ return TcuSimulator.IHK_PSU_VLOW
1055
+
1056
+ def ihk_psu_vhi(self):
1057
+ return TcuSimulator.IHK_PSU_VHI
1058
+
1059
+ def ihk_psu_vmotor(self):
1060
+ return TcuSimulator.IHK_PSU_VMOTOR
1061
+
1062
+ def thk_psu_first(self):
1063
+ return TcuSimulator.THK_PSU_FIRST
1064
+
1065
+ def thk_m2md_first(self):
1066
+ return TcuSimulator.THK_M2MD_FIRST
1067
+
1068
+ def thk_psu_second(self):
1069
+ return TcuSimulator.THK_PSU_SECOND
1070
+
1071
+ def thk_m2md_second(self):
1072
+ return TcuSimulator.THK_M2MD_SECOND
1073
+
1074
+ def thk_cts_q1(self):
1075
+ return TcuSimulator.THK_CTS_Q1
1076
+
1077
+ def thk_cts_q2(self):
1078
+ return TcuSimulator.THK_CTS_Q2
1079
+
1080
+ def thk_cts_q3(self):
1081
+ return TcuSimulator.THK_CTS_Q3
1082
+
1083
+ def thk_cts_q4(self):
1084
+ return TcuSimulator.THK_CTS_Q4
1085
+
1086
+ def thk_cts_fpga(self):
1087
+ return TcuSimulator.THK_CTS_FPGA
1088
+
1089
+ def thk_cts_ads1282(self):
1090
+ return TcuSimulator.THK_CTS_ADS1282
1091
+
1092
+ def vhk_ths_ret(self):
1093
+ return TcuSimulator.VHK_THS_RET
1094
+
1095
+ def hk_acq_counter(self):
1096
+ return TcuSimulator.HK_ACQ_COUNTER
1097
+
1098
+
1099
+ class TcuProxy(DynamicProxy, TcuInterface):
1100
+ """
1101
+ The TcuProxy class is used to connect to the TCU Control Server and send commands to the TCU Hardware Controller remotely.
1102
+ """
1103
+
1104
+ def __init__(self):
1105
+ """Initialisation of a TCUProxy."""
1106
+
1107
+ with RegistryClient() as reg:
1108
+ service = reg.discover_service(SERVICE_TYPE)
1109
+
1110
+ if service:
1111
+ protocol = service.get("protocol", "tcp")
1112
+ hostname = service["host"]
1113
+ port = service["port"]
1114
+
1115
+ super().__init__(connect_address(protocol, hostname, port), timeout=PROXY_TIMEOUT)
1116
+
1117
+ else:
1118
+ raise RuntimeError(f"No service registered as {SERVICE_TYPE}")