caltime/caltime.c

Copyright (C) 2001-2005 by egnite Software GmbH. All rights reserved.

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/

$Log$ Revision 1.1 2007/06/03 08:48:17 haraldkipp New application sample demonstrates calendar functions.

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/