diff --git a/README.rst b/README.rst index 003cde2..03dbdb2 100644 --- a/README.rst +++ b/README.rst @@ -75,7 +75,7 @@ Of course, you must import the library to use it: .. code:: python import busio - import adafruit_pcf8563 + from adafruit_pcf8563.pcf8563 import PCF8563 import time All the Adafruit RTC libraries take an instantiated and active I2C object @@ -98,7 +98,7 @@ the RTC object: .. code:: python - rtc = adafruit_pcf8563.PCF8563(i2c_bus) + rtc = PCF8563(i2c_bus) Date and time ------------- diff --git a/adafruit_pcf8563/clock.py b/adafruit_pcf8563/clock.py new file mode 100644 index 0000000..830779d --- /dev/null +++ b/adafruit_pcf8563/clock.py @@ -0,0 +1,92 @@ +# SPDX-FileCopyrightText: 2016 Philip R. Moyer and Radomir Dopieralski for Adafruit Industries. +# SPDX-FileCopyrightText: Copyright (c) 2021 Jeff Epler for Adafruit Industries +# SPDX-FileCopyrightText: Copyright (c) 2023 Bernhard Bablok +# +# SPDX-License-Identifier: MIT + +""" +`clock` - PCF8563 Clock module +============================== + +This class supports the clkout-feature of the PCF8563-based RTC in CircuitPython. + +Functions are included for reading and writing registers to configure +clklout frequency. + +The class supports stand-alone usage. In this case, pass an i2-bus object +to the constructor. If used together with the PCF8563 class (rtc), instantiate +the rtc-object first and then pass the i2c_device attribute of the rtc +to the constructor of the clock. + +Author(s): Bernhard Bablok +Date: March 2023 + +Implementation Notes +-------------------- + +**Hardware:** + +* `Seeeduino XIAO Expansion Board `_ + - Works With Adafruit QT Py (Product ID: 5033) + +**Software and Dependencies:** + +* Adafruit CircuitPython firmware: https://github.com/adafruit/circuitpython/releases +* Adafruit's Register library: https://github.com/adafruit/Adafruit_CircuitPython_Register +* Adafruit's Bus Device library: https://github.com/adafruit/Adafruit_CircuitPython_BusDevice + +**Notes:** + +#. Datasheet: http://cache.nxp.com/documents/data_sheet/PCF8563.pdf +""" + +__version__ = "0.0.0+auto.0" +__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_PCF8563.git" + +import time + +from adafruit_bus_device.i2c_device import I2CDevice +from adafruit_register import i2c_bit +from adafruit_register import i2c_bits +from micropython import const + +try: + from typing import Union + from busio import I2C +except ImportError: + pass + + +class Clock: # pylint: disable=too-few-public-methods + """Interface to the clkout of the PCF8563 RTC. + + :param I2C i2c_bus: The I2C bus object + """ + + clockout_enabled = i2c_bit.RWBit(0x0D, 7) + """True if clockout is enabled (default). To disable clockout, set to False""" + + clockout_frequency = i2c_bits.RWBits(2, 0x0D, 0) + """Clock output frequencies generated. Default is 32.768kHz. + Possible values are as shown (selection value - frequency). + 00 - 32.768khz + 01 - 1.024kHz + 10 - 0.032kHz (32Hz) + 11 - 0.001kHz (1Hz) + """ + + CLOCKOUT_FREQ_32KHZ = const(0b00) + """Clock frequency of 32 KHz""" + CLOCKOUT_FREQ_1KHZ = const(0b01) + """Clock frequency of 4 KHz""" + CLOCKOUT_FREQ_32HZ = const(0b10) + """Clock frequency of 32 Hz""" + CLOCKOUT_FREQ_1HZ = const(0b11) + """Clock frequency of 1 Hz""" + + def __init__(self, i2c: Union[I2C, I2CDevice]) -> None: + if isinstance(i2c, I2CDevice): + self.i2c_device = i2c # reuse i2c_device (from PCF8563-instance) + else: + time.sleep(0.05) + self.i2c_device = I2CDevice(i2c, 0x51) diff --git a/adafruit_pcf8563.py b/adafruit_pcf8563/pcf8563.py similarity index 81% rename from adafruit_pcf8563.py rename to adafruit_pcf8563/pcf8563.py index 9e507bb..7fd0e76 100644 --- a/adafruit_pcf8563.py +++ b/adafruit_pcf8563/pcf8563.py @@ -4,7 +4,7 @@ # SPDX-License-Identifier: MIT """ -`adafruit_pcf8563` - PCF8563 Real Time Clock module +`pcf8563` - PCF8563 Real Time Clock module ==================================================== This library supports the use of the PCF8563-based RTC in CircuitPython. It @@ -35,8 +35,10 @@ class is inherited by the chip-specific subclasses. **Notes:** #. Milliseconds are not supported by this RTC. +#. The alarm does not support seconds. It will always fire on full minutes. +#. This RTC has a single timer. The class Timer implements the interface to timer-specfic registers. +#. The class Clock implements the configuration of the clkout-pin. #. Datasheet: http://cache.nxp.com/documents/data_sheet/PCF8563.pdf - """ __version__ = "0.0.0+auto.0" @@ -75,7 +77,9 @@ class PCF8563: alarm = i2c_bcd_alarm.BCDAlarmTimeRegister( 0x09, has_seconds=False, weekday_shared=False, weekday_start=0 ) - """Alarm time for the alarm.""" + """Alarm time for the alarm. Note that the value of the seconds-fields + is ignored, i.e. alarms only fire at full minutes. For short-term + alarms, use a timer instead.""" alarm_interrupt = i2c_bit.RWBit(0x01, 1) """True if the interrupt pin will output when alarm is alarming.""" @@ -83,18 +87,13 @@ class PCF8563: alarm_status = i2c_bit.RWBit(0x01, 3) """True if alarm is alarming. Set to False to reset.""" + clockout_enabled = i2c_bit.RWBit(0x0D, 7) + """True if clockout is enabled (default). To disable clockout, set to False""" + def __init__(self, i2c_bus: I2C) -> None: time.sleep(0.05) self.i2c_device = I2CDevice(i2c_bus, 0x51) - # 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) - @property def datetime(self) -> time.struct_time: """Gets the current date and time or sets the current date and time then starts the @@ -106,3 +105,8 @@ def datetime(self, value: time.struct_time) -> None: # Automatically sets lost_power to false. self.datetime_register = value self.datetime_compromised = False + + @property + def lost_power(self) -> bool: + """Compatibility property for PCF8523-lib""" + return self.datetime_compromised diff --git a/adafruit_pcf8563/timer.py b/adafruit_pcf8563/timer.py new file mode 100644 index 0000000..65fea23 --- /dev/null +++ b/adafruit_pcf8563/timer.py @@ -0,0 +1,111 @@ +# SPDX-FileCopyrightText: 2016 Philip R. Moyer and Radomir Dopieralski for Adafruit Industries. +# SPDX-FileCopyrightText: Copyright (c) 2021 Jeff Epler for Adafruit Industries +# SPDX-FileCopyrightText: Copyright (c) 2023 Bernhard Bablok +# +# SPDX-License-Identifier: MIT + +""" +`timer` - PCF8563 Timer module +============================== + +This class supports the timer of the PCF8563-based RTC in CircuitPython. + +Functions are included for reading and writing registers and manipulating +timer objects. + +The class supports stand-alone usage. In this case, pass an i2-bus object +to the constructor. If used together with the PCF8563 class (rtc), instantiate +the rtc-object first and then pass the i2c_device attribute of the rtc +to the constructor of the timer. + +Author(s): Bernhard Bablok +Date: March 2023 + +Implementation Notes +-------------------- + +**Hardware:** + +* `Seeeduino XIAO Expansion Board `_ + - Works With Adafruit QT Py (Product ID: 5033) + +**Software and Dependencies:** + +* Adafruit CircuitPython firmware: https://github.com/adafruit/circuitpython/releases +* Adafruit's Register library: https://github.com/adafruit/Adafruit_CircuitPython_Register +* Adafruit's Bus Device library: https://github.com/adafruit/Adafruit_CircuitPython_BusDevice + +**Notes:** + +#. Datasheet: http://cache.nxp.com/documents/data_sheet/PCF8563.pdf +""" + +__version__ = "0.0.0+auto.0" +__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_PCF8563.git" + +import time + +from adafruit_bus_device.i2c_device import I2CDevice +from adafruit_register import i2c_bit +from adafruit_register import i2c_bits +from micropython import const + +try: + from typing import Union + from busio import I2C +except ImportError: + pass + + +class Timer: # pylint: disable=too-few-public-methods + """Interface to the timer of the PCF8563 RTC. + + :param I2C i2c_bus: The I2C bus object + """ + + timer_enabled = i2c_bit.RWBit(0x0E, 7) + """True if the timer is enabled. Default is False.""" + + timer_frequency = i2c_bits.RWBits(2, 0x0E, 0) + """Timer clock frequency. Default is 1/60Hz. + Possible values are as shown (selection value - frequency). + 00 - 4.096kHz + 01 - 64Hz + 10 - 1Hz + 11 - 1/60Hz + """ + TIMER_FREQ_4KHZ = const(0b00) + """Timer frequency of 4 KHz""" + TIMER_FREQ_64HZ = const(0b01) + """Timer frequency of 64 Hz""" + TIMER_FREQ_1HZ = const(0b10) + """Timer frequency of 1 Hz""" + TIMER_FREQ_1_60HZ = const(0b11) + """Timer frequency of 1/60 Hz""" + + timer_value = i2c_bits.RWBits(8, 0x0F, 0) + """ Timer value (0-255). The default is undefined. + The total countdown duration is calcuated by + timer_value/timer_frequency. For a higher precision, use higher values + and frequencies, e.g. for a one minute timer you could use + value=1, frequency=1/60Hz or value=60, frequency=1Hz. The + latter will give better results. See the PCF85x3 User's Manual + for details.""" + + timer_interrupt = i2c_bit.RWBit(0x01, 0) + """True if the interrupt pin will assert when timer has elapsed. + Defaults to False.""" + + timer_status = i2c_bit.RWBit(0x01, 2) + """True if timer has elapsed. Set to False to reset.""" + + timer_pulsed = i2c_bit.RWBit(0x01, 4) + """True if timer asserts INT as a pulse. The default + value False asserts INT permanently.""" + + def __init__(self, i2c: Union[I2C, I2CDevice]) -> None: + if isinstance(i2c, I2CDevice): + self.i2c_device = i2c # reuse i2c_device (from PCF8563-instance) + else: + time.sleep(0.05) + self.i2c_device = I2CDevice(i2c, 0x51) diff --git a/docs/api.rst b/docs/api.rst index 4931671..b211a32 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -1,3 +1,9 @@ -.. automodule:: adafruit_pcf8563 +.. automodule:: adafruit_pcf8563.pcf8563 + :members: + +.. automodule:: adafruit_pcf8563.timer + :members: + +.. automodule:: adafruit_pcf8563.clock :members: diff --git a/docs/conf.py b/docs/conf.py index e3c23a7..6cd355a 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -24,7 +24,7 @@ # Uncomment the below if you use native CircuitPython modules such as # digitalio, micropython and busio. List the modules you use. Without it, the # autodoc module docs will fail to generate with a warning. -# autodoc_mock_imports = ["adafruit_bus_device", "adafruit_register"] +autodoc_mock_imports = ["adafruit_bus_device", "adafruit_register"] # Add any paths that contain templates here, relative to this directory. templates_path = ["_templates"] diff --git a/examples/pcf8563_simpletest.py b/examples/pcf8563_simpletest.py index 8e82516..e45141b 100644 --- a/examples/pcf8563_simpletest.py +++ b/examples/pcf8563_simpletest.py @@ -12,13 +12,13 @@ import board import busio -import adafruit_pcf8563 +from adafruit_pcf8563.pcf8563 import PCF8563 # Change to the appropriate I2C clock & data pins here! i2c_bus = busio.I2C(board.SCL, board.SDA) # Create the RTC instance: -rtc = adafruit_pcf8563.PCF8563(i2c_bus) +rtc = PCF8563(i2c_bus) # Lookup table for names of days (nicer printing). days = ("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday") diff --git a/pyproject.toml b/pyproject.toml index d54fcbd..2f75f9a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -42,7 +42,7 @@ classifiers = [ dynamic = ["dependencies", "optional-dependencies"] [tool.setuptools] -py-modules = ["adafruit_pcf8563"] +packages = ["adafruit_pcf8563"] [tool.setuptools.dynamic] dependencies = {file = ["requirements.txt"]}