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:   mbed_escm2000

Committer:
WiredHome
Date:
Wed Jun 08 11:36:11 2011 +0000
Revision:
2:cbcdd97f3a6d
Parent:
1:6d3d16f4b27c
Child:
3:524ad47afdc7
v1.01 added methods for working with the calibration register

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 2:cbcdd97f3a6d 18 /// Version History
WiredHome 2:cbcdd97f3a6d 19 /// 20110601
WiredHome 2:cbcdd97f3a6d 20 /// \li discovered the CCALEN flag to enable calibration
WiredHome 2:cbcdd97f3a6d 21 /// 20110529
WiredHome 2:cbcdd97f3a6d 22 /// \li original version
WiredHome 2:cbcdd97f3a6d 23 ///
WiredHome 0:108436d3cea9 24 #ifndef WIN32
WiredHome 0:108436d3cea9 25 // embedded build
WiredHome 0:108436d3cea9 26 #include "mbed.h"
WiredHome 0:108436d3cea9 27 #endif
WiredHome 0:108436d3cea9 28
WiredHome 0:108436d3cea9 29 #include "TimeUtilities.h"
WiredHome 0:108436d3cea9 30 #include <time.h>
WiredHome 0:108436d3cea9 31 #include <string.h>
WiredHome 0:108436d3cea9 32 #include <stdio.h>
WiredHome 0:108436d3cea9 33 #include <stdlib.h>
WiredHome 0:108436d3cea9 34
WiredHome 0:108436d3cea9 35 #ifdef WIN32
WiredHome 0:108436d3cea9 36 // Fake it out for Win32
WiredHome 0:108436d3cea9 37 struct LPC {
WiredHome 2:cbcdd97f3a6d 38 unsigned long CCR; // Clock Control register
WiredHome 2:cbcdd97f3a6d 39 unsigned long GPREG0; // General Purpose Register - Battery backed
WiredHome 2:cbcdd97f3a6d 40 unsigned long CALIBRATION; // Calibration Register
WiredHome 0:108436d3cea9 41 };
WiredHome 0:108436d3cea9 42 struct LPC X;
WiredHome 0:108436d3cea9 43 struct LPC * LPC_RTC = &X;
WiredHome 0:108436d3cea9 44 #define set_time(x) (void)x
WiredHome 0:108436d3cea9 45 #endif
WiredHome 0:108436d3cea9 46
WiredHome 0:108436d3cea9 47 static int tzOffsetHr = 0; ///!< time zone offset hours to print time in local time
WiredHome 0:108436d3cea9 48 static int tzOffsetMin = 0; ///!< time zone offset minutes to print time in local time
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 2:cbcdd97f3a6d 63
WiredHome 0:108436d3cea9 64 void RealTimeClock::GetTimeString(char *buf, time_t tValue) {
WiredHome 0:108436d3cea9 65 GetTimeOffsetStore(); // Load the time zone offset values from the battery ram
WiredHome 0:108436d3cea9 66 GetTimeString(buf, tValue, tzOffsetHr, tzOffsetMin);
WiredHome 0:108436d3cea9 67 }
WiredHome 0:108436d3cea9 68
WiredHome 2:cbcdd97f3a6d 69
WiredHome 0:108436d3cea9 70 void RealTimeClock::GetTimeString(char *buf, int hOffset, int mOffset) {
WiredHome 0:108436d3cea9 71 GetTimeString(buf, 0, hOffset, mOffset);
WiredHome 0:108436d3cea9 72 }
WiredHome 0:108436d3cea9 73
WiredHome 2:cbcdd97f3a6d 74
WiredHome 0:108436d3cea9 75 void RealTimeClock::GetTimeString(char *buf, time_t tValue, int hOffset, int mOffset) {
WiredHome 0:108436d3cea9 76 time_t ctTime;
WiredHome 0:108436d3cea9 77
WiredHome 0:108436d3cea9 78 if (tValue == 0)
WiredHome 0:108436d3cea9 79 tValue = time(NULL);
WiredHome 0:108436d3cea9 80 ctTime = tValue + hOffset * 3600 + SignOf(hOffset) * mOffset * 60;
WiredHome 0:108436d3cea9 81 strcpy(buf, ctime(&ctTime));
WiredHome 0:108436d3cea9 82 buf[strlen(buf)-1] = '\0'; // remove the \n
WiredHome 0:108436d3cea9 83 sprintf(buf + strlen(buf), " (tzo: %2i:%02i)", hOffset, mOffset);
WiredHome 0:108436d3cea9 84 }
WiredHome 0:108436d3cea9 85
WiredHome 2:cbcdd97f3a6d 86
WiredHome 0:108436d3cea9 87 int32_t RealTimeClock::GetTimeCalibration() {
WiredHome 0:108436d3cea9 88 int32_t calvalue = LPC_RTC->CALIBRATION & 0x3FFFF;
WiredHome 0:108436d3cea9 89
WiredHome 0:108436d3cea9 90 if (calvalue & 0x20000) {
WiredHome 0:108436d3cea9 91 calvalue = -(calvalue & 0x1FFFF);
WiredHome 0:108436d3cea9 92 }
WiredHome 0:108436d3cea9 93 return calvalue;
WiredHome 0:108436d3cea9 94 }
WiredHome 0:108436d3cea9 95
WiredHome 2:cbcdd97f3a6d 96
WiredHome 0:108436d3cea9 97 void RealTimeClock::SetTimeCalibration(int32_t calibration) {
WiredHome 2:cbcdd97f3a6d 98 if (calibration) {
WiredHome 2:cbcdd97f3a6d 99 if (calibration < 0) {
WiredHome 2:cbcdd97f3a6d 100 calibration = (-calibration & 0x1FFFF) | 0x20000;
WiredHome 2:cbcdd97f3a6d 101 }
WiredHome 2:cbcdd97f3a6d 102 LPC_RTC->CCR = 0x000001; //(LPC_RTC->CCR & 0x0003); // Clear CCALEN to enable it
WiredHome 2:cbcdd97f3a6d 103 } else {
WiredHome 2:cbcdd97f3a6d 104 LPC_RTC->CCR = 0x000011; //(LPC_RTC->CCR & 0x0003) | 0x0010; // Set CCALEN to disable it
WiredHome 0:108436d3cea9 105 }
WiredHome 0:108436d3cea9 106 LPC_RTC->CALIBRATION = calibration;
WiredHome 0:108436d3cea9 107 }
WiredHome 0:108436d3cea9 108
WiredHome 2:cbcdd97f3a6d 109
WiredHome 0:108436d3cea9 110 void RealTimeClock::SetTimeOffset(int offsetHour, int offsetMinute) {
WiredHome 0:108436d3cea9 111 tzOffsetHr = offsetHour;
WiredHome 0:108436d3cea9 112 tzOffsetMin = offsetMinute;
WiredHome 0:108436d3cea9 113 SetTimeOffsetStore();
WiredHome 0:108436d3cea9 114 }
WiredHome 0:108436d3cea9 115
WiredHome 2:cbcdd97f3a6d 116
WiredHome 0:108436d3cea9 117 void RealTimeClock::SetTimeOffsetStore() {
WiredHome 0:108436d3cea9 118 LPC_RTC->GPREG0 = tzOffsetHr * 256 + tzOffsetMin;
WiredHome 0:108436d3cea9 119 }
WiredHome 0:108436d3cea9 120
WiredHome 2:cbcdd97f3a6d 121
WiredHome 0:108436d3cea9 122 void RealTimeClock::GetTimeOffsetStore() {
WiredHome 0:108436d3cea9 123 tzOffsetHr = (int32_t)LPC_RTC->GPREG0 / 256;
WiredHome 0:108436d3cea9 124 tzOffsetMin = (LPC_RTC->GPREG0 & 0xFF);
WiredHome 0:108436d3cea9 125 }
WiredHome 0:108436d3cea9 126
WiredHome 2:cbcdd97f3a6d 127
WiredHome 0:108436d3cea9 128 // MM/DD/YYYY HH:MM:SS [(+/-hh:mm)]
WiredHome 0:108436d3cea9 129 bool RealTimeClock::SetTime(char * timestring) {
WiredHome 0:108436d3cea9 130 bool success = false;
WiredHome 0:108436d3cea9 131 char * p;
WiredHome 0:108436d3cea9 132 time_t seconds = time(NULL);
WiredHome 0:108436d3cea9 133 struct tm *t = localtime(&seconds);
WiredHome 0:108436d3cea9 134 int _oH, _oM;
WiredHome 0:108436d3cea9 135
WiredHome 0:108436d3cea9 136 p = strtok(timestring," /");
WiredHome 0:108436d3cea9 137 if (p != NULL) {
WiredHome 0:108436d3cea9 138 t->tm_mon = atoi(p) - 1;
WiredHome 0:108436d3cea9 139 p = strtok(NULL, " /");
WiredHome 0:108436d3cea9 140 if (p != NULL) {
WiredHome 0:108436d3cea9 141 t->tm_mday = atoi(p);
WiredHome 0:108436d3cea9 142 p = strtok(NULL, " /");
WiredHome 0:108436d3cea9 143 if (p != NULL) {
WiredHome 0:108436d3cea9 144 t->tm_year = atoi(p) - 1900;
WiredHome 0:108436d3cea9 145 p = strtok(NULL, " :");
WiredHome 0:108436d3cea9 146 if (p != NULL) {
WiredHome 0:108436d3cea9 147 t->tm_hour = atoi(p);
WiredHome 0:108436d3cea9 148 p = strtok(NULL, " :");
WiredHome 0:108436d3cea9 149 if (p != NULL) {
WiredHome 1:6d3d16f4b27c 150 t->tm_min = atoi(p);
WiredHome 1:6d3d16f4b27c 151 p = strtok(NULL, " (:");
WiredHome 1:6d3d16f4b27c 152 if (p != NULL) {
WiredHome 1:6d3d16f4b27c 153 t->tm_sec = atoi(p);
WiredHome 1:6d3d16f4b27c 154 success = true; // if we get to here, we're good
WiredHome 1:6d3d16f4b27c 155 p = strtok(NULL, " (:");
WiredHome 1:6d3d16f4b27c 156 if (p != NULL) {
WiredHome 1:6d3d16f4b27c 157 success = false; // but can't accept a partial tzo
WiredHome 1:6d3d16f4b27c 158 _oH = atoi(p);
WiredHome 1:6d3d16f4b27c 159 p = strtok(NULL, " (:)");
WiredHome 1:6d3d16f4b27c 160 if (p != NULL) {
WiredHome 1:6d3d16f4b27c 161 _oM = atoi(p);
WiredHome 1:6d3d16f4b27c 162 success = true; // but a whole tzo is ok
WiredHome 1:6d3d16f4b27c 163 SetTimeOffset(_oH, _oM);
WiredHome 1:6d3d16f4b27c 164 }
WiredHome 1:6d3d16f4b27c 165 }
WiredHome 1:6d3d16f4b27c 166 seconds = mktime(t);
WiredHome 1:6d3d16f4b27c 167 seconds = seconds - (time_t)(tzOffsetHr * 3600 + tzOffsetMin * 60);
WiredHome 1:6d3d16f4b27c 168 set_time(seconds);
WiredHome 1:6d3d16f4b27c 169 }
WiredHome 1:6d3d16f4b27c 170 }
WiredHome 0:108436d3cea9 171 }
WiredHome 0:108436d3cea9 172 }
WiredHome 0:108436d3cea9 173 }
WiredHome 0:108436d3cea9 174 }
WiredHome 0:108436d3cea9 175 return success;
WiredHome 0:108436d3cea9 176 }
WiredHome 0:108436d3cea9 177
WiredHome 0:108436d3cea9 178 #if 0
WiredHome 0:108436d3cea9 179 // GetNumber will get from the user a number using the
WiredHome 0:108436d3cea9 180 /// specified number of digits.
WiredHome 0:108436d3cea9 181 ///
WiredHome 0:108436d3cea9 182 /// They can enter a number from 0 to 10^(digits-1)
WiredHome 0:108436d3cea9 183 ///
WiredHome 0:108436d3cea9 184 /// @param digits is the number of digits to enter
WiredHome 0:108436d3cea9 185 /// @param pValue is a pointer to where to store the result
WiredHome 0:108436d3cea9 186 /// @returns true if a number was entered
WiredHome 0:108436d3cea9 187 /// @returns false if they entered a non-digit
WiredHome 0:108436d3cea9 188 ///
WiredHome 0:108436d3cea9 189 int GetNumber(int digits, int * pValue) {
WiredHome 0:108436d3cea9 190 int tempValue = 0;
WiredHome 0:108436d3cea9 191 int i;
WiredHome 0:108436d3cea9 192
WiredHome 0:108436d3cea9 193 while (digits--) {
WiredHome 0:108436d3cea9 194 while (!pc.readable())
WiredHome 0:108436d3cea9 195 wdt.Service();
WiredHome 0:108436d3cea9 196 i = pc.getc();
WiredHome 0:108436d3cea9 197 if (i == ' ') i = '0'; // special case for leading blank
WiredHome 0:108436d3cea9 198 if (i >= '0' && i <= '9') {
WiredHome 0:108436d3cea9 199 pc.putc(i);
WiredHome 0:108436d3cea9 200 tempValue = tempValue * 10 + (i - '0');
WiredHome 0:108436d3cea9 201 } else
WiredHome 0:108436d3cea9 202 return false;
WiredHome 0:108436d3cea9 203 }
WiredHome 0:108436d3cea9 204 *pValue = tempValue;
WiredHome 0:108436d3cea9 205 return true;
WiredHome 0:108436d3cea9 206 }
WiredHome 0:108436d3cea9 207
WiredHome 0:108436d3cea9 208 /// RTC_Set will interactively set the Real Time Clock
WiredHome 0:108436d3cea9 209 ///
WiredHome 0:108436d3cea9 210 /// It will allow you to enter the date and time information
WiredHome 0:108436d3cea9 211 /// and then create a timestamp. After this, it will set
WiredHome 0:108436d3cea9 212 /// the RTC to that timestamp.
WiredHome 0:108436d3cea9 213 ///
WiredHome 0:108436d3cea9 214 void RTC_Set(void) {
WiredHome 0:108436d3cea9 215 time_t seconds = time(NULL);
WiredHome 0:108436d3cea9 216 struct tm *t = localtime(&seconds);
WiredHome 0:108436d3cea9 217
WiredHome 0:108436d3cea9 218 pc.printf("RTC Set:\r\n");
WiredHome 0:108436d3cea9 219 GetTimeString(seconds, tzOffsetHr, tzOffsetMin);
WiredHome 0:108436d3cea9 220 pc.printf(" Enter the time MM/DD/YYYY HH:MM:SS\r\n");
WiredHome 0:108436d3cea9 221 while (1) {
WiredHome 0:108436d3cea9 222 int _m, _d, _y, _H, _M, _S;
WiredHome 0:108436d3cea9 223 printf(" > ");
WiredHome 0:108436d3cea9 224 if (GetNumber(2, &_m)) {
WiredHome 0:108436d3cea9 225 pc.putc('/');
WiredHome 0:108436d3cea9 226 if (!GetNumber(2, &_d))
WiredHome 0:108436d3cea9 227 continue;
WiredHome 0:108436d3cea9 228 pc.putc('/');
WiredHome 0:108436d3cea9 229 if (!GetNumber(4, &_y))
WiredHome 0:108436d3cea9 230 continue;
WiredHome 0:108436d3cea9 231 t->tm_mon = _m - 1;
WiredHome 0:108436d3cea9 232 t->tm_mday = _d;
WiredHome 0:108436d3cea9 233 t->tm_year = _y - 1900;
WiredHome 0:108436d3cea9 234 } else {
WiredHome 0:108436d3cea9 235 pc.printf("%02d/%02d/%04d", t->tm_mon+1, t->tm_mday, t->tm_year+1900);
WiredHome 0:108436d3cea9 236 }
WiredHome 0:108436d3cea9 237 pc.putc(' ');
WiredHome 0:108436d3cea9 238 if (GetNumber(2, &_H)) {
WiredHome 0:108436d3cea9 239 pc.putc(':');
WiredHome 0:108436d3cea9 240 if (!GetNumber(2, &_M))
WiredHome 0:108436d3cea9 241 continue;
WiredHome 0:108436d3cea9 242 pc.putc(':');
WiredHome 0:108436d3cea9 243 if (!GetNumber(2, &_S))
WiredHome 0:108436d3cea9 244 continue;
WiredHome 0:108436d3cea9 245 t->tm_hour = _H;
WiredHome 0:108436d3cea9 246 t->tm_min = _M;
WiredHome 0:108436d3cea9 247 t->tm_sec = _S;
WiredHome 0:108436d3cea9 248 pc.printf("\r\n");
WiredHome 0:108436d3cea9 249 pc.printf("%02d/%02d/%04d ", t->tm_mon+1, t->tm_mday, t->tm_year+1900);
WiredHome 0:108436d3cea9 250 pc.printf("%02d:%02d:%02d\r\n", t->tm_hour, t->tm_min, t->tm_sec);
WiredHome 0:108436d3cea9 251 // convert to timestamp and display (1256729737)
WiredHome 0:108436d3cea9 252 time_t seconds = mktime(t);
WiredHome 0:108436d3cea9 253 seconds = seconds - (time_t)(tzOffsetHr * 3600 + tzOffsetMin * 60);
WiredHome 0:108436d3cea9 254 set_time(seconds);
WiredHome 0:108436d3cea9 255 break;
WiredHome 0:108436d3cea9 256 } else {
WiredHome 0:108436d3cea9 257 pc.printf("%02d:%02d:%02d\r\n", t->tm_hour, t->tm_min, t->tm_sec);
WiredHome 0:108436d3cea9 258 break; // they can bail here
WiredHome 0:108436d3cea9 259 }
WiredHome 0:108436d3cea9 260 }
WiredHome 0:108436d3cea9 261 }
WiredHome 0:108436d3cea9 262 #endif