From 727e8aa6817be8816bc32184f2e2eb36b90b4a9e Mon Sep 17 00:00:00 2001 From: Bertrik Sikken Date: Thu, 8 Mar 2012 21:21:31 +0100 Subject: Introduce gmtime.c and use it in the AS3514 RTC driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I00a09ae28a68f8153fb8fa854fea741ddfb0bf09 Reviewed-on: http://gerrit.rockbox.org/175 Tested-by: Bertrik Sikken Reviewed-by: Michael Sevakis Reviewed-by: Rafaël Carré --- firmware/SOURCES | 1 + firmware/drivers/rtc/rtc_as3514.c | 127 +++++--------------------------------- firmware/libc/gmtime.c | 112 +++++++++++++++++++++++++++++++++ firmware/libc/include/time.h | 2 + 4 files changed, 131 insertions(+), 111 deletions(-) create mode 100644 firmware/libc/gmtime.c diff --git a/firmware/SOURCES b/firmware/SOURCES index 32fbfbb49b..9b0f83d0ed 100644 --- a/firmware/SOURCES +++ b/firmware/SOURCES @@ -128,6 +128,7 @@ libc/strncmp.c libc/strrchr.c libc/strstr.c libc/mktime.c +libc/gmtime.c #endif /* CONFIG_PLATFORM || HAVE_ROCKBOX_C_LIBRARY */ /* Common */ diff --git a/firmware/drivers/rtc/rtc_as3514.c b/firmware/drivers/rtc/rtc_as3514.c index 868fa9753b..a4d2eb13f7 100644 --- a/firmware/drivers/rtc/rtc_as3514.c +++ b/firmware/drivers/rtc/rtc_as3514.c @@ -23,34 +23,17 @@ #include "rtc.h" #include "as3514.h" #include "ascodec.h" +#include "time.h" /* AMS Sansas start counting from Jan 1st 1970 instead of 1980 (not as3525v2) */ #if (CONFIG_CPU==AS3525) -#define SECS_ADJUST 315532800 /* seconds between 1970-1-1 and 1980-1-1 */ +#define SECS_ADJUST 0 #elif (CONFIG_CPU==AS3525v2) -#define SECS_ADJUST 315532800 - (2*365*24*3600) - 26*(24*3600) + 7*3600 + 25*60 +#define SECS_ADJUST ((2*365*24*3600) + 26*(24*3600) - 7*3600 - 25*60) #else -#define SECS_ADJUST 0 +#define SECS_ADJUST 315532800 /* 1980/1/1 */ #endif -#define MINUTE_SECONDS 60 -#define HOUR_SECONDS 3600 -#define DAY_SECONDS 86400 -#define WEEK_SECONDS 604800 -#define YEAR_SECONDS 31536000 -#define LEAP_YEAR_SECONDS 31622400 - -/* Days in each month */ -static unsigned int days_in_month[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; - -static inline bool is_leapyear(int year) -{ - if( ((year%4)==0) && (((year%100)!=0) || ((year%400)==0)) ) - return true; - else - return false; -} - #ifdef HAVE_RTC_ALARM /* as3543 */ static struct { unsigned int seconds; /* total seconds to wakeup */ @@ -197,109 +180,31 @@ void rtc_init(void) int rtc_read_datetime(struct tm *tm) { char tmp[4]; - int i, year, mday, hour, min; unsigned int seconds; + int i; - /* RTC_AS3514's slave address is 0x46*/ + /* Get seconds time stamp from RTC */ for (i = 0; i < 4; i++){ tmp[i] = ascodec_read(AS3514_RTC_0 + i); } seconds = tmp[0] + (tmp[1]<<8) + (tmp[2]<<16) + (tmp[3]<<24); - seconds -= SECS_ADJUST; - /* Convert seconds since Jan-1-1980 to format compatible with - * get_time() from firmware/common/timefuncs.c */ + /* convert to struct tm */ + time_t time = seconds + SECS_ADJUST; + gmtime_r(&time, tm); - /* weekday */ - tm->tm_wday = ((seconds % WEEK_SECONDS) / DAY_SECONDS + 2) % 7; - - /* Year */ - year = 1980; - while (seconds >= LEAP_YEAR_SECONDS) - { - if (is_leapyear(year)){ - seconds -= LEAP_YEAR_SECONDS; - } else { - seconds -= YEAR_SECONDS; - } - - year++; - } - - if (is_leapyear(year)) { - days_in_month[1] = 29; - } else { - days_in_month[1] = 28; - if(seconds>YEAR_SECONDS){ - year++; - seconds -= YEAR_SECONDS; - } - } - tm->tm_year = year%100 + 100; - - /* Month */ - for (i = 0; i < 12; i++) - { - if (seconds < days_in_month[i]*DAY_SECONDS){ - tm->tm_mon = i; - break; - } - - seconds -= days_in_month[i]*DAY_SECONDS; - } - - /* Month Day */ - mday = seconds/DAY_SECONDS; - seconds -= mday*DAY_SECONDS; - tm->tm_mday = mday + 1; /* 1 ... 31 */ - - /* Hour */ - hour = seconds/HOUR_SECONDS; - seconds -= hour*HOUR_SECONDS; - tm->tm_hour = hour; - - /* Minute */ - min = seconds/MINUTE_SECONDS; - seconds -= min*MINUTE_SECONDS; - tm->tm_min = min; - - /* Second */ - tm->tm_sec = seconds; - - return 7; + return 1; } int rtc_write_datetime(const struct tm *tm) { - int i, year; - unsigned int year_days = 0; - unsigned int month_days = 0; - unsigned int seconds = 0; - - year = 2000 + tm->tm_year - 100; - - if(is_leapyear(year)) { - days_in_month[1] = 29; - } else { - days_in_month[1] = 28; - } - - /* Number of days in months gone by this year*/ - for(i = 0; i < tm->tm_mon; i++){ - month_days += days_in_month[i]; - } + time_t time; + unsigned int seconds; + int i; - /* Number of days in years gone by since 1-Jan-1980 */ - year_days = 365*(tm->tm_year-100+20) + (tm->tm_year-100-1)/4 + 6; - - /* Convert to seconds since 1-Jan-1980 */ - seconds = tm->tm_sec - + tm->tm_min*MINUTE_SECONDS - + tm->tm_hour*HOUR_SECONDS - + (tm->tm_mday-1)*DAY_SECONDS - + month_days*DAY_SECONDS - + year_days*DAY_SECONDS; - seconds += SECS_ADJUST; + /* convert struct tm to time stamp */ + time = mktime((struct tm *)tm); + seconds = time - SECS_ADJUST; /* Send data to RTC */ for (i=0; i<4; i++){ diff --git a/firmware/libc/gmtime.c b/firmware/libc/gmtime.c new file mode 100644 index 0000000000..23b9c7b247 --- /dev/null +++ b/firmware/libc/gmtime.c @@ -0,0 +1,112 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2012 by Bertrik Sikken + * + * Based on code from: rtc_as3514.c + * Copyright (C) 2007 by Barry Wardell + * + * 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 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#include +#include "time.h" + +#define MINUTE_SECONDS 60 +#define HOUR_SECONDS 3600 +#define DAY_SECONDS 86400 +#define WEEK_SECONDS 604800 +#define YEAR_SECONDS 31536000 +#define LEAP_YEAR_SECONDS 31622400 + +/* Days in each month */ +static int days_in_month[] = + {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; + +static inline bool is_leapyear(int year) +{ + return (((year%4)==0) && (((year%100)!=0) || ((year%400)==0))); +} + +struct tm *gmtime(const time_t *timep) +{ + static struct tm time; + return gmtime_r(timep, &time); +} + +struct tm *gmtime_r(const time_t *timep, struct tm *tm) +{ + time_t seconds = *timep; + int year, i, mday, hour, min; + + /* weekday */ + tm->tm_wday = ((seconds % WEEK_SECONDS) / DAY_SECONDS + 4) % 7; + + /* Year */ + year = 1970; + while (seconds >= LEAP_YEAR_SECONDS) + { + if (is_leapyear(year)){ + seconds -= LEAP_YEAR_SECONDS; + } else { + seconds -= YEAR_SECONDS; + } + + year++; + } + + if (is_leapyear(year)) { + days_in_month[1] = 29; + } else { + days_in_month[1] = 28; + if(seconds>YEAR_SECONDS){ + year++; + seconds -= YEAR_SECONDS; + } + } + tm->tm_year = year%100 + 100; + + /* Month */ + for (i = 0; i < 12; i++) + { + if (seconds < days_in_month[i]*DAY_SECONDS){ + tm->tm_mon = i; + break; + } + + seconds -= days_in_month[i]*DAY_SECONDS; + } + + /* Month Day */ + mday = seconds/DAY_SECONDS; + seconds -= mday*DAY_SECONDS; + tm->tm_mday = mday + 1; /* 1 ... 31 */ + + /* Hour */ + hour = seconds/HOUR_SECONDS; + seconds -= hour*HOUR_SECONDS; + tm->tm_hour = hour; + + /* Minute */ + min = seconds/MINUTE_SECONDS; + seconds -= min*MINUTE_SECONDS; + tm->tm_min = min; + + /* Second */ + tm->tm_sec = seconds; + + return tm; +} + diff --git a/firmware/libc/include/time.h b/firmware/libc/include/time.h index 912fafe7ca..4796b8b083 100644 --- a/firmware/libc/include/time.h +++ b/firmware/libc/include/time.h @@ -34,6 +34,8 @@ typedef long time_t; #define _TIME_T_DECLARED time_t time(time_t *t); struct tm *localtime(const time_t *timep); +struct tm *gmtime(const time_t *timep); +struct tm *gmtime_r(const time_t *timep, struct tm *result); time_t mktime(struct tm *t); #endif /* SIMULATOR */ -- cgit v1.2.3