This is a library for managing the mbed real time clock, including functions for setting and getting the rtc in text format, getting and setting the timezone offset, and getting and setting the calibration register, both directly, and by using an adjustment API to automatically set the calibration value.

Dependents:   LAB4WEEK1 Motor

Revision:
5:fbbdf57675c3
Parent:
3:524ad47afdc7
Child:
6:a517fee06e2e
--- a/TimeUtilities.cpp	Sat Jul 16 16:57:22 2011 +0000
+++ b/TimeUtilities.cpp	Sun Oct 30 23:42:43 2011 +0000
@@ -15,19 +15,13 @@
 ///
 /// @author David Smart, Smartware Computing
 ///
-/// Version History
-/// 20110616
-/// \li minor documentation changes
-/// 20110601
-/// \li discovered the CCALEN flag to enable calibration
-/// 20110529
-/// \li original version
-///
 #ifndef WIN32
 // embedded build
 #include "mbed.h"
 #endif
 
+#define VERSION "1.03"
+
 #include "TimeUtilities.h"
 #include <time.h>
 #include <string.h>
@@ -38,7 +32,8 @@
 // Fake it out for Win32 development and testing
 struct LPC {
     unsigned long CCR;          // Clock Control register
-    unsigned long GPREG0;       // General Purpose Register - Battery backed
+    unsigned long GPREG0;       // General Purpose Register #0 - 32-bit Battery backed
+    unsigned long GPREG1;       // General Purpose Register #1 - 32-bit Battery backed
     unsigned long CALIBRATION;  // Calibration Register
 };
 struct LPC X;
@@ -48,6 +43,10 @@
 
 static int tzOffsetHr = 0;       ///!< time zone offset hours to print time in local time
 static int tzOffsetMin = 0;      ///!< time zone offset minutes to print time in local time
+static time_t timeWhenLastSet = 0;
+
+
+static const char ver[] = VERSION;
 
 static int SignOf(const int i) {
     return (i >= 0) ? 1 : -1;
@@ -56,12 +55,25 @@
 
 RealTimeClock::RealTimeClock() {
     GetTimeOffsetStore();
+    GetTimeLastSetStore();
 }
 
 
 RealTimeClock::~RealTimeClock() {
 }
 
+const char * RealTimeClock::GetVersion() {
+    return ver;
+}
+
+time_t RealTimeClock::GetTimeValue() {
+    return time(NULL);
+}
+
+time_t RealTimeClock::GetTimeValueWhenSet() {
+    return timeWhenLastSet;
+}
+
 
 void RealTimeClock::GetTimeString(char *buf, time_t tValue) {
     GetTimeOffsetStore();       // Load the time zone offset values from the battery ram
@@ -126,6 +138,13 @@
     tzOffsetMin = (LPC_RTC->GPREG0 & 0xFF);
 }
 
+void RealTimeClock::SetTimeLastSetStore() {
+    LPC_RTC->GPREG1 = timeWhenLastSet;
+}
+
+void RealTimeClock::GetTimeLastSetStore() {
+    timeWhenLastSet = LPC_RTC->GPREG1;
+}
 
 // MM/DD/YYYY HH:MM:SS [(+/-hh:mm)]
 bool RealTimeClock::SetTime(char * timestring) {
@@ -168,6 +187,8 @@
                             seconds = mktime(t);
                             seconds = seconds - (time_t)(tzOffsetHr * 3600 + tzOffsetMin * 60);
                             set_time(seconds);
+                            timeWhenLastSet = seconds;
+                            SetTimeLastSetStore();
                         }
                     }
                 }
@@ -177,3 +198,34 @@
     return success;
 }
 
+bool RealTimeClock::AdjustBySeconds(int32_t adjustSeconds) {
+    if (timeWhenLastSet != 0) {
+        time_t seconds = time(NULL);    // get "now" according to the rtc
+        int32_t delta = seconds - timeWhenLastSet;
+        int32_t curCal = GetTimeCalibration();
+        int32_t calMAX = 131071;
+        int32_t secPerDay = 86400;
+        float errSecPerDay;
+                
+        // Make the clock correct
+        seconds = seconds + adjustSeconds;
+        set_time(seconds);
+        
+        // Convert the current calibration and the adjustment into
+        // the new calibration value
+        // assume it is +10sec and it has been 2days, then the adjustment
+        // needs to be +5 sec per day, or one adjustment every 1/5th 
+        // of a day, or 1 adjustment every 86400/5 counts.
+        // delta = now - then (number of elapsed seconds)
+        if (adjustSeconds != 0 && delta != 0) {
+            int32_t calFactor;
+            errSecPerDay = (float)adjustSeconds / ((float)(delta)/secPerDay);
+            calFactor = (int32_t)((float)secPerDay/errSecPerDay);
+            if (abs(calFactor) < calMAX)
+                SetTimeCalibration(calFactor);
+        }
+        return true;
+    } else {
+        return false;
+    }
+}
\ No newline at end of file