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

Files at this revision

API Documentation at this revision

Comitter:
lionello
Date:
Thu Apr 16 11:43:56 2015 +0000
Parent:
2:e1479e6ffc37
Commit message:
Fixed clock drift by keep tracking of the fractional seconds (ticks)

Changed in this revision

nrf51_rtc.cpp Show annotated file Show diff for this revision Revisions of this file
nrf51_rtc.h Show annotated file Show diff for this revision Revisions of this file
--- a/nrf51_rtc.cpp	Wed Mar 18 09:35:02 2015 +0000
+++ b/nrf51_rtc.cpp	Thu Apr 16 11:43:56 2015 +0000
@@ -2,13 +2,16 @@
 
 #include <mbed.h>
 
+#define LFCLK_FREQUENCY 0x8000
+#define RTC_COUNTER_MASK 0xFFFFFF
+
 nrf51_rtc rtc;
 
 
 int nrf51_rtc::set_time(time_t rawtime) {
+    rtc_previous = NRF_RTC1->COUNTER;
     // set the current time from a parameter
-    time_base = rawtime;
-    rtc_previous = int (NRF_RTC1->COUNTER) / ticks_per_second;
+    time_base = rawtime;    
     return 0;
 }
 
@@ -20,10 +23,14 @@
     //    LFCLK_FREQUENCY = 2^15 cycles/sec 
     //    NRF_RTC1->PRESCALER = 0 -- as (currently) set by mbed library!
     //  = (2^24)/(2^15/1) = 2^9 seconds = 512 seconds, ~ 8.5 minutes
-    unsigned int rtc_now = (NRF_RTC1->COUNTER) / ticks_per_second;
-    unsigned int delta_seconds = ((rtc_now + counter_size_in_seconds) - rtc_previous) % counter_size_in_seconds;
-    time_base = time_base + (time_t) delta_seconds;
-    rtc_previous = rtc_now;
+
+    uint32_t rtc_now = NRF_RTC1->COUNTER;
+    uint32_t delta_ticks = (rtc_now - rtc_previous) & RTC_COUNTER_MASK;
+
+    uint32_t delta_seconds = delta_ticks / ticks_per_second;
+    time_base += delta_seconds;
+    uint32_t missing_ticks = delta_ticks - delta_seconds * ticks_per_second;
+    rtc_previous = rtc_now - missing_ticks;
     return time_base;
 }
 
@@ -32,13 +39,12 @@
     rtc.time();
 }
 
-nrf51_rtc::nrf51_rtc() {
+nrf51_rtc::nrf51_rtc() :
+    ticks_per_second(LFCLK_FREQUENCY / (NRF_RTC1->PRESCALER + 1))
+{
     rtc_previous=0;
     time_base=0;
-    #define LFCLK_FREQUENCY 0x8000
-    #define RTC_COUNTER_SIZE 0x1000000
-    ticks_per_second = LFCLK_FREQUENCY / (NRF_RTC1->PRESCALER + 1);
-    counter_size_in_seconds = RTC_COUNTER_SIZE / ticks_per_second;
+
     
     // Ticker inside the method doesn't work:  the interrupt attachment to the ticker messes up the world (code goes to the weeds)
     //  ... not needed if "rtc.time()" is called frequently enough (once per 512 seconds)
--- a/nrf51_rtc.h	Wed Mar 18 09:35:02 2015 +0000
+++ b/nrf51_rtc.h	Thu Apr 16 11:43:56 2015 +0000
@@ -17,7 +17,7 @@
 private:
     time_t time_base;
     unsigned int rtc_previous;
-    unsigned int ticks_per_second, counter_size_in_seconds;
+    const unsigned int ticks_per_second;
 };
 
 extern nrf51_rtc rtc;