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:
Sun Jun 08 00:18:43 2014 +0000
Revision:
0:61112ca9193b
Child:
1:2ee90f546f54
A time interface class to emulate, but improve upon, the conventional time apis.

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