caltime/caltime.c

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(&ltm, localtime(&now), sizeof(ltm));
00319 
00320     /* Query date and time. */
00321     if (EnterDate(&ltm) == 0 && EnterTime(&ltm) == 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(&ltm);
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 

© 2000-2007 by egnite Software GmbH - visit http://www.ethernut.de/