summaryrefslogtreecommitdiff
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
parent66d5bd7cf8c10971578c643c16f72b51df4a1ddf (diff)
downloadrockbox-c8b87d76eb506d374edd2631d4c29e4300be84c4.tar.gz
rockbox-c8b87d76eb506d374edd2631d4c29e4300be84c4.zip
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
-rw-r--r--firmware/common/timefuncs.c77
-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
-rw-r--r--firmware/export/rtc.h11
-rw-r--r--firmware/include/timefuncs.h1
-rw-r--r--uisimulator/common/stubs.c16
16 files changed, 454 insertions, 375 deletions
diff --git a/firmware/common/timefuncs.c b/firmware/common/timefuncs.c
index 405bce4f5f..eef804d302 100644
--- a/firmware/common/timefuncs.c
+++ b/firmware/common/timefuncs.c
@@ -27,9 +27,7 @@
27#include "timefuncs.h" 27#include "timefuncs.h"
28#include "debug.h" 28#include "debug.h"
29 29
30#if !defined SIMULATOR || !CONFIG_RTC
31static struct tm tm; 30static struct tm tm;
32#endif /* !defined SIMULATOR || !CONFIG_RTC */
33 31
34#if !CONFIG_RTC 32#if !CONFIG_RTC
35static void fill_default_tm(struct tm *tm) 33static void fill_default_tm(struct tm *tm)
@@ -62,7 +60,6 @@ bool valid_time(const struct tm *tm)
62 60
63struct tm *get_time(void) 61struct tm *get_time(void)
64{ 62{
65#ifndef SIMULATOR
66#if CONFIG_RTC 63#if CONFIG_RTC
67 static long timeout = 0; 64 static long timeout = 0;
68 65
@@ -71,76 +68,25 @@ struct tm *get_time(void)
71 { 68 {
72 /* Once per second, 1/10th of a second off */ 69 /* Once per second, 1/10th of a second off */
73 timeout = HZ * (current_tick / HZ + 1) + HZ / 5; 70 timeout = HZ * (current_tick / HZ + 1) + HZ / 5;
74#if CONFIG_RTC != RTC_JZ47XX 71 rtc_read_datetime(&tm);
75 char rtcbuf[7];
76 rtc_read_datetime(rtcbuf);
77
78 tm.tm_sec = ((rtcbuf[0] & 0x70) >> 4) * 10 + (rtcbuf[0] & 0x0f);
79 tm.tm_min = ((rtcbuf[1] & 0x70) >> 4) * 10 + (rtcbuf[1] & 0x0f);
80 tm.tm_hour = ((rtcbuf[2] & 0x30) >> 4) * 10 + (rtcbuf[2] & 0x0f);
81 tm.tm_wday = rtcbuf[3] & 0x07;
82 tm.tm_mday = ((rtcbuf[4] & 0x30) >> 4) * 10 + (rtcbuf[4] & 0x0f);
83 tm.tm_mon = ((rtcbuf[5] & 0x10) >> 4) * 10 + (rtcbuf[5] & 0x0f) - 1;
84#ifdef IRIVER_H300_SERIES
85 /* Special kludge to coexist with the iriver firmware. The iriver firmware
86 stores the date as 1965+nn, and allows a range of 1980..2064. We use
87 1964+nn here to make leap years work correctly, so the date will be one
88 year off in the iriver firmware but at least won't be reset anymore. */
89 tm.tm_year = ((rtcbuf[6] & 0xf0) >> 4) * 10 + (rtcbuf[6] & 0x0f) + 64;
90#else /* Not IRIVER_H300_SERIES */
91 tm.tm_year = ((rtcbuf[6] & 0xf0) >> 4) * 10 + (rtcbuf[6] & 0x0f) + 100;
92#endif /* IRIVER_H300_SERIES */
93 72
94 tm.tm_yday = 0; /* Not implemented for now */ 73 tm.tm_yday = 0; /* Not implemented for now */
95 tm.tm_isdst = -1; /* Not implemented for now */ 74 tm.tm_isdst = -1; /* Not implemented for now */
96#else /* CONFIG_RTC == RTC_JZ47XX */
97 rtc_read_datetime((unsigned char*)&tm);
98#endif /* CONFIG_RTC */
99 } 75 }
100#else /* No RTC */ 76#else /* No RTC */
101 fill_default_tm(&tm); 77 fill_default_tm(&tm);
102#endif /* RTC */ 78#endif /* RTC */
103 return &tm; 79 return &tm;
104
105#else /* SIMULATOR */
106#if CONFIG_RTC
107 time_t now = time(NULL);
108 return localtime(&now);
109#else /* Simulator, no RTC */
110 fill_default_tm(&tm);
111 return &tm;
112#endif
113#endif /* SIMULATOR */
114} 80}
115 81
116int set_time(const struct tm *tm) 82int set_time(const struct tm *tm)
117{ 83{
118#if CONFIG_RTC 84#if CONFIG_RTC
119 int rc; 85 int rc;
120#if CONFIG_RTC != RTC_JZ47XX 86
121 char rtcbuf[7];
122#endif
123
124 if (valid_time(tm)) 87 if (valid_time(tm))
125 { 88 {
126#if CONFIG_RTC != RTC_JZ47XX 89 rc = rtc_write_datetime(tm);
127 rtcbuf[0]=((tm->tm_sec/10) << 4) | (tm->tm_sec%10);
128 rtcbuf[1]=((tm->tm_min/10) << 4) | (tm->tm_min%10);
129 rtcbuf[2]=((tm->tm_hour/10) << 4) | (tm->tm_hour%10);
130 rtcbuf[3]=tm->tm_wday;
131 rtcbuf[4]=((tm->tm_mday/10) << 4) | (tm->tm_mday%10);
132 rtcbuf[5]=(((tm->tm_mon+1)/10) << 4) | ((tm->tm_mon+1)%10);
133#ifdef IRIVER_H300_SERIES
134 /* Iriver firmware compatibility kludge, see get_time(). */
135 rtcbuf[6]=(((tm->tm_year-64)/10) << 4) | ((tm->tm_year-64)%10);
136#else
137 rtcbuf[6]=(((tm->tm_year-100)/10) << 4) | ((tm->tm_year-100)%10);
138#endif
139
140 rc = rtc_write_datetime(rtcbuf);
141#else
142 rc = rtc_write_datetime((unsigned char*)tm);
143#endif
144 90
145 if (rc < 0) 91 if (rc < 0)
146 return -1; 92 return -1;
@@ -151,10 +97,10 @@ int set_time(const struct tm *tm)
151 { 97 {
152 return -2; 98 return -2;
153 } 99 }
154#else 100#else /* No RTC */
155 (void)tm; 101 (void)tm;
156 return 0; 102 return 0;
157#endif 103#endif /* RTC */
158} 104}
159 105
160#if CONFIG_RTC 106#if CONFIG_RTC
@@ -196,11 +142,12 @@ time_t mktime(struct tm *t)
196 142
197void set_day_of_week(struct tm *tm) 143void set_day_of_week(struct tm *tm)
198{ 144{
199 int y=tm->tm_year+1900; 145 int y=tm->tm_year+1900;
200 int d=tm->tm_mday; 146 int d=tm->tm_mday;
201 int m=tm->tm_mon; 147 int m=tm->tm_mon;
202 static const char mo[] = { 0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4 }; 148 static const char mo[] = { 0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4 };
203 149
204 if(m == 0 || m == 1) y--; 150 if(m == 0 || m == 1) y--;
205 tm->tm_wday = (d + mo[m] + y + y/4 - y/100 + y/400) % 7; 151 tm->tm_wday = (d + mo[m] + y + y/4 - y/100 + y/400) % 7;
206} 152}
153
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 @@
38#define YEAR_SECONDS 31536000 38#define YEAR_SECONDS 31536000
39#define LEAP_YEAR_SECONDS 31622400 39#define LEAP_YEAR_SECONDS 31622400
40 40
41#define BCD2DEC(X) (((((X)>>4) & 0x0f) * 10) + ((X) & 0xf))
42#define DEC2BCD(X) ((((X)/10)<<4) | ((X)%10))
43
44/* Days in each month */ 41/* Days in each month */
45static unsigned int days_in_month[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; 42static unsigned int days_in_month[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
46 43
@@ -56,31 +53,30 @@ void rtc_init(void)
56{ 53{
57} 54}
58 55
59int rtc_read_datetime(unsigned char* buf) 56int rtc_read_datetime(struct tm *tm)
60{ 57{
61 char tmp[4]; 58 char tmp[4];
62 int year; 59 int i, year, mday, hour, min;
63 int i;
64 unsigned int seconds; 60 unsigned int seconds;
65 61
66 /* RTC_AS3514's slave address is 0x46*/ 62 /* RTC_AS3514's slave address is 0x46*/
67 for (i=0;i<4;i++){ 63 for (i = 0; i < 4; i++){
68 tmp[i] = ascodec_read(AS3514_RTC_0 + i); 64 tmp[i] = ascodec_read(AS3514_RTC_0 + i);
69 } 65 }
70 seconds = tmp[0] + (tmp[1]<<8) + (tmp[2]<<16) + (tmp[3]<<24); 66 seconds = tmp[0] + (tmp[1]<<8) + (tmp[2]<<16) + (tmp[3]<<24);
71 seconds -= SECS_ADJUST; 67 seconds -= SECS_ADJUST;
72 68
73 /* Convert seconds since Jan-1-1980 to format compatible with 69 /* Convert seconds since Jan-1-1980 to format compatible with
74 * get_time() from firmware/common/timefuncs.c */ 70 * get_time() from firmware/common/timefuncs.c */
75 71
76 /* weekday */ 72 /* weekday */
77 buf[3] = ((seconds % WEEK_SECONDS) / DAY_SECONDS + 2) % 7; 73 tm->tm_wday = ((seconds % WEEK_SECONDS) / DAY_SECONDS + 2) % 7;
78 74
79 /* Year */ 75 /* Year */
80 year = 1980; 76 year = 1980;
81 while(seconds>=LEAP_YEAR_SECONDS) 77 while (seconds >= LEAP_YEAR_SECONDS)
82 { 78 {
83 if(is_leapyear(year)){ 79 if (is_leapyear(year)){
84 seconds -= LEAP_YEAR_SECONDS; 80 seconds -= LEAP_YEAR_SECONDS;
85 } else { 81 } else {
86 seconds -= YEAR_SECONDS; 82 seconds -= YEAR_SECONDS;
@@ -88,8 +84,8 @@ int rtc_read_datetime(unsigned char* buf)
88 84
89 year++; 85 year++;
90 } 86 }
91 87
92 if(is_leapyear(year)) { 88 if (is_leapyear(year)) {
93 days_in_month[1] = 29; 89 days_in_month[1] = 29;
94 } else { 90 } else {
95 days_in_month[1] = 28; 91 days_in_month[1] = 28;
@@ -98,54 +94,48 @@ int rtc_read_datetime(unsigned char* buf)
98 seconds -= YEAR_SECONDS; 94 seconds -= YEAR_SECONDS;
99 } 95 }
100 } 96 }
101 buf[6] = year%100; 97 tm->tm_year = year%100 + 100;
102 98
103 /* Month */ 99 /* Month */
104 for(i=0; i<12; i++) 100 for (i = 0; i < 12; i++)
105 { 101 {
106 if(seconds < days_in_month[i]*DAY_SECONDS){ 102 if (seconds < days_in_month[i]*DAY_SECONDS){
107 buf[5] = i+1; 103 tm->tm_mon = i;
108 break; 104 break;
109 } 105 }
110 106
111 seconds -= days_in_month[i]*DAY_SECONDS; 107 seconds -= days_in_month[i]*DAY_SECONDS;
112 } 108 }
113 109
114 /* Month Day */ 110 /* Month Day */
115 buf[4] = seconds/DAY_SECONDS; 111 mday = seconds/DAY_SECONDS;
116 seconds -= buf[4]*DAY_SECONDS; 112 seconds -= mday*DAY_SECONDS;
117 buf[4]++; /* 1 ... 31 */ 113 tm->tm_mday = mday + 1; /* 1 ... 31 */
118 114
119 /* Hour */ 115 /* Hour */
120 buf[2] = seconds/HOUR_SECONDS; 116 hour = seconds/HOUR_SECONDS;
121 seconds -= buf[2]*HOUR_SECONDS; 117 seconds -= hour*HOUR_SECONDS;
122 118 tm->tm_hour = hour;
119
123 /* Minute */ 120 /* Minute */
124 buf[1] = seconds/MINUTE_SECONDS; 121 min = seconds/MINUTE_SECONDS;
125 seconds -= buf[1]*MINUTE_SECONDS; 122 seconds -= min*MINUTE_SECONDS;
126 123 tm->tm_min = min;
124
127 /* Second */ 125 /* Second */
128 buf[0] = seconds; 126 tm->tm_sec = seconds;
129 127
130 /* Convert to Binary Coded Decimal format */
131 for(i=0; i<7; i++)
132 buf[i] = DEC2BCD(buf[i]);
133
134 return 7; 128 return 7;
135} 129}
136 130
137int rtc_write_datetime(unsigned char* buf) 131int rtc_write_datetime(const struct tm *tm)
138{ 132{
139 int i, year; 133 int i, year;
140 unsigned int year_days = 0; 134 unsigned int year_days = 0;
141 unsigned int month_days = 0; 135 unsigned int month_days = 0;
142 unsigned int seconds = 0; 136 unsigned int seconds = 0;
143
144 /* Convert from Binary Coded Decimal format */
145 for(i=0; i<7; i++)
146 buf[i] = BCD2DEC(buf[i]);
147 137
148 year = 2000 + buf[6]; 138 year = 2000 + tm->tm_year - 100;
149 139
150 if(is_leapyear(year)) { 140 if(is_leapyear(year)) {
151 days_in_month[1] = 29; 141 days_in_month[1] = 29;
@@ -154,24 +144,24 @@ int rtc_write_datetime(unsigned char* buf)
154 } 144 }
155 145
156 /* Number of days in months gone by this year*/ 146 /* Number of days in months gone by this year*/
157 for(i=0; i<(buf[5]-1); i++){ 147 for(i = 0; i < tm->tm_mon; i++){
158 month_days += days_in_month[i]; 148 month_days += days_in_month[i];
159 } 149 }
160 150
161 /* Number of days in years gone by since 1-Jan-1980 */ 151 /* Number of days in years gone by since 1-Jan-1980 */
162 year_days = 365*(buf[6]+20) + (buf[6]-1)/4 + 6; 152 year_days = 365*(tm->tm_year+20) + (tm->tm_year-1)/4 + 6;
163 153
164 /* Convert to seconds since 1-Jan-1980 */ 154 /* Convert to seconds since 1-Jan-1980 */
165 seconds = buf[0] 155 seconds = tm->tm_sec
166 + buf[1]*MINUTE_SECONDS 156 + tm->tm_min*MINUTE_SECONDS
167 + buf[2]*HOUR_SECONDS 157 + tm->tm_hour*HOUR_SECONDS
168 + (buf[4]-1)*DAY_SECONDS 158 + (tm->tm_mday-1)*DAY_SECONDS
169 + month_days*DAY_SECONDS 159 + month_days*DAY_SECONDS
170 + year_days*DAY_SECONDS; 160 + year_days*DAY_SECONDS;
171 seconds += SECS_ADJUST; 161 seconds += SECS_ADJUST;
172 162
173 /* Send data to RTC */ 163 /* Send data to RTC */
174 for (i=0;i<4;i++){ 164 for (i=0; i<4; i++){
175 ascodec_write(AS3514_RTC_0 + i, ((seconds >> (8 * i)) & 0xff)); 165 ascodec_write(AS3514_RTC_0 + i, ((seconds >> (8 * i)) & 0xff));
176 } 166 }
177 return 1; 167 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)
115 115
116#endif /* HAVE_RTC_ALARM */ 116#endif /* HAVE_RTC_ALARM */
117 117
118int rtc_read_datetime(unsigned char* buf) 118int rtc_read_datetime(struct tm *tm)
119{ 119{
120 int i; 120 int rc;
121 unsigned char buf[7];
121 122
122 i = sw_i2c_read(RTC_ADDR, 0, buf, 7); 123 rc = sw_i2c_read(RTC_ADDR, 0, buf, sizeof(buf));
123 124
124 buf[3]--; /* timefuncs wants 0..6 for wday */ 125 /* convert from bcd, avoid getting extra bits */
126 tm->tm_sec = BCD2DEC(buf[0] & 0x7f);
127 tm->tm_min = BCD2DEC(buf[1] & 0x7f);
128 tm->tm_hour = BCD2DEC(buf[2] & 0x3f);
129 tm->tm_wday = BCD2DEC(buf[3] & 0x3) - 1; /* timefuncs wants 0..6 for wday */
130 tm->tm_mday = BCD2DEC(buf[4] & 0x3f);
131 tm->tm_mon = BCD2DEC(buf[5] & 0x1f) - 1;
132 tm->tm_year = BCD2DEC(buf[6]) + 100;
125 133
126 return i; 134 return rc;
127} 135}
128 136
129int rtc_write_datetime(unsigned char* buf) 137int rtc_write_datetime(const struct tm *tm)
130{ 138{
131 int i; 139 unsigned int i;
140 int rc;
141 unsigned char buf[7];
132 142
133 buf[3]++; /* chip wants 1..7 for wday */ 143 buf[0] = tm->tm_sec;
134 buf[5]|=0x80; /* chip wants century (always 20xx) */ 144 buf[1] = tm->tm_min;
145 buf[2] = tm->tm_hour;
146 buf[3] = tm->tm_wday + 1; /* chip wants 1..7 for wday */
147 buf[4] = tm->tm_mday;
148 buf[5] = tm->tm_mon + 1;
149 buf[6] = tm->tm_year - 100;
135 150
136 i = sw_i2c_write(RTC_ADDR, 0, buf, 7); 151 for (i = 0; i < sizeof(buf); i++)
152 buf[i] = DEC2BCD(buf[i]);
137 153
138 return i; 154 buf[5] |= 0x80; /* chip wants century (always 20xx) */
155
156 rc = sw_i2c_write(RTC_ADDR, 0, buf, sizeof(buf));
157
158 return rc;
139} 159}
140 160
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 @@
27#include "i2c-pp.h" 27#include "i2c-pp.h"
28#include <stdbool.h> 28#include <stdbool.h>
29 29
30/*RTC_E8564's slave address is 0x51*/
31#define RTC_ADDR 0x51
32
30/* RTC registers */ 33/* RTC registers */
31#define RTC_CTRL1 0x00 34#define RTC_CTRL1 0x00
32#define RTC_CTRL2 0x01 35#define RTC_CTRL2 0x01
@@ -59,94 +62,96 @@ void rtc_init(void)
59 62
60 /* initialize Control 1 register */ 63 /* initialize Control 1 register */
61 tmp = 0; 64 tmp = 0;
62 pp_i2c_send(0x51, RTC_CTRL1,tmp); 65 pp_i2c_send(RTC_ADDR, RTC_CTRL1, tmp);
63 66
64 /* read value of the Control 2 register - we'll need it to preserve alarm and timer interrupt assertion flags */ 67 /* read value of the Control 2 register - we'll need it to preserve alarm and timer interrupt assertion flags */
65 rv = i2c_readbytes(0x51,RTC_CTRL2,1,&tmp); 68 rv = i2c_readbytes(RTC_ADDR, RTC_CTRL2, 1, &tmp);
66 /* preserve alarm and timer interrupt flags */ 69 /* preserve alarm and timer interrupt flags */
67 tmp &= (RTC_TF | RTC_AF | RTC_TIE | RTC_AIE); 70 tmp &= (RTC_TF | RTC_AF | RTC_TIE | RTC_AIE);
68 pp_i2c_send(0x51, RTC_CTRL2,tmp); 71 pp_i2c_send(RTC_ADDR, RTC_CTRL2, tmp);
69} 72}
70 73
71int rtc_read_datetime(unsigned char* buf) 74int rtc_read_datetime(struct tm *tm)
72{ 75{
73 unsigned char tmp;
74 int read; 76 int read;
75 77 unsigned char buf[7];
76 /*RTC_E8564's slave address is 0x51*/ 78
77 read = i2c_readbytes(0x51,0x02,7,buf); 79 read = i2c_readbytes(RTC_ADDR, 0x02, sizeof(buf), buf);
78 80
79 /* swap wday and mday to be compatible with 81 /* convert from bcd, avoid getting extra bits */
80 * get_time() from firmware/common/timefuncs.c */ 82 tm->tm_sec = BCD2DEC(buf[0] & 0x7f);
81 tmp=buf[3]; 83 tm->tm_min = BCD2DEC(buf[1] & 0x7f);
82 buf[3]=buf[4]; 84 tm->tm_hour = BCD2DEC(buf[2] & 0x3f);
83 buf[4]=tmp; 85 tm->tm_mday = BCD2DEC(buf[3] & 0x3f);
84 86 tm->tm_wday = BCD2DEC(buf[4] & 0x3);
87 tm->tm_mon = BCD2DEC(buf[5] & 0x1f) - 1;
88 tm->tm_year = BCD2DEC(buf[6]) + 100;
89
85 return read; 90 return read;
86} 91}
87 92
88int rtc_write_datetime(unsigned char* buf) 93int rtc_write_datetime(const struct tm *tm)
89{ 94{
90 int i; 95 unsigned int i;
91 unsigned char tmp; 96 unsigned char buf[7];
92 97
93 /* swap wday and mday to be compatible with 98 buf[0] = tm->tm_sec;
94 * set_time() in firmware/common/timefuncs.c */ 99 buf[1] = tm->tm_min;
95 tmp=buf[3]; 100 buf[2] = tm->tm_hour;
96 buf[3]=buf[4]; 101 buf[3] = tm->tm_mday;
97 buf[4]=tmp; 102 buf[4] = tm->tm_wday;
98 103 buf[5] = tm->tm_mon + 1;
99 for (i=0;i<7;i++){ 104 buf[6] = tm->tm_year - 100;
100 pp_i2c_send(0x51, 0x02+i,buf[i]); 105
101 } 106 for (i = 0; i < sizeof(buf); i++)
107 pp_i2c_send(RTC_ADDR, 0x02 + i, DEC2BCD(buf[i]));
108
102 return 1; 109 return 1;
103} 110}
104 111
105void rtc_set_alarm(int h, int m) 112void rtc_set_alarm(int h, int m)
106{ 113{
107 unsigned char buf[4]={0}; 114 unsigned char buf[4] = {0};
108 int rv=0; 115 int i, rv;
109 int i=0; 116
110
111 /* clear alarm interrupt */ 117 /* clear alarm interrupt */
112 rv = i2c_readbytes(0x51,RTC_CTRL2,1,buf); 118 rv = i2c_readbytes(RTC_ADDR, RTC_CTRL2, 1, buf);
113 buf[0] &= RTC_AF; 119 buf[0] &= RTC_AF;
114 pp_i2c_send(0x51, RTC_CTRL2,buf[0]); 120 pp_i2c_send(RTC_ADDR, RTC_CTRL2, buf[0]);
115 121
116 /* prepare new alarm */ 122 /* prepare new alarm */
117 if( m >= 0 ) 123 if( m >= 0 )
118 buf[0] = (((m/10) << 4) | m%10); 124 buf[0] = DEC2BCD(m);
119 else 125 else
120 /* ignore minutes comparison query */ 126 /* ignore minutes comparison query */
121 buf[0] = RTC_AE; 127 buf[0] = RTC_AE;
122 128
123 if( h >= 0 ) 129 if( h >= 0 )
124 buf[1] = (((h/10) << 4) | h%10); 130 buf[1] = DEC2BCD(h);
125 else 131 else
126 /* ignore hours comparison query */ 132 /* ignore hours comparison query */
127 buf[1] = RTC_AE; 133 buf[1] = RTC_AE;
128 134
129 /* ignore day and wday */ 135 /* ignore day and wday */
130 buf[2] = RTC_AE; 136 buf[2] = RTC_AE;
131 buf[3] = RTC_AE; 137 buf[3] = RTC_AE;
132 138
133 /* write new alarm */ 139 /* write new alarm */
134 for(;i<4;i++) 140 for(i = 0; i < 4; i++)
135 pp_i2c_send(0x51, RTC_ALARM_MINUTES+i,buf[i]); 141 pp_i2c_send(RTC_ADDR, RTC_ALARM_MINUTES + i, buf[i]);
136 142
137 /* note: alarm is not enabled at the point */ 143 /* note: alarm is not enabled at the point */
138} 144}
139 145
140void rtc_get_alarm(int *h, int *m) 146void rtc_get_alarm(int *h, int *m)
141{ 147{
142 unsigned char buf[4]={0}; 148 unsigned char buf[4]={0};
143
144 /* get alarm preset */
145 i2c_readbytes(0x51, RTC_ALARM_MINUTES,4,buf);
146 149
147 *m = ((buf[0] >> 4) & 0x7)*10 + (buf[0] & 0x0f); 150 /* get alarm preset */
148 *h = ((buf[1] >> 4) & 0x3)*10 + (buf[1] & 0x0f); 151 i2c_readbytes(RTC_ADDR, RTC_ALARM_MINUTES, 4 ,buf);
149 152
153 *m = BCD2DEC(buf[0] & 0x7f);
154 *h = BCD2DEC(buf[0] & 0x3f);
150} 155}
151 156
152bool rtc_enable_alarm(bool enable) 157bool rtc_enable_alarm(bool enable)
@@ -157,10 +162,10 @@ bool rtc_enable_alarm(bool enable)
157 if(enable) 162 if(enable)
158 { 163 {
159 /* enable alarm interrupt */ 164 /* enable alarm interrupt */
160 rv = i2c_readbytes(0x51,RTC_CTRL2,1,&tmp); 165 rv = i2c_readbytes(RTC_ADDR, RTC_CTRL2, 1, &tmp);
161 tmp |= RTC_AIE; 166 tmp |= RTC_AIE;
162 tmp &= ~RTC_AF; 167 tmp &= ~RTC_AF;
163 pp_i2c_send(0x51, RTC_CTRL2,tmp); 168 pp_i2c_send(RTC_ADDR, RTC_CTRL2, tmp);
164 } 169 }
165 else 170 else
166 { 171 {
@@ -168,9 +173,9 @@ bool rtc_enable_alarm(bool enable)
168 if(rtc_lock_alarm_clear) 173 if(rtc_lock_alarm_clear)
169 /* lock disabling alarm before it was checked whether or not the unit was started by RTC alarm */ 174 /* lock disabling alarm before it was checked whether or not the unit was started by RTC alarm */
170 return false; 175 return false;
171 rv = i2c_readbytes(0x51,RTC_CTRL2,1,&tmp); 176 rv = i2c_readbytes(RTC_ADDR, RTC_CTRL2, 1, &tmp);
172 tmp &= ~(RTC_AIE | RTC_AF); 177 tmp &= ~(RTC_AIE | RTC_AF);
173 pp_i2c_send(0x51, RTC_CTRL2,tmp); 178 pp_i2c_send(RTC_ADDR, RTC_CTRL2, tmp);
174 } 179 }
175 180
176 return false; 181 return false;
@@ -186,21 +191,21 @@ bool rtc_check_alarm_started(bool release_alarm)
186 if (run_before) 191 if (run_before)
187 { 192 {
188 started = alarm_state; 193 started = alarm_state;
189 alarm_state &= ~release_alarm; 194 alarm_state &= ~release_alarm;
190 } 195 }
191 else 196 else
192 { 197 {
193 /* read Control 2 register which contains alarm flag */ 198 /* read Control 2 register which contains alarm flag */
194 rv = i2c_readbytes(0x51,RTC_CTRL2,1,&tmp); 199 rv = i2c_readbytes(RTC_ADDR, RTC_CTRL2, 1, &tmp);
195 200
196 alarm_state = started = ( (tmp & RTC_AF) && (tmp & RTC_AIE) ); 201 alarm_state = started = ( (tmp & RTC_AF) && (tmp & RTC_AIE) );
197 202
198 if(release_alarm && started) 203 if(release_alarm && started)
199 { 204 {
200 rv = i2c_readbytes(0x51,RTC_CTRL2,1,&tmp); 205 rv = i2c_readbytes(RTC_ADDR, RTC_CTRL2, 1, &tmp);
201 /* clear alarm interrupt enable and alarm flag */ 206 /* clear alarm interrupt enable and alarm flag */
202 tmp &= ~(RTC_AF | RTC_AIE); 207 tmp &= ~(RTC_AF | RTC_AIE);
203 pp_i2c_send(0x51, RTC_CTRL2,tmp); 208 pp_i2c_send(RTC_ADDR, RTC_CTRL2, tmp);
204 } 209 }
205 run_before = true; 210 run_before = true;
206 rtc_lock_alarm_clear = false; 211 rtc_lock_alarm_clear = false;
@@ -215,7 +220,8 @@ bool rtc_check_alarm_flag(void)
215 int rv=0; 220 int rv=0;
216 221
217 /* read Control 2 register which contains alarm flag */ 222 /* read Control 2 register which contains alarm flag */
218 rv = i2c_readbytes(0x51,RTC_CTRL2,1,&tmp); 223 rv = i2c_readbytes(RTC_ADDR, RTC_CTRL2, 1, &tmp);
219 224
220 return (tmp & RTC_AF); 225 return (tmp & RTC_AF);
221} 226}
227
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,
116 *year += 2000; 116 *year += 2000;
117} 117}
118 118
119int rtc_read_datetime(unsigned char* buf) 119int rtc_read_datetime(struct tm *tm)
120{ 120{
121 struct tm rtc_tm;
122 unsigned int sec,mon,mday,wday,year,hour,min; 121 unsigned int sec,mon,mday,wday,year,hour,min;
123 122
124 /* 123 /*
125 * Only the values that we read from the RTC are set. We leave 124 * Only the values that we read from the RTC are set. We leave
126 * tm_wday, tm_yday and tm_isdst untouched. Even though the 125 * tm_wday, tm_yday and tm_isdst untouched. Even though the
@@ -131,37 +130,32 @@ int rtc_read_datetime(unsigned char* buf)
131 130
132 year -= 2000; 131 year -= 2000;
133 132
134 rtc_tm.tm_sec = sec; 133 tm->tm_sec = sec;
135 rtc_tm.tm_min = min; 134 tm->tm_min = min;
136 rtc_tm.tm_hour = hour; 135 tm->tm_hour = hour;
137 rtc_tm.tm_mday = mday; 136 tm->tm_mday = mday;
138 rtc_tm.tm_wday = wday; 137 tm->tm_wday = wday;
139 /* Don't use centry, but start from year 1970 */ 138 /* Don't use centry, but start from year 1970 */
140 rtc_tm.tm_mon = mon; 139 tm->tm_mon = mon;
141 if (year <= 69) 140 if (year <= 69)
142 year += 100; 141 year += 100;
143 rtc_tm.tm_year = year; 142 tm->tm_year = year;
144 143
145 rtc_tm.tm_yday = 0; /* Not implemented for now */
146 rtc_tm.tm_isdst = -1; /* Not implemented for now */
147
148 (*((struct tm*)buf)) = rtc_tm;
149 return 1; 144 return 1;
150} 145}
151 146
152int rtc_write_datetime(unsigned char* buf) 147int rtc_write_datetime(const struct tm *tm)
153{ 148{
154 struct tm *rtc_tm = (struct tm*)buf;
155 unsigned int year, lval; 149 unsigned int year, lval;
156 150
157 year = rtc_tm->tm_year; 151 year = tm->tm_year;
158 /* Don't use centry, but start from year 1970 */ 152 /* Don't use centry, but start from year 1970 */
159 if (year > 69) 153 if (year > 69)
160 year -= 100; 154 year -= 100;
161 year += 2000; 155 year += 2000;
162 156
163 lval = jz_mktime(year, rtc_tm->tm_mon, rtc_tm->tm_mday, rtc_tm->tm_hour, 157 lval = jz_mktime(year, tm->tm_mon, tm->tm_mday, tm->tm_hour,
164 rtc_tm->tm_min, rtc_tm->tm_sec); 158 tm->tm_min, tm->tm_sec);
165 159
166 __cpm_start_rtc(); 160 __cpm_start_rtc();
167 udelay(100); 161 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)
110 110
111 /* for daily alarm, RPT5=RPT4=on, RPT1=RPT2=RPT3=off */ 111 /* for daily alarm, RPT5=RPT4=on, RPT1=RPT2=RPT3=off */
112 112
113 rtc_write(0x0e, 0x00); /* seconds 0 and RTP1 */ 113 rtc_write(0x0e, 0x00); /* seconds 0 and RTP1 */
114 rtc_write(0x0d, ((m / 10) << 4) | (m % 10)); /* minutes and RPT2 */ 114 rtc_write(0x0d, DEC2BCD(m); /* minutes and RPT2 */
115 rtc_write(0x0c, ((h / 10) << 4) | (h % 10)); /* hour and RPT3 */ 115 rtc_write(0x0c, DEC2BCD(h); /* hour and RPT3 */
116 rtc_write(0x0b, 0xc1); /* set date 01 and RPT4 and RTP5 */ 116 rtc_write(0x0b, 0xc1); /* set date 01 and RPT4 and RTP5 */
117 117
118 /* set month to 1, if it's invalid, the rtc does an alarm every second instead */ 118 /* set month to 1, if it's invalid, the rtc does an alarm every second instead */
119 data = rtc_read(0x0a); 119 data = rtc_read(0x0a);
@@ -128,10 +128,10 @@ void rtc_get_alarm(int *h, int *m)
128 unsigned char data; 128 unsigned char data;
129 129
130 data = rtc_read(0x0c); 130 data = rtc_read(0x0c);
131 *h = ((data & 0x30) >> 4) * 10 + (data & 0x0f); 131 *h = BCD2DEC(data & 0x3f);
132 132
133 data = rtc_read(0x0d); 133 data = rtc_read(0x0d);
134 *m = ((data & 0x70) >> 4) * 10 + (data & 0x0f); 134 *m = BCD2DEC(data & 0x7f);
135} 135}
136 136
137/* turn alarm on or off by setting the alarm flag enable */ 137/* 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)
250 return ret; 250 return ret;
251} 251}
252 252
253int rtc_read_datetime(unsigned char* buf) { 253int rtc_read_datetime(struct tm *tm)
254{
254 int rc; 255 int rc;
256 unsigned char buf[7];
257
258 rc = rtc_read_multiple(1, buf, sizeof(buf));
255 259
256 rc = rtc_read_multiple(1, buf, 7); 260 /* convert from bcd, avoid getting extra bits */
261 tm->tm_sec = BCD2DEC(buf[0] & 0x7f);
262 tm->tm_min = BCD2DEC(buf[1] & 0x7f);
263 tm->tm_hour = BCD2DEC(buf[2] & 0x3f);
264 tm->tm_wday = BCD2DEC(buf[3] & 0x3);
265 tm->tm_mday = BCD2DEC(buf[4] & 0x3f);
266 tm->tm_mon = BCD2DEC(buf[5] & 0x1f) - 1;
267 tm->tm_year = BCD2DEC(buf[6]) + 100;
257 268
258 /* Adjust weekday */ 269 /* Adjust weekday */
259 if(buf[3] == 7) 270 if (tm->tm_wday == 7)
260 buf[3]=0; 271 tm->tm_wday = 0;
261 272
262 return rc; 273 return rc;
263} 274}
264 275
265int rtc_write_datetime(unsigned char* buf) { 276int rtc_write_datetime(const struct tm *tm)
266 int i; 277{
278 unsigned int i;
267 int rc = 0; 279 int rc = 0;
268 280 unsigned char buf[7];
281
282 buf[0] = tm->tm_sec;
283 buf[1] = tm->tm_min;
284 buf[2] = tm->tm_hour;
285 buf[3] = tm->tm_wday;
286 buf[4] = tm->tm_mday;
287 buf[5] = tm->tm_mon + 1;
288 buf[6] = tm->tm_year - 100;
289
269 /* Adjust weekday */ 290 /* Adjust weekday */
270 if(buf[3] == 0) 291 if (buf[3] == 0)
271 buf[3] = 7; 292 buf[3] = 7;
272 293
273 for (i = 0; i < 7 ; i++) 294 for (i = 0; i < sizeof(buf) ;i++)
274 { 295 {
275 rc |= rtc_write(i+1, buf[i]); 296 rc |= rtc_write(i + 1, DEC2BCD(buf[i]));
276 } 297 }
277 rc |= rtc_write(8, 0x80); /* Out=1, calibration = 0 */ 298 rc |= rtc_write(8, 0x80); /* Out=1, calibration = 0 */
278 299
279 return rc; 300 return rc;
280} 301}
302
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 @@
46 #define RTC_BASE_YEAR 1970 46 #define RTC_BASE_YEAR 1970
47#endif 47#endif
48 48
49enum rtc_buffer_field_indexes
50{
51 RTC_I_SECONDS = 0,
52 RTC_I_MINUTES,
53 RTC_I_HOURS,
54 RTC_I_WEEKDAY,
55 RTC_I_DAY,
56 RTC_I_MONTH,
57 RTC_I_YEAR,
58 RTC_NUM_FIELDS,
59};
60
61enum rtc_registers_indexes 49enum rtc_registers_indexes
62{ 50{
63 RTC_REG_TIME = 0, 51 RTC_REG_TIME = 0,
@@ -82,26 +70,6 @@ static const unsigned char month_table[2][12] =
82 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, 70 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
83}; 71};
84 72
85static inline void to_bcd(unsigned char *bcd, const unsigned char *buf,
86 int len)
87{
88 while (len-- > 0)
89 {
90 unsigned char d = *buf++;
91 *bcd++ = ((d / 10) << 4) | (d % 10);
92 }
93}
94
95static inline void from_bcd(unsigned char *buf, const unsigned char *bcd,
96 int len)
97{
98 while (len-- > 0)
99 {
100 unsigned char d = *bcd++;
101 *buf++ = ((d >> 4) & 0x0f) * 10 + (d & 0xf);
102 }
103}
104
105/* Get number of leaps since the reference date of 1601/01/01 */ 73/* Get number of leaps since the reference date of 1601/01/01 */
106static int get_leap_count(int d) 74static int get_leap_count(int d)
107{ 75{
@@ -127,10 +95,10 @@ void rtc_init(void)
127 } 95 }
128} 96}
129 97
130int rtc_read_datetime(unsigned char* buf) 98int rtc_read_datetime(struct tm *tm)
131{ 99{
132 uint32_t regs[RTC_NUM_REGS]; 100 uint32_t regs[RTC_NUM_REGS];
133 int year, leap, month, day; 101 int year, leap, month, day, hour, min;
134 102
135 /* Read time, day, time - 2nd read of time should be the same or 103 /* Read time, day, time - 2nd read of time should be the same or
136 * greater */ 104 * greater */
@@ -147,19 +115,21 @@ int rtc_read_datetime(unsigned char* buf)
147 while (regs[RTC_REG_TIME2] < regs[RTC_REG_TIME]); 115 while (regs[RTC_REG_TIME2] < regs[RTC_REG_TIME]);
148 116
149 /* TOD: = 0 to 86399 */ 117 /* TOD: = 0 to 86399 */
150 buf[RTC_I_HOURS] = regs[RTC_REG_TIME] / 3600; 118 hour = regs[RTC_REG_TIME] / 3600;
151 regs[RTC_REG_TIME] -= buf[RTC_I_HOURS]*3600; 119 regs[RTC_REG_TIME] -= hour*3600;
120 tm->tm_hour = hour;
152 121
153 buf[RTC_I_MINUTES] = regs[RTC_REG_TIME] / 60; 122 min = regs[RTC_REG_TIME] / 60;
154 regs[RTC_REG_TIME] -= buf[RTC_I_MINUTES]*60; 123 regs[RTC_REG_TIME] -= min*60;
124 tm->tm_min = min;
155 125
156 buf[RTC_I_SECONDS] = regs[RTC_REG_TIME]; 126 tm->tm_sec = regs[RTC_REG_TIME];
157 127
158 /* DAY: 0 to 32767 */ 128 /* DAY: 0 to 32767 */
159 day = regs[RTC_REG_DAY] + RTC_BASE_DAY_COUNT; 129 day = regs[RTC_REG_DAY] + RTC_BASE_DAY_COUNT;
160 130
161 /* Weekday */ 131 /* Weekday */
162 buf[RTC_I_WEEKDAY] = (day + 1) % 7; /* 1601/01/01 = Monday */ 132 tm->tm_wday = (day + 1) % 7; /* 1601/01/01 = Monday */
163 133
164 /* Get number of leaps for today */ 134 /* Get number of leaps for today */
165 leap = get_leap_count(day); 135 leap = get_leap_count(day);
@@ -186,28 +156,23 @@ int rtc_read_datetime(unsigned char* buf)
186 day -= days; 156 day -= days;
187 } 157 }
188 158
189 buf[RTC_I_DAY] = day + 1; /* 1 to 31 */ 159 tm->tm_mday = day + 1; /* 1 to 31 */
190 buf[RTC_I_MONTH] = month + 1; /* 1 to 12 */ 160 tm->tm_mon = month; /* 0 to 11 */
191 buf[RTC_I_YEAR] = year % 100; 161 tm->tm_year = year % 100 + 100;
192
193 to_bcd(buf, buf, RTC_NUM_FIELDS);
194 162
195 return 7; 163 return 7;
196} 164}
197 165
198int rtc_write_datetime(unsigned char* buf) 166int rtc_write_datetime(const struct tm *tm)
199{ 167{
200 uint32_t regs[2]; 168 uint32_t regs[2];
201 unsigned char fld[RTC_NUM_FIELDS];
202 int year, leap, month, day, i, base_yearday; 169 int year, leap, month, day, i, base_yearday;
203 170
204 from_bcd(fld, buf, RTC_NUM_FIELDS); 171 regs[RTC_REG_TIME] = tm->tm_sec +
205 172 tm->tm_min*60 +
206 regs[RTC_REG_TIME] = fld[RTC_I_SECONDS] + 173 tm->tm_hour*3600;
207 fld[RTC_I_MINUTES]*60 +
208 fld[RTC_I_HOURS]*3600;
209 174
210 year = fld[RTC_I_YEAR]; 175 year = tm->tm_year - 100;
211 176
212 if (year < RTC_BASE_YEAR - 1900) 177 if (year < RTC_BASE_YEAR - 1900)
213 year += 2000; 178 year += 2000;
@@ -230,18 +195,18 @@ int rtc_write_datetime(unsigned char* buf)
230 /* Find the number of days passed this year up to the 1st of the 195 /* Find the number of days passed this year up to the 1st of the
231 * month. */ 196 * month. */
232 leap = is_leap_year(year); 197 leap = is_leap_year(year);
233 month = fld[RTC_I_MONTH] - 1; 198 month = tm->tm_mon;
234 199
235 for (i = 0; i < month; i++) 200 for (i = 0; i < month; i++)
236 { 201 {
237 day += month_table[leap][i]; 202 day += month_table[leap][i];
238 } 203 }
239 204
240 regs[RTC_REG_DAY] = day + fld[RTC_I_DAY] - 1 - base_yearday; 205 regs[RTC_REG_DAY] = day + tm->tm_mday - 1 - base_yearday;
241 206
242 if (mc13783_write_regset(rtc_registers, regs, 2) == 2) 207 if (mc13783_write_regset(rtc_registers, regs, 2) == 2)
243 { 208 {
244 return RTC_NUM_FIELDS; 209 return 7;
245 } 210 }
246 211
247 return 0; 212 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)
124 124
125} 125}
126 126
127int rtc_read_datetime(unsigned char* buf) 127int rtc_read_datetime(struct tm *tm)
128{ 128{
129 int i; 129 unsigned int i;
130 unsigned char v[7]; 130 int rc;
131 unsigned char buf[7];
131 132
132 i = sw_i2c(SW_I2C_READ, RTC_CMD_DATA, v, 7); 133 rc = sw_i2c(SW_I2C_READ, RTC_CMD_DATA, buf, sizeof(buf));
133 134
134 v[4] &= 0x3f; /* mask out p.m. flag */ 135 buf[4] &= 0x3f; /* mask out p.m. flag */
135 136
136 for(i=0; i<7; i++) 137 for (i = 0; i < sizeof(buf); i++)
137 buf[i] = v[6-i]; 138 buf[i] = BCD2DEC(buf[i]);
138 139
139 return i; 140 tm->tm_sec = buf[6];
141 tm->tm_min = buf[5];
142 tm->tm_hour = buf[4];
143 tm->tm_wday = buf[3];
144 tm->tm_mday = buf[2];
145 tm->tm_mon = buf[1] - 1;
146 tm->tm_year = buf[0] + 100;
147
148 return rc;
140} 149}
141 150
142int rtc_write_datetime(unsigned char* buf) 151int rtc_write_datetime(const struct tm *tm)
143{ 152{
144 int i; 153 unsigned int i;
145 unsigned char v[7]; 154 int rc;
155 unsigned char buf[7];
146 156
147 for(i=0; i<7; i++) 157 buf[6] = tm->tm_sec;
148 v[i]=buf[6-i]; 158 buf[5] = tm->tm_min;
149 159 buf[4] = tm->tm_hour;
150 i = sw_i2c(SW_I2C_WRITE, RTC_CMD_DATA, v, 7); 160 buf[3] = tm->tm_wday;
151 161 buf[2] = tm->tm_mday;
152 return i; 162 buf[1] = tm->tm_mon + 1;
163 buf[0] = tm->tm_year - 100;
164
165 for (i = 0; i < sizeof(buf); i++)
166 buf[i] = DEC2BCD(buf[i]);
167
168 rc = sw_i2c(SW_I2C_WRITE, RTC_CMD_DATA, buf, sizeof(buf));
169
170 return rc;
153} 171}
154 172
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)
36 rtc_check_alarm_started(false); 36 rtc_check_alarm_started(false);
37} 37}
38 38
39int rtc_read_datetime(unsigned char* buf) 39int rtc_read_datetime(struct tm *tm)
40{ 40{
41 return pcf50605_read_multiple(0x0a, buf, 7); 41 unsigned int i;
42 int rc;
43 unsigned char buf[7];
44 rc = pcf50605_read_multiple(0x0a, buf, sizeof(buf));
45
46 for (i = 0; i < sizeof(buf); i++)
47 buf[i] = BCD2DEC(buf[i]);
48
49 tm->tm_sec = buf[0];
50 tm->tm_min = buf[1];
51 tm->tm_hour = buf[2];
52 tm->tm_wday = buf[3];
53 tm->tm_mday = buf[4];
54 tm->tm_mon = buf[5] - 1;
55 tm->tm_year = buf[6] + 100;
56
57 return rc;
42} 58}
43 59
44int rtc_write_datetime(unsigned char* buf) 60int rtc_write_datetime(const struct tm *tm)
45{ 61{
46 pcf50605_write_multiple(0x0a, buf, 7); 62 unsigned int i;
63 unsigned char buf[7];
64
65 buf[0] = tm->tm_sec;
66 buf[1] = tm->tm_min;
67 buf[2] = tm->tm_hour;
68 buf[3] = tm->tm_wday;
69 buf[4] = tm->tm_mday;
70 buf[5] = tm->tm_mon + 1;
71 buf[6] = tm->tm_year - 100;
72
73 for (i = 0; i < sizeof(buf); i++)
74 buf[i] = DEC2BCD(buf[i]);
75
76 pcf50605_write_multiple(0x0a, buf, sizeof(buf));
77
47 return 1; 78 return 1;
48} 79}
49 80
@@ -121,17 +152,17 @@ void rtc_set_alarm(int h, int m)
121 /* Set us to wake at the first second of the specified time */ 152 /* Set us to wake at the first second of the specified time */
122 pcf50605_write(0x11, 0); 153 pcf50605_write(0x11, 0);
123 /* Convert to BCD */ 154 /* Convert to BCD */
124 pcf50605_write(0x12, ((m/10) << 4) | m%10); 155 pcf50605_write(0x12, DEC2BCD(m));
125 pcf50605_write(0x13, ((h/10) << 4) | h%10); 156 pcf50605_write(0x13, DEC2BCD(h));
126} 157}
127 158
128void rtc_get_alarm(int *h, int *m) 159void rtc_get_alarm(int *h, int *m)
129{ 160{
130 char buf[2]; 161 char buf[2];
131 162
132 pcf50605_read_multiple(0x12, buf, 2); 163 pcf50605_read_multiple(0x12, buf, sizeof(buf));
133 /* Convert from BCD */ 164 /* Convert from BCD */
134 *m = ((buf[0] >> 4) & 0x7)*10 + (buf[0] & 0x0f); 165 *m = BCD2DEC(buf[0]);
135 *h = ((buf[1] >> 4) & 0x3)*10 + (buf[1] & 0x0f); 166 *h = BCD2DEC(buf[1]);
136} 167}
137 168
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 @@
24#include "kernel.h" 24#include "kernel.h"
25#include "system.h" 25#include "system.h"
26#include "pcf50606.h" 26#include "pcf50606.h"
27#include <stdbool.h>
28 27
29void rtc_init(void) 28void rtc_init(void)
30{ 29{
31} 30}
32 31
33int rtc_read_datetime(unsigned char* buf) { 32int rtc_read_datetime(struct tm *tm)
34 int rc; 33{
35 int oldlevel = disable_irq_save(); 34 unsigned int i;
36 35 int rc, oldlevel;
37 rc = pcf50606_read_multiple(0x0a, buf, 7); 36 unsigned char buf[7];
37
38 oldlevel = disable_irq_save();
39
40 rc = pcf50606_read_multiple(0x0a, buf, sizeof(buf));
38 41
39 restore_irq(oldlevel); 42 restore_irq(oldlevel);
43
44 for (i = 0; i < sizeof(buf); i++)
45 buf[i] = BCD2DEC(buf[i]);
46
47 tm->tm_sec = buf[0];
48 tm->tm_min = buf[1];
49 tm->tm_hour = buf[2];
50 tm->tm_wday = buf[3];
51 tm->tm_mday = buf[4];
52 tm->tm_mon = buf[5] - 1;
53#ifdef IRIVER_H300_SERIES
54 /* Special kludge to coexist with the iriver firmware. The iriver firmware
55 stores the date as 1965+nn, and allows a range of 1980..2064. We use
56 1964+nn here to make leap years work correctly, so the date will be one
57 year off in the iriver firmware but at least won't be reset anymore. */
58 tm->tm_year = buf[6] + 64;
59#else /* Not IRIVER_H300_SERIES */
60 tm->tm_year = buf[6] + 100;
61#endif /* IRIVER_H300_SERIES */
62
40 return rc; 63 return rc;
41} 64}
42 65
43int rtc_write_datetime(unsigned char* buf) { 66int rtc_write_datetime(const struct tm *tm)
44 int rc; 67{
45 int oldlevel = disable_irq_save(); 68 unsigned int i;
46 69 int rc, oldlevel;
47 rc = pcf50606_write_multiple(0x0a, buf, 7); 70 unsigned char buf[7];
71
72 buf[0] = tm->tm_sec;
73 buf[1] = tm->tm_min;
74 buf[2] = tm->tm_hour;
75 buf[3] = tm->tm_wday;
76 buf[4] = tm->tm_mday;
77 buf[5] = tm->tm_mon + 1;
78#ifdef IRIVER_H300_SERIES
79 /* Iriver firmware compatibility kludge, see rtc_read_datetime(). */
80 buf[6] = tm->tm_year - 64;
81#else /* Not IRIVER_H300_SERIES */
82 buf[6] = tm->tm_year - 100;
83#endif /* IRIVER_H300_SERIES */
84
85 for (i = 0; i < sizeof(buf); i++)
86 buf[i] = DEC2BCD(buf[i]);
87
88 oldlevel = disable_irq_save();
89
90 rc = pcf50606_write_multiple(0x0a, buf, sizeof(buf));
48 91
49 restore_irq(oldlevel); 92 restore_irq(oldlevel);
50 93
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 @@
22#include "config.h" 22#include "config.h"
23#include "spi.h" 23#include "spi.h"
24#include "rtc.h" 24#include "rtc.h"
25#include <stdbool.h> 25
26/* Choose one of: */ 26/* Choose one of: */
27#define ADDR_READ 0x04 27#define ADDR_READ 0x04
28#define ADDR_WRITE 0x00 28#define ADDR_WRITE 0x00
29/* and one of: */ 29/* and one of: */
30#define ADDR_ONE 0x08 30#define ADDR_ONE 0x08
31#define ADDR_BURST 0x00 31#define ADDR_BURST 0x00
32
32void rtc_init(void) 33void rtc_init(void)
33{ 34{
34} 35}
35 36
36int rtc_read_datetime(unsigned char* buf) 37int rtc_read_datetime(struct tm *tm)
37{ 38{
39 unsigned int i;
40 unsigned char buf[7];
38 char command = ADDR_READ|ADDR_BURST; /* burst read from the start of the time/date reg */ 41 char command = ADDR_READ|ADDR_BURST; /* burst read from the start of the time/date reg */
39 spi_block_transfer(SPI_target_RX5X348AB, &command, 1, buf, 7); 42
43 spi_block_transfer(SPI_target_RX5X348AB, &command, 1, buf, sizeof(buf));
44
45 for (i = 0; i < sizeof(buf); i++)
46 buf[i] = BCD2DEC(buf[i]);
47
48 tm->tm_sec = buf[0];
49 tm->tm_min = buf[1];
50 tm->tm_hour = buf[2];
51 tm->tm_wday = buf[3];
52 tm->tm_mday = buf[4];
53 tm->tm_mon = buf[5] - 1;
54 tm->tm_year = buf[6] + 100;
55
40 return 1; 56 return 1;
41} 57}
42int rtc_write_datetime(unsigned char* buf) 58
59int rtc_write_datetime(const struct tm *tm)
43{ 60{
61 unsigned int i;
44 char command = ADDR_WRITE|ADDR_BURST; /* burst read from the start of the time/date reg */ 62 char command = ADDR_WRITE|ADDR_BURST; /* burst read from the start of the time/date reg */
45 char data[8]; 63 unsigned char buf[8];
46 int i; 64
47 data[0] = command; 65 buf[0] = command;
48 for (i=1;i<8;i++) 66 buf[1] = tm->tm_sec;
49 data[i] = buf[i-1]; 67 buf[2] = tm->tm_min;
50 spi_block_transfer(SPI_target_RX5X348AB, data, 8, NULL, 0); 68 buf[3] = tm->tm_hour;
69 buf[4] = tm->tm_wday;
70 buf[5] = tm->tm_mday;
71 buf[6] = tm->tm_mon + 1;
72 buf[7] = tm->tm_year - 100;
73
74 /* don't encode the comand byte */
75 for (i = 1; i < sizeof(buf); i++)
76 buf[i] = DEC2BCD(buf[i]);
77
78 spi_block_transfer(SPI_target_RX5X348AB, buf, sizeof(buf), NULL, 0);
51 return 1; 79 return 1;
52} 80}
81
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)
58{ 58{
59} 59}
60 60
61int rtc_read_datetime(unsigned char* buf) 61int rtc_read_datetime(struct tm *tm)
62{ 62{
63 unsigned char data[7]; 63 unsigned char buf[7];
64 int i, ret; 64 int i, ret;
65 65
66 ret = i2c_read(RTC_ADDR | (REALTIME_DATA1 << 1), -1, sizeof(data), data); 66 ret = i2c_read(RTC_ADDR | (REALTIME_DATA1 << 1), -1, sizeof(buf), buf);
67 reverse_bits(data, sizeof(data)); 67 reverse_bits(buf, sizeof(buf));
68 68
69 buf[4] &= 0x3f; /* mask out p.m. flag */ 69 buf[4] &= 0x3f; /* mask out p.m. flag */
70 70
71 for (i = 0; i < 7; i++) { 71 for (i = 0; i < sizeof(buf); i++)
72 buf[i] = data[6 - i]; 72 BCD2DEC(buf[i]);
73 } 73
74 tm->tm_sec = buf[6];
75 tm->tm_min = buf[5];
76 tm->tm_hour = buf[4];
77 tm->tm_wday = buf[3];
78 tm->tm_mday = buf[2];
79 tm->tm_mon = buf[1] - 1;
80 tm->tm_year = buf[0] + 100;
74 81
75 return ret; 82 return ret;
76} 83}
77 84
78int rtc_write_datetime(unsigned char* buf) 85int rtc_write_datetime(const struct tm *tm)
79{ 86{
80 unsigned char data[7]; 87 unsigned char buf[7];
81 int i, ret; 88 int i, ret;
82 89
83 for (i = 0; i < 7; i++) { 90 buf[6] = tm->tm_sec;
84 data[i] = buf[6 - i]; 91 buf[5] = tm->tm_min;
85 } 92 buf[4] = tm->tm_hour;
86 93 buf[3] = tm->tm_wday;
87 reverse_bits(data, sizeof(data)); 94 buf[2] = tm->tm_mday;
88 ret = i2c_write(RTC_ADDR | (REALTIME_DATA1 << 1), -1, sizeof(data), data); 95 buf[1] = tm->tm_mon + 1;
89 96 buf[0] = tm->tm_year - 100;
97
98 for (i = 0; i < sizeof(buf); i++)
99 DEC2BCD(buf[i]);
100
101 reverse_bits(buf, sizeof(buf));
102 ret = i2c_write(RTC_ADDR | (REALTIME_DATA1 << 1), -1, sizeof(buf), buf);
103
90 return ret; 104 return ret;
91} 105}
92 106
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)
30 RTCCON |= 1; 30 RTCCON |= 1;
31} 31}
32 32
33int rtc_read_datetime(unsigned char* buf) 33int rtc_read_datetime(struct tm *tm)
34{ 34{
35 buf[0] = BCDSEC; 35 tm->tm_sec = BCD2DEC(BCDSEC);
36 buf[1] = BCDMIN; 36 tm->tm_min = BCD2DEC(BCDMIN);
37 buf[2] = BCDHOUR; 37 tm->tm_hour = BCD2DEC(BCDHOUR);
38 buf[3] = BCDDAY-1; /* timefuncs wants 0..6 for wday */ 38 tm->tm_wday = BCD2DEC(BCDDAY) - 1; /* timefuncs wants 0..6 for wday */
39 buf[4] = BCDDATE; 39 tm->tm_mday = BCD2DEC(BCDDATE);
40 buf[5] = BCDMON; 40 tm->tm_mon = BCD2DEC(BCDMON) - 1;
41 buf[6] = BCDYEAR; 41 tm->tm_year = BCD2DEC(BCDYEAR) + 100;
42 42
43 return 1; 43 return 1;
44} 44}
45 45
46int rtc_write_datetime(unsigned char* buf) 46int rtc_write_datetime(const struct tm *tm)
47{ 47{
48 BCDSEC = buf[0]; 48 BCDSEC = DEC2BCD(tm->tm_sec);
49 BCDMIN = buf[1]; 49 BCDMIN = DEC2BCD(tm->tm_min);
50 BCDHOUR = buf[2]; 50 BCDHOUR = DEC2BCD(tm->tm_hour);
51 BCDDAY = buf[3]+1; /* chip wants 1..7 for wday */ 51 BCDDAY = DEC2BCD(tm->tm_wday) + 1; /* chip wants 1..7 for wday */
52 BCDDATE = buf[4]; 52 BCDDATE = DEC2BCD(tm->tm_mday);
53 BCDMON = buf[5]; 53 BCDMON = DEC2BCD(tm->tm_mon + 1);
54 BCDYEAR = buf[6]; 54 BCDYEAR = DEC2BCD(tm->tm_year - 100);
55 55
56 return 1; 56 return 1;
57} 57}
@@ -88,15 +88,15 @@ bool rtc_check_alarm_flag(void)
88/* set alarm time registers to the given time (repeat once per day) */ 88/* set alarm time registers to the given time (repeat once per day) */
89void rtc_set_alarm(int h, int m) 89void rtc_set_alarm(int h, int m)
90{ 90{
91 ALMMIN=(((m / 10) << 4) | (m % 10)) & 0x7f; /* minutes */ 91 ALMMIN = DEC2BCD(m); /* minutes */
92 ALMHOUR=(((h / 10) << 4) | (h % 10)) & 0x3f; /* hour */ 92 ALMHOUR = DEC2BCD(h); /* hour */
93} 93}
94 94
95/* read out the current alarm time */ 95/* read out the current alarm time */
96void rtc_get_alarm(int *h, int *m) 96void rtc_get_alarm(int *h, int *m)
97{ 97{
98 *m=((ALMMIN & 0x70) >> 4) * 10 + (ALMMIN & 0x0f); 98 *m = BCD2DEC(ALMMIN);
99 *h=((ALMHOUR & 0x30) >> 4) * 10 + (ALMHOUR & 0x0f); 99 *h = BCD2DEC(ALMHOUR);
100} 100}
101 101
102/* turn alarm on or off by setting the alarm flag enable 102/* turn alarm on or off by setting the alarm flag enable
diff --git a/firmware/export/rtc.h b/firmware/export/rtc.h
index 6d21b1f37f..57853f28cc 100644
--- a/firmware/export/rtc.h
+++ b/firmware/export/rtc.h
@@ -24,13 +24,19 @@
24#include <stdbool.h> 24#include <stdbool.h>
25#include "system.h" 25#include "system.h"
26#include "config.h" 26#include "config.h"
27#include "time.h"
28
29/* Macros used to convert to and from BCD, used in various rtc drivers
30 this is the wrong place but misc.h is in apps... */
31#define BCD2DEC(X) (((((X)>>4) & 0x0f) * 10) + ((X) & 0xf))
32#define DEC2BCD(X) ((((X)/10)<<4) | ((X)%10))
27 33
28#if CONFIG_RTC 34#if CONFIG_RTC
29 35
30/* Common functions for all targets */ 36/* Common functions for all targets */
31void rtc_init(void); 37void rtc_init(void);
32int rtc_read_datetime(unsigned char* buf); 38int rtc_read_datetime(struct tm *tm);
33int rtc_write_datetime(unsigned char* buf); 39int rtc_write_datetime(const struct tm *tm);
34 40
35#if CONFIG_RTC == RTC_M41ST84W 41#if CONFIG_RTC == RTC_M41ST84W
36 42
@@ -53,3 +59,4 @@ bool rtc_check_alarm_flag(void);
53#endif /* CONFIG_RTC */ 59#endif /* CONFIG_RTC */
54 60
55#endif 61#endif
62
diff --git a/firmware/include/timefuncs.h b/firmware/include/timefuncs.h
index ab566d9e5f..f51fa996cc 100644
--- a/firmware/include/timefuncs.h
+++ b/firmware/include/timefuncs.h
@@ -35,3 +35,4 @@ time_t mktime(struct tm *t);
35#endif 35#endif
36 36
37#endif /* _TIMEFUNCS_H_ */ 37#endif /* _TIMEFUNCS_H_ */
38
diff --git a/uisimulator/common/stubs.c b/uisimulator/common/stubs.c
index cb208bfeab..2218c497f8 100644
--- a/uisimulator/common/stubs.c
+++ b/uisimulator/common/stubs.c
@@ -142,25 +142,17 @@ int rtc_write(int address, int value)
142 return 0; 142 return 0;
143} 143}
144 144
145int rtc_read_datetime(unsigned char* buf) 145int rtc_read_datetime(struct tm *tm)
146{ 146{
147 time_t now = time(NULL); 147 time_t now = time(NULL);
148 struct tm *teem = localtime(&now); 148 *tm = *localtime(&now);
149
150 buf[0] = (teem->tm_sec%10) | ((teem->tm_sec/10) << 4);
151 buf[1] = (teem->tm_min%10) | ((teem->tm_min/10) << 4);
152 buf[2] = (teem->tm_hour%10) | ((teem->tm_hour/10) << 4);
153 buf[3] = (teem->tm_wday);
154 buf[4] = (teem->tm_mday%10) | ((teem->tm_mday/10) << 4);
155 buf[5] = ((teem->tm_year-100)%10) | (((teem->tm_year-100)/10) << 4);
156 buf[6] = ((teem->tm_mon+1)%10) | (((teem->tm_mon+1)/10) << 4);
157 149
158 return 0; 150 return 0;
159} 151}
160 152
161int rtc_write_datetime(unsigned char* buf) 153int rtc_write_datetime(const struct tm *tm)
162{ 154{
163 (void)buf; 155 (void)tm;
164 return 0; 156 return 0;
165} 157}
166 158