Source code for adafruit_register.i2c_bcd_datetime

# SPDX-FileCopyrightText: 2016 Scott Shawcroft for Adafruit Industries
#
# SPDX-License-Identifier: MIT
# pylint: disable=too-few-public-methods

"""
`adafruit_register.i2c_bcd_datetime`
====================================================

Binary Coded Decimal date and time register

* Author(s): Scott Shawcroft
"""

__version__ = "0.0.0+auto.0"
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_Register.git"

import time

try:
    from typing import Optional, Type
    from typing_extensions import Literal
    from circuitpython_typing.device_drivers import I2CDeviceDriver
except ImportError:
    pass


def _bcd2bin(value: int) -> int:
    """Convert binary coded decimal to Binary

    :param value: the BCD value to convert to binary (required, no default)
    """
    return value - 6 * (value >> 4)


def _bin2bcd(value: int) -> int:
    """Convert a binary value to binary coded decimal.

    :param value: the binary value to convert to BCD. (required, no default)
    """
    return value + 6 * (value // 10)


[docs] class BCDDateTimeRegister: """ Date and time register using binary coded decimal structure. The byte order of the register must* be: second, minute, hour, weekday, day (1-31), month, year (in years after 2000). * Setting weekday_first=False will flip the weekday/day order so that day comes first. Values are `time.struct_time` :param int register_address: The register address to start the read :param bool weekday_first: True if weekday is in a lower register than the day of the month (1-31) :param int weekday_start: 0 or 1 depending on the RTC's representation of the first day of the week """ def __init__( self, register_address: int, weekday_first: bool = True, weekday_start: Literal[0, 1] = 1, ) -> None: self.buffer = bytearray(8) self.buffer[0] = register_address if weekday_first: self.weekday_offset = 0 else: self.weekday_offset = 1 self.weekday_start = weekday_start # Masking value list n/a sec min hr day wkday mon year self.mask_datetime = b"\xFF\x7F\x7F\x3F\x3F\x07\x1F\xFF" def __get__( self, obj: Optional[I2CDeviceDriver], objtype: Optional[Type[I2CDeviceDriver]] = None, ) -> time.struct_time: # Read and return the date and time. with obj.i2c_device as i2c: i2c.write_then_readinto(self.buffer, self.buffer, out_end=1, in_start=1) return time.struct_time( ( _bcd2bin(self.buffer[7] & self.mask_datetime[7]) + 2000, _bcd2bin(self.buffer[6] & self.mask_datetime[6]), _bcd2bin(self.buffer[5 - self.weekday_offset] & self.mask_datetime[4]), _bcd2bin(self.buffer[3] & self.mask_datetime[3]), _bcd2bin(self.buffer[2] & self.mask_datetime[2]), _bcd2bin(self.buffer[1] & self.mask_datetime[1]), _bcd2bin( (self.buffer[4 + self.weekday_offset] & self.mask_datetime[5]) - self.weekday_start ), -1, -1, ) ) def __set__(self, obj: I2CDeviceDriver, value: time.struct_time) -> None: self.buffer[1] = _bin2bcd(value.tm_sec) & 0x7F # format conversions self.buffer[2] = _bin2bcd(value.tm_min) self.buffer[3] = _bin2bcd(value.tm_hour) self.buffer[4 + self.weekday_offset] = _bin2bcd( value.tm_wday + self.weekday_start ) self.buffer[5 - self.weekday_offset] = _bin2bcd(value.tm_mday) self.buffer[6] = _bin2bcd(value.tm_mon) self.buffer[7] = _bin2bcd(value.tm_year - 2000) with obj.i2c_device: obj.i2c_device.write(self.buffer)