Пример #1
0
class DS1307:
    """Interface to the DS1307 RTC."""

    disable_oscillator = i2c_bit.RWBit(0x0, 7)
    """True if the oscillator is disabled."""

    datetime_register = i2c_bcd_datetime.BCDDateTimeRegister(0x00)
    """Current date and time."""
    def __init__(self, i2c_bus):
        self.i2c_device = I2CDevice(i2c_bus, 0x68)

        # Try and verify this is the RTC we expect by checking the rate select
        # control bits which are 1 on reset and shouldn't ever be changed.
        buf = bytearray(2)
        buf[0] = 0x07
        with self.i2c_device as i2c:
            i2c.write_then_readinto(buf, buf, out_end=1, in_start=1)

        if (buf[1] & 0b00000011) != 0b00000011:
            raise ValueError("Unable to find DS1307 at i2c address 0x68.")

    @property
    def datetime(self):
        """Gets the current date and time or sets the current date and time then starts the
        clock."""
        return self.datetime_register

    @datetime.setter
    def datetime(self, value):
        self.disable_oscillator = False
        self.datetime_register = value
Пример #2
0
class PCF8523:
    """Interface to the PCF8523 RTC."""

    lost_power = i2c_bit.RWBit(0x03, 7)
    """True if the device has lost power since the time was set."""

    power_management = i2c_bits.RWBits(3, 0x02, 5)
    """Power management state that dictates battery switchover, power sources
    and low battery detection. Defaults to BATTERY_SWITCHOVER_OFF (0b000)."""

    # The False means that day comes before weekday in the registers. The 0 is
    # that the first day of the week is value 0 and not 1.
    datetime_register = i2c_bcd_datetime.BCDDateTimeRegister(0x03, False, 0)
    """Current date and time."""

    # The False means that day and weekday share a register. The 0 is that the
    # first day of the week is value 0 and not 1.
    alarm = i2c_bcd_alarm.BCDAlarmTimeRegister(0x0a, has_seconds=False, weekday_shared=False,
                                               weekday_start=0)
    """Alarm time for the first alarm."""

    alarm_interrupt = i2c_bit.RWBit(0x00, 1)
    """True if the interrupt pin will output when alarm is alarming."""

    alarm_status = i2c_bit.RWBit(0x01, 3)
    """True if alarm is alarming. Set to False to reset."""

    battery_low = i2c_bit.ROBit(0x02, 2)
    """True if the battery is low and should be replaced."""

    def __init__(self, i2c_bus):
        self.i2c_device = I2CDevice(i2c_bus, 0x68)

        # Try and verify this is the RTC we expect by checking the timer B
        # frequency control bits which are 1 on reset and shouldn't ever be
        # changed.
        buf = bytearray(2)
        buf[0] = 0x12
        with self.i2c_device as i2c:
            i2c.write(buf, end=1, stop=False)
            i2c.readinto(buf, start=1)

        if (buf[1] & 0b00000111) != 0b00000111:
            raise ValueError("Unable to find PCF8523 at i2c address 0x68.")

    @property
    def datetime(self):
        """Gets the current date and time or sets the current date and time then starts the
           clock."""
        return self.datetime_register

    @datetime.setter
    def datetime(self, value):
        # Automatically sets lost_power to false.
        self.power_management = STANDARD_BATTERY_SWITCHOVER_AND_DETECTION
        self.datetime_register = value
