rockbox/firmware/drivers/rtc/rtc_as3514.c
Daniel Stenberg 2acc0ac542 Updated our source code header to explicitly mention that we are GPL v2 or
later. We still need to hunt down snippets used that are not. 1324 modified
files...
http://www.rockbox.org/mail/archive/rockbox-dev-archive-2008-06/0060.shtml


git-svn-id: svn://svn.rockbox.org/rockbox/trunk@17847 a1c6a512-1295-4272-9138-f99709370657
2008-06-28 18:10:04 +00:00

169 lines
4.4 KiB
C

/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id: rtc_as3514.c 12131 2007-01-27 20:48:48Z dan_a $
*
* 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 <stdbool.h>
#include "rtc.h"
#include "i2c-pp.h"
#include "as3514.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
#define BCD2DEC(X) (((((X)>>4) & 0x0f) * 10) + ((X) & 0xf))
#define DEC2BCD(X) ((((X)/10)<<4) | ((X)%10))
/* 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;
}
void rtc_init(void)
{
}
int rtc_read_datetime(unsigned char* buf)
{
char tmp[4];
int year;
int i;
unsigned int seconds;
/* RTC_AS3514's slave address is 0x46*/
for (i=0;i<4;i++){
tmp[i] = i2c_readbyte(AS3514_I2C_ADDR, AS3514_RTC_0 + i);
}
seconds = tmp[0] + (tmp[1]<<8) + (tmp[2]<<16) + (tmp[3]<<24);
/* Convert seconds since Jan-1-1980 to format compatible with
* get_time() from firmware/common/timefuncs.c */
/* weekday */
buf[3] = ((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;
}
}
buf[6] = year%100;
/* Month */
for(i=0; i<12; i++)
{
if(seconds < days_in_month[i]*DAY_SECONDS){
buf[5] = i+1;
break;
}
seconds -= days_in_month[i]*DAY_SECONDS;
}
/* Month Day */
buf[4] = seconds/DAY_SECONDS;
seconds -= buf[4]*DAY_SECONDS;
buf[4]++; /* 1 ... 31 */
/* Hour */
buf[2] = seconds/HOUR_SECONDS;
seconds -= buf[2]*HOUR_SECONDS;
/* Minute */
buf[1] = seconds/MINUTE_SECONDS;
seconds -= buf[1]*MINUTE_SECONDS;
/* Second */
buf[0] = seconds;
/* Convert to Binary Coded Decimal format */
for(i=0; i<7; i++)
buf[i] = DEC2BCD(buf[i]);
return 7;
}
int rtc_write_datetime(unsigned char* buf)
{
int i, year;
unsigned int year_days = 0;
unsigned int month_days = 0;
unsigned int seconds = 0;
/* Convert from Binary Coded Decimal format */
for(i=0; i<7; i++)
buf[i] = BCD2DEC(buf[i]);
year = 2000 + buf[6];
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<(buf[5]-1); i++){
month_days += days_in_month[i];
}
/* Number of days in years gone by since 1-Jan-1980 */
year_days = 365*(buf[6]+20) + (buf[6]-1)/4 + 6;
/* Convert to seconds since 1-Jan-1980 */
seconds = buf[0]
+ buf[1]*MINUTE_SECONDS
+ buf[2]*HOUR_SECONDS
+ (buf[4]-1)*DAY_SECONDS
+ month_days*DAY_SECONDS
+ year_days*DAY_SECONDS;
/* Send data to RTC */
for (i=0;i<4;i++){
pp_i2c_send(AS3514_I2C_ADDR, AS3514_RTC_0 + i, ((seconds >> (8 * i)) & 0xff));
}
return 1;
}