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:11:27 2011 +0000
Revision:
0:108436d3cea9
Child:
1:6d3d16f4b27c
Initial release of a real time clock management library

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