E3 Designers / TimeManagement

Dependents:   mbed_escm2000

Committer:
WiredHome
Date:
Wed Nov 02 01:32:07 2011 +0000
Revision:
6:a517fee06e2e
Parent:
5:fbbdf57675c3
Child:
7:812452a275fa
v1.04 Minor changes to the adjustment logic for complexity reduction

Who changed what in which revision?

UserRevisionLine numberNew contents of line
WiredHome 0:108436d3cea9 1 /// @file TimeUtilities.cpp contains a real time clock interface for the mbed
WiredHome 0:108436d3cea9 2 ///
WiredHome 0:108436d3cea9 3 /// APIs for showing the time from the RTC, or from a passed in value.
WiredHome 0:108436d3cea9 4 /// Also supports setting the clock, timezone offsets and calibration
WiredHome 0:108436d3cea9 5 /// of the RTC subsystem.
WiredHome 0:108436d3cea9 6 ///
WiredHome 1:6d3d16f4b27c 7 /// @note Copyright &copr; 2011 by Smartware Computing, all rights reserved.
WiredHome 1:6d3d16f4b27c 8 /// Individuals may use this application for evaluation or non-commercial
WiredHome 1:6d3d16f4b27c 9 /// purposes. Within this restriction, changes may be made to this application
WiredHome 1:6d3d16f4b27c 10 /// as long as this copyright notice is retained. The user shall make
WiredHome 1:6d3d16f4b27c 11 /// clear that their work is a derived work, and not the original.
WiredHome 1:6d3d16f4b27c 12 /// Users of this application and sources accept this application "as is" and
WiredHome 1:6d3d16f4b27c 13 /// shall hold harmless Smartware Computing, for any undesired results while
WiredHome 1:6d3d16f4b27c 14 /// using this application - whether real or imagined.
WiredHome 1:6d3d16f4b27c 15 ///
WiredHome 1:6d3d16f4b27c 16 /// @author David Smart, Smartware Computing
WiredHome 0:108436d3cea9 17 ///
WiredHome 0:108436d3cea9 18 #ifndef WIN32
WiredHome 0:108436d3cea9 19 // embedded build
WiredHome 0:108436d3cea9 20 #include "mbed.h"
WiredHome 0:108436d3cea9 21 #endif
WiredHome 0:108436d3cea9 22
WiredHome 6:a517fee06e2e 23 #define VERSION "1.04"
WiredHome 5:fbbdf57675c3 24
WiredHome 0:108436d3cea9 25 #include "TimeUtilities.h"
WiredHome 0:108436d3cea9 26 #include <time.h>
WiredHome 0:108436d3cea9 27 #include <string.h>
WiredHome 0:108436d3cea9 28 #include <stdio.h>
WiredHome 0:108436d3cea9 29 #include <stdlib.h>
WiredHome 0:108436d3cea9 30
WiredHome 0:108436d3cea9 31 #ifdef WIN32
WiredHome 3:524ad47afdc7 32 // Fake it out for Win32 development and testing
WiredHome 0:108436d3cea9 33 struct LPC {
WiredHome 2:cbcdd97f3a6d 34 unsigned long CCR; // Clock Control register
WiredHome 5:fbbdf57675c3 35 unsigned long GPREG0; // General Purpose Register #0 - 32-bit Battery backed
WiredHome 5:fbbdf57675c3 36 unsigned long GPREG1; // General Purpose Register #1 - 32-bit Battery backed
WiredHome 2:cbcdd97f3a6d 37 unsigned long CALIBRATION; // Calibration Register
WiredHome 0:108436d3cea9 38 };
WiredHome 0:108436d3cea9 39 struct LPC X;
WiredHome 0:108436d3cea9 40 struct LPC * LPC_RTC = &X;
WiredHome 0:108436d3cea9 41 #define set_time(x) (void)x
WiredHome 0:108436d3cea9 42 #endif
WiredHome 0:108436d3cea9 43
WiredHome 0:108436d3cea9 44 static int tzOffsetHr = 0; ///!< time zone offset hours to print time in local time
WiredHome 0:108436d3cea9 45 static int tzOffsetMin = 0; ///!< time zone offset minutes to print time in local time
WiredHome 5:fbbdf57675c3 46
WiredHome 5:fbbdf57675c3 47
WiredHome 5:fbbdf57675c3 48 static const char ver[] = VERSION;
WiredHome 0:108436d3cea9 49
WiredHome 0:108436d3cea9 50 static int SignOf(const int i) {
WiredHome 0:108436d3cea9 51 return (i >= 0) ? 1 : -1;
WiredHome 0:108436d3cea9 52 }
WiredHome 0:108436d3cea9 53
WiredHome 2:cbcdd97f3a6d 54
WiredHome 0:108436d3cea9 55 RealTimeClock::RealTimeClock() {
WiredHome 1:6d3d16f4b27c 56 GetTimeOffsetStore();
WiredHome 0:108436d3cea9 57 }
WiredHome 0:108436d3cea9 58
WiredHome 2:cbcdd97f3a6d 59
WiredHome 0:108436d3cea9 60 RealTimeClock::~RealTimeClock() {
WiredHome 0:108436d3cea9 61 }
WiredHome 0:108436d3cea9 62
WiredHome 5:fbbdf57675c3 63 const char * RealTimeClock::GetVersion() {
WiredHome 5:fbbdf57675c3 64 return ver;
WiredHome 5:fbbdf57675c3 65 }
WiredHome 5:fbbdf57675c3 66
WiredHome 5:fbbdf57675c3 67 time_t RealTimeClock::GetTimeValue() {
WiredHome 5:fbbdf57675c3 68 return time(NULL);
WiredHome 5:fbbdf57675c3 69 }
WiredHome 5:fbbdf57675c3 70
WiredHome 2:cbcdd97f3a6d 71
WiredHome 0:108436d3cea9 72 void RealTimeClock::GetTimeString(char *buf, time_t tValue) {
WiredHome 0:108436d3cea9 73 GetTimeOffsetStore(); // Load the time zone offset values from the battery ram
WiredHome 0:108436d3cea9 74 GetTimeString(buf, tValue, tzOffsetHr, tzOffsetMin);
WiredHome 0:108436d3cea9 75 }
WiredHome 0:108436d3cea9 76
WiredHome 2:cbcdd97f3a6d 77
WiredHome 0:108436d3cea9 78 void RealTimeClock::GetTimeString(char *buf, int hOffset, int mOffset) {
WiredHome 0:108436d3cea9 79 GetTimeString(buf, 0, hOffset, mOffset);
WiredHome 0:108436d3cea9 80 }
WiredHome 0:108436d3cea9 81
WiredHome 2:cbcdd97f3a6d 82
WiredHome 0:108436d3cea9 83 void RealTimeClock::GetTimeString(char *buf, time_t tValue, int hOffset, int mOffset) {
WiredHome 0:108436d3cea9 84 time_t ctTime;
WiredHome 0:108436d3cea9 85
WiredHome 0:108436d3cea9 86 if (tValue == 0)
WiredHome 0:108436d3cea9 87 tValue = time(NULL);
WiredHome 0:108436d3cea9 88 ctTime = tValue + hOffset * 3600 + SignOf(hOffset) * mOffset * 60;
WiredHome 0:108436d3cea9 89 strcpy(buf, ctime(&ctTime));
WiredHome 0:108436d3cea9 90 buf[strlen(buf)-1] = '\0'; // remove the \n
WiredHome 0:108436d3cea9 91 sprintf(buf + strlen(buf), " (tzo: %2i:%02i)", hOffset, mOffset);
WiredHome 0:108436d3cea9 92 }
WiredHome 0:108436d3cea9 93
WiredHome 2:cbcdd97f3a6d 94
WiredHome 0:108436d3cea9 95 int32_t RealTimeClock::GetTimeCalibration() {
WiredHome 0:108436d3cea9 96 int32_t calvalue = LPC_RTC->CALIBRATION & 0x3FFFF;
WiredHome 0:108436d3cea9 97
WiredHome 0:108436d3cea9 98 if (calvalue & 0x20000) {
WiredHome 0:108436d3cea9 99 calvalue = -(calvalue & 0x1FFFF);
WiredHome 0:108436d3cea9 100 }
WiredHome 0:108436d3cea9 101 return calvalue;
WiredHome 0:108436d3cea9 102 }
WiredHome 0:108436d3cea9 103
WiredHome 2:cbcdd97f3a6d 104
WiredHome 0:108436d3cea9 105 void RealTimeClock::SetTimeCalibration(int32_t calibration) {
WiredHome 2:cbcdd97f3a6d 106 if (calibration) {
WiredHome 2:cbcdd97f3a6d 107 if (calibration < 0) {
WiredHome 2:cbcdd97f3a6d 108 calibration = (-calibration & 0x1FFFF) | 0x20000;
WiredHome 2:cbcdd97f3a6d 109 }
WiredHome 2:cbcdd97f3a6d 110 LPC_RTC->CCR = 0x000001; //(LPC_RTC->CCR & 0x0003); // Clear CCALEN to enable it
WiredHome 2:cbcdd97f3a6d 111 } else {
WiredHome 2:cbcdd97f3a6d 112 LPC_RTC->CCR = 0x000011; //(LPC_RTC->CCR & 0x0003) | 0x0010; // Set CCALEN to disable it
WiredHome 0:108436d3cea9 113 }
WiredHome 0:108436d3cea9 114 LPC_RTC->CALIBRATION = calibration;
WiredHome 0:108436d3cea9 115 }
WiredHome 0:108436d3cea9 116
WiredHome 2:cbcdd97f3a6d 117
WiredHome 0:108436d3cea9 118 void RealTimeClock::SetTimeOffset(int offsetHour, int offsetMinute) {
WiredHome 0:108436d3cea9 119 tzOffsetHr = offsetHour;
WiredHome 0:108436d3cea9 120 tzOffsetMin = offsetMinute;
WiredHome 0:108436d3cea9 121 SetTimeOffsetStore();
WiredHome 0:108436d3cea9 122 }
WiredHome 0:108436d3cea9 123
WiredHome 2:cbcdd97f3a6d 124
WiredHome 0:108436d3cea9 125 void RealTimeClock::SetTimeOffsetStore() {
WiredHome 0:108436d3cea9 126 LPC_RTC->GPREG0 = tzOffsetHr * 256 + tzOffsetMin;
WiredHome 0:108436d3cea9 127 }
WiredHome 0:108436d3cea9 128
WiredHome 2:cbcdd97f3a6d 129
WiredHome 0:108436d3cea9 130 void RealTimeClock::GetTimeOffsetStore() {
WiredHome 0:108436d3cea9 131 tzOffsetHr = (int32_t)LPC_RTC->GPREG0 / 256;
WiredHome 0:108436d3cea9 132 tzOffsetMin = (LPC_RTC->GPREG0 & 0xFF);
WiredHome 0:108436d3cea9 133 }
WiredHome 0:108436d3cea9 134
WiredHome 6:a517fee06e2e 135 void RealTimeClock::SetTimeLastSet(time_t t) {
WiredHome 6:a517fee06e2e 136 LPC_RTC->GPREG1 = t;
WiredHome 5:fbbdf57675c3 137 }
WiredHome 5:fbbdf57675c3 138
WiredHome 6:a517fee06e2e 139 time_t RealTimeClock::GetTimeLastSet() {
WiredHome 6:a517fee06e2e 140 return LPC_RTC->GPREG1;
WiredHome 5:fbbdf57675c3 141 }
WiredHome 2:cbcdd97f3a6d 142
WiredHome 0:108436d3cea9 143 // MM/DD/YYYY HH:MM:SS [(+/-hh:mm)]
WiredHome 0:108436d3cea9 144 bool RealTimeClock::SetTime(char * timestring) {
WiredHome 0:108436d3cea9 145 bool success = false;
WiredHome 0:108436d3cea9 146 char * p;
WiredHome 0:108436d3cea9 147 time_t seconds = time(NULL);
WiredHome 0:108436d3cea9 148 struct tm *t = localtime(&seconds);
WiredHome 0:108436d3cea9 149 int _oH, _oM;
WiredHome 0:108436d3cea9 150
WiredHome 0:108436d3cea9 151 p = strtok(timestring," /");
WiredHome 0:108436d3cea9 152 if (p != NULL) {
WiredHome 0:108436d3cea9 153 t->tm_mon = atoi(p) - 1;
WiredHome 0:108436d3cea9 154 p = strtok(NULL, " /");
WiredHome 0:108436d3cea9 155 if (p != NULL) {
WiredHome 0:108436d3cea9 156 t->tm_mday = atoi(p);
WiredHome 0:108436d3cea9 157 p = strtok(NULL, " /");
WiredHome 0:108436d3cea9 158 if (p != NULL) {
WiredHome 0:108436d3cea9 159 t->tm_year = atoi(p) - 1900;
WiredHome 0:108436d3cea9 160 p = strtok(NULL, " :");
WiredHome 0:108436d3cea9 161 if (p != NULL) {
WiredHome 0:108436d3cea9 162 t->tm_hour = atoi(p);
WiredHome 0:108436d3cea9 163 p = strtok(NULL, " :");
WiredHome 0:108436d3cea9 164 if (p != NULL) {
WiredHome 1:6d3d16f4b27c 165 t->tm_min = atoi(p);
WiredHome 1:6d3d16f4b27c 166 p = strtok(NULL, " (:");
WiredHome 1:6d3d16f4b27c 167 if (p != NULL) {
WiredHome 1:6d3d16f4b27c 168 t->tm_sec = atoi(p);
WiredHome 1:6d3d16f4b27c 169 success = true; // if we get to here, we're good
WiredHome 1:6d3d16f4b27c 170 p = strtok(NULL, " (:");
WiredHome 1:6d3d16f4b27c 171 if (p != NULL) {
WiredHome 1:6d3d16f4b27c 172 success = false; // but can't accept a partial tzo
WiredHome 1:6d3d16f4b27c 173 _oH = atoi(p);
WiredHome 1:6d3d16f4b27c 174 p = strtok(NULL, " (:)");
WiredHome 1:6d3d16f4b27c 175 if (p != NULL) {
WiredHome 1:6d3d16f4b27c 176 _oM = atoi(p);
WiredHome 1:6d3d16f4b27c 177 success = true; // but a whole tzo is ok
WiredHome 1:6d3d16f4b27c 178 SetTimeOffset(_oH, _oM);
WiredHome 1:6d3d16f4b27c 179 }
WiredHome 1:6d3d16f4b27c 180 }
WiredHome 1:6d3d16f4b27c 181 seconds = mktime(t);
WiredHome 1:6d3d16f4b27c 182 seconds = seconds - (time_t)(tzOffsetHr * 3600 + tzOffsetMin * 60);
WiredHome 1:6d3d16f4b27c 183 set_time(seconds);
WiredHome 6:a517fee06e2e 184 SetTimeLastSet(seconds);
WiredHome 1:6d3d16f4b27c 185 }
WiredHome 1:6d3d16f4b27c 186 }
WiredHome 0:108436d3cea9 187 }
WiredHome 0:108436d3cea9 188 }
WiredHome 0:108436d3cea9 189 }
WiredHome 0:108436d3cea9 190 }
WiredHome 0:108436d3cea9 191 return success;
WiredHome 0:108436d3cea9 192 }
WiredHome 0:108436d3cea9 193
WiredHome 5:fbbdf57675c3 194 bool RealTimeClock::AdjustBySeconds(int32_t adjustSeconds) {
WiredHome 6:a517fee06e2e 195 time_t lastSet = GetTimeLastSet();
WiredHome 6:a517fee06e2e 196
WiredHome 6:a517fee06e2e 197 if (lastSet != 0) {
WiredHome 5:fbbdf57675c3 198 time_t seconds = time(NULL); // get "now" according to the rtc
WiredHome 6:a517fee06e2e 199 int32_t delta = seconds - lastSet;
WiredHome 5:fbbdf57675c3 200 int32_t curCal = GetTimeCalibration();
WiredHome 5:fbbdf57675c3 201 int32_t calMAX = 131071;
WiredHome 5:fbbdf57675c3 202 int32_t secPerDay = 86400;
WiredHome 5:fbbdf57675c3 203 float errSecPerDay;
WiredHome 5:fbbdf57675c3 204
WiredHome 5:fbbdf57675c3 205 // Convert the current calibration and the adjustment into
WiredHome 5:fbbdf57675c3 206 // the new calibration value
WiredHome 5:fbbdf57675c3 207 // assume it is +10sec and it has been 2days, then the adjustment
WiredHome 5:fbbdf57675c3 208 // needs to be +5 sec per day, or one adjustment every 1/5th
WiredHome 5:fbbdf57675c3 209 // of a day, or 1 adjustment every 86400/5 counts.
WiredHome 5:fbbdf57675c3 210 // delta = now - then (number of elapsed seconds)
WiredHome 5:fbbdf57675c3 211 if (adjustSeconds != 0 && delta != 0) {
WiredHome 5:fbbdf57675c3 212 int32_t calFactor;
WiredHome 6:a517fee06e2e 213
WiredHome 6:a517fee06e2e 214 // Make the clock correct
WiredHome 6:a517fee06e2e 215 seconds = seconds + adjustSeconds;
WiredHome 6:a517fee06e2e 216 set_time(seconds);
WiredHome 6:a517fee06e2e 217 SetTimeLastSet(seconds);
WiredHome 6:a517fee06e2e 218 // Compute the calibration factor
WiredHome 5:fbbdf57675c3 219 errSecPerDay = (float)adjustSeconds / ((float)(delta)/secPerDay);
WiredHome 5:fbbdf57675c3 220 calFactor = (int32_t)((float)secPerDay/errSecPerDay);
WiredHome 5:fbbdf57675c3 221 if (abs(calFactor) < calMAX)
WiredHome 5:fbbdf57675c3 222 SetTimeCalibration(calFactor);
WiredHome 5:fbbdf57675c3 223 }
WiredHome 5:fbbdf57675c3 224 return true;
WiredHome 5:fbbdf57675c3 225 } else {
WiredHome 5:fbbdf57675c3 226 return false;
WiredHome 5:fbbdf57675c3 227 }
WiredHome 5:fbbdf57675c3 228 }