ekfsm 0.13.0a183__py3-none-any.whl → 1.5.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.
Potentially problematic release.
This version of ekfsm might be problematic. Click here for more details.
- ekfsm/__init__.py +3 -14
- ekfsm/boards/oem/ekf/shu-shuttle.yaml +43 -0
- ekfsm/boards/oem/ekf/sq3-quartet.yaml +51 -37
- ekfsm/boards/oem/ekf/z1010.yaml +102 -0
- ekfsm/boards/oem/hitron/hdrc-300s.yaml +1 -1
- ekfsm/cli.py +32 -9
- ekfsm/config.py +14 -6
- ekfsm/core/__init__.py +13 -3
- ekfsm/core/components.py +7 -8
- ekfsm/core/connections.py +19 -0
- ekfsm/core/slots.py +6 -8
- ekfsm/core/sysfs.py +215 -25
- ekfsm/core/utils.py +128 -64
- ekfsm/devices/__init__.py +27 -7
- ekfsm/devices/buttons.py +251 -0
- ekfsm/devices/colorLed.py +110 -0
- ekfsm/devices/coretemp.py +35 -13
- ekfsm/devices/eeprom.py +73 -45
- ekfsm/devices/ekf_ccu_uc.py +76 -54
- ekfsm/devices/ekf_sur_led.py +6 -2
- ekfsm/devices/generic.py +200 -59
- ekfsm/devices/gpio.py +37 -27
- ekfsm/devices/iio.py +15 -31
- ekfsm/devices/iio_thermal_humidity.py +20 -13
- ekfsm/devices/imu.py +8 -4
- ekfsm/devices/io4edge.py +185 -0
- ekfsm/devices/ledArray.py +54 -0
- ekfsm/devices/mux.py +46 -8
- ekfsm/devices/pixelDisplay.py +141 -0
- ekfsm/devices/pmbus.py +74 -101
- ekfsm/devices/smbios.py +28 -8
- ekfsm/devices/smbus.py +1 -1
- ekfsm/devices/thermal_humidity.py +80 -0
- ekfsm/devices/toggles.py +90 -0
- ekfsm/devices/utils.py +52 -8
- ekfsm/devices/watchdog.py +79 -0
- ekfsm/exceptions.py +28 -7
- ekfsm/lock.py +48 -21
- ekfsm/simctrl.py +37 -83
- ekfsm/system.py +89 -73
- ekfsm/utils.py +44 -0
- {ekfsm-0.13.0a183.dist-info → ekfsm-1.5.0.dist-info}/METADATA +12 -6
- ekfsm-1.5.0.dist-info/RECORD +57 -0
- ekfsm-0.13.0a183.dist-info/RECORD +0 -45
- {ekfsm-0.13.0a183.dist-info → ekfsm-1.5.0.dist-info}/WHEEL +0 -0
- {ekfsm-0.13.0a183.dist-info → ekfsm-1.5.0.dist-info}/entry_points.txt +0 -0
ekfsm/devices/ekf_ccu_uc.py
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
|
-
|
|
2
|
-
from smbus2 import SMBus
|
|
1
|
+
import struct
|
|
3
2
|
from enum import Enum
|
|
4
|
-
from typing import Tuple
|
|
3
|
+
from typing import Any, Tuple
|
|
4
|
+
|
|
5
|
+
from smbus2 import SMBus
|
|
6
|
+
|
|
5
7
|
from ekfsm.core.components import SysTree
|
|
8
|
+
|
|
6
9
|
from ..exceptions import AcquisitionError
|
|
7
10
|
from ..lock import Locker
|
|
11
|
+
from .generic import Device
|
|
8
12
|
from .imu import ImuSample
|
|
9
|
-
import struct
|
|
10
13
|
|
|
11
14
|
|
|
12
15
|
class CcuCommands(Enum):
|
|
@@ -37,10 +40,13 @@ class EKFCcuUc(Device):
|
|
|
37
40
|
self,
|
|
38
41
|
name: str,
|
|
39
42
|
parent: SysTree | None,
|
|
43
|
+
children: list["Device"] | None = None,
|
|
44
|
+
abort: bool = False,
|
|
45
|
+
debug: Any = None, # XXX: What is this?
|
|
40
46
|
*args,
|
|
41
47
|
**kwargs,
|
|
42
48
|
):
|
|
43
|
-
super().__init__(name, parent, None, *args, **kwargs)
|
|
49
|
+
super().__init__(name, parent, None, abort, *args, **kwargs)
|
|
44
50
|
self._i2c_addr = self.get_i2c_chip_addr()
|
|
45
51
|
self._i2c_bus = self.get_i2c_bus_number()
|
|
46
52
|
self._smbus = SMBus(self._i2c_bus)
|
|
@@ -54,7 +60,10 @@ class EKFCcuUc(Device):
|
|
|
54
60
|
def temperature(self) -> float:
|
|
55
61
|
"""
|
|
56
62
|
Get the temperature from the CCU thermal/humidity sensor.
|
|
57
|
-
|
|
63
|
+
|
|
64
|
+
Note
|
|
65
|
+
----
|
|
66
|
+
The CCU reads the temperature once per second.
|
|
58
67
|
|
|
59
68
|
Returns
|
|
60
69
|
-------
|
|
@@ -66,10 +75,7 @@ class EKFCcuUc(Device):
|
|
|
66
75
|
AcquisitionError
|
|
67
76
|
If the temperature cannot be read, for example, because the sensor is not working.
|
|
68
77
|
"""
|
|
69
|
-
return (
|
|
70
|
-
self._get_signed_word_data(CcuCommands.CCU_TEMPERATURE.value, "temperature")
|
|
71
|
-
/ 10.0
|
|
72
|
-
)
|
|
78
|
+
return self._get_signed_word_data(CcuCommands.CCU_TEMPERATURE.value, "temperature") / 10.0
|
|
73
79
|
|
|
74
80
|
def humidity(self) -> float:
|
|
75
81
|
"""
|
|
@@ -86,10 +92,7 @@ class EKFCcuUc(Device):
|
|
|
86
92
|
AcquisitionError
|
|
87
93
|
If the humidity cannot be read, for example, because the sensor is not working.
|
|
88
94
|
"""
|
|
89
|
-
return (
|
|
90
|
-
self._get_signed_word_data(CcuCommands.CCU_HUMIDITY.value, "humidity")
|
|
91
|
-
/ 10.0
|
|
92
|
-
)
|
|
95
|
+
return self._get_signed_word_data(CcuCommands.CCU_HUMIDITY.value, "humidity") / 10.0
|
|
93
96
|
|
|
94
97
|
def vin_voltage(self) -> float:
|
|
95
98
|
"""
|
|
@@ -106,15 +109,14 @@ class EKFCcuUc(Device):
|
|
|
106
109
|
AcquisitionError
|
|
107
110
|
If the voltage cannot be read, for example, because the ADC is not working.
|
|
108
111
|
"""
|
|
109
|
-
return (
|
|
110
|
-
self._get_signed_word_data(CcuCommands.VIN_VOLTAGE.value, "VIN voltage")
|
|
111
|
-
/ 10.0
|
|
112
|
-
)
|
|
112
|
+
return self._get_signed_word_data(CcuCommands.VIN_VOLTAGE.value, "VIN voltage") / 10.0
|
|
113
113
|
|
|
114
114
|
def _get_signed_word_data(self, cmd: int, what: str) -> int:
|
|
115
115
|
v = self._smbus.read_word_data(self._i2c_addr, cmd)
|
|
116
|
+
|
|
116
117
|
if v == 0x8000:
|
|
117
|
-
raise AcquisitionError(f"
|
|
118
|
+
raise AcquisitionError(f"Cannot read {what}")
|
|
119
|
+
|
|
118
120
|
return struct.unpack("<h", struct.pack("<H", v))[0]
|
|
119
121
|
|
|
120
122
|
def fan_status(self, fan: int) -> Tuple[float, float, int]:
|
|
@@ -128,9 +130,16 @@ class EKFCcuUc(Device):
|
|
|
128
130
|
|
|
129
131
|
Returns
|
|
130
132
|
-------
|
|
131
|
-
|
|
132
|
-
The desired speed
|
|
133
|
-
|
|
133
|
+
desired: float
|
|
134
|
+
The desired speed.
|
|
135
|
+
actual: float
|
|
136
|
+
The actual speed.
|
|
137
|
+
diag: int
|
|
138
|
+
The diagnostic value.
|
|
139
|
+
|
|
140
|
+
Note
|
|
141
|
+
----
|
|
142
|
+
The diagnostic value is a bitfield with the following meaning:
|
|
134
143
|
|
|
135
144
|
- bit 0: 0 = fan status is invalid, 1 = fan status is valid
|
|
136
145
|
- bit 1: 0 = no error detected, 1 = fan is stuck
|
|
@@ -161,9 +170,7 @@ class EKFCcuUc(Device):
|
|
|
161
170
|
if fan == -1:
|
|
162
171
|
fan = 0xFF
|
|
163
172
|
data = struct.pack("<Bh", fan, int(temp * 10))
|
|
164
|
-
self._smbus.write_block_data(
|
|
165
|
-
self._i2c_addr, CcuCommands.PUSH_TEMPERATURE.value, list(data)
|
|
166
|
-
)
|
|
173
|
+
self._smbus.write_block_data(self._i2c_addr, CcuCommands.PUSH_TEMPERATURE.value, list(data))
|
|
167
174
|
|
|
168
175
|
def imu_sample(self) -> Tuple[ImuSample | None, bool]:
|
|
169
176
|
"""
|
|
@@ -184,19 +191,17 @@ class EKFCcuUc(Device):
|
|
|
184
191
|
|
|
185
192
|
Returns
|
|
186
193
|
-------
|
|
187
|
-
|
|
188
|
-
The IMU sample
|
|
194
|
+
imu_data: ImuSample | None
|
|
195
|
+
The IMU sample, or None if no sample is available.
|
|
196
|
+
more_samples: bool
|
|
197
|
+
True if more samples are available in the FIFO, False otherwise.
|
|
189
198
|
"""
|
|
190
199
|
more_samples = False
|
|
191
|
-
_data = self._smbus.read_block_data(
|
|
192
|
-
self._i2c_addr, CcuCommands.IMU_SAMPLES.value
|
|
193
|
-
)
|
|
200
|
+
_data = self._smbus.read_block_data(self._i2c_addr, CcuCommands.IMU_SAMPLES.value)
|
|
194
201
|
data = bytes(_data)
|
|
195
202
|
if len(data) < 14:
|
|
196
203
|
return None, False # No data available
|
|
197
|
-
diag, fsr, acc_x, acc_y, acc_z, gyro_x, gyro_y, gyro_z = struct.unpack(
|
|
198
|
-
"<BBhhhhhh", data
|
|
199
|
-
)
|
|
204
|
+
diag, fsr, acc_x, acc_y, acc_z, gyro_x, gyro_y, gyro_z = struct.unpack("<BBhhhhhh", data)
|
|
200
205
|
imu_data = ImuSample(
|
|
201
206
|
[
|
|
202
207
|
self._scale_imu_accel(acc_x, fsr),
|
|
@@ -257,18 +262,16 @@ class EKFCcuUc(Device):
|
|
|
257
262
|
|
|
258
263
|
Returns
|
|
259
264
|
-------
|
|
260
|
-
|
|
261
|
-
The firmware title
|
|
265
|
+
title: str
|
|
266
|
+
The firmware title.
|
|
267
|
+
version: str
|
|
268
|
+
The firmware version.
|
|
262
269
|
"""
|
|
263
|
-
title = bytes(
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
)
|
|
267
|
-
).decode("utf-8")
|
|
270
|
+
title = bytes(self._smbus.read_block_data(self._i2c_addr, CcuCommands.IDENTIFY_FIRMWARE_TITLE.value)).decode(
|
|
271
|
+
"utf-8"
|
|
272
|
+
)
|
|
268
273
|
version = bytes(
|
|
269
|
-
self._smbus.read_block_data(
|
|
270
|
-
self._i2c_addr, CcuCommands.IDENTIFY_FIRMWARE_VERSION.value
|
|
271
|
-
)
|
|
274
|
+
self._smbus.read_block_data(self._i2c_addr, CcuCommands.IDENTIFY_FIRMWARE_VERSION.value)
|
|
272
275
|
).decode("utf-8")
|
|
273
276
|
return title, version
|
|
274
277
|
|
|
@@ -293,27 +296,37 @@ class EKFCcuUc(Device):
|
|
|
293
296
|
progress_callback
|
|
294
297
|
A callback function that is called with the current progress in bytes.
|
|
295
298
|
|
|
299
|
+
Example
|
|
300
|
+
-------
|
|
301
|
+
>>> from ekfsm.devices import EkfCcuUc
|
|
302
|
+
>>> ccu = EkfCcuUc("ccu")
|
|
303
|
+
>>> firmware = open("fw-ccu-1.0.0.bin", "rb").read()
|
|
304
|
+
>>> # Load firmware with progress callback
|
|
305
|
+
>>> ccu.load_firmware(firmware, progress_callback=lambda x: print(f"Progress: {x} bytes"))
|
|
296
306
|
"""
|
|
297
307
|
with Locker(self.name + "-load_firmware").lock():
|
|
298
308
|
offset = 0
|
|
299
309
|
max_chunk_len = 28
|
|
310
|
+
|
|
300
311
|
while len(firmware) > 0:
|
|
301
312
|
chunk, firmware = firmware[:max_chunk_len], firmware[max_chunk_len:]
|
|
302
313
|
self._load_firmware_chunk(offset, len(firmware) == 0, chunk)
|
|
303
314
|
offset += len(chunk)
|
|
315
|
+
|
|
304
316
|
if len(firmware) != 0:
|
|
305
317
|
self._nop()
|
|
318
|
+
|
|
306
319
|
if progress_callback is not None:
|
|
307
320
|
progress_callback(offset)
|
|
308
321
|
|
|
309
322
|
def _load_firmware_chunk(self, offset: int, is_last: bool, data: bytes) -> None:
|
|
310
323
|
if is_last:
|
|
311
324
|
offset |= 0x80000000
|
|
325
|
+
|
|
312
326
|
hdr = struct.pack("<I", offset)
|
|
313
327
|
data = hdr + data
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
)
|
|
328
|
+
|
|
329
|
+
self._smbus.write_block_data(self._i2c_addr, CcuCommands.LOAD_FIRMWARE_CHUNK.value, list(data))
|
|
317
330
|
|
|
318
331
|
def get_parameterset(self) -> str:
|
|
319
332
|
"""
|
|
@@ -371,6 +384,7 @@ class EKFCcuUc(Device):
|
|
|
371
384
|
with Locker(self.name + "-parameterset").lock():
|
|
372
385
|
json = b""
|
|
373
386
|
begin = True
|
|
387
|
+
|
|
374
388
|
while True:
|
|
375
389
|
chunk = self._get_parameterset_chunk(begin)
|
|
376
390
|
if len(chunk) < 32:
|
|
@@ -380,16 +394,13 @@ class EKFCcuUc(Device):
|
|
|
380
394
|
chunk = chunk[:-1]
|
|
381
395
|
json += chunk
|
|
382
396
|
begin = False
|
|
397
|
+
|
|
383
398
|
return json.decode("utf-8")
|
|
384
399
|
|
|
385
400
|
def _get_parameterset_chunk(self, begin: bool) -> bytes:
|
|
386
401
|
data = self._smbus.read_block_data(
|
|
387
402
|
self._i2c_addr,
|
|
388
|
-
(
|
|
389
|
-
CcuCommands.GET_PARAMETERSET_BEGIN.value
|
|
390
|
-
if begin
|
|
391
|
-
else CcuCommands.GET_PARAMETERSET_FOLLOW.value
|
|
392
|
-
),
|
|
403
|
+
(CcuCommands.GET_PARAMETERSET_BEGIN.value if begin else CcuCommands.GET_PARAMETERSET_FOLLOW.value),
|
|
393
404
|
)
|
|
394
405
|
return bytes(data)
|
|
395
406
|
|
|
@@ -412,6 +423,8 @@ class EKFCcuUc(Device):
|
|
|
412
423
|
This would load a parameterset with just one parameter, the default fan speed. All other parameters will
|
|
413
424
|
be set to their default values.
|
|
414
425
|
|
|
426
|
+
Important
|
|
427
|
+
---------
|
|
415
428
|
In order to apply the parameterset, the CCU must be restarted.
|
|
416
429
|
|
|
417
430
|
Parameters
|
|
@@ -419,11 +432,20 @@ class EKFCcuUc(Device):
|
|
|
419
432
|
_cfg
|
|
420
433
|
The parameterset in JSON format.
|
|
421
434
|
|
|
435
|
+
Example
|
|
436
|
+
-------
|
|
437
|
+
>>> from ekfsm.devices import EkfCcuUc
|
|
438
|
+
>>> ccu = EkfCcuUc("ccu")
|
|
439
|
+
>>> # Load parameterset
|
|
440
|
+
>>> ccu.load_parameterset('{"version": "1.0.0", "parameters": {"fan-defrpm": "6000"}}')
|
|
441
|
+
>>> # Restart CCU to apply parameterset
|
|
442
|
+
>>> ccu.restart()
|
|
422
443
|
"""
|
|
423
444
|
with Locker(self.name + "-parameterset").lock():
|
|
424
445
|
cfg = _cfg.encode("utf-8")
|
|
425
446
|
offset = 0
|
|
426
447
|
max_chunk_len = 28
|
|
448
|
+
|
|
427
449
|
while len(cfg) > 0:
|
|
428
450
|
chunk, cfg = cfg[:max_chunk_len], cfg[max_chunk_len:]
|
|
429
451
|
self._load_parameterset_chunk(offset, len(cfg) == 0, chunk)
|
|
@@ -433,11 +455,11 @@ class EKFCcuUc(Device):
|
|
|
433
455
|
def _load_parameterset_chunk(self, offset: int, is_last: bool, data: bytes) -> None:
|
|
434
456
|
if is_last:
|
|
435
457
|
offset |= 0x80000000
|
|
458
|
+
|
|
436
459
|
hdr = struct.pack("<I", offset)
|
|
437
460
|
data = hdr + data
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
)
|
|
461
|
+
|
|
462
|
+
self._smbus.write_block_data(self._i2c_addr, CcuCommands.LOAD_PARAMETERSET.value, list(data))
|
|
441
463
|
|
|
442
464
|
def restart(self) -> None:
|
|
443
465
|
"""
|
ekfsm/devices/ekf_sur_led.py
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
from .gpio import GPIOExpander
|
|
2
1
|
from ekfsm.core.components import SysTree
|
|
2
|
+
from ekfsm.devices.generic import Device
|
|
3
|
+
|
|
4
|
+
from .gpio import GPIOExpander
|
|
3
5
|
|
|
4
6
|
|
|
5
7
|
class EKFSurLed(GPIOExpander):
|
|
@@ -11,10 +13,12 @@ class EKFSurLed(GPIOExpander):
|
|
|
11
13
|
self,
|
|
12
14
|
name: str,
|
|
13
15
|
parent: SysTree | None,
|
|
16
|
+
children: list["Device"] | None = None,
|
|
17
|
+
abort: bool = False,
|
|
14
18
|
*args,
|
|
15
19
|
**kwargs,
|
|
16
20
|
):
|
|
17
|
-
super().__init__(name, parent, None, *args, **kwargs)
|
|
21
|
+
super().__init__(name, parent, None, abort, *args, **kwargs)
|
|
18
22
|
|
|
19
23
|
def __str__(self) -> str:
|
|
20
24
|
return (
|