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:
Sun May 29 20:34:27 2011 +0000
Revision:
1:6d3d16f4b27c
Parent:
0:108436d3cea9
Child:
2:cbcdd97f3a6d
v1.01 slightly improved documentation

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