Skip to content

Commit f0acff6

Browse files
authored
Merge pull request #30 from bablokb/4upstream
timer-support
2 parents d336221 + 4d3cf8b commit f0acff6

File tree

11 files changed

+493
-35
lines changed

11 files changed

+493
-35
lines changed

README.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ Of course, you must import the library to use it:
7979
.. code:: python3
8080
8181
import time
82-
import adafruit_pcf8523
82+
from adafruit_pcf8523.pcf8523 import PCF8523
8383
8484
All the Adafruit RTC libraries take an instantiated and active I2C object
8585
(from the `board` library) as an argument to their constructor. The way to
@@ -101,7 +101,7 @@ the RTC object:
101101

102102
.. code:: python3
103103
104-
rtc = adafruit_pcf8523.PCF8523(i2c)
104+
rtc = PCF8523(i2c)
105105
106106
Date and time
107107
-------------

adafruit_pcf8523/clock.py

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
# SPDX-FileCopyrightText: 2016 Philip R. Moyer for Adafruit Industries
2+
# SPDX-FileCopyrightText: 2016 Radomir Dopieralski for Adafruit Industries
3+
# SPDX-FileCopyrightText: Copyright (c) 2023 Bernhard Bablok
4+
#
5+
# SPDX-License-Identifier: MIT
6+
7+
"""
8+
`clock` - PCF8523 Clock module
9+
==============================
10+
11+
This class supports the clkout-feature of the PCF8523-based RTC in CircuitPython.
12+
13+
Functions are included for reading and writing registers to configure
14+
clklout frequency.
15+
16+
The class supports stand-alone usage. In this case, pass an i2-bus object
17+
to the constructor. If used together with the PCF8523 class (rtc), instantiate
18+
the rtc-object first and then pass the i2c_device attribute of the rtc
19+
to the constructor of the clock.
20+
21+
Author(s): Bernhard Bablok
22+
Date: September 2023
23+
24+
Implementation Notes
25+
--------------------
26+
27+
**Hardware:**
28+
29+
* Adafruit `Adalogger FeatherWing - RTC + SD Add-on <https://www.adafruit.com/products/2922>`_
30+
(Product ID: 2922)
31+
* Adafruit `PCF8523 RTC breakout <https://www.adafruit.com/products/3295>`_ (Product ID: 3295)
32+
33+
**Software and Dependencies:**
34+
35+
* Adafruit CircuitPython firmware for the supported boards:
36+
https://circuitpython.org/downloads
37+
38+
* Adafruit's Register library: https://github.com/adafruit/Adafruit_CircuitPython_Register
39+
40+
* Adafruit's Bus Device library: https://github.com/adafruit/Adafruit_CircuitPython_BusDevice
41+
42+
**Notes:**
43+
44+
#. Milliseconds are not supported by this RTC.
45+
#. The alarm does not support seconds. It will always fire on full minutes.
46+
#. Datasheet: http://cache.nxp.com/documents/data_sheet/PCF8523.pdf
47+
48+
"""
49+
50+
__version__ = "0.0.0+auto.0"
51+
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_PCF8523.git"
52+
53+
import time
54+
55+
from adafruit_bus_device.i2c_device import I2CDevice
56+
from adafruit_register import i2c_bits
57+
from micropython import const
58+
59+
try:
60+
from typing import Union
61+
from busio import I2C
62+
except ImportError:
63+
pass
64+
65+
66+
class Clock: # pylint: disable=too-few-public-methods
67+
"""Interface to the clkout of the PCF8523 RTC.
68+
69+
:param I2C i2c_bus: The I2C bus object
70+
"""
71+
72+
clockout_frequency = i2c_bits.RWBits(3, 0x0F, 3) # COF[2:0]
73+
"""Clock output frequencies generated. Default is 32.768kHz.
74+
Possible values are as shown (selection value - frequency).
75+
000 - 32.768khz
76+
001 - 16.384khz
77+
010 - 8.192kHz
78+
011 - 4.096kHz
79+
100 - 1.024kHz
80+
101 - 0.032kHz (32Hz)
81+
110 - 0.001kHz (1Hz)
82+
111 - Disabled
83+
"""
84+
85+
CLOCKOUT_FREQ_32KHZ = const(0b000)
86+
"""Clock frequency of 32 KHz"""
87+
CLOCKOUT_FREQ_16KHZ = const(0b001)
88+
"""Clock frequency of 16 KHz"""
89+
CLOCKOUT_FREQ_8KHZ = const(0b010)
90+
"""Clock frequency of 8 KHz"""
91+
CLOCKOUT_FREQ_4KHZ = const(0b011)
92+
"""Clock frequency of 4 KHz"""
93+
CLOCKOUT_FREQ_1KHZ = const(0b100)
94+
"""Clock frequency of 4 KHz"""
95+
CLOCKOUT_FREQ_32HZ = const(0b101)
96+
"""Clock frequency of 32 Hz"""
97+
CLOCKOUT_FREQ_1HZ = const(0b110)
98+
"""Clock frequency of 1 Hz"""
99+
CLOCKOUT_FREQ_DISABLED = const(0b111)
100+
"""Clock output disabled"""
101+
102+
def __init__(self, i2c: Union[I2C, I2CDevice]) -> None:
103+
if isinstance(i2c, I2CDevice):
104+
self.i2c_device = i2c # reuse i2c_device (from PCF8563-instance)
105+
else:
106+
time.sleep(0.05)
107+
self.i2c_device = I2CDevice(i2c, 0x68)

