ProtoCore v1.0.16
Deterministic, zero-heap network stack for embedded targets
Loading...
Searching...
No Matches
rtc.h
Go to the documentation of this file.
1// ProtoCore v1.0.16 - Copyright (C) 2026 Douglas Quigg (dstroy0) <dquigg123@gmail.com>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4#ifndef PROTOCORE_RTC_H
5#define PROTOCORE_RTC_H
6
7#include "protocore_config.h" // the entry point: protocore_types.h for the widths
8
10
11/**
12 * @file rtc.h
13 * @brief I2C real-time-clock driver (DS1307 / DS3231) - a battery-backed time source.
14 *
15 * A DS1307 or DS3231 keeps the wall-clock time running from a coin cell when the ESP32 is off
16 * or offline. This reads it (and can set it) over I2C, and plugs into the time-source chain so
17 * `protocore_time_now()` - and the NTP server - can use it: GPS when locked, the RTC when GPS and
18 * the internet are gone, upstream NTP otherwise. Both chips expose the same seven BCD time
19 * registers at address 0x68, so one driver serves both. Zero heap; gated by PROTOCORE_ENABLE_RTC.
20 *
21 * The BCD <-> Unix-epoch conversion (12/24-hour, leap years, range validation) is pure and
22 * host-tested; only the register read/write touches hardware, over the shared I2C bus owner.
23 *
24 * @c work is PROTOCORE_I2C_DEVICE_BORROW bytes the CALLER took, at an address it knows. It is not held past the call,
25 * so nothing here aliases it. How those bytes are carved is this module's and is never named here.
26 *
27 * @author Douglas Quigg (dstroy0)
28 * @date 2026
29 */
30
31#define RTC_REG_COUNT 7
32
33/** @brief Dispatch table. Addressed by offset, so the layout is asserted below. */
34typedef struct
35{
36 proto_bool (*regs_to_epoch)(uint8_t *, const uint8_t *, uint32_t *);
37 void (*epoch_to_regs)(uint8_t *, uint32_t, uint8_t *);
38 proto_bool (*begin)(uint8_t *);
39 uint32_t (*read_epoch)(uint8_t *);
40 proto_bool (*set_epoch)(uint8_t *, uint32_t);
41 void (*time_source)(uint8_t *);
42} RtcNs;
43PROTOCORE_NS_LAYOUT(RtcNs, regs_to_epoch, epoch_to_regs, begin, read_epoch, set_epoch, time_source);
44
45/**
46 * @brief Convert the 7 raw RTC time registers (BCD: sec, min, hour, dow, .
47 * @param work PROTOCORE_RTC_BORROW bytes the caller took. Not held past the call.
48 * @param regs the 7 register bytes as read from register 0 RTC_REG_COUNT bytes
49 * @param epoch out: seconds since 1970-01-01 UTC
50 * @return PROTO_TRUE on success.
51 */
52proto_bool protocore_rtc_regs_to_epoch(uint8_t *work, const uint8_t *regs, uint32_t *epoch);
53/**
54 * @brief Convert a Unix timestamp to the 7 RTC time registers (BCD, .
55 * @param work PROTOCORE_RTC_BORROW bytes the caller took. Not held past the call.
56 * @param epoch Epoch
57 * @param regs RTC_REG_COUNT bytes
58 */
59void protocore_rtc_epoch_to_regs(uint8_t *work, uint32_t epoch, uint8_t *regs);
60/**
61 * @brief Initialize the I2C bus for the RTC. true; with no bus seam it is a .
62 * @param work PROTOCORE_RTC_BORROW bytes the caller took. Not held past the call.
63 * @return PROTO_TRUE on success.
64 */
66/**
67 * @brief Read the current time from the RTC over I2C.
68 * @param work PROTOCORE_RTC_BORROW bytes the caller took. Not held past the call.
69 * @return The uint32_t.
70 */
71uint32_t protocore_rtc_read_epoch(uint8_t *work);
72/**
73 * @brief Set the RTC to epoch over I2C. true if the write succeeded.
74 * @param work PROTOCORE_RTC_BORROW bytes the caller took. Not held past the call.
75 * @param epoch Epoch
76 * @return PROTO_TRUE on success.
77 */
78proto_bool protocore_rtc_set_epoch(uint8_t *work, uint32_t epoch);
79/**
80 * @brief A ::TimeSourceFn wrapper (returns protocore_rtc_read_epoch()) to .
81 * @param work PROTOCORE_RTC_BORROW bytes the caller took. Not held past the call.
82 */
83void protocore_rtc_time_source(uint8_t *work);
84
85/**
86 * @brief The PROTOCORE_I2C_DEVICE_BORROW bytes this module's state lives in.
87 *
88 * Stated beside the namespace rather than on it: an entry takes a borrow, and this is where
89 * that borrow comes from. Taken once from the end of the pool, which no mark and no release
90 * walks, so the state lasts the life of the program.
91 *
92 * @return the span.
93 */
94uint8_t *protocore_rtc_span(void);
95
96/** @brief Module namespace. */
103
105
106#endif // PROTOCORE_RTC_H
#define PROTOCORE_NS_LAYOUT(T,...)
Pin every dispatch slot of a table that is nothing but function pointers.
#define PROTOCORE_NS
Storage for a dispatch table. The const is load bearing.
proto_bool protocore_rtc_begin(uint8_t *work)
Initialize the I2C bus for the RTC. true; with no bus seam it is a .
uint32_t protocore_rtc_read_epoch(uint8_t *work)
Read the current time from the RTC over I2C.
proto_bool protocore_rtc_regs_to_epoch(uint8_t *work, const uint8_t *regs, uint32_t *epoch)
Convert the 7 raw RTC time registers (BCD: sec, min, hour, dow, .
PROTOCORE_NS RtcNs Rtc PROTOCORE_UNUSED
Module namespace.
Definition rtc.h:97
proto_bool protocore_rtc_set_epoch(uint8_t *work, uint32_t epoch)
Set the RTC to epoch over I2C. true if the write succeeded.
void protocore_rtc_epoch_to_regs(uint8_t *work, uint32_t epoch, uint8_t *regs)
Convert a Unix timestamp to the 7 RTC time registers (BCD, .
uint8_t * protocore_rtc_span(void)
The PROTOCORE_I2C_DEVICE_BORROW bytes this module's state lives in.
void protocore_rtc_time_source(uint8_t *work)
A TimeSourceFn wrapper (returns protocore_rtc_read_epoch()) to .
Dispatch table. Addressed by offset, so the layout is asserted below.
Definition rtc.h:35
proto_bool(* regs_to_epoch)(uint8_t *, const uint8_t *, uint32_t *)
Definition rtc.h:36
#define PROTOCORE_BEGIN_DECLS
Give a header's declarations C linkage, so their symbol names carry no parameter types.
Definition types.h:96
_Bool proto_bool
The truth value.
Definition types.h:64
#define PROTOCORE_END_DECLS
Definition types.h:97