Skip to content

Commit 16610a7

Browse files
drivers/max31343: add driver for MAX31343 I2C RTC
1 parent 7846852 commit 16610a7

11 files changed

Lines changed: 1583 additions & 0 deletions

File tree

drivers/include/max31343.h

Lines changed: 316 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,316 @@
1+
/*
2+
* SPDX-FileCopyrightText: 2026 Jakob Müller <ja.mueller@tuhh.de>
3+
* SPDX-License-Identifier: LGPL-2.1-only
4+
*/
5+
6+
/**
7+
* @file
8+
* @brief Driver interface for the MAX31343 I2C real-time clock with integrated MEMS oscillator
9+
*
10+
* @author Jakob Müller <ja.mueller@tuhh.de>
11+
*/
12+
13+
#pragma once
14+
15+
#include <stdint.h>
16+
#include <time.h>
17+
#include <stdbool.h>
18+
19+
#include "periph/i2c.h"
20+
#ifndef USE_INTERNAL_RTC
21+
#include "periph/rtc.h"
22+
#endif
23+
24+
#ifdef __cplusplus
25+
extern "C" {
26+
#endif
27+
28+
/**
29+
* @ingroup drivers_max31343
30+
* @{
31+
*/
32+
33+
/**
34+
* @brief Device descriptor for the MAX31343 RTC.
35+
*
36+
* Holds the runtime state of a MAX31343 device instance.
37+
* Currently this only contains the I2C bus, but may be extended
38+
* in the future.
39+
*/
40+
typedef struct {
41+
i2c_t i2c; /**< I2C bus */
42+
} max31343_t;
43+
44+
/**
45+
* @brief Square-wave output frequency selection.
46+
*
47+
* Selects the output frequency of the SQW pin.
48+
* The exact mapping is defined by the MAX31343 datasheet.
49+
*/
50+
typedef enum {
51+
MAX31343_SQW_1HZ = 0,
52+
MAX31343_SQW_2HZ = 1,
53+
MAX31343_SQW_4HZ = 2,
54+
MAX31343_SQW_8HZ = 3,
55+
MAX31343_SQW_16HZ = 4,
56+
MAX31343_SQW_32HZ = 5,
57+
} max31343_sqw_freq_t;
58+
59+
/**
60+
* @brief Automatic temperature conversion interval.
61+
*
62+
* Defines the interval for automatic temperature measurements
63+
* when temperature AUTOMODE is enabled.
64+
*
65+
* The values correspond to the TTSINT field (TS_Config[5:3]).
66+
*/
67+
typedef enum {
68+
MAX31343_TTSINT_1S = 0x0,
69+
MAX31343_TTSINT_2S = 0x1,
70+
MAX31343_TTSINT_4S = 0x2,
71+
MAX31343_TTSINT_8S = 0x3,
72+
MAX31343_TTSINT_16S = 0x4,
73+
MAX31343_TTSINT_32S = 0x5,
74+
MAX31343_TTSINT_64S = 0x6,
75+
MAX31343_TTSINT_128S = 0x7,
76+
} max31343_ttsint_t;
77+
78+
/**
79+
* @brief Trickle charger resistor selection.
80+
*
81+
* Selects the series resistor in the trickle charging path.
82+
* Corresponds to D_TRICKLE bits [1:0].
83+
*/
84+
typedef enum {
85+
MAX31343_TRICKLE_RES_3K = 0x0U, /**< 3 kΩ */
86+
MAX31343_TRICKLE_RES_6K = 0x2U, /**< 6 kΩ */
87+
MAX31343_TRICKLE_RES_11K = 0x3U, /**< 11 kΩ */
88+
} max31343_trickle_res_t;
89+
90+
/**
91+
* @brief Trickle charger diode path selection.
92+
*
93+
* Selects whether an additional diode is inserted in the charging path.
94+
* Corresponds to D_TRICKLE bit 2.
95+
*
96+
* - SCHOTTKY: Schottky diode only.
97+
* - PLUS_SCHOTTKY: Additional diode in series with a Schottky diode.
98+
*/
99+
typedef enum {
100+
MAX31343_TRICKLE_DIODE_SCHOTTKY = 0U, /**< Schottky diode only */
101+
MAX31343_TRICKLE_DIODE_PLUS_SCHOTTKY = 1U, /**< Diode + Schottky diode path */
102+
} max31343_trickle_diode_t;
103+
104+
/**
105+
* @brief Configuration parameters for MAX31343 initialization.
106+
*
107+
* These parameters allow optional default configuration during
108+
* device initialization. Features are only configured if the
109+
* corresponding @c use_* flag is set.
110+
*/
111+
typedef struct {
112+
i2c_t i2c; /**< I2C bus the device is connected to */
113+
bool use_sqw; /**< enable SQW output on init */
114+
max31343_sqw_freq_t sqw_freq; /**< SQW output frequency */
115+
bool use_temp_automode; /**< configure temp automode on init */
116+
bool temp_automode_enable; /**< enable or disable automode */
117+
max31343_ttsint_t temp_ttsint; /**< temperature conversion interval */
118+
} max31343_params_t;
119+
120+
/**
121+
* @brief Initialize MAX31343 device
122+
*
123+
* This function initializes the device and checks the Oscillator Stop Flag (OSF).
124+
* If OSF is set (indicating the oscillator was stopped, e.g., after power loss),
125+
* the current time may be invalid and should be set using max31343_set_time().
126+
* The OSF flag is automatically cleared when the time registers are written.
127+
*
128+
* @param[out] dev device descriptor
129+
* @param[in] params device parameters
130+
*
131+
* @retval 0 Success
132+
* @retval -EINVAL Invalid argument (NULL pointer)
133+
* @retval -EIO I2C communication error
134+
* @retval -ENODATA Oscillator was stopped; time is invalid.
135+
* Call max31343_set_time() before using max31343_get_time().
136+
*
137+
* @note After power-on or if the oscillator was stopped, the caller should
138+
* check if the time is valid and set it if necessary.
139+
*/
140+
int max31343_init(max31343_t *dev, const max31343_params_t *params);
141+
142+
/**
143+
* @brief Read current time from device
144+
*
145+
* @param[in] dev device descriptor
146+
* @param[out] time time structure to fill
147+
*
148+
* @retval 0 Success
149+
* @retval -EIO I2C communication error or invalid time read from device
150+
*/
151+
int max31343_get_time(const max31343_t *dev, struct tm *time);
152+
153+
/**
154+
* @brief Set current time on device
155+
*
156+
* @param[in] dev device descriptor
157+
* @param[in] time time structure to set
158+
*
159+
* @retval 0 Success
160+
* @retval -ERANGE Time values are out of supported range (year must be 2000-2099)
161+
* @retval -EIO I2C communication error
162+
*/
163+
int max31343_set_time(const max31343_t *dev, const struct tm *time);
164+
165+
/**
166+
* @brief Enable RTC oscillator (power on timekeeping).
167+
*
168+
* Sets ENOSC bit in RTC_CFG1.
169+
*
170+
* @param[in] dev device descriptor
171+
*
172+
* @retval 0 Success
173+
* @retval -EIO I2C communication error
174+
*/
175+
int max31343_poweron(const max31343_t *dev);
176+
177+
/**
178+
* @brief Disable RTC oscillator (stop timekeeping).
179+
*
180+
* Clears ENOSC bit in RTC_CFG1.
181+
*
182+
* @param[in] dev device descriptor
183+
*
184+
* @retval 0 Success
185+
* @retval -EIO I2C communication error
186+
*/
187+
int max31343_poweroff(const max31343_t *dev);
188+
189+
/**
190+
* @brief Set alarm time registers.
191+
*
192+
* Writes the alarm time to the device and disables the alarm interrupt (A1IE).
193+
* The alarm interrupt is NOT automatically re-enabled by this function.
194+
*
195+
* @param[in] dev device descriptor
196+
* @param[in] time alarm time to store
197+
*
198+
* @retval 0 Success
199+
* @retval -ERANGE Time values are out of supported range (year must be 2000-2099)
200+
* @retval -EIO I2C communication error
201+
*
202+
* @note Per datasheet requirement, the alarm interrupt (A1IE) must not be
203+
* enabled until at least 1 second after calling this function.
204+
* Use max31343_alarm_enable() after the required delay.
205+
*/
206+
int max31343_set_alarm(const max31343_t *dev, const struct tm *time);
207+
208+
/**
209+
* @brief Get the currently configured alarm time.
210+
*
211+
* @param[in] dev device descriptor
212+
* @param[out] time receives the stored alarm time
213+
*
214+
* @retval 0 Success
215+
* @retval -ENOENT No alarm is set (mask bits are active)
216+
* @retval -EIO I2C communication error
217+
*/
218+
int max31343_get_alarm(const max31343_t *dev, struct tm *time);
219+
220+
/**
221+
* @brief Enable or disable the alarm interrupt.
222+
*
223+
* Controls the alarm interrupt enable bit (A1IE) in the interrupt enable register.
224+
*
225+
* @param[in] dev device descriptor
226+
* @param[in] enable true to enable alarm interrupt, false to disable
227+
*
228+
* @retval 0 Success
229+
* @retval -EIO I2C communication error
230+
*
231+
* @note When enabling the alarm after max31343_set_alarm(), wait at least
232+
* 1 second as required by the datasheet before calling this function.
233+
*/
234+
int max31343_alarm_enable(const max31343_t *dev, bool enable);
235+
236+
/**
237+
* @brief Clear the alarm.
238+
*
239+
* Disables the alarm interrupt (A1IE) and reads the status register
240+
* to clear the alarm flag (A1F).
241+
*
242+
* @param[in] dev device descriptor
243+
*
244+
* @retval 0 Success
245+
* @retval -EIO I2C communication error
246+
*/
247+
int max31343_clear_alarm(const max31343_t *dev);
248+
249+
/**
250+
* @brief Configure the square-wave (SQW) output frequency.
251+
*
252+
* This function enables and configures the SQW output according
253+
* to the selected frequency.
254+
*
255+
* @param[in] dev device descriptor
256+
* @param[in] freq square-wave frequency selection
257+
*
258+
* @retval 0 Success
259+
* @retval -ERANGE Invalid frequency value
260+
* @retval -EIO I2C communication error
261+
*/
262+
int max31343_set_sqw(const max31343_t *dev, max31343_sqw_freq_t freq);
263+
264+
/**
265+
* @brief Read temperature in centi-degrees Celsius (°C * 100)
266+
*
267+
* Example: 84.75°C -> 8475
268+
*
269+
* @param[in] dev device descriptor
270+
* @param[out] temp_centi temperature in centi-degC
271+
*
272+
* @retval 0 Success
273+
* @retval -EIO I2C communication error
274+
*/
275+
int max31343_get_temp_centi_c(const max31343_t *dev, int16_t *temp_centi);
276+
/**
277+
* @brief Configure and enable or disable the trickle charger.
278+
*
279+
* When @p enable is true the TCHE field is set to 0x5 (the only magic
280+
* value that activates the charger per the datasheet) and D_TRICKLE is
281+
* composed from @p diode and @p res.
282+
* When @p enable is false the entire register is written as 0x00,
283+
* disabling the charger regardless of the other parameters.
284+
*
285+
* @param[in] dev Device descriptor.
286+
* @param[in] enable true = enable trickle charger,
287+
* false = disable trickle charger.
288+
* @param[in] diode Diode path selection (ignored when @p enable is false).
289+
* @param[in] res Resistor selection (ignored when @p enable is false).
290+
*
291+
* @retval 0 Success
292+
* @retval -EIO I2C communication error
293+
*/
294+
int max31343_set_trickle_charger(const max31343_t *dev,
295+
bool enable,
296+
max31343_trickle_diode_t diode,
297+
max31343_trickle_res_t res);
298+
299+
/**
300+
* @brief Configure automatic temperature conversion mode and interval.
301+
*
302+
* @param[in] dev device descriptor
303+
* @param[in] enable true to set AUTOMODE=1, false to set AUTOMODE=0
304+
* @param[in] ttsint value written to TS_Config[5:3]
305+
*
306+
* @retval 0 Success
307+
* @retval -ERANGE Invalid ttsint value
308+
* @retval -EIO I2C communication error
309+
*/
310+
int max31343_temp_set_automode(const max31343_t *dev, bool enable, max31343_ttsint_t ttsint);
311+
312+
/** @} */
313+
314+
#ifdef __cplusplus
315+
}
316+
#endif

drivers/max31343/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
MODULE = max31343
2+
include $(RIOTBASE)/Makefile.base

drivers/max31343/Makefile.dep

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
FEATURES_REQUIRED += periph_i2c
2+
3+
# The Makefile.dep is evaluated multiple times, fall back to the internal RTC
4+
# if the `periph_rtc_external` has not been set yet.
5+
ifneq (,$(filter periph_rtc, $(FEATURES_PROVIDED)))
6+
ifeq (,$(filter periph_rtc_external, $(FEATURES_PROVIDED)))
7+
CFLAGS += -DUSE_INTERNAL_RTC
8+
endif
9+
else
10+
FEATURES_PROVIDED += periph_rtc
11+
endif
12+
13+
# avoid duplicated entries
14+
ifeq (,$(filter periph_rtc_external, $(FEATURES_PROVIDED)))
15+
FEATURES_PROVIDED += periph_rtc_external
16+
endif

drivers/max31343/Makefile.include

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
USEMODULE_INCLUDES_max31343 := $(LAST_MAKEFILEDIR)/include
2+
USEMODULE_INCLUDES += $(USEMODULE_INCLUDES_max31343)

0 commit comments

Comments
 (0)