1
0
Fork 0
forked from len0rd/rockbox

FS#10569 RTC driver cleanup

Change the RTC drivers so that the rtc_(read|write)_datetime functions now deal directly with the tm struct instead of passing a string of bcd digits to/from (set|get)_time .
This simplifies drivers for rtc's that do not use a bcd representation internally and cleans up some target specific code and #ifdefs in generic code. Implement simple stubs for the sim to avoid #ifdefing for that too.


git-svn-id: svn://svn.rockbox.org/rockbox/trunk@22839 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Nils Wallménius 2009-09-26 14:58:32 +00:00
parent 66d5bd7cf8
commit c8b87d76eb
16 changed files with 452 additions and 373 deletions

View file

@ -27,9 +27,7 @@
#include "timefuncs.h" #include "timefuncs.h"
#include "debug.h" #include "debug.h"
#if !defined SIMULATOR || !CONFIG_RTC
static struct tm tm; static struct tm tm;
#endif /* !defined SIMULATOR || !CONFIG_RTC */
#if !CONFIG_RTC #if !CONFIG_RTC
static void fill_default_tm(struct tm *tm) static void fill_default_tm(struct tm *tm)
@ -62,7 +60,6 @@ bool valid_time(const struct tm *tm)
struct tm *get_time(void) struct tm *get_time(void)
{ {
#ifndef SIMULATOR
#if CONFIG_RTC #if CONFIG_RTC
static long timeout = 0; static long timeout = 0;
@ -71,76 +68,25 @@ struct tm *get_time(void)
{ {
/* Once per second, 1/10th of a second off */ /* Once per second, 1/10th of a second off */
timeout = HZ * (current_tick / HZ + 1) + HZ / 5; timeout = HZ * (current_tick / HZ + 1) + HZ / 5;
#if CONFIG_RTC != RTC_JZ47XX rtc_read_datetime(&tm);
char rtcbuf[7];
rtc_read_datetime(rtcbuf);
tm.tm_sec = ((rtcbuf[0] & 0x70) >> 4) * 10 + (rtcbuf[0] & 0x0f);
tm.tm_min = ((rtcbuf[1] & 0x70) >> 4) * 10 + (rtcbuf[1] & 0x0f);
tm.tm_hour = ((rtcbuf[2] & 0x30) >> 4) * 10 + (rtcbuf[2] & 0x0f);
tm.tm_wday = rtcbuf[3] & 0x07;
tm.tm_mday = ((rtcbuf[4] & 0x30) >> 4) * 10 + (rtcbuf[4] & 0x0f);
tm.tm_mon = ((rtcbuf[5] & 0x10) >> 4) * 10 + (rtcbuf[5] & 0x0f) - 1;
#ifdef IRIVER_H300_SERIES
/* Special kludge to coexist with the iriver firmware. The iriver firmware
stores the date as 1965+nn, and allows a range of 1980..2064. We use
1964+nn here to make leap years work correctly, so the date will be one
year off in the iriver firmware but at least won't be reset anymore. */
tm.tm_year = ((rtcbuf[6] & 0xf0) >> 4) * 10 + (rtcbuf[6] & 0x0f) + 64;
#else /* Not IRIVER_H300_SERIES */
tm.tm_year = ((rtcbuf[6] & 0xf0) >> 4) * 10 + (rtcbuf[6] & 0x0f) + 100;
#endif /* IRIVER_H300_SERIES */
tm.tm_yday = 0; /* Not implemented for now */ tm.tm_yday = 0; /* Not implemented for now */
tm.tm_isdst = -1; /* Not implemented for now */ tm.tm_isdst = -1; /* Not implemented for now */
#else /* CONFIG_RTC == RTC_JZ47XX */
rtc_read_datetime((unsigned char*)&tm);
#endif /* CONFIG_RTC */
} }
#else /* No RTC */ #else /* No RTC */
fill_default_tm(&tm); fill_default_tm(&tm);
#endif /* RTC */ #endif /* RTC */
return &tm; return &tm;
#else /* SIMULATOR */
#if CONFIG_RTC
time_t now = time(NULL);
return localtime(&now);
#else /* Simulator, no RTC */
fill_default_tm(&tm);
return &tm;
#endif
#endif /* SIMULATOR */
} }
int set_time(const struct tm *tm) int set_time(const struct tm *tm)
{ {
#if CONFIG_RTC #if CONFIG_RTC
int rc; int rc;
#if CONFIG_RTC != RTC_JZ47XX
char rtcbuf[7];
#endif
if (valid_time(tm)) if (valid_time(tm))
{ {
#if CONFIG_RTC != RTC_JZ47XX rc = rtc_write_datetime(tm);
rtcbuf[0]=((tm->tm_sec/10) << 4) | (tm->tm_sec%10);
rtcbuf[1]=((tm->tm_min/10) << 4) | (tm->tm_min%10);
rtcbuf[2]=((tm->tm_hour/10) << 4) | (tm->tm_hour%10);
rtcbuf[3]=tm->tm_wday;
rtcbuf[4]=((tm->tm_mday/10) << 4) | (tm->tm_mday%10);
rtcbuf[5]=(((tm->tm_mon+1)/10) << 4) | ((tm->tm_mon+1)%10);
#ifdef IRIVER_H300_SERIES
/* Iriver firmware compatibility kludge, see get_time(). */
rtcbuf[6]=(((tm->tm_year-64)/10) << 4) | ((tm->tm_year-64)%10);
#else
rtcbuf[6]=(((tm->tm_year-100)/10) << 4) | ((tm->tm_year-100)%10);
#endif
rc = rtc_write_datetime(rtcbuf);
#else
rc = rtc_write_datetime((unsigned char*)tm);
#endif
if (rc < 0) if (rc < 0)
return -1; return -1;
@ -151,10 +97,10 @@ int set_time(const struct tm *tm)
{ {
return -2; return -2;
} }
#else #else /* No RTC */
(void)tm; (void)tm;
return 0; return 0;
#endif #endif /* RTC */
} }
#if CONFIG_RTC #if CONFIG_RTC
@ -196,11 +142,12 @@ time_t mktime(struct tm *t)
void set_day_of_week(struct tm *tm) void set_day_of_week(struct tm *tm)
{ {
int y=tm->tm_year+1900; int y=tm->tm_year+1900;
int d=tm->tm_mday; int d=tm->tm_mday;
int m=tm->tm_mon; int m=tm->tm_mon;
static const char mo[] = { 0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4 }; static const char mo[] = { 0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4 };
if(m == 0 || m == 1) y--; if(m == 0 || m == 1) y--;
tm->tm_wday = (d + mo[m] + y + y/4 - y/100 + y/400) % 7; tm->tm_wday = (d + mo[m] + y + y/4 - y/100 + y/400) % 7;
} }

View file

@ -38,9 +38,6 @@
#define YEAR_SECONDS 31536000 #define YEAR_SECONDS 31536000
#define LEAP_YEAR_SECONDS 31622400 #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 */ /* Days in each month */
static unsigned int days_in_month[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; static unsigned int days_in_month[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
@ -56,31 +53,30 @@ void rtc_init(void)
{ {
} }
int rtc_read_datetime(unsigned char* buf) int rtc_read_datetime(struct tm *tm)
{ {
char tmp[4]; char tmp[4];
int year; int i, year, mday, hour, min;
int i;
unsigned int seconds; unsigned int seconds;
/* RTC_AS3514's slave address is 0x46*/ /* RTC_AS3514's slave address is 0x46*/
for (i=0;i<4;i++){ for (i = 0; i < 4; i++){
tmp[i] = ascodec_read(AS3514_RTC_0 + i); tmp[i] = ascodec_read(AS3514_RTC_0 + i);
} }
seconds = tmp[0] + (tmp[1]<<8) + (tmp[2]<<16) + (tmp[3]<<24); seconds = tmp[0] + (tmp[1]<<8) + (tmp[2]<<16) + (tmp[3]<<24);
seconds -= SECS_ADJUST; seconds -= SECS_ADJUST;
/* Convert seconds since Jan-1-1980 to format compatible with /* Convert seconds since Jan-1-1980 to format compatible with
* get_time() from firmware/common/timefuncs.c */ * get_time() from firmware/common/timefuncs.c */
/* weekday */ /* weekday */
buf[3] = ((seconds % WEEK_SECONDS) / DAY_SECONDS + 2) % 7; tm->tm_wday = ((seconds % WEEK_SECONDS) / DAY_SECONDS + 2) % 7;
/* Year */ /* Year */
year = 1980; year = 1980;
while(seconds>=LEAP_YEAR_SECONDS) while (seconds >= LEAP_YEAR_SECONDS)
{ {
if(is_leapyear(year)){ if (is_leapyear(year)){
seconds -= LEAP_YEAR_SECONDS; seconds -= LEAP_YEAR_SECONDS;
} else { } else {
seconds -= YEAR_SECONDS; seconds -= YEAR_SECONDS;
@ -88,8 +84,8 @@ int rtc_read_datetime(unsigned char* buf)
year++; year++;
} }
if(is_leapyear(year)) { if (is_leapyear(year)) {
days_in_month[1] = 29; days_in_month[1] = 29;
} else { } else {
days_in_month[1] = 28; days_in_month[1] = 28;
@ -98,54 +94,48 @@ int rtc_read_datetime(unsigned char* buf)
seconds -= YEAR_SECONDS; seconds -= YEAR_SECONDS;
} }
} }
buf[6] = year%100; tm->tm_year = year%100 + 100;
/* Month */ /* Month */
for(i=0; i<12; i++) for (i = 0; i < 12; i++)
{ {
if(seconds < days_in_month[i]*DAY_SECONDS){ if (seconds < days_in_month[i]*DAY_SECONDS){
buf[5] = i+1; tm->tm_mon = i;
break; break;
} }
seconds -= days_in_month[i]*DAY_SECONDS; seconds -= days_in_month[i]*DAY_SECONDS;
} }
/* Month Day */ /* Month Day */
buf[4] = seconds/DAY_SECONDS; mday = seconds/DAY_SECONDS;
seconds -= buf[4]*DAY_SECONDS; seconds -= mday*DAY_SECONDS;
buf[4]++; /* 1 ... 31 */ tm->tm_mday = mday + 1; /* 1 ... 31 */
/* Hour */ /* Hour */
buf[2] = seconds/HOUR_SECONDS; hour = seconds/HOUR_SECONDS;
seconds -= buf[2]*HOUR_SECONDS; seconds -= hour*HOUR_SECONDS;
tm->tm_hour = hour;
/* Minute */ /* Minute */
buf[1] = seconds/MINUTE_SECONDS; min = seconds/MINUTE_SECONDS;
seconds -= buf[1]*MINUTE_SECONDS; seconds -= min*MINUTE_SECONDS;
tm->tm_min = min;
/* Second */ /* Second */
buf[0] = seconds; tm->tm_sec = seconds;
/* Convert to Binary Coded Decimal format */
for(i=0; i<7; i++)
buf[i] = DEC2BCD(buf[i]);
return 7; return 7;
} }
int rtc_write_datetime(unsigned char* buf) int rtc_write_datetime(const struct tm *tm)
{ {
int i, year; int i, year;
unsigned int year_days = 0; unsigned int year_days = 0;
unsigned int month_days = 0; unsigned int month_days = 0;
unsigned int seconds = 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]; year = 2000 + tm->tm_year - 100;
if(is_leapyear(year)) { if(is_leapyear(year)) {
days_in_month[1] = 29; days_in_month[1] = 29;
@ -154,24 +144,24 @@ int rtc_write_datetime(unsigned char* buf)
} }
/* Number of days in months gone by this year*/ /* Number of days in months gone by this year*/
for(i=0; i<(buf[5]-1); i++){ for(i = 0; i < tm->tm_mon; i++){
month_days += days_in_month[i]; month_days += days_in_month[i];
} }
/* Number of days in years gone by since 1-Jan-1980 */ /* Number of days in years gone by since 1-Jan-1980 */
year_days = 365*(buf[6]+20) + (buf[6]-1)/4 + 6; year_days = 365*(tm->tm_year+20) + (tm->tm_year-1)/4 + 6;
/* Convert to seconds since 1-Jan-1980 */ /* Convert to seconds since 1-Jan-1980 */
seconds = buf[0] seconds = tm->tm_sec
+ buf[1]*MINUTE_SECONDS + tm->tm_min*MINUTE_SECONDS
+ buf[2]*HOUR_SECONDS + tm->tm_hour*HOUR_SECONDS
+ (buf[4]-1)*DAY_SECONDS + (tm->tm_mday-1)*DAY_SECONDS
+ month_days*DAY_SECONDS + month_days*DAY_SECONDS
+ year_days*DAY_SECONDS; + year_days*DAY_SECONDS;
seconds += SECS_ADJUST; seconds += SECS_ADJUST;
/* Send data to RTC */ /* Send data to RTC */
for (i=0;i<4;i++){ for (i=0; i<4; i++){
ascodec_write(AS3514_RTC_0 + i, ((seconds >> (8 * i)) & 0xff)); ascodec_write(AS3514_RTC_0 + i, ((seconds >> (8 * i)) & 0xff));
} }
return 1; return 1;

View file

@ -115,26 +115,46 @@ bool rtc_enable_alarm(bool enable)
#endif /* HAVE_RTC_ALARM */ #endif /* HAVE_RTC_ALARM */
int rtc_read_datetime(unsigned char* buf) int rtc_read_datetime(struct tm *tm)
{ {
int i; int rc;
unsigned char buf[7];
i = sw_i2c_read(RTC_ADDR, 0, buf, 7); rc = sw_i2c_read(RTC_ADDR, 0, buf, sizeof(buf));
buf[3]--; /* timefuncs wants 0..6 for wday */
return i; /* convert from bcd, avoid getting extra bits */
tm->tm_sec = BCD2DEC(buf[0] & 0x7f);
tm->tm_min = BCD2DEC(buf[1] & 0x7f);
tm->tm_hour = BCD2DEC(buf[2] & 0x3f);
tm->tm_wday = BCD2DEC(buf[3] & 0x3) - 1; /* timefuncs wants 0..6 for wday */
tm->tm_mday = BCD2DEC(buf[4] & 0x3f);
tm->tm_mon = BCD2DEC(buf[5] & 0x1f) - 1;
tm->tm_year = BCD2DEC(buf[6]) + 100;
return rc;
} }
int rtc_write_datetime(unsigned char* buf) int rtc_write_datetime(const struct tm *tm)
{ {
int i; unsigned int i;
int rc;
unsigned char buf[7];
buf[3]++; /* chip wants 1..7 for wday */ buf[0] = tm->tm_sec;
buf[5]|=0x80; /* chip wants century (always 20xx) */ buf[1] = tm->tm_min;
buf[2] = tm->tm_hour;
buf[3] = tm->tm_wday + 1; /* chip wants 1..7 for wday */
buf[4] = tm->tm_mday;
buf[5] = tm->tm_mon + 1;
buf[6] = tm->tm_year - 100;
i = sw_i2c_write(RTC_ADDR, 0, buf, 7); for (i = 0; i < sizeof(buf); i++)
buf[i] = DEC2BCD(buf[i]);
return i; buf[5] |= 0x80; /* chip wants century (always 20xx) */
rc = sw_i2c_write(RTC_ADDR, 0, buf, sizeof(buf));
return rc;
} }

View file

@ -27,6 +27,9 @@
#include "i2c-pp.h" #include "i2c-pp.h"
#include <stdbool.h> #include <stdbool.h>
/*RTC_E8564's slave address is 0x51*/
#define RTC_ADDR 0x51
/* RTC registers */ /* RTC registers */
#define RTC_CTRL1 0x00 #define RTC_CTRL1 0x00
#define RTC_CTRL2 0x01 #define RTC_CTRL2 0x01
@ -59,94 +62,96 @@ void rtc_init(void)
/* initialize Control 1 register */ /* initialize Control 1 register */
tmp = 0; tmp = 0;
pp_i2c_send(0x51, RTC_CTRL1,tmp); pp_i2c_send(RTC_ADDR, RTC_CTRL1, tmp);
/* read value of the Control 2 register - we'll need it to preserve alarm and timer interrupt assertion flags */ /* read value of the Control 2 register - we'll need it to preserve alarm and timer interrupt assertion flags */
rv = i2c_readbytes(0x51,RTC_CTRL2,1,&tmp); rv = i2c_readbytes(RTC_ADDR, RTC_CTRL2, 1, &tmp);
/* preserve alarm and timer interrupt flags */ /* preserve alarm and timer interrupt flags */
tmp &= (RTC_TF | RTC_AF | RTC_TIE | RTC_AIE); tmp &= (RTC_TF | RTC_AF | RTC_TIE | RTC_AIE);
pp_i2c_send(0x51, RTC_CTRL2,tmp); pp_i2c_send(RTC_ADDR, RTC_CTRL2, tmp);
} }
int rtc_read_datetime(unsigned char* buf) int rtc_read_datetime(struct tm *tm)
{ {
unsigned char tmp;
int read; int read;
unsigned char buf[7];
/*RTC_E8564's slave address is 0x51*/
read = i2c_readbytes(0x51,0x02,7,buf); read = i2c_readbytes(RTC_ADDR, 0x02, sizeof(buf), buf);
/* convert from bcd, avoid getting extra bits */
tm->tm_sec = BCD2DEC(buf[0] & 0x7f);
tm->tm_min = BCD2DEC(buf[1] & 0x7f);
tm->tm_hour = BCD2DEC(buf[2] & 0x3f);
tm->tm_mday = BCD2DEC(buf[3] & 0x3f);
tm->tm_wday = BCD2DEC(buf[4] & 0x3);
tm->tm_mon = BCD2DEC(buf[5] & 0x1f) - 1;
tm->tm_year = BCD2DEC(buf[6]) + 100;
/* swap wday and mday to be compatible with
* get_time() from firmware/common/timefuncs.c */
tmp=buf[3];
buf[3]=buf[4];
buf[4]=tmp;
return read; return read;
} }
int rtc_write_datetime(unsigned char* buf) int rtc_write_datetime(const struct tm *tm)
{ {
int i; unsigned int i;
unsigned char tmp; unsigned char buf[7];
/* swap wday and mday to be compatible with buf[0] = tm->tm_sec;
* set_time() in firmware/common/timefuncs.c */ buf[1] = tm->tm_min;
tmp=buf[3]; buf[2] = tm->tm_hour;
buf[3]=buf[4]; buf[3] = tm->tm_mday;
buf[4]=tmp; buf[4] = tm->tm_wday;
buf[5] = tm->tm_mon + 1;
buf[6] = tm->tm_year - 100;
for (i = 0; i < sizeof(buf); i++)
pp_i2c_send(RTC_ADDR, 0x02 + i, DEC2BCD(buf[i]));
for (i=0;i<7;i++){
pp_i2c_send(0x51, 0x02+i,buf[i]);
}
return 1; return 1;
} }
void rtc_set_alarm(int h, int m) void rtc_set_alarm(int h, int m)
{ {
unsigned char buf[4]={0}; unsigned char buf[4] = {0};
int rv=0; int i, rv;
int i=0;
/* clear alarm interrupt */ /* clear alarm interrupt */
rv = i2c_readbytes(0x51,RTC_CTRL2,1,buf); rv = i2c_readbytes(RTC_ADDR, RTC_CTRL2, 1, buf);
buf[0] &= RTC_AF; buf[0] &= RTC_AF;
pp_i2c_send(0x51, RTC_CTRL2,buf[0]); pp_i2c_send(RTC_ADDR, RTC_CTRL2, buf[0]);
/* prepare new alarm */ /* prepare new alarm */
if( m >= 0 ) if( m >= 0 )
buf[0] = (((m/10) << 4) | m%10); buf[0] = DEC2BCD(m);
else else
/* ignore minutes comparison query */ /* ignore minutes comparison query */
buf[0] = RTC_AE; buf[0] = RTC_AE;
if( h >= 0 ) if( h >= 0 )
buf[1] = (((h/10) << 4) | h%10); buf[1] = DEC2BCD(h);
else else
/* ignore hours comparison query */ /* ignore hours comparison query */
buf[1] = RTC_AE; buf[1] = RTC_AE;
/* ignore day and wday */ /* ignore day and wday */
buf[2] = RTC_AE; buf[2] = RTC_AE;
buf[3] = RTC_AE; buf[3] = RTC_AE;
/* write new alarm */ /* write new alarm */
for(;i<4;i++) for(i = 0; i < 4; i++)
pp_i2c_send(0x51, RTC_ALARM_MINUTES+i,buf[i]); pp_i2c_send(RTC_ADDR, RTC_ALARM_MINUTES + i, buf[i]);
/* note: alarm is not enabled at the point */ /* note: alarm is not enabled at the point */
} }
void rtc_get_alarm(int *h, int *m) void rtc_get_alarm(int *h, int *m)
{ {
unsigned char buf[4]={0}; unsigned char buf[4]={0};
/* get alarm preset */ /* get alarm preset */
i2c_readbytes(0x51, RTC_ALARM_MINUTES,4,buf); i2c_readbytes(RTC_ADDR, RTC_ALARM_MINUTES, 4 ,buf);
*m = ((buf[0] >> 4) & 0x7)*10 + (buf[0] & 0x0f);
*h = ((buf[1] >> 4) & 0x3)*10 + (buf[1] & 0x0f);
*m = BCD2DEC(buf[0] & 0x7f);
*h = BCD2DEC(buf[0] & 0x3f);
} }
bool rtc_enable_alarm(bool enable) bool rtc_enable_alarm(bool enable)
@ -157,10 +162,10 @@ bool rtc_enable_alarm(bool enable)
if(enable) if(enable)
{ {
/* enable alarm interrupt */ /* enable alarm interrupt */
rv = i2c_readbytes(0x51,RTC_CTRL2,1,&tmp); rv = i2c_readbytes(RTC_ADDR, RTC_CTRL2, 1, &tmp);
tmp |= RTC_AIE; tmp |= RTC_AIE;
tmp &= ~RTC_AF; tmp &= ~RTC_AF;
pp_i2c_send(0x51, RTC_CTRL2,tmp); pp_i2c_send(RTC_ADDR, RTC_CTRL2, tmp);
} }
else else
{ {
@ -168,9 +173,9 @@ bool rtc_enable_alarm(bool enable)
if(rtc_lock_alarm_clear) if(rtc_lock_alarm_clear)
/* lock disabling alarm before it was checked whether or not the unit was started by RTC alarm */ /* lock disabling alarm before it was checked whether or not the unit was started by RTC alarm */
return false; return false;
rv = i2c_readbytes(0x51,RTC_CTRL2,1,&tmp); rv = i2c_readbytes(RTC_ADDR, RTC_CTRL2, 1, &tmp);
tmp &= ~(RTC_AIE | RTC_AF); tmp &= ~(RTC_AIE | RTC_AF);
pp_i2c_send(0x51, RTC_CTRL2,tmp); pp_i2c_send(RTC_ADDR, RTC_CTRL2, tmp);
} }
return false; return false;
@ -186,21 +191,21 @@ bool rtc_check_alarm_started(bool release_alarm)
if (run_before) if (run_before)
{ {
started = alarm_state; started = alarm_state;
alarm_state &= ~release_alarm; alarm_state &= ~release_alarm;
} }
else else
{ {
/* read Control 2 register which contains alarm flag */ /* read Control 2 register which contains alarm flag */
rv = i2c_readbytes(0x51,RTC_CTRL2,1,&tmp); rv = i2c_readbytes(RTC_ADDR, RTC_CTRL2, 1, &tmp);
alarm_state = started = ( (tmp & RTC_AF) && (tmp & RTC_AIE) ); alarm_state = started = ( (tmp & RTC_AF) && (tmp & RTC_AIE) );
if(release_alarm && started) if(release_alarm && started)
{ {
rv = i2c_readbytes(0x51,RTC_CTRL2,1,&tmp); rv = i2c_readbytes(RTC_ADDR, RTC_CTRL2, 1, &tmp);
/* clear alarm interrupt enable and alarm flag */ /* clear alarm interrupt enable and alarm flag */
tmp &= ~(RTC_AF | RTC_AIE); tmp &= ~(RTC_AF | RTC_AIE);
pp_i2c_send(0x51, RTC_CTRL2,tmp); pp_i2c_send(RTC_ADDR, RTC_CTRL2, tmp);
} }
run_before = true; run_before = true;
rtc_lock_alarm_clear = false; rtc_lock_alarm_clear = false;
@ -215,7 +220,8 @@ bool rtc_check_alarm_flag(void)
int rv=0; int rv=0;
/* read Control 2 register which contains alarm flag */ /* read Control 2 register which contains alarm flag */
rv = i2c_readbytes(0x51,RTC_CTRL2,1,&tmp); rv = i2c_readbytes(RTC_ADDR, RTC_CTRL2, 1, &tmp);
return (tmp & RTC_AF); return (tmp & RTC_AF);
} }

View file

@ -116,11 +116,10 @@ static void jz_gettime(unsigned int rtc, int *year, int *mon, int *day,
*year += 2000; *year += 2000;
} }
int rtc_read_datetime(unsigned char* buf) int rtc_read_datetime(struct tm *tm)
{ {
struct tm rtc_tm;
unsigned int sec,mon,mday,wday,year,hour,min; unsigned int sec,mon,mday,wday,year,hour,min;
/* /*
* Only the values that we read from the RTC are set. We leave * Only the values that we read from the RTC are set. We leave
* tm_wday, tm_yday and tm_isdst untouched. Even though the * tm_wday, tm_yday and tm_isdst untouched. Even though the
@ -131,37 +130,32 @@ int rtc_read_datetime(unsigned char* buf)
year -= 2000; year -= 2000;
rtc_tm.tm_sec = sec; tm->tm_sec = sec;
rtc_tm.tm_min = min; tm->tm_min = min;
rtc_tm.tm_hour = hour; tm->tm_hour = hour;
rtc_tm.tm_mday = mday; tm->tm_mday = mday;
rtc_tm.tm_wday = wday; tm->tm_wday = wday;
/* Don't use centry, but start from year 1970 */ /* Don't use centry, but start from year 1970 */
rtc_tm.tm_mon = mon; tm->tm_mon = mon;
if (year <= 69) if (year <= 69)
year += 100; year += 100;
rtc_tm.tm_year = year; tm->tm_year = year;
rtc_tm.tm_yday = 0; /* Not implemented for now */
rtc_tm.tm_isdst = -1; /* Not implemented for now */
(*((struct tm*)buf)) = rtc_tm;
return 1; return 1;
} }
int rtc_write_datetime(unsigned char* buf) int rtc_write_datetime(const struct tm *tm)
{ {
struct tm *rtc_tm = (struct tm*)buf;
unsigned int year, lval; unsigned int year, lval;
year = rtc_tm->tm_year; year = tm->tm_year;
/* Don't use centry, but start from year 1970 */ /* Don't use centry, but start from year 1970 */
if (year > 69) if (year > 69)
year -= 100; year -= 100;
year += 2000; year += 2000;
lval = jz_mktime(year, rtc_tm->tm_mon, rtc_tm->tm_mday, rtc_tm->tm_hour, lval = jz_mktime(year, tm->tm_mon, tm->tm_mday, tm->tm_hour,
rtc_tm->tm_min, rtc_tm->tm_sec); tm->tm_min, tm->tm_sec);
__cpm_start_rtc(); __cpm_start_rtc();
udelay(100); udelay(100);

View file

@ -110,10 +110,10 @@ void rtc_set_alarm(int h, int m)
/* for daily alarm, RPT5=RPT4=on, RPT1=RPT2=RPT3=off */ /* for daily alarm, RPT5=RPT4=on, RPT1=RPT2=RPT3=off */
rtc_write(0x0e, 0x00); /* seconds 0 and RTP1 */ rtc_write(0x0e, 0x00); /* seconds 0 and RTP1 */
rtc_write(0x0d, ((m / 10) << 4) | (m % 10)); /* minutes and RPT2 */ rtc_write(0x0d, DEC2BCD(m); /* minutes and RPT2 */
rtc_write(0x0c, ((h / 10) << 4) | (h % 10)); /* hour and RPT3 */ rtc_write(0x0c, DEC2BCD(h); /* hour and RPT3 */
rtc_write(0x0b, 0xc1); /* set date 01 and RPT4 and RTP5 */ rtc_write(0x0b, 0xc1); /* set date 01 and RPT4 and RTP5 */
/* set month to 1, if it's invalid, the rtc does an alarm every second instead */ /* set month to 1, if it's invalid, the rtc does an alarm every second instead */
data = rtc_read(0x0a); data = rtc_read(0x0a);
@ -128,10 +128,10 @@ void rtc_get_alarm(int *h, int *m)
unsigned char data; unsigned char data;
data = rtc_read(0x0c); data = rtc_read(0x0c);
*h = ((data & 0x30) >> 4) * 10 + (data & 0x0f); *h = BCD2DEC(data & 0x3f);
data = rtc_read(0x0d); data = rtc_read(0x0d);
*m = ((data & 0x70) >> 4) * 10 + (data & 0x0f); *m = BCD2DEC(data & 0x7f);
} }
/* turn alarm on or off by setting the alarm flag enable */ /* turn alarm on or off by setting the alarm flag enable */
@ -250,31 +250,53 @@ int rtc_read_multiple(unsigned char address, unsigned char *buf, int numbytes)
return ret; return ret;
} }
int rtc_read_datetime(unsigned char* buf) { int rtc_read_datetime(struct tm *tm)
{
int rc; int rc;
unsigned char buf[7];
rc = rtc_read_multiple(1, buf, 7); rc = rtc_read_multiple(1, buf, sizeof(buf));
/* convert from bcd, avoid getting extra bits */
tm->tm_sec = BCD2DEC(buf[0] & 0x7f);
tm->tm_min = BCD2DEC(buf[1] & 0x7f);
tm->tm_hour = BCD2DEC(buf[2] & 0x3f);
tm->tm_wday = BCD2DEC(buf[3] & 0x3);
tm->tm_mday = BCD2DEC(buf[4] & 0x3f);
tm->tm_mon = BCD2DEC(buf[5] & 0x1f) - 1;
tm->tm_year = BCD2DEC(buf[6]) + 100;
/* Adjust weekday */ /* Adjust weekday */
if(buf[3] == 7) if (tm->tm_wday == 7)
buf[3]=0; tm->tm_wday = 0;
return rc; return rc;
} }
int rtc_write_datetime(unsigned char* buf) { int rtc_write_datetime(const struct tm *tm)
int i; {
unsigned int i;
int rc = 0; int rc = 0;
unsigned char buf[7];
buf[0] = tm->tm_sec;
buf[1] = tm->tm_min;
buf[2] = tm->tm_hour;
buf[3] = tm->tm_wday;
buf[4] = tm->tm_mday;
buf[5] = tm->tm_mon + 1;
buf[6] = tm->tm_year - 100;
/* Adjust weekday */ /* Adjust weekday */
if(buf[3] == 0) if (buf[3] == 0)
buf[3] = 7; buf[3] = 7;
for (i = 0; i < 7 ; i++) for (i = 0; i < sizeof(buf) ;i++)
{ {
rc |= rtc_write(i+1, buf[i]); rc |= rtc_write(i + 1, DEC2BCD(buf[i]));
} }
rc |= rtc_write(8, 0x80); /* Out=1, calibration = 0 */ rc |= rtc_write(8, 0x80); /* Out=1, calibration = 0 */
return rc; return rc;
} }

View file

@ -46,18 +46,6 @@
#define RTC_BASE_YEAR 1970 #define RTC_BASE_YEAR 1970
#endif #endif
enum rtc_buffer_field_indexes
{
RTC_I_SECONDS = 0,
RTC_I_MINUTES,
RTC_I_HOURS,
RTC_I_WEEKDAY,
RTC_I_DAY,
RTC_I_MONTH,
RTC_I_YEAR,
RTC_NUM_FIELDS,
};
enum rtc_registers_indexes enum rtc_registers_indexes
{ {
RTC_REG_TIME = 0, RTC_REG_TIME = 0,
@ -82,26 +70,6 @@ static const unsigned char month_table[2][12] =
{ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
}; };
static inline void to_bcd(unsigned char *bcd, const unsigned char *buf,
int len)
{
while (len-- > 0)
{
unsigned char d = *buf++;
*bcd++ = ((d / 10) << 4) | (d % 10);
}
}
static inline void from_bcd(unsigned char *buf, const unsigned char *bcd,
int len)
{
while (len-- > 0)
{
unsigned char d = *bcd++;
*buf++ = ((d >> 4) & 0x0f) * 10 + (d & 0xf);
}
}
/* Get number of leaps since the reference date of 1601/01/01 */ /* Get number of leaps since the reference date of 1601/01/01 */
static int get_leap_count(int d) static int get_leap_count(int d)
{ {
@ -127,10 +95,10 @@ void rtc_init(void)
} }
} }
int rtc_read_datetime(unsigned char* buf) int rtc_read_datetime(struct tm *tm)
{ {
uint32_t regs[RTC_NUM_REGS]; uint32_t regs[RTC_NUM_REGS];
int year, leap, month, day; int year, leap, month, day, hour, min;
/* Read time, day, time - 2nd read of time should be the same or /* Read time, day, time - 2nd read of time should be the same or
* greater */ * greater */
@ -147,19 +115,21 @@ int rtc_read_datetime(unsigned char* buf)
while (regs[RTC_REG_TIME2] < regs[RTC_REG_TIME]); while (regs[RTC_REG_TIME2] < regs[RTC_REG_TIME]);
/* TOD: = 0 to 86399 */ /* TOD: = 0 to 86399 */
buf[RTC_I_HOURS] = regs[RTC_REG_TIME] / 3600; hour = regs[RTC_REG_TIME] / 3600;
regs[RTC_REG_TIME] -= buf[RTC_I_HOURS]*3600; regs[RTC_REG_TIME] -= hour*3600;
tm->tm_hour = hour;
buf[RTC_I_MINUTES] = regs[RTC_REG_TIME] / 60; min = regs[RTC_REG_TIME] / 60;
regs[RTC_REG_TIME] -= buf[RTC_I_MINUTES]*60; regs[RTC_REG_TIME] -= min*60;
tm->tm_min = min;
buf[RTC_I_SECONDS] = regs[RTC_REG_TIME]; tm->tm_sec = regs[RTC_REG_TIME];
/* DAY: 0 to 32767 */ /* DAY: 0 to 32767 */
day = regs[RTC_REG_DAY] + RTC_BASE_DAY_COUNT; day = regs[RTC_REG_DAY] + RTC_BASE_DAY_COUNT;
/* Weekday */ /* Weekday */
buf[RTC_I_WEEKDAY] = (day + 1) % 7; /* 1601/01/01 = Monday */ tm->tm_wday = (day + 1) % 7; /* 1601/01/01 = Monday */
/* Get number of leaps for today */ /* Get number of leaps for today */
leap = get_leap_count(day); leap = get_leap_count(day);
@ -186,28 +156,23 @@ int rtc_read_datetime(unsigned char* buf)
day -= days; day -= days;
} }
buf[RTC_I_DAY] = day + 1; /* 1 to 31 */ tm->tm_mday = day + 1; /* 1 to 31 */
buf[RTC_I_MONTH] = month + 1; /* 1 to 12 */ tm->tm_mon = month; /* 0 to 11 */
buf[RTC_I_YEAR] = year % 100; tm->tm_year = year % 100 + 100;
to_bcd(buf, buf, RTC_NUM_FIELDS);
return 7; return 7;
} }
int rtc_write_datetime(unsigned char* buf) int rtc_write_datetime(const struct tm *tm)
{ {
uint32_t regs[2]; uint32_t regs[2];
unsigned char fld[RTC_NUM_FIELDS];
int year, leap, month, day, i, base_yearday; int year, leap, month, day, i, base_yearday;
from_bcd(fld, buf, RTC_NUM_FIELDS); regs[RTC_REG_TIME] = tm->tm_sec +
tm->tm_min*60 +
tm->tm_hour*3600;
regs[RTC_REG_TIME] = fld[RTC_I_SECONDS] + year = tm->tm_year - 100;
fld[RTC_I_MINUTES]*60 +
fld[RTC_I_HOURS]*3600;
year = fld[RTC_I_YEAR];
if (year < RTC_BASE_YEAR - 1900) if (year < RTC_BASE_YEAR - 1900)
year += 2000; year += 2000;
@ -230,18 +195,18 @@ int rtc_write_datetime(unsigned char* buf)
/* Find the number of days passed this year up to the 1st of the /* Find the number of days passed this year up to the 1st of the
* month. */ * month. */
leap = is_leap_year(year); leap = is_leap_year(year);
month = fld[RTC_I_MONTH] - 1; month = tm->tm_mon;
for (i = 0; i < month; i++) for (i = 0; i < month; i++)
{ {
day += month_table[leap][i]; day += month_table[leap][i];
} }
regs[RTC_REG_DAY] = day + fld[RTC_I_DAY] - 1 - base_yearday; regs[RTC_REG_DAY] = day + tm->tm_mday - 1 - base_yearday;
if (mc13783_write_regset(rtc_registers, regs, 2) == 2) if (mc13783_write_regset(rtc_registers, regs, 2) == 2)
{ {
return RTC_NUM_FIELDS; return 7;
} }
return 0; return 0;

View file

@ -124,31 +124,49 @@ void rtc_init(void)
} }
int rtc_read_datetime(unsigned char* buf) int rtc_read_datetime(struct tm *tm)
{ {
int i; unsigned int i;
unsigned char v[7]; int rc;
unsigned char buf[7];
i = sw_i2c(SW_I2C_READ, RTC_CMD_DATA, v, 7); rc = sw_i2c(SW_I2C_READ, RTC_CMD_DATA, buf, sizeof(buf));
v[4] &= 0x3f; /* mask out p.m. flag */ buf[4] &= 0x3f; /* mask out p.m. flag */
for(i=0; i<7; i++) for (i = 0; i < sizeof(buf); i++)
buf[i] = v[6-i]; buf[i] = BCD2DEC(buf[i]);
return i; tm->tm_sec = buf[6];
tm->tm_min = buf[5];
tm->tm_hour = buf[4];
tm->tm_wday = buf[3];
tm->tm_mday = buf[2];
tm->tm_mon = buf[1] - 1;
tm->tm_year = buf[0] + 100;
return rc;
} }
int rtc_write_datetime(unsigned char* buf) int rtc_write_datetime(const struct tm *tm)
{ {
int i; unsigned int i;
unsigned char v[7]; int rc;
unsigned char buf[7];
for(i=0; i<7; i++) buf[6] = tm->tm_sec;
v[i]=buf[6-i]; buf[5] = tm->tm_min;
buf[4] = tm->tm_hour;
i = sw_i2c(SW_I2C_WRITE, RTC_CMD_DATA, v, 7); buf[3] = tm->tm_wday;
buf[2] = tm->tm_mday;
return i; buf[1] = tm->tm_mon + 1;
buf[0] = tm->tm_year - 100;
for (i = 0; i < sizeof(buf); i++)
buf[i] = DEC2BCD(buf[i]);
rc = sw_i2c(SW_I2C_WRITE, RTC_CMD_DATA, buf, sizeof(buf));
return rc;
} }