Пример #3
0
class DS3231:
    """Interface to the DS3231 RTC."""

    lost_power = i2c_bit.RWBit(0x0f, 7)
    """True if the device has lost power since the time was set."""

    disable_oscillator = i2c_bit.RWBit(0x0e, 7)
    """True if the oscillator is disabled."""

    datetime_register = i2c_bcd_datetime.BCDDateTimeRegister(0x00)
    """Current date and time."""

    alarm1 = i2c_bcd_alarm.BCDAlarmTimeRegister(0x07)
    """Alarm time for the first alarm."""

    alarm1_interrupt = i2c_bit.RWBit(0x0e, 0)
    """True if the interrupt pin will output when alarm1 is alarming."""

    alarm1_status = i2c_bit.RWBit(0x0f, 0)
    """True if alarm1 is alarming. Set to False to reset."""

    alarm2 = i2c_bcd_alarm.BCDAlarmTimeRegister(0x0b, has_seconds=False)
    """Alarm time for the second alarm."""

    alarm2_interrupt = i2c_bit.RWBit(0x0e, 1)
    """True if the interrupt pin will output when alarm2 is alarming."""

    alarm2_status = i2c_bit.RWBit(0x0f, 1)
    """True if alarm2 is alarming. Set to False to reset."""

    def __init__(self, i2c):
        self.i2c_device = I2CDevice(i2c, 0x68)

        # Try and verify this is the RTC we expect by checking the rate select
        # control bits which are 1 on reset and shouldn't ever be changed.
        buf = bytearray(2)
        buf[0] = 0x0e
        with self.i2c_device as i2c_device:
            i2c_device.write(buf, end=1, stop=False)
            i2c_device.readinto(buf, start=1)

        if (buf[1] & 0b00011000) != 0b00011000:
            raise ValueError("Unable to find DS3231 at i2c address 0x68.")

    @property
    def datetime(self):
        """Gets the current date and time or sets the current date and time
        then starts the clock."""
        return self.datetime_register

    @datetime.setter
    def datetime(self, value):
        self.datetime_register = value
        self.disable_oscillator = False
        self.lost_power = False
Пример #4
0
class DS3231:
    """Interface to the DS3231 RTC."""

    lost_power = i2c_bit.RWBit(0x0F, 7)
    """True if the device has lost power since the time was set."""

    disable_oscillator = i2c_bit.RWBit(0x0E, 7)
    """True if the oscillator is disabled."""

    datetime_register = i2c_bcd_datetime.BCDDateTimeRegister(0x00)
    """Current date and time."""

    alarm1 = i2c_bcd_alarm.BCDAlarmTimeRegister(0x07)
    """Alarm time for the first alarm."""

    alarm1_interrupt = i2c_bit.RWBit(0x0E, 0)
    """True if the interrupt pin will output when alarm1 is alarming."""

    alarm1_status = i2c_bit.RWBit(0x0F, 0)
    """True if alarm1 is alarming. Set to False to reset."""

    alarm2 = i2c_bcd_alarm.BCDAlarmTimeRegister(0x0B, has_seconds=False)
    """Alarm time for the second alarm."""

    alarm2_interrupt = i2c_bit.RWBit(0x0E, 1)
    """True if the interrupt pin will output when alarm2 is alarming."""

    alarm2_status = i2c_bit.RWBit(0x0F, 1)
    """True if alarm2 is alarming. Set to False to reset."""

    def __init__(self, i2c):
        self.i2c_device = I2CDevice(i2c, 0x68)

    @property
    def datetime(self):
        """Gets the current date and time or sets the current date and time
        then starts the clock."""
        return self.datetime_register

    @datetime.setter
    def datetime(self, value):
        self.datetime_register = value
        self.disable_oscillator = False
        self.lost_power = False
