summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBertrik Sikken <bertrik@sikken.nl>2012-03-08 21:21:31 +0100
committerRafaël Carré <rafael.carre@gmail.com>2012-03-11 22:10:54 +0100
commit727e8aa6817be8816bc32184f2e2eb36b90b4a9e (patch)
treea5e8f7c50ba68bdd4a6ca60c2bdfdbde6a6d6bfd
parent3448f5b6ad25f59e01ece347cb06e09652915e30 (diff)
downloadrockbox-727e8aa6817be8816bc32184f2e2eb36b90b4a9e.tar.gz
rockbox-727e8aa6817be8816bc32184f2e2eb36b90b4a9e.zip
Introduce gmtime.c and use it in the AS3514 RTC driver
Change-Id: I00a09ae28a68f8153fb8fa854fea741ddfb0bf09 Reviewed-on: http://gerrit.rockbox.org/175 Tested-by: Bertrik Sikken <bertrik@sikken.nl> Reviewed-by: Michael Sevakis <jethead71@rockbox.org> Reviewed-by: Rafaël Carré <rafael.carre@gmail.com>
-rw-r--r--firmware/SOURCES1
-rw-r--r--firmware/drivers/rtc/rtc_as3514.c127
-rw-r--r--firmware/libc/gmtime.c112
-rw-r--r--firmware/libc/include/time.h2
4 files changed, 131 insertions, 111 deletions
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
128libc/strrchr.c 128libc/strrchr.c
129libc/strstr.c 129libc/strstr.c
130libc/mktime.c 130libc/mktime.c
131libc/gmtime.c
131#endif /* CONFIG_PLATFORM || HAVE_ROCKBOX_C_LIBRARY */ 132#endif /* CONFIG_PLATFORM || HAVE_ROCKBOX_C_LIBRARY */
132 133
133/* Common */ 134/* 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 @@
23#include "rtc.h" 23#include "rtc.h"
24#include "as3514.h" 24#include "as3514.h"
25#include "ascodec.h" 25#include "ascodec.h"
26#include "time.h"
26 27
27/* AMS Sansas start counting from Jan 1st 1970 instead of 1980 (not as3525v2) */ 28/* AMS Sansas start counting from Jan 1st 1970 instead of 1980 (not as3525v2) */
28#if (CONFIG_CPU==AS3525) 29#if (CONFIG_CPU==AS3525)
29#define SECS_ADJUST 315532800 /* seconds between 1970-1-1 and 1980-1-1 */ 30#define SECS_ADJUST 0
30#elif (CONFIG_CPU==AS3525v2) 31#elif (CONFIG_CPU==AS3525v2)
31#define SECS_ADJUST 315532800 - (2*365*24*3600) - 26*(24*3600) + 7*3600 + 25*60 32#define SECS_ADJUST ((2*365*24*3600) + 26*(24*3600) - 7*3600 - 25*60)
32#else 33#else
33#define SECS_ADJUST 0 34#define SECS_ADJUST 315532800 /* 1980/1/1 */
34#endif 35#endif
35 36
36#define MINUTE_SECONDS 60
37#define HOUR_SECONDS 3600
38#define DAY_SECONDS 86400
39#define WEEK_SECONDS 604800
40#define YEAR_SECONDS 31536000
41#define LEAP_YEAR_SECONDS 31622400
42
43/* Days in each month */
44static unsigned int days_in_month[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
45
46static inline bool is_leapyear(int year)
47{
48 if( ((year%4)==0) && (((year%100)!=0) || ((year%400)==0)) )
49 return true;
50 else
51 return false;
52}
53
54#ifdef HAVE_RTC_ALARM /* as3543 */ 37#ifdef HAVE_RTC_ALARM /* as3543 */
55static struct { 38static struct {
56 unsigned int seconds; /* total seconds to wakeup */ 39 unsigned int seconds; /* total seconds to wakeup */
@@ -197,109 +180,31 @@ void rtc_init(void)
197int rtc_read_datetime(struct tm *tm) 180int rtc_read_datetime(struct tm *tm)
198{ 181{
199 char tmp[4]; 182 char tmp[4];
200 int i, year, mday, hour, min;
201 unsigned int seconds; 183 unsigned int seconds;
184 int i;
202 185
203 /* RTC_AS3514's slave address is 0x46*/ 186 /* Get seconds time stamp from RTC */
204 for (i = 0; i < 4; i++){ 187 for (i = 0; i < 4; i++){
205 tmp[i] = ascodec_read(AS3514_RTC_0 + i); 188 tmp[i] = ascodec_read(AS3514_RTC_0 + i);
206 } 189 }
207 seconds = tmp[0] + (tmp[1]<<8) + (tmp[2]<<16) + (tmp[3]<<24); 190 seconds = tmp[0] + (tmp[1]<<8) + (tmp[2]<<16) + (tmp[3]<<24);
208 seconds -= SECS_ADJUST;
209 191
210 /* Convert seconds since Jan-1-1980 to format compatible with 192 /* convert to struct tm */
211 * get_time() from firmware/common/timefuncs.c */ 193 time_t time = seconds + SECS_ADJUST;
194 gmtime_r(&time, tm);
212 195
213 /* weekday */ 196 return 1;
214 tm->tm_wday = ((seconds % WEEK_SECONDS) / DAY_SECONDS + 2) % 7;
215
216 /* Year */
217 year = 1980;
218 while (seconds >= LEAP_YEAR_SECONDS)
219 {
220 if (is_leapyear(year)){
221 seconds -= LEAP_YEAR_SECONDS;
222 } else {
223 seconds -= YEAR_SECONDS;
224 }
225
226 year++;
227 }
228
229 if (is_leapyear(year)) {
230 days_in_month[1] = 29;
231 } else {
232 days_in_month[1] = 28;
233 if(seconds>YEAR_SECONDS){
234 year++;
235 seconds -= YEAR_SECONDS;
236 }
237 }
238 tm->tm_year = year%100 + 100;
239
240 /* Month */
241 for (i = 0; i < 12; i++)
242 {
243 if (seconds < days_in_month[i]*DAY_SECONDS){
244 tm->tm_mon = i;
245 break;
246 }
247
248 seconds -= days_in_month[i]*DAY_SECONDS;
249 }
250
251 /* Month Day */
252 mday = seconds/DAY_SECONDS;
253 seconds -= mday*DAY_SECONDS;
254 tm->tm_mday = mday + 1; /* 1 ... 31 */
255
256 /* Hour */
257 hour = seconds/HOUR_SECONDS;
258 seconds -= hour*HOUR_SECONDS;
259 tm->tm_hour = hour;
260
261 /* Minute */
262 min = seconds/MINUTE_SECONDS;
263 seconds -= min*MINUTE_SECONDS;
264 tm->tm_min = min;
265
266 /* Second */
267 tm->tm_sec = seconds;
268
269 return 7;
270} 197}
271 198
272int rtc_write_datetime(const struct tm *tm) 199int rtc_write_datetime(const struct tm *tm)
273{ 200{
274 int i, year; 201 time_t time;
275 unsigned int year_days = 0; 202 unsigned int seconds;
276 unsigned int month_days = 0; 203 int i;
277 unsigned int seconds = 0;
278
279 year = 2000 + tm->tm_year - 100;
280
281 if(is_leapyear(year)) {
282 days_in_month[1] = 29;
283 } else {
284 days_in_month[1] = 28;
285 }
286
287 /* Number of days in months gone by this year*/
288 for(i = 0; i < tm->tm_mon; i++){
289 month_days += days_in_month[i];
290 }
291 204
292 /* Number of days in years gone by since 1-Jan-1980 */ 205 /* convert struct tm to time stamp */
293 year_days = 365*(tm->tm_year-100+20) + (tm->tm_year-100-1)/4 + 6; 206 time = mktime((struct tm *)tm);
294 207 seconds = time - SECS_ADJUST;
295 /* Convert to seconds since 1-Jan-1980 */
296 seconds = tm->tm_sec
297 + tm->tm_min*MINUTE_SECONDS
298 + tm->tm_hour*HOUR_SECONDS
299 + (tm->tm_mday-1)*DAY_SECONDS
300 + month_days*DAY_SECONDS
301 + year_days*DAY_SECONDS;
302 seconds += SECS_ADJUST;
303 208
304 /* Send data to RTC */ 209 /* Send data to RTC */
305 for (i=0; i<4; i++){ 210 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 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2012 by Bertrik Sikken
11 *
12 * Based on code from: rtc_as3514.c
13 * Copyright (C) 2007 by Barry Wardell
14 *
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
19 *
20 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
21 * KIND, either express or implied.
22 *
23 ****************************************************************************/
24#include <stdbool.h>
25#include "time.h"
26
27#define MINUTE_SECONDS 60
28#define HOUR_SECONDS 3600
29#define DAY_SECONDS 86400
30#define WEEK_SECONDS 604800
31#define YEAR_SECONDS 31536000
32#define LEAP_YEAR_SECONDS 31622400
33
34/* Days in each month */
35static int days_in_month[] =
36 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
37
38static inline bool is_leapyear(int year)
39{
40 return (((year%4)==0) && (((year%100)!=0) || ((year%400)==0)));
41}
42
43struct tm *gmtime(const time_t *timep)
44{
45 static struct tm time;
46 return gmtime_r(timep, &time);
47}
48
49struct tm *gmtime_r(const time_t *timep, struct tm *tm)
50{
51 time_t seconds = *timep;
52 int year, i, mday, hour, min;
53
54 /* weekday */
55 tm->tm_wday = ((seconds % WEEK_SECONDS) / DAY_SECONDS + 4) % 7;
56
57 /* Year */
58 year = 1970;
59 while (seconds >= LEAP_YEAR_SECONDS)
60 {
61 if (is_leapyear(year)){
62 seconds -= LEAP_YEAR_SECONDS;
63 } else {
64 seconds -= YEAR_SECONDS;
65 }
66
67 year++;
68 }
69
70 if (is_leapyear(year)) {
71 days_in_month[1] = 29;
72 } else {
73 days_in_month[1] = 28;
74 if(seconds>YEAR_SECONDS){
75 year++;
76 seconds -= YEAR_SECONDS;
77 }
78 }
79 tm->tm_year = year%100 + 100;
80
81 /* Month */
82 for (i = 0; i < 12; i++)
83 {
84 if (seconds < days_in_month[i]*DAY_SECONDS){
85 tm->tm_mon = i;
86 break;
87 }
88
89 seconds -= days_in_month[i]*DAY_SECONDS;
90 }
91
92 /* Month Day */
93 mday = seconds/DAY_SECONDS;
94 seconds -= mday*DAY_SECONDS;
95 tm->tm_mday = mday + 1; /* 1 ... 31 */
96
97 /* Hour */
98 hour = seconds/HOUR_SECONDS;
99 seconds -= hour*HOUR_SECONDS;
100 tm->tm_hour = hour;
101
102 /* Minute */
103 min = seconds/MINUTE_SECONDS;
104 seconds -= min*MINUTE_SECONDS;
105 tm->tm_min = min;
106
107 /* Second */
108 tm->tm_sec = seconds;
109
110 return tm;
111}
112
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;
34#define _TIME_T_DECLARED 34#define _TIME_T_DECLARED
35time_t time(time_t *t); 35time_t time(time_t *t);
36struct tm *localtime(const time_t *timep); 36struct tm *localtime(const time_t *timep);
37struct tm *gmtime(const time_t *timep);
38struct tm *gmtime_r(const time_t *timep, struct tm *result);
37time_t mktime(struct tm *t); 39time_t mktime(struct tm *t);
38 40
39#endif /* SIMULATOR */ 41#endif /* SIMULATOR */