px-fwlib 0.10.0
Cross-platform embedded library and documentation for 8/16/32-bit microcontrollers generated with Doxygen 1.9.2
px_m41t00.c
1/* =============================================================================
2 ____ ___ ____ ___ _ _ ___ __ __ ___ __ __ TM
3 | _ \ |_ _| / ___| / _ \ | \ | | / _ \ | \/ | |_ _| \ \/ /
4 | |_) | | | | | | | | | | \| | | | | | | |\/| | | | \ /
5 | __/ | | | |___ | |_| | | |\ | | |_| | | | | | | | / \
6 |_| |___| \____| \___/ |_| \_| \___/ |_| |_| |___| /_/\_\
7
8 Copyright (c) 2006 Pieter Conradie <https://piconomix.com>
9
10 License: MIT
11 https://github.com/piconomix/px-fwlib/blob/master/LICENSE.md
12
13 Title: px_m41t00.h : Driver for an ST M41T00 Real Time Clock
14 Author(s): Pieter Conradie
15 Creation Date: 2007-03-31
16
17============================================================================= */
18
19/* _____STANDARD INCLUDES____________________________________________________ */
20
21/* _____PROJECT INCLUDES_____________________________________________________ */
22#include "px_rtc_m41t00.h"
23#include "px_log.h"
24
25/* _____LOCAL DEFINITIONS____________________________________________________ */
26PX_LOG_NAME("m41t00");
27
28/// BCD Date/Time
29typedef struct
30{
31 uint8_t sec;
32 uint8_t min;
33 uint8_t century_hours;
34 uint8_t day_of_week;
35 uint8_t day_of_month;
36 uint8_t month;
37 uint8_t year;
39
40/// M41T00 Data
41typedef struct
42{
43 uint8_t adr;
44 px_m41t00_bcd_time_t bcd_time;
45 uint8_t control;
47
48/// Stop bit
49#define PX_M41T00_ST_ADR 0x00
50#define PX_M41T00_ST_BIT (1 << 7)
51
52/// Century Enable Bit
53#define PX_M41T00_CEB_ADR 0x02
54#define PX_M41T00_CEB_BIT (1 << 7)
55
56/// Century Bit
57#define PX_M41T00_CB_ADR 0x02
58#define PX_M41T00_CB_BIT (1 << 6)
59
60// Control register map
61
62/// Output level bit
63#define PX_M41T00_OUT_BIT (1 << 7)
64
65/// Frequency test bit
66#define PX_M41T00_FT_BIT (1 << 6)
67
68/// Sign bit
69#define PX_M41T00_S_BIT (1 << 5)
70
71/// Clock calibration
72#define PX_M41T00_CAL_MASK 0x1F
73
74/* _____MACROS_______________________________________________________________ */
75
76/* _____GLOBAL VARIABLES_____________________________________________________ */
77
78/* _____LOCAL VARIABLES______________________________________________________ */
79static px_i2c_handle * px_m41t00_i2c_handle;
80static px_m41t00_data_t px_m41t00_data;
81
82/* _____LOCAL FUNCTION DECLARATIONS__________________________________________ */
83
84/* _____LOCAL FUNCTIONS______________________________________________________ */
85static uint8_t px_m41t00_bcd_to_byte(uint8_t bcd_val)
86{
87 return (bcd_val & 0xf) + ((bcd_val & 0xf0) >> 4) * 10;
88}
89
90static uint8_t px_m41t00_byte_to_bcd(uint8_t byte_val)
91{
92 return (byte_val % 10) + ((byte_val / 10) << 4);
93}
94
95static bool px_m41t00_rd_data(void)
96{
97 // Set address to start reading from
98 px_m41t00_data.adr = 0;
99 // Send address to read
100 if(!px_i2c_wr(px_m41t00_i2c_handle, &px_m41t00_data.adr, 1, PX_I2C_FLAG_START_AND_END))
101 {
102 PX_LOG_E("Unable to write address");
103 return false;
104 }
105 // Read data
106 if(!px_i2c_rd(px_m41t00_i2c_handle,
107 &px_m41t00_data.bcd_time,
108 sizeof(px_m41t00_data.bcd_time) + sizeof(px_m41t00_data.control),
110 {
111 PX_LOG_E("Unable to read data");
112 return false;
113 }
114 // Success
115 return true;
116}
117
118static bool px_m41t00_wr_data(void)
119{
120 // Set address to start writing to
121 px_m41t00_data.adr = 0;
122 // Write data
123 if(!px_i2c_wr(px_m41t00_i2c_handle,
124 &px_m41t00_data,
125 sizeof(px_m41t00_data),
127 {
128 PX_LOG_E("Unable to write data");
129 return false;
130 }
131 // Success
132 return true;
133}
134
135/* _____GLOBAL FUNCTIONS_____________________________________________________ */
136void px_m41t00_init(px_i2c_handle_t * px_i2c_handle)
137{
138 px_m41t00_i2c_handle = px_i2c_handle;
139}
140
142{
143 uint8_t i;
144
145 // Populate with default values
146 px_rtc_time->sec = 0;
147 px_rtc_time->min = 0;
148 px_rtc_time->hour = 0;
149 px_rtc_time->day_of_week = 1;
150 px_rtc_time->day_of_month = 1;
151 px_rtc_time->month = 1;
152 px_rtc_time->year = 7;
153 // Read RTC data
154 if(!px_m41t00_rd_data())
155 {
156 return false;
157 }
158 // See if timer has been stopped
159 if(((uint8_t *)(&px_m41t00_data.bcd_time))[PX_M41T00_ST_ADR] & PX_M41T00_ST_BIT)
160 {
161 PX_LOG_E("RTC has been stopped!");
162 return false;
163 }
164 // Mask off century bits
165 ((uint8_t *)(&px_m41t00_data.bcd_time))[PX_M41T00_CEB_ADR] &= ~PX_M41T00_CEB_BIT;
166 ((uint8_t *)(&px_m41t00_data.bcd_time))[PX_M41T00_CB_ADR] &= ~PX_M41T00_CB_BIT;
167 // Convert to binary format
168 for(i = 0; i < sizeof(*px_rtc_time); i++)
169 {
170 ((uint8_t *)px_rtc_time)[i] = px_m41t00_bcd_to_byte(((uint8_t *)(&px_m41t00_data.bcd_time))[i]);
171 }
172 // Sanity check
173 if((px_rtc_time->month < 1 ) || (px_rtc_time->month > 12)) return false;
174 if((px_rtc_time->day_of_month < 1 ) || (px_rtc_time->day_of_month > 31)) return false;
175 if(px_rtc_time->hour > 23) return false;
176 if(px_rtc_time->min > 59) return false;
177 if(px_rtc_time->sec > 59) return false;
178
179 return true;
180}
181
182bool px_m41t00_set_time(const px_m41t00_time_t * px_rtc_time)
183{
184 int i;
185
186 // Convert to BCD format
187 for(i = 0; i < sizeof(px_m41t00_data.bcd_time); i++)
188 {
189 ((uint8_t *)(&px_m41t00_data.bcd_time))[i] = px_m41t00_byte_to_bcd(((uint8_t *)px_rtc_time)[i]);
190 }
191
192 // Set control bits
193 ((uint8_t *)(&px_m41t00_data.bcd_time))[PX_M41T00_ST_ADR] &= ~PX_M41T00_ST_BIT;
194 ((uint8_t *)(&px_m41t00_data.bcd_time))[PX_M41T00_CEB_ADR] &= ~PX_M41T00_CEB_BIT;
195 ((uint8_t *)(&px_m41t00_data.bcd_time))[PX_M41T00_CB_ADR] &= ~PX_M41T00_CB_BIT;
196
197 px_m41t00_data.control = 0x00;
198
199 return px_m41t00_wr_data();
200}
201
#define PX_LOG_NAME(name)
Macro to declare a log name string once for each file to reduce code size.
Definition: px_log.h:349
#define PX_LOG_E(format,...)
Macro to display a formatted ERROR message.
Definition: px_log.h:377
uint8_t sec
Seconds: 0 to 59.
Definition: px_m41t00.h:55
uint8_t year
Years: 00 to 99.
Definition: px_m41t00.h:61
uint8_t hour
Hours: 0 to 23.
Definition: px_m41t00.h:57
uint8_t day_of_month
Days of Month: 1 to 31 (depending on month)
Definition: px_m41t00.h:59
uint8_t min
Minutes: 0 to 59.
Definition: px_m41t00.h:56
uint8_t month
Months: 1 to 12.
Definition: px_m41t00.h:60
uint8_t day_of_week
Day of Week: 1 to 7.
Definition: px_m41t00.h:58
bool px_m41t00_get_time(px_m41t00_time_t *px_rtc_time)
Get RTC time using I2C driver.
Definition: px_m41t00.c:141
bool px_m41t00_set_time(const px_m41t00_time_t *px_rtc_time)
Set RTC time using I2C driver.
Definition: px_m41t00.c:182
void px_m41t00_init(px_i2c_handle_t *px_i2c_handle)
Initialise driver.
Definition: px_m41t00.c:136
Structure to store time and date.
Definition: px_m41t00.h:54
#define PX_I2C_FLAG_START_AND_STOP
Begin and finish an I2C transaction with a START and STOP condition.
Definition: px_i2c.h:93
bool px_i2c_rd(px_i2c_handle_t *handle, void *data, size_t nr_of_bytes, uint8_t flags)
Perform an I2C read transaction with an I2C slave.
Definition: px_i2c.c:430
#define PX_I2C_FLAG_REP_START_AND_STOP
Begin and finish an I2C transaction with a REP START and STOP condition.
Definition: px_i2c.h:97
#define PX_I2C_FLAG_START_AND_END
Begin and finish an I2C transaction with a START and END condition.
Definition: px_i2c.h:95
bool px_i2c_wr(px_i2c_handle_t *handle, const void *data, size_t nr_of_bytes, uint8_t flags)
Perform an I2C write transaction with an I2C slave.
Definition: px_i2c.c:240
Define I2C handle for a slave.
Definition: px_i2c.h:104
BCD Date/Time.
Definition: px_m41t00.c:30
M41T00 Data.
Definition: px_m41t00.c:42