LED clock
 All Files Functions Variables Macros Groups Pages
rtc_ds1307.c
Go to the documentation of this file.
1 /* This program is free software: you can redistribute it and/or modify
2  * it under the terms of the GNU General Public License as published by
3  * the Free Software Foundation, either version 3 of the License, or
4  * (at your option) any later version.
5  *
6  * This program is distributed in the hope that it will be useful,
7  * but WITHOUT ANY WARRANTY; without even the implied warranty of
8  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9  * GNU General Public License for more details.
10  *
11  * You should have received a copy of the GNU General Public License
12  * along with this program. If not, see <http://www.gnu.org/licenses/>.
13  *
14  */
23 /* standard libraries */
24 #include <stdint.h> // standard integer types
25 #include <stdio.h> // standard I/O facilities
26 #include <stdlib.h> // general utilities
27 
28 /* STM32 (including CM3) libraries */
29 #include <libopencm3/stm32/rcc.h> // real-time control clock library
30 #include <libopencm3/stm32/gpio.h> // general purpose input output library
31 #include <libopencm3/stm32/i2c.h> // I2C library
32 #include <libopencm3/cm3/nvic.h> // interrupt handler
33 #include <libopencmsis/core_cm3.h> // Cortex M3 utilities
34 
35 #include "global.h" // global utilities
36 #include "rtc_ds1307.h" // RTC header and definitions
37 
42 #define I2C I2C1
43 #define I2C_RCC RCC_I2C1
44 #define I2C_PORT GPIOB
45 #define I2C_PIN_SDA GPIO_I2C1_SDA
46 #define I2C_PIN_SCL GPIO_I2C1_SCL
48 #define I2C_ADDR 0x68
50 #if defined(SQUARE_WAVE_EXTI) && defined(SQUARE_WAVE_IRQ) && defined(SQUARE_WAVE_ISR) && defined(SQUARE_WAVE_HANDLING) && SQUARE_WAVE_HANDLING
51 volatile bool square_wave_flag = false;
52 #endif
53 
54 void rtc_setup(void)
55 {
56  /* enable peripheral */
57  rcc_periph_clock_enable(RCC_AFIO); // enable clock for alternate function
58  rcc_periph_clock_enable(I2C_RCC); // enable clock for I2C peripheral
59  gpio_set_mode(I2C_PORT, GPIO_MODE_OUTPUT_10_MHZ, GPIO_CNF_OUTPUT_ALTFN_OPENDRAIN, I2C_PIN_SDA | I2C_PIN_SCL); // setup I2C pin
60 
61  /* configure I2C peripheral (see RM008 26.3.3, I2C master) */
62  i2c_reset(I2C); // reset configuration
63  i2c_peripheral_disable(I2C); // I2C needs to be disable to be configured
64  i2c_set_clock_frequency(I2C, rcc_apb1_frequency/1E6); // configure the peripheral clock to the APB1 freq (where it is connected to)
65  i2c_set_standard_mode(I2C); // the DS1307 has a maximum I2C SCL freq if 100 kHz (corresponding to the standard mode)
66  i2c_set_ccr(I2C, rcc_apb1_frequency/(100E3*2)); // set Thigh/Tlow to generate frequency of 100 kHz
67  i2c_set_trise(I2C, rcc_apb1_frequency/1E6); // max rise time for 100 kHz is 1000 ns (~1 MHz)
68  i2c_peripheral_enable(I2C); // enable I2C after configuration completed
69 
70  /* setup square wave interrupt input */
71 #if defined(SQUARE_WAVE_RCC) && defined(SQUARE_WAVE_PORT) && defined(SQUARE_WAVE_PIN)
72  rcc_periph_clock_enable(SQUARE_WAVE_RCC); // enable GPIO peripheral
73  gpio_set_mode(SQUARE_WAVE_PORT, GPIO_MODE_INPUT, GPIO_CNF_INPUT_PULL_UPDOWN, SQUARE_WAVE_PIN); // set pin to input with pull up
74  gpio_set(SQUARE_WAVE_PORT, SQUARE_WAVE_PIN); // pull up since the square wave output is open drain
75 #if defined(SQUARE_WAVE_EXTI) && defined(SQUARE_WAVE_IRQ) && defined(SQUARE_WAVE_ISR)
76  rcc_periph_clock_enable(RCC_AFIO); // enable alternate function clock for external interrupt
77  exti_select_source(SQUARE_WAVE_EXTI, SQUARE_WAVE_PORT); // mask external interrupt of this pin only for this port
78  exti_set_trigger(SQUARE_WAVE_EXTI, EXTI_TRIGGER_FALLING); // trigger on falling
79  exti_enable_request(SQUARE_WAVE_EXTI); // enable external interrupt
80  nvic_enable_irq(SQUARE_WAVE_IRQ); // enable interrupt
81 #endif
82 #endif
83 
84 }
85 
92 static bool rtc_read_memory(uint8_t addr, uint8_t* data, size_t len)
93 {
94  bool to_return = false; // return if read succeeded
95  if (data==NULL || len==0) { // verify there it data to be read
96  goto error;
97  }
98  i2c_send_start(I2C); // send start condition to start transaction
99  while (!(I2C_SR1(I2C) & I2C_SR1_SB)); // wait until start condition is transmitted
100  if (!(I2C_SR2(I2C) & I2C_SR2_MSL)) { // verify if in master mode
101  goto error;
102  }
103  i2c_send_7bit_address(I2C, I2C_ADDR, I2C_WRITE); // select slave
104  while (!(I2C_SR1(I2C) & I2C_SR1_ADDR)); // wait until address is transmitted
105  if (!((I2C_SR2(I2C) & I2C_SR2_TRA))) { // verify we are in transmit mode (and read SR2 to clear ADDR)
106  goto error;
107  }
108  i2c_send_data(I2C, addr); // send memory address we want to read
109  while (!(I2C_SR1(I2C) & I2C_SR1_TxE)); // wait until byte has been transmitted
110  i2c_send_start(I2C); // send restart condition to switch from write to read mode
111  while (!(I2C_SR1(I2C) & I2C_SR1_SB)); // wait until start condition is transmitted
112  i2c_send_7bit_address(I2C, I2C_ADDR, I2C_READ); // select slave
113  while (!(I2C_SR1(I2C) & I2C_SR1_ADDR)); // wait until address is transmitted
114  if ((I2C_SR2(I2C) & I2C_SR2_TRA)) { // verify we are in read mode (and read SR2 to clear ADDR)
115  goto error;
116  }
117  for (size_t i=0; i<len; i++) { // read bytes
118  if (i==len-1) { // prepare to sent NACK for last byte
119  i2c_disable_ack(I2C); // NACK received to stop slave transmission
120  i2c_send_stop(I2C); // send STOP after receiving byte
121  } else {
122  i2c_enable_ack(I2C); // ACK received byte to continue slave transmission
123  }
124  while (!(I2C_SR1(I2C) & I2C_SR1_RxNE)); // wait until byte has been received
125  data[i] = i2c_get_data(I2C); // read received byte
126  }
127  to_return = true;
128 error:
129  if (I2C_SR2(I2C) & I2C_SR2_BUSY) { // release bus if busy
130  i2c_send_stop(I2C); // send stop to release bus
131  }
132  while (I2C_SR2(I2C) & I2C_SR2_MSL); // wait until bus released (non master mode)
133  return to_return;
134 }
135 
137 {
138  uint8_t data[1] = {0}; // to read data over I2C
139  rtc_read_memory(0, data, LENGTH(data)); // read a single byte containing CH value
140  return data[0]&0x80; // return CH bit value to indicate if oscillator is disabled
141 }
142 
143 uint16_t rtc_read_square_wave(void)
144 {
145  uint16_t to_return = 0; // square wave frequency to return (in Hz)
146  uint8_t data[1] = {0}; // to read data over I2C
147  const uint16_t rtc_rs[] = {1, 4096, 8192, 32768}; // RS1/RS0 values
148  rtc_read_memory(7, data, LENGTH(data)); // read a single byte containing control register
149  if (data[0]&0x10) { // verify if the square wave is enabled (SQWE)
150  to_return = rtc_rs[data[0]&0x03]; // read RS1/RS0 and get value
151  } else {
152  to_return = 0; // square wave output is disabled
153  }
154  return to_return;
155 }
156 
157 uint8_t rtc_read_seconds(void)
158 {
159  uint8_t to_return = 0; // seconds to return
160  uint8_t data[1] = {0}; // to read data over I2C
161  rtc_read_memory(0, data, LENGTH(data)); // read a single byte containing seconds value
162  to_return = ((data[0]&0x70)>>4)*10+(data[0]&0x0f); // convert BCD coding into seconds
163  return to_return;
164 }
165 
166 uint8_t rtc_read_minutes(void)
167 {
168  uint8_t to_return = 0; // minutes to return
169  uint8_t data[1] = {0}; // to read data over I2C
170  rtc_read_memory(1, data, LENGTH(data)); // read a single byte containing minutes value
171  to_return = (data[0]>>4)*10+(data[0]&0x0f); // convert BCD coding into minutes
172  return to_return;
173 }
174 
175 uint8_t rtc_read_hours(void)
176 {
177  uint8_t to_return = 0; // hours to return
178  uint8_t data[1] = {0}; // to read data over I2C
179  rtc_read_memory(2, data, LENGTH(data)); // read a single byte containing hours value
180  if (data[0]&0x40) { // 12 hour mode
181  if (data[0]&0x02) { // PM
182  to_return += 12; // add the 12 hours
183  }
184  to_return += ((data[0]&0x10)>>4)*10; // convert BCD coding into hours (first digit)
185  } else {
186  to_return = ((data[0]&0x30)>>4)*10; // convert BCD coding into hours (first digit)
187  }
188  to_return += (data[0]&0x0f); // convert BCD coding into hours (second digit)
189  return to_return;
190 }
191 
192 uint8_t rtc_read_day(void)
193 {
194  uint8_t to_return = 0; // day to return
195  uint8_t data[1] = {0}; // to read data over I2C
196  rtc_read_memory(3, data, LENGTH(data)); // read a single byte containing day value
197  to_return = (data[0]&0x07); // convert BCD coding into days
198  return to_return;
199 }
200 
201 uint8_t rtc_read_date(void)
202 {
203  uint8_t to_return = 0; // date to return
204  uint8_t data[1] = {0}; // to read data over I2C
205  rtc_read_memory(4, data, LENGTH(data)); // read a single byte containing date value
206  to_return = ((data[0]&0x30)>>4)*10+(data[0]&0x0f); // convert BCD coding into date
207  return to_return;
208 }
209 
210 uint8_t rtc_read_month(void)
211 {
212  uint8_t to_return = 0; // month to return
213  uint8_t data[1] = {0}; // to read data over I2C
214  rtc_read_memory(5, data, LENGTH(data)); // read a single byte containing month value
215  to_return = ((data[0]&0x10)>>4)*10+(data[0]&0x0f); // convert BCD coding into month
216  return to_return;
217 }
218 
219 uint16_t rtc_read_year(void)
220 {
221  uint16_t to_return = 2000; // year to return
222  uint8_t data[1] = {0}; // to read data over I2C
223  rtc_read_memory(6, data, LENGTH(data)); // read a single byte containing year value
224  to_return += ((data[0]&0xf0)>>4)*10+(data[0]&0x0f); // convert BCD coding into year
225  return to_return;
226 }
227 
228 uint16_t* rtc_read_time(void)
229 {
230  static uint16_t time[7] = {0}; // store time {seconds, minutes, hours, day, date, month, year}
231  uint8_t data[7] = {0}; // to read data over I2C
232  rtc_read_memory(0, data, LENGTH(data)); // read all time bytes
233  time[0] = ((data[0]&0x70)>>4)*10+(data[0]&0x0f); // convert seconds from BCD
234  time[1] = (data[1]>>4)*10+(data[1]&0x0f); // convert minutes from BCD
235  time[2] = 0; // re-initialize hours
236  if (data[2]&0x40) { // 12 hour mode
237  if (data[2]&0x02) { // PM
238  time[2] += 12; // add the 12 hours
239  }
240  time[2] += ((data[2]&0x10)>>4)*10; // convert BCD coding into hours (first digit)
241  } else {
242  time[2] = ((data[2]&0x30)>>4)*10; // convert BCD coding into hours (first digit)
243  }
244  time[2] += (data[2]&0x0f); // convert BCD coding into hours (second digit)
245  time[3] = (data[3]&0x07); // convert BCD coding into days
246  time[4] = ((data[4]&0x30)>>4)*10+(data[4]&0x0f); // convert BCD coding into date
247  time[5] = ((data[5]&0x10)>>4)*10+(data[5]&0x0f); // convert BCD coding into month
248  time[6] = 2000+((data[6]&0xf0)>>4)*10+(data[6]&0x0f); // convert BCD coding into year
249  return time;
250 }
251 
258 static bool rtc_write_memory(uint8_t addr, uint8_t* data, size_t len)
259 {
260  bool to_return = false; // return if read succeeded
261  if (data==NULL || len==0) { // verify there it data to be read
262  goto error;
263  }
264  i2c_send_start(I2C); // send start condition to start transaction
265  while (!(I2C_SR1(I2C) & I2C_SR1_SB)); // wait until start condition is transmitted
266  if (!(I2C_SR2(I2C) & I2C_SR2_MSL)) { // verify if in master mode
267  goto error;
268  }
269  i2c_send_7bit_address(I2C, I2C_ADDR, I2C_WRITE); // select slave
270  while (!(I2C_SR1(I2C) & I2C_SR1_ADDR)); // wait until address is transmitted
271  if (!((I2C_SR2(I2C) & I2C_SR2_TRA))) { // verify we are in transmit mode (and read SR2 to clear ADDR)
272  goto error;
273  }
274  i2c_send_data(I2C, addr); // send memory address we want to read
275  while (!(I2C_SR1(I2C) & I2C_SR1_TxE)); // wait until byte has been transmitted
276  for (size_t i=0; i<len; i++) { // write bytes
277  i2c_send_data(I2C, data[i]); // send byte to be written in memory
278  while (!(I2C_SR1(I2C) & I2C_SR1_TxE)); // wait until byte has been transmitted
279  }
280  to_return = true;
281 error:
282  if (I2C_SR2(I2C) & I2C_SR2_BUSY) { // release bus if busy
283  i2c_send_stop(I2C); // send stop to release bus
284  }
285  while (I2C_SR2(I2C) & I2C_SR2_MSL); // wait until bus released (non master mode)
286  return to_return;
287 }
288 
290 {
291  uint8_t data[1] = {0}; // to write CH value data over I2C
292  rtc_read_memory(0, data, LENGTH(data)); // read seconds with CH value
293  data[0] |= 0x80; // set CH to disable oscillator
294  return rtc_write_memory(0, data, LENGTH(data)); // write current seconds with CH value
295 }
296 
298 {
299  uint8_t data[1] = {0}; // to write CH value data over I2C
300  rtc_read_memory(0, data, LENGTH(data)); // read seconds with CH value
301  data[0] &= 0x7f; // clear CH to enable oscillator
302  return rtc_write_memory(0, data, LENGTH(data)); // write current seconds with CH value
303 }
304 
305 bool rtc_write_square_wave(uint16_t frequency)
306 {
307  uint8_t data[1] = {0}; // to write control register value data over I2C
308  switch (frequency) { // set RS1/RS0 based on frequency
309  case 0:
310  data[0] = 0;
311  break;
312  case 1:
313  data[0] = 0|(1<<4);
314  break;
315  case 4096:
316  data[0] = 1|(1<<4);
317  break;
318  case 8192:
319  data[0] = 2|(1<<4);
320  break;
321  case 32768:
322  data[0] = 3|(1<<4);
323  break;
324  default: // unspecified frequency
325  return false;
326  }
327  return rtc_write_memory(7, data, LENGTH(data)); // write current seconds with CH value
328 }
329 
330 bool rtc_write_seconds(uint8_t seconds)
331 {
332  if (seconds>59) {
333  return false;
334  }
335  uint8_t data[1] = {0}; // to read CH value data and write seconds value over I2C
336  if (!rtc_read_memory(0, data, LENGTH(data))) { // read seconds with CH value
337  return false;
338  }
339  data[0] &= 0x80; // only keep CH flag
340  data[0] |= (((seconds/10)%6)<<4)+(seconds%10); // encode seconds in BCD format
341  return rtc_write_memory(0, data, LENGTH(data)); // write current seconds with previous CH value
342 }
343 
344 bool rtc_write_minutes(uint8_t minutes)
345 {
346  if (minutes>59) {
347  return false;
348  }
349  uint8_t data[1] = {0}; // to write time value
350  data[0] = (((minutes/10)%6)<<4)+(minutes%10); // encode minutes in BCD format
351  return rtc_write_memory(1, data, LENGTH(data)); // write time value on RTC
352 }
353 
354 bool rtc_write_hours(uint8_t hours)
355 {
356  if (hours>24) {
357  return false;
358  }
359  uint8_t data[1] = {0}; // to write time value
360  data[0] = (((hours/10)%3)<<4)+(hours%10); // encode hours in BCD 24h format
361  return rtc_write_memory(2, data, LENGTH(data)); // write time value on RTC
362 }
363 
364 bool rtc_write_day(uint8_t day)
365 {
366  if (day<1 || day>7) {
367  return false;
368  }
369  uint8_t data[1] = {0}; // to write time value
370  data[0] = (day%8); // encode day in BCD format
371  return rtc_write_memory(3, data, LENGTH(data)); // write time value on RTC
372 }
373 
374 bool rtc_write_date(uint8_t date)
375 {
376  if (date<1 || date>31) {
377  return false;
378  }
379  uint8_t data[1] = {0}; // to write time value
380  data[0] = (((date/10)%4)<<4)+(date%10); // encode date in BCD format
381  return rtc_write_memory(4, data, LENGTH(data)); // write time value on RTC
382 }
383 
384 bool rtc_write_month(uint8_t month)
385 {
386  if (month<1 || month>12) {
387  return false;
388  }
389  uint8_t data[1] = {0}; // to write time value
390  data[0] = (((month/10)%2)<<4)+(month%10); // encode month in BCD format
391  return rtc_write_memory(5, data, LENGTH(data)); // write time value on RTC
392 }
393 
394 bool rtc_write_year(uint16_t year)
395 {
396  if (year<2000 || year>2099) {
397  return false;
398  }
399  uint8_t data[1] = {0}; // to write time value
400  data[0] = (((year/10)%10)<<4)+(year%10); // encode year in BCD format
401  return rtc_write_memory(6, data, LENGTH(data)); // write time value on RTC
402 }
403 
404 bool rtc_write_time(uint8_t seconds, uint8_t minutes, uint8_t hours, uint8_t day, uint8_t date, uint8_t month, uint16_t year)
405 {
406  uint8_t data[7] = {0}; // to write all time values
407  // seconds
408  if (seconds>59) {
409  return false;
410  }
411  if (!rtc_read_memory(0, data, 1)) { // read seconds with CH value
412  return false;
413  }
414  data[0] &= 0x80; // only keep CH flag
415  data[0] |= (((seconds/10)%6)<<4)+(seconds%10); // encode seconds in BCD format
416  // minutes
417  if (minutes>59) {
418  return false;
419  }
420  data[1] = (((minutes/10)%6)<<4)+(minutes%10); // encode minutes in BCD format
421  // hours
422  if (hours>24) {
423  return false;
424  }
425  data[2] = (((hours/10)%3)<<4)+(hours%10); // encode hours in BCD 24h format
426  // day
427  if (day<1 || day>7) {
428  return false;
429  }
430  data[3] = (day%8); // encode day in BCD format
431  // date
432  if (date<1 || date>31) {
433  return false;
434  }
435  data[4] = (((date/10)%4)<<4)+(date%10); // encode date in BCD format
436  // month
437  if (month<1 || month>12) {
438  return false;
439  }
440  data[5] = (((month/10)%2)<<4)+(month%10); // encode month in BCD format
441  // year
442  if (year<2000 || year>2099) {
443  return false;
444  }
445  data[6] = (((year/10)%10)<<4)+(year%10); // encode year in BCD format
446 
447  return rtc_write_memory(0, data, LENGTH(data)); // write time values on RTC
448 }
449 
450 #if defined(SQUARE_WAVE_EXTI) && defined(SQUARE_WAVE_IRQ) && defined(SQUARE_WAVE_ISR) && defined(SQUARE_WAVE_HANDLING) && SQUARE_WAVE_HANDLING
451 
452 void SQUARE_WAVE_ISR(void)
453 {
454  exti_reset_request(SQUARE_WAVE_EXTI); // reset interrupt
455  square_wave_flag = true; // update flag
456 }
457 #endif
458 
bool rtc_oscillator_enable(void)
enable RTC IC oscillator
Definition: rtc_ds1307.c:297
static bool rtc_write_memory(uint8_t addr, uint8_t *data, size_t len)
write memory into RTC IC
Definition: rtc_ds1307.c:258
#define SQUARE_WAVE_PIN
Definition: rtc_ds1307.h:29
bool rtc_write_hours(uint8_t hours)
write hours into RTC IC
Definition: rtc_ds1307.c:354
bool rtc_write_date(uint8_t date)
write date into RTC IC
Definition: rtc_ds1307.c:374
uint8_t rtc_read_month(void)
read month from RTC IC
Definition: rtc_ds1307.c:210
bool rtc_write_seconds(uint8_t seconds)
write seconds into RTC IC
Definition: rtc_ds1307.c:330
uint8_t rtc_read_hours(void)
read hours from RTC IC
Definition: rtc_ds1307.c:175
void rtc_setup(void)
setup communication with RTC IC configure the I2C port defined in the sources
Definition: rtc_ds1307.c:54
bool rtc_write_minutes(uint8_t minutes)
write minutes into RTC IC
Definition: rtc_ds1307.c:344
bool rtc_write_time(uint8_t seconds, uint8_t minutes, uint8_t hours, uint8_t day, uint8_t date, uint8_t month, uint16_t year)
write time into RTC IC
Definition: rtc_ds1307.c:404
#define SQUARE_WAVE_EXTI
Definition: rtc_ds1307.h:30
global definitions and methods
uint8_t rtc_read_seconds(void)
read seconds from RTC IC
Definition: rtc_ds1307.c:157
#define I2C_PIN_SDA
Definition: rtc_ds1307.c:45
bool rtc_write_day(uint8_t day)
write day into RTC IC
Definition: rtc_ds1307.c:364
bool rtc_write_year(uint16_t year)
write year into RTC IC
Definition: rtc_ds1307.c:394
uint16_t rtc_read_year(void)
read year from RTC IC
Definition: rtc_ds1307.c:219
bool rtc_write_month(uint8_t month)
write month into RTC IC
Definition: rtc_ds1307.c:384
bool rtc_write_square_wave(uint16_t frequency)
write square wave output frequency (in Hz)
Definition: rtc_ds1307.c:305
#define I2C_PIN_SCL
Definition: rtc_ds1307.c:46
#define I2C_PORT
Definition: rtc_ds1307.c:44
uint8_t rtc_read_day(void)
read day from RTC IC
Definition: rtc_ds1307.c:192
#define SQUARE_WAVE_RCC
Definition: rtc_ds1307.h:27
uint8_t rtc_read_date(void)
read date from RTC IC
Definition: rtc_ds1307.c:201
#define I2C
Definition: rtc_ds1307.c:42
bool rtc_oscillator_disable(void)
disable RTC IC oscillator
Definition: rtc_ds1307.c:289
uint16_t * rtc_read_time(void)
read time from RTC IC
Definition: rtc_ds1307.c:228
#define LENGTH(x)
Definition: global.h:26
#define I2C_RCC
Definition: rtc_ds1307.c:43
uint8_t rtc_read_minutes(void)
read minutes from RTC IC
Definition: rtc_ds1307.c:166
uint16_t rtc_read_square_wave(void)
read square wave output frequency (in Hz)
Definition: rtc_ds1307.c:143
#define I2C_ADDR
Definition: rtc_ds1307.c:48
#define SQUARE_WAVE_PORT
Definition: rtc_ds1307.h:28
library to communicate with the Maxim DS1307 I2C RTC IC (API)
bool rtc_oscillator_disabled(void)
verify if oscillator is disabled
Definition: rtc_ds1307.c:136
static bool rtc_read_memory(uint8_t addr, uint8_t *data, size_t len)
read memory from RTC IC
Definition: rtc_ds1307.c:92