summaryrefslogtreecommitdiff
path: root/firmware/drivers/rtc/rtc_mc13783.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/drivers/rtc/rtc_mc13783.c')
-rw-r--r--firmware/drivers/rtc/rtc_mc13783.c77
1 files changed, 21 insertions, 56 deletions
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;