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 | |
parent | 66d5bd7cf8c10971578c643c16f72b51df4a1ddf (diff) | |
download | rockbox-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.c | 77 | ||||
-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 | ||||
-rw-r--r-- | firmware/export/rtc.h | 11 | ||||
-rw-r--r-- | firmware/include/timefuncs.h | 1 | ||||
-rw-r--r-- | uisimulator/common/stubs.c | 16 |
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 | ||
31 | static struct tm tm; | 30 | static struct tm tm; |
32 | #endif /* !defined SIMULATOR || !CONFIG_RTC */ | ||
33 | 31 | ||
34 | #if !CONFIG_RTC | 32 | #if !CONFIG_RTC |
35 | static void fill_default_tm(struct tm *tm) | 33 | static void fill_default_tm(struct tm *tm) |
@@ -62,7 +60,6 @@ bool valid_time(const struct tm *tm) | |||
62 | 60 | ||
63 | struct tm *get_time(void) | 61 | struct 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 | ||
116 | int set_time(const struct tm *tm) | 82 | int 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 | ||
197 | void set_day_of_week(struct tm *tm) | 143 | void 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 */ |
45 | static unsigned int days_in_month[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; | 42 | static 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 | ||
59 | int rtc_read_datetime(unsigned char* buf) | 56 | int 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 | ||
137 | int rtc_write_datetime(unsigned char* buf) | 131 | int 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 | ||
118 | int rtc_read_datetime(unsigned char* buf) | 118 | int 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 | ||
129 | int rtc_write_datetime(unsigned char* buf) | 137 | int 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 | ||
71 | int rtc_read_datetime(unsigned char* buf) | 74 | int 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 | ||
88 | int rtc_write_datetime(unsigned char* buf) | 93 | int 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 | ||
105 | void rtc_set_alarm(int h, int m) | 112 | void 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 | ||
140 | void rtc_get_alarm(int *h, int *m) | 146 | void 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 | ||
152 | bool rtc_enable_alarm(bool enable) | 157 | bool 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 | ||
119 | int rtc_read_datetime(unsigned char* buf) | 119 | int 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 | ||
152 | int rtc_write_datetime(unsigned char* buf) | 147 | int 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 | ||
253 | int rtc_read_datetime(unsigned char* buf) { | 253 | int 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 | ||
265 | int rtc_write_datetime(unsigned char* buf) { | 276 | int 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 | ||
49 | enum 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 | |||
61 | enum rtc_registers_indexes | 49 | enum 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 | ||
85 | static 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 | |||
95 | static 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 */ |
106 | static int get_leap_count(int d) | 74 | static int get_leap_count(int d) |
107 | { | 75 | { |
@@ -127,10 +95,10 @@ void rtc_init(void) | |||
127 | } | 95 | } |
128 | } | 96 | } |
129 | 97 | ||
130 | int rtc_read_datetime(unsigned char* buf) | 98 | int 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 | ||
198 | int rtc_write_datetime(unsigned char* buf) | 166 | int 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 | ||
127 | int rtc_read_datetime(unsigned char* buf) | 127 | int 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 | ||
142 | int rtc_write_datetime(unsigned char* buf) | 151 | int 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 | ||
39 | int rtc_read_datetime(unsigned char* buf) | 39 | int 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 | ||
44 | int rtc_write_datetime(unsigned char* buf) | 60 | int 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 | ||
128 | void rtc_get_alarm(int *h, int *m) | 159 | void 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 | ||
29 | void rtc_init(void) | 28 | void rtc_init(void) |
30 | { | 29 | { |
31 | } | 30 | } |
32 | 31 | ||
33 | int rtc_read_datetime(unsigned char* buf) { | 32 | int 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 | ||
43 | int rtc_write_datetime(unsigned char* buf) { | 66 | int 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 | |||
32 | void rtc_init(void) | 33 | void rtc_init(void) |
33 | { | 34 | { |
34 | } | 35 | } |
35 | 36 | ||
36 | int rtc_read_datetime(unsigned char* buf) | 37 | int 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 | } |
42 | int rtc_write_datetime(unsigned char* buf) | 58 | |
59 | int 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 | ||
61 | int rtc_read_datetime(unsigned char* buf) | 61 | int 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 | ||
78 | int rtc_write_datetime(unsigned char* buf) | 85 | int 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 | ||
33 | int rtc_read_datetime(unsigned char* buf) | 33 | int 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 | ||
46 | int rtc_write_datetime(unsigned char* buf) | 46 | int 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) */ |
89 | void rtc_set_alarm(int h, int m) | 89 | void 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 */ |
96 | void rtc_get_alarm(int *h, int *m) | 96 | void 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 */ |
31 | void rtc_init(void); | 37 | void rtc_init(void); |
32 | int rtc_read_datetime(unsigned char* buf); | 38 | int rtc_read_datetime(struct tm *tm); |
33 | int rtc_write_datetime(unsigned char* buf); | 39 | int 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 | ||
145 | int rtc_read_datetime(unsigned char* buf) | 145 | int 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 | ||
161 | int rtc_write_datetime(unsigned char* buf) | 153 | int 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 | ||