Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holders nor the names of contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY EGNITE SOFTWARE GMBH AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL EGNITE SOFTWARE GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
For additional information see http://www.ethernut.de/
Demonstrates Nut/OS date and time functions, which had been contributed by Oliver Schulz.
00001 00040 #include <dev/board.h> 00041 #include <dev/debug.h> 00042 00043 #include <sys/version.h> 00044 #include <sys/timer.h> 00045 00046 #include <stdlib.h> 00047 #include <stdio.h> 00048 #include <io.h> 00049 #include <string.h> 00050 #include <time.h> 00051 00058 static char *version = "1.0"; 00059 00060 /* Used for ASCII Art Animation. */ 00061 static char *rotor = "|/-\\"; 00062 00063 static char *weekday_name[7] = { 00064 "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" 00065 }; 00066 00067 /* 00068 * Print content of tm structure. 00069 */ 00070 static void PrintDateTime(CONST struct _tm *stm) 00071 { 00072 printf("%s, %04d/%02d/%02d, %02d:%02d:%02d%s" 00073 , weekday_name[stm->tm_wday] 00074 , stm->tm_year + 1900, stm->tm_mon + 1, stm->tm_mday 00075 , stm->tm_hour, stm->tm_min, stm->tm_sec 00076 , stm->tm_isdst ? " DST" : "" 00077 ); 00078 } 00079 00080 /* 00081 * Query calendar date from user. 00082 * 00083 * Returns 0 on success, -1 otherwise. 00084 */ 00085 static int EnterDate(struct _tm *stm) 00086 { 00087 int year; 00088 int mon; 00089 int mday; 00090 int n; 00091 00092 printf("Enter date, use format YYYY/MM/DD (%04d/%02d/%02d): ", 00093 stm->tm_year + 1900, stm->tm_mon + 1, stm->tm_mday); 00094 n = scanf("%d/%d/%d", &year, &mon, &mday); 00095 if (n >= 1) { 00096 printf("%04d", year); 00097 if (year < 1970 || year > 2038) { 00098 printf("\nBad year: %d is not within range 1970..2038\n", year); 00099 return -1; 00100 } 00101 stm->tm_year = year - 1900; 00102 } 00103 if (n >= 2) { 00104 printf("/%02d", mon); 00105 if (mon < 1 || mon > 31) { 00106 printf("\nBad month: %d is not within range 1..12\n", mon); 00107 return -1; 00108 } 00109 stm->tm_mon = mon - 1; 00110 } 00111 if (n >= 3) { 00112 printf("/%02d", mday); 00113 if (mday < 1 || mday > 31) { 00114 printf("\nBad day: %d is not within range 1..31\n", mday); 00115 return -1; 00116 } 00117 stm->tm_mday = mday; 00118 } 00119 putchar('\n'); 00120 00121 return 0; 00122 } 00123 00124 /* 00125 * Query time of day from user. 00126 * 00127 * Returns 0 on success, -1 otherwise. 00128 */ 00129 static int EnterTime(struct _tm *stm) 00130 { 00131 int hour; 00132 int minute; 00133 int second; 00134 int n; 00135 00136 printf("Enter time, use 24h format HH:MM:SS (%02d:%02d:%02d): ", 00137 stm->tm_hour, stm->tm_min, stm->tm_sec); 00138 n = scanf("%d:%d:%d", &hour, &minute, &second); 00139 if (n >= 1) { 00140 printf("%02d", hour); 00141 if (hour < 0 || hour > 23) { 00142 printf("\nBad hour: %d is not within range 0..23\n", hour); 00143 return -1; 00144 } 00145 stm->tm_hour = hour; 00146 } 00147 if (n >= 2) { 00148 printf(":%02d", minute); 00149 if (minute < 0 || minute > 59) { 00150 printf("\nBad minute: %d is not within range 0..59\n", minute); 00151 return -1; 00152 } 00153 stm->tm_min = minute; 00154 } 00155 if (n >= 3) { 00156 printf(":%02d", second); 00157 if (second < 0 || second > 59) { 00158 printf("\nBad second: %d is not within range 0..59\n", second); 00159 return -1; 00160 } 00161 stm->tm_sec = second; 00162 } 00163 putchar('\n'); 00164 00165 return 0; 00166 } 00167 00168 /* 00169 * Query time difference from user, specified in hours and minutes. 00170 * 00171 * 'init' specifies the default number of seconds. 00172 * 00173 * Returns the number of seconds. 00174 */ 00175 static long EnterTimeDiff(long init) 00176 { 00177 long hours; 00178 long minutes; 00179 long seconds; 00180 int n; 00181 00182 seconds = init; 00183 minutes = seconds / 60L; 00184 hours = minutes / 60L; 00185 minutes = abs(minutes % 60L); 00186 printf("Enter time difference in format HH:MM (%+03ld:%02ld): ", hours, minutes); 00187 n = scanf("%ld:%ld", &hours, &minutes); 00188 if (n >= 1) { 00189 printf("%+03ld", hours); 00190 if (hours < -12 || hours > 12) { 00191 printf("\nBad hours: %ld is not within range -12..+12\n", hours); 00192 return init; 00193 } 00194 } 00195 if (n >= 2) { 00196 printf("%02ld", minutes); 00197 if (minutes < 0 || minutes > 59) { 00198 printf("\nBad minutes: %ld is not within range 0..59\n", minutes); 00199 return init; 00200 } 00201 } 00202 putchar('\n'); 00203 00204 return (hours * 60L + minutes) * 60L; 00205 } 00206 00207 /* 00208 * Display the elapsed seconds of the epoch. 00209 * 00210 * The value is constantly updated until the user presses a key. 00211 */ 00212 static void DisplaySeconds(void) 00213 { 00214 int i = 0; 00215 00216 while (!kbhit()) { 00217 printf(" [%c] Seconds since epoch: %ld\r", rotor[++i & 3], (long)time(NULL)); 00218 NutSleep(200); 00219 } 00220 putchar('\n'); 00221 } 00222 00223 /* 00224 * Display the coordinated universal time. 00225 * 00226 * The value is constantly updated until the user presses a key. 00227 */ 00228 static void DisplayZuluTime(void) 00229 { 00230 time_t secs; 00231 struct _tm *gmt; 00232 int i = 0; 00233 00234 while (!kbhit()) { 00235 secs = time(NULL); 00236 gmt = gmtime(&secs); 00237 printf(" [%c] Universal time: ", rotor[++i & 3]); 00238 PrintDateTime(gmt); 00239 printf(" \r"); 00240 NutSleep(500); 00241 } 00242 putchar('\n'); 00243 } 00244 00245 /* 00246 * Display the local time. 00247 * 00248 * The value is constantly updated until the user presses a key. 00249 */ 00250 static void DisplayLocalTime(void) 00251 { 00252 time_t tt; 00253 struct _tm *ltm; 00254 int i = 0; 00255 00256 while (!kbhit()) { 00257 /* Get local time and print it. */ 00258 tt = time(NULL); 00259 ltm = localtime(&tt); 00260 printf(" [%c] Local time: ", rotor[++i & 3]); 00261 PrintDateTime(ltm); 00262 00263 /* Calculate the offset from UTC in minutes. */ 00264 tt = _timezone; 00265 if (ltm->tm_isdst > 0) { 00266 tt += _dstbias; 00267 } 00268 tt /= -60L; 00269 00270 /* Print UTC offset in format HH:MM. */ 00271 printf(" UTC%+03ld:%02ld \r", tt / 60L, abs(tt) % 60L); 00272 NutSleep(200); 00273 } 00274 putchar('\n'); 00275 } 00276 00277 /* 00278 * Display the week day of a queried calendar date. 00279 * 00280 * mktime() updates the structure members tm_yday and tm_wday. 00281 * This can be used to determine the week day name of any given 00282 * date. 00283 */ 00284 static void CalcWeekDay(void) 00285 { 00286 struct _tm date; 00287 time_t secs; 00288 00289 /* Use current local time as default. */ 00290 time(&secs); 00291 memcpy(&date, localtime(&secs), sizeof(date)); 00292 /* Query date and print week day name if we got a valid entry. */ 00293 if (EnterDate(&date) == 0) { 00294 mktime(&date); 00295 puts(weekday_name[date.tm_wday]); 00296 } 00297 } 00298 00299 /* 00300 * Query user for a new time zone offset. 00301 */ 00302 static void SetTimeZone(void) 00303 { 00304 /* Nut/OS uses a global variable to store the current TZ offset. */ 00305 _timezone = EnterTimeDiff(_timezone); 00306 } 00307 00308 /* 00309 * Query user for a new system time. 00310 */ 00311 static void SetLocalTime(void) 00312 { 00313 struct _tm ltm; 00314 time_t now; 00315 00316 /* Use current local time as default. */ 00317 time(&now); 00318 memcpy(<m, localtime(&now), sizeof(ltm)); 00319 00320 /* Query date and time. */ 00321 if (EnterDate(<m) == 0 && EnterTime(<m) == 0) { 00322 /* Let mktime determine whether DST is in effect. */ 00323 ltm.tm_isdst = -1; 00324 /* mktime expects local time and returns seconds since the epoch. */ 00325 now = mktime(<m); 00326 /* stime expects seconds since the epoch. */ 00327 stime(&now); 00328 } 00329 } 00330 00331 /* 00332 * Application entry. 00333 */ 00334 int main(void) 00335 { 00336 u_long baud = 115200; 00337 int cmd; 00338 00339 /* Use UART device for stdin and stdout. */ 00340 NutRegisterDevice(&DEV_UART, 0, 0); 00341 freopen(DEV_UART_NAME, "w", stdout); 00342 freopen(DEV_UART_NAME, "r", stdin); 00343 _ioctl(_fileno(stdout), UART_SETSPEED, &baud); 00344 printf("\n\nCalendar Time %s running on Nut/OS %s\n", version, NutVersionString()); 00345 00346 #ifdef RTC_CHIP 00347 /* Register and query hardware RTC, if available. */ 00348 printf("Registering RTC hardware..."); 00349 if (NutRegisterRtc(&RTC_CHIP)) { 00350 puts("failed"); 00351 } else { 00352 u_long rtc_stat; 00353 00354 NutRtcGetStatus(&rtc_stat); 00355 if (rtc_stat & RTC_STATUS_PF) { 00356 puts("power failure"); 00357 } 00358 else { 00359 puts("OK"); 00360 } 00361 } 00362 #endif 00363 00364 for (;;) { 00365 /* Print command menu. */ 00366 puts("\n 0 - Display seconds counter"); 00367 puts(" 1 - Display universal time"); 00368 puts(" 2 - Display local time"); 00369 puts(" 3 - Calculate weekday"); 00370 puts(" S - Set local time"); 00371 puts(" Y - Toggle DST calculation"); 00372 puts(" Z - Set timezone"); 00373 00374 printf("What is thy bidding, my master? "); 00375 00376 /* Flush input buffer. */ 00377 while (kbhit()) { 00378 cmd = getchar(); 00379 } 00380 00381 /* Get the next command. */ 00382 cmd = getchar(); 00383 putchar(cmd); 00384 putchar('\n'); 00385 00386 /* Process the command. */ 00387 switch(cmd) { 00388 case '0': 00389 DisplaySeconds(); 00390 break; 00391 case '1': 00392 DisplayZuluTime(); 00393 break; 00394 case '2': 00395 DisplayLocalTime(); 00396 break; 00397 case '3': 00398 CalcWeekDay(); 00399 break; 00400 case 'S': 00401 case 's': 00402 SetLocalTime(); 00403 break; 00404 case 'Y': 00405 case 'y': 00406 /* Nut/OS uses a global variable to enable/disable DST. 00407 Toggle the current status and display the result. */ 00408 _daylight = _daylight == 0; 00409 printf("DST calculation %sabled\n", _daylight ? "en" : "dis"); 00410 break; 00411 case 'Z': 00412 case 'z': 00413 SetTimeZone(); 00414 break; 00415 } 00416 } 00417 return 0; 00418 } 00419