A time interface class. This class replicates the normal time functions, but goes a couple of steps further. mbed library 82 and prior has a defective gmtime function. Also, this class enables access to setting the time, and adjusting the accuracy of the RTC.

Dependencies:   CalendarPage

Dependents:   CI-data-logger-server WattEye X10Svr SSDP_Server

Committer:
WiredHome
Date:
Sat Jun 14 12:34:53 2014 +0000
Revision:
1:2ee90f546f54
Parent:
0:61112ca9193b
Child:
2:65e0a25c7551
Add timelocal() method so local time offset does not have to be added in every use of time().

Who changed what in which revision?

UserRevisionLine numberNew contents of line
WiredHome 0:61112ca9193b 1
WiredHome 0:61112ca9193b 2 #include "TimeInterface.h"
WiredHome 0:61112ca9193b 3
WiredHome 0:61112ca9193b 4 #include "rtc_api.h"
WiredHome 0:61112ca9193b 5
WiredHome 0:61112ca9193b 6 #ifdef WIN32
WiredHome 0:61112ca9193b 7 // Fake it out for Win32 development and testing
WiredHome 0:61112ca9193b 8 struct LPC {
WiredHome 0:61112ca9193b 9 unsigned long CCR; // Clock Control register
WiredHome 0:61112ca9193b 10 unsigned long GPREG0; // General Purpose Register #0 - 32-bit Battery backed
WiredHome 0:61112ca9193b 11 unsigned long GPREG1; // General Purpose Register #1 - 32-bit Battery backed
WiredHome 0:61112ca9193b 12 unsigned long CALIBRATION; // Calibration Register
WiredHome 0:61112ca9193b 13 };
WiredHome 0:61112ca9193b 14 struct LPC X;
WiredHome 0:61112ca9193b 15 struct LPC * LPC_RTC = &X;
WiredHome 0:61112ca9193b 16 #define set_time(x) (void)x
WiredHome 0:61112ca9193b 17 #endif
WiredHome 0:61112ca9193b 18
WiredHome 0:61112ca9193b 19
WiredHome 0:61112ca9193b 20 TimeInterface::TimeInterface()
WiredHome 0:61112ca9193b 21 {
WiredHome 0:61112ca9193b 22 }
WiredHome 0:61112ca9193b 23
WiredHome 0:61112ca9193b 24 TimeInterface::~TimeInterface()
WiredHome 0:61112ca9193b 25 {
WiredHome 0:61112ca9193b 26 }
WiredHome 0:61112ca9193b 27
WiredHome 0:61112ca9193b 28 clock_t TimeInterface::clock(void)
WiredHome 0:61112ca9193b 29 {
WiredHome 0:61112ca9193b 30 return std::clock();
WiredHome 0:61112ca9193b 31 }
WiredHome 0:61112ca9193b 32
WiredHome 0:61112ca9193b 33 time_t TimeInterface::time(time_t* timer)
WiredHome 0:61112ca9193b 34 {
WiredHome 0:61112ca9193b 35 return std::time(timer);
WiredHome 0:61112ca9193b 36 }
WiredHome 0:61112ca9193b 37
WiredHome 1:2ee90f546f54 38 time_t TimeInterface::timelocal(time_t* timer)
WiredHome 1:2ee90f546f54 39 {
WiredHome 1:2ee90f546f54 40 return std::time(timer) + 60 * get_tzo_min();
WiredHome 1:2ee90f546f54 41 }
WiredHome 1:2ee90f546f54 42
WiredHome 0:61112ca9193b 43 char * TimeInterface::ctime(const time_t * timer)
WiredHome 0:61112ca9193b 44 {
WiredHome 0:61112ca9193b 45 char * p = std::ctime(timer);
WiredHome 0:61112ca9193b 46
WiredHome 0:61112ca9193b 47 if (strlen(p) < sizeof(result)) {
WiredHome 0:61112ca9193b 48 strcpy(result, p);
WiredHome 0:61112ca9193b 49 p = strchr(result, '\n');
WiredHome 0:61112ca9193b 50 if (p)
WiredHome 0:61112ca9193b 51 *p = '\0';
WiredHome 0:61112ca9193b 52 } else {
WiredHome 0:61112ca9193b 53 result[0] = '\0';
WiredHome 0:61112ca9193b 54 }
WiredHome 0:61112ca9193b 55 return result;
WiredHome 0:61112ca9193b 56 }
WiredHome 0:61112ca9193b 57
WiredHome 0:61112ca9193b 58 char * TimeInterface::asctime(const struct tm_ex *timeptr)
WiredHome 0:61112ca9193b 59 {
WiredHome 0:61112ca9193b 60 static const char wday_name[][4] = {
WiredHome 0:61112ca9193b 61 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
WiredHome 0:61112ca9193b 62 };
WiredHome 0:61112ca9193b 63 static const char mon_name[][4] = {
WiredHome 0:61112ca9193b 64 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
WiredHome 0:61112ca9193b 65 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
WiredHome 0:61112ca9193b 66 };
WiredHome 0:61112ca9193b 67
WiredHome 0:61112ca9193b 68 sprintf(result, "%.3s %.3s%3d %.2d:%.2d:%.2d %d",
WiredHome 0:61112ca9193b 69 wday_name[timeptr->tm_wday % 7],
WiredHome 0:61112ca9193b 70 mon_name[timeptr->tm_mon % 12],
WiredHome 0:61112ca9193b 71 timeptr->tm_mday, timeptr->tm_hour,
WiredHome 0:61112ca9193b 72 timeptr->tm_min, timeptr->tm_sec,
WiredHome 0:61112ca9193b 73 1900 + timeptr->tm_year);
WiredHome 0:61112ca9193b 74 return result;
WiredHome 0:61112ca9193b 75 }
WiredHome 0:61112ca9193b 76
WiredHome 0:61112ca9193b 77 struct tm_ex * TimeInterface::gmtime(const time_t * timer)
WiredHome 0:61112ca9193b 78 {
WiredHome 0:61112ca9193b 79 time_t priv = *timer + (get_tzo_min() * 60);
WiredHome 0:61112ca9193b 80 struct tm * tmp = std::localtime(&priv);
WiredHome 0:61112ca9193b 81
WiredHome 0:61112ca9193b 82 tm_ext.tm_sec = tmp->tm_sec;
WiredHome 0:61112ca9193b 83 tm_ext.tm_min = tmp->tm_min;
WiredHome 0:61112ca9193b 84 tm_ext.tm_hour = tmp->tm_hour;
WiredHome 0:61112ca9193b 85 tm_ext.tm_mday = tmp->tm_mday;
WiredHome 0:61112ca9193b 86 tm_ext.tm_mon = tmp->tm_mon;
WiredHome 0:61112ca9193b 87 tm_ext.tm_year = tmp->tm_year;
WiredHome 0:61112ca9193b 88 tm_ext.tm_wday = tmp->tm_wday;
WiredHome 0:61112ca9193b 89 tm_ext.tm_yday = tmp->tm_yday;
WiredHome 0:61112ca9193b 90 tm_ext.tm_isdst = tmp->tm_isdst;
WiredHome 0:61112ca9193b 91 tm_ext.tm_tzo_min = get_tzo_min();
WiredHome 0:61112ca9193b 92 return &tm_ext;
WiredHome 0:61112ca9193b 93 }
WiredHome 0:61112ca9193b 94
WiredHome 0:61112ca9193b 95 struct tm_ex * TimeInterface::localtime(const time_t * timer)
WiredHome 0:61112ca9193b 96 {
WiredHome 0:61112ca9193b 97 struct tm * tmp = std::localtime(timer);
WiredHome 0:61112ca9193b 98
WiredHome 0:61112ca9193b 99 tm_ext.tm_sec = tmp->tm_sec;
WiredHome 0:61112ca9193b 100 tm_ext.tm_min = tmp->tm_min;
WiredHome 0:61112ca9193b 101 tm_ext.tm_hour = tmp->tm_hour;
WiredHome 0:61112ca9193b 102 tm_ext.tm_mday = tmp->tm_mday;
WiredHome 0:61112ca9193b 103 tm_ext.tm_mon = tmp->tm_mon;
WiredHome 0:61112ca9193b 104 tm_ext.tm_year = tmp->tm_year;
WiredHome 0:61112ca9193b 105 tm_ext.tm_wday = tmp->tm_wday;
WiredHome 0:61112ca9193b 106 tm_ext.tm_yday = tmp->tm_yday;
WiredHome 0:61112ca9193b 107 tm_ext.tm_isdst = tmp->tm_isdst;
WiredHome 0:61112ca9193b 108 tm_ext.tm_tzo_min = get_tzo_min();
WiredHome 0:61112ca9193b 109 return &tm_ext;
WiredHome 0:61112ca9193b 110 }
WiredHome 0:61112ca9193b 111
WiredHome 0:61112ca9193b 112 time_t TimeInterface::mktime(struct tm_ex * timeptr)
WiredHome 0:61112ca9193b 113 {
WiredHome 0:61112ca9193b 114 return std::mktime((struct tm *)timeptr);
WiredHome 0:61112ca9193b 115 }
WiredHome 0:61112ca9193b 116
WiredHome 0:61112ca9193b 117 size_t TimeInterface::strftime(char * ptr, size_t maxsize, const char * format, const struct tm_ex * timeptr)
WiredHome 0:61112ca9193b 118 {
WiredHome 0:61112ca9193b 119 return std::strftime(ptr, maxsize, format, (struct tm *)timeptr);
WiredHome 0:61112ca9193b 120 }
WiredHome 0:61112ca9193b 121
WiredHome 0:61112ca9193b 122 double TimeInterface::difftime(time_t end, time_t beginning)
WiredHome 0:61112ca9193b 123 {
WiredHome 0:61112ca9193b 124 return std::difftime(end, beginning);
WiredHome 0:61112ca9193b 125 }
WiredHome 0:61112ca9193b 126
WiredHome 0:61112ca9193b 127
WiredHome 0:61112ca9193b 128
WiredHome 0:61112ca9193b 129 // time zone functions
WiredHome 0:61112ca9193b 130
WiredHome 0:61112ca9193b 131 void TimeInterface::set_time(time_t t, int16_t tzo_min)
WiredHome 0:61112ca9193b 132 {
WiredHome 0:61112ca9193b 133 time_t tval = t - tzo_min;
WiredHome 0:61112ca9193b 134 rtc_init();
WiredHome 0:61112ca9193b 135 rtc_write(tval);
WiredHome 0:61112ca9193b 136 LPC_RTC->GPREG1 = tval;
WiredHome 0:61112ca9193b 137 }
WiredHome 0:61112ca9193b 138
WiredHome 0:61112ca9193b 139 void TimeInterface::set_tzo_min(int16_t tzo_min)
WiredHome 0:61112ca9193b 140 {
WiredHome 0:61112ca9193b 141 uint16_t th;
WiredHome 0:61112ca9193b 142 uint32_t treg;
WiredHome 0:61112ca9193b 143
WiredHome 0:61112ca9193b 144 if (tzo_min >= -720 && tzo_min <= 720) {
WiredHome 0:61112ca9193b 145 th = (uint16_t)(-tzo_min);
WiredHome 0:61112ca9193b 146 treg = (th << 16) | (uint16_t)tzo_min;
WiredHome 0:61112ca9193b 147 LPC_RTC->GPREG0 = treg;
WiredHome 0:61112ca9193b 148 //printf("set_tzo(%d) %d is %08X\r\n", tzo, th, LPC_RTC->GPREG0);
WiredHome 0:61112ca9193b 149 }
WiredHome 0:61112ca9193b 150 }
WiredHome 0:61112ca9193b 151
WiredHome 0:61112ca9193b 152 int16_t TimeInterface::get_tzo_min(void)
WiredHome 0:61112ca9193b 153 {
WiredHome 0:61112ca9193b 154 uint16_t th, tl;
WiredHome 0:61112ca9193b 155
WiredHome 0:61112ca9193b 156 th = LPC_RTC->GPREG0 >> 16;
WiredHome 0:61112ca9193b 157 tl = LPC_RTC->GPREG0;
WiredHome 0:61112ca9193b 158 //printf("get_tzo() is %04X %04X\r\n", th, tl);
WiredHome 0:61112ca9193b 159 if ((uint16_t)(th + tl) == 0) {
WiredHome 0:61112ca9193b 160 return tl;
WiredHome 0:61112ca9193b 161 } else {
WiredHome 0:61112ca9193b 162 return 0;
WiredHome 0:61112ca9193b 163 }
WiredHome 0:61112ca9193b 164 }
WiredHome 0:61112ca9193b 165
WiredHome 0:61112ca9193b 166 time_t TimeInterface::get_timelastset(void)
WiredHome 0:61112ca9193b 167 {
WiredHome 0:61112ca9193b 168 return LPC_RTC->GPREG1;
WiredHome 0:61112ca9193b 169 }
WiredHome 0:61112ca9193b 170
WiredHome 0:61112ca9193b 171 int32_t TimeInterface::get_cal() {
WiredHome 0:61112ca9193b 172 int32_t calvalue = LPC_RTC->CALIBRATION & 0x3FFFF;
WiredHome 0:61112ca9193b 173
WiredHome 0:61112ca9193b 174 if (calvalue & 0x20000) {
WiredHome 0:61112ca9193b 175 calvalue = -(calvalue & 0x1FFFF);
WiredHome 0:61112ca9193b 176 }
WiredHome 0:61112ca9193b 177 return calvalue;
WiredHome 0:61112ca9193b 178 }
WiredHome 0:61112ca9193b 179
WiredHome 0:61112ca9193b 180 void TimeInterface::set_cal(int32_t calibration) {
WiredHome 0:61112ca9193b 181 if (calibration) {
WiredHome 0:61112ca9193b 182 if (calibration < 0) {
WiredHome 0:61112ca9193b 183 calibration = (-calibration & 0x1FFFF) | 0x20000;
WiredHome 0:61112ca9193b 184 }
WiredHome 0:61112ca9193b 185 LPC_RTC->CCR = 0x000001; //(LPC_RTC->CCR & 0x0003); // Clear CCALEN to enable it
WiredHome 0:61112ca9193b 186 } else {
WiredHome 0:61112ca9193b 187 LPC_RTC->CCR = 0x000011; //(LPC_RTC->CCR & 0x0003) | 0x0010; // Set CCALEN to disable it
WiredHome 0:61112ca9193b 188 }
WiredHome 0:61112ca9193b 189 LPC_RTC->CALIBRATION = calibration;
WiredHome 0:61112ca9193b 190 }
WiredHome 0:61112ca9193b 191
WiredHome 0:61112ca9193b 192 bool TimeInterface::adjust_sec(int32_t adjustSeconds)
WiredHome 0:61112ca9193b 193 {
WiredHome 0:61112ca9193b 194 time_t lastSet = get_timelastset();
WiredHome 0:61112ca9193b 195
WiredHome 0:61112ca9193b 196 if (lastSet != 0) {
WiredHome 0:61112ca9193b 197 time_t seconds = time(NULL); // get "now" according to the rtc
WiredHome 0:61112ca9193b 198 int32_t delta = seconds - lastSet;
WiredHome 0:61112ca9193b 199 int32_t curCal = get_cal();
WiredHome 0:61112ca9193b 200 int32_t calMAX = 131071;
WiredHome 0:61112ca9193b 201 int32_t secPerDay = 86400;
WiredHome 0:61112ca9193b 202 float errSecPerDay;
WiredHome 0:61112ca9193b 203
WiredHome 0:61112ca9193b 204 // Convert the current calibration and the adjustment into
WiredHome 0:61112ca9193b 205 // the new calibration value
WiredHome 0:61112ca9193b 206 // assume it is +10sec and it has been 2days, then the adjustment
WiredHome 0:61112ca9193b 207 // needs to be +5 sec per day, or one adjustment every 1/5th
WiredHome 0:61112ca9193b 208 // of a day, or 1 adjustment every 86400/5 counts.
WiredHome 0:61112ca9193b 209 // delta = now - then (number of elapsed seconds)
WiredHome 0:61112ca9193b 210 if (adjustSeconds != 0 && delta != 0) {
WiredHome 0:61112ca9193b 211 int32_t calFactor;
WiredHome 0:61112ca9193b 212
WiredHome 0:61112ca9193b 213 // Make the clock correct
WiredHome 0:61112ca9193b 214 seconds = seconds + adjustSeconds;
WiredHome 0:61112ca9193b 215 set_time(seconds);
WiredHome 0:61112ca9193b 216 // Compute the calibration factor
WiredHome 0:61112ca9193b 217 errSecPerDay = (float)adjustSeconds / ((float)(delta)/secPerDay);
WiredHome 0:61112ca9193b 218 calFactor = (int32_t)((float)secPerDay/errSecPerDay);
WiredHome 0:61112ca9193b 219 if (abs(calFactor) < calMAX)
WiredHome 0:61112ca9193b 220 set_cal(calFactor);
WiredHome 0:61112ca9193b 221 }
WiredHome 0:61112ca9193b 222 return true;
WiredHome 0:61112ca9193b 223 } else {
WiredHome 0:61112ca9193b 224 return false;
WiredHome 0:61112ca9193b 225 }
WiredHome 0:61112ca9193b 226 }