Пример #5
0
class DS3231:
    """Interface to the DS3231 RTC."""

    lost_power = i2c_bit.RWBit(0x0F, 7)
    """True if the device has lost power since the time was set."""

    disable_oscillator = i2c_bit.RWBit(0x0E, 7)
    """True if the oscillator is disabled."""

    datetime_register = i2c_bcd_datetime.BCDDateTimeRegister(0x00)
    """Current date and time."""

    alarm1 = i2c_bcd_alarm.BCDAlarmTimeRegister(0x07)
    """Alarm time for the first alarm."""

    alarm1_interrupt = i2c_bit.RWBit(0x0E, 0)
    """True if the interrupt pin will output when alarm1 is alarming."""

    alarm1_status = i2c_bit.RWBit(0x0F, 0)
    """True if alarm1 is alarming. Set to False to reset."""

    alarm2 = i2c_bcd_alarm.BCDAlarmTimeRegister(0x0B, has_seconds=False)
    """Alarm time for the second alarm."""

    alarm2_interrupt = i2c_bit.RWBit(0x0E, 1)
    """True if the interrupt pin will output when alarm2 is alarming."""

    alarm2_status = i2c_bit.RWBit(0x0F, 1)
    """True if alarm2 is alarming. Set to False to reset."""

    _calibration = i2c_bits.RWBits(8, 0x10, 0, 8, signed=True)

    _temperature = i2c_bits.RWBits(
        10, 0x11, 6, register_width=2, lsb_first=False, signed=True
    )

    _busy = i2c_bit.ROBit(0x0F, 2)
    _conv = i2c_bit.RWBit(0x0E, 5)

    def __init__(self, i2c):
        self.i2c_device = I2CDevice(i2c, 0x68)

    @property
    def datetime(self):
        """Gets the current date and time or sets the current date and time
        then starts the clock."""
        return self.datetime_register

    @datetime.setter
    def datetime(self, value):
        self.datetime_register = value
        self.disable_oscillator = False
        self.lost_power = False

    @property
    def temperature(self):
        """Returns the last temperature measurement.  Temperature is updated
        only every 64 seconds, or when a conversion is forced."""
        return self._temperature / 4

    def force_temperature_conversion(self):
        """Forces a conversion and returns the new temperature"""
        while self._busy:
            pass  # Wait for any normal in-progress conversion to complete
        self._conv = True
        while self._conv:
            pass  # Wait for manual conversion request to complete
        return self.temperature

    @property
    def calibration(self):
        """Calibrate the frequency of the crystal oscillator by adding or
        removing capacitance.  The datasheet calls this the Aging Offset.
        Calibration values range from -128 to 127; each step is approximately
        0.1ppm, and positive values decrease the frequency (increase the
        period).  When set, a temperature conversion is forced so the result of
        calibration can be seen directly at the 32kHz pin immediately"""
        return self._calibration

    @calibration.setter
    def calibration(self, value):
        self._calibration = value
        self.force_temperature_conversion()
class PCF8523:
    """Interface to the PCF8523 RTC."""

    lost_power = i2c_bit.RWBit(0x03, 7)
    """True if the device has lost power since the time was set."""

    power_management = i2c_bits.RWBits(3, 0x02, 5)
    """Power management state that dictates battery switchover, power sources
    and low battery detection. Defaults to BATTERY_SWITCHOVER_OFF (0b000)."""

    # The False means that day comes before weekday in the registers. The 0 is
    # that the first day of the week is value 0 and not 1.
    datetime_register = i2c_bcd_datetime.BCDDateTimeRegister(0x03, False, 0)
    """Current date and time."""

    # The False means that day and weekday share a register. The 0 is that the
    # first day of the week is value 0 and not 1.
    alarm = i2c_bcd_alarm.BCDAlarmTimeRegister(0x0A,
                                               has_seconds=False,
                                               weekday_shared=False,
                                               weekday_start=0)
    """Alarm time for the first alarm."""

    alarm_interrupt = i2c_bit.RWBit(0x00, 1)
    """True if the interrupt pin will output when alarm is alarming."""

    alarm_status = i2c_bit.RWBit(0x01, 3)
    """True if alarm is alarming. Set to False to reset."""

    battery_low = i2c_bit.ROBit(0x02, 2)
    """True if the battery is low and should be replaced."""

    high_capacitance = i2c_bit.RWBit(0x00, 7)
    """True for high oscillator capacitance (12.5pF), otherwise lower (7pF)"""

    calibration_schedule_per_minute = i2c_bit.RWBit(0x0E, 7)
    """False to apply the calibration offset every 2 hours (1 LSB = 4.340ppm);
    True to offset every minute (1 LSB = 4.069ppm).  The default, False,
    consumes less power.  See datasheet figures 28-31 for details."""

    calibration = i2c_bits.RWBits(7, 0xE, 0, signed=True)
    """Calibration offset to apply, from -64 to +63.  See the PCF8523 datasheet
    figure 18 for the offset calibration calculation workflow."""
    def __init__(self, i2c_bus):
        self.i2c_device = I2CDevice(i2c_bus, 0x68)

        # Try and verify this is the RTC we expect by checking the timer B
        # frequency control bits which are 1 on reset and shouldn't ever be
        # changed.
        buf = bytearray(2)
        buf[0] = 0x12
        with self.i2c_device as i2c:
            i2c.write_then_readinto(buf, buf, out_end=1, in_start=1)

        if (buf[1] & 0b00000111) != 0b00000111:
            raise ValueError("Unable to find PCF8523 at i2c address 0x68.")

    @property
    def datetime(self):
        """Gets the current date and time or sets the current date and time then starts the
           clock."""
        return self.datetime_register

    @datetime.setter
    def datetime(self, value):
        # Automatically sets lost_power to false.
        self.power_management = STANDARD_BATTERY_SWITCHOVER_AND_DETECTION
        self.datetime_register = value
