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:
Thu Jun 16 21:11:44 2011 +0000
Revision:
3:524ad47afdc7
Parent:
2:cbcdd97f3a6d
Child:
5:fbbdf57675c3
v1.02 minor documentation updates

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 3:524ad47afdc7 19 /// 20110616
WiredHome 3:524ad47afdc7 20 /// \li minor documentation changes
WiredHome 2:cbcdd97f3a6d 21 /// 20110601
WiredHome 2:cbcdd97f3a6d 22 /// \li discovered the CCALEN flag to enable calibration
WiredHome 2:cbcdd97f3a6d 23 /// 20110529
WiredHome 2:cbcdd97f3a6d 24 /// \li original version
WiredHome 2:cbcdd97f3a6d 25 ///
WiredHome 0:108436d3cea9 26 #ifndef WIN32
WiredHome 0:108436d3cea9 27 // embedded build
WiredHome 0:108436d3cea9 28 #include "mbed.h"
WiredHome 0:108436d3cea9 29 #endif
WiredHome 0:108436d3cea9 30
WiredHome 0:108436d3cea9 31 #include "TimeUtilities.h"
WiredHome 0:108436d3cea9 32 #include <time.h>
WiredHome 0:108436d3cea9 33 #include <string.h>
WiredHome 0:108436d3cea9 34 #include <stdio.h>
WiredHome 0:108436d3cea9 35 #include <stdlib.h>
WiredHome 0:108436d3cea9 36
WiredHome 0:108436d3cea9 37 #ifdef WIN32
WiredHome 3:524ad47afdc7 38 // Fake it out for Win32 development and testing
WiredHome 0:108436d3cea9 39 struct LPC {
WiredHome 2:cbcdd97f3a6d 40 unsigned long CCR; // Clock Control register
WiredHome 2:cbcdd97f3a6d 41 unsigned long GPREG0; // General Purpose Register - Battery backed
WiredHome 2:cbcdd97f3a6d 42 unsigned long CALIBRATION; // Calibration Register
WiredHome 0:108436d3cea9 43 };
WiredHome 0:108436d3cea9 44 struct LPC X;
WiredHome 0:108436d3cea9 45 struct LPC * LPC_RTC = &X;
WiredHome 0:108436d3cea9 46 #define set_time(x) (void)x
WiredHome 0:108436d3cea9 47 #endif
WiredHome 0:108436d3cea9 48
WiredHome 0:108436d3cea9 49 static int tzOffsetHr = 0; ///!< time zone offset hours to print time in local time
WiredHome 0:108436d3cea9 50 static int tzOffsetMin = 0; ///!< time zone offset minutes to print time in local time
WiredHome 0:108436d3cea9 51
WiredHome 0:108436d3cea9 52 static int SignOf(const int i) {
WiredHome 0:108436d3cea9 53 return (i >= 0) ? 1 : -1;
WiredHome 0:108436d3cea9 54 }
WiredHome 0:108436d3cea9 55
WiredHome 2:cbcdd97f3a6d 56
WiredHome 0:108436d3cea9 57 RealTimeClock::RealTimeClock() {
WiredHome 1:6d3d16f4b27c 58 GetTimeOffsetStore();
WiredHome 0:108436d3cea9 59 }
WiredHome 0:108436d3cea9 60
WiredHome 2:cbcdd97f3a6d 61
WiredHome 0:108436d3cea9 62 RealTimeClock::~RealTimeClock() {
WiredHome 0:108436d3cea9 63 }
WiredHome 0:108436d3cea9 64
WiredHome 2:cbcdd97f3a6d 65
WiredHome 0:108436d3cea9 66 void RealTimeClock::GetTimeString(char *buf, time_t tValue) {
WiredHome 0:108436d3cea9 67 GetTimeOffsetStore(); // Load the time zone offset values from the battery ram
WiredHome 0:108436d3cea9 68 GetTimeString(buf, tValue, tzOffsetHr, tzOffsetMin);
WiredHome 0:108436d3cea9 69 }
WiredHome 0:108436d3cea9 70
WiredHome 2:cbcdd97f3a6d 71
WiredHome 0:108436d3cea9 72 void RealTimeClock::GetTimeString(char *buf, int hOffset, int mOffset) {
WiredHome 0:108436d3cea9 73 GetTimeString(buf, 0, hOffset, mOffset);
WiredHome 0:108436d3cea9 74 }
WiredHome 0:108436d3cea9 75
WiredHome 2:cbcdd97f3a6d 76
WiredHome 0:108436d3cea9 77 void RealTimeClock::GetTimeString(char *buf, time_t tValue, int hOffset, int mOffset) {
WiredHome 0:108436d3cea9 78 time_t ctTime;
WiredHome 0:108436d3cea9 79
WiredHome 0:108436d3cea9 80 if (tValue == 0)
WiredHome 0:108436d3cea9 81 tValue = time(NULL);
WiredHome 0:108436d3cea9 82 ctTime = tValue + hOffset * 3600 + SignOf(hOffset) * mOffset * 60;
WiredHome 0:108436d3cea9 83 strcpy(buf, ctime(&ctTime));
WiredHome 0:108436d3cea9 84 buf[strlen(buf)-1] = '\0'; // remove the \n
WiredHome 0:108436d3cea9 85 sprintf(buf + strlen(buf), " (tzo: %2i:%02i)", hOffset, mOffset);
WiredHome 0:108436d3cea9 86 }
WiredHome 0:108436d3cea9 87
WiredHome 2:cbcdd97f3a6d 88
WiredHome 0:108436d3cea9 89 int32_t RealTimeClock::GetTimeCalibration() {
WiredHome 0:108436d3cea9 90 int32_t calvalue = LPC_RTC->CALIBRATION & 0x3FFFF;
WiredHome 0:108436d3cea9 91
WiredHome 0:108436d3cea9 92 if (calvalue & 0x20000) {
WiredHome 0:108436d3cea9 93 calvalue = -(calvalue & 0x1FFFF);
WiredHome 0:108436d3cea9 94 }
WiredHome 0:108436d3cea9 95 return calvalue;
WiredHome 0:108436d3cea9 96 }
WiredHome 0:108436d3cea9 97
WiredHome 2:cbcdd97f3a6d 98
WiredHome 0:108436d3cea9 99 void RealTimeClock::SetTimeCalibration(int32_t calibration) {
WiredHome 2:cbcdd97f3a6d 100 if (calibration) {
WiredHome 2:cbcdd97f3a6d 101 if (calibration < 0) {
WiredHome 2:cbcdd97f3a6d 102 calibration = (-calibration & 0x1FFFF) | 0x20000;
WiredHome 2:cbcdd97f3a6d 103 }
WiredHome 2:cbcdd97f3a6d 104 LPC_RTC->CCR = 0x000001; //(LPC_RTC->CCR & 0x0003); // Clear CCALEN to enable it
WiredHome 2:cbcdd97f3a6d 105 } else {
WiredHome 2:cbcdd97f3a6d 106 LPC_RTC->CCR = 0x000011; //(LPC_RTC->CCR & 0x0003) | 0x0010; // Set CCALEN to disable it
WiredHome 0:108436d3cea9 107 }
WiredHome 0:108436d3cea9 108 LPC_RTC->CALIBRATION = calibration;
WiredHome 0:108436d3cea9 109 }
WiredHome 0:108436d3cea9 110
WiredHome 2:cbcdd97f3a6d 111
WiredHome 0:108436d3cea9 112 void RealTimeClock::SetTimeOffset(int offsetHour, int offsetMinute) {
WiredHome 0:108436d3cea9 113 tzOffsetHr = offsetHour;
WiredHome 0:108436d3cea9 114 tzOffsetMin = offsetMinute;
WiredHome 0:108436d3cea9 115 SetTimeOffsetStore();
WiredHome 0:108436d3cea9 116 }
WiredHome 0:108436d3cea9 117
WiredHome 2:cbcdd97f3a6d 118
WiredHome 0:108436d3cea9 119 void RealTimeClock::SetTimeOffsetStore() {
WiredHome 0:108436d3cea9 120 LPC_RTC->GPREG0 = tzOffsetHr * 256 + tzOffsetMin;
WiredHome 0:108436d3cea9 121 }
WiredHome 0:108436d3cea9 122
WiredHome 2:cbcdd97f3a6d 123
WiredHome 0:108436d3cea9 124 void RealTimeClock::GetTimeOffsetStore() {
WiredHome 0:108436d3cea9 125 tzOffsetHr = (int32_t)LPC_RTC->GPREG0 / 256;
WiredHome 0:108436d3cea9 126 tzOffsetMin = (LPC_RTC->GPREG0 & 0xFF);
WiredHome 0:108436d3cea9 127 }
WiredHome 0:108436d3cea9 128
WiredHome 2:cbcdd97f3a6d 129
WiredHome 0:108436d3cea9 130 // MM/DD/YYYY HH:MM:SS [(+/-hh:mm)]
WiredHome 0:108436d3cea9 131 bool RealTimeClock::SetTime(char * timestring) {
WiredHome 0:108436d3cea9 132 bool success = false;
WiredHome 0:108436d3cea9 133 char * p;
WiredHome 0:108436d3cea9 134 time_t seconds = time(NULL);
WiredHome 0:108436d3cea9 135 struct tm *t = localtime(&seconds);
WiredHome 0:108436d3cea9 136 int _oH, _oM;
WiredHome 0:108436d3cea9 137
WiredHome 0:108436d3cea9 138 p = strtok(timestring," /");
WiredHome 0:108436d3cea9 139 if (p != NULL) {
WiredHome 0:108436d3cea9 140 t->tm_mon = atoi(p) - 1;
WiredHome 0:108436d3cea9 141 p = strtok(NULL, " /");
WiredHome 0:108436d3cea9 142 if (p != NULL) {
WiredHome 0:108436d3cea9 143 t->tm_mday = atoi(p);
WiredHome 0:108436d3cea9 144 p = strtok(NULL, " /");
WiredHome 0:108436d3cea9 145 if (p != NULL) {
WiredHome 0:108436d3cea9 146 t->tm_year = atoi(p) - 1900;
WiredHome 0:108436d3cea9 147 p = strtok(NULL, " :");
WiredHome 0:108436d3cea9 148 if (p != NULL) {
WiredHome 0:108436d3cea9 149 t->tm_hour = atoi(p);
WiredHome 0:108436d3cea9 150 p = strtok(NULL, " :");
WiredHome 0:108436d3cea9 151 if (p != NULL) {
WiredHome 1:6d3d16f4b27c 152 t->tm_min = atoi(p);
WiredHome 1:6d3d16f4b27c 153 p = strtok(NULL, " (:");
WiredHome 1:6d3d16f4b27c 154 if (p != NULL) {
WiredHome 1:6d3d16f4b27c 155 t->tm_sec = atoi(p);
WiredHome 1:6d3d16f4b27c 156 success = true; // if we get to here, we're good
WiredHome 1:6d3d16f4b27c 157 p = strtok(NULL, " (:");
WiredHome 1:6d3d16f4b27c 158 if (p != NULL) {
WiredHome 1:6d3d16f4b27c 159 success = false; // but can't accept a partial tzo
WiredHome 1:6d3d16f4b27c 160 _oH = atoi(p);
WiredHome 1:6d3d16f4b27c 161 p = strtok(NULL, " (:)");
WiredHome 1:6d3d16f4b27c 162 if (p != NULL) {
WiredHome 1:6d3d16f4b27c 163 _oM = atoi(p);
WiredHome 1:6d3d16f4b27c 164 success = true; // but a whole tzo is ok
WiredHome 1:6d3d16f4b27c 165 SetTimeOffset(_oH, _oM);
WiredHome 1:6d3d16f4b27c 166 }
WiredHome 1:6d3d16f4b27c 167 }
WiredHome 1:6d3d16f4b27c 168 seconds = mktime(t);
WiredHome 1:6d3d16f4b27c 169 seconds = seconds - (time_t)(tzOffsetHr * 3600 + tzOffsetMin * 60);
WiredHome 1:6d3d16f4b27c 170 set_time(seconds);
WiredHome 1:6d3d16f4b27c 171 }
WiredHome 1:6d3d16f4b27c 172 }
WiredHome 0:108436d3cea9 173 }
WiredHome 0:108436d3cea9 174 }
WiredHome 0:108436d3cea9 175 }
WiredHome 0:108436d3cea9 176 }
WiredHome 0:108436d3cea9 177 return success;
WiredHome 0:108436d3cea9 178 }
WiredHome 0:108436d3cea9 179