Skip to content

Commit dc2a33f

Browse files
committed
Merge pull request #3 from GabrielNotman/master
Added Epoch Support
2 parents 420ef5e + 07ef730 commit dc2a33f

File tree

2 files changed

+107
-14
lines changed

2 files changed

+107
-14
lines changed

src/RTCZero.cpp

+86-2
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@
1919

2020
#include "RTCZero.h"
2121

22+
#define EPOCH_TIME_OFF 946684800 // This is 1st January 2000, 00:00:00 in epoch time
23+
24+
static const uint8_t daysInMonth[12] = { 31,28,31,30,31,30,31,31,30,31,30,31 };
25+
2226
voidFuncPtr RTC_callBack = NULL;
2327

2428
void RTCZero::begin()
@@ -46,7 +50,9 @@ void RTCZero::begin()
4650
tmp_reg |= RTC_MODE2_CTRL_MODE_CLOCK; // set clock operating mode
4751
tmp_reg |= RTC_MODE2_CTRL_PRESCALER_DIV1024; // set prescaler to 1024 for MODE2
4852
tmp_reg &= ~RTC_MODE2_CTRL_MATCHCLR; // disable clear on match
49-
tmp_reg |= RTC_MODE2_CTRL_CLKREP; // 24h time representation
53+
54+
//According to the datasheet RTC_MODE2_CTRL_CLKREP = 0 for 24h
55+
tmp_reg &= ~RTC_MODE2_CTRL_CLKREP; // 24h time representation
5056

5157
RTC->MODE2.READREQ.reg &= ~RTC_READREQ_RCONT; // disable continuously mode
5258

@@ -102,7 +108,9 @@ void RTCZero::detachInterrupt()
102108

103109
void RTCZero::standbyMode()
104110
{
105-
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
111+
// Entering standby mode when connected
112+
// via the native USB port causes issues.
113+
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
106114
__WFI();
107115
}
108116

@@ -286,6 +294,82 @@ void RTCZero::setAlarmDate(uint8_t day, uint8_t month, uint8_t year)
286294
setAlarmYear(year);
287295
}
288296

297+
uint32_t RTCZero::getEpoch()
298+
{
299+
return getY2kEpoch() + EPOCH_TIME_OFF;
300+
}
301+
302+
uint32_t RTCZero::getY2kEpoch()
303+
{
304+
uint16_t days = RTC->MODE2.CLOCK.bit.DAY;
305+
days = days > 0 ? days : 1;
306+
uint8_t months = RTC->MODE2.CLOCK.bit.MONTH;
307+
uint16_t years = RTC->MODE2.CLOCK.bit.YEAR;
308+
309+
for (uint8_t i = 1; i < months; ++i) {
310+
days += daysInMonth[i - 1];
311+
}
312+
313+
if ((months > 2) && (years % 4 == 0)) {
314+
++days;
315+
}
316+
days += 365 * years + (years + 3) / 4 - 1;
317+
318+
uint8_t hours = RTC->MODE2.CLOCK.bit.HOUR;
319+
320+
return ((days * 24 + hours) * 60 +
321+
RTC->MODE2.CLOCK.bit.MINUTE) * 60 + RTC->MODE2.CLOCK.bit.SECOND;
322+
}
323+
324+
void RTCZero::setEpoch(uint32_t ts)
325+
{
326+
if (ts < EPOCH_TIME_OFF) {
327+
setY2kEpoch(0);
328+
}
329+
else {
330+
setY2kEpoch(ts - EPOCH_TIME_OFF);
331+
}
332+
}
333+
334+
void RTCZero::setY2kEpoch(uint32_t ts)
335+
{
336+
RTC->MODE2.CLOCK.bit.SECOND = ts % 60;
337+
ts /= 60;
338+
RTC->MODE2.CLOCK.bit.MINUTE = ts % 60;
339+
ts /= 60;
340+
RTC->MODE2.CLOCK.bit.HOUR = ts % 24;
341+
342+
uint16_t days = ts / 24;
343+
uint8_t months;
344+
uint8_t years;
345+
346+
uint8_t leap;
347+
348+
// Calculate years
349+
for (years = 0; ; ++years) {
350+
leap = years % 4 == 0;
351+
if (days < 365 + leap)
352+
break;
353+
days -= 365 + leap;
354+
}
355+
356+
// Calculate months
357+
for (months = 1; ; ++months) {
358+
uint8_t daysPerMonth = daysInMonth[months - 1];
359+
if (leap && months == 2)
360+
++daysPerMonth;
361+
if (days < daysPerMonth)
362+
break;
363+
days -= daysPerMonth;
364+
}
365+
366+
RTC->MODE2.CLOCK.bit.YEAR = years;
367+
RTC->MODE2.CLOCK.bit.MONTH = months;
368+
RTC->MODE2.CLOCK.bit.DAY = days + 1;
369+
while (RTCisSyncing())
370+
;
371+
}
372+
289373
/*
290374
* Private Utility Functions
291375
*/