class PCF8523:
    """Interface to the PCF8523 RTC.

    :param ~busio.I2C i2c_bus: The I2C bus the device is connected to

    **Quickstart: Importing and using the device**

        Here is an example of using the :class:`PCF8523` class.
        First you will need to import the libraries to use the sensor

        .. code-block:: python

            import time
            import board
            import adafruit_pcf8523

        Once this is done you can define your `board.I2C` object and define your sensor object

        .. code-block:: python

            i2c = board.I2C()  # uses board.SCL and board.SDA
            rtc = adafruit_pcf8523.PCF8523(i2c)

        Now you can give the current time to the device.

        .. code-block:: python

            t = time.struct_time((2017, 10, 29, 15, 14, 15, 0, -1, -1))
            rtc.datetime = t

        You can access the current time accessing the :attr:`datetime` attribute.

        .. code-block:: python

            current_time = rtc.datetime

    """

    lost_power = i2c_bit.RWBit(0x03, 7)
    """True if the device has lost power since the time was set."""

    power_management = i2c_bits.RWBits(3, 0x02, 5)
    """Power management state that dictates battery switchover, power sources
    and low battery detection. Defaults to BATTERY_SWITCHOVER_OFF (0b000)."""

    # The False means that day comes before weekday in the registers. The 0 is
    # that the first day of the week is value 0 and not 1.
    datetime_register = i2c_bcd_datetime.BCDDateTimeRegister(0x03, False, 0)
    """Current date and time."""

    # The False means that day and weekday share a register. The 0 is that the
    # first day of the week is value 0 and not 1.
    alarm = i2c_bcd_alarm.BCDAlarmTimeRegister(0x0A,
                                               has_seconds=False,
                                               weekday_shared=False,
                                               weekday_start=0)
    """Alarm time for the first alarm."""

    alarm_interrupt = i2c_bit.RWBit(0x00, 1)
    """True if the interrupt pin will output when alarm is alarming."""

    alarm_status = i2c_bit.RWBit(0x01, 3)
    """True if alarm is alarming. Set to False to reset."""

    battery_low = i2c_bit.ROBit(0x02, 2)
    """True if the battery is low and should be replaced."""

    high_capacitance = i2c_bit.RWBit(0x00, 7)
    """True for high oscillator capacitance (12.5pF), otherwise lower (7pF)"""

    calibration_schedule_per_minute = i2c_bit.RWBit(0x0E, 7)
    """False to apply the calibration offset every 2 hours (1 LSB = 4.340ppm);
    True to offset every minute (1 LSB = 4.069ppm).  The default, False,
    consumes less power.  See datasheet figures 28-31 for details."""

    calibration = i2c_bits.RWBits(  # pylint: disable=unexpected-keyword-arg
        7, 0xE, 0, signed=True)
    """Calibration offset to apply, from -64 to +63.  See the PCF8523 datasheet
    figure 18 for the offset calibration calculation workflow."""
    def __init__(self, i2c_bus: I2C):
        self.i2c_device = I2CDevice(i2c_bus, 0x68)

        # Try and verify this is the RTC we expect by checking the timer B
        # frequency control bits which are 1 on reset and shouldn't ever be
        # changed.
        buf = bytearray(2)
        buf[0] = 0x12
        with self.i2c_device as i2c:
            i2c.write_then_readinto(buf, buf, out_end=1, in_start=1)

        if (buf[1] & 0b00000111) != 0b00000111:
            raise ValueError("Unable to find PCF8523 at i2c address 0x68.")

    @property
    def datetime(self) -> struct_time:
        """Gets the current date and time or sets the current date and time then starts the
        clock."""
        return self.datetime_register

    @datetime.setter
    def datetime(self, value: struct_time):
        # Automatically sets lost_power to false.
        self.power_management = STANDARD_BATTERY_SWITCHOVER_AND_DETECTION
        self.datetime_register = value
