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
nrf51_rtc.cpp@3:9be93d7808ca, 2015-04-16 (annotated)
- 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?
User | Revision | Line number | New 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 | } |