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.
- harp_hobgoblin-0.2.0/.gitignore +4 -0
- harp_hobgoblin-0.2.0/.python-version +1 -0
- harp_hobgoblin-0.2.0/LICENSE +19 -0
- harp_hobgoblin-0.2.0/PKG-INFO +61 -0
- harp_hobgoblin-0.2.0/README.md +30 -0
- harp_hobgoblin-0.2.0/pyproject.toml +62 -0
- harp_hobgoblin-0.2.0/setup.cfg +4 -0
- harp_hobgoblin-0.2.0/src/harp/device/hobgoblin/__init__.py +418 -0
- harp_hobgoblin-0.2.0/src/harp/device/hobgoblin/py.typed +0 -0
- harp_hobgoblin-0.2.0/src/harp_hobgoblin.egg-info/PKG-INFO +61 -0
- harp_hobgoblin-0.2.0/src/harp_hobgoblin.egg-info/SOURCES.txt +15 -0
- harp_hobgoblin-0.2.0/src/harp_hobgoblin.egg-info/dependency_links.txt +1 -0
- harp_hobgoblin-0.2.0/src/harp_hobgoblin.egg-info/requires.txt +3 -0
- harp_hobgoblin-0.2.0/src/harp_hobgoblin.egg-info/scm_file_list.json +13 -0
- harp_hobgoblin-0.2.0/src/harp_hobgoblin.egg-info/top_level.txt +1 -0
- harp_hobgoblin-0.2.0/tests/test_interface.py +14 -0
- harp_hobgoblin-0.2.0/uv.lock +483 -0
|
@@ -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,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
|
+
}
|
|
File without changes
|
|
@@ -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).
|