View file

@ -36,14 +36,45 @@ void rtc_init(void)
rtc_check_alarm_started(false); rtc_check_alarm_started(false);
} }
int rtc_read_datetime(unsigned char* buf) int rtc_read_datetime(struct tm *tm)
{ {
return pcf50605_read_multiple(0x0a, buf, 7); unsigned int i;
int rc;
unsigned char buf[7];
rc = pcf50605_read_multiple(0x0a, buf, sizeof(buf));
for (i = 0; i < sizeof(buf); i++)
buf[i] = BCD2DEC(buf[i]);
tm->tm_sec = buf[0];
tm->tm_min = buf[1];
tm->tm_hour = buf[2];
tm->tm_wday = buf[3];
tm->tm_mday = buf[4];
tm->tm_mon = buf[5] - 1;
tm->tm_year = buf[6] + 100;
return rc;
} }
int rtc_write_datetime(unsigned char* buf) int rtc_write_datetime(const struct tm *tm)
{ {
pcf50605_write_multiple(0x0a, buf, 7); unsigned int i;
unsigned char buf[7];
buf[0] = tm->tm_sec;
buf[1] = tm->tm_min;
buf[2] = tm->tm_hour;
buf[3] = tm->tm_wday;
buf[4] = tm->tm_mday;
buf[5] = tm->tm_mon + 1;
buf[6] = tm->tm_year - 100;
for (i = 0; i < sizeof(buf); i++)
buf[i] = DEC2BCD(buf[i]);
pcf50605_write_multiple(0x0a, buf, sizeof(buf));
return 1; return 1;
} }
@ -121,17 +152,17 @@ void rtc_set_alarm(int h, int m)
/* Set us to wake at the first second of the specified time */ /* Set us to wake at the first second of the specified time */
pcf50605_write(0x11, 0); pcf50605_write(0x11, 0);
/* Convert to BCD */ /* Convert to BCD */
pcf50605_write(0x12, ((m/10) << 4) | m%10); pcf50605_write(0x12, DEC2BCD(m));
pcf50605_write(0x13, ((h/10) << 4) | h%10); pcf50605_write(0x13, DEC2BCD(h));
} }
void rtc_get_alarm(int *h, int *m) void rtc_get_alarm(int *h, int *m)
{ {
char buf[2]; char buf[2];
pcf50605_read_multiple(0x12, buf, 2); pcf50605_read_multiple(0x12, buf, sizeof(buf));
/* Convert from BCD */ /* Convert from BCD */
*m = ((buf[0] >> 4) & 0x7)*10 + (buf[0] & 0x0f); *m = BCD2DEC(buf[0]);
*h = ((buf[1] >> 4) & 0x3)*10 + (buf[1] & 0x0f); *h = BCD2DEC(buf[1]);
} }

