harp-hobgoblin 0.2.0__tar.gz

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,4 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ dist/
4
+ *.egg-info/
@@ -0,0 +1 @@
1
+ 3.11
@@ -0,0 +1,19 @@
1
+ Copyright (C) harp-tech and Contributors
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
4
+ this software and associated documentation files (the "Software"), to deal in
5
+ the Software without restriction, including without limitation the rights to
6
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7
+ of the Software, and to permit persons to whom the Software is furnished to do
8
+ so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ SOFTWARE.
@@ -0,0 +1,61 @@
1
+ Metadata-Version: 2.4
2
+ Name: harp-hobgoblin
3
+ Version: 0.2.0
4
+ Summary: Interface for data acquisition and control of Harp Hobgoblin devices.
5
+ Author-email: harp-tech <contact@harp-tech.org>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://harp-tech.org/device.hobgoblin
8
+ Project-URL: Repository, https://github.com/harp-tech/device.hobgoblin
9
+ Project-URL: Bug Tracker, https://github.com/harp-tech/device.hobgoblin/issues
10
+ Project-URL: Changelog, https://github.com/harp-tech/device.hobgoblin/releases
11
+ Keywords: harp,hobgoblin,data-acquisition,hardware,device-control
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Intended Audience :: Science/Research
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: Operating System :: Microsoft :: Windows
16
+ Classifier: Operating System :: POSIX :: Linux
17
+ Classifier: Operating System :: MacOS
18
+ Classifier: Programming Language :: Python :: 3
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Programming Language :: Python :: 3.13
22
+ Classifier: Topic :: Scientific/Engineering
23
+ Classifier: Topic :: System :: Hardware :: Hardware Drivers
24
+ Requires-Python: >=3.11
25
+ Description-Content-Type: text/markdown
26
+ License-File: LICENSE
27
+ Requires-Dist: harp-protocol>=0.5
28
+ Requires-Dist: harp-device>=0.5
29
+ Requires-Dist: numpy>=1.24
30
+ Dynamic: license-file
31
+
32
+ # harp-hobgoblin
33
+
34
+ The Python interface for the [Harp Hobgoblin](https://harp-tech.org/device.hobgoblin) device. It carries the register classes for the device, the payload and enumeration types those registers use, and a `REGISTER_MAP` pairing every address with its register.
35
+
36
+ ## Installation
37
+
38
+ ```text
39
+ pip install harp-hobgoblin
40
+ ```
41
+
42
+ ## Reading and writing registers
43
+
44
+ Register classes are passed to `read` and `write` on an open device transport, such as the serial transport in [Harp Python](https://harp-tech.org/python/).
45
+
46
+ ```python
47
+ from harp import serial
48
+ from harp.device import hobgoblin, client
49
+
50
+ SERIAL_PORT = "/dev/ttyUSB0" # or "COMx" in Windows, where "x" is the serial port number
51
+
52
+ with serial.open_device(client.Device, port=SERIAL_PORT) as device:
53
+ print("device:", hobgoblin.DEVICE_NAME, "WhoAmI:", hobgoblin.WHO_AM_I)
54
+ print("analog data:", device.read(hobgoblin.AnalogData).payload)
55
+ ```
56
+
57
+ `open_dataset` in `harp.data` takes this module as its second argument, and decodes recorded data through the same register classes.
58
+
59
+ ## Feedback and contributing
60
+
61
+ `harp-hobgoblin` is released as open source under the MIT license. Bug reports and contributions are welcome at [the GitHub repository](https://github.com/harp-tech/device.hobgoblin).
@@ -0,0 +1,30 @@
1
+ # harp-hobgoblin
2
+
3
+ The Python interface for the [Harp Hobgoblin](https://harp-tech.org/device.hobgoblin) device. It carries the register classes for the device, the payload and enumeration types those registers use, and a `REGISTER_MAP` pairing every address with its register.
4
+
5
+ ## Installation
6
+
7
+ ```text
8
+ pip install harp-hobgoblin
9
+ ```
10
+
11
+ ## Reading and writing registers
12
+
13
+ Register classes are passed to `read` and `write` on an open device transport, such as the serial transport in [Harp Python](https://harp-tech.org/python/).
14
+
15
+ ```python
16
+ from harp import serial
17
+ from harp.device import hobgoblin, client
18
+
19
+ SERIAL_PORT = "/dev/ttyUSB0" # or "COMx" in Windows, where "x" is the serial port number
20
+
21
+ with serial.open_device(client.Device, port=SERIAL_PORT) as device:
22
+ print("device:", hobgoblin.DEVICE_NAME, "WhoAmI:", hobgoblin.WHO_AM_I)
23
+ print("analog data:", device.read(hobgoblin.AnalogData).payload)
24
+ ```
25
+
26
+ `open_dataset` in `harp.data` takes this module as its second argument, and decodes recorded data through the same register classes.
27
+
28
+ ## Feedback and contributing
29
+
30
+ `harp-hobgoblin` is released as open source under the MIT license. Bug reports and contributions are welcome at [the GitHub repository](https://github.com/harp-tech/device.hobgoblin).
@@ -0,0 +1,62 @@
1
+ [project]
2
+ name = "harp-hobgoblin"
3
+ dynamic = ["version"]
4
+ description = "Interface for data acquisition and control of Harp Hobgoblin devices."
5
+ authors = [{ name = "harp-tech", email = "contact@harp-tech.org" }]
6
+ license = "MIT"
7
+ license-files = ["LICENSE"]
8
+ readme = "README.md"
9
+ keywords = [
10
+ "harp",
11
+ "hobgoblin",
12
+ "data-acquisition",
13
+ "hardware",
14
+ "device-control",
15
+ ]
16
+ requires-python = ">=3.11"
17
+ classifiers = [
18
+ "Development Status :: 4 - Beta",
19
+ "Intended Audience :: Science/Research",
20
+ "Intended Audience :: Developers",
21
+ "Operating System :: Microsoft :: Windows",
22
+ "Operating System :: POSIX :: Linux",
23
+ "Operating System :: MacOS",
24
+ "Programming Language :: Python :: 3",
25
+ "Programming Language :: Python :: 3.11",
26
+ "Programming Language :: Python :: 3.12",
27
+ "Programming Language :: Python :: 3.13",
28
+ "Topic :: Scientific/Engineering",
29
+ "Topic :: System :: Hardware :: Hardware Drivers",
30
+ ]
31
+ dependencies = [
32
+ "harp-protocol>=0.5",
33
+ "harp-device>=0.5",
34
+ "numpy>=1.24",
35
+ ]
36
+
37
+ [project.urls]
38
+ Homepage = "https://harp-tech.org/device.hobgoblin"
39
+ Repository = "https://github.com/harp-tech/device.hobgoblin"
40
+ "Bug Tracker" = "https://github.com/harp-tech/device.hobgoblin/issues"
41
+ Changelog = "https://github.com/harp-tech/device.hobgoblin/releases"
42
+
43
+ [build-system]
44
+ requires = ["setuptools>=77", "setuptools-scm>=8"]
45
+ build-backend = "setuptools.build_meta"
46
+
47
+ [tool.setuptools_scm]
48
+ root = "../.."
49
+ git_describe_command = "git describe --dirty --tags --long --match v[0-9]*.[0-9]*.[0-9]*"
50
+
51
+ [tool.setuptools.packages.find]
52
+ where = ["src"]
53
+ include = ["harp*"]
54
+
55
+ [dependency-groups]
56
+ dev = ["pytest>=8"]
57
+
58
+ [tool.docfx-tools]
59
+ inventories = [
60
+ "https://harp-tech.org/python/objects.inv",
61
+ "https://numpy.org/doc/stable/objects.inv",
62
+ ]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,418 @@
1
+ # This file was automatically generated and should not be edited directly.
2
+ # To make changes, edit the device metadata and regenerate the interface.
3
+
4
+ import enum
5
+ from typing import Any, ClassVar
6
+
7
+ import numpy as np
8
+ from harp.protocol import (
9
+ AnonymousPayload,
10
+ BitMask,
11
+ Field,
12
+ IdentityConverter,
13
+ PayloadType,
14
+ RegisterBase,
15
+ StructPayload,
16
+ )
17
+ from harp.device.core import REGISTER_MAP as _CORE_REGISTER_MAP
18
+
19
+
20
+ __all__ = [
21
+ "DEVICE_NAME",
22
+ "WHO_AM_I",
23
+ "DigitalInputs",
24
+ "DigitalOutputs",
25
+ "DigitalInputStatePayload",
26
+ "DigitalOutputSetPayload",
27
+ "DigitalOutputClearPayload",
28
+ "DigitalOutputTogglePayload",
29
+ "DigitalOutputStatePayload",
30
+ "AnalogDataPayload",
31
+ "PulseTrainGP15Payload",
32
+ "PulseTrainGP16Payload",
33
+ "PulseTrainGP17Payload",
34
+ "PulseTrainGP18Payload",
35
+ "PulseTrainGP19Payload",
36
+ "PulseTrainGP20Payload",
37
+ "PulseTrainGP21Payload",
38
+ "PulseTrainGP22Payload",
39
+ "PulseEventEnablePayload",
40
+ "DigitalInputState",
41
+ "DigitalOutputSet",
42
+ "DigitalOutputClear",
43
+ "DigitalOutputToggle",
44
+ "DigitalOutputState",
45
+ "AnalogData",
46
+ "PulseTrainGP15",
47
+ "PulseTrainGP16",
48
+ "PulseTrainGP17",
49
+ "PulseTrainGP18",
50
+ "PulseTrainGP19",
51
+ "PulseTrainGP20",
52
+ "PulseTrainGP21",
53
+ "PulseTrainGP22",
54
+ "PulseEventEnable",
55
+ "REGISTER_MAP",
56
+ ]
57
+
58
+ DEVICE_NAME: str = "Hobgoblin"
59
+ WHO_AM_I: int = 123
60
+
61
+
62
+ class DigitalInputs(enum.IntFlag):
63
+ """Specifies the state of port digital input lines."""
64
+
65
+ GP2 = 0x1
66
+ """Digital input on pin GP2"""
67
+
68
+ GP3 = 0x2
69
+ """Digital input on pin GP3"""
70
+
71
+ GP12 = 0x4
72
+ """Digital input on pin GP12"""
73
+
74
+ GP13 = 0x8
75
+ """Digital input on pin GP13"""
76
+
77
+ GP14 = 0x10
78
+ """Digital input on pin GP14"""
79
+
80
+
81
+ class DigitalOutputs(enum.IntFlag):
82
+ """Specifies the state of port digital output lines."""
83
+
84
+ GP15 = 0x1
85
+ """Digital output on pin GP15"""
86
+
87
+ GP16 = 0x2
88
+ """Digital output on pin GP16"""
89
+
90
+ GP17 = 0x4
91
+ """Digital output on pin GP17"""
92
+
93
+ GP18 = 0x8
94
+ """Digital output on pin GP18"""
95
+
96
+ GP19 = 0x10
97
+ """Digital output on pin GP19"""
98
+
99
+ GP20 = 0x20
100
+ """Digital output on pin GP20"""
101
+
102
+ GP21 = 0x40
103
+ """Digital output on pin GP21"""
104
+
105
+ GP22 = 0x80
106
+ """Digital output on pin GP22"""
107
+
108
+
109
+ class DigitalInputStatePayload(AnonymousPayload[np.uint8]):
110
+ """Represents the DigitalInputState payload."""
111
+
112
+ __value__: DigitalInputs = BitMask(enum=DigitalInputs)
113
+
114
+
115
+ class DigitalOutputSetPayload(AnonymousPayload[np.uint8]):
116
+ """Represents the DigitalOutputSet payload."""
117
+
118
+ __value__: DigitalOutputs = BitMask(enum=DigitalOutputs)
119
+
120
+
121
+ class DigitalOutputClearPayload(AnonymousPayload[np.uint8]):
122
+ """Represents the DigitalOutputClear payload."""
123
+
124
+ __value__: DigitalOutputs = BitMask(enum=DigitalOutputs)
125
+
126
+
127
+ class DigitalOutputTogglePayload(AnonymousPayload[np.uint8]):
128
+ """Represents the DigitalOutputToggle payload."""
129
+
130
+ __value__: DigitalOutputs = BitMask(enum=DigitalOutputs)
131
+
132
+
133
+ class DigitalOutputStatePayload(AnonymousPayload[np.uint8]):
134
+ """Represents the DigitalOutputState payload."""
135
+
136
+ __value__: DigitalOutputs = BitMask(enum=DigitalOutputs)
137
+
138
+
139
+ class AnalogDataPayload(StructPayload[np.uint16], length=3):
140
+ """Represents the AnalogData payload."""
141
+
142
+ analog_input0: np.uint16 = Field(IdentityConverter(np.uint16))
143
+ """The analog value sampled from ADC channel 0."""
144
+
145
+ analog_input1: np.uint16 = Field(IdentityConverter(np.uint16), offset=1)
146
+ """The analog value sampled from ADC channel 1."""
147
+
148
+ analog_input2: np.uint16 = Field(IdentityConverter(np.uint16), offset=2)
149
+ """The analog value sampled from ADC channel 2."""
150
+
151
+
152
+ class PulseTrainGP15Payload(StructPayload[np.uint32], length=3):
153
+ """Represents the PulseTrainGP15 payload."""
154
+
155
+ pulse_width: np.uint32 = Field(IdentityConverter(np.uint32), default=np.uint32(500000))
156
+ """Specifies the duration in microseconds that each pulse is high. A value of zero stops the pulse train."""
157
+
158
+ pulse_period: np.uint32 = Field(
159
+ IdentityConverter(np.uint32), offset=1, default=np.uint32(1000000)
160
+ )
161
+ """Specifies the interval in microseconds between the start of each pulse."""
162
+
163
+ pulse_count: np.uint32 = Field(IdentityConverter(np.uint32), offset=2, default=np.uint32(1))
164
+ """Specifies the number of pulses in the pulse train. A value of zero runs the pulse train until it is stopped."""
165
+
166
+
167
+ class PulseTrainGP16Payload(StructPayload[np.uint32], length=3):
168
+ """Represents the PulseTrainGP16 payload."""
169
+
170
+ pulse_width: np.uint32 = Field(IdentityConverter(np.uint32), default=np.uint32(500000))
171
+ """Specifies the duration in microseconds that each pulse is high. A value of zero stops the pulse train."""
172
+
173
+ pulse_period: np.uint32 = Field(
174
+ IdentityConverter(np.uint32), offset=1, default=np.uint32(1000000)
175
+ )
176
+ """Specifies the interval in microseconds between the start of each pulse."""
177
+
178
+ pulse_count: np.uint32 = Field(IdentityConverter(np.uint32), offset=2, default=np.uint32(1))
179
+ """Specifies the number of pulses in the pulse train. A value of zero runs the pulse train until it is stopped."""
180
+
181
+
182
+ class PulseTrainGP17Payload(StructPayload[np.uint32], length=3):
183
+ """Represents the PulseTrainGP17 payload."""
184
+
185
+ pulse_width: np.uint32 = Field(IdentityConverter(np.uint32), default=np.uint32(500000))
186
+ """Specifies the duration in microseconds that each pulse is high. A value of zero stops the pulse train."""
187
+
188
+ pulse_period: np.uint32 = Field(
189
+ IdentityConverter(np.uint32), offset=1, default=np.uint32(1000000)
190
+ )
191
+ """Specifies the interval in microseconds between the start of each pulse."""
192
+
193
+ pulse_count: np.uint32 = Field(IdentityConverter(np.uint32), offset=2, default=np.uint32(1))
194
+ """Specifies the number of pulses in the pulse train. A value of zero runs the pulse train until it is stopped."""
195
+
196
+
197
+ class PulseTrainGP18Payload(StructPayload[np.uint32], length=3):
198
+ """Represents the PulseTrainGP18 payload."""
199
+
200
+ pulse_width: np.uint32 = Field(IdentityConverter(np.uint32), default=np.uint32(500000))
201
+ """Specifies the duration in microseconds that each pulse is high. A value of zero stops the pulse train."""
202
+
203
+ pulse_period: np.uint32 = Field(
204
+ IdentityConverter(np.uint32), offset=1, default=np.uint32(1000000)
205
+ )
206
+ """Specifies the interval in microseconds between the start of each pulse."""
207
+
208
+ pulse_count: np.uint32 = Field(IdentityConverter(np.uint32), offset=2, default=np.uint32(1))
209
+ """Specifies the number of pulses in the pulse train. A value of zero runs the pulse train until it is stopped."""
210
+
211
+
212
+ class PulseTrainGP19Payload(StructPayload[np.uint32], length=3):
213
+ """Represents the PulseTrainGP19 payload."""
214
+
215
+ pulse_width: np.uint32 = Field(IdentityConverter(np.uint32), default=np.uint32(500000))
216
+ """Specifies the duration in microseconds that each pulse is high. A value of zero stops the pulse train."""
217
+
218
+ pulse_period: np.uint32 = Field(
219
+ IdentityConverter(np.uint32), offset=1, default=np.uint32(1000000)
220
+ )
221
+ """Specifies the interval in microseconds between the start of each pulse."""
222
+
223
+ pulse_count: np.uint32 = Field(IdentityConverter(np.uint32), offset=2, default=np.uint32(1))
224
+ """Specifies the number of pulses in the pulse train. A value of zero runs the pulse train until it is stopped."""
225
+
226
+
227
+ class PulseTrainGP20Payload(StructPayload[np.uint32], length=3):
228
+ """Represents the PulseTrainGP20 payload."""
229
+
230
+ pulse_width: np.uint32 = Field(IdentityConverter(np.uint32), default=np.uint32(500000))
231
+ """Specifies the duration in microseconds that each pulse is high. A value of zero stops the pulse train."""
232
+
233
+ pulse_period: np.uint32 = Field(
234
+ IdentityConverter(np.uint32), offset=1, default=np.uint32(1000000)
235
+ )
236
+ """Specifies the interval in microseconds between the start of each pulse."""
237
+
238
+ pulse_count: np.uint32 = Field(IdentityConverter(np.uint32), offset=2, default=np.uint32(1))
239
+ """Specifies the number of pulses in the pulse train. A value of zero runs the pulse train until it is stopped."""
240
+
241
+
242
+ class PulseTrainGP21Payload(StructPayload[np.uint32], length=3):
243
+ """Represents the PulseTrainGP21 payload."""
244
+
245
+ pulse_width: np.uint32 = Field(IdentityConverter(np.uint32), default=np.uint32(500000))
246
+ """Specifies the duration in microseconds that each pulse is high. A value of zero stops the pulse train."""
247
+
248
+ pulse_period: np.uint32 = Field(
249
+ IdentityConverter(np.uint32), offset=1, default=np.uint32(1000000)
250
+ )
251
+ """Specifies the interval in microseconds between the start of each pulse."""
252
+
253
+ pulse_count: np.uint32 = Field(IdentityConverter(np.uint32), offset=2, default=np.uint32(1))
254
+ """Specifies the number of pulses in the pulse train. A value of zero runs the pulse train until it is stopped."""
255
+
256
+
257
+ class PulseTrainGP22Payload(StructPayload[np.uint32], length=3):
258
+ """Represents the PulseTrainGP22 payload."""
259
+
260
+ pulse_width: np.uint32 = Field(IdentityConverter(np.uint32), default=np.uint32(500000))
261
+ """Specifies the duration in microseconds that each pulse is high. A value of zero stops the pulse train."""
262
+
263
+ pulse_period: np.uint32 = Field(
264
+ IdentityConverter(np.uint32), offset=1, default=np.uint32(1000000)
265
+ )
266
+ """Specifies the interval in microseconds between the start of each pulse."""
267
+
268
+ pulse_count: np.uint32 = Field(IdentityConverter(np.uint32), offset=2, default=np.uint32(1))
269
+ """Specifies the number of pulses in the pulse train. A value of zero runs the pulse train until it is stopped."""
270
+
271
+
272
+ class PulseEventEnablePayload(AnonymousPayload[np.uint8]):
273
+ """Represents the PulseEventEnable payload."""
274
+
275
+ __value__: DigitalOutputs = BitMask(
276
+ enum=DigitalOutputs,
277
+ default=DigitalOutputs.GP15 | DigitalOutputs.GP16 | DigitalOutputs.GP17 | DigitalOutputs.GP18 | DigitalOutputs.GP19 | DigitalOutputs.GP20 | DigitalOutputs.GP21 | DigitalOutputs.GP22,
278
+ )
279
+
280
+
281
+ class DigitalInputState(RegisterBase[DigitalInputs]):
282
+ """Reflects the state of the digital input lines."""
283
+
284
+ address: ClassVar[int] = 32
285
+ payload_type: ClassVar[PayloadType] = PayloadType.U8
286
+ payload_class = DigitalInputStatePayload
287
+
288
+
289
+ class DigitalOutputSet(RegisterBase[DigitalOutputs]):
290
+ """Sets the specified output lines and reports each pulse start. Setting a line stops its pulse train."""
291
+
292
+ address: ClassVar[int] = 33
293
+ payload_type: ClassVar[PayloadType] = PayloadType.U8
294
+ payload_class = DigitalOutputSetPayload
295
+
296
+
297
+ class DigitalOutputClear(RegisterBase[DigitalOutputs]):
298
+ """Clears the specified output lines. Clearing a line stops its pulse train."""
299
+
300
+ address: ClassVar[int] = 34
301
+ payload_type: ClassVar[PayloadType] = PayloadType.U8
302
+ payload_class = DigitalOutputClearPayload
303
+
304
+
305
+ class DigitalOutputToggle(RegisterBase[DigitalOutputs]):
306
+ """Toggles the specified output lines. Toggling a line stops its pulse train."""
307
+
308
+ address: ClassVar[int] = 35
309
+ payload_type: ClassVar[PayloadType] = PayloadType.U8
310
+ payload_class = DigitalOutputTogglePayload
311
+
312
+
313
+ class DigitalOutputState(RegisterBase[DigitalOutputs]):
314
+ """Writes the state of all output lines. Writing the state stops every pulse train."""
315
+
316
+ address: ClassVar[int] = 36
317
+ payload_type: ClassVar[PayloadType] = PayloadType.U8
318
+ payload_class = DigitalOutputStatePayload
319
+
320
+
321
+ class AnalogData(RegisterBase[AnalogDataPayload]):
322
+ """Reports the sampled analog signal on each of the ADC input channels. The ADC is capped at 12 bits of resolution."""
323
+
324
+ address: ClassVar[int] = 37
325
+ payload_type: ClassVar[PayloadType] = PayloadType.U16
326
+ payload_class = AnalogDataPayload
327
+
328
+
329
+ class PulseTrainGP15(RegisterBase[PulseTrainGP15Payload]):
330
+ """Starts a pulse train on digital output GP15, or stops it if the pulse width is zero."""
331
+
332
+ address: ClassVar[int] = 38
333
+ payload_type: ClassVar[PayloadType] = PayloadType.U32
334
+ payload_class = PulseTrainGP15Payload
335
+
336
+
337
+ class PulseTrainGP16(RegisterBase[PulseTrainGP16Payload]):
338
+ """Starts a pulse train on digital output GP16, or stops it if the pulse width is zero."""
339
+
340
+ address: ClassVar[int] = 39
341
+ payload_type: ClassVar[PayloadType] = PayloadType.U32
342
+ payload_class = PulseTrainGP16Payload
343
+
344
+
345
+ class PulseTrainGP17(RegisterBase[PulseTrainGP17Payload]):
346
+ """Starts a pulse train on digital output GP17, or stops it if the pulse width is zero."""
347
+
348
+ address: ClassVar[int] = 40
349
+ payload_type: ClassVar[PayloadType] = PayloadType.U32
350
+ payload_class = PulseTrainGP17Payload
351
+
352
+
353
+ class PulseTrainGP18(RegisterBase[PulseTrainGP18Payload]):
354
+ """Starts a pulse train on digital output GP18, or stops it if the pulse width is zero."""
355
+
356
+ address: ClassVar[int] = 41
357
+ payload_type: ClassVar[PayloadType] = PayloadType.U32
358
+ payload_class = PulseTrainGP18Payload
359
+
360
+
361
+ class PulseTrainGP19(RegisterBase[PulseTrainGP19Payload]):
362
+ """Starts a pulse train on digital output GP19, or stops it if the pulse width is zero."""
363
+
364
+ address: ClassVar[int] = 42
365
+ payload_type: ClassVar[PayloadType] = PayloadType.U32
366
+ payload_class = PulseTrainGP19Payload
367
+
368
+
369
+ class PulseTrainGP20(RegisterBase[PulseTrainGP20Payload]):
370
+ """Starts a pulse train on digital output GP20, or stops it if the pulse width is zero."""
371
+
372
+ address: ClassVar[int] = 43
373
+ payload_type: ClassVar[PayloadType] = PayloadType.U32
374
+ payload_class = PulseTrainGP20Payload
375
+
376
+
377
+ class PulseTrainGP21(RegisterBase[PulseTrainGP21Payload]):
378
+ """Starts a pulse train on digital output GP21, or stops it if the pulse width is zero."""
379
+
380
+ address: ClassVar[int] = 44
381
+ payload_type: ClassVar[PayloadType] = PayloadType.U32
382
+ payload_class = PulseTrainGP21Payload
383
+
384
+
385
+ class PulseTrainGP22(RegisterBase[PulseTrainGP22Payload]):
386
+ """Starts a pulse train on digital output GP22, or stops it if the pulse width is zero."""
387
+
388
+ address: ClassVar[int] = 45
389
+ payload_type: ClassVar[PayloadType] = PayloadType.U32
390
+ payload_class = PulseTrainGP22Payload
391
+
392
+
393
+ class PulseEventEnable(RegisterBase[DigitalOutputs]):
394
+ """Specifies the digital output lines whose pulse trains report the start of each pulse on DigitalOutputSet."""
395
+
396
+ address: ClassVar[int] = 46
397
+ payload_type: ClassVar[PayloadType] = PayloadType.U8
398
+ payload_class = PulseEventEnablePayload
399
+
400
+
401
+ REGISTER_MAP: dict[int, type[RegisterBase[Any]]] = {
402
+ **_CORE_REGISTER_MAP,
403
+ 32: DigitalInputState,
404
+ 33: DigitalOutputSet,
405
+ 34: DigitalOutputClear,
406
+ 35: DigitalOutputToggle,
407
+ 36: DigitalOutputState,
408
+ 37: AnalogData,
409
+ 38: PulseTrainGP15,
410
+ 39: PulseTrainGP16,
411
+ 40: PulseTrainGP17,
412
+ 41: PulseTrainGP18,
413
+ 42: PulseTrainGP19,
414
+ 43: PulseTrainGP20,
415
+ 44: PulseTrainGP21,
416
+ 45: PulseTrainGP22,
417
+ 46: PulseEventEnable,
418
+ }
@@ -0,0 +1,61 @@
1
+ Metadata-Version: 2.4
2
+ Name: harp-hobgoblin
3
+ Version: 0.2.0
4
+ Summary: Interface for data acquisition and control of Harp Hobgoblin devices.
5
+ Author-email: harp-tech <contact@harp-tech.org>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://harp-tech.org/device.hobgoblin
8
+ Project-URL: Repository, https://github.com/harp-tech/device.hobgoblin
9
+ Project-URL: Bug Tracker, https://github.com/harp-tech/device.hobgoblin/issues
10
+ Project-URL: Changelog, https://github.com/harp-tech/device.hobgoblin/releases
11
+ Keywords: harp,hobgoblin,data-acquisition,hardware,device-control
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Intended Audience :: Science/Research
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: Operating System :: Microsoft :: Windows
16
+ Classifier: Operating System :: POSIX :: Linux
17
+ Classifier: Operating System :: MacOS
18
+ Classifier: Programming Language :: Python :: 3
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Programming Language :: Python :: 3.13
22
+ Classifier: Topic :: Scientific/Engineering
23
+ Classifier: Topic :: System :: Hardware :: Hardware Drivers
24
+ Requires-Python: >=3.11
25
+ Description-Content-Type: text/markdown
26
+ License-File: LICENSE
27
+ Requires-Dist: harp-protocol>=0.5
28
+ Requires-Dist: harp-device>=0.5
29
+ Requires-Dist: numpy>=1.24
30
+ Dynamic: license-file
31
+
32
+ # harp-hobgoblin
33
+
34
+ The Python interface for the [Harp Hobgoblin](https://harp-tech.org/device.hobgoblin) device. It carries the register classes for the device, the payload and enumeration types those registers use, and a `REGISTER_MAP` pairing every address with its register.
35
+
36
+ ## Installation
37
+
38
+ ```text
39
+ pip install harp-hobgoblin
40
+ ```
41
+
42
+ ## Reading and writing registers
43
+
44
+ Register classes are passed to `read` and `write` on an open device transport, such as the serial transport in [Harp Python](https://harp-tech.org/python/).
45
+
46
+ ```python
47
+ from harp import serial
48
+ from harp.device import hobgoblin, client
49
+
50
+ SERIAL_PORT = "/dev/ttyUSB0" # or "COMx" in Windows, where "x" is the serial port number
51
+
52
+ with serial.open_device(client.Device, port=SERIAL_PORT) as device:
53
+ print("device:", hobgoblin.DEVICE_NAME, "WhoAmI:", hobgoblin.WHO_AM_I)
54
+ print("analog data:", device.read(hobgoblin.AnalogData).payload)
55
+ ```
56
+
57
+ `open_dataset` in `harp.data` takes this module as its second argument, and decodes recorded data through the same register classes.
58
+
59
+ ## Feedback and contributing
60
+
61
+ `harp-hobgoblin` is released as open source under the MIT license. Bug reports and contributions are welcome at [the GitHub repository](https://github.com/harp-tech/device.hobgoblin).