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.

Files changed (46) hide show
  1. ekfsm/__init__.py +3 -14
  2. ekfsm/boards/oem/ekf/shu-shuttle.yaml +43 -0
  3. ekfsm/boards/oem/ekf/sq3-quartet.yaml +51 -37
  4. ekfsm/boards/oem/ekf/z1010.yaml +102 -0
  5. ekfsm/boards/oem/hitron/hdrc-300s.yaml +1 -1
  6. ekfsm/cli.py +32 -9
  7. ekfsm/config.py +14 -6
  8. ekfsm/core/__init__.py +13 -3
  9. ekfsm/core/components.py +7 -8
  10. ekfsm/core/connections.py +19 -0
  11. ekfsm/core/slots.py +6 -8
  12. ekfsm/core/sysfs.py +215 -25
  13. ekfsm/core/utils.py +128 -64
  14. ekfsm/devices/__init__.py +27 -7
  15. ekfsm/devices/buttons.py +251 -0
  16. ekfsm/devices/colorLed.py +110 -0
  17. ekfsm/devices/coretemp.py +35 -13
  18. ekfsm/devices/eeprom.py +73 -45
  19. ekfsm/devices/ekf_ccu_uc.py +76 -54
  20. ekfsm/devices/ekf_sur_led.py +6 -2
  21. ekfsm/devices/generic.py +200 -59
  22. ekfsm/devices/gpio.py +37 -27
  23. ekfsm/devices/iio.py +15 -31
  24. ekfsm/devices/iio_thermal_humidity.py +20 -13
  25. ekfsm/devices/imu.py +8 -4
  26. ekfsm/devices/io4edge.py +185 -0
  27. ekfsm/devices/ledArray.py +54 -0
  28. ekfsm/devices/mux.py +46 -8
  29. ekfsm/devices/pixelDisplay.py +141 -0
  30. ekfsm/devices/pmbus.py +74 -101
  31. ekfsm/devices/smbios.py +28 -8
  32. ekfsm/devices/smbus.py +1 -1
  33. ekfsm/devices/thermal_humidity.py +80 -0
  34. ekfsm/devices/toggles.py +90 -0
  35. ekfsm/devices/utils.py +52 -8
  36. ekfsm/devices/watchdog.py +79 -0
  37. ekfsm/exceptions.py +28 -7
  38. ekfsm/lock.py +48 -21
  39. ekfsm/simctrl.py +37 -83
  40. ekfsm/system.py +89 -73
  41. ekfsm/utils.py +44 -0
  42. {ekfsm-0.13.0a183.dist-info → ekfsm-1.5.0.dist-info}/METADATA +12 -6
  43. ekfsm-1.5.0.dist-info/RECORD +57 -0
  44. ekfsm-0.13.0a183.dist-info/RECORD +0 -45
  45. {ekfsm-0.13.0a183.dist-info → ekfsm-1.5.0.dist-info}/WHEEL +0 -0
  46. {ekfsm-0.13.0a183.dist-info → ekfsm-1.5.0.dist-info}/entry_points.txt +0 -0
@@ -1,12 +1,15 @@
1
- from .generic import Device
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
- The temperature is read once per second.
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"cannot read {what}")
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
- Tuple[float, float, int]
132
- The desired speed, the actual speed, and the diagnostic value.
133
- The diagnostic value is a bitfield with the following meaning:
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
- Tuple[ImuSample | None, bool]
188
- The IMU sample (or None) and a flag indicating if more samples are available in the FIFO.
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
- Tuple[str, str]
261
- The firmware title and version.
265
+ title: str
266
+ The firmware title.
267
+ version: str
268
+ The firmware version.
262
269
  """
263
- title = bytes(
264
- self._smbus.read_block_data(
265
- self._i2c_addr, CcuCommands.IDENTIFY_FIRMWARE_TITLE.value
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
- self._smbus.write_block_data(
315
- self._i2c_addr, CcuCommands.LOAD_FIRMWARE_CHUNK.value, list(data)
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
- self._smbus.write_block_data(
439
- self._i2c_addr, CcuCommands.LOAD_PARAMETERSET.value, list(data)
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
  """
@@ -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 (