harp-protocol 0.2.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.
- harp/communication/__init__.py +2 -0
- harp/communication/device.py +1173 -0
- harp/communication/harp_serial.py +153 -0
- harp/devices/.gitignore +0 -0
- harp/protocol/__init__.py +1 -0
- harp/protocol/base.py +276 -0
- harp/protocol/device_names.py +51 -0
- harp/protocol/exceptions.py +26 -0
- harp/protocol/messages.py +579 -0
- harp_protocol-0.2.0.dist-info/METADATA +88 -0
- harp_protocol-0.2.0.dist-info/RECORD +13 -0
- harp_protocol-0.2.0.dist-info/WHEEL +4 -0
- harp_protocol-0.2.0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,1173 @@
|
|
|
1
|
+
from __future__ import annotations # enable subscriptable type hints for lists.
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
import queue
|
|
5
|
+
from io import BufferedWriter
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
from typing import Optional, Union
|
|
8
|
+
|
|
9
|
+
import serial
|
|
10
|
+
|
|
11
|
+
from harp.communication.harp_serial import HarpSerial
|
|
12
|
+
from harp.protocol import (
|
|
13
|
+
ClockConfig,
|
|
14
|
+
CommonRegisters,
|
|
15
|
+
MessageType,
|
|
16
|
+
OperationCtrl,
|
|
17
|
+
OperationMode,
|
|
18
|
+
PayloadType,
|
|
19
|
+
ResetMode,
|
|
20
|
+
)
|
|
21
|
+
from harp.protocol.device_names import device_names
|
|
22
|
+
from harp.protocol.messages import HarpMessage, ReplyHarpMessage
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class Device:
|
|
26
|
+
"""
|
|
27
|
+
The `Device` class provides the interface for interacting with Harp devices. This implementation of the Harp device was based on the official documentation available on the [harp-tech website](https://harp-tech.org/protocol/Device.html).
|
|
28
|
+
|
|
29
|
+
Attributes
|
|
30
|
+
----------
|
|
31
|
+
WHO_AM_I : int
|
|
32
|
+
The device ID number. A list of devices can be found [here](https://github.com/harp-tech/protocol/blob/main/whoami.md)
|
|
33
|
+
DEFAULT_DEVICE_NAME : str
|
|
34
|
+
The device name, i.e. "Behavior". This name is derived by cross-referencing the `WHO_AM_I` identifier with the corresponding device name in the `device_names` dictionary
|
|
35
|
+
HW_VERSION_H : int
|
|
36
|
+
The major hardware version
|
|
37
|
+
HW_VERSION_L : int
|
|
38
|
+
The minor hardware version
|
|
39
|
+
ASSEMBLY_VERSION : int
|
|
40
|
+
The version of the assembled components
|
|
41
|
+
HARP_VERSION_H : int
|
|
42
|
+
The major Harp core version
|
|
43
|
+
HARP_VERSION_L : int
|
|
44
|
+
The minor Harp core version
|
|
45
|
+
FIRMWARE_VERSION_H : int
|
|
46
|
+
The major firmware version
|
|
47
|
+
FIRMWARE_VERSION_L : int
|
|
48
|
+
The minor firmware version
|
|
49
|
+
DEVICE_NAME : str
|
|
50
|
+
The device name stored in the Harp device
|
|
51
|
+
SERIAL_NUMBER : int, optional
|
|
52
|
+
The serial number of the device
|
|
53
|
+
"""
|
|
54
|
+
|
|
55
|
+
WHO_AM_I: int
|
|
56
|
+
DEFAULT_DEVICE_NAME: str
|
|
57
|
+
HW_VERSION_H: int
|
|
58
|
+
HW_VERSION_L: int
|
|
59
|
+
ASSEMBLY_VERSION: int
|
|
60
|
+
HARP_VERSION_H: int
|
|
61
|
+
HARP_VERSION_L: int
|
|
62
|
+
FIRMWARE_VERSION_H: int
|
|
63
|
+
FIRMWARE_VERSION_L: int
|
|
64
|
+
DEVICE_NAME: str
|
|
65
|
+
SERIAL_NUMBER: int
|
|
66
|
+
CLOCK_CONFIG: int
|
|
67
|
+
TIMESTAMP_OFFSET: int
|
|
68
|
+
|
|
69
|
+
_ser: HarpSerial
|
|
70
|
+
_dump_file_path: Path
|
|
71
|
+
_dump_file: Optional[BufferedWriter] = None
|
|
72
|
+
_read_timeout_s: float
|
|
73
|
+
|
|
74
|
+
_TIMEOUT_S: float = 1.0
|
|
75
|
+
|
|
76
|
+
def __init__(
|
|
77
|
+
self,
|
|
78
|
+
serial_port: str,
|
|
79
|
+
dump_file_path: Optional[str] = None,
|
|
80
|
+
read_timeout_s: float = 1,
|
|
81
|
+
):
|
|
82
|
+
"""
|
|
83
|
+
Parameters
|
|
84
|
+
----------
|
|
85
|
+
serial_port : str
|
|
86
|
+
The serial port used to establish the connection with the Harp device. It must be denoted as `/dev/ttyUSBx` in Linux and `COMx` in Windows, where `x` is the number of the serial port
|
|
87
|
+
dump_file_path: str, optional
|
|
88
|
+
The binary file to which all Harp messages will be written
|
|
89
|
+
read_timeout_s: float, optional
|
|
90
|
+
_TODO_
|
|
91
|
+
"""
|
|
92
|
+
self.log = logging.getLogger(f"{__name__}.{self.__class__.__name__}")
|
|
93
|
+
self._serial_port = serial_port
|
|
94
|
+
self._dump_file_path = dump_file_path
|
|
95
|
+
if dump_file_path is not None:
|
|
96
|
+
self._dump_file_path = Path() / dump_file_path
|
|
97
|
+
self._read_timeout_s = read_timeout_s
|
|
98
|
+
|
|
99
|
+
# Connect to the Harp device and load the data stored in the device's common registers
|
|
100
|
+
self.connect()
|
|
101
|
+
self.load()
|
|
102
|
+
|
|
103
|
+
def load(self) -> None:
|
|
104
|
+
"""
|
|
105
|
+
Loads the data stored in the device's common registers.
|
|
106
|
+
"""
|
|
107
|
+
self.WHO_AM_I = self._read_who_am_i()
|
|
108
|
+
self.DEFAULT_DEVICE_NAME = self._read_default_device_name()
|
|
109
|
+
self.HW_VERSION_H = self._read_hw_version_h()
|
|
110
|
+
self.HW_VERSION_L = self._read_hw_version_l()
|
|
111
|
+
self.ASSEMBLY_VERSION = self._read_assembly_version()
|
|
112
|
+
self.HARP_VERSION_H = self._read_harp_version_h()
|
|
113
|
+
self.HARP_VERSION_L = self._read_harp_version_l()
|
|
114
|
+
self.FIRMWARE_VERSION_H = self._read_fw_version_h()
|
|
115
|
+
self.FIRMWARE_VERSION_L = self._read_fw_version_l()
|
|
116
|
+
self.DEVICE_NAME = self._read_device_name()
|
|
117
|
+
self.SERIAL_NUMBER = self._read_serial_number()
|
|
118
|
+
self.CLOCK_CONFIG = self._read_clock_config()
|
|
119
|
+
self.TIMESTAMP_OFFSET = self._read_timestamp_offset()
|
|
120
|
+
|
|
121
|
+
def info(self) -> None:
|
|
122
|
+
"""
|
|
123
|
+
Prints the device information.
|
|
124
|
+
"""
|
|
125
|
+
print("Device info:")
|
|
126
|
+
print(f"* Who am I: ({self.WHO_AM_I}) {self.DEFAULT_DEVICE_NAME}")
|
|
127
|
+
print(f"* HW version: {self.HW_VERSION_H}.{self.HW_VERSION_L}")
|
|
128
|
+
print(f"* Assembly version: {self.ASSEMBLY_VERSION}")
|
|
129
|
+
print(f"* HARP version: {self.HARP_VERSION_H}.{self.HARP_VERSION_L}")
|
|
130
|
+
print(
|
|
131
|
+
f"* Firmware version: {self.FIRMWARE_VERSION_H}.{self.FIRMWARE_VERSION_L}"
|
|
132
|
+
)
|
|
133
|
+
print(f"* Device user name: {self.DEVICE_NAME}")
|
|
134
|
+
print(f"* Serial number: {self.SERIAL_NUMBER}")
|
|
135
|
+
print(f"* Mode: {self._read_device_mode().name}")
|
|
136
|
+
|
|
137
|
+
def connect(self) -> None:
|
|
138
|
+
"""
|
|
139
|
+
Connects to the Harp device.
|
|
140
|
+
"""
|
|
141
|
+
self._ser = HarpSerial(
|
|
142
|
+
self._serial_port, # "/dev/tty.usbserial-A106C8O9"
|
|
143
|
+
baudrate=1000000,
|
|
144
|
+
timeout=self._TIMEOUT_S,
|
|
145
|
+
parity=serial.PARITY_NONE,
|
|
146
|
+
stopbits=1,
|
|
147
|
+
bytesize=8,
|
|
148
|
+
rtscts=True,
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
# open file if it is defined
|
|
152
|
+
if self._dump_file_path is not None:
|
|
153
|
+
self._dump_file = open(self._dump_file_path, "ab")
|
|
154
|
+
|
|
155
|
+
def disconnect(self) -> None:
|
|
156
|
+
"""
|
|
157
|
+
Disconnects from the Harp device.
|
|
158
|
+
"""
|
|
159
|
+
# close file if it exists
|
|
160
|
+
if self._dump_file:
|
|
161
|
+
self._dump_file.close()
|
|
162
|
+
self._dump_file = None
|
|
163
|
+
|
|
164
|
+
self._ser.close()
|
|
165
|
+
|
|
166
|
+
def _read_device_mode(self) -> OperationMode:
|
|
167
|
+
"""
|
|
168
|
+
Reads the current operation mode of the Harp device.
|
|
169
|
+
|
|
170
|
+
Returns
|
|
171
|
+
-------
|
|
172
|
+
DeviceMode
|
|
173
|
+
The current device mode
|
|
174
|
+
"""
|
|
175
|
+
address = CommonRegisters.OPERATION_CTRL
|
|
176
|
+
reply = self.send(HarpMessage.create(MessageType.READ, address, PayloadType.U8))
|
|
177
|
+
return OperationMode(reply.payload & OperationCtrl.OP_MODE)
|
|
178
|
+
|
|
179
|
+
def dump_registers(self) -> list:
|
|
180
|
+
"""
|
|
181
|
+
Asserts the DUMP bit to dump the values of all core and app registers
|
|
182
|
+
as Harp Read Reply Messages. More information on the DUMP bit can be found [here](https://harp-tech.org/protocol/Device.html#r_operation_ctrl-u16--operation-mode-configuration).
|
|
183
|
+
|
|
184
|
+
Returns
|
|
185
|
+
-------
|
|
186
|
+
list
|
|
187
|
+
The list containing the reply Harp messages for all the device's registers
|
|
188
|
+
"""
|
|
189
|
+
address = CommonRegisters.OPERATION_CTRL
|
|
190
|
+
reg_value = self.send(
|
|
191
|
+
HarpMessage.create(MessageType.READ, address, PayloadType.U8)
|
|
192
|
+
).payload
|
|
193
|
+
# Assert DUMP bit
|
|
194
|
+
reg_value |= OperationCtrl.DUMP
|
|
195
|
+
self.send(
|
|
196
|
+
HarpMessage.create(MessageType.WRITE, address, PayloadType.U8, reg_value)
|
|
197
|
+
)
|
|
198
|
+
|
|
199
|
+
# Receive the contents of all registers as Harp Read Reply Messages
|
|
200
|
+
replies = []
|
|
201
|
+
while True:
|
|
202
|
+
msg = self._read()
|
|
203
|
+
if msg is not None:
|
|
204
|
+
replies.append(msg)
|
|
205
|
+
else:
|
|
206
|
+
break
|
|
207
|
+
return replies
|
|
208
|
+
|
|
209
|
+
def set_mode(self, mode: OperationMode) -> ReplyHarpMessage:
|
|
210
|
+
"""
|
|
211
|
+
Sets the operation mode of the device.
|
|
212
|
+
|
|
213
|
+
Parameters
|
|
214
|
+
----------
|
|
215
|
+
mode : DeviceMode
|
|
216
|
+
The new device mode value
|
|
217
|
+
|
|
218
|
+
Returns
|
|
219
|
+
-------
|
|
220
|
+
ReplyHarpMessage
|
|
221
|
+
The reply to the Harp message
|
|
222
|
+
"""
|
|
223
|
+
address = CommonRegisters.OPERATION_CTRL
|
|
224
|
+
|
|
225
|
+
# Read register first
|
|
226
|
+
reg_value = self.send(
|
|
227
|
+
HarpMessage.create(MessageType.READ, address, PayloadType.U8)
|
|
228
|
+
).payload
|
|
229
|
+
|
|
230
|
+
# Clear old operation mode
|
|
231
|
+
reg_value &= ~OperationCtrl.OP_MODE
|
|
232
|
+
|
|
233
|
+
# Set new operation mode
|
|
234
|
+
reg_value |= mode
|
|
235
|
+
reply = self.send(
|
|
236
|
+
HarpMessage.create(MessageType.WRITE, address, PayloadType.U8, reg_value)
|
|
237
|
+
)
|
|
238
|
+
|
|
239
|
+
return reply
|
|
240
|
+
|
|
241
|
+
def alive_en(self, enable: bool) -> bool:
|
|
242
|
+
"""
|
|
243
|
+
Sets the ALIVE_EN bit of the device.
|
|
244
|
+
|
|
245
|
+
Parameters
|
|
246
|
+
----------
|
|
247
|
+
enable : bool
|
|
248
|
+
If True, enables the ALIVE_EN bit. If False, disables it
|
|
249
|
+
|
|
250
|
+
Returns
|
|
251
|
+
-------
|
|
252
|
+
bool
|
|
253
|
+
True if the operation was successful, False otherwise
|
|
254
|
+
"""
|
|
255
|
+
address = CommonRegisters.OPERATION_CTRL
|
|
256
|
+
|
|
257
|
+
# Read register first
|
|
258
|
+
reg_value = self.send(
|
|
259
|
+
HarpMessage.create(MessageType.READ, address, PayloadType.U8)
|
|
260
|
+
).payload
|
|
261
|
+
|
|
262
|
+
if enable:
|
|
263
|
+
reg_value |= OperationCtrl.ALIVE_EN
|
|
264
|
+
else:
|
|
265
|
+
reg_value &= ~OperationCtrl.ALIVE_EN
|
|
266
|
+
|
|
267
|
+
reply = self.send(
|
|
268
|
+
HarpMessage.create(MessageType.WRITE, address, PayloadType.U8, reg_value)
|
|
269
|
+
)
|
|
270
|
+
|
|
271
|
+
return reply
|
|
272
|
+
|
|
273
|
+
def op_led_en(self, enable: bool) -> bool:
|
|
274
|
+
"""
|
|
275
|
+
Sets the operation LED of the device.
|
|
276
|
+
|
|
277
|
+
Parameters
|
|
278
|
+
----------
|
|
279
|
+
enable : bool
|
|
280
|
+
If True, enables the operation LED. If False, disables it
|
|
281
|
+
|
|
282
|
+
Returns
|
|
283
|
+
-------
|
|
284
|
+
bool
|
|
285
|
+
True if the operation was successful, False otherwise
|
|
286
|
+
"""
|
|
287
|
+
address = CommonRegisters.OPERATION_CTRL
|
|
288
|
+
|
|
289
|
+
# Read register first
|
|
290
|
+
reg_value = self.send(
|
|
291
|
+
HarpMessage.create(MessageType.READ, address, PayloadType.U8)
|
|
292
|
+
).payload
|
|
293
|
+
|
|
294
|
+
if enable:
|
|
295
|
+
reg_value |= OperationCtrl.OPLEDEN
|
|
296
|
+
else:
|
|
297
|
+
reg_value &= ~OperationCtrl.OPLEDEN
|
|
298
|
+
|
|
299
|
+
reply = self.send(
|
|
300
|
+
HarpMessage.create(MessageType.WRITE, address, PayloadType.U8, reg_value)
|
|
301
|
+
)
|
|
302
|
+
|
|
303
|
+
return reply
|
|
304
|
+
|
|
305
|
+
def status_led(self, enable: bool) -> bool:
|
|
306
|
+
"""
|
|
307
|
+
Sets the status led of the device.
|
|
308
|
+
|
|
309
|
+
Parameters
|
|
310
|
+
----------
|
|
311
|
+
enable : bool
|
|
312
|
+
If True, enables the status led. If False, disables it
|
|
313
|
+
|
|
314
|
+
Returns
|
|
315
|
+
-------
|
|
316
|
+
bool
|
|
317
|
+
True if the operation was successful, False otherwise
|
|
318
|
+
"""
|
|
319
|
+
address = CommonRegisters.OPERATION_CTRL
|
|
320
|
+
|
|
321
|
+
# Read register first
|
|
322
|
+
reg_value = self.send(
|
|
323
|
+
HarpMessage.create(MessageType.READ, address, PayloadType.U8)
|
|
324
|
+
).payload
|
|
325
|
+
|
|
326
|
+
if enable:
|
|
327
|
+
reg_value |= OperationCtrl.STATUS_LED
|
|
328
|
+
else:
|
|
329
|
+
reg_value &= ~OperationCtrl.STATUS_LED
|
|
330
|
+
|
|
331
|
+
reply = self.send(
|
|
332
|
+
HarpMessage.create(MessageType.WRITE, address, PayloadType.U8, reg_value)
|
|
333
|
+
)
|
|
334
|
+
|
|
335
|
+
return reply
|
|
336
|
+
|
|
337
|
+
def mute_reply(self, enable: bool) -> bool:
|
|
338
|
+
"""
|
|
339
|
+
Sets the MUTE_REPLY bit of the device.
|
|
340
|
+
|
|
341
|
+
Parameters
|
|
342
|
+
----------
|
|
343
|
+
enable : bool
|
|
344
|
+
If True, the Replies to all the Commands are muted. If False, un-mutes them
|
|
345
|
+
|
|
346
|
+
Returns
|
|
347
|
+
-------
|
|
348
|
+
bool
|
|
349
|
+
True if the operation was successful, False otherwise
|
|
350
|
+
"""
|
|
351
|
+
address = CommonRegisters.OPERATION_CTRL
|
|
352
|
+
|
|
353
|
+
# Read register first
|
|
354
|
+
reg_value = self.send(
|
|
355
|
+
HarpMessage.create(MessageType.READ, address, PayloadType.U8)
|
|
356
|
+
).payload
|
|
357
|
+
|
|
358
|
+
if enable:
|
|
359
|
+
reg_value |= OperationCtrl.MUTE_RPL
|
|
360
|
+
else:
|
|
361
|
+
reg_value &= ~OperationCtrl.MUTE_RPL
|
|
362
|
+
|
|
363
|
+
reply = self.send(
|
|
364
|
+
HarpMessage.create(MessageType.WRITE, address, PayloadType.U8, reg_value)
|
|
365
|
+
)
|
|
366
|
+
|
|
367
|
+
return reply
|
|
368
|
+
|
|
369
|
+
def reset_device(
|
|
370
|
+
self, reset_mode: ResetMode = ResetMode.RST_DEF
|
|
371
|
+
) -> ReplyHarpMessage:
|
|
372
|
+
"""
|
|
373
|
+
Resets the device and reboots with all the registers with the default values. Beware that the EEPROM will be erased. More information on the reset device register can be found [here](https://harp-tech.org/protocol/Device.html#r_reset_dev-u8--reset-device-and-save-non-volatile-registers).
|
|
374
|
+
|
|
375
|
+
Returns
|
|
376
|
+
-------
|
|
377
|
+
ReplyHarpMessage
|
|
378
|
+
The reply to the Harp message
|
|
379
|
+
"""
|
|
380
|
+
address = CommonRegisters.RESET_DEV
|
|
381
|
+
reply = self.send(
|
|
382
|
+
HarpMessage.create(MessageType.WRITE, address, PayloadType.U8, reset_mode)
|
|
383
|
+
)
|
|
384
|
+
|
|
385
|
+
return reply
|
|
386
|
+
|
|
387
|
+
def set_clock_config(self, clock_config: ClockConfig) -> ReplyHarpMessage:
|
|
388
|
+
"""
|
|
389
|
+
Sets the clock configuration of the device.
|
|
390
|
+
|
|
391
|
+
Parameters
|
|
392
|
+
----------
|
|
393
|
+
clock_config : ClockConfig
|
|
394
|
+
The clock configuration value
|
|
395
|
+
|
|
396
|
+
Returns
|
|
397
|
+
-------
|
|
398
|
+
ReplyHarpMessage
|
|
399
|
+
The reply to the Harp message
|
|
400
|
+
"""
|
|
401
|
+
address = CommonRegisters.CLOCK_CONFIG
|
|
402
|
+
reply = self.send(
|
|
403
|
+
HarpMessage.create(MessageType.WRITE, address, PayloadType.U8, clock_config)
|
|
404
|
+
)
|
|
405
|
+
|
|
406
|
+
return reply
|
|
407
|
+
|
|
408
|
+
def set_timestamp_offset(self, timestamp_offset: int) -> ReplyHarpMessage:
|
|
409
|
+
"""
|
|
410
|
+
When the value of this register is above 0 (zero), the device's timestamp will be offset by this amount. The register is sensitive to 500 microsecond increments. This register is non-volatile.
|
|
411
|
+
|
|
412
|
+
Parameters
|
|
413
|
+
----------
|
|
414
|
+
timestamp_offset : int
|
|
415
|
+
The timestamp offset value
|
|
416
|
+
|
|
417
|
+
Returns
|
|
418
|
+
-------
|
|
419
|
+
ReplyHarpMessage
|
|
420
|
+
The reply to the Harp message
|
|
421
|
+
"""
|
|
422
|
+
address = CommonRegisters.TIMESTAMP_OFFSET
|
|
423
|
+
reply = self.send(
|
|
424
|
+
HarpMessage.create(
|
|
425
|
+
MessageType.WRITE, address, PayloadType.U8, timestamp_offset
|
|
426
|
+
)
|
|
427
|
+
)
|
|
428
|
+
|
|
429
|
+
return reply
|
|
430
|
+
|
|
431
|
+
def send(self, message: HarpMessage) -> Optional[ReplyHarpMessage]:
|
|
432
|
+
"""
|
|
433
|
+
Sends a Harp message.
|
|
434
|
+
|
|
435
|
+
Parameters
|
|
436
|
+
----------
|
|
437
|
+
message : HarpMessage
|
|
438
|
+
The HarpMessage containing the message to be sent to the device
|
|
439
|
+
|
|
440
|
+
Returns
|
|
441
|
+
-------
|
|
442
|
+
Optional[ReplyHarpMessage]
|
|
443
|
+
The reply to the Harp message or None if no reply is given
|
|
444
|
+
"""
|
|
445
|
+
self._ser.write(message.frame)
|
|
446
|
+
|
|
447
|
+
reply = self._read()
|
|
448
|
+
if reply is None:
|
|
449
|
+
return None
|
|
450
|
+
|
|
451
|
+
self._dump_reply(reply.frame)
|
|
452
|
+
|
|
453
|
+
return reply
|
|
454
|
+
|
|
455
|
+
def _read(self) -> Union[ReplyHarpMessage, None]:
|
|
456
|
+
"""
|
|
457
|
+
Reads an incoming serial message in a blocking way.
|
|
458
|
+
|
|
459
|
+
Returns
|
|
460
|
+
-------
|
|
461
|
+
Union[ReplyHarpMessage, None]
|
|
462
|
+
The incoming Harp message in case it exists
|
|
463
|
+
"""
|
|
464
|
+
try:
|
|
465
|
+
return self._ser.msg_q.get(block=True, timeout=self._read_timeout_s)
|
|
466
|
+
except queue.Empty:
|
|
467
|
+
return None
|
|
468
|
+
|
|
469
|
+
def _dump_reply(self, reply: bytes):
|
|
470
|
+
"""
|
|
471
|
+
Dumps the reply to a Harp message in the dump file in case it exists.
|
|
472
|
+
"""
|
|
473
|
+
if self._dump_file:
|
|
474
|
+
self._dump_file.write(reply)
|
|
475
|
+
|
|
476
|
+
def get_events(self) -> list[ReplyHarpMessage]:
|
|
477
|
+
"""
|
|
478
|
+
Gets all events from the event queue.
|
|
479
|
+
|
|
480
|
+
Returns
|
|
481
|
+
-------
|
|
482
|
+
list
|
|
483
|
+
The list containing every Harp event message that were on the queue
|
|
484
|
+
"""
|
|
485
|
+
msgs = []
|
|
486
|
+
while True:
|
|
487
|
+
try:
|
|
488
|
+
msgs.append(self._ser.event_q.get(timeout=False))
|
|
489
|
+
except queue.Empty:
|
|
490
|
+
break
|
|
491
|
+
return msgs
|
|
492
|
+
|
|
493
|
+
def event_count(self) -> int:
|
|
494
|
+
"""
|
|
495
|
+
Gets the number of events in the event queue.
|
|
496
|
+
|
|
497
|
+
Returns
|
|
498
|
+
-------
|
|
499
|
+
int
|
|
500
|
+
The number of events in the event queue
|
|
501
|
+
"""
|
|
502
|
+
return self._ser.event_q.qsize()
|
|
503
|
+
|
|
504
|
+
def read_u8(self, address: int) -> ReplyHarpMessage:
|
|
505
|
+
"""
|
|
506
|
+
Reads the value of a register of type U8.
|
|
507
|
+
|
|
508
|
+
Parameters
|
|
509
|
+
----------
|
|
510
|
+
address : int
|
|
511
|
+
The register to be read
|
|
512
|
+
|
|
513
|
+
Returns
|
|
514
|
+
-------
|
|
515
|
+
ReplyHarpMessage
|
|
516
|
+
The reply to the Harp message that will contain the value read from the register
|
|
517
|
+
"""
|
|
518
|
+
return self.send(
|
|
519
|
+
HarpMessage.create(
|
|
520
|
+
message_type=MessageType.READ,
|
|
521
|
+
address=address,
|
|
522
|
+
payload_type=PayloadType.U8,
|
|
523
|
+
)
|
|
524
|
+
)
|
|
525
|
+
|
|
526
|
+
def read_s8(self, address: int) -> ReplyHarpMessage:
|
|
527
|
+
"""
|
|
528
|
+
Reads the value of a register of type S8.
|
|
529
|
+
|
|
530
|
+
Parameters
|
|
531
|
+
----------
|
|
532
|
+
address : int
|
|
533
|
+
The register to be read
|
|
534
|
+
|
|
535
|
+
Returns
|
|
536
|
+
-------
|
|
537
|
+
ReplyHarpMessage
|
|
538
|
+
The reply to the Harp message that will contain the value read from the register
|
|
539
|
+
"""
|
|
540
|
+
return self.send(
|
|
541
|
+
HarpMessage.create(
|
|
542
|
+
message_type=MessageType.READ,
|
|
543
|
+
address=address,
|
|
544
|
+
payload_type=PayloadType.S8,
|
|
545
|
+
)
|
|
546
|
+
)
|
|
547
|
+
|
|
548
|
+
def read_u16(self, address: int) -> ReplyHarpMessage:
|
|
549
|
+
"""
|
|
550
|
+
Reads the value of a register of type U16.
|
|
551
|
+
|
|
552
|
+
Parameters
|
|
553
|
+
----------
|
|
554
|
+
address : int
|
|
555
|
+
The register to be read
|
|
556
|
+
|
|
557
|
+
Returns
|
|
558
|
+
-------
|
|
559
|
+
ReplyHarpMessage
|
|
560
|
+
The reply to the Harp message that will contain the value read from the register
|
|
561
|
+
"""
|
|
562
|
+
return self.send(
|
|
563
|
+
HarpMessage.create(
|
|
564
|
+
message_type=MessageType.READ,
|
|
565
|
+
address=address,
|
|
566
|
+
payload_type=PayloadType.U16,
|
|
567
|
+
)
|
|
568
|
+
)
|
|
569
|
+
|
|
570
|
+
def read_s16(self, address: int) -> ReplyHarpMessage:
|
|
571
|
+
"""
|
|
572
|
+
Reads the value of a register of type S16.
|
|
573
|
+
|
|
574
|
+
Parameters
|
|
575
|
+
----------
|
|
576
|
+
address : int
|
|
577
|
+
The register to be read
|
|
578
|
+
|
|
579
|
+
Returns
|
|
580
|
+
-------
|
|
581
|
+
ReplyHarpMessage
|
|
582
|
+
The reply to the Harp message that will contain the value read from the register
|
|
583
|
+
"""
|
|
584
|
+
return self.send(
|
|
585
|
+
HarpMessage.create(
|
|
586
|
+
message_type=MessageType.READ,
|
|
587
|
+
address=address,
|
|
588
|
+
payload_type=PayloadType.S16,
|
|
589
|
+
)
|
|
590
|
+
)
|
|
591
|
+
|
|
592
|
+
def read_u32(self, address: int) -> ReplyHarpMessage:
|
|
593
|
+
"""
|
|
594
|
+
Reads the value of a register of type U32.
|
|
595
|
+
|
|
596
|
+
Parameters
|
|
597
|
+
----------
|
|
598
|
+
address : int
|
|
599
|
+
The register to be read
|
|
600
|
+
|
|
601
|
+
Returns
|
|
602
|
+
-------
|
|
603
|
+
ReplyHarpMessage
|
|
604
|
+
The reply to the Harp message that will contain the value read from the register
|
|
605
|
+
"""
|
|
606
|
+
return self.send(
|
|
607
|
+
HarpMessage.create(
|
|
608
|
+
message_type=MessageType.READ,
|
|
609
|
+
address=address,
|
|
610
|
+
payload_type=PayloadType.U32,
|
|
611
|
+
)
|
|
612
|
+
)
|
|
613
|
+
|
|
614
|
+
def read_s32(self, address: int) -> ReplyHarpMessage:
|
|
615
|
+
"""
|
|
616
|
+
Reads the value of a register of type S32.
|
|
617
|
+
|
|
618
|
+
Parameters
|
|
619
|
+
----------
|
|
620
|
+
address : int
|
|
621
|
+
The register to be read
|
|
622
|
+
|
|
623
|
+
Returns
|
|
624
|
+
-------
|
|
625
|
+
ReplyHarpMessage
|
|
626
|
+
The reply to the Harp message that will contain the value read from the register
|
|
627
|
+
"""
|
|
628
|
+
return self.send(
|
|
629
|
+
HarpMessage.create(
|
|
630
|
+
message_type=MessageType.READ,
|
|
631
|
+
address=address,
|
|
632
|
+
payload_type=PayloadType.S32,
|
|
633
|
+
)
|
|
634
|
+
)
|
|
635
|
+
|
|
636
|
+
def read_u64(self, address: int) -> ReplyHarpMessage:
|
|
637
|
+
"""
|
|
638
|
+
Reads the value of a register of type U64.
|
|
639
|
+
|
|
640
|
+
Parameters
|
|
641
|
+
----------
|
|
642
|
+
address : int
|
|
643
|
+
The register to be read
|
|
644
|
+
|
|
645
|
+
Returns
|
|
646
|
+
-------
|
|
647
|
+
ReplyHarpMessage
|
|
648
|
+
The reply to the Harp message that will contain the value read from the register
|
|
649
|
+
"""
|
|
650
|
+
return self.send(
|
|
651
|
+
HarpMessage.create(
|
|
652
|
+
message_type=MessageType.READ,
|
|
653
|
+
address=address,
|
|
654
|
+
payload_type=PayloadType.U64,
|
|
655
|
+
)
|
|
656
|
+
)
|
|
657
|
+
|
|
658
|
+
def read_s64(self, address: int) -> ReplyHarpMessage:
|
|
659
|
+
"""
|
|
660
|
+
Reads the value of a register of type S64.
|
|
661
|
+
|
|
662
|
+
Parameters
|
|
663
|
+
----------
|
|
664
|
+
address : int
|
|
665
|
+
The register to be read
|
|
666
|
+
|
|
667
|
+
Returns
|
|
668
|
+
-------
|
|
669
|
+
ReplyHarpMessage
|
|
670
|
+
The reply to the Harp message that will contain the value read from the register
|
|
671
|
+
"""
|
|
672
|
+
return self.send(
|
|
673
|
+
HarpMessage.create(
|
|
674
|
+
message_type=MessageType.READ,
|
|
675
|
+
address=address,
|
|
676
|
+
payload_type=PayloadType.S64,
|
|
677
|
+
)
|
|
678
|
+
)
|
|
679
|
+
|
|
680
|
+
def read_float(self, address: int) -> ReplyHarpMessage:
|
|
681
|
+
"""
|
|
682
|
+
Reads the value of a register of type Float.
|
|
683
|
+
|
|
684
|
+
Parameters
|
|
685
|
+
----------
|
|
686
|
+
address : int
|
|
687
|
+
The register to be read
|
|
688
|
+
|
|
689
|
+
Returns
|
|
690
|
+
-------
|
|
691
|
+
ReplyHarpMessage
|
|
692
|
+
The reply to the Harp message that will contain the value read from the register
|
|
693
|
+
"""
|
|
694
|
+
return self.send(
|
|
695
|
+
HarpMessage.create(
|
|
696
|
+
message_type=MessageType.READ,
|
|
697
|
+
address=address,
|
|
698
|
+
payload_type=PayloadType.Float,
|
|
699
|
+
)
|
|
700
|
+
)
|
|
701
|
+
|
|
702
|
+
def write_u8(self, address: int, value: int | list[int]) -> ReplyHarpMessage:
|
|
703
|
+
"""
|
|
704
|
+
Writes the value of a register of type U8.
|
|
705
|
+
|
|
706
|
+
Parameters
|
|
707
|
+
----------
|
|
708
|
+
address : int
|
|
709
|
+
The register to be written on
|
|
710
|
+
value: int | list[int]
|
|
711
|
+
The value to be written to the register
|
|
712
|
+
|
|
713
|
+
Returns
|
|
714
|
+
-------
|
|
715
|
+
ReplyHarpMessage
|
|
716
|
+
The reply to the Harp message
|
|
717
|
+
"""
|
|
718
|
+
return self.send(
|
|
719
|
+
HarpMessage.create(
|
|
720
|
+
message_type=MessageType.WRITE,
|
|
721
|
+
address=address,
|
|
722
|
+
payload_type=PayloadType.U8,
|
|
723
|
+
value=value,
|
|
724
|
+
)
|
|
725
|
+
)
|
|
726
|
+
|
|
727
|
+
def write_s8(self, address: int, value: int | list[int]) -> ReplyHarpMessage:
|
|
728
|
+
"""
|
|
729
|
+
Writes the value of a register of type S8.
|
|
730
|
+
|
|
731
|
+
Parameters
|
|
732
|
+
----------
|
|
733
|
+
address : int
|
|
734
|
+
The register to be written on
|
|
735
|
+
value: int | list[int]
|
|
736
|
+
The value to be written to the register
|
|
737
|
+
|
|
738
|
+
Returns
|
|
739
|
+
-------
|
|
740
|
+
ReplyHarpMessage
|
|
741
|
+
The reply to the Harp message
|
|
742
|
+
"""
|
|
743
|
+
return self.send(
|
|
744
|
+
HarpMessage.create(
|
|
745
|
+
message_type=MessageType.WRITE,
|
|
746
|
+
address=address,
|
|
747
|
+
payload_type=PayloadType.S8,
|
|
748
|
+
value=value,
|
|
749
|
+
)
|
|
750
|
+
)
|
|
751
|
+
|
|
752
|
+
def write_u16(self, address: int, value: int | list[int]) -> ReplyHarpMessage:
|
|
753
|
+
"""
|
|
754
|
+
Writes the value of a register of type U16.
|
|
755
|
+
|
|
756
|
+
Parameters
|
|
757
|
+
----------
|
|
758
|
+
address : int
|
|
759
|
+
The register to be written on
|
|
760
|
+
value: int | list[int]
|
|
761
|
+
The value to be written to the register
|
|
762
|
+
|
|
763
|
+
Returns
|
|
764
|
+
-------
|
|
765
|
+
ReplyHarpMessage
|
|
766
|
+
The reply to the Harp message
|
|
767
|
+
"""
|
|
768
|
+
return self.send(
|
|
769
|
+
HarpMessage.create(
|
|
770
|
+
message_type=MessageType.WRITE,
|
|
771
|
+
address=address,
|
|
772
|
+
payload_type=PayloadType.U16,
|
|
773
|
+
value=value,
|
|
774
|
+
)
|
|
775
|
+
)
|
|
776
|
+
|
|
777
|
+
def write_s16(self, address: int, value: int | list[int]) -> ReplyHarpMessage:
|
|
778
|
+
"""
|
|
779
|
+
Writes the value of a register of type S16.
|
|
780
|
+
|
|
781
|
+
Parameters
|
|
782
|
+
----------
|
|
783
|
+
address : int
|
|
784
|
+
The register to be written on
|
|
785
|
+
value: int | list[int]
|
|
786
|
+
The value to be written to the register
|
|
787
|
+
|
|
788
|
+
Returns
|
|
789
|
+
-------
|
|
790
|
+
ReplyHarpMessage
|
|
791
|
+
The reply to the Harp message
|
|
792
|
+
"""
|
|
793
|
+
return self.send(
|
|
794
|
+
HarpMessage.create(
|
|
795
|
+
message_type=MessageType.WRITE,
|
|
796
|
+
address=address,
|
|
797
|
+
payload_type=PayloadType.S16,
|
|
798
|
+
value=value,
|
|
799
|
+
)
|
|
800
|
+
)
|
|
801
|
+
|
|
802
|
+
def write_u32(self, address: int, value: int | list[int]) -> ReplyHarpMessage:
|
|
803
|
+
"""
|
|
804
|
+
Writes the value of a register of type U32.
|
|
805
|
+
|
|
806
|
+
Parameters
|
|
807
|
+
----------
|
|
808
|
+
address : int
|
|
809
|
+
The register to be written on
|
|
810
|
+
value: int | list[int]
|
|
811
|
+
The value to be written to the register
|
|
812
|
+
|
|
813
|
+
Returns
|
|
814
|
+
-------
|
|
815
|
+
ReplyHarpMessage
|
|
816
|
+
The reply to the Harp message
|
|
817
|
+
"""
|
|
818
|
+
return self.send(
|
|
819
|
+
HarpMessage.create(
|
|
820
|
+
message_type=MessageType.WRITE,
|
|
821
|
+
address=address,
|
|
822
|
+
payload_type=PayloadType.U32,
|
|
823
|
+
value=value,
|
|
824
|
+
)
|
|
825
|
+
)
|
|
826
|
+
|
|
827
|
+
def write_s32(self, address: int, value: int | list[int]) -> ReplyHarpMessage:
|
|
828
|
+
"""
|
|
829
|
+
Writes the value of a register of type S32.
|
|
830
|
+
|
|
831
|
+
Parameters
|
|
832
|
+
----------
|
|
833
|
+
address : int
|
|
834
|
+
The register to be written on
|
|
835
|
+
value: int | list[int]
|
|
836
|
+
The value to be written to the register
|
|
837
|
+
|
|
838
|
+
Returns
|
|
839
|
+
-------
|
|
840
|
+
ReplyHarpMessage
|
|
841
|
+
The reply to the Harp message
|
|
842
|
+
"""
|
|
843
|
+
return self.send(
|
|
844
|
+
HarpMessage.create(
|
|
845
|
+
message_type=MessageType.WRITE,
|
|
846
|
+
address=address,
|
|
847
|
+
payload_type=PayloadType.S32,
|
|
848
|
+
value=value,
|
|
849
|
+
)
|
|
850
|
+
)
|
|
851
|
+
|
|
852
|
+
def write_u64(self, address: int, value: int | list[int]) -> ReplyHarpMessage:
|
|
853
|
+
"""
|
|
854
|
+
Writes the value of a register of type U64.
|
|
855
|
+
|
|
856
|
+
Parameters
|
|
857
|
+
----------
|
|
858
|
+
address : int
|
|
859
|
+
The register to be written on
|
|
860
|
+
value: int | list[int]
|
|
861
|
+
The value to be written to the register
|
|
862
|
+
|
|
863
|
+
Returns
|
|
864
|
+
-------
|
|
865
|
+
ReplyHarpMessage
|
|
866
|
+
The reply to the Harp message
|
|
867
|
+
"""
|
|
868
|
+
return self.send(
|
|
869
|
+
HarpMessage.create(
|
|
870
|
+
message_type=MessageType.WRITE,
|
|
871
|
+
address=address,
|
|
872
|
+
payload_type=PayloadType.U64,
|
|
873
|
+
value=value,
|
|
874
|
+
)
|
|
875
|
+
)
|
|
876
|
+
|
|
877
|
+
def write_s64(self, address: int, value: int | list[int]) -> ReplyHarpMessage:
|
|
878
|
+
"""
|
|
879
|
+
Writes the value of a register of type S64.
|
|
880
|
+
|
|
881
|
+
Parameters
|
|
882
|
+
----------
|
|
883
|
+
address : int
|
|
884
|
+
The register to be written on
|
|
885
|
+
value: int | list[int]
|
|
886
|
+
The value to be written to the register
|
|
887
|
+
|
|
888
|
+
Returns
|
|
889
|
+
-------
|
|
890
|
+
ReplyHarpMessage
|
|
891
|
+
The reply to the Harp message
|
|
892
|
+
"""
|
|
893
|
+
return self.send(
|
|
894
|
+
HarpMessage.create(
|
|
895
|
+
message_type=MessageType.WRITE,
|
|
896
|
+
address=address,
|
|
897
|
+
payload_type=PayloadType.S64,
|
|
898
|
+
value=value,
|
|
899
|
+
)
|
|
900
|
+
)
|
|
901
|
+
|
|
902
|
+
def write_float(self, address: int, value: float | list[float]) -> ReplyHarpMessage:
|
|
903
|
+
"""
|
|
904
|
+
Writes the value of a register of type Float.
|
|
905
|
+
|
|
906
|
+
Parameters
|
|
907
|
+
----------
|
|
908
|
+
address : int
|
|
909
|
+
The register to be written on
|
|
910
|
+
value: int | list[int]
|
|
911
|
+
The value to be written to the register
|
|
912
|
+
|
|
913
|
+
Returns
|
|
914
|
+
-------
|
|
915
|
+
ReplyHarpMessage
|
|
916
|
+
The reply to the Harp message
|
|
917
|
+
"""
|
|
918
|
+
return self.send(
|
|
919
|
+
HarpMessage.create(
|
|
920
|
+
message_type=MessageType.WRITE,
|
|
921
|
+
address=address,
|
|
922
|
+
payload_type=PayloadType.Float,
|
|
923
|
+
value=value,
|
|
924
|
+
)
|
|
925
|
+
)
|
|
926
|
+
|
|
927
|
+
def _read_who_am_i(self) -> int:
|
|
928
|
+
"""
|
|
929
|
+
Reads the value stored in the `WHO_AM_I` register.
|
|
930
|
+
|
|
931
|
+
Returns
|
|
932
|
+
-------
|
|
933
|
+
int
|
|
934
|
+
The value of the `WHO_AM_I` register
|
|
935
|
+
"""
|
|
936
|
+
address = CommonRegisters.WHO_AM_I
|
|
937
|
+
|
|
938
|
+
reply: ReplyHarpMessage = self.send(
|
|
939
|
+
HarpMessage.create(MessageType.READ, address, PayloadType.U16)
|
|
940
|
+
)
|
|
941
|
+
|
|
942
|
+
return reply.payload
|
|
943
|
+
|
|
944
|
+
def _read_default_device_name(self) -> str:
|
|
945
|
+
"""
|
|
946
|
+
Returns the `DEFAULT_DEVICE_NAME` by cross-referencing the `WHO_AM_I` with the corresponding device name in the `device_names` dictionary.
|
|
947
|
+
|
|
948
|
+
Returns
|
|
949
|
+
-------
|
|
950
|
+
str
|
|
951
|
+
The default device name
|
|
952
|
+
"""
|
|
953
|
+
return device_names.get(self.WHO_AM_I, "Unknown device")
|
|
954
|
+
|
|
955
|
+
def _read_hw_version_h(self) -> int:
|
|
956
|
+
"""
|
|
957
|
+
Reads the value stored in the `HW_VERSION_H` register.
|
|
958
|
+
|
|
959
|
+
Returns
|
|
960
|
+
-------
|
|
961
|
+
int
|
|
962
|
+
The value of the `HW_VERSION_H` register
|
|
963
|
+
"""
|
|
964
|
+
address = CommonRegisters.HW_VERSION_H
|
|
965
|
+
|
|
966
|
+
reply: ReplyHarpMessage = self.send(
|
|
967
|
+
HarpMessage.create(MessageType.READ, address, PayloadType.U8)
|
|
968
|
+
)
|
|
969
|
+
|
|
970
|
+
return reply.payload
|
|
971
|
+
|
|
972
|
+
def _read_hw_version_l(self) -> int:
|
|
973
|
+
"""
|
|
974
|
+
Reads the value stored in the `HW_VERSION_L` register.
|
|
975
|
+
|
|
976
|
+
Returns
|
|
977
|
+
-------
|
|
978
|
+
int
|
|
979
|
+
The value of the `HW_VERSION_L` register
|
|
980
|
+
"""
|
|
981
|
+
address = CommonRegisters.HW_VERSION_L
|
|
982
|
+
|
|
983
|
+
reply: ReplyHarpMessage = self.send(
|
|
984
|
+
HarpMessage.create(MessageType.READ, address, PayloadType.U8)
|
|
985
|
+
)
|
|
986
|
+
|
|
987
|
+
return reply.payload
|
|
988
|
+
|
|
989
|
+
def _read_assembly_version(self) -> int:
|
|
990
|
+
"""
|
|
991
|
+
Reads the value stored in the `ASSEMBLY_VERSION` register.
|
|
992
|
+
|
|
993
|
+
Returns
|
|
994
|
+
-------
|
|
995
|
+
int
|
|
996
|
+
The value of the `ASSEMBLY_VERSION` register
|
|
997
|
+
"""
|
|
998
|
+
address = CommonRegisters.ASSEMBLY_VERSION
|
|
999
|
+
|
|
1000
|
+
reply: ReplyHarpMessage = self.send(
|
|
1001
|
+
HarpMessage.create(MessageType.READ, address, PayloadType.U8)
|
|
1002
|
+
)
|
|
1003
|
+
|
|
1004
|
+
return reply.payload
|
|
1005
|
+
|
|
1006
|
+
def _read_harp_version_h(self) -> int:
|
|
1007
|
+
"""
|
|
1008
|
+
Reads the value stored in the `HARP_VERSION_H` register.
|
|
1009
|
+
|
|
1010
|
+
Returns
|
|
1011
|
+
-------
|
|
1012
|
+
int
|
|
1013
|
+
The value of the `HARP_VERSION_H` register
|
|
1014
|
+
"""
|
|
1015
|
+
address = CommonRegisters.HARP_VERSION_H
|
|
1016
|
+
|
|
1017
|
+
reply: ReplyHarpMessage = self.send(
|
|
1018
|
+
HarpMessage.create(MessageType.READ, address, PayloadType.U8)
|
|
1019
|
+
)
|
|
1020
|
+
|
|
1021
|
+
return reply.payload
|
|
1022
|
+
|
|
1023
|
+
def _read_harp_version_l(self) -> int:
|
|
1024
|
+
"""
|
|
1025
|
+
Reads the value stored in the `HARP_VERSION_L` register.
|
|
1026
|
+
|
|
1027
|
+
Returns
|
|
1028
|
+
-------
|
|
1029
|
+
int
|
|
1030
|
+
The value of the `HARP_VERSION_L` register
|
|
1031
|
+
"""
|
|
1032
|
+
address = CommonRegisters.HARP_VERSION_L
|
|
1033
|
+
|
|
1034
|
+
reply: ReplyHarpMessage = self.send(
|
|
1035
|
+
HarpMessage.create(MessageType.READ, address, PayloadType.U8)
|
|
1036
|
+
)
|
|
1037
|
+
|
|
1038
|
+
return reply.payload
|
|
1039
|
+
|
|
1040
|
+
def _read_fw_version_h(self) -> int:
|
|
1041
|
+
"""
|
|
1042
|
+
Reads the value stored in the `FW_VERSION_H` register.
|
|
1043
|
+
|
|
1044
|
+
Returns
|
|
1045
|
+
-------
|
|
1046
|
+
int
|
|
1047
|
+
The value of the `FW_VERSION_H` register
|
|
1048
|
+
"""
|
|
1049
|
+
address = CommonRegisters.FIRMWARE_VERSION_H
|
|
1050
|
+
|
|
1051
|
+
reply: ReplyHarpMessage = self.send(
|
|
1052
|
+
HarpMessage.create(MessageType.READ, address, PayloadType.U8)
|
|
1053
|
+
)
|
|
1054
|
+
|
|
1055
|
+
return reply.payload
|
|
1056
|
+
|
|
1057
|
+
def _read_fw_version_l(self) -> int:
|
|
1058
|
+
"""
|
|
1059
|
+
Reads the value stored in the `FW_VERSION_L` register.
|
|
1060
|
+
|
|
1061
|
+
Returns
|
|
1062
|
+
-------
|
|
1063
|
+
int
|
|
1064
|
+
The value of the `FW_VERSION_L` register
|
|
1065
|
+
"""
|
|
1066
|
+
address = CommonRegisters.FIRMWARE_VERSION_L
|
|
1067
|
+
|
|
1068
|
+
reply: ReplyHarpMessage = self.send(
|
|
1069
|
+
HarpMessage.create(MessageType.READ, address, PayloadType.U8)
|
|
1070
|
+
)
|
|
1071
|
+
|
|
1072
|
+
return reply.payload
|
|
1073
|
+
|
|
1074
|
+
def _read_device_name(self) -> str:
|
|
1075
|
+
"""
|
|
1076
|
+
Reads the value stored in the `DEVICE_NAME` register.
|
|
1077
|
+
|
|
1078
|
+
Returns
|
|
1079
|
+
-------
|
|
1080
|
+
int
|
|
1081
|
+
The value of the `DEVICE_NAME` register
|
|
1082
|
+
"""
|
|
1083
|
+
address = CommonRegisters.DEVICE_NAME
|
|
1084
|
+
|
|
1085
|
+
reply: ReplyHarpMessage = self.send(
|
|
1086
|
+
HarpMessage.create(MessageType.READ, address, PayloadType.U8)
|
|
1087
|
+
)
|
|
1088
|
+
|
|
1089
|
+
return reply.payload_as_string()
|
|
1090
|
+
|
|
1091
|
+
def _read_serial_number(self) -> int:
|
|
1092
|
+
"""
|
|
1093
|
+
Reads the value stored in the `SERIAL_NUMBER` register.
|
|
1094
|
+
|
|
1095
|
+
Returns
|
|
1096
|
+
-------
|
|
1097
|
+
int
|
|
1098
|
+
The value of the `SERIAL_NUMBER` register
|
|
1099
|
+
"""
|
|
1100
|
+
address = CommonRegisters.SERIAL_NUMBER
|
|
1101
|
+
|
|
1102
|
+
reply: ReplyHarpMessage = self.send(
|
|
1103
|
+
HarpMessage.create(MessageType.READ, address, PayloadType.U8)
|
|
1104
|
+
)
|
|
1105
|
+
|
|
1106
|
+
if reply.is_error:
|
|
1107
|
+
return 0
|
|
1108
|
+
|
|
1109
|
+
return reply.payload
|
|
1110
|
+
|
|
1111
|
+
def _read_clock_config(self) -> int:
|
|
1112
|
+
"""
|
|
1113
|
+
Reads the value stored in the `CLOCK_CONFIG` register.
|
|
1114
|
+
|
|
1115
|
+
Returns
|
|
1116
|
+
-------
|
|
1117
|
+
int
|
|
1118
|
+
The value of the `CLOCK_CONFIG` register
|
|
1119
|
+
"""
|
|
1120
|
+
address = CommonRegisters.CLOCK_CONFIG
|
|
1121
|
+
|
|
1122
|
+
reply: ReplyHarpMessage = self.send(
|
|
1123
|
+
HarpMessage.create(MessageType.READ, address, PayloadType.U8)
|
|
1124
|
+
)
|
|
1125
|
+
|
|
1126
|
+
return reply.payload
|
|
1127
|
+
|
|
1128
|
+
def _read_timestamp_offset(self) -> int:
|
|
1129
|
+
"""
|
|
1130
|
+
Reads the value stored in the `TIMESTAMP_OFFSET` register.
|
|
1131
|
+
|
|
1132
|
+
Returns
|
|
1133
|
+
-------
|
|
1134
|
+
int
|
|
1135
|
+
The value of the `TIMESTAMP_OFFSET` register
|
|
1136
|
+
"""
|
|
1137
|
+
address = CommonRegisters.TIMESTAMP_OFFSET
|
|
1138
|
+
|
|
1139
|
+
reply: ReplyHarpMessage = self.send(
|
|
1140
|
+
HarpMessage.create(MessageType.READ, address, PayloadType.U8)
|
|
1141
|
+
)
|
|
1142
|
+
|
|
1143
|
+
return reply.payload
|
|
1144
|
+
|
|
1145
|
+
def __enter__(self):
|
|
1146
|
+
"""
|
|
1147
|
+
Support for using Device with 'with' statement.
|
|
1148
|
+
|
|
1149
|
+
Returns
|
|
1150
|
+
-------
|
|
1151
|
+
Device
|
|
1152
|
+
The Device instance
|
|
1153
|
+
"""
|
|
1154
|
+
# Connection is already established in __init__
|
|
1155
|
+
# but we could add additional setup if needed
|
|
1156
|
+
return self
|
|
1157
|
+
|
|
1158
|
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
1159
|
+
"""
|
|
1160
|
+
Cleanup resources when exiting the 'with' block.
|
|
1161
|
+
|
|
1162
|
+
Parameters
|
|
1163
|
+
----------
|
|
1164
|
+
exc_type : Exception type or None
|
|
1165
|
+
Type of the exception that caused the context to be exited
|
|
1166
|
+
exc_val : Exception or None
|
|
1167
|
+
Exception instance that caused the context to be exited
|
|
1168
|
+
exc_tb : traceback or None
|
|
1169
|
+
Traceback if an exception occurred
|
|
1170
|
+
"""
|
|
1171
|
+
self.disconnect()
|
|
1172
|
+
# Return False to propagate exceptions that occurred in the with block
|
|
1173
|
+
return False
|