adafruit_pcf8523.py renamed to adafruit_pcf8523/pcf8523.py

Lines changed: 7 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
# SPDX-License-Identifier: MIT
55

66
"""
7-
`adafruit_pcf8523` - PCF8523 Real Time Clock module
8-
====================================================
7+
`pcf8523` - PCF8523 Real Time Clock module
8+
==========================================
99
1010
This library supports the use of the PCF8523-based RTC in CircuitPython. It
1111
contains a base RTC class used by all Adafruit RTC libraries. This base
@@ -39,6 +39,7 @@ class is inherited by the chip-specific subclasses.
3939
**Notes:**
4040
4141
#. Milliseconds are not supported by this RTC.
42+
#. The alarm does not support seconds. It will always fire on full minutes.
4243
#. Datasheet: http://cache.nxp.com/documents/data_sheet/PCF8523.pdf
4344
4445
"""
@@ -106,32 +107,21 @@ class PCF8523:
106107

107108
power_management = i2c_bits.RWBits(3, 0x02, 5)
108109
"""Power management state that dictates battery switchover, power sources
109-
and low battery detection. Defaults to BATTERY_SWITCHOVER_OFF (0b000)."""
110+
and low battery detection. Defaults to BATTERY_SWITCHOVER_OFF (0b111)."""
110111

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

116-
clockout_frequency = i2c_bits.RWBits(3, 0x0F, 3)
117-
"""Clock output frequencies generated. Default is 32.768kHz.
118-
Possible values are as shown (selection value - frequency).
119-
000 - 32.768khz
120-
001 - 16.384khz
121-
010 - 8.192kHz
122-
011 - 4.096kHz
123-
100 - 1.024kHz
124-
101 - 0.032kHz (32Hz)
125-
110 - 0.001kHz (1Hz)
126-
111 - Disabled
127-
"""
128-
129117
# The False means that day and weekday share a register. The 0 is that the
130118
# first day of the week is value 0 and not 1.
131119
alarm = i2c_bcd_alarm.BCDAlarmTimeRegister(
132120
0x0A, has_seconds=False, weekday_shared=False, weekday_start=0
133121
)
134-
"""Alarm time for the first alarm."""
122+
"""Alarm time for the first alarm. Note that the value of the seconds-fields
123+
is ignored, i.e. alarms only fire at full minutes. For short-term
124+
alarms, use a timer instead."""
135125

136126
alarm_interrupt = i2c_bit.RWBit(0x00, 1)
137127
"""True if the interrupt pin will output when alarm is alarming."""
@@ -159,17 +149,6 @@ class PCF8523:
159149
def __init__(self, i2c_bus: I2C):
160150
self.i2c_device = I2CDevice(i2c_bus, 0x68)
161151

162-
# Try and verify this is the RTC we expect by checking the timer B
163-
# frequency control bits which are 1 on reset and shouldn't ever be
164-
# changed.
165-
buf = bytearray(2)
166-
buf[0] = 0x12
167-
with self.i2c_device as i2c:
168-
i2c.write_then_readinto(buf, buf, out_end=1, in_start=1)
169-
170-
if (buf[1] & 0b00000111) != 0b00000111:
171-
raise ValueError("Unable to find PCF8523 at i2c address 0x68.")
172-
173152
@property
174153
def datetime(self) -> struct_time:
175154
"""Gets the current date and time or sets the current date and time then starts the

