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.
Revision 0:108436d3cea9, committed 2011-05-29
- Comitter:
- WiredHome
- Date:
- Sun May 29 20:11:27 2011 +0000
- Child:
- 1:6d3d16f4b27c
- Commit message:
- Initial release of a real time clock management library
Changed in this revision
TimeUtilities.cpp | Show annotated file Show diff for this revision Revisions of this file |
TimeUtilities.h | Show annotated file Show diff for this revision Revisions of this file |
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TimeUtilities.cpp Sun May 29 20:11:27 2011 +0000 @@ -0,0 +1,231 @@ +/// @file TimeUtilities.cpp contains a real time clock interface for the mbed +/// +/// APIs for showing the time from the RTC, or from a passed in value. +/// Also supports setting the clock, timezone offsets and calibration +/// of the RTC subsystem. +/// +/// @note Copyright © 2011 by Smartware Computing, all rights reserved. +/// @author David Smart +/// +#ifndef WIN32 +// embedded build +#include "mbed.h" +#endif + +#include "TimeUtilities.h" +#include <time.h> +#include <string.h> +#include <stdio.h> +#include <stdlib.h> + +#ifdef WIN32 +// Fake it out for Win32 +struct LPC { + unsigned long GPREG0; + unsigned long CALIBRATION; +}; +struct LPC X; +struct LPC * LPC_RTC = &X; +#define set_time(x) (void)x +#endif + +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 int SignOf(const int i) { + return (i >= 0) ? 1 : -1; +} + +RealTimeClock::RealTimeClock() { + GetTimeOffsetStore(); +} + +RealTimeClock::~RealTimeClock() { +} + +void RealTimeClock::GetTimeString(char *buf, time_t tValue) { + GetTimeOffsetStore(); // Load the time zone offset values from the battery ram + GetTimeString(buf, tValue, tzOffsetHr, tzOffsetMin); +} + +void RealTimeClock::GetTimeString(char *buf, int hOffset, int mOffset) { + GetTimeString(buf, 0, hOffset, mOffset); +} + +void RealTimeClock::GetTimeString(char *buf, time_t tValue, int hOffset, int mOffset) { + time_t ctTime; + + if (tValue == 0) + tValue = time(NULL); + ctTime = tValue + hOffset * 3600 + SignOf(hOffset) * mOffset * 60; + strcpy(buf, ctime(&ctTime)); + buf[strlen(buf)-1] = '\0'; // remove the \n + sprintf(buf + strlen(buf), " (tzo: %2i:%02i)", hOffset, mOffset); +} + +int32_t RealTimeClock::GetTimeCalibration() { + int32_t calvalue = LPC_RTC->CALIBRATION & 0x3FFFF; + + if (calvalue & 0x20000) { + calvalue = -(calvalue & 0x1FFFF); + } + return calvalue; +} + +void RealTimeClock::SetTimeCalibration(int32_t calibration) { + if (calibration < 0) { + calibration = (-calibration & 0x1FFFF) | 0x20000; + } + LPC_RTC->CALIBRATION = calibration; +} + +void RealTimeClock::SetTimeOffset(int offsetHour, int offsetMinute) { + tzOffsetHr = offsetHour; + tzOffsetMin = offsetMinute; + SetTimeOffsetStore(); +} + +void RealTimeClock::SetTimeOffsetStore() { + LPC_RTC->GPREG0 = tzOffsetHr * 256 + tzOffsetMin; +} + +void RealTimeClock::GetTimeOffsetStore() { + tzOffsetHr = (int32_t)LPC_RTC->GPREG0 / 256; + tzOffsetMin = (LPC_RTC->GPREG0 & 0xFF); +} + +// MM/DD/YYYY HH:MM:SS [(+/-hh:mm)] +bool RealTimeClock::SetTime(char * timestring) { + bool success = false; + char * p; + time_t seconds = time(NULL); + struct tm *t = localtime(&seconds); + int _oH, _oM; + + p = strtok(timestring," /"); + if (p != NULL) { + t->tm_mon = atoi(p) - 1; + p = strtok(NULL, " /"); + if (p != NULL) { + t->tm_mday = atoi(p); + p = strtok(NULL, " /"); + if (p != NULL) { + t->tm_year = atoi(p) - 1900; + p = strtok(NULL, " :"); + if (p != NULL) { + t->tm_hour = atoi(p); + p = strtok(NULL, " :"); + if (p != NULL) { + t->tm_min = atoi(p); + p = strtok(NULL, " (:"); + if (p != NULL) { + t->tm_sec = atoi(p); + success = true; // if we get to here, we're good + p = strtok(NULL, " (:"); + if (p != NULL) { + success = false; // but can't accept a partial tzo + _oH = atoi(p); + p = strtok(NULL, " (:)"); + if (p != NULL) { + _oM = atoi(p); + success = true; // but a whole tzo is ok + SetTimeOffset(_oH, _oM); + } + } + seconds = mktime(t); + seconds = seconds - (time_t)(tzOffsetHr * 3600 + tzOffsetMin * 60); + set_time(seconds); + } + } + } + } + } + } + return success; +} + +#if 0 +// GetNumber will get from the user a number using the +/// specified number of digits. +/// +/// They can enter a number from 0 to 10^(digits-1) +/// +/// @param digits is the number of digits to enter +/// @param pValue is a pointer to where to store the result +/// @returns true if a number was entered +/// @returns false if they entered a non-digit +/// +int GetNumber(int digits, int * pValue) { + int tempValue = 0; + int i; + + while (digits--) { + while (!pc.readable()) + wdt.Service(); + i = pc.getc(); + if (i == ' ') i = '0'; // special case for leading blank + if (i >= '0' && i <= '9') { + pc.putc(i); + tempValue = tempValue * 10 + (i - '0'); + } else + return false; + } + *pValue = tempValue; + return true; +} + +/// RTC_Set will interactively set the Real Time Clock +/// +/// It will allow you to enter the date and time information +/// and then create a timestamp. After this, it will set +/// the RTC to that timestamp. +/// +void RTC_Set(void) { + time_t seconds = time(NULL); + struct tm *t = localtime(&seconds); + + pc.printf("RTC Set:\r\n"); + GetTimeString(seconds, tzOffsetHr, tzOffsetMin); + pc.printf(" Enter the time MM/DD/YYYY HH:MM:SS\r\n"); + while (1) { + int _m, _d, _y, _H, _M, _S; + printf(" > "); + if (GetNumber(2, &_m)) { + pc.putc('/'); + if (!GetNumber(2, &_d)) + continue; + pc.putc('/'); + if (!GetNumber(4, &_y)) + continue; + t->tm_mon = _m - 1; + t->tm_mday = _d; + t->tm_year = _y - 1900; + } else { + pc.printf("%02d/%02d/%04d", t->tm_mon+1, t->tm_mday, t->tm_year+1900); + } + pc.putc(' '); + if (GetNumber(2, &_H)) { + pc.putc(':'); + if (!GetNumber(2, &_M)) + continue; + pc.putc(':'); + if (!GetNumber(2, &_S)) + continue; + t->tm_hour = _H; + t->tm_min = _M; + t->tm_sec = _S; + pc.printf("\r\n"); + pc.printf("%02d/%02d/%04d ", t->tm_mon+1, t->tm_mday, t->tm_year+1900); + pc.printf("%02d:%02d:%02d\r\n", t->tm_hour, t->tm_min, t->tm_sec); + // convert to timestamp and display (1256729737) + time_t seconds = mktime(t); + seconds = seconds - (time_t)(tzOffsetHr * 3600 + tzOffsetMin * 60); + set_time(seconds); + break; + } else { + pc.printf("%02d:%02d:%02d\r\n", t->tm_hour, t->tm_min, t->tm_sec); + break; // they can bail here + } + } +} +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TimeUtilities.h Sun May 29 20:11:27 2011 +0000 @@ -0,0 +1,158 @@ +/// @file TimeUtilities.h contains a real time clock interface for the mbed +/// +/// APIs for showing the time from the RTC, or from a passed in value. +/// Also supports setting the clock, timezone offsets and calibration +/// of the RTC subsystem. +/// +/// @note Copyright © 2011 by Smartware Computing, all rights reserved. +/// @author David Smart +/// +#ifndef TIMEUTILITIES_H +#define TIMEUTILITIES_H + +#ifndef WIN32 +// embedded build +#include "mbed.h" +#else +// fake it for Windows build +typedef int int32_t; +#endif + +#include <time.h> + +class RealTimeClock +{ +public: + /// RealTimeClock is an interface to the mbed RTC module + /// + /// It provides interfaces to get and set the time in text representation + /// as well as a means to get and set the timezone offset, so that it + /// maintains time in UTC format. + /// + /// Additionally, it provides an interface to adjust the calibration + /// registers of the RTC, to compensate for 32 kHz clock error, whether + /// based on the oscillator itself or on some bias to ambient temperature. + /// + /// Example: + /// @code + /// RealTimeClock rtc; + /// + /// void main() { + /// bool success; + /// char TimeTest[] = "05/29/2011 14:15:18 (-6:00)"; + /// char buf[50]; + /// + /// success = rtc.SetTime(Test); + /// rtc.GetTimeString(buf); + /// printf("success: %i, time: %s\n", success, buf); + /// } + /// prints + /// "success: 1, time: Sun May 29 14:15:18 2011 (tzo: -6:00)" + /// + RealTimeClock(); + + /// Destructor for the RealTimeClock - normally not used + ~RealTimeClock(); + + /// GetTimeString gets the formatted time applying the internal time-zone offset of hours and minutes + /// + /// It places the formatted string into the buffer in the format of + /// Sun May 29 07:19:24 2011 (tzo: -6:00) + /// The internal timezone offset can be set with SetTimeOffset + /// + /// @param buffer is a pointer to a buffer large enough (>= 40 chars) for the formatted time string + /// @param tValue is the optional time value to convert to text, if zero, then the current + /// time is used. + /// @returns nothing + /// + void GetTimeString(char * buffer, time_t tValue = 0); + + /// GetTimeString gets the formatted time applying the time-zone offset of hours and minutes + /// + /// It places the formatted string into the buffer in the format of + /// Sun May 29 07:19:24 2011 (tzo: -6:00) + /// + /// @param buffer is a pointer to a buffer large enough (>= 40 chars) for the formatted time string + /// @param hOffset is the hours offset + /// @param mOffset is the minutes offset + /// @returns nothing + /// + void GetTimeString(char * buffer, int hOffset, int mOffset); + + /// GetTimeString gets the formatted time value applying the time-zone offset of hours and minutes + /// + /// It places the formatted string into the buffer in the format of + /// Sun May 29 07:19:24 2011 (tzo: -6:00) + /// + /// @param buffer is a pointer to a buffer large enough (>= 40 chars) for the formatted time string + /// @param tValue is the time value to convert to text, if zero, then the current + /// time is used. + /// @param hOffset is the hours offset + /// @param mOffset is the minutes offset + /// @returns nothing + /// + void GetTimeString(char * buffer, time_t tValue, int hOffset, int mOffset); + + /// SetTimeOffset will set the hour and minute timezone offset + /// + /// @param offsetHour is the timezone offset in hours + /// @param offsetMinute is the timezone offset in minutes + /// @returns nothing + /// + void SetTimeOffset(int offsetHour, int offsetMinute); + + /// SetTimeOffsetStore will store the timezone offset values in RTC ram + /// + /// This takes the current timezone offset values and stores them in + /// the RTC battery backed ram. + /// + /// @returns nothing + /// + void SetTimeOffsetStore(); + + /// GetTimeOffsetStore will extract the timezone offset values from RTC ram + /// + /// This extracts the timezone offset values that were stored in RTC + /// battery backed ram and uses them for time information. + /// + /// @returns nothing + /// + void GetTimeOffsetStore(); + + /// GetTimeCalibration will return the calibration register value + /// + /// This is the raw register value as a signed 32-bit value (even though + /// it is actually a 17-bit unsigned value with an additional 'direction' flag). + /// + /// @returns calibration settings ranging from -131071 to +131071 + /// + int32_t GetTimeCalibration(); + + /// SetTimeCalibration will set the calibration register value + /// + /// This accepts a signed value to be used to set the calibration + /// registers. Setting the calibration value to zero disables the + /// calibration function. + /// + /// @param calibration value to use ranging from -131071 to +131071 + /// @returns nothing + /// + void SetTimeCalibration(int32_t calibration); + + + /// SetTime will set the Real Time Clock from a well formatted string + /// + /// This will read a string, and if it is well formed, it will then + /// set the RTC based on this string. The string should be of the form: + /// 'MM/DD/YYYY HH:MM:SS' and may have the optional timezone offset + /// of the form '(+/-HH:MM)' + /// + /// example: 05/29/2011 13:15:07 (-6:00) + /// + /// @param timestring is the string to parse + /// @returns true if the time was set + /// + bool SetTime(char * timestring); +}; + +#endif