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.
Dependents: CI-data-logger-server WattEye X10Svr SSDP_Server
TimeInterface.cpp@13:17e1f5bb9b0e, 2016-05-19 (annotated)
- Committer:
- WiredHome
- Date:
- Thu May 19 18:13:09 2016 +0000
- Revision:
- 13:17e1f5bb9b0e
- Parent:
- 7:1de342fa7840
band-aid the strftime api to append UTC if there is a %Z in the formatter.
Who changed what in which revision?
User | Revision | Line number | New 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 | 7:1de342fa7840 | 6 | //#define DEBUG "Time" |
WiredHome | 2:65e0a25c7551 | 7 | #include <cstdio> |
WiredHome | 2:65e0a25c7551 | 8 | #if (defined(DEBUG) && !defined(TARGET_LPC11U24)) |
WiredHome | 2:65e0a25c7551 | 9 | #define DBG(x, ...) std::printf("[DBG %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__); |
WiredHome | 2:65e0a25c7551 | 10 | #define WARN(x, ...) std::printf("[WRN %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__); |
WiredHome | 2:65e0a25c7551 | 11 | #define ERR(x, ...) std::printf("[ERR %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__); |
WiredHome | 2:65e0a25c7551 | 12 | #define INFO(x, ...) std::printf("[INF %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__); |
WiredHome | 2:65e0a25c7551 | 13 | #else |
WiredHome | 2:65e0a25c7551 | 14 | #define DBG(x, ...) |
WiredHome | 2:65e0a25c7551 | 15 | #define WARN(x, ...) |
WiredHome | 2:65e0a25c7551 | 16 | #define ERR(x, ...) |
WiredHome | 2:65e0a25c7551 | 17 | #define INFO(x, ...) |
WiredHome | 2:65e0a25c7551 | 18 | #endif |
WiredHome | 2:65e0a25c7551 | 19 | |
WiredHome | 0:61112ca9193b | 20 | #ifdef WIN32 |
WiredHome | 0:61112ca9193b | 21 | // Fake it out for Win32 development and testing |
WiredHome | 0:61112ca9193b | 22 | struct LPC { |
WiredHome | 0:61112ca9193b | 23 | unsigned long CCR; // Clock Control register |
WiredHome | 0:61112ca9193b | 24 | unsigned long GPREG0; // General Purpose Register #0 - 32-bit Battery backed |
WiredHome | 0:61112ca9193b | 25 | unsigned long GPREG1; // General Purpose Register #1 - 32-bit Battery backed |
WiredHome | 0:61112ca9193b | 26 | unsigned long CALIBRATION; // Calibration Register |
WiredHome | 0:61112ca9193b | 27 | }; |
WiredHome | 0:61112ca9193b | 28 | struct LPC X; |
WiredHome | 0:61112ca9193b | 29 | struct LPC * LPC_RTC = &X; |
WiredHome | 0:61112ca9193b | 30 | #define set_time(x) (void)x |
WiredHome | 0:61112ca9193b | 31 | #endif |
WiredHome | 0:61112ca9193b | 32 | |
WiredHome | 0:61112ca9193b | 33 | |
WiredHome | 0:61112ca9193b | 34 | TimeInterface::TimeInterface() |
WiredHome | 0:61112ca9193b | 35 | { |
WiredHome | 6:c79cfe750416 | 36 | dst = false; |
WiredHome | 6:c79cfe750416 | 37 | memset(&dst_pair, 0, sizeof(dst_pair)); // that's enough to keep it from running |
WiredHome | 0:61112ca9193b | 38 | } |
WiredHome | 0:61112ca9193b | 39 | |
WiredHome | 0:61112ca9193b | 40 | TimeInterface::~TimeInterface() |
WiredHome | 0:61112ca9193b | 41 | { |
WiredHome | 0:61112ca9193b | 42 | } |
WiredHome | 0:61112ca9193b | 43 | |
WiredHome | 2:65e0a25c7551 | 44 | NTPResult TimeInterface::setTime(const char* host, uint16_t port, uint32_t timeout) |
WiredHome | 2:65e0a25c7551 | 45 | { |
WiredHome | 2:65e0a25c7551 | 46 | NTPClient ntp; |
WiredHome | 2:65e0a25c7551 | 47 | NTPResult res; |
WiredHome | 5:a5f50b5fb856 | 48 | // int16_t tzomin = get_tzo_min(); |
WiredHome | 6:c79cfe750416 | 49 | INFO("setTime(%s, %d, %d)\r\n", host, port, timeout); |
WiredHome | 2:65e0a25c7551 | 50 | res = ntp.setTime(host, port, timeout); |
WiredHome | 2:65e0a25c7551 | 51 | INFO(" ret: %d\r\n", res); |
WiredHome | 2:65e0a25c7551 | 52 | if (res == NTP_OK) { |
WiredHome | 2:65e0a25c7551 | 53 | // if the time was fetched successfully, then |
WiredHome | 2:65e0a25c7551 | 54 | // let's save the time last set with the local tzo applied |
WiredHome | 2:65e0a25c7551 | 55 | // and this saves the last time set for later precision |
WiredHome | 2:65e0a25c7551 | 56 | // tuning. |
WiredHome | 2:65e0a25c7551 | 57 | set_time(std::time(NULL)); |
WiredHome | 2:65e0a25c7551 | 58 | } |
WiredHome | 2:65e0a25c7551 | 59 | return res; |
WiredHome | 2:65e0a25c7551 | 60 | } |
WiredHome | 2:65e0a25c7551 | 61 | |
WiredHome | 6:c79cfe750416 | 62 | bool TimeInterface::parseDSTstring(TimeInterface::dst_event_t * result, const char * dstr) |
WiredHome | 3:49f36b489b64 | 63 | { |
WiredHome | 6:c79cfe750416 | 64 | int x; |
WiredHome | 6:c79cfe750416 | 65 | dst_event_t test_dst; |
WiredHome | 6:c79cfe750416 | 66 | |
WiredHome | 6:c79cfe750416 | 67 | x = atoi(dstr); |
WiredHome | 6:c79cfe750416 | 68 | if (x >= 1 && x <= 12) { |
WiredHome | 6:c79cfe750416 | 69 | test_dst.MM = x; |
WiredHome | 6:c79cfe750416 | 70 | dstr = strchr(dstr, '/'); |
WiredHome | 6:c79cfe750416 | 71 | if (dstr++) { |
WiredHome | 6:c79cfe750416 | 72 | x = atoi(dstr); |
WiredHome | 6:c79cfe750416 | 73 | if (x >= 1 && x <= 31) { |
WiredHome | 6:c79cfe750416 | 74 | test_dst.DD = x; |
WiredHome | 6:c79cfe750416 | 75 | dstr = strchr(dstr, ','); |
WiredHome | 6:c79cfe750416 | 76 | if (dstr++) { |
WiredHome | 6:c79cfe750416 | 77 | x = atoi(dstr); |
WiredHome | 6:c79cfe750416 | 78 | if (x >= 0 && x <= 23) { |
WiredHome | 6:c79cfe750416 | 79 | test_dst.hh = x; |
WiredHome | 6:c79cfe750416 | 80 | dstr = strchr(dstr, ':'); |
WiredHome | 6:c79cfe750416 | 81 | if (dstr++) { |
WiredHome | 6:c79cfe750416 | 82 | x = atoi(dstr); |
WiredHome | 6:c79cfe750416 | 83 | if (x >= 0 && x <= 59) { |
WiredHome | 6:c79cfe750416 | 84 | test_dst.mm = x; |
WiredHome | 6:c79cfe750416 | 85 | memcpy(result, &test_dst, sizeof(dst_event_t)); |
WiredHome | 6:c79cfe750416 | 86 | INFO("parsed: %d/%d %d:%02d", test_dst.MM, test_dst.DD, test_dst.hh, test_dst.mm); |
WiredHome | 6:c79cfe750416 | 87 | return true; |
WiredHome | 6:c79cfe750416 | 88 | } |
WiredHome | 6:c79cfe750416 | 89 | } |
WiredHome | 6:c79cfe750416 | 90 | } |
WiredHome | 6:c79cfe750416 | 91 | } |
WiredHome | 6:c79cfe750416 | 92 | } |
WiredHome | 6:c79cfe750416 | 93 | } |
WiredHome | 6:c79cfe750416 | 94 | } |
WiredHome | 6:c79cfe750416 | 95 | return false; |
WiredHome | 3:49f36b489b64 | 96 | } |
WiredHome | 3:49f36b489b64 | 97 | |
WiredHome | 6:c79cfe750416 | 98 | // parse MM/DD,hh:mm |
WiredHome | 6:c79cfe750416 | 99 | bool TimeInterface::set_dst(const char * dstStart, const char * dstStop) |
WiredHome | 3:49f36b489b64 | 100 | { |
WiredHome | 6:c79cfe750416 | 101 | dst_event_pair_t test_pair; |
WiredHome | 6:c79cfe750416 | 102 | |
WiredHome | 6:c79cfe750416 | 103 | if (parseDSTstring(&test_pair.dst_start, dstStart) |
WiredHome | 6:c79cfe750416 | 104 | && parseDSTstring(&test_pair.dst_stop, dstStop)) { |
WiredHome | 6:c79cfe750416 | 105 | memcpy(&dst_pair, &test_pair, sizeof(dst_event_pair_t)); |
WiredHome | 6:c79cfe750416 | 106 | INFO("set_dst from (%s,%s)", dstStart, dstStop); |
WiredHome | 6:c79cfe750416 | 107 | return true; |
WiredHome | 6:c79cfe750416 | 108 | } |
WiredHome | 6:c79cfe750416 | 109 | WARN("failed to set_dst from (%s,%s)", dstStart, dstStop); |
WiredHome | 6:c79cfe750416 | 110 | return false; |
WiredHome | 6:c79cfe750416 | 111 | } |
WiredHome | 6:c79cfe750416 | 112 | |
WiredHome | 6:c79cfe750416 | 113 | bool TimeInterface::set_dst(bool isdst) |
WiredHome | 6:c79cfe750416 | 114 | { |
WiredHome | 6:c79cfe750416 | 115 | dst = isdst; |
WiredHome | 6:c79cfe750416 | 116 | return true; |
WiredHome | 6:c79cfe750416 | 117 | } |
WiredHome | 6:c79cfe750416 | 118 | |
WiredHome | 6:c79cfe750416 | 119 | bool TimeInterface::get_dst(void) |
WiredHome | 6:c79cfe750416 | 120 | { |
WiredHome | 6:c79cfe750416 | 121 | return dst; |
WiredHome | 3:49f36b489b64 | 122 | } |
WiredHome | 3:49f36b489b64 | 123 | |
WiredHome | 0:61112ca9193b | 124 | clock_t TimeInterface::clock(void) |
WiredHome | 0:61112ca9193b | 125 | { |
WiredHome | 0:61112ca9193b | 126 | return std::clock(); |
WiredHome | 0:61112ca9193b | 127 | } |
WiredHome | 0:61112ca9193b | 128 | |
WiredHome | 7:1de342fa7840 | 129 | time_t TimeInterface::time(time_t * timer) |
WiredHome | 0:61112ca9193b | 130 | { |
WiredHome | 0:61112ca9193b | 131 | return std::time(timer); |
WiredHome | 0:61112ca9193b | 132 | } |
WiredHome | 0:61112ca9193b | 133 | |
WiredHome | 6:c79cfe750416 | 134 | uint32_t TimeInterface::minutesSinceJan(int mon, int day, int hr, int min) |
WiredHome | 6:c79cfe750416 | 135 | { |
WiredHome | 6:c79cfe750416 | 136 | return (mon * 60 * 24 * 31) + (day * 60 * 24) + (hr * 60) + min; |
WiredHome | 6:c79cfe750416 | 137 | } |
WiredHome | 6:c79cfe750416 | 138 | |
WiredHome | 7:1de342fa7840 | 139 | time_t TimeInterface::timelocal(time_t * timer) |
WiredHome | 1:2ee90f546f54 | 140 | { |
WiredHome | 6:c79cfe750416 | 141 | time_t privTime; |
WiredHome | 6:c79cfe750416 | 142 | struct tm * tminfo; |
WiredHome | 6:c79cfe750416 | 143 | |
WiredHome | 6:c79cfe750416 | 144 | if (dst_pair.dst_start.MM) { // may have to change the dst |
WiredHome | 6:c79cfe750416 | 145 | std::time(&privTime); |
WiredHome | 6:c79cfe750416 | 146 | tminfo = std::localtime(&privTime); |
WiredHome | 6:c79cfe750416 | 147 | |
WiredHome | 6:c79cfe750416 | 148 | uint32_t min_since_jan = minutesSinceJan(tminfo->tm_mon + 1, tminfo->tm_mday, tminfo->tm_hour, tminfo->tm_min); |
WiredHome | 7:1de342fa7840 | 149 | uint32_t min_dst_start = minutesSinceJan(dst_pair.dst_start.MM, dst_pair.dst_start.DD, dst_pair.dst_start.hh, dst_pair.dst_start.mm) + get_tzo_min(); |
WiredHome | 7:1de342fa7840 | 150 | uint32_t min_dst_stop = minutesSinceJan(dst_pair.dst_stop.MM, dst_pair.dst_stop.DD, dst_pair.dst_stop.hh, dst_pair.dst_stop.mm) + get_tzo_min(); |
WiredHome | 6:c79cfe750416 | 151 | |
WiredHome | 6:c79cfe750416 | 152 | if (min_since_jan >= min_dst_start && min_since_jan < min_dst_stop) { |
WiredHome | 6:c79cfe750416 | 153 | dst = 1; |
WiredHome | 7:1de342fa7840 | 154 | //INFO(" is dst: %u - %u - %u", min_since_jan, min_dst_start, min_dst_stop); |
WiredHome | 6:c79cfe750416 | 155 | } else { |
WiredHome | 6:c79cfe750416 | 156 | dst = 0; |
WiredHome | 7:1de342fa7840 | 157 | //INFO("not dst: %u - %u - %u", min_since_jan, min_dst_start, min_dst_stop); |
WiredHome | 6:c79cfe750416 | 158 | } |
WiredHome | 6:c79cfe750416 | 159 | } |
WiredHome | 7:1de342fa7840 | 160 | INFO(" timelocal: %u, %d, %d", std::time(timer), get_tzo_min(), dst); |
WiredHome | 7:1de342fa7840 | 161 | return std::time(timer) + get_tzo_min() * 60 + dst * 3600; |
WiredHome | 1:2ee90f546f54 | 162 | } |
WiredHome | 1:2ee90f546f54 | 163 | |
WiredHome | 0:61112ca9193b | 164 | char * TimeInterface::ctime(const time_t * timer) |
WiredHome | 0:61112ca9193b | 165 | { |
WiredHome | 0:61112ca9193b | 166 | char * p = std::ctime(timer); |
WiredHome | 0:61112ca9193b | 167 | |
WiredHome | 0:61112ca9193b | 168 | if (strlen(p) < sizeof(result)) { |
WiredHome | 0:61112ca9193b | 169 | strcpy(result, p); |
WiredHome | 0:61112ca9193b | 170 | p = strchr(result, '\n'); |
WiredHome | 0:61112ca9193b | 171 | if (p) |
WiredHome | 0:61112ca9193b | 172 | *p = '\0'; |
WiredHome | 0:61112ca9193b | 173 | } else { |
WiredHome | 0:61112ca9193b | 174 | result[0] = '\0'; |
WiredHome | 0:61112ca9193b | 175 | } |
WiredHome | 0:61112ca9193b | 176 | return result; |
WiredHome | 0:61112ca9193b | 177 | } |
WiredHome | 0:61112ca9193b | 178 | |
WiredHome | 2:65e0a25c7551 | 179 | char * TimeInterface::asctime(const struct tm_ex * timeptr) |
WiredHome | 0:61112ca9193b | 180 | { |
WiredHome | 0:61112ca9193b | 181 | static const char wday_name[][4] = { |
WiredHome | 0:61112ca9193b | 182 | "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" |
WiredHome | 0:61112ca9193b | 183 | }; |
WiredHome | 0:61112ca9193b | 184 | static const char mon_name[][4] = { |
WiredHome | 0:61112ca9193b | 185 | "Jan", "Feb", "Mar", "Apr", "May", "Jun", |
WiredHome | 0:61112ca9193b | 186 | "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" |
WiredHome | 0:61112ca9193b | 187 | }; |
WiredHome | 0:61112ca9193b | 188 | |
WiredHome | 0:61112ca9193b | 189 | sprintf(result, "%.3s %.3s%3d %.2d:%.2d:%.2d %d", |
WiredHome | 0:61112ca9193b | 190 | wday_name[timeptr->tm_wday % 7], |
WiredHome | 0:61112ca9193b | 191 | mon_name[timeptr->tm_mon % 12], |
WiredHome | 0:61112ca9193b | 192 | timeptr->tm_mday, timeptr->tm_hour, |
WiredHome | 0:61112ca9193b | 193 | timeptr->tm_min, timeptr->tm_sec, |
WiredHome | 0:61112ca9193b | 194 | 1900 + timeptr->tm_year); |
WiredHome | 0:61112ca9193b | 195 | return result; |
WiredHome | 0:61112ca9193b | 196 | } |
WiredHome | 0:61112ca9193b | 197 | |
WiredHome | 0:61112ca9193b | 198 | struct tm_ex * TimeInterface::gmtime(const time_t * timer) |
WiredHome | 0:61112ca9193b | 199 | { |
WiredHome | 13:17e1f5bb9b0e | 200 | time_t priv = *timer; // + get_tzo_min() * 60 + dst * 3600; |
WiredHome | 0:61112ca9193b | 201 | struct tm * tmp = std::localtime(&priv); |
WiredHome | 0:61112ca9193b | 202 | |
WiredHome | 0:61112ca9193b | 203 | tm_ext.tm_sec = tmp->tm_sec; |
WiredHome | 0:61112ca9193b | 204 | tm_ext.tm_min = tmp->tm_min; |
WiredHome | 0:61112ca9193b | 205 | tm_ext.tm_hour = tmp->tm_hour; |
WiredHome | 0:61112ca9193b | 206 | tm_ext.tm_mday = tmp->tm_mday; |
WiredHome | 0:61112ca9193b | 207 | tm_ext.tm_mon = tmp->tm_mon; |
WiredHome | 0:61112ca9193b | 208 | tm_ext.tm_year = tmp->tm_year; |
WiredHome | 0:61112ca9193b | 209 | tm_ext.tm_wday = tmp->tm_wday; |
WiredHome | 0:61112ca9193b | 210 | tm_ext.tm_yday = tmp->tm_yday; |
WiredHome | 0:61112ca9193b | 211 | tm_ext.tm_isdst = tmp->tm_isdst; |
WiredHome | 0:61112ca9193b | 212 | tm_ext.tm_tzo_min = get_tzo_min(); |
WiredHome | 0:61112ca9193b | 213 | return &tm_ext; |
WiredHome | 0:61112ca9193b | 214 | } |
WiredHome | 0:61112ca9193b | 215 | |
WiredHome | 0:61112ca9193b | 216 | struct tm_ex * TimeInterface::localtime(const time_t * timer) |
WiredHome | 0:61112ca9193b | 217 | { |
WiredHome | 0:61112ca9193b | 218 | struct tm * tmp = std::localtime(timer); |
WiredHome | 0:61112ca9193b | 219 | |
WiredHome | 0:61112ca9193b | 220 | tm_ext.tm_sec = tmp->tm_sec; |
WiredHome | 0:61112ca9193b | 221 | tm_ext.tm_min = tmp->tm_min; |
WiredHome | 0:61112ca9193b | 222 | tm_ext.tm_hour = tmp->tm_hour; |
WiredHome | 0:61112ca9193b | 223 | tm_ext.tm_mday = tmp->tm_mday; |
WiredHome | 0:61112ca9193b | 224 | tm_ext.tm_mon = tmp->tm_mon; |
WiredHome | 0:61112ca9193b | 225 | tm_ext.tm_year = tmp->tm_year; |
WiredHome | 0:61112ca9193b | 226 | tm_ext.tm_wday = tmp->tm_wday; |
WiredHome | 0:61112ca9193b | 227 | tm_ext.tm_yday = tmp->tm_yday; |
WiredHome | 0:61112ca9193b | 228 | tm_ext.tm_isdst = tmp->tm_isdst; |
WiredHome | 0:61112ca9193b | 229 | tm_ext.tm_tzo_min = get_tzo_min(); |
WiredHome | 0:61112ca9193b | 230 | return &tm_ext; |
WiredHome | 0:61112ca9193b | 231 | } |
WiredHome | 0:61112ca9193b | 232 | |
WiredHome | 0:61112ca9193b | 233 | time_t TimeInterface::mktime(struct tm_ex * timeptr) |
WiredHome | 0:61112ca9193b | 234 | { |
WiredHome | 0:61112ca9193b | 235 | return std::mktime((struct tm *)timeptr); |
WiredHome | 0:61112ca9193b | 236 | } |
WiredHome | 0:61112ca9193b | 237 | |
WiredHome | 0:61112ca9193b | 238 | size_t TimeInterface::strftime(char * ptr, size_t maxsize, const char * format, const struct tm_ex * timeptr) |
WiredHome | 0:61112ca9193b | 239 | { |
WiredHome | 13:17e1f5bb9b0e | 240 | size_t r = std::strftime(ptr, maxsize, format, (struct tm *)timeptr); |
WiredHome | 13:17e1f5bb9b0e | 241 | // strftime looks like it should return "GMT" on the tail, but doesn't. |
WiredHome | 13:17e1f5bb9b0e | 242 | if (strstr(format,"%Z") && strlen(ptr) + 3 < maxsize) { |
WiredHome | 13:17e1f5bb9b0e | 243 | strcat(ptr, "GMT"); |
WiredHome | 13:17e1f5bb9b0e | 244 | r += 3; |
WiredHome | 13:17e1f5bb9b0e | 245 | } |
WiredHome | 13:17e1f5bb9b0e | 246 | return r; |
WiredHome | 0:61112ca9193b | 247 | } |
WiredHome | 0:61112ca9193b | 248 | |
WiredHome | 0:61112ca9193b | 249 | double TimeInterface::difftime(time_t end, time_t beginning) |
WiredHome | 0:61112ca9193b | 250 | { |
WiredHome | 0:61112ca9193b | 251 | return std::difftime(end, beginning); |
WiredHome | 0:61112ca9193b | 252 | } |
WiredHome | 0:61112ca9193b | 253 | |
WiredHome | 0:61112ca9193b | 254 | |
WiredHome | 0:61112ca9193b | 255 | |
WiredHome | 0:61112ca9193b | 256 | // time zone functions |
WiredHome | 0:61112ca9193b | 257 | |
WiredHome | 0:61112ca9193b | 258 | void TimeInterface::set_time(time_t t, int16_t tzo_min) |
WiredHome | 0:61112ca9193b | 259 | { |
WiredHome | 2:65e0a25c7551 | 260 | time_t tval = t - (tzo_min * 60); |
WiredHome | 0:61112ca9193b | 261 | rtc_init(); |
WiredHome | 0:61112ca9193b | 262 | rtc_write(tval); |
WiredHome | 0:61112ca9193b | 263 | LPC_RTC->GPREG1 = tval; |
WiredHome | 2:65e0a25c7551 | 264 | INFO("set_time(%s)", ctime(&tval)); |
WiredHome | 0:61112ca9193b | 265 | } |
WiredHome | 0:61112ca9193b | 266 | |
WiredHome | 0:61112ca9193b | 267 | void TimeInterface::set_tzo_min(int16_t tzo_min) |
WiredHome | 0:61112ca9193b | 268 | { |
WiredHome | 0:61112ca9193b | 269 | uint16_t th; |
WiredHome | 0:61112ca9193b | 270 | uint32_t treg; |
WiredHome | 0:61112ca9193b | 271 | |
WiredHome | 0:61112ca9193b | 272 | if (tzo_min >= -720 && tzo_min <= 720) { |
WiredHome | 0:61112ca9193b | 273 | th = (uint16_t)(-tzo_min); |
WiredHome | 0:61112ca9193b | 274 | treg = (th << 16) | (uint16_t)tzo_min; |
WiredHome | 0:61112ca9193b | 275 | LPC_RTC->GPREG0 = treg; |
WiredHome | 0:61112ca9193b | 276 | //printf("set_tzo(%d) %d is %08X\r\n", tzo, th, LPC_RTC->GPREG0); |
WiredHome | 0:61112ca9193b | 277 | } |
WiredHome | 0:61112ca9193b | 278 | } |
WiredHome | 0:61112ca9193b | 279 | |
WiredHome | 0:61112ca9193b | 280 | int16_t TimeInterface::get_tzo_min(void) |
WiredHome | 0:61112ca9193b | 281 | { |
WiredHome | 0:61112ca9193b | 282 | uint16_t th, tl; |
WiredHome | 0:61112ca9193b | 283 | |
WiredHome | 0:61112ca9193b | 284 | th = LPC_RTC->GPREG0 >> 16; |
WiredHome | 0:61112ca9193b | 285 | tl = LPC_RTC->GPREG0; |
WiredHome | 0:61112ca9193b | 286 | //printf("get_tzo() is %04X %04X\r\n", th, tl); |
WiredHome | 0:61112ca9193b | 287 | if ((uint16_t)(th + tl) == 0) { |
WiredHome | 0:61112ca9193b | 288 | return tl; |
WiredHome | 0:61112ca9193b | 289 | } else { |
WiredHome | 0:61112ca9193b | 290 | return 0; |
WiredHome | 0:61112ca9193b | 291 | } |
WiredHome | 0:61112ca9193b | 292 | } |
WiredHome | 0:61112ca9193b | 293 | |
WiredHome | 0:61112ca9193b | 294 | time_t TimeInterface::get_timelastset(void) |
WiredHome | 0:61112ca9193b | 295 | { |
WiredHome | 0:61112ca9193b | 296 | return LPC_RTC->GPREG1; |
WiredHome | 0:61112ca9193b | 297 | } |
WiredHome | 0:61112ca9193b | 298 | |
WiredHome | 0:61112ca9193b | 299 | int32_t TimeInterface::get_cal() { |
WiredHome | 0:61112ca9193b | 300 | int32_t calvalue = LPC_RTC->CALIBRATION & 0x3FFFF; |
WiredHome | 0:61112ca9193b | 301 | |
WiredHome | 0:61112ca9193b | 302 | if (calvalue & 0x20000) { |
WiredHome | 0:61112ca9193b | 303 | calvalue = -(calvalue & 0x1FFFF); |
WiredHome | 0:61112ca9193b | 304 | } |
WiredHome | 0:61112ca9193b | 305 | return calvalue; |
WiredHome | 0:61112ca9193b | 306 | } |
WiredHome | 0:61112ca9193b | 307 | |
WiredHome | 0:61112ca9193b | 308 | void TimeInterface::set_cal(int32_t calibration) { |
WiredHome | 0:61112ca9193b | 309 | if (calibration) { |
WiredHome | 0:61112ca9193b | 310 | if (calibration < 0) { |
WiredHome | 0:61112ca9193b | 311 | calibration = (-calibration & 0x1FFFF) | 0x20000; |
WiredHome | 0:61112ca9193b | 312 | } |
WiredHome | 0:61112ca9193b | 313 | LPC_RTC->CCR = 0x000001; //(LPC_RTC->CCR & 0x0003); // Clear CCALEN to enable it |
WiredHome | 0:61112ca9193b | 314 | } else { |
WiredHome | 0:61112ca9193b | 315 | LPC_RTC->CCR = 0x000011; //(LPC_RTC->CCR & 0x0003) | 0x0010; // Set CCALEN to disable it |
WiredHome | 0:61112ca9193b | 316 | } |
WiredHome | 0:61112ca9193b | 317 | LPC_RTC->CALIBRATION = calibration; |
WiredHome | 0:61112ca9193b | 318 | } |
WiredHome | 0:61112ca9193b | 319 | |
WiredHome | 0:61112ca9193b | 320 | bool TimeInterface::adjust_sec(int32_t adjustSeconds) |
WiredHome | 0:61112ca9193b | 321 | { |
WiredHome | 0:61112ca9193b | 322 | time_t lastSet = get_timelastset(); |
WiredHome | 0:61112ca9193b | 323 | |
WiredHome | 0:61112ca9193b | 324 | if (lastSet != 0) { |
WiredHome | 0:61112ca9193b | 325 | time_t seconds = time(NULL); // get "now" according to the rtc |
WiredHome | 0:61112ca9193b | 326 | int32_t delta = seconds - lastSet; |
WiredHome | 5:a5f50b5fb856 | 327 | //int32_t curCal = get_cal(); // calibration might want to leverage the current cal factor. |
WiredHome | 0:61112ca9193b | 328 | int32_t calMAX = 131071; |
WiredHome | 0:61112ca9193b | 329 | int32_t secPerDay = 86400; |
WiredHome | 0:61112ca9193b | 330 | float errSecPerDay; |
WiredHome | 0:61112ca9193b | 331 | |
WiredHome | 0:61112ca9193b | 332 | // Convert the current calibration and the adjustment into |
WiredHome | 0:61112ca9193b | 333 | // the new calibration value |
WiredHome | 0:61112ca9193b | 334 | // assume it is +10sec and it has been 2days, then the adjustment |
WiredHome | 0:61112ca9193b | 335 | // needs to be +5 sec per day, or one adjustment every 1/5th |
WiredHome | 0:61112ca9193b | 336 | // of a day, or 1 adjustment every 86400/5 counts. |
WiredHome | 0:61112ca9193b | 337 | // delta = now - then (number of elapsed seconds) |
WiredHome | 0:61112ca9193b | 338 | if (adjustSeconds != 0 && delta != 0) { |
WiredHome | 0:61112ca9193b | 339 | int32_t calFactor; |
WiredHome | 0:61112ca9193b | 340 | |
WiredHome | 0:61112ca9193b | 341 | // Make the clock correct |
WiredHome | 0:61112ca9193b | 342 | seconds = seconds + adjustSeconds; |
WiredHome | 0:61112ca9193b | 343 | set_time(seconds); |
WiredHome | 0:61112ca9193b | 344 | // Compute the calibration factor |
WiredHome | 0:61112ca9193b | 345 | errSecPerDay = (float)adjustSeconds / ((float)(delta)/secPerDay); |
WiredHome | 0:61112ca9193b | 346 | calFactor = (int32_t)((float)secPerDay/errSecPerDay); |
WiredHome | 0:61112ca9193b | 347 | if (abs(calFactor) < calMAX) |
WiredHome | 0:61112ca9193b | 348 | set_cal(calFactor); |
WiredHome | 0:61112ca9193b | 349 | } |
WiredHome | 0:61112ca9193b | 350 | return true; |
WiredHome | 0:61112ca9193b | 351 | } else { |
WiredHome | 0:61112ca9193b | 352 | return false; |
WiredHome | 0:61112ca9193b | 353 | } |
WiredHome | 0:61112ca9193b | 354 | } |