INA_TI

Форк
0
/
regmod.py 
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
7
from sensor_pack_2.base_sensor import DeviceEx, get_error_str, check_value
8
from sensor_pack_2.bitfield import BitFields
9

10
# 24.04.2024 было-> address: int; стало-> address: [int, None]. Смотри def __init__(...
11

12

13
class BaseRegistry:
14
    """Представление аппаратного регистра. Базовый класс."""
15

16
    def _get_width(self) -> int:
17
        """Возвращает разрядность регистра по информация из параметра типа BitFields в байтах!"""
18
        mx = max(map(lambda val: val.position.stop, self._fields))
19
        # print(f"DBG: _get_width: {mx}")
20
        return 1 + int((mx - 1)/8)
21

22
    def __init__(self, device: [DeviceEx, None], address: [int, None], fields: BitFields, byte_len: [int, None] = None):
23
        """device - устройство, которому принадлежит регистр.
24
        address - адрес регистра в памяти устройства.
25
        fields - битовые поля регистра.
26
        byte_len - разрядность регистра в байтах!"""
27
        check_value(byte_len, range(1, 3), get_error_str('byte_len', byte_len, range(1, 3)))
28
        self._device = device
29
        self._address = address
30
        self._fields = fields
31
        # один или два байта!!! Если больше, придется изменить метод read!!!
32
        self._byte_len = byte_len if byte_len else self._get_width()
33
        # проверка битового диапазона поля
34
        # str_err = f"Неверный параметр битового поля!"
35
        _k = 8 * self._byte_len
36
        for field in fields:
37
            check_value(field.position.start, range(_k),
38
                        get_error_str('field.position.start', field.position.start, range(_k)))
39
            check_value(field.position.stop - 1, range(_k),
40
                        get_error_str('field.position.stop', field.position.stop, range(_k)))
41
            check_value(field.position.step, range(1, 2),
42
                        get_error_str('field.position.step', field.position.step, range(1, 2)))  # шаг только единица!
43
        #
44
        self._value = 0  # значение, считанное из регистра
45

46
    def _rw_enabled(self) -> bool:
47
        """Возвращает Истина, когда возможна запись в регистр по шине"""
48
        return self._device is not None and self._address is not None
49

50
    def __len__(self) -> int:
51
        return len(self._fields)
52

53
    def __getitem__(self, key: str) -> int:
54
        """Возвращает значение битового поля в виде числа или bool по его имени в виде строки!"""
55
        lnk = self._fields
56
        lnk.field_name = key
57
        # установлю значение, иначе правильной работы не будет!!!
58
        lnk.source = self.value
59
        # возврат
60
        return lnk.get_field_value(validate=False)
61

62
    def __setitem__(self, key: str, value: int) -> int:
63
        """Устанавливает значение битового поля в виде числа или bool по его имени в виде строки!"""
64
        lnk = self._fields
65
        lnk.field_name = key
66
        # установлю значение, иначе правильной работы не будет!!!
67
        lnk.source = self.value
68
        # установка
69
        _tmp = lnk.set_field_value(value=value)
70
        self._value = _tmp
71
        return _tmp
72

73
    @property
74
    def value(self) -> int:
75
        """Возвращает значение, считанное из регистра. Из этого значения будут извлекаться значения битовых полей."""
76
        return self._value
77

78
    @value.setter
79
    def value(self, new_val: int):
80
        """Иногда требуется явно присвоить значение полю экземпляра класса. Для удобства использования."""
81
        self._value = new_val
82

83
    @property
84
    def byte_len(self) -> int:
85
        """Возвращает разрядность регистра в байтах"""
86
        return self._byte_len
87

88

89
class RegistryRO(BaseRegistry):
90
    """Представление аппаратного регистра. Только для чтения"""
91

92
    def read(self) -> [int, None]:
93
        """Чтение значения из регистра устройства и запись его в поле класса"""
94
        if not self._rw_enabled():
95
            return
96
        bl = self._byte_len
97
        by = self._device.read_reg(self._address, bl)
98
        fmt = "B" if 1 == bl else "H"
99
        self._value = self._device.unpack(fmt, by)[0]
100
        # print(f"DBG:read: 0x{self._value:x}; byte len: {bl}; address: {self._address}")
101
        return self._value
102

103
    def __int__(self) -> int:
104
        return self.read()
105

106

107
class RegistryRW(RegistryRO):
108
    """Представление аппаратного регистра. Чтение и запись."""
109

110
    def write(self, value: [int, None] = None):
111
        """Запись значения в регистр устройства.
112
        Если value в None, то метод запишет в регистр значение поля self.value"""
113
        if self._rw_enabled():
114
            val = value if value else self.value
115
            self._device.write_reg(self._address, val, self._byte_len)
116
            # print(f"DBG:RegistryRW.write: 0x{val:x}")
117

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.