class DS3231:
    """Interface to the DS3231 RTC.

    :param ~busio.I2C i2c: The I2C bus the device is connected to

    **Quickstart: Importing and using the device**

        Here is an example of using the :class:`DS3231` class.
        First you will need to import the libraries to use the sensor

        .. code-block:: python

            import time
            import board
            import adafruit_ds3231

        Once this is done you can define your `board.I2C` object and define your sensor object

        .. code-block:: python

            i2c = board.I2C()  # uses board.SCL and board.SDA
            rtc = adafruit_ds3231.DS3231(i2c)

        Now you can give the current time to the device.

        .. code-block:: python

            t = time.struct_time((2017, 10, 29, 15, 14, 15, 0, -1, -1))
            rtc.datetime = t

        You can access the current time accessing the :attr:`datetime` attribute.

        .. code-block:: python

            current_time = rtc.datetime

    """

    lost_power = i2c_bit.RWBit(0x0F, 7)
    """True if the device has lost power since the time was set."""

    disable_oscillator = i2c_bit.RWBit(0x0E, 7)
    """True if the oscillator is disabled."""

    datetime_register = i2c_bcd_datetime.BCDDateTimeRegister(0x00)
    """Current date and time."""

    alarm1 = i2c_bcd_alarm.BCDAlarmTimeRegister(0x07)
    """Alarm time for the first alarm."""

    alarm1_interrupt = i2c_bit.RWBit(0x0E, 0)
    """True if the interrupt pin will output when alarm1 is alarming."""

    alarm1_status = i2c_bit.RWBit(0x0F, 0)
    """True if alarm1 is alarming. Set to False to reset."""

    alarm2 = i2c_bcd_alarm.BCDAlarmTimeRegister(0x0B, has_seconds=False)
    """Alarm time for the second alarm."""

    alarm2_interrupt = i2c_bit.RWBit(0x0E, 1)
    """True if the interrupt pin will output when alarm2 is alarming."""

    alarm2_status = i2c_bit.RWBit(0x0F, 1)
    """True if alarm2 is alarming. Set to False to reset."""

    # pylint: disable=unexpected-keyword-arg
    _calibration = i2c_bits.RWBits(8, 0x10, 0, 1, signed=True)

    _temperature = i2c_bits.RWBits(
        10, 0x11, 6, register_width=2, lsb_first=False, signed=True
    )
    # pylint: enable=unexpected-keyword-arg

    _busy = i2c_bit.ROBit(0x0F, 2)
    _conv = i2c_bit.RWBit(0x0E, 5)

    def __init__(self, i2c: I2C) -> None:
        self.i2c_device = I2CDevice(i2c, 0x68)

    @property
    def datetime(self) -> struct_time:
        """Gets the current date and time or sets the current date and time
        then starts the clock."""
        return self.datetime_register

    @datetime.setter
    def datetime(self, value: struct_time) -> None:
        self.datetime_register = value
        self.disable_oscillator = False
        self.lost_power = False

    @property
    def temperature(self) -> float:
        """Returns the last temperature measurement.  Temperature is updated
        only every 64 seconds, or when a conversion is forced."""
        return self._temperature / 4

    def force_temperature_conversion(self) -> float:
        """Forces a conversion and returns the new temperature"""
        while self._busy:
            pass  # Wait for any normal in-progress conversion to complete
        self._conv = True
        while self._conv:
            pass  # Wait for manual conversion request to complete
        return self.temperature

    @property
    def calibration(self) -> int:
        """Calibrate the frequency of the crystal oscillator by adding or
        removing capacitance.  The datasheet calls this the Aging Offset.
        Calibration values range from -128 to 127; each step is approximately
        0.1ppm, and positive values decrease the frequency (increase the
        period).  When set, a temperature conversion is forced so the result of
        calibration can be seen directly at the 32kHz pin immediately"""
        return self._calibration

    @calibration.setter
    def calibration(self, value: int) -> None:
        self._calibration = value
        self.force_temperature_conversion()
