diff options
author | Amaury Pouly <pamaury@rockbox.org> | 2011-12-31 13:35:45 +0000 |
---|---|---|
committer | Amaury Pouly <pamaury@rockbox.org> | 2011-12-31 13:35:45 +0000 |
commit | 094e62a528e95677a16a9465a1decfdc045e7197 (patch) | |
tree | 03018b3aebf4c0938f2b3e0936233d036ea54829 /firmware/drivers/rtc/rtc_imx233.c | |
parent | 162fdeaa979074a0ad9711b94571894d737d3efe (diff) | |
download | rockbox-094e62a528e95677a16a9465a1decfdc045e7197.tar.gz rockbox-094e62a528e95677a16a9465a1decfdc045e7197.zip |
imx233/fuze+: implement rtc (time only, alarm still to implement)
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@31473 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/drivers/rtc/rtc_imx233.c')
-rw-r--r-- | firmware/drivers/rtc/rtc_imx233.c | 142 |
1 files changed, 138 insertions, 4 deletions
diff --git a/firmware/drivers/rtc/rtc_imx233.c b/firmware/drivers/rtc/rtc_imx233.c index 4368610875..9e62476be6 100644 --- a/firmware/drivers/rtc/rtc_imx233.c +++ b/firmware/drivers/rtc/rtc_imx233.c | |||
@@ -22,21 +22,155 @@ | |||
22 | #include "system.h" | 22 | #include "system.h" |
23 | #include "rtc.h" | 23 | #include "rtc.h" |
24 | #include "timefuncs.h" | 24 | #include "timefuncs.h" |
25 | #include "rtc-imx233.h" | ||
26 | |||
27 | #if defined(SANSA_FUZEPLUS) | ||
28 | #define SECS_ADJUST 315532800 /* seconds between 1970-1-1 and 1980-1-1 */ | ||
29 | #else | ||
30 | #define SECS_ADJUST 0 | ||
31 | #endif | ||
32 | |||
33 | #define MINUTE_SECONDS 60 | ||
34 | #define HOUR_SECONDS 3600 | ||
35 | #define DAY_SECONDS 86400 | ||
36 | #define WEEK_SECONDS 604800 | ||
37 | #define YEAR_SECONDS 31536000 | ||
38 | #define LEAP_YEAR_SECONDS 31622400 | ||
39 | |||
40 | /* Days in each month */ | ||
41 | static unsigned int days_in_month[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; | ||
42 | |||
43 | static inline bool is_leapyear(int year) | ||
44 | { | ||
45 | if( ((year%4)==0) && (((year%100)!=0) || ((year%400)==0)) ) | ||
46 | return true; | ||
47 | else | ||
48 | return false; | ||
49 | } | ||
25 | 50 | ||
26 | void rtc_init(void) | 51 | void rtc_init(void) |
27 | { | 52 | { |
53 | imx233_rtc_init(); | ||
28 | } | 54 | } |
29 | 55 | ||
30 | int rtc_read_datetime(struct tm *tm) | 56 | int rtc_read_datetime(struct tm *tm) |
31 | { | 57 | { |
32 | (void) tm; | 58 | uint32_t seconds = imx233_rtc_read_seconds() - SECS_ADJUST; |
33 | return -1; | 59 | #ifdef SANSA_FUZEPLUS |
60 | /* The OF uses PERSISTENT2 register to keep the adjustment and only changes | ||
61 | * SECONDS if necessary. */ | ||
62 | seconds += imx233_rtc_read_persistent(2); | ||
63 | #else | ||
64 | /* The Freescale recommended way of keeping time is the number of seconds | ||
65 | * since 00:00 1/1/1980 */ | ||
66 | #endif | ||
67 | |||
68 | /* Convert seconds since 00:00 1/1/xxxx (xxxx=year) */ | ||
69 | |||
70 | /* weekday */ | ||
71 | tm->tm_wday = ((seconds % WEEK_SECONDS) / DAY_SECONDS + 2) % 7; | ||
72 | |||
73 | /* Year */ | ||
74 | int year = 1980; | ||
75 | while(seconds >= LEAP_YEAR_SECONDS) | ||
76 | { | ||
77 | if(is_leapyear(year)) | ||
78 | seconds -= LEAP_YEAR_SECONDS; | ||
79 | else | ||
80 | seconds -= YEAR_SECONDS; | ||
81 | |||
82 | year++; | ||
83 | } | ||
84 | |||
85 | if(is_leapyear(year)) | ||
86 | days_in_month[1] = 29; | ||
87 | else | ||
88 | { | ||
89 | days_in_month[1] = 28; | ||
90 | if(seconds>YEAR_SECONDS) | ||
91 | { | ||
92 | year++; | ||
93 | seconds -= YEAR_SECONDS; | ||
94 | } | ||
95 | } | ||
96 | tm->tm_year = year % 100 + 100; | ||
97 | |||
98 | /* Month */ | ||
99 | for(int i = 0; i < 12; i++) | ||
100 | { | ||
101 | if(seconds < days_in_month[i] * DAY_SECONDS) | ||
102 | { | ||
103 | tm->tm_mon = i; | ||
104 | break; | ||
105 | } | ||
106 | |||
107 | seconds -= days_in_month[i] * DAY_SECONDS; | ||
108 | } | ||
109 | |||
110 | /* Month Day */ | ||
111 | int mday = seconds / DAY_SECONDS; | ||
112 | seconds -= mday * DAY_SECONDS; | ||
113 | tm->tm_mday = mday + 1; /* 1 ... 31 */ | ||
114 | |||
115 | /* Hour */ | ||
116 | int hour = seconds / HOUR_SECONDS; | ||
117 | seconds -= hour*HOUR_SECONDS; | ||
118 | tm->tm_hour = hour; | ||
119 | |||
120 | /* Minute */ | ||
121 | int min = seconds / MINUTE_SECONDS; | ||
122 | seconds -= min*MINUTE_SECONDS; | ||
123 | tm->tm_min = min; | ||
124 | |||
125 | /* Second */ | ||
126 | tm->tm_sec = seconds; | ||
127 | |||
128 | return 0; | ||
34 | } | 129 | } |
35 | 130 | ||
36 | int rtc_write_datetime(const struct tm *tm) | 131 | int rtc_write_datetime(const struct tm *tm) |
37 | { | 132 | { |
38 | (void) tm; | 133 | int i, year; |
39 | return -1; | 134 | unsigned int year_days = 0; |
135 | unsigned int month_days = 0; | ||
136 | unsigned int seconds = 0; | ||
137 | |||
138 | year = 2000 + tm->tm_year - 100; | ||
139 | |||
140 | if(is_leapyear(year)) | ||
141 | days_in_month[1] = 29; | ||
142 | else | ||
143 | days_in_month[1] = 28; | ||
144 | |||
145 | /* Number of days in months gone by this year*/ | ||
146 | for(i = 0; i < tm->tm_mon; i++) | ||
147 | month_days += days_in_month[i]; | ||
148 | |||
149 | /* Number of days in years gone by since 1-Jan-1980 */ | ||
150 | year_days = 365*(tm->tm_year-100+20) + (tm->tm_year-100-1)/4 + 6; | ||
151 | |||
152 | /* Convert to seconds since 1-Jan-1980 */ | ||
153 | seconds = tm->tm_sec | ||
154 | + tm->tm_min*MINUTE_SECONDS | ||
155 | + tm->tm_hour*HOUR_SECONDS | ||
156 | + (tm->tm_mday-1)*DAY_SECONDS | ||
157 | + month_days*DAY_SECONDS | ||
158 | + year_days*DAY_SECONDS; | ||
159 | seconds += SECS_ADJUST; | ||
160 | |||
161 | #ifdef SANSA_FUZEPLUS | ||
162 | /* The OF uses PERSISTENT2 register to keep the adjustment and only changes | ||
163 | * SECONDS if necessary. | ||
164 | * NOTE: the OF uses this mechanism to prevent roll back in time. Although | ||
165 | * Rockbox will handle a negative PERSISTENT2 value, the OF will detect | ||
166 | * it and won't return in time before SECONDS */ | ||
167 | imx233_rtc_write_persistent(2, seconds - imx233_rtc_read_seconds()); | ||
168 | #else | ||
169 | /* The Freescale recommended way of keeping time is the number of seconds | ||
170 | * since 00:00 1/1/1980 */ | ||
171 | imx233_rtc_write_seconds(seconds); | ||
172 | #endif | ||
173 | return 0; | ||
40 | } | 174 | } |
41 | 175 | ||
42 | void rtc_set_alarm(int h, int m) | 176 | void rtc_set_alarm(int h, int m) |