|
19 | 19 |
|
20 | 20 | #include "RTCZero.h"
|
21 | 21 |
|
| 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 | + |
22 | 26 | voidFuncPtr RTC_callBack = NULL;
|
23 | 27 |
|
24 | 28 | void RTCZero::begin()
|
@@ -46,7 +50,9 @@ void RTCZero::begin()
|
46 | 50 | tmp_reg |= RTC_MODE2_CTRL_MODE_CLOCK; // set clock operating mode
|
47 | 51 | tmp_reg |= RTC_MODE2_CTRL_PRESCALER_DIV1024; // set prescaler to 1024 for MODE2
|
48 | 52 | 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 |
50 | 56 |
|
51 | 57 | RTC->MODE2.READREQ.reg &= ~RTC_READREQ_RCONT; // disable continuously mode
|
52 | 58 |
|
@@ -102,7 +108,9 @@ void RTCZero::detachInterrupt()
|
102 | 108 |
|
103 | 109 | void RTCZero::standbyMode()
|
104 | 110 | {
|
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; |
106 | 114 | __WFI();
|
107 | 115 | }
|
108 | 116 |
|
@@ -286,6 +294,82 @@ void RTCZero::setAlarmDate(uint8_t day, uint8_t month, uint8_t year)
|
286 | 294 | setAlarmYear(year);
|
287 | 295 | }
|
288 | 296 |
|
| 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 | + |
289 | 373 | /*
|
290 | 374 | * Private Utility Functions
|
291 | 375 | */
|
|
0 commit comments