From: johanknol Date: Sat, 17 Feb 2001 19:56:25 +0000 (+0000) Subject: added stdc time support X-Git-Url: https://git.gag.com/?a=commitdiff_plain;h=930dd232af107d224c9385774658b178c3ad62f2;p=fw%2Fsdcc added stdc time support git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@620 4a8a32a2-be11-0410-ad9d-d568d2c75423 --- diff --git a/device/include/time.h b/device/include/time.h new file mode 100755 index 00000000..8cb2daf4 --- /dev/null +++ b/device/include/time.h @@ -0,0 +1,43 @@ +#ifndef TIME_H +#define TIME_H + +#if 1 +struct tm +{ + unsigned char tm_sec; /* Seconds. [0-60] */ + unsigned char tm_min; /* Minutes. [0-59] */ + unsigned char tm_hour; /* Hours. [0-23] */ + unsigned char tm_mday; /* Day. [1-31] */ + unsigned char tm_mon; /* Month. [0-11] */ + int tm_year; /* Year since 1900 */ + unsigned char tm_wday; /* Day of week. [0-6] */ + int tm_yday; /* Days in year.[0-365] */ + unsigned char tm_isdst; /* Daylight saving time */ + unsigned char tm_hundredth; /* not standard 1/100th sec */ +}; +#else +struct tm +{ + int tm_sec; /* Seconds. [0-60] */ + int tm_min; /* Minutes. [0-59] */ + int tm_hour; /* Hours. [0-23] */ + int tm_mday; /* Day. [1-31] */ + int tm_mon; /* Month. [0-11] */ + int tm_year; /* Year since 1900 */ + int tm_wday; /* Day of week. [0-6] */ + int tm_yday; /* Days in year.[0-365] */ + int tm_isdst; /* Daylight saving time */ + char *tm_zone; /* Abbreviated timezone */ +}; +#endif + +typedef unsigned long time_t; + +time_t time(time_t *t); +struct tm *gmtime(time_t *timep); +struct tm *localtime(time_t *timep); +time_t mktime(struct tm *timeptr); +char *asctime(struct tm *timeptr); +char *ctime(time_t *timep); + +#endif TIME_H diff --git a/device/include/tinibios.h b/device/include/tinibios.h index 3e9bd3cc..07a4aac7 100755 --- a/device/include/tinibios.h +++ b/device/include/tinibios.h @@ -3,6 +3,7 @@ #define TINIBIOS_H #include +#include #define Serial0GetChar getchar #define Serial0PutChar putchar @@ -50,13 +51,9 @@ void CpuSpeed(unsigned int speed); #define CPU_MOVX_STRETCH 0x01 // from rtc390.c -static struct RTCDate{ - int year; - unsigned char month, day, weekDay, hour, minute, second, hundredth; -}; - -unsigned char RtcRead(struct RTCDate *rtcDate); -void RtcWrite(struct RTCDate *rtcDate); +#define HAVE_RTC +unsigned char RtcRead(struct tm *rtcDate); +void RtcWrite(struct tm *rtcDate); // from lcd390.c extern void LcdInit(void); diff --git a/device/lib/Makefile.in b/device/lib/Makefile.in index 830ab76c..25746d17 100644 --- a/device/lib/Makefile.in +++ b/device/lib/Makefile.in @@ -51,7 +51,7 @@ OBJECTS = _atoi.rel _atol.rel _autobaud.rel _bp.rel _schar2fs.rel \ _strstr.rel _strtok.rel _uchar2fs.rel _uint2fs.rel \ _ulong2fs.rel malloc.rel serial.rel ser_ir.rel printfl.rel \ printf_large.rel vprintf.rel puts.rel gets.rel \ - assert.rel _strcat.rel + assert.rel _strcat.rel time.rel SOURCES = $(patsubst %.rel,%.c,$(OBJECTS)) include incl.mk diff --git a/device/lib/libsdcc.lib b/device/lib/libsdcc.lib index 8a95b82e..31c36e12 100644 --- a/device/lib/libsdcc.lib +++ b/device/lib/libsdcc.lib @@ -42,3 +42,4 @@ printfl printf_large vprintf assert +time \ No newline at end of file diff --git a/device/lib/time.c b/device/lib/time.c new file mode 100755 index 00000000..dcdb09f6 --- /dev/null +++ b/device/lib/time.c @@ -0,0 +1,204 @@ +/*------------------------------------------------------------------------- + time.c - stdlib time conversion routines + + Written By - Johan Knol, johan.knol@iduna.nl + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2, or (at your option) any + later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + In other words, you are welcome to use, share and improve this program. + You are forbidden to forbid anyone else to use, share and improve + what you give them. Help stamp out software-hoarding! +-------------------------------------------------------------------------*/ + +#include +#include + +#define FIXDS390BUG (long) + +// please note that the tm structure has the years since 1900, +// but time returns the seconds since 1970 + +/* You need some kind of real time clock for the time() function. + Either a rtc-chip or some kind of DCF device will do. For TINI, the + HAVE_RTC is defined in tinibios.h + If not, the conversion routines still work. +*/ + +#ifndef HAVE_RTC +unsigned char RtcRead(struct tm *timeptr) { + // no real time hardware + return 0; +} +#endif + +// return the calendar time, seconds since the Epoch (Jan 1 1970 00:00:00) +time_t time(time_t *timeptr) { + struct tm now; + time_t t=-1; + + if (RtcRead(&now)) { + t=mktime(&now); + } + if (timeptr) { + *timeptr=t; + } + return t; +} + +static code char monthDays[]={31,28,31,30,31,30,31,31,30,31,30,31}; + +static code char *month[]={"Jan","Feb","Mar","Apr","May","Jun", + "Jul","Aug","Sep","Oct","Nov","Dec"}; + +static code char *day[]={"Sun","Mon","Tue","Wed","Thu","Fri","Sat"}; + +static char ascTimeBuffer[32]; + +// validate the tm structure +static void CheckTime(struct tm *timeptr) { + // we could do some normalization here, e.g. + // change 40 october to 9 november + if (timeptr->tm_sec<0) timeptr->tm_sec=0; + else if (timeptr->tm_sec>59) timeptr->tm_sec=59; + if (timeptr->tm_min<0) timeptr->tm_min=0; + else if (timeptr->tm_min>59) timeptr->tm_min=59; + if (timeptr->tm_hour<0) timeptr->tm_hour=0; + else if (timeptr->tm_hour>23) timeptr->tm_hour=23; + if (timeptr->tm_wday<0) timeptr->tm_wday=0; + else if (timeptr->tm_wday>6) timeptr->tm_wday=6; + if (timeptr->tm_mday<1) timeptr->tm_mday=1; + else if (timeptr->tm_mday>31) timeptr->tm_mday=31; + if (timeptr->tm_mon<0) timeptr->tm_mon=0; + else if (timeptr->tm_mon>11) timeptr->tm_mon=11; + if (timeptr->tm_year<0) timeptr->tm_year=0; +} + +// format the time into "Sat Feb 17 17:45:23 2001\n" +char *asctime(struct tm *timeptr) { + CheckTime(timeptr); + sprintf (ascTimeBuffer, "%s %s %2d %02d:%02d:%02d %04d\n", + day[timeptr->tm_wday], month[timeptr->tm_mon], timeptr->tm_mday, + timeptr->tm_hour, timeptr->tm_min, timeptr->tm_sec, + timeptr->tm_year+1900); + return ascTimeBuffer; +} + +char *ctime(time_t *timep) { + return asctime(localtime(timep)); +} + +static struct tm lastTime; + +/* convert calendar time (seconds since 1970) to broken-time + This only works for dates between 01-01-1970 00:00:00 and + 19-01-2038 03:14:07 + + A leap year is ((((year%4)==0) && ((year%100)!=0)) || ((year%400)==0)) + but since we have no fancy years between 1970 and 2038 we can do: +*/ + +#define LEAP_YEAR(year) ((year%4)==0) + +// forget about timezones for now +struct tm *localtime(time_t *timep) { + return gmtime(timep); +} + +struct tm *gmtime(time_t *timep) { + unsigned long epoch=*timep; + unsigned int year; + unsigned char month, monthLength; + unsigned long days; + + lastTime.tm_sec=epoch%60; + epoch/=60; // now it is minutes + lastTime.tm_min=epoch%60; + epoch/=60; // now it is hours + lastTime.tm_hour=epoch%24; + epoch/=24; // now it is days + lastTime.tm_wday=(epoch+4)%7; + + year=1970; + days=0; + while((days += (LEAP_YEAR(year) ? 366 : 365)) <= epoch) { + year++; + } + lastTime.tm_year=year-1900; + + days -= LEAP_YEAR(year) ? 366 : 365; + epoch -= days; // now it is days in this year, starting at 0 + lastTime.tm_yday=epoch; + + days=0; + month=0; + monthLength=0; + for (month=0; month<12; month++) { + if (month==1) { // februari + if (LEAP_YEAR(year)) { + monthLength=29; + } else { + monthLength=28; + } + } else { + monthLength = monthDays[month]; + } + + if (epoch>=monthLength) { + epoch-=monthLength; + } else { + break; + } + } + lastTime.tm_mon=month; + lastTime.tm_mday=epoch+1; + + lastTime.tm_isdst=0; + + return &lastTime; +} + +// convert broken time to calendar time (seconds since 1970) +time_t mktime(struct tm *timeptr) { + int year=timeptr->tm_year+1900, month=timeptr->tm_mon, i; + long seconds; + + CheckTime(timeptr); + + // seconds from 1970 till 1 jan 00:00:00 this year + seconds= FIXDS390BUG (year-1970)*60*60*24*365; + + // add extra days for leap years + for (i=1970; itm_mday-1)*60*60*24; + seconds+= FIXDS390BUG timeptr->tm_hour*60*60; + seconds+= FIXDS390BUG timeptr->tm_min*60; + seconds+= FIXDS390BUG timeptr->tm_sec; + return seconds; +} +