adafruit_pcf8523/timer.py

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
# SPDX-FileCopyrightText: 2016 Philip R. Moyer for Adafruit Industries
2+
# SPDX-FileCopyrightText: 2016 Radomir Dopieralski for Adafruit Industries
3+
# SPDX-FileCopyrightText: Copyright (c) 2023 Bernhard Bablok
4+
#
5+
# SPDX-License-Identifier: MIT
6+
7+
"""
8+
`timer` - PCF8523 Timer module
9+
==============================
10+
11+
This class supports the timer of the PCF8523-based RTC in CircuitPython.
12+
13+
Functions are included for reading and writing registers and manipulating
14+
timer objects.
15+
16+
The PCF8523 support two timers named Tmr_A and Tmr_B in the datasheet.
17+
For compatibility with the PCF8563, the Tmr_A is named timer while the
18+
second timer is named timerB.
19+
20+
The class supports stand-alone usage. In this case, pass an i2-bus object
21+
to the constructor. If used together with the PCF8523 class (rtc), instantiate
22+
the rtc-object first and then pass the i2c_device attribute of the rtc
23+
to the constructor of the timer.
24+
25+
Author(s): Bernhard Bablok
26+
Date: September 2023
27+
28+
Implementation Notes
29+
--------------------
30+
31+
**Hardware:**
32+
33+
* Adafruit `Adalogger FeatherWing - RTC + SD Add-on <https://www.adafruit.com/products/2922>`_
34+
(Product ID: 2922)
35+
* Adafruit `PCF8523 RTC breakout <https://www.adafruit.com/products/3295>`_ (Product ID: 3295)
36+
37+
**Software and Dependencies:**
38+
39+
* Adafruit CircuitPython firmware for the supported boards:
40+
https://circuitpython.org/downloads
41+
42+
* Adafruit's Register library: https://github.com/adafruit/Adafruit_CircuitPython_Register
43+
44+
* Adafruit's Bus Device library: https://github.com/adafruit/Adafruit_CircuitPython_BusDevice
45+
46+
**Notes:**
47+
48+
#. Milliseconds are not supported by this RTC.
49+
#. The alarm does not support seconds. It will always fire on full minutes.
50+
#. Datasheet: http://cache.nxp.com/documents/data_sheet/PCF8523.pdf
51+
52+
"""
53+
54+
__version__ = "0.0.0+auto.0"
55+
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_PCF8523.git"
56+
57+
import time
58+
59+
from adafruit_bus_device.i2c_device import I2CDevice
60+
from adafruit_register import i2c_bit
61+
from adafruit_register import i2c_bits
62+
from micropython import const
63+
64+
try:
65+
from typing import Union
66+
from busio import I2C
67+
except ImportError:
68+
pass
69+
70+
71+
class Timer: # pylint: disable=too-few-public-methods
72+
"""Interface to the timer of the PCF8563 RTC.
73+
74+
:param I2C i2c_bus: The I2C bus object
75+
"""
76+
77+
timer_enabled = i2c_bits.RWBits(2, 0x0F, 1) # TAC[1:0]
78+
"""Configures timer. Possible values:
79+
00 - disabled
80+
01 - enabled as countdown timer
81+
10 - enabled as watchdog timer
82+
11 - disabled
83+
"""
84+
85+
timer_frequency = i2c_bits.RWBits(3, 0x10, 0) # TAQ[2:0]
86+
"""TimerA clock frequency. Default is 1/3600Hz.
87+
Possible values are as shown (selection value - frequency).
88+
000 - 4.096kHz
89+
001 - 64Hz
90+
010 - 1Hz
91+
011 - 1/60Hz
92+
111 - 1/3600Hz
93+
"""
94+
95+
TIMER_FREQ_4KHZ = const(0b000)
96+
"""Timer frequency of 4 KHz"""
97+
TIMER_FREQ_64HZ = const(0b001)
98+
"""Timer frequency of 64 Hz"""
99+
TIMER_FREQ_1HZ = const(0b010)
100+
"""Timer frequency of 1 Hz"""
101+
TIMER_FREQ_1_60HZ = const(0b011)
102+
"""Timer frequency of 1/60 Hz"""
103+
TIMER_FREQ_1_3600HZ = const(0b111)
104+
"""Timer frequency of 1/3600 Hz"""
105+
106+
timer_value = i2c_bits.RWBits(8, 0x11, 0) # T_A[7:0]
107+
""" TimerA value (0-255). The default is undefined.
108+
The total countdown duration is calcuated by
109+
timer_value/timer_frequency. For a higher precision, use higher values
110+
and frequencies, e.g. for a one minute timer you could use
111+
value=1, frequency=1/60Hz or value=60, frequency=1Hz. The
112+
latter will give better results. See the PCF85x3 User's Manual
113+
for details."""
114+
115+
timer_interrupt = i2c_bit.RWBit(0x01, 1) # CTAIE
116+
"""True if the interrupt pin will assert when timer has elapsed.
117+
Defaults to False."""
118+
119+
timer_watchdog = i2c_bit.RWBit(0x01, 2) # WTAIE
120+
"""True if the interrupt pin will output when timer generates a
121+
watchdog-alarm. Defaults to False."""
122+
123+
timer_status = i2c_bit.RWBit(0x01, 6) # CTAF
124+
"""True if timer has elapsed. Set to False to reset."""
125+
126+
timer_pulsed = i2c_bit.RWBit(0x0F, 7) # TAM
127+
"""True if timer asserts INT as a pulse. The default
128+
value False asserts INT permanently."""
129+
130+
timerB_enabled = i2c_bit.RWBit(0x0F, 0) # TBC
131+
"""True if the timerB is enabled. Default is False."""
132+
133+
timerB_frequency = i2c_bits.RWBits(3, 0x12, 0) # TBQ[2:0]
134+
"""TimerB clock frequency. Default is 1/3600Hz.
135+
Possible values are as shown (selection value - frequency).
136+
000 - 4.096kHz
137+
001 - 64Hz
138+
010 - 1Hz
139+
011 - 1/60Hz
140+
111 - 1/3600Hz
141+
"""
142+
143+
timerB_value = i2c_bits.RWBits(8, 0x13, 0) # T_B[7:0]
144+
""" TimerB value (0-255). The default is undefined.
145+
The total countdown duration is calcuated by
146+
timerB_value/timerB_frequency. For a higher precision, use higher values
147+
and frequencies, e.g. for a one minute timer you could use
148+
value=1, frequency=1/60Hz or value=60, frequency=1Hz. The
149+
latter will give better results. See the PCF85x3 User's Manual
150+
for details."""
151+
152+
timerB_interrupt = i2c_bit.RWBit(0x01, 0) # CTBIE
153+
"""True if the interrupt pin will assert when timerB has elapsed.
154+
Defaults to False."""
155+
156+
timerB_status = i2c_bit.RWBit(0x01, 5) # CTBF
157+
"""True if timerB has elapsed. Set to False to reset."""
158+
159+
timerB_pulsed = i2c_bit.RWBit(0x0F, 6) # TBM
160+
"""True if timerB asserts INT as a pulse. The default
161+
value False asserts INT permanently."""
162+
163+
def __init__(self, i2c: Union[I2C, I2CDevice]) -> None:
164+
if isinstance(i2c, I2CDevice):
165+
self.i2c_device = i2c # reuse i2c_device (from PCF8523-instance)
166+
else:
167+
time.sleep(0.05)
168+
self.i2c_device = I2CDevice(i2c, 0x68)

docs/api.rst

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
11

2-
.. automodule:: adafruit_pcf8523
2+
.. automodule:: adafruit_pcf8523.pcf8523
3+
:members:
4+
5+
.. automodule:: adafruit_pcf8523.timer
6+
:members:
7+
8+
.. automodule:: adafruit_pcf8523.clock
39
:members:

docs/conf.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
# Uncomment the below if you use native CircuitPython modules such as
4545
# digitalio, micropython and busio. List the modules you use. Without it, the
4646
# autodoc module docs will fail to generate with a warning.
47-
# autodoc_mock_imports = ["adafruit_bus_device", "adafruit_register"]
47+
autodoc_mock_imports = ["adafruit_bus_device", "adafruit_register"]
4848

4949
# Add any paths that contain templates here, relative to this directory.
5050
templates_path = ["_templates"]

0 commit comments

Comments
 (0)