An attempt to provide a Real Time Clock for the nRF51-DK. This code provides rtc.time and rtc.set_time replacements for the similarly named C standard methods (unimplemented for nRF51-DK last I checked). Not very well tested, but it seems to work for simple applications.

Fork of nrf51_rtc by Francis Schumacher

Committer:
lionello
Date:
Thu Apr 16 11:43:56 2015 +0000
Revision:
3:9be93d7808ca
Parent:
2:e1479e6ffc37
Fixed clock drift by keep tracking of the fractional seconds (ticks)

Who changed what in which revision?

UserRevisionLine numberNew contents of line
fxschumacher 0:3677a016109b 1 #include "nrf51_rtc.h"
fxschumacher 0:3677a016109b 2
lionello 2:e1479e6ffc37 3 #include <mbed.h>
lionello 1:5917157d58c6 4
lionello 3:9be93d7808ca 5 #define LFCLK_FREQUENCY 0x8000
lionello 3:9be93d7808ca 6 #define RTC_COUNTER_MASK 0xFFFFFF
lionello 3:9be93d7808ca 7
lionello 1:5917157d58c6 8 nrf51_rtc rtc;
lionello 1:5917157d58c6 9
lionello 1:5917157d58c6 10
fxschumacher 0:3677a016109b 11 int nrf51_rtc::set_time(time_t rawtime) {
lionello 3:9be93d7808ca 12 rtc_previous = NRF_RTC1->COUNTER;
fxschumacher 0:3677a016109b 13 // set the current time from a parameter
lionello 3:9be93d7808ca 14 time_base = rawtime;
fxschumacher 0:3677a016109b 15 return 0;
fxschumacher 0:3677a016109b 16 }
fxschumacher 0:3677a016109b 17
fxschumacher 0:3677a016109b 18 time_t nrf51_rtc::time() {
fxschumacher 0:3677a016109b 19 // get the current time... and update the underlying variables for tracking time
fxschumacher 0:3677a016109b 20 // ...this routine must be called regularly, before the 24b RTC register can wrap around:
fxschumacher 0:3677a016109b 21 // t < size of register / (LFCLK_FREQUENCY / (NRF_RTC1->PRESCALER + 1))
fxschumacher 0:3677a016109b 22 // size of register = 2^24 ticks
fxschumacher 0:3677a016109b 23 // LFCLK_FREQUENCY = 2^15 cycles/sec
fxschumacher 0:3677a016109b 24 // NRF_RTC1->PRESCALER = 0 -- as (currently) set by mbed library!
fxschumacher 0:3677a016109b 25 // = (2^24)/(2^15/1) = 2^9 seconds = 512 seconds, ~ 8.5 minutes
lionello 3:9be93d7808ca 26
lionello 3:9be93d7808ca 27 uint32_t rtc_now = NRF_RTC1->COUNTER;
lionello 3:9be93d7808ca 28 uint32_t delta_ticks = (rtc_now - rtc_previous) & RTC_COUNTER_MASK;
lionello 3:9be93d7808ca 29
lionello 3:9be93d7808ca 30 uint32_t delta_seconds = delta_ticks / ticks_per_second;
lionello 3:9be93d7808ca 31 time_base += delta_seconds;
lionello 3:9be93d7808ca 32 uint32_t missing_ticks = delta_ticks - delta_seconds * ticks_per_second;
lionello 3:9be93d7808ca 33 rtc_previous = rtc_now - missing_ticks;
fxschumacher 0:3677a016109b 34 return time_base;
fxschumacher 0:3677a016109b 35 }
fxschumacher 0:3677a016109b 36
fxschumacher 0:3677a016109b 37 void nrf51_rtc::update_rtc() {
fxschumacher 0:3677a016109b 38 // for use as interrupt routine, same as "time" but doesn't return a value (as req'd for interrupt)
lionello 1:5917157d58c6 39 rtc.time();
fxschumacher 0:3677a016109b 40 }
fxschumacher 0:3677a016109b 41
lionello 3:9be93d7808ca 42 nrf51_rtc::nrf51_rtc() :
lionello 3:9be93d7808ca 43 ticks_per_second(LFCLK_FREQUENCY / (NRF_RTC1->PRESCALER + 1))
lionello 3:9be93d7808ca 44 {
fxschumacher 0:3677a016109b 45 rtc_previous=0;
fxschumacher 0:3677a016109b 46 time_base=0;
lionello 3:9be93d7808ca 47
fxschumacher 0:3677a016109b 48
fxschumacher 0:3677a016109b 49 // Ticker inside the method doesn't work: the interrupt attachment to the ticker messes up the world (code goes to the weeds)
fxschumacher 0:3677a016109b 50 // ... not needed if "rtc.time()" is called frequently enough (once per 512 seconds)
fxschumacher 0:3677a016109b 51 // ... this scheme (ticker+interrupt routine to update rtc) works correctly when implemented at the next level up
fxschumacher 0:3677a016109b 52 //Ticker rtc_ticker;
fxschumacher 0:3677a016109b 53 //#define RTC_UPDATE 1
fxschumacher 0:3677a016109b 54 //rtc_ticker.attach(this,&nrf51_rtc::update_rtc, RTC_UPDATE); // update the time regularly (must be < duration of 24b timer)
fxschumacher 0:3677a016109b 55 }