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:
foxbrianr
Date:
Thu Jul 25 00:43:33 2019 +0000
Revision:
7:812452a275fa
Parent:
6:a517fee06e2e
Baseline for testing

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 6:a517fee06e2e 23 #define VERSION "1.04"
WiredHome 5:fbbdf57675c3 24
WiredHome 0:108436d3cea9 25 #include "TimeUtilities.h"
WiredHome 0:108436d3cea9 26 #include <time.h>
WiredHome 0:108436d3cea9 27 #include <string.h>
WiredHome 0:108436d3cea9 28 #include <stdio.h>
WiredHome 0:108436d3cea9 29 #include <stdlib.h>
WiredHome 0:108436d3cea9 30
WiredHome 0:108436d3cea9 31 #ifdef WIN32
WiredHome 3:524ad47afdc7 32 // Fake it out for Win32 development and testing
WiredHome 0:108436d3cea9 33 struct LPC {
WiredHome 2:cbcdd97f3a6d 34 unsigned long CCR; // Clock Control register
WiredHome 5:fbbdf57675c3 35 unsigned long GPREG0; // General Purpose Register #0 - 32-bit Battery backed
WiredHome 5:fbbdf57675c3 36 unsigned long GPREG1; // General Purpose Register #1 - 32-bit Battery backed
WiredHome 2:cbcdd97f3a6d 37 unsigned long CALIBRATION; // Calibration Register
WiredHome 0:108436d3cea9 38 };
WiredHome 0:108436d3cea9 39 struct LPC X;
WiredHome 0:108436d3cea9 40 struct LPC * LPC_RTC = &X;
WiredHome 0:108436d3cea9 41 #define set_time(x) (void)x
WiredHome 0:108436d3cea9 42 #endif
WiredHome 0:108436d3cea9 43
WiredHome 0:108436d3cea9 44 static int tzOffsetHr = 0; ///!< time zone offset hours to print time in local time
WiredHome 0:108436d3cea9 45 static int tzOffsetMin = 0; ///!< time zone offset minutes to print time in local time
WiredHome 5:fbbdf57675c3 46
WiredHome 5:fbbdf57675c3 47
WiredHome 5:fbbdf57675c3 48 static const char ver[] = VERSION;
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 5:fbbdf57675c3 63 const char * RealTimeClock::GetVersion() {
WiredHome 5:fbbdf57675c3 64 return ver;
WiredHome 5:fbbdf57675c3 65 }
WiredHome 5:fbbdf57675c3 66
WiredHome 5:fbbdf57675c3 67 time_t RealTimeClock::GetTimeValue() {
WiredHome 5:fbbdf57675c3 68 return time(NULL);
WiredHome 5:fbbdf57675c3 69 }
WiredHome 5:fbbdf57675c3 70
WiredHome 2:cbcdd97f3a6d 71
WiredHome 0:108436d3cea9 72 void RealTimeClock::GetTimeString(char *buf, time_t tValue) {
WiredHome 0:108436d3cea9 73 GetTimeOffsetStore(); // Load the time zone offset values from the battery ram
WiredHome 0:108436d3cea9 74 GetTimeString(buf, tValue, tzOffsetHr, tzOffsetMin);
WiredHome 0:108436d3cea9 75 }
WiredHome 0:108436d3cea9 76
WiredHome 2:cbcdd97f3a6d 77
WiredHome 0:108436d3cea9 78 void RealTimeClock::GetTimeString(char *buf, int hOffset, int mOffset) {
WiredHome 0:108436d3cea9 79 GetTimeString(buf, 0, hOffset, mOffset);
WiredHome 0:108436d3cea9 80 }
WiredHome 0:108436d3cea9 81
WiredHome 2:cbcdd97f3a6d 82
WiredHome 0:108436d3cea9 83 void RealTimeClock::GetTimeString(char *buf, time_t tValue, int hOffset, int mOffset) {
WiredHome 0:108436d3cea9 84 time_t ctTime;
WiredHome 0:108436d3cea9 85
WiredHome 0:108436d3cea9 86 if (tValue == 0)
WiredHome 0:108436d3cea9 87 tValue = time(NULL);
WiredHome 0:108436d3cea9 88 ctTime = tValue + hOffset * 3600 + SignOf(hOffset) * mOffset * 60;
WiredHome 0:108436d3cea9 89 strcpy(buf, ctime(&ctTime));
WiredHome 0:108436d3cea9 90 buf[strlen(buf)-1] = '\0'; // remove the \n
foxbrianr 7:812452a275fa 91 //sprintf(buf + strlen(buf), " (tzo: %2i:%02i)", hOffset, mOffset);
WiredHome 0:108436d3cea9 92 }
WiredHome 0:108436d3cea9 93
WiredHome 2:cbcdd97f3a6d 94
WiredHome 0:108436d3cea9 95 int32_t RealTimeClock::GetTimeCalibration() {
WiredHome 0:108436d3cea9 96 int32_t calvalue = LPC_RTC->CALIBRATION & 0x3FFFF;
WiredHome 0:108436d3cea9 97
WiredHome 0:108436d3cea9 98 if (calvalue & 0x20000) {
WiredHome 0:108436d3cea9 99 calvalue = -(calvalue & 0x1FFFF);
WiredHome 0:108436d3cea9 100 }
WiredHome 0:108436d3cea9 101 return calvalue;
WiredHome 0:108436d3cea9 102 }
WiredHome 0:108436d3cea9 103
WiredHome 2:cbcdd97f3a6d 104
WiredHome 0:108436d3cea9 105 void RealTimeClock::SetTimeCalibration(int32_t calibration) {
WiredHome 2:cbcdd97f3a6d 106 if (calibration) {
WiredHome 2:cbcdd97f3a6d 107 if (calibration < 0) {
WiredHome 2:cbcdd97f3a6d 108 calibration = (-calibration & 0x1FFFF) | 0x20000;
WiredHome 2:cbcdd97f3a6d 109 }
WiredHome 2:cbcdd97f3a6d 110 LPC_RTC->CCR = 0x000001; //(LPC_RTC->CCR & 0x0003); // Clear CCALEN to enable it
WiredHome 2:cbcdd97f3a6d 111 } else {
WiredHome 2:cbcdd97f3a6d 112 LPC_RTC->CCR = 0x000011; //(LPC_RTC->CCR & 0x0003) | 0x0010; // Set CCALEN to disable it
WiredHome 0:108436d3cea9 113 }
WiredHome 0:108436d3cea9 114 LPC_RTC->CALIBRATION = calibration;
WiredHome 0:108436d3cea9 115 }
WiredHome 0:108436d3cea9 116
WiredHome 2:cbcdd97f3a6d 117
WiredHome 0:108436d3cea9 118 void RealTimeClock::SetTimeOffset(int offsetHour, int offsetMinute) {
WiredHome 0:108436d3cea9 119 tzOffsetHr = offsetHour;
WiredHome 0:108436d3cea9 120 tzOffsetMin = offsetMinute;
WiredHome 0:108436d3cea9 121 SetTimeOffsetStore();
WiredHome 0:108436d3cea9 122 }
WiredHome 0:108436d3cea9 123
WiredHome 2:cbcdd97f3a6d 124
WiredHome 0:108436d3cea9 125 void RealTimeClock::SetTimeOffsetStore() {
WiredHome 0:108436d3cea9 126 LPC_RTC->GPREG0 = tzOffsetHr * 256 + tzOffsetMin;
WiredHome 0:108436d3cea9 127 }
WiredHome 0:108436d3cea9 128
WiredHome 2:cbcdd97f3a6d 129
WiredHome 0:108436d3cea9 130 void RealTimeClock::GetTimeOffsetStore() {
WiredHome 0:108436d3cea9 131 tzOffsetHr = (int32_t)LPC_RTC->GPREG0 / 256;
WiredHome 0:108436d3cea9 132 tzOffsetMin = (LPC_RTC->GPREG0 & 0xFF);
WiredHome 0:108436d3cea9 133 }
WiredHome 0:108436d3cea9 134
WiredHome 6:a517fee06e2e 135 void RealTimeClock::SetTimeLastSet(time_t t) {
WiredHome 6:a517fee06e2e 136 LPC_RTC->GPREG1 = t;
WiredHome 5:fbbdf57675c3 137 }
WiredHome 5:fbbdf57675c3 138
WiredHome 6:a517fee06e2e 139 time_t RealTimeClock::GetTimeLastSet() {
WiredHome 6:a517fee06e2e 140 return LPC_RTC->GPREG1;
WiredHome 5:fbbdf57675c3 141 }
WiredHome 2:cbcdd97f3a6d 142
WiredHome 0:108436d3cea9 143 // MM/DD/YYYY HH:MM:SS [(+/-hh:mm)]
WiredHome 0:108436d3cea9 144 bool RealTimeClock::SetTime(char * timestring) {
WiredHome 0:108436d3cea9 145 bool success = false;
WiredHome 0:108436d3cea9 146 char * p;
WiredHome 0:108436d3cea9 147 time_t seconds = time(NULL);
WiredHome 0:108436d3cea9 148 struct tm *t = localtime(&seconds);
WiredHome 0:108436d3cea9 149 int _oH, _oM;
WiredHome 0:108436d3cea9 150
WiredHome 0:108436d3cea9 151 p = strtok(timestring," /");
WiredHome 0:108436d3cea9 152 if (p != NULL) {
WiredHome 0:108436d3cea9 153 t->tm_mon = atoi(p) - 1;
WiredHome 0:108436d3cea9 154 p = strtok(NULL, " /");
WiredHome 0:108436d3cea9 155 if (p != NULL) {
WiredHome 0:108436d3cea9 156 t->tm_mday = atoi(p);
WiredHome 0:108436d3cea9 157 p = strtok(NULL, " /");
WiredHome 0:108436d3cea9 158 if (p != NULL) {
WiredHome 0:108436d3cea9 159 t->tm_year = atoi(p) - 1900;
WiredHome 0:108436d3cea9 160 p = strtok(NULL, " :");
WiredHome 0:108436d3cea9 161 if (p != NULL) {
WiredHome 0:108436d3cea9 162 t->tm_hour = atoi(p);
WiredHome 0:108436d3cea9 163 p = strtok(NULL, " :");
WiredHome 0:108436d3cea9 164 if (p != NULL) {
WiredHome 1:6d3d16f4b27c 165 t->tm_min = atoi(p);
WiredHome 1:6d3d16f4b27c 166 p = strtok(NULL, " (:");
WiredHome 1:6d3d16f4b27c 167 if (p != NULL) {
WiredHome 1:6d3d16f4b27c 168 t->tm_sec = atoi(p);
WiredHome 1:6d3d16f4b27c 169 success = true; // if we get to here, we're good
WiredHome 1:6d3d16f4b27c 170 p = strtok(NULL, " (:");
WiredHome 1:6d3d16f4b27c 171 if (p != NULL) {
WiredHome 1:6d3d16f4b27c 172 success = false; // but can't accept a partial tzo
WiredHome 1:6d3d16f4b27c 173 _oH = atoi(p);
WiredHome 1:6d3d16f4b27c 174 p = strtok(NULL, " (:)");
WiredHome 1:6d3d16f4b27c 175 if (p != NULL) {
WiredHome 1:6d3d16f4b27c 176 _oM = atoi(p);
WiredHome 1:6d3d16f4b27c 177 success = true; // but a whole tzo is ok
WiredHome 1:6d3d16f4b27c 178 SetTimeOffset(_oH, _oM);
WiredHome 1:6d3d16f4b27c 179 }
WiredHome 1:6d3d16f4b27c 180 }
WiredHome 1:6d3d16f4b27c 181 seconds = mktime(t);
WiredHome 1:6d3d16f4b27c 182 seconds = seconds - (time_t)(tzOffsetHr * 3600 + tzOffsetMin * 60);
WiredHome 1:6d3d16f4b27c 183 set_time(seconds);
WiredHome 6:a517fee06e2e 184 SetTimeLastSet(seconds);
WiredHome 1:6d3d16f4b27c 185 }
WiredHome 1:6d3d16f4b27c 186 }
WiredHome 0:108436d3cea9 187 }
WiredHome 0:108436d3cea9 188 }
WiredHome 0:108436d3cea9 189 }
WiredHome 0:108436d3cea9 190 }
WiredHome 0:108436d3cea9 191 return success;
WiredHome 0:108436d3cea9 192 }
WiredHome 0:108436d3cea9 193
WiredHome 5:fbbdf57675c3 194 bool RealTimeClock::AdjustBySeconds(int32_t adjustSeconds) {
WiredHome 6:a517fee06e2e 195 time_t lastSet = GetTimeLastSet();
WiredHome 6:a517fee06e2e 196
WiredHome 6:a517fee06e2e 197 if (lastSet != 0) {
WiredHome 5:fbbdf57675c3 198 time_t seconds = time(NULL); // get "now" according to the rtc
WiredHome 6:a517fee06e2e 199 int32_t delta = seconds - lastSet;
WiredHome 5:fbbdf57675c3 200 int32_t curCal = GetTimeCalibration();
WiredHome 5:fbbdf57675c3 201 int32_t calMAX = 131071;
WiredHome 5:fbbdf57675c3 202 int32_t secPerDay = 86400;
WiredHome 5:fbbdf57675c3 203 float errSecPerDay;
WiredHome 5:fbbdf57675c3 204
WiredHome 5:fbbdf57675c3 205 // Convert the current calibration and the adjustment into
WiredHome 5:fbbdf57675c3 206 // the new calibration value
WiredHome 5:fbbdf57675c3 207 // assume it is +10sec and it has been 2days, then the adjustment
WiredHome 5:fbbdf57675c3 208 // needs to be +5 sec per day, or one adjustment every 1/5th
WiredHome 5:fbbdf57675c3 209 // of a day, or 1 adjustment every 86400/5 counts.
WiredHome 5:fbbdf57675c3 210 // delta = now - then (number of elapsed seconds)
WiredHome 5:fbbdf57675c3 211 if (adjustSeconds != 0 && delta != 0) {
WiredHome 5:fbbdf57675c3 212 int32_t calFactor;
WiredHome 6:a517fee06e2e 213
WiredHome 6:a517fee06e2e 214 // Make the clock correct
WiredHome 6:a517fee06e2e 215 seconds = seconds + adjustSeconds;
WiredHome 6:a517fee06e2e 216 set_time(seconds);
WiredHome 6:a517fee06e2e 217 SetTimeLastSet(seconds);
WiredHome 6:a517fee06e2e 218 // Compute the calibration factor
WiredHome 5:fbbdf57675c3 219 errSecPerDay = (float)adjustSeconds / ((float)(delta)/secPerDay);
WiredHome 5:fbbdf57675c3 220 calFactor = (int32_t)((float)secPerDay/errSecPerDay);
WiredHome 5:fbbdf57675c3 221 if (abs(calFactor) < calMAX)
WiredHome 5:fbbdf57675c3 222 SetTimeCalibration(calFactor);
WiredHome 5:fbbdf57675c3 223 }
WiredHome 5:fbbdf57675c3 224 return true;
WiredHome 5:fbbdf57675c3 225 } else {
WiredHome 5:fbbdf57675c3 226 return false;
WiredHome 5:fbbdf57675c3 227 }
WiredHome 5:fbbdf57675c3 228 }