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