Пример #9
0
class PCF8523:
    """Interface to the PCF8523 RTC."""

    lost_power = i2c_bit.RWBit(0x03, 7)
    """True if the device has lost power since the time was set."""

    disable_oscillator = i2c_bit.RWBit(0x00, 5)
    """True if the oscillator is disabled."""

    _square_wave_control = i2c_bits.RWBits(3, 0x0F, 3)
    """reg 0x0F, bits 3:5 identify the square wave frequency"""

    _r13b0 = i2c_bit.ROBit(0x13, 0)
    """reg 0x13, bit 0 used to distinguish ds3231"""
    _r3fb0 = i2c_bit.RWBit(0x3f, 0)
    """reg 0x3f, bit 0 used to distinguish between ds1307 and pcf8523"""

    power_management = i2c_bits.RWBits(3, 0x02, 5)
    """Power management state that dictates battery switchover, power sources
    and low battery detection. Defaults to BATTERY_SWITCHOVER_OFF (0b111)."""

    # The False means that day comes before weekday in the registers. The 0 is
    # that the first day of the week is value 0 and not 1.
    datetime_register = i2c_bcd_datetime.BCDDateTimeRegister(0x03, False, 0)
    """Current date and time."""

    # The False means that day and weekday share a register. The 0 is that the
    # first day of the week is value 0 and not 1.
    alarm = i2c_bcd_alarm.BCDAlarmTimeRegister(0x0A,
                                               has_seconds=False,
                                               weekday_shared=False,
                                               weekday_start=0)
    """Alarm time for the first alarm."""

    alarm_interrupt = i2c_bit.RWBit(0x00, 1)
    """True if the interrupt pin will output when alarm is alarming."""

    alarm_status = i2c_bit.RWBit(0x01, 3)
    """True if alarm is alarming. Set to False to reset."""

    battery_low = i2c_bit.ROBit(0x02, 2)
    """True if the battery is low and should be replaced."""

    high_capacitance = i2c_bit.RWBit(0x00, 7)
    """True for high oscillator capacitance (12.5pF), otherwise lower (7pF)"""

    calibration_schedule_per_minute = i2c_bit.RWBit(0x0E, 7)
    """False to apply the calibration offset every 2 hours (1 LSB = 4.340ppm);
    True to offset every minute (1 LSB = 4.069ppm).  The default, False,
    consumes less power.  See datasheet figures 28-31 for details."""

    calibration = i2c_bits.RWBits(  # pylint: disable=unexpected-keyword-arg
        7, 0xE, 0, signed=True)
    """Calibration offset to apply, from -64 to +63.  See the PCF8523 datasheet
    figure 18 for the offset calibration calculation workflow."""
    def __init__(self, i2c_bus):
        self.i2c_device = I2CDevice(i2c_bus, 0x68)
        chip = self.chip_identity
        expected = self.__class__.__name__
        if chip != expected:
            raise RuntimeError(
                'Expected {}, found {} at i2c address 0x68'.format(
                    expected, chip))

    @property
    def chip_identity(self):
        """identify the RTC chip (distinguishes among DS1307, PCF8523 and DS3231)"""
        try:
            r13b0 = self._r13b0
        except OSError:
            return 'DS3231'
        else:
            r3fb0 = self._r3fb0
            self._r3fb0 = not r3fb0
            if r3fb0 != self._r3fb0:
                self._r3fb0 = r3fb0
                return 'DS1307'
        return 'PCF8523'

    @property
    def datetime(self):
        """Gets the current date and time or sets the current date and time then starts the
        clock."""
        return self.datetime_register

    @datetime.setter
    def datetime(self, value):
        # Required to enable switching to battery
        self.power_management = STANDARD_BATTERY_SWITCHOVER_AND_DETECTION
        # Automatically sets lost_power to false.
        self.datetime_register = value
        self.disable_oscillator = False

    @property
    def square_wave_frequency(self):
        """Return the square wave frequency, 0 if not enabled"""
        value = self._square_wave_control
        freqs = (1, 32, 1024, 4096, 8192, 16384, 32768, 0)
        return freqs[value]

    @square_wave_frequency.setter
    def square_wave_frequency(self, frequency):
        available_frequencies = {
            0: 7,
            1: 6,
            32: 5,
            1024: 4,
            4096: 3,
            8192: 2,
            16384: 1,
            32768: 0
        }
        try:
            code = available_frequencies[frequency]
            self._square_wave_control = code
        except KeyError:
            raise ValueError(
                'square wave frequency {} not available'.format(frequency))
