Rockbox supports not only 1bpp BMPs
[kugel-rb.git] / firmware / drivers / rtc / rtc_as3514.c
blob878f204a4e8897cea2df4b3d375d41be97da3e05
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id: rtc_as3514.c 12131 2007-01-27 20:48:48Z dan_a $
10 * Copyright (C) 2007 by Barry Wardell
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
21 #include <stdbool.h>
22 #include "rtc.h"
23 #include "i2c-pp.h"
24 #include "as3514.h"
25 #include "ascodec.h"
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
34 #define BCD2DEC(X) (((((X)>>4) & 0x0f) * 10) + ((X) & 0xf))
35 #define DEC2BCD(X) ((((X)/10)<<4) | ((X)%10))
37 /* Days in each month */
38 static unsigned int days_in_month[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
40 static inline bool is_leapyear(int year)
42 if( ((year%4)==0) && (((year%100)!=0) || ((year%400)==0)) )
43 return true;
44 else
45 return false;
48 void rtc_init(void)
52 int rtc_read_datetime(unsigned char* buf)
54 char tmp[4];
55 int year;
56 int i;
57 unsigned int seconds;
59 /* RTC_AS3514's slave address is 0x46*/
60 for (i=0;i<4;i++){
61 tmp[i] = ascodec_read(AS3514_RTC_0 + i);
63 seconds = tmp[0] + (tmp[1]<<8) + (tmp[2]<<16) + (tmp[3]<<24);
65 /* Convert seconds since Jan-1-1980 to format compatible with
66 * get_time() from firmware/common/timefuncs.c */
68 /* weekday */
69 buf[3] = ((seconds % WEEK_SECONDS) / DAY_SECONDS + 2) % 7;
71 /* Year */
72 year = 1980;
73 while(seconds>=LEAP_YEAR_SECONDS)
75 if(is_leapyear(year)){
76 seconds -= LEAP_YEAR_SECONDS;
77 } else {
78 seconds -= YEAR_SECONDS;
81 year++;
84 if(is_leapyear(year)) {
85 days_in_month[1] = 29;
86 } else {
87 days_in_month[1] = 28;
88 if(seconds>YEAR_SECONDS){
89 year++;
90 seconds -= YEAR_SECONDS;
93 buf[6] = year%100;
95 /* Month */
96 for(i=0; i<12; i++)
98 if(seconds < days_in_month[i]*DAY_SECONDS){
99 buf[5] = i+1;
100 break;
103 seconds -= days_in_month[i]*DAY_SECONDS;
106 /* Month Day */
107 buf[4] = seconds/DAY_SECONDS;
108 seconds -= buf[4]*DAY_SECONDS;
109 buf[4]++; /* 1 ... 31 */
111 /* Hour */
112 buf[2] = seconds/HOUR_SECONDS;
113 seconds -= buf[2]*HOUR_SECONDS;
115 /* Minute */
116 buf[1] = seconds/MINUTE_SECONDS;
117 seconds -= buf[1]*MINUTE_SECONDS;
119 /* Second */
120 buf[0] = seconds;
122 /* Convert to Binary Coded Decimal format */
123 for(i=0; i<7; i++)
124 buf[i] = DEC2BCD(buf[i]);
126 return 7;
129 int rtc_write_datetime(unsigned char* buf)
131 int i, year;
132 unsigned int year_days = 0;
133 unsigned int month_days = 0;
134 unsigned int seconds = 0;
136 /* Convert from Binary Coded Decimal format */
137 for(i=0; i<7; i++)
138 buf[i] = BCD2DEC(buf[i]);
140 year = 2000 + buf[6];
142 if(is_leapyear(year)) {
143 days_in_month[1] = 29;
144 } else {
145 days_in_month[1] = 28;
148 /* Number of days in months gone by this year*/
149 for(i=0; i<(buf[5]-1); i++){
150 month_days += days_in_month[i];
153 /* Number of days in years gone by since 1-Jan-1980 */
154 year_days = 365*(buf[6]+20) + (buf[6]-1)/4 + 6;
156 /* Convert to seconds since 1-Jan-1980 */
157 seconds = buf[0]
158 + buf[1]*MINUTE_SECONDS
159 + buf[2]*HOUR_SECONDS
160 + (buf[4]-1)*DAY_SECONDS
161 + month_days*DAY_SECONDS
162 + year_days*DAY_SECONDS;
164 /* Send data to RTC */
165 for (i=0;i<4;i++){
166 ascodec_write(AS3514_RTC_0 + i, ((seconds >> (8 * i)) & 0xff));
168 return 1;