src/RTCZero.h

+21-12
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,8 @@
1717
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1818
*/
1919

20-
#pragma once
21-
22-
#define H24 1
23-
#define H12 0
20+
#ifndef RTC_ZERO_H
21+
#define RTC_ZERO_H
2422

2523
#include "Arduino.h"
2624

@@ -31,13 +29,13 @@ class RTCZero {
3129

3230
enum Alarm_Match: uint8_t // Should we have this enum or just use the identifiers from /component/rtc.h ?
3331
{
34-
MATCH_OFF = RTC_MODE2_MASK_SEL_OFF_Val,
35-
MATCH_SS = RTC_MODE2_MASK_SEL_SS_Val,
36-
MATCH_MMSS = RTC_MODE2_MASK_SEL_MMSS_Val,
37-
MATCH_HHMMSS = RTC_MODE2_MASK_SEL_HHMMSS_Val,
38-
MATCH_DHHMMSS = RTC_MODE2_MASK_SEL_DDHHMMSS_Val,
39-
MATCH_MMDDHHMMSS = RTC_MODE2_MASK_SEL_MMDDHHMMSS_Val,
40-
MATCH_YYMMDDHHMMSS = RTC_MODE2_MASK_SEL_YYMMDDHHMMSS_Val
32+
MATCH_OFF = RTC_MODE2_MASK_SEL_OFF_Val, // Never
33+
MATCH_SS = RTC_MODE2_MASK_SEL_SS_Val, // Every Minute
34+
MATCH_MMSS = RTC_MODE2_MASK_SEL_MMSS_Val, // Every Hour
35+
MATCH_HHMMSS = RTC_MODE2_MASK_SEL_HHMMSS_Val, // Every Day
36+
MATCH_DHHMMSS = RTC_MODE2_MASK_SEL_DDHHMMSS_Val, // Every Month
37+
MATCH_MMDDHHMMSS = RTC_MODE2_MASK_SEL_MMDDHHMMSS_Val, // Every Year
38+
MATCH_YYMMDDHHMMSS = RTC_MODE2_MASK_SEL_YYMMDDHHMMSS_Val // Once, on a specific date and a specific time
4139
};
4240

4341
RTCZero() {};
@@ -56,14 +54,16 @@ class RTCZero {
5654
uint8_t getSeconds();
5755
uint8_t getMinutes();
5856
uint8_t getHours();
57+
uint8_t getAM_PM();
5958

6059
uint8_t getDay();
6160
uint8_t getMonth();
6261
uint8_t getYear();
63-
62+
6463
uint8_t getAlarmSeconds();
6564
uint8_t getAlarmMinutes();
6665
uint8_t getAlarmHours();
66+
uint8_t getAlarmAM_PM();
6767

6868
uint8_t getAlarmDay();
6969
uint8_t getAlarmMonth();
@@ -91,6 +91,13 @@ class RTCZero {
9191
void setAlarmYear(uint8_t year);
9292
void setAlarmDate(uint8_t day, uint8_t month, uint8_t year);
9393

94+
/* Epoch Functions */
95+
96+
uint32_t getEpoch();
97+
uint32_t getY2kEpoch();
98+
void setEpoch(uint32_t ts);
99+
void setY2kEpoch(uint32_t ts);
100+
94101
private:
95102
void config32kOSC(void);
96103
bool RTCisSyncing(void);
@@ -99,3 +106,5 @@ class RTCZero {
99106
void RTCreset();
100107
void RTCresetRemove();
101108
};
109+
110+
#endif // RTC_ZERO_H

0 commit comments

Comments
 (0)