import collections import time from micropython import const from adafruit_bus_device.i2c_device import I2CDevice _CONTROL0 = const(0) _IRQ_STATUS = const(2) _STATUS0 = const(3) _YEAR = const(4) _DST = const(0xa) _ID = const(0xd) class RxComplete: pass RX_COMPLETE = RxComplete() class CycleComplete: pass CYCLE_COMPLETE = CycleComplete() class _ROBits: def __init__(self, count, reg, shift): self.reg = reg self.shift = shift self.mask = (1<> self.shift) & self.mask class _RWBits(_ROBits): def __set__(self, obj, value): if value & ~self.mask: raise ValueError( f"Value 0x{value:02x} does not fit in mask 0x{self.mask:02x}" ) reg_value = self.__get__(obj) reg_value &= ~(self.mask << self.shift) reg_value |= value << self.shift buf = obj._buffer buf[1] = reg_value with obj._i2c_device as i2c: i2c.write(buf, end=2) def _ROBit(reg, shift): return _ROBits(1, reg, shift) def _RWBit(reg, shift): return _RWBits(1, reg, shift) def _bcd2bin(value): """Convert binary coded decimal to Binary :param value: the BCD value to convert to binary (required, no default) """ return value - 6 * (value >> 4) DSTInfo = collections.namedtuple('DSTInfo', ( 'month', 'day', 'hour', 'special')) class ES100: device_id = _ROBits(8, _ID, 0) cycle_start = _ROBit(_CONTROL0, 0) antenna_1_off = _ROBit(_CONTROL0, 1) antenna_2_off = _ROBit(_CONTROL0, 2) start_antenna_2 = _ROBit(_CONTROL0, 3) tracking_enable = _ROBit(_CONTROL0, 4) irq_status_raw = _ROBits(3, _IRQ_STATUS, 0) status0_raw = _ROBits(8, _STATUS0, 0) rx_ok = _ROBit(_STATUS0, 0) antenna = _ROBit(_STATUS0, 1) lsw = _ROBits(2, _STATUS0, 3) dst = _ROBits(2, _STATUS0, 5) tracking = _ROBit(_STATUS0, 7) @property def utcnow(self): buf = self._buffer buf[0] = _YEAR with self._i2c_device as i2c: i2c.write(buf, end=1) i2c.readinto(buf, end=6) return time.struct_time( _bcd2bin(buf[0]), _bcd2bin(buf[1]), _bcd2bin(buf[2]), _bcd2bin(buf[3]), _bcd2bin(buf[4]), _bcd2bin(buf[5]), -1, -1, -1) @property def dstinfo(self): buf = self._buffer buf[0] = _DST with self._i2c_device as i2c: i2c.write(buf, end=1) i2c.readinto(buf, end=3) return DSTInfo( _bcd2bin(buf[0]), _bcd2bin(buf[1]), buf[2] & 0xf, buf[2] >> 4) def __init__(self, bus, address=0x32): self._buffer = bytearray(6) self._i2c_device = I2CDevice(bus, address) def start_reception(self): with self._i2c_device as dev: dev.write(b'\00\01') @property def irq_status(self): i = self.irq_status_raw result = [] if i & 1: result.append(RX_COMPLETE) if i & 4: result.append(CYCLE_COMPLETE) return result