View file

@ -24,27 +24,70 @@
#include "kernel.h" #include "kernel.h"
#include "system.h" #include "system.h"
#include "pcf50606.h" #include "pcf50606.h"
#include <stdbool.h>
void rtc_init(void) void rtc_init(void)
{ {
} }
int rtc_read_datetime(unsigned char* buf) { int rtc_read_datetime(struct tm *tm)
int rc; {
int oldlevel = disable_irq_save(); unsigned int i;
int rc, oldlevel;
rc = pcf50606_read_multiple(0x0a, buf, 7); unsigned char buf[7];
oldlevel = disable_irq_save();
rc = pcf50606_read_multiple(0x0a, buf, sizeof(buf));
restore_irq(oldlevel); restore_irq(oldlevel);
for (i = 0; i < sizeof(buf); i++)
buf[i] = BCD2DEC(buf[i]);
tm->tm_sec = buf[0];
tm->tm_min = buf[1];
tm->tm_hour = buf[2];
tm->tm_wday = buf[3];
tm->tm_mday = buf[4];
tm->tm_mon = buf[5] - 1;
#ifdef IRIVER_H300_SERIES
/* Special kludge to coexist with the iriver firmware. The iriver firmware
stores the date as 1965+nn, and allows a range of 1980..2064. We use
1964+nn here to make leap years work correctly, so the date will be one
year off in the iriver firmware but at least won't be reset anymore. */
tm->tm_year = buf[6] + 64;
#else /* Not IRIVER_H300_SERIES */
tm->tm_year = buf[6] + 100;
#endif /* IRIVER_H300_SERIES */
return rc; return rc;
} }
int rtc_write_datetime(unsigned char* buf) { int rtc_write_datetime(const struct tm *tm)
int rc; {
int oldlevel = disable_irq_save(); unsigned int i;
int rc, oldlevel;
rc = pcf50606_write_multiple(0x0a, buf, 7); unsigned char buf[7];
buf[0] = tm->tm_sec;
buf[1] = tm->tm_min;
buf[2] = tm->tm_hour;
buf[3] = tm->tm_wday;
buf[4] = tm->tm_mday;
buf[5] = tm->tm_mon + 1;
#ifdef IRIVER_H300_SERIES
/* Iriver firmware compatibility kludge, see rtc_read_datetime(). */
buf[6] = tm->tm_year - 64;
#else /* Not IRIVER_H300_SERIES */
buf[6] = tm->tm_year - 100;
#endif /* IRIVER_H300_SERIES */
for (i = 0; i < sizeof(buf); i++)
buf[i] = DEC2BCD(buf[i]);
oldlevel = disable_irq_save();
rc = pcf50606_write_multiple(0x0a, buf, sizeof(buf));
restore_irq(oldlevel); restore_irq(oldlevel);

View file

@ -22,31 +22,60 @@
#include "config.h" #include "config.h"
#include "spi.h" #include "spi.h"
#include "rtc.h" #include "rtc.h"
#include <stdbool.h>
/* Choose one of: */ /* Choose one of: */
#define ADDR_READ 0x04 #define ADDR_READ 0x04
#define ADDR_WRITE 0x00 #define ADDR_WRITE 0x00
/* and one of: */ /* and one of: */
#define ADDR_ONE 0x08 #define ADDR_ONE 0x08
#define ADDR_BURST 0x00 #define ADDR_BURST 0x00
void rtc_init(void) void rtc_init(void)
{ {
} }
int rtc_read_datetime(unsigned char* buf) int rtc_read_datetime(struct tm *tm)
{ {
unsigned int i;
unsigned char buf[7];
char command = ADDR_READ|ADDR_BURST; /* burst read from the start of the time/date reg */ char command = ADDR_READ|ADDR_BURST; /* burst read from the start of the time/date reg */
spi_block_transfer(SPI_target_RX5X348AB, &command, 1, buf, 7);
spi_block_transfer(SPI_target_RX5X348AB, &command, 1, buf, sizeof(buf));
for (i = 0; i < sizeof(buf); i++)
buf[i] = BCD2DEC(buf[i]);
tm->tm_sec = buf[0];
tm->tm_min = buf[1];
tm->tm_hour = buf[2];
tm->tm_wday = buf[3];
tm->tm_mday = buf[4];
tm->tm_mon = buf[5] - 1;
tm->tm_year = buf[6] + 100;
return 1; return 1;
} }
int rtc_write_datetime(unsigned char* buf)
int rtc_write_datetime(const struct tm *tm)
{ {
unsigned int i;
char command = ADDR_WRITE|ADDR_BURST; /* burst read from the start of the time/date reg */ char command = ADDR_WRITE|ADDR_BURST; /* burst read from the start of the time/date reg */
char data[8]; unsigned char buf[8];
int i;
data[0] = command; buf[0] = command;
for (i=1;i<8;i++) buf[1] = tm->tm_sec;
data[i] = buf[i-1]; buf[2] = tm->tm_min;
spi_block_transfer(SPI_target_RX5X348AB, data, 8, NULL, 0); buf[3] = tm->tm_hour;
buf[4] = tm->tm_wday;
buf[5] = tm->tm_mday;
buf[6] = tm->tm_mon + 1;
buf[7] = tm->tm_year - 100;
/* don't encode the comand byte */
for (i = 1; i < sizeof(buf); i++)
buf[i] = DEC2BCD(buf[i]);
spi_block_transfer(SPI_target_RX5X348AB, buf, sizeof(buf), NULL, 0);
return 1; return 1;
} }

View file

@ -58,35 +58,49 @@ void rtc_init(void)
{ {
} }
int rtc_read_datetime(unsigned char* buf) int rtc_read_datetime(struct tm *tm)
{ {
unsigned char data[7]; unsigned char buf[7];
int i, ret; int i, ret;
ret = i2c_read(RTC_ADDR | (REALTIME_DATA1 << 1), -1, sizeof(data), data); ret = i2c_read(RTC_ADDR | (REALTIME_DATA1 << 1), -1, sizeof(buf), buf);
reverse_bits(data, sizeof(data)); reverse_bits(buf, sizeof(buf));
buf[4] &= 0x3f; /* mask out p.m. flag */ buf[4] &= 0x3f; /* mask out p.m. flag */
for (i = 0; i < 7; i++) { for (i = 0; i < sizeof(buf); i++)
buf[i] = data[6 - i]; BCD2DEC(buf[i]);
}
tm->tm_sec = buf[6];
tm->tm_min = buf[5];
tm->tm_hour = buf[4];
tm->tm_wday = buf[3];
tm->tm_mday = buf[2];
tm->tm_mon = buf[1] - 1;
tm->tm_year = buf[0] + 100;
return ret; return ret;
} }
int rtc_write_datetime(unsigned char* buf) int rtc_write_datetime(const struct tm *tm)
{ {
unsigned char data[7]; unsigned char buf[7];
int i, ret; int i, ret;
for (i = 0; i < 7; i++) { buf[6] = tm->tm_sec;
data[i] = buf[6 - i]; buf[5] = tm->tm_min;
} buf[4] = tm->tm_hour;
buf[3] = tm->tm_wday;
reverse_bits(data, sizeof(data)); buf[2] = tm->tm_mday;
ret = i2c_write(RTC_ADDR | (REALTIME_DATA1 << 1), -1, sizeof(data), data); buf[1] = tm->tm_mon + 1;
buf[0] = tm->tm_year - 100;
for (i = 0; i < sizeof(buf); i++)
DEC2BCD(buf[i]);
reverse_bits(buf, sizeof(buf));
ret = i2c_write(RTC_ADDR | (REALTIME_DATA1 << 1), -1, sizeof(buf), buf);
return ret; return ret;
} }

View file

@ -30,28 +30,28 @@ void rtc_init(void)
RTCCON |= 1; RTCCON |= 1;
} }
int rtc_read_datetime(unsigned char* buf) int rtc_read_datetime(struct tm *tm)
{ {
buf[0] = BCDSEC; tm->tm_sec = BCD2DEC(BCDSEC);
buf[1] = BCDMIN; tm->tm_min = BCD2DEC(BCDMIN);
buf[2] = BCDHOUR; tm->tm_hour = BCD2DEC(BCDHOUR);
buf[3] = BCDDAY-1; /* timefuncs wants 0..6 for wday */ tm->tm_wday = BCD2DEC(BCDDAY) - 1; /* timefuncs wants 0..6 for wday */
buf[4] = BCDDATE; tm->tm_mday = BCD2DEC(BCDDATE);
buf[5] = BCDMON; tm->tm_mon = BCD2DEC(BCDMON) - 1;
buf[6] = BCDYEAR; tm->tm_year = BCD2DEC(BCDYEAR) + 100;
return 1; return 1;
} }
int rtc_write_datetime(unsigned char* buf) int rtc_write_datetime(const struct tm *tm)
{ {
BCDSEC = buf[0]; BCDSEC = DEC2BCD(tm->tm_sec);
BCDMIN = buf[1]; BCDMIN = DEC2BCD(tm->tm_min);
BCDHOUR = buf[2]; BCDHOUR = DEC2BCD(tm->tm_hour);
BCDDAY = buf[3]+1; /* chip wants 1..7 for wday */ BCDDAY = DEC2BCD(tm->tm_wday) + 1; /* chip wants 1..7 for wday */
BCDDATE = buf[4]; BCDDATE = DEC2BCD(tm->tm_mday);
BCDMON = buf[5]; BCDMON = DEC2BCD(tm->tm_mon + 1);
BCDYEAR = buf[6]; BCDYEAR = DEC2BCD(tm->tm_year - 100);
return 1; return 1;
} }
@ -88,15 +88,15 @@ bool rtc_check_alarm_flag(void)
/* set alarm time registers to the given time (repeat once per day) */ /* set alarm time registers to the given time (repeat once per day) */
void rtc_set_alarm(int h, int m) void rtc_set_alarm(int h, int m)
{ {
ALMMIN=(((m / 10) << 4) | (m % 10)) & 0x7f; /* minutes */ ALMMIN = DEC2BCD(m); /* minutes */
ALMHOUR=(((h / 10) << 4) | (h % 10)) & 0x3f; /* hour */ ALMHOUR = DEC2BCD(h); /* hour */
} }
/* read out the current alarm time */ /* read out the current alarm time */
void rtc_get_alarm(int *h, int *m) void rtc_get_alarm(int *h, int *m)
{ {
*m=((ALMMIN & 0x70) >> 4) * 10 + (ALMMIN & 0x0f); *m = BCD2DEC(ALMMIN);
*h=((ALMHOUR & 0x30) >> 4) * 10 + (ALMHOUR & 0x0f); *h = BCD2DEC(ALMHOUR);
} }
/* turn alarm on or off by setting the alarm flag enable /* turn alarm on or off by setting the alarm flag enable

View file

@ -24,13 +24,19 @@
#include <stdbool.h> #include <stdbool.h>
#include "system.h" #include "system.h"
#include "config.h" #include "config.h"
#include "time.h"
/* Macros used to convert to and from BCD, used in various rtc drivers
this is the wrong place but misc.h is in apps... */
#define BCD2DEC(X) (((((X)>>4) & 0x0f) * 10) + ((X) & 0xf))
#define DEC2BCD(X) ((((X)/10)<<4) | ((X)%10))
#if CONFIG_RTC #if CONFIG_RTC
/* Common functions for all targets */ /* Common functions for all targets */
void rtc_init(void); void rtc_init(void);
int rtc_read_datetime(unsigned char* buf); int rtc_read_datetime(struct tm *tm);
int rtc_write_datetime(unsigned char* buf); int rtc_write_datetime(const struct tm *tm);
#if CONFIG_RTC == RTC_M41ST84W #if CONFIG_RTC == RTC_M41ST84W
@ -53,3 +59,4 @@ bool rtc_check_alarm_flag(void);
#endif /* CONFIG_RTC */ #endif /* CONFIG_RTC */
#endif #endif