Пример #10
0
class DS3231:
    """Interface to the DS3231 RTC."""

    lost_power = i2c_bit.RWBit(0x0F, 7)
    """True if the device has lost power since the time was set."""

    disable_oscillator = i2c_bit.RWBit(0x0E, 7)
    """True if the oscillator is disabled."""

    datetime_register = i2c_bcd_datetime.BCDDateTimeRegister(0x00)
    """Current date and time."""

    alarm1 = i2c_bcd_alarm.BCDAlarmTimeRegister(0x07)
    """Alarm time for the first alarm."""

    alarm1_interrupt = i2c_bit.RWBit(0x0E, 0)
    """True if the interrupt pin will output when alarm1 is alarming."""

    alarm1_status = i2c_bit.RWBit(0x0F, 0)
    """True if alarm1 is alarming. Set to False to reset."""

    alarm2 = i2c_bcd_alarm.BCDAlarmTimeRegister(0x0B, has_seconds=False)
    """Alarm time for the second alarm."""

    alarm2_interrupt = i2c_bit.RWBit(0x0E, 1)
    """True if the interrupt pin will output when alarm2 is alarming."""

    alarm2_status = i2c_bit.RWBit(0x0F, 1)
    """True if alarm2 is alarming. Set to False to reset."""

    _square_wave_control = i2c_bits.RWBits(3, 0x0E, 2)
    """reg 0x0e, bits 3:4 identify the square wave frequency, bit 2 is disable"""

    _r13b0 = i2c_bit.ROBit(0x13, 0)
    """reg 0x13, bit 0 used to distinguish ds3231"""
    _r3fb0 = i2c_bit.RWBit(0x3f, 0)
    """reg 0x3f, bit 0 used to distinguish between ds1307 and pcf8523"""

    # pylint: disable=unexpected-keyword-arg
    _calibration = i2c_bits.RWBits(8, 0x10, 0, 1, signed=True)

    _temperature = i2c_bits.RWBits(
        10, 0x11, 6, register_width=2, lsb_first=False, signed=True
    )
    # pylint: enable=unexpected-keyword-arg

    _busy = i2c_bit.ROBit(0x0F, 2)
    _conv = i2c_bit.RWBit(0x0E, 5)

    def __init__(self, i2c):
        self.i2c_device = I2CDevice(i2c, 0x68)
        chip = self.chip_identity
        expected = self.__class__.__name__
        if chip != expected:
            raise RuntimeError('Expected {}, found {}'.format(expected, chip))

    @property
    def chip_identity(self):
        """identify the RTC chip (distinguishes among DS1307, PCF8523 and DS3231)"""
        try:
            r13b0 = self._r13b0
        except OSError:
            return 'DS3231'
        else:
            r3fb0 = self._r3fb0
            self._r3fb0 = not r3fb0
            if r3fb0 != self._r3fb0:
                self._r3fb0 = r3fb0
                return 'DS1307'
        return 'PCF8523'
        
    @property
    def datetime(self):
        """Gets the current date and time or sets the current date and time
        then starts the clock."""
        return self.datetime_register

    @datetime.setter
    def datetime(self, value):
        self.datetime_register = value
        self.disable_oscillator = False
        self.lost_power = False

    @property
    def temperature(self):
        """Returns the last temperature measurement.  Temperature is updated
        only every 64 seconds, or when a conversion is forced."""
        return self._temperature / 4

    def force_temperature_conversion(self):
        """Forces a conversion and returns the new temperature"""
        while self._busy:
            pass  # Wait for any normal in-progress conversion to complete
        self._conv = True
        while self._conv:
            pass  # Wait for manual conversion request to complete
        return self.temperature

    @property
    def square_wave_frequency(self):
        """Return the square wave frequency, 0 if not enabled"""
        value = self._square_wave_control
        freqs = (1, 0, 1024, 0, 4096, 0, 8192, 0)
        return freqs[value]

    @square_wave_frequency.setter
    def square_wave_frequency(self, frequency):
        available_frequencies = {0: 1, 1: 0, 1024: 2, 4096: 4, 8192: 6}
        try:
            code = available_frequencies[frequency]
            self._square_wave_control = code
        except KeyError:
            raise ValueError('square wave frequency {} not available'.format(frequency))

    @property
    def calibration(self):
        """Calibrate the frequency of the crystal oscillator by adding or
        removing capacitance.  The datasheet calls this the Aging Offset.
        Calibration values range from -128 to 127; each step is approximately
        0.1ppm, and positive values decrease the frequency (increase the
        period).  When set, a temperature conversion is forced so the result of
        calibration can be seen directly at the 32kHz pin immediately"""
        return self._calibration

    @calibration.setter
    def calibration(self, value):
        self._calibration = value
        self.force_temperature_conversion()
