diff options
author | Nils Wallménius <nils@rockbox.org> | 2009-09-26 14:58:32 +0000 |
---|---|---|
committer | Nils Wallménius <nils@rockbox.org> | 2009-09-26 14:58:32 +0000 |
commit | c8b87d76eb506d374edd2631d4c29e4300be84c4 (patch) | |
tree | 5d380f1f32f317afc579798c5fc4d988e9c48122 /firmware/drivers | |
parent | 66d5bd7cf8c10971578c643c16f72b51df4a1ddf (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.c | 92 | ||||
-rw-r--r-- | firmware/drivers/rtc/rtc_ds1339_ds3231.c | 44 | ||||
-rw-r--r-- | firmware/drivers/rtc/rtc_e8564.c | 118 | ||||
-rw-r--r-- | firmware/drivers/rtc/rtc_jz4740.c | 34 | ||||
-rw-r--r-- | firmware/drivers/rtc/rtc_m41st84w.c | 54 | ||||
-rw-r--r-- | firmware/drivers/rtc/rtc_mc13783.c | 77 | ||||
-rw-r--r-- | firmware/drivers/rtc/rtc_mr100.c | 54 | ||||
-rw-r--r-- | firmware/drivers/rtc/rtc_pcf50605.c | 49 | ||||
-rw-r--r-- | firmware/drivers/rtc/rtc_pcf50606.c | 65 | ||||
-rw-r--r-- | firmware/drivers/rtc/rtc_rx5x348ab.c | 49 | ||||
-rw-r--r-- | firmware/drivers/rtc/rtc_s35390a.c | 48 | ||||
-rw-r--r-- | firmware/drivers/rtc/rtc_s3c2440.c | 40 |
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 |