View file

@ -35,3 +35,4 @@ time_t mktime(struct tm *t);
#endif #endif
#endif /* _TIMEFUNCS_H_ */ #endif /* _TIMEFUNCS_H_ */

View file

@ -142,25 +142,17 @@ int rtc_write(int address, int value)
return 0; return 0;
} }
int rtc_read_datetime(unsigned char* buf) int rtc_read_datetime(struct tm *tm)
{ {
time_t now = time(NULL); time_t now = time(NULL);
struct tm *teem = localtime(&now); *tm = *localtime(&now);
buf[0] = (teem->tm_sec%10) | ((teem->tm_sec/10) << 4);
buf[1] = (teem->tm_min%10) | ((teem->tm_min/10) << 4);
buf[2] = (teem->tm_hour%10) | ((teem->tm_hour/10) << 4);
buf[3] = (teem->tm_wday);
buf[4] = (teem->tm_mday%10) | ((teem->tm_mday/10) << 4);
buf[5] = ((teem->tm_year-100)%10) | (((teem->tm_year-100)/10) << 4);
buf[6] = ((teem->tm_mon+1)%10) | (((teem->tm_mon+1)/10) << 4);
return 0; return 0;
} }
int rtc_write_datetime(unsigned char* buf) int rtc_write_datetime(const struct tm *tm)
{ {
(void)buf; (void)tm;
return 0; return 0;
} }