blob: 65d8359e08a902dace59a9014811d6a718016025 [file] [log] [blame]
Barry Wardell1a2dddc2007-02-03 13:10:17 +00001/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id: rtc_as3514.c 12131 2007-01-27 20:48:48Z dan_a $
9 *
10 * Copyright (C) 2007 by Barry Wardell
11 *
Daniel Stenberg2acc0ac2008-06-28 18:10:04 +000012 * 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.
Barry Wardell1a2dddc2007-02-03 13:10:17 +000016 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
Barry Wardell007563c2007-10-25 09:03:47 +000021#include <stdbool.h>
Barry Wardell1a2dddc2007-02-03 13:10:17 +000022#include "rtc.h"
23#include "i2c-pp.h"
Barry Wardell007563c2007-10-25 09:03:47 +000024#include "as3514.h"
Barry Wardell1a2dddc2007-02-03 13:10:17 +000025
26#define MINUTE_SECONDS 60
27#define HOUR_SECONDS 3600
28#define DAY_SECONDS 86400
29#define WEEK_SECONDS 604800
30#define YEAR_SECONDS 31536000
31#define LEAP_YEAR_SECONDS 31622400
32
33#define BCD2DEC(X) (((((X)>>4) & 0x0f) * 10) + ((X) & 0xf))
34#define DEC2BCD(X) ((((X)/10)<<4) | ((X)%10))
35
36/* Days in each month */
37static unsigned int days_in_month[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
38
39static inline bool is_leapyear(int year)
40{
41 if( ((year%4)==0) && (((year%100)!=0) || ((year%400)==0)) )
42 return true;
43 else
44 return false;
45}
46
47void rtc_init(void)
48{
49}
50
51int rtc_read_datetime(unsigned char* buf)
52{
53 char tmp[4];
54 int year;
55 int i;
56 unsigned int seconds;
57
58 /* RTC_AS3514's slave address is 0x46*/
59 for (i=0;i<4;i++){
Bertrik Sikkena24f4b72008-04-15 21:33:32 +000060 tmp[i] = i2c_readbyte(AS3514_I2C_ADDR, AS3514_RTC_0 + i);
Barry Wardell1a2dddc2007-02-03 13:10:17 +000061 }
62 seconds = tmp[0] + (tmp[1]<<8) + (tmp[2]<<16) + (tmp[3]<<24);
63
64 /* Convert seconds since Jan-1-1980 to format compatible with
65 * get_time() from firmware/common/timefuncs.c */
66
67 /* weekday */
Linus Nielsen Feltzing03795882007-03-15 22:25:04 +000068 buf[3] = ((seconds % WEEK_SECONDS) / DAY_SECONDS + 2) % 7;
Barry Wardell1a2dddc2007-02-03 13:10:17 +000069
70 /* Year */
71 year = 1980;
72 while(seconds>=LEAP_YEAR_SECONDS)
73 {
Barry Wardell1a2dddc2007-02-03 13:10:17 +000074 if(is_leapyear(year)){
75 seconds -= LEAP_YEAR_SECONDS;
76 } else {
77 seconds -= YEAR_SECONDS;
78 }
Antonius Hellmannd68a5162007-05-04 07:37:19 +000079
80 year++;
Barry Wardell1a2dddc2007-02-03 13:10:17 +000081 }
82
83 if(is_leapyear(year)) {
84 days_in_month[1] = 29;
85 } else {
86 days_in_month[1] = 28;
87 if(seconds>YEAR_SECONDS){
88 year++;
89 seconds -= YEAR_SECONDS;
90 }
91 }
92 buf[6] = year%100;
93
94 /* Month */
95 for(i=0; i<12; i++)
96 {
97 if(seconds < days_in_month[i]*DAY_SECONDS){
98 buf[5] = i+1;
99 break;
100 }
101
102 seconds -= days_in_month[i]*DAY_SECONDS;
103 }
104
105 /* Month Day */
106 buf[4] = seconds/DAY_SECONDS;
107 seconds -= buf[4]*DAY_SECONDS;
Antonius Hellmannd68a5162007-05-04 07:37:19 +0000108 buf[4]++; /* 1 ... 31 */
Barry Wardell1a2dddc2007-02-03 13:10:17 +0000109
110 /* Hour */
111 buf[2] = seconds/HOUR_SECONDS;
112 seconds -= buf[2]*HOUR_SECONDS;
113
114 /* Minute */
115 buf[1] = seconds/MINUTE_SECONDS;
116 seconds -= buf[1]*MINUTE_SECONDS;
117
118 /* Second */
119 buf[0] = seconds;
120
121 /* Convert to Binary Coded Decimal format */
122 for(i=0; i<7; i++)
123 buf[i] = DEC2BCD(buf[i]);
124
125 return 7;
126}
127
128int rtc_write_datetime(unsigned char* buf)
129{
130 int i, year;
131 unsigned int year_days = 0;
132 unsigned int month_days = 0;
133 unsigned int seconds = 0;
134
135 /* Convert from Binary Coded Decimal format */
136 for(i=0; i<7; i++)
137 buf[i] = BCD2DEC(buf[i]);
138
139 year = 2000 + buf[6];
140
141 if(is_leapyear(year)) {
142 days_in_month[1] = 29;
143 } else {
144 days_in_month[1] = 28;
145 }
146
147 /* Number of days in months gone by this year*/
148 for(i=0; i<(buf[5]-1); i++){
149 month_days += days_in_month[i];
150 }
151
152 /* Number of days in years gone by since 1-Jan-1980 */
Antonius Hellmannd68a5162007-05-04 07:37:19 +0000153 year_days = 365*(buf[6]+20) + (buf[6]-1)/4 + 6;
Barry Wardell1a2dddc2007-02-03 13:10:17 +0000154
155 /* Convert to seconds since 1-Jan-1980 */
156 seconds = buf[0]
157 + buf[1]*MINUTE_SECONDS
158 + buf[2]*HOUR_SECONDS
Barry Wardell7174e882007-02-04 20:43:25 +0000159 + (buf[4]-1)*DAY_SECONDS
Barry Wardell1a2dddc2007-02-03 13:10:17 +0000160 + month_days*DAY_SECONDS
161 + year_days*DAY_SECONDS;
162
163 /* Send data to RTC */
164 for (i=0;i<4;i++){
Bertrik Sikkena24f4b72008-04-15 21:33:32 +0000165 pp_i2c_send(AS3514_I2C_ADDR, AS3514_RTC_0 + i, ((seconds >> (8 * i)) & 0xff));
Barry Wardell1a2dddc2007-02-03 13:10:17 +0000166 }
167 return 1;
168}
169