INA_TI
116 строк · 5.8 Кб
1# micropython
2# MIT license
3# Copyright (c) 2024 Roman Shevchik goctaprog@gmail.com
4"""представление аппаратного регистра устройства"""
5
6# from sensor_pack_2 import bus_service
7from sensor_pack_2.base_sensor import DeviceEx, get_error_str, check_value
8from sensor_pack_2.bitfield import BitFields
9
10# 24.04.2024 было-> address: int; стало-> address: [int, None]. Смотри def __init__(...
11
12
13class BaseRegistry:
14"""Представление аппаратного регистра. Базовый класс."""
15
16def _get_width(self) -> int:
17"""Возвращает разрядность регистра по информация из параметра типа BitFields в байтах!"""
18mx = max(map(lambda val: val.position.stop, self._fields))
19# print(f"DBG: _get_width: {mx}")
20return 1 + int((mx - 1)/8)
21
22def __init__(self, device: [DeviceEx, None], address: [int, None], fields: BitFields, byte_len: [int, None] = None):
23"""device - устройство, которому принадлежит регистр.
24address - адрес регистра в памяти устройства.
25fields - битовые поля регистра.
26byte_len - разрядность регистра в байтах!"""
27check_value(byte_len, range(1, 3), get_error_str('byte_len', byte_len, range(1, 3)))
28self._device = device
29self._address = address
30self._fields = fields
31# один или два байта!!! Если больше, придется изменить метод read!!!
32self._byte_len = byte_len if byte_len else self._get_width()
33# проверка битового диапазона поля
34# str_err = f"Неверный параметр битового поля!"
35_k = 8 * self._byte_len
36for field in fields:
37check_value(field.position.start, range(_k),
38get_error_str('field.position.start', field.position.start, range(_k)))
39check_value(field.position.stop - 1, range(_k),
40get_error_str('field.position.stop', field.position.stop, range(_k)))
41check_value(field.position.step, range(1, 2),
42get_error_str('field.position.step', field.position.step, range(1, 2))) # шаг только единица!
43#
44self._value = 0 # значение, считанное из регистра
45
46def _rw_enabled(self) -> bool:
47"""Возвращает Истина, когда возможна запись в регистр по шине"""
48return self._device is not None and self._address is not None
49
50def __len__(self) -> int:
51return len(self._fields)
52
53def __getitem__(self, key: str) -> int:
54"""Возвращает значение битового поля в виде числа или bool по его имени в виде строки!"""
55lnk = self._fields
56lnk.field_name = key
57# установлю значение, иначе правильной работы не будет!!!
58lnk.source = self.value
59# возврат
60return lnk.get_field_value(validate=False)
61
62def __setitem__(self, key: str, value: int) -> int:
63"""Устанавливает значение битового поля в виде числа или bool по его имени в виде строки!"""
64lnk = self._fields
65lnk.field_name = key
66# установлю значение, иначе правильной работы не будет!!!
67lnk.source = self.value
68# установка
69_tmp = lnk.set_field_value(value=value)
70self._value = _tmp
71return _tmp
72
73@property
74def value(self) -> int:
75"""Возвращает значение, считанное из регистра. Из этого значения будут извлекаться значения битовых полей."""
76return self._value
77
78@value.setter
79def value(self, new_val: int):
80"""Иногда требуется явно присвоить значение полю экземпляра класса. Для удобства использования."""
81self._value = new_val
82
83@property
84def byte_len(self) -> int:
85"""Возвращает разрядность регистра в байтах"""
86return self._byte_len
87
88
89class RegistryRO(BaseRegistry):
90"""Представление аппаратного регистра. Только для чтения"""
91
92def read(self) -> [int, None]:
93"""Чтение значения из регистра устройства и запись его в поле класса"""
94if not self._rw_enabled():
95return
96bl = self._byte_len
97by = self._device.read_reg(self._address, bl)
98fmt = "B" if 1 == bl else "H"
99self._value = self._device.unpack(fmt, by)[0]
100# print(f"DBG:read: 0x{self._value:x}; byte len: {bl}; address: {self._address}")
101return self._value
102
103def __int__(self) -> int:
104return self.read()
105
106
107class RegistryRW(RegistryRO):
108"""Представление аппаратного регистра. Чтение и запись."""
109
110def write(self, value: [int, None] = None):
111"""Запись значения в регистр устройства.
112Если value в None, то метод запишет в регистр значение поля self.value"""
113if self._rw_enabled():
114val = value if value else self.value
115self._device.write_reg(self._address, val, self._byte_len)
116# print(f"DBG:RegistryRW.write: 0x{val:x}")
117