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.
Dependents: nRF51_rtc_example LoRa_PIR BLE_Lightning_sensor BLE_AlarmWatch ... more
nrf51_rtc.cpp@0:3677a016109b, 2015-02-08 (annotated)
- Committer:
- fxschumacher
- Date:
- Sun Feb 08 01:28:47 2015 +0000
- Revision:
- 0:3677a016109b
Initial revision -- library to implement Real Time Clock (time and set_time) for nRF51-DK.
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 | |
fxschumacher | 0:3677a016109b | 3 | int nrf51_rtc::set_time(time_t rawtime) { |
fxschumacher | 0:3677a016109b | 4 | // set the current time from a parameter |
fxschumacher | 0:3677a016109b | 5 | time_base = rawtime; |
fxschumacher | 0:3677a016109b | 6 | rtc_previous = int (NRF_RTC1->COUNTER) / ticks_per_second; |
fxschumacher | 0:3677a016109b | 7 | return 0; |
fxschumacher | 0:3677a016109b | 8 | } |
fxschumacher | 0:3677a016109b | 9 | |
fxschumacher | 0:3677a016109b | 10 | time_t nrf51_rtc::time() { |
fxschumacher | 0:3677a016109b | 11 | // get the current time... and update the underlying variables for tracking time |
fxschumacher | 0:3677a016109b | 12 | // ...this routine must be called regularly, before the 24b RTC register can wrap around: |
fxschumacher | 0:3677a016109b | 13 | // t < size of register / (LFCLK_FREQUENCY / (NRF_RTC1->PRESCALER + 1)) |
fxschumacher | 0:3677a016109b | 14 | // size of register = 2^24 ticks |
fxschumacher | 0:3677a016109b | 15 | // LFCLK_FREQUENCY = 2^15 cycles/sec |
fxschumacher | 0:3677a016109b | 16 | // NRF_RTC1->PRESCALER = 0 -- as (currently) set by mbed library! |
fxschumacher | 0:3677a016109b | 17 | // = (2^24)/(2^15/1) = 2^9 seconds = 512 seconds, ~ 8.5 minutes |
fxschumacher | 0:3677a016109b | 18 | unsigned int rtc_now = (NRF_RTC1->COUNTER) / ticks_per_second; |
fxschumacher | 0:3677a016109b | 19 | unsigned int delta_seconds = ((rtc_now + counter_size_in_seconds) - rtc_previous) % counter_size_in_seconds; |
fxschumacher | 0:3677a016109b | 20 | time_base = time_base + (time_t) delta_seconds; |
fxschumacher | 0:3677a016109b | 21 | rtc_previous = rtc_now; |
fxschumacher | 0:3677a016109b | 22 | return time_base; |
fxschumacher | 0:3677a016109b | 23 | } |
fxschumacher | 0:3677a016109b | 24 | |
fxschumacher | 0:3677a016109b | 25 | void nrf51_rtc::update_rtc() { |
fxschumacher | 0:3677a016109b | 26 | // for use as interrupt routine, same as "time" but doesn't return a value (as req'd for interrupt) |
fxschumacher | 0:3677a016109b | 27 | // ...but this is useless since the compiler seems to be unable to correctly attach a member function to the ticker interrupt |
fxschumacher | 0:3677a016109b | 28 | // ...the exact same interrupt routine attached to a ticker works fine when declared outside the method |
fxschumacher | 0:3677a016109b | 29 | nrf51_rtc::time(); |
fxschumacher | 0:3677a016109b | 30 | } |
fxschumacher | 0:3677a016109b | 31 | |
fxschumacher | 0:3677a016109b | 32 | nrf51_rtc::nrf51_rtc() { |
fxschumacher | 0:3677a016109b | 33 | rtc_previous=0; |
fxschumacher | 0:3677a016109b | 34 | time_base=0; |
fxschumacher | 0:3677a016109b | 35 | #define LFCLK_FREQUENCY 0x8000 |
fxschumacher | 0:3677a016109b | 36 | #define RTC_COUNTER_SIZE 0x1000000 |
fxschumacher | 0:3677a016109b | 37 | ticks_per_second = LFCLK_FREQUENCY / (NRF_RTC1->PRESCALER + 1); |
fxschumacher | 0:3677a016109b | 38 | counter_size_in_seconds = RTC_COUNTER_SIZE / ticks_per_second; |
fxschumacher | 0:3677a016109b | 39 | |
fxschumacher | 0:3677a016109b | 40 | // 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 | 41 | // ... not needed if "rtc.time()" is called frequently enough (once per 512 seconds) |
fxschumacher | 0:3677a016109b | 42 | // ... this scheme (ticker+interrupt routine to update rtc) works correctly when implemented at the next level up |
fxschumacher | 0:3677a016109b | 43 | //Ticker rtc_ticker; |
fxschumacher | 0:3677a016109b | 44 | //#define RTC_UPDATE 1 |
fxschumacher | 0:3677a016109b | 45 | //rtc_ticker.attach(this,&nrf51_rtc::update_rtc, RTC_UPDATE); // update the time regularly (must be < duration of 24b timer) |
fxschumacher | 0:3677a016109b | 46 | } |