summaryrefslogtreecommitdiff
path: root/firmware/drivers
diff options
context:
space:
mode:
authorNils Wallménius <nils@rockbox.org>2009-09-26 14:58:32 +0000
committerNils Wallménius <nils@rockbox.org>2009-09-26 14:58:32 +0000
commitc8b87d76eb506d374edd2631d4c29e4300be84c4 (patch)
tree5d380f1f32f317afc579798c5fc4d988e9c48122 /firmware/drivers
parent66d5bd7cf8c10971578c643c16f72b51df4a1ddf (diff)
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
Diffstat (limited to 'firmware/drivers')
-rw-r--r--firmware/drivers/rtc/rtc_as3514.c92
-rw-r--r--firmware/drivers/rtc/rtc_ds1339_ds3231.c44
-rw-r--r--firmware/drivers/rtc/rtc_e8564.c118
-rw-r--r--firmware/drivers/rtc/rtc_jz4740.c34
-rw-r--r--firmware/drivers/rtc/rtc_m41st84w.c54
-rw-r--r--firmware/drivers/rtc/rtc_mc13783.c77
-rw-r--r--firmware/drivers/rtc/rtc_mr100.c54
-rw-r--r--firmware/drivers/rtc/rtc_pcf50605.c49
-rw-r--r--firmware/drivers/rtc/rtc_pcf50606.c65
-rw-r--r--firmware/drivers/rtc/rtc_rx5x348ab.c49
-rw-r--r--firmware/drivers/rtc/rtc_s35390a.c48
-rw-r--r--firmware/drivers/rtc/rtc_s3c2440.c40
12 files changed, 428 insertions, 296 deletions
diff --git a/firmware/drivers/rtc/rtc_as3514.c b/firmware/drivers/rtc/rtc_as3514.c
index d0c4cd7c17..159a0456a3 100644
--- a/firmware/drivers/rtc/rtc_as3514.c
+++ b/firmware/drivers/rtc/rtc_as3514.c
@@ -38,9 +38,6 @@
#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};
@@ -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];
- int year;
- int i;
+ int i, year, mday, hour, min;
unsigned int seconds;
-
+
/* 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);
}
seconds = tmp[0] + (tmp[1]<<8) + (tmp[2]<<16) + (tmp[3]<<24);
seconds -= SECS_ADJUST;
-
+
/* 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;
-
+ tm->tm_wday = ((seconds % WEEK_SECONDS) / DAY_SECONDS + 2) % 7;
+
/* Year */
year = 1980;
- while(seconds>=LEAP_YEAR_SECONDS)
+ while (seconds >= LEAP_YEAR_SECONDS)
{
- if(is_leapyear(year)){
+ if (is_leapyear(year)){
seconds -= LEAP_YEAR_SECONDS;
} else {
seconds -= YEAR_SECONDS;
@@ -88,8 +84,8 @@ int rtc_read_datetime(unsigned char* buf)
year++;
}
-
- if(is_leapyear(year)) {
+
+ if (is_leapyear(year)) {
days_in_month[1] = 29;
} else {
days_in_month[1] = 28;
@@ -98,54 +94,48 @@ int rtc_read_datetime(unsigned char* buf)
seconds -= YEAR_SECONDS;
}
}
- buf[6] = year%100;
-
+ tm->tm_year = year%100 + 100;
+
/* Month */
- for(i=0; i<12; i++)
+ for (i = 0; i < 12; i++)
{
- if(seconds < days_in_month[i]*DAY_SECONDS){
- buf[5] = i+1;
+ if (seconds < days_in_month[i]*DAY_SECONDS){
+ tm->tm_mon = i;
break;
}
-
+
seconds -= days_in_month[i]*DAY_SECONDS;
}
-
+
/* Month Day */
- buf[4] = seconds/DAY_SECONDS;
- seconds -= buf[4]*DAY_SECONDS;
- buf[4]++; /* 1 ... 31 */
+ mday = seconds/DAY_SECONDS;
+ seconds -= mday*DAY_SECONDS;
+ tm->tm_mday = mday + 1; /* 1 ... 31 */
/* Hour */
- buf[2] = seconds/HOUR_SECONDS;
- seconds -= buf[2]*HOUR_SECONDS;
-
+ hour = seconds/HOUR_SECONDS;
+ seconds -= hour*HOUR_SECONDS;
+ tm->tm_hour = hour;
+
/* Minute */
- buf[1] = seconds/MINUTE_SECONDS;
- seconds -= buf[1]*MINUTE_SECONDS;
-
+ min = seconds/MINUTE_SECONDS;
+ seconds -= min*MINUTE_SECONDS;
+ tm->tm_min = min;
+
/* Second */
- buf[0] = seconds;
-
- /* Convert to Binary Coded Decimal format */
- for(i=0; i<7; i++)
- buf[i] = DEC2BCD(buf[i]);
-
+ tm->tm_sec = seconds;
+
return 7;
}
-int rtc_write_datetime(unsigned char* buf)
+int rtc_write_datetime(const struct tm *tm)
{
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];
+ year = 2000 + tm->tm_year - 100;
if(is_leapyear(year)) {
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*/
- for(i=0; i<(buf[5]-1); i++){
+ for(i = 0; i < tm->tm_mon; 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;
+ year_days = 365*(tm->tm_year+20) + (tm->tm_year-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
+ seconds = tm->tm_sec
+ + tm->tm_min*MINUTE_SECONDS
+ + tm->tm_hour*HOUR_SECONDS
+ + (tm->tm_mday-1)*DAY_SECONDS
+ month_days*DAY_SECONDS
+ year_days*DAY_SECONDS;
seconds += SECS_ADJUST;
/* 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));
}
return 1;
diff --git a/firmware/drivers/rtc/rtc_ds1339_ds3231.c b/firmware/drivers/rtc/rtc_ds1339_ds3231.c
index d7d3f2492c..3788dc75c0 100644
--- a/firmware/drivers/rtc/rtc_ds1339_ds3231.c
+++ b/firmware/drivers/rtc/rtc_ds1339_ds3231.c
@@ -115,26 +115,46 @@ bool rtc_enable_alarm(bool enable)
#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);
-
- buf[3]--; /* timefuncs wants 0..6 for wday */
+ rc = sw_i2c_read(RTC_ADDR, 0, 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) - 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 i;
+ 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[5]|=0x80; /* chip wants century (always 20xx) */
+ buf[0] = tm->tm_sec;
+ 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;
}
diff --git a/firmware/drivers/rtc/rtc_e8564.c b/firmware/drivers/rtc/rtc_e8564.c
index b4cd4b91f8..55c67c13c8 100644
--- a/firmware/drivers/rtc/rtc_e8564.c
+++ b/firmware/drivers/rtc/rtc_e8564.c
@@ -27,6 +27,9 @@
#include "i2c-pp.h"
#include <stdbool.h>
+/*RTC_E8564's slave address is 0x51*/
+#define RTC_ADDR 0x51
+
/* RTC registers */
#define RTC_CTRL1 0x00
#define RTC_CTRL2 0x01
@@ -59,94 +62,96 @@ void rtc_init(void)
/* initialize Control 1 register */
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 */
- rv = i2c_readbytes(0x51,RTC_CTRL2,1,&tmp);
+ rv = i2c_readbytes(RTC_ADDR, RTC_CTRL2, 1, &tmp);
/* preserve alarm and timer interrupt flags */
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;
-
- /*RTC_E8564's slave address is 0x51*/
- read = i2c_readbytes(0x51,0x02,7,buf);
-
- /* 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;
-
+ unsigned char buf[7];
+
+ 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;
+
return read;
}
-int rtc_write_datetime(unsigned char* buf)
+int rtc_write_datetime(const struct tm *tm)
{
- int i;
- unsigned char tmp;
-
- /* swap wday and mday to be compatible with
- * set_time() in firmware/common/timefuncs.c */
- tmp=buf[3];
- buf[3]=buf[4];
- buf[4]=tmp;
-
- for (i=0;i<7;i++){
- pp_i2c_send(0x51, 0x02+i,buf[i]);
- }
+ 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_mday;
+ 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]));
+
return 1;
}
void rtc_set_alarm(int h, int m)
{
- unsigned char buf[4]={0};
- int rv=0;
- int i=0;
-
+ unsigned char buf[4] = {0};
+ int i, rv;
+
/* clear alarm interrupt */
- rv = i2c_readbytes(0x51,RTC_CTRL2,1,buf);
+ rv = i2c_readbytes(RTC_ADDR, RTC_CTRL2, 1, buf);
buf[0] &= RTC_AF;
- pp_i2c_send(0x51, RTC_CTRL2,buf[0]);
-
+ pp_i2c_send(RTC_ADDR, RTC_CTRL2, buf[0]);
+
/* prepare new alarm */
if( m >= 0 )
- buf[0] = (((m/10) << 4) | m%10);
+ buf[0] = DEC2BCD(m);
else
/* ignore minutes comparison query */
buf[0] = RTC_AE;
if( h >= 0 )
- buf[1] = (((h/10) << 4) | h%10);
+ buf[1] = DEC2BCD(h);
else
/* ignore hours comparison query */
buf[1] = RTC_AE;
-
+
/* ignore day and wday */
buf[2] = RTC_AE;
buf[3] = RTC_AE;
-
+
/* write new alarm */
- for(;i<4;i++)
- pp_i2c_send(0x51, RTC_ALARM_MINUTES+i,buf[i]);
-
+ for(i = 0; i < 4; i++)
+ pp_i2c_send(RTC_ADDR, RTC_ALARM_MINUTES + i, buf[i]);
+
/* note: alarm is not enabled at the point */
}
void rtc_get_alarm(int *h, int *m)
{
unsigned char buf[4]={0};
-
- /* get alarm preset */
- i2c_readbytes(0x51, RTC_ALARM_MINUTES,4,buf);
- *m = ((buf[0] >> 4) & 0x7)*10 + (buf[0] & 0x0f);
- *h = ((buf[1] >> 4) & 0x3)*10 + (buf[1] & 0x0f);
+ /* get alarm preset */
+ i2c_readbytes(RTC_ADDR, RTC_ALARM_MINUTES, 4 ,buf);
+ *m = BCD2DEC(buf[0] & 0x7f);
+ *h = BCD2DEC(buf[0] & 0x3f);
}
bool rtc_enable_alarm(bool enable)
@@ -157,10 +162,10 @@ bool rtc_enable_alarm(bool enable)
if(enable)
{
/* 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_AF;
- pp_i2c_send(0x51, RTC_CTRL2,tmp);
+ pp_i2c_send(RTC_ADDR, RTC_CTRL2, tmp);
}
else
{
@@ -168,9 +173,9 @@ bool rtc_enable_alarm(bool enable)
if(rtc_lock_alarm_clear)
/* lock disabling alarm before it was checked whether or not the unit was started by RTC alarm */
return false;
- rv = i2c_readbytes(0x51,RTC_CTRL2,1,&tmp);
+ rv = i2c_readbytes(RTC_ADDR, RTC_CTRL2, 1, &tmp);
tmp &= ~(RTC_AIE | RTC_AF);
- pp_i2c_send(0x51, RTC_CTRL2,tmp);
+ pp_i2c_send(RTC_ADDR, RTC_CTRL2, tmp);
}
return false;
@@ -186,21 +191,21 @@ bool rtc_check_alarm_started(bool release_alarm)
if (run_before)
{
started = alarm_state;
- alarm_state &= ~release_alarm;
+ alarm_state &= ~release_alarm;
}
else
{
/* 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) );
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 */
tmp &= ~(RTC_AF | RTC_AIE);
- pp_i2c_send(0x51, RTC_CTRL2,tmp);
+ pp_i2c_send(RTC_ADDR, RTC_CTRL2, tmp);
}
run_before = true;
rtc_lock_alarm_clear = false;
@@ -215,7 +220,8 @@ bool rtc_check_alarm_flag(void)
int rv=0;
/* 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);
}
+
diff --git a/firmware/drivers/rtc/rtc_jz4740.c b/firmware/drivers/rtc/rtc_jz4740.c
index 479e3591db..a73f300aa8 100644
--- a/firmware/drivers/rtc/rtc_jz4740.c
+++ b/firmware/drivers/rtc/rtc_jz4740.c
@@ -116,11 +116,10 @@ static void jz_gettime(unsigned int rtc, int *year, int *mon, int *day,
*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;
-
+
/*
* Only the values that we read from the RTC are set. We leave
* tm_wday, tm_yday and tm_isdst untouched. Even though the
@@ -131,37 +130,32 @@ int rtc_read_datetime(unsigned char* buf)
year -= 2000;
- rtc_tm.tm_sec = sec;
- rtc_tm.tm_min = min;
- rtc_tm.tm_hour = hour;
- rtc_tm.tm_mday = mday;
- rtc_tm.tm_wday = wday;
+ tm->tm_sec = sec;
+ tm->tm_min = min;
+ tm->tm_hour = hour;
+ tm->tm_mday = mday;
+ tm->tm_wday = wday;
/* Don't use centry, but start from year 1970 */
- rtc_tm.tm_mon = mon;
+ tm->tm_mon = mon;
if (year <= 69)
year += 100;
- rtc_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;
+ tm->tm_year = year;
+
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;
- year = rtc_tm->tm_year;
+ year = tm->tm_year;
/* Don't use centry, but start from year 1970 */
if (year > 69)
year -= 100;
year += 2000;
- lval = jz_mktime(year, rtc_tm->tm_mon, rtc_tm->tm_mday, rtc_tm->tm_hour,
- rtc_tm->tm_min, rtc_tm->tm_sec);
+ lval = jz_mktime(year, tm->tm_mon, tm->tm_mday, tm->tm_hour,
+ tm->tm_min, tm->tm_sec);
__cpm_start_rtc();
udelay(100);
diff --git a/firmware/drivers/rtc/rtc_m41st84w.c b/firmware/drivers/rtc/rtc_m41st84w.c
index 738fb201bf..2627191252 100644
--- a/firmware/drivers/rtc/rtc_m41st84w.c
+++ b/firmware/drivers/rtc/rtc_m41st84w.c
@@ -110,10 +110,10 @@ void rtc_set_alarm(int h, int m)
/* for daily alarm, RPT5=RPT4=on, RPT1=RPT2=RPT3=off */
- rtc_write(0x0e, 0x00); /* seconds 0 and RTP1 */
- rtc_write(0x0d, ((m / 10) << 4) | (m % 10)); /* minutes and RPT2 */
- rtc_write(0x0c, ((h / 10) << 4) | (h % 10)); /* hour and RPT3 */
- rtc_write(0x0b, 0xc1); /* set date 01 and RPT4 and RTP5 */
+ rtc_write(0x0e, 0x00); /* seconds 0 and RTP1 */
+ rtc_write(0x0d, DEC2BCD(m); /* minutes and RPT2 */
+ rtc_write(0x0c, DEC2BCD(h); /* hour and RPT3 */
+ 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 */
data = rtc_read(0x0a);
@@ -128,10 +128,10 @@ void rtc_get_alarm(int *h, int *m)
unsigned char data;
data = rtc_read(0x0c);
- *h = ((data & 0x30) >> 4) * 10 + (data & 0x0f);
+ *h = BCD2DEC(data & 0x3f);
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 */
@@ -250,31 +250,53 @@ int rtc_read_multiple(unsigned char address, unsigned char *buf, int numbytes)
return ret;
}
-int rtc_read_datetime(unsigned char* buf) {
+int rtc_read_datetime(struct tm *tm)
+{
int rc;
+ unsigned char buf[7];
+
+ rc = rtc_read_multiple(1, buf, sizeof(buf));
- rc = rtc_read_multiple(1, buf, 7);
+ /* 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 */
- if(buf[3] == 7)
- buf[3]=0;
+ if (tm->tm_wday == 7)
+ tm->tm_wday = 0;
return rc;
}
-int rtc_write_datetime(unsigned char* buf) {
- int i;
+int rtc_write_datetime(const struct tm *tm)
+{
+ unsigned int i;
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 */
- if(buf[3] == 0)
+ if (buf[3] == 0)
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 */
return rc;
}
+
diff --git a/firmware/drivers/rtc/rtc_mc13783.c b/firmware/drivers/rtc/rtc_mc13783.c
index 15ed5b148b..e36faa6089 100644
--- a/firmware/drivers/rtc/rtc_mc13783.c
+++ b/firmware/drivers/rtc/rtc_mc13783.c
@@ -46,18 +46,6 @@
#define RTC_BASE_YEAR 1970
#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
{
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 },
};
-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 */
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];
- 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
* greater */
@@ -147,19 +115,21 @@ int rtc_read_datetime(unsigned char* buf)
while (regs[RTC_REG_TIME2] < regs[RTC_REG_TIME]);
/* TOD: = 0 to 86399 */
- buf[RTC_I_HOURS] = regs[RTC_REG_TIME] / 3600;
- regs[RTC_REG_TIME] -= buf[RTC_I_HOURS]*3600;
+ hour = regs[RTC_REG_TIME] / 3600;
+ regs[RTC_REG_TIME] -= hour*3600;
+ tm->tm_hour = hour;
- buf[RTC_I_MINUTES] = regs[RTC_REG_TIME] / 60;
- regs[RTC_REG_TIME] -= buf[RTC_I_MINUTES]*60;
+ min = regs[RTC_REG_TIME] / 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 = regs[RTC_REG_DAY] + RTC_BASE_DAY_COUNT;
/* 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 */
leap = get_leap_count(day);
@@ -186,28 +156,23 @@ int rtc_read_datetime(unsigned char* buf)
day -= days;
}
- buf[RTC_I_DAY] = day + 1; /* 1 to 31 */
- buf[RTC_I_MONTH] = month + 1; /* 1 to 12 */
- buf[RTC_I_YEAR] = year % 100;
-
- to_bcd(buf, buf, RTC_NUM_FIELDS);
+ tm->tm_mday = day + 1; /* 1 to 31 */
+ tm->tm_mon = month; /* 0 to 11 */
+ tm->tm_year = year % 100 + 100;
return 7;
}
-int rtc_write_datetime(unsigned char* buf)
+int rtc_write_datetime(const struct tm *tm)
{
uint32_t regs[2];
- unsigned char fld[RTC_NUM_FIELDS];
int year, leap, month, day, i, base_yearday;
- from_bcd(fld, buf, RTC_NUM_FIELDS);
-
- regs[RTC_REG_TIME] = fld[RTC_I_SECONDS] +
- fld[RTC_I_MINUTES]*60 +
- fld[RTC_I_HOURS]*3600;
+ regs[RTC_REG_TIME] = tm->tm_sec +
+ tm->tm_min*60 +
+ tm->tm_hour*3600;
- year = fld[RTC_I_YEAR];
+ year = tm->tm_year - 100;
if (year < RTC_BASE_YEAR - 1900)
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
* month. */
leap = is_leap_year(year);
- month = fld[RTC_I_MONTH] - 1;
+ month = tm->tm_mon;
for (i = 0; i < month; 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)
{
- return RTC_NUM_FIELDS;
+ return 7;
}
return 0;
diff --git a/firmware/drivers/rtc/rtc_mr100.c b/firmware/drivers/rtc/rtc_mr100.c
index 7ec3996a87..209845cea8 100644
--- a/firmware/drivers/rtc/rtc_mr100.c
+++ b/firmware/drivers/rtc/rtc_mr100.c
@@ -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 char v[7];
+ unsigned int i;
+ 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++)
- buf[i] = v[6-i];
-
- return i;
+ for (i = 0; i < sizeof(buf); i++)
+ buf[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 rc;
}
-int rtc_write_datetime(unsigned char* buf)
+int rtc_write_datetime(const struct tm *tm)
{
- int i;
- unsigned char v[7];
+ unsigned int i;
+ int rc;
+ unsigned char buf[7];
- for(i=0; i<7; i++)
- v[i]=buf[6-i];
-
- i = sw_i2c(SW_I2C_WRITE, RTC_CMD_DATA, v, 7);
-
- return i;
+ buf[6] = tm->tm_sec;
+ buf[5] = tm->tm_min;
+ buf[4] = tm->tm_hour;
+ buf[3] = tm->tm_wday;
+ buf[2] = tm->tm_mday;
+ 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;
}
diff --git a/firmware/drivers/rtc/rtc_pcf50605.c b/firmware/drivers/rtc/rtc_pcf50605.c
index fe12766c4a..b030fba37a 100644
--- a/firmware/drivers/rtc/rtc_pcf50605.c
+++ b/firmware/drivers/rtc/rtc_pcf50605.c
@@ -36,14 +36,45 @@ void rtc_init(void)
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;
}
@@ -121,17 +152,17 @@ void rtc_set_alarm(int h, int m)
/* Set us to wake at the first second of the specified time */
pcf50605_write(0x11, 0);
/* Convert to BCD */
- pcf50605_write(0x12, ((m/10) << 4) | m%10);
- pcf50605_write(0x13, ((h/10) << 4) | h%10);
+ pcf50605_write(0x12, DEC2BCD(m));
+ pcf50605_write(0x13, DEC2BCD(h));
}
void rtc_get_alarm(int *h, int *m)
{
char buf[2];
- pcf50605_read_multiple(0x12, buf, 2);
+ pcf50605_read_multiple(0x12, buf, sizeof(buf));
/* Convert from BCD */
- *m = ((buf[0] >> 4) & 0x7)*10 + (buf[0] & 0x0f);
- *h = ((buf[1] >> 4) & 0x3)*10 + (buf[1] & 0x0f);
+ *m = BCD2DEC(buf[0]);
+ *h = BCD2DEC(buf[1]);
}
diff --git a/firmware/drivers/rtc/rtc_pcf50606.c b/firmware/drivers/rtc/rtc_pcf50606.c
index 50df5a1f95..cb6697207b 100644
--- a/firmware/drivers/rtc/rtc_pcf50606.c
+++ b/firmware/drivers/rtc/rtc_pcf50606.c
@@ -24,27 +24,70 @@
#include "kernel.h"
#include "system.h"
#include "pcf50606.h"
-#include <stdbool.h>
void rtc_init(void)
{
}
-int rtc_read_datetime(unsigned char* buf) {
- int rc;
- int oldlevel = disable_irq_save();
-
- rc = pcf50606_read_multiple(0x0a, buf, 7);
+int rtc_read_datetime(struct tm *tm)
+{
+ unsigned int i;
+ int rc, oldlevel;
+ unsigned char buf[7];
+
+ oldlevel = disable_irq_save();
+
+ rc = pcf50606_read_multiple(0x0a, buf, sizeof(buf));
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;
}
-int rtc_write_datetime(unsigned char* buf) {
- int rc;
- int oldlevel = disable_irq_save();
-
- rc = pcf50606_write_multiple(0x0a, buf, 7);
+int rtc_write_datetime(const struct tm *tm)
+{
+ unsigned int i;
+ int rc, oldlevel;
+ 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);
diff --git a/firmware/drivers/rtc/rtc_rx5x348ab.c b/firmware/drivers/rtc/rtc_rx5x348ab.c
index 331b2d6cb8..f31ab5623e 100644
--- a/firmware/drivers/rtc/rtc_rx5x348ab.c
+++ b/firmware/drivers/rtc/rtc_rx5x348ab.c
@@ -22,31 +22,60 @@
#include "config.h"
#include "spi.h"
#include "rtc.h"
-#include <stdbool.h>
+
/* Choose one of: */
#define ADDR_READ 0x04
#define ADDR_WRITE 0x00
/* and one of: */
#define ADDR_ONE 0x08
#define ADDR_BURST 0x00
+
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 */
- 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;
}
-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 data[8];
- int i;
- data[0] = command;
- for (i=1;i<8;i++)
- data[i] = buf[i-1];
- spi_block_transfer(SPI_target_RX5X348AB, data, 8, NULL, 0);
+ unsigned char buf[8];
+
+ buf[0] = command;
+ buf[1] = tm->tm_sec;
+ buf[2] = tm->tm_min;
+ 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;
}
+
diff --git a/firmware/drivers/rtc/rtc_s35390a.c b/firmware/drivers/rtc/rtc_s35390a.c
index 6bcf5c939b..0b95431330 100644
--- a/firmware/drivers/rtc/rtc_s35390a.c
+++ b/firmware/drivers/rtc/rtc_s35390a.c
@@ -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;
- ret = i2c_read(RTC_ADDR | (REALTIME_DATA1 << 1), -1, sizeof(data), data);
- reverse_bits(data, sizeof(data));
+ ret = i2c_read(RTC_ADDR | (REALTIME_DATA1 << 1), -1, sizeof(buf), buf);
+ reverse_bits(buf, sizeof(buf));
buf[4] &= 0x3f; /* mask out p.m. flag */
-
- for (i = 0; i < 7; i++) {
- buf[i] = data[6 - i];
- }
+
+ for (i = 0; i < sizeof(buf); 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;
}
-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;
- for (i = 0; i < 7; i++) {
- data[i] = buf[6 - i];
- }
-
- reverse_bits(data, sizeof(data));
- ret = i2c_write(RTC_ADDR | (REALTIME_DATA1 << 1), -1, sizeof(data), data);
-
+ buf[6] = tm->tm_sec;
+ buf[5] = tm->tm_min;
+ buf[4] = tm->tm_hour;
+ buf[3] = tm->tm_wday;
+ buf[2] = tm->tm_mday;
+ 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;
}
diff --git a/firmware/drivers/rtc/rtc_s3c2440.c b/firmware/drivers/rtc/rtc_s3c2440.c
index d39b50a2ca..9b449052a9 100644
--- a/firmware/drivers/rtc/rtc_s3c2440.c
+++ b/firmware/drivers/rtc/rtc_s3c2440.c
@@ -30,28 +30,28 @@ void rtc_init(void)
RTCCON |= 1;
}
-int rtc_read_datetime(unsigned char* buf)
+int rtc_read_datetime(struct tm *tm)
{
- buf[0] = BCDSEC;
- buf[1] = BCDMIN;
- buf[2] = BCDHOUR;
- buf[3] = BCDDAY-1; /* timefuncs wants 0..6 for wday */
- buf[4] = BCDDATE;
- buf[5] = BCDMON;
- buf[6] = BCDYEAR;
+ tm->tm_sec = BCD2DEC(BCDSEC);
+ tm->tm_min = BCD2DEC(BCDMIN);
+ tm->tm_hour = BCD2DEC(BCDHOUR);
+ tm->tm_wday = BCD2DEC(BCDDAY) - 1; /* timefuncs wants 0..6 for wday */
+ tm->tm_mday = BCD2DEC(BCDDATE);
+ tm->tm_mon = BCD2DEC(BCDMON) - 1;
+ tm->tm_year = BCD2DEC(BCDYEAR) + 100;
return 1;
}
-int rtc_write_datetime(unsigned char* buf)
+int rtc_write_datetime(const struct tm *tm)
{
- BCDSEC = buf[0];
- BCDMIN = buf[1];
- BCDHOUR = buf[2];
- BCDDAY = buf[3]+1; /* chip wants 1..7 for wday */
- BCDDATE = buf[4];
- BCDMON = buf[5];
- BCDYEAR = buf[6];
+ BCDSEC = DEC2BCD(tm->tm_sec);
+ BCDMIN = DEC2BCD(tm->tm_min);
+ BCDHOUR = DEC2BCD(tm->tm_hour);
+ BCDDAY = DEC2BCD(tm->tm_wday) + 1; /* chip wants 1..7 for wday */
+ BCDDATE = DEC2BCD(tm->tm_mday);
+ BCDMON = DEC2BCD(tm->tm_mon + 1);
+ BCDYEAR = DEC2BCD(tm->tm_year - 100);
return 1;
}
@@ -88,15 +88,15 @@ bool rtc_check_alarm_flag(void)
/* set alarm time registers to the given time (repeat once per day) */
void rtc_set_alarm(int h, int m)
{
- ALMMIN=(((m / 10) << 4) | (m % 10)) & 0x7f; /* minutes */
- ALMHOUR=(((h / 10) << 4) | (h % 10)) & 0x3f; /* hour */
+ ALMMIN = DEC2BCD(m); /* minutes */
+ ALMHOUR = DEC2BCD(h); /* hour */
}
/* read out the current alarm time */
void rtc_get_alarm(int *h, int *m)
{
- *m=((ALMMIN & 0x70) >> 4) * 10 + (ALMMIN & 0x0f);
- *h=((ALMHOUR & 0x30) >> 4) * 10 + (ALMHOUR & 0x0f);
+ *m = BCD2DEC(ALMMIN);
+ *h = BCD2DEC(ALMHOUR);
}
/* turn alarm on or off by setting the alarm flag enable