]> git.sur5r.net Git - freertos/blob - Demo/Common/drivers/Atmel/at91lib/peripherals/rtc/rtc.c
Atmel provided hardware specifics.
[freertos] / Demo / Common / drivers / Atmel / at91lib / peripherals / rtc / rtc.c
1 /* ----------------------------------------------------------------------------\r
2  *         ATMEL Microcontroller Software Support \r
3  * ----------------------------------------------------------------------------\r
4  * Copyright (c) 2008, Atmel Corporation\r
5  *\r
6  * All rights reserved.\r
7  *\r
8  * Redistribution and use in source and binary forms, with or without\r
9  * modification, are permitted provided that the following conditions are met:\r
10  *\r
11  * - Redistributions of source code must retain the above copyright notice,\r
12  * this list of conditions and the disclaimer below.\r
13  *\r
14  * Atmel's name may not be used to endorse or promote products derived from\r
15  * this software without specific prior written permission.\r
16  *\r
17  * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR\r
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE\r
20  * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,\r
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\r
22  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\r
23  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\r
24  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\r
25  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\r
26  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
27  * ----------------------------------------------------------------------------\r
28  */\r
29 \r
30 #ifndef trace_LEVEL\r
31         #define trace_LEVEL trace_INFO\r
32 #endif\r
33 \r
34 //------------------------------------------------------------------------------\r
35 //         Headers\r
36 //------------------------------------------------------------------------------\r
37 \r
38 #include "rtc.h"\r
39 #include <board.h>\r
40 #include <utility/assert.h>\r
41 #include <utility/trace.h>\r
42 \r
43 //------------------------------------------------------------------------------\r
44 //         Exported functions\r
45 //------------------------------------------------------------------------------\r
46 \r
47 //------------------------------------------------------------------------------\r
48 /// Sets the RTC in either 12- or 24-hour mode.\r
49 /// \param mode  Hour mode.\r
50 //------------------------------------------------------------------------------\r
51 void RTC_SetHourMode(unsigned int mode)\r
52 {\r
53         SANITY_CHECK((mode & 0xFFFFFFFE) == 0);\r
54 \r
55     trace_LOG(trace_DEBUG, "-D- RTC_SetHourMode()\n\r");\r
56 \r
57         AT91C_BASE_RTC->RTC_MR = mode;\r
58 }\r
59 \r
60 //------------------------------------------------------------------------------\r
61 /// Enables the selected interrupt sources of the RTC.\r
62 /// \param sources  Interrupt sources to enable.\r
63 //------------------------------------------------------------------------------\r
64 void RTC_EnableIt(unsigned int sources)\r
65 {\r
66     SANITY_CHECK((sources & ~0x1F) == 0);\r
67 \r
68     trace_LOG(trace_DEBUG, "-D- RTC_EnableIt()\n\r");\r
69 \r
70     AT91C_BASE_RTC->RTC_IER = sources;\r
71 }\r
72 \r
73 //------------------------------------------------------------------------------\r
74 /// Disables the selected interrupt sources of the RTC.\r
75 /// \param sources  Interrupt sources to disable.\r
76 //------------------------------------------------------------------------------\r
77 void RTC_DisableIt(unsigned int sources)\r
78 {\r
79     SANITY_CHECK((sources & ~0x1F) == 0);\r
80 \r
81     trace_LOG(trace_DEBUG, "-D- RTC_DisableIt()\n\r");\r
82 \r
83     AT91C_BASE_RTC->RTC_IDR = sources;\r
84 }\r
85 \r
86 //------------------------------------------------------------------------------\r
87 /// Sets the current time in the RTC.\r
88 /// \param hour  Current hour.\r
89 /// \param minute  Current minute.\r
90 /// \param second  Current second.\r
91 //------------------------------------------------------------------------------\r
92 void RTC_SetTime(unsigned char hour, unsigned char minute, unsigned char second)\r
93 {\r
94         unsigned int time;\r
95 \r
96         SANITY_CHECK(hour < 24);\r
97         SANITY_CHECK(minute < 60);\r
98         SANITY_CHECK(second < 60);\r
99 \r
100     trace_LOG(trace_DEBUG, "-D- RTC_SetTime(%02d:%02d:%02d)\n\r", hour, minute, second);\r
101 \r
102         time = (second % 10) | ((second / 10) << 4)\r
103                    | ((minute % 10) << 8) | ((minute / 10) << 12);\r
104 \r
105         // 12-hour mode\r
106         if ((AT91C_BASE_RTC->RTC_MR & AT91C_RTC_HRMOD) == AT91C_RTC_HRMOD) {\r
107 \r
108                 if (hour > 12) {\r
109 \r
110                         hour -= 12;\r
111                         time |= AT91C_RTC_AMPM;\r
112                 }\r
113         }\r
114 \r
115         time |= ((hour % 10) << 16) | ((hour / 10) << 20);\r
116 \r
117         // Set time\r
118         AT91C_BASE_RTC->RTC_CR |= AT91C_RTC_UPDTIM;\r
119         while ((AT91C_BASE_RTC->RTC_SR & AT91C_RTC_ACKUPD) != AT91C_RTC_ACKUPD);\r
120         AT91C_BASE_RTC->RTC_SCCR = AT91C_RTC_ACKUPD;\r
121         AT91C_BASE_RTC->RTC_TIMR = time;\r
122         AT91C_BASE_RTC->RTC_CR &= ~AT91C_RTC_UPDTIM;\r
123         SANITY_CHECK((AT91C_BASE_RTC->RTC_CR & AT91C_RTC_UPDTIM) != AT91C_RTC_UPDTIM);\r
124 }\r
125 \r
126 //------------------------------------------------------------------------------\r
127 /// Retrieves the current time as stored in the RTC in several variables.\r
128 /// \param pHour  If not null, current hour is stored in this variable.\r
129 /// \param pMinute  If not null, current minute is stored in this variable.\r
130 /// \param pSecond  If not null, current second is stored in this variable.\r
131 //------------------------------------------------------------------------------\r
132 void RTC_GetTime(\r
133         unsigned char *pHour,\r
134         unsigned char *pMinute,\r
135         unsigned char *pSecond)\r
136 {\r
137         unsigned int time;\r
138 \r
139         SANITY_CHECK(pHour || pMinute || pSecond);\r
140 \r
141     trace_LOG(trace_DEBUG, "-D- RTC_GetTime()\n\r");\r
142 \r
143         // Get current RTC time\r
144         time = AT91C_BASE_RTC->RTC_TIMR;\r
145         while (time != AT91C_BASE_RTC->RTC_TIMR) {\r
146 \r
147                 time = AT91C_BASE_RTC->RTC_TIMR;\r
148         }\r
149 \r
150         // Hour\r
151         if (pHour) {\r
152 \r
153                 *pHour = ((time & 0x00300000) >> 20) * 10\r
154                                  + ((time & 0x000F0000) >> 16);\r
155                 if ((time & AT91C_RTC_AMPM) == AT91C_RTC_AMPM) {\r
156 \r
157                         *pHour += 12;\r
158                 }\r
159         }\r
160         \r
161         // Minute\r
162         if (pMinute) {\r
163 \r
164                 *pMinute = ((time & 0x00007000) >> 12) * 10\r
165                                    + ((time & 0x00000F00) >> 8);\r
166         }\r
167 \r
168         // Second\r
169         if (pSecond) {\r
170 \r
171                 *pSecond = ((time & 0x00000070) >> 4) * 10\r
172                                    + (time & 0x0000000F);\r
173         }\r
174 }\r
175 \r
176 //------------------------------------------------------------------------------\r
177 /// Sets a time alarm on the RTC. The match is performed only on the provided\r
178 /// variables; setting all pointers to 0 disables the time alarm.\r
179 /// Note: in AM/PM mode, the hour value must have bit #7 set for PM, cleared for\r
180 /// AM (as expected in the time registers).\r
181 /// \param pHour  If not null, the time alarm will hour-match this value.\r
182 /// \param pMinute  If not null, the time alarm will minute-match this value.\r
183 /// \param pSecond  If not null, the time alarm will second-match this value.\r
184 //------------------------------------------------------------------------------\r
185 void RTC_SetTimeAlarm(\r
186         unsigned char *pHour,\r
187         unsigned char *pMinute,\r
188         unsigned char *pSecond)\r
189 {\r
190         unsigned int alarm = 0;\r
191 \r
192     SANITY_CHECK(!pHour || ((*pHour & 0x80) == 0));\r
193     SANITY_CHECK(!pMinute || (*pMinute < 60));\r
194     SANITY_CHECK(!pSecond || (*pSecond < 60));\r
195 \r
196         trace_LOG(trace_DEBUG, "-D- RTC_SetTimeAlarm()\n\r");\r
197 \r
198         // Hour\r
199         if (pHour) {\r
200 \r
201                 alarm |= AT91C_RTC_HOUREN | ((*pHour / 10) << 20) | ((*pHour % 10) << 16);\r
202         }\r
203 \r
204         // Minute\r
205         if (pMinute) {\r
206 \r
207                 alarm |= AT91C_RTC_MINEN | ((*pMinute / 10) << 12) | ((*pMinute % 10) << 8);\r
208         }\r
209 \r
210         // Second\r
211         if (pSecond) {\r
212 \r
213                 alarm |= AT91C_RTC_SECEN | ((*pSecond / 10) << 4) | (*pSecond % 10);\r
214         }\r
215 \r
216         AT91C_BASE_RTC->RTC_TIMALR = alarm;\r
217 }\r
218 \r
219 //------------------------------------------------------------------------------\r
220 /// Retrieves the current year, month and day from the RTC. Month, day and week\r
221 /// values are numbered starting at 1.\r
222 /// \param pYear  Current year (optional).\r
223 /// \param pMonth  Current month (optional).\r
224 /// \param pDay  Current day (optional).\r
225 /// \param pWeek  Current day in current week (optional).\r
226 //------------------------------------------------------------------------------\r
227 void RTC_GetDate(\r
228     unsigned short *pYear,\r
229     unsigned char *pMonth,\r
230     unsigned char *pDay,\r
231     unsigned char *pWeek)\r
232 {\r
233     unsigned int date;\r
234 \r
235     // Get current date (multiple reads are necessary to insure a stable value)\r
236     do {\r
237 \r
238         date = AT91C_BASE_RTC->RTC_CALR;\r
239     }\r
240     while (date != AT91C_BASE_RTC->RTC_CALR);\r
241 \r
242     // Retrieve year\r
243     if (pYear) {\r
244 \r
245         *pYear = (((date  >> 4) & 0x7) * 1000)\r
246                  + ((date & 0xF) * 100)\r
247                  + (((date >> 12) & 0xF) * 10)\r
248                  + ((date >> 8) & 0xF);\r
249     }\r
250 \r
251     // Retrieve month\r
252     if (pMonth) {\r
253 \r
254         *pMonth = (((date >> 20) & 1) * 10) + ((date >> 16) & 0xF);\r
255     }\r
256 \r
257     // Retrieve day\r
258     if (pDay) {\r
259 \r
260         *pDay = (((date >> 28) & 0x3) * 10) + ((date >> 24) & 0xF);\r
261     }\r
262 \r
263     // Retrieve week\r
264     if (pWeek) {\r
265 \r
266         *pWeek = ((date >> 21) & 0x7);\r
267     }\r
268 }\r
269 \r
270 //------------------------------------------------------------------------------\r
271 /// Sets the current year, month and day in the RTC. Month, day and week values\r
272 /// must be numbered starting from 1.\r
273 /// \param year  Current year.\r
274 /// \param month  Current month.\r
275 /// \param day  Current day.\r
276 /// \param week  Day number in current week.\r
277 //------------------------------------------------------------------------------\r
278 void RTC_SetDate(\r
279     unsigned short year,\r
280     unsigned char month,\r
281     unsigned char day,\r
282     unsigned char week)\r
283 {\r
284     unsigned int date;\r
285 \r
286     SANITY_CHECK((year >= 1900) && (year <= 2099));\r
287     SANITY_CHECK((month >= 1) && (month <= 12));\r
288     SANITY_CHECK((day >= 1) && (day <= 31));\r
289     SANITY_CHECK((week >= 1) && (week <= 7));\r
290 \r
291     // Convert values to date register value\r
292     date = ((year / 100) % 10)\r
293            | ((year / 1000) << 4)\r
294            | ((year % 10) << 8)\r
295            | (((year / 10) % 10) << 12)\r
296            | ((month % 10) << 16)\r
297            | ((month / 10) << 20)\r
298            | (week << 21)\r
299            | ((day % 10) << 24)\r
300            | ((day / 10) << 28);\r
301 \r
302     // Update calendar register\r
303     AT91C_BASE_RTC->RTC_CR |= AT91C_RTC_UPDCAL;\r
304     while ((AT91C_BASE_RTC->RTC_SR & AT91C_RTC_ACKUPD) != AT91C_RTC_ACKUPD);\r
305     AT91C_BASE_RTC->RTC_SCCR = AT91C_RTC_ACKUPD;\r
306     AT91C_BASE_RTC->RTC_CALR = date;\r
307     AT91C_BASE_RTC->RTC_CR &= ~AT91C_RTC_UPDCAL;\r
308 }\r
309 \r
310 //------------------------------------------------------------------------------\r
311 /// Sets a date alarm in the RTC. The alarm will match only the provided values;\r
312 /// passing a null-pointer disables the corresponding field match.\r
313 /// \param pMonth  If not null, the RTC alarm will month-match this value.\r
314 /// \param pDay  If not null, the RTC alarm will day-match this value.\r
315 //------------------------------------------------------------------------------\r
316 void RTC_SetDateAlarm(unsigned char *pMonth, unsigned char *pDay)\r
317 {\r
318     unsigned int alarm = 0;\r
319 \r
320     SANITY_CHECK(!pMonth || ((*pMonth >= 1) && (*pMonth <= 12)));\r
321     SANITY_CHECK(!pDay || ((*pDay >= 1) && (*pDay <= 31)));\r
322 \r
323     trace_LOG(trace_DEBUG, "-D- RTC_SetDateAlarm()\n\r");\r
324 \r
325     // Compute alarm field value\r
326     if (pMonth) {\r
327 \r
328         alarm |= AT91C_RTC_MONTHEN | ((*pMonth / 10) << 20) | ((*pMonth % 10) << 16);\r
329     }\r
330     if (pDay) {\r
331 \r
332         alarm |= AT91C_RTC_DATEEN | ((*pDay / 10) << 28) | ((*pDay % 10) << 24);\r
333     }\r
334 \r
335     // Set alarm\r
336     AT91C_BASE_RTC->RTC_CALALR = alarm;\r
337 }\r
338 \r