Пример #11
0
class DS1307:
    """Interface to the DS1307 RTC."""

    disable_oscillator = i2c_bit.RWBit(0x0, 7)
    """True if the oscillator is disabled."""

    datetime_register = i2c_bcd_datetime.BCDDateTimeRegister(0x00)
    """Current date and time."""

    _square_wave_control = i2c_bits.RWBits(5, 0x07, 0)
    """reg 0x07, bits 0:1 identify the square wave frequency, bit 4 = 1"""

    _r13b0 = i2c_bit.ROBit(0x13, 0)
    """reg 0x13, bit 0 used to distinguish ds3231"""
    _r3fb0 = i2c_bit.RWBit(0x3f, 0)
    """reg 0x3f, bit 0 used to distinguish between ds1307 and pcf8523"""
    def __init__(self, i2c_bus):
        self.i2c_device = I2CDevice(i2c_bus, 0x68)
        chip = self.chip_identity
        expected = self.__class__.__name__
        if chip != expected:
            raise RuntimeError('Expected {}, found {}'.format(expected, chip))

    @property
    def chip_identity(self):
        """identify the RTC chip (distinguishes among DS1307, PCF8523 and DS3231)"""
        try:
            r13b0 = self._r13b0
        except OSError:
            return 'DS3231'
        else:
            r3fb0 = self._r3fb0
            self._r3fb0 = not r3fb0
            if r3fb0 != self._r3fb0:
                self._r3fb0 = r3fb0
                return 'DS1307'
        return 'PCF8523'

    @property
    def datetime(self):
        """Gets the current date and time or sets the current date and time then starts the
        clock."""
        return self.datetime_register

    @datetime.setter
    def datetime(self, value):
        # automatically starts the oscillator
        self.datetime_register = value

    @property
    def square_wave_frequency(self):
        """Return the square wave frequency, 0 if disabled"""
        value = self._square_wave_control
        freq_bits = value & 0x3
        if value == freq_bits:  # if square wave is disabled
            return 0
        freqs = (1, 4096, 8192, 32768)
        return freqs[freq_bits]

    @square_wave_frequency.setter
    def square_wave_frequency(self, frequency):
        """Select the frequency and enable the square wave output"""
        available_frequencies = {
            0: 0x00,
            1: 0x10,
            4096: 0x11,
            8192: 0x12,
            32768: 0x13
        }
        try:
            code = available_frequencies[frequency]
            self._square_wave_control = code
        except KeyError:
            raise ValueError(
                'square wave frequency {} not available'.format(frequency))