1 /* ----------------------------------------------------------------------------
\r
2 * ATMEL Microcontroller Software Support
\r
3 * ----------------------------------------------------------------------------
\r
4 * Copyright (c) 2008, Atmel Corporation
\r
6 * All rights reserved.
\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
11 * - Redistributions of source code must retain the above copyright notice,
\r
12 * this list of conditions and the disclaimer below.
\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
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
31 #define trace_LEVEL trace_INFO
\r
34 //------------------------------------------------------------------------------
\r
36 //------------------------------------------------------------------------------
\r
40 #include <utility/assert.h>
\r
41 #include <utility/trace.h>
\r
43 //------------------------------------------------------------------------------
\r
44 // Exported functions
\r
45 //------------------------------------------------------------------------------
\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
53 SANITY_CHECK((mode & 0xFFFFFFFE) == 0);
\r
55 trace_LOG(trace_DEBUG, "-D- RTC_SetHourMode()\n\r");
\r
57 AT91C_BASE_RTC->RTC_MR = mode;
\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
66 SANITY_CHECK((sources & ~0x1F) == 0);
\r
68 trace_LOG(trace_DEBUG, "-D- RTC_EnableIt()\n\r");
\r
70 AT91C_BASE_RTC->RTC_IER = sources;
\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
79 SANITY_CHECK((sources & ~0x1F) == 0);
\r
81 trace_LOG(trace_DEBUG, "-D- RTC_DisableIt()\n\r");
\r
83 AT91C_BASE_RTC->RTC_IDR = sources;
\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
96 SANITY_CHECK(hour < 24);
\r
97 SANITY_CHECK(minute < 60);
\r
98 SANITY_CHECK(second < 60);
\r
100 trace_LOG(trace_DEBUG, "-D- RTC_SetTime(%02d:%02d:%02d)\n\r", hour, minute, second);
\r
102 time = (second % 10) | ((second / 10) << 4)
\r
103 | ((minute % 10) << 8) | ((minute / 10) << 12);
\r
106 if ((AT91C_BASE_RTC->RTC_MR & AT91C_RTC_HRMOD) == AT91C_RTC_HRMOD) {
\r
111 time |= AT91C_RTC_AMPM;
\r
115 time |= ((hour % 10) << 16) | ((hour / 10) << 20);
\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
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
133 unsigned char *pHour,
\r
134 unsigned char *pMinute,
\r
135 unsigned char *pSecond)
\r
139 SANITY_CHECK(pHour || pMinute || pSecond);
\r
141 trace_LOG(trace_DEBUG, "-D- RTC_GetTime()\n\r");
\r
143 // Get current RTC time
\r
144 time = AT91C_BASE_RTC->RTC_TIMR;
\r
145 while (time != AT91C_BASE_RTC->RTC_TIMR) {
\r
147 time = AT91C_BASE_RTC->RTC_TIMR;
\r
153 *pHour = ((time & 0x00300000) >> 20) * 10
\r
154 + ((time & 0x000F0000) >> 16);
\r
155 if ((time & AT91C_RTC_AMPM) == AT91C_RTC_AMPM) {
\r
164 *pMinute = ((time & 0x00007000) >> 12) * 10
\r
165 + ((time & 0x00000F00) >> 8);
\r
171 *pSecond = ((time & 0x00000070) >> 4) * 10
\r
172 + (time & 0x0000000F);
\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
190 unsigned int alarm = 0;
\r
192 SANITY_CHECK(!pHour || ((*pHour & 0x80) == 0));
\r
193 SANITY_CHECK(!pMinute || (*pMinute < 60));
\r
194 SANITY_CHECK(!pSecond || (*pSecond < 60));
\r
196 trace_LOG(trace_DEBUG, "-D- RTC_SetTimeAlarm()\n\r");
\r
201 alarm |= AT91C_RTC_HOUREN | ((*pHour / 10) << 20) | ((*pHour % 10) << 16);
\r
207 alarm |= AT91C_RTC_MINEN | ((*pMinute / 10) << 12) | ((*pMinute % 10) << 8);
\r
213 alarm |= AT91C_RTC_SECEN | ((*pSecond / 10) << 4) | (*pSecond % 10);
\r
216 AT91C_BASE_RTC->RTC_TIMALR = alarm;
\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
228 unsigned short *pYear,
\r
229 unsigned char *pMonth,
\r
230 unsigned char *pDay,
\r
231 unsigned char *pWeek)
\r
235 // Get current date (multiple reads are necessary to insure a stable value)
\r
238 date = AT91C_BASE_RTC->RTC_CALR;
\r
240 while (date != AT91C_BASE_RTC->RTC_CALR);
\r
245 *pYear = (((date >> 4) & 0x7) * 1000)
\r
246 + ((date & 0xF) * 100)
\r
247 + (((date >> 12) & 0xF) * 10)
\r
248 + ((date >> 8) & 0xF);
\r
254 *pMonth = (((date >> 20) & 1) * 10) + ((date >> 16) & 0xF);
\r
260 *pDay = (((date >> 28) & 0x3) * 10) + ((date >> 24) & 0xF);
\r
266 *pWeek = ((date >> 21) & 0x7);
\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
279 unsigned short year,
\r
280 unsigned char month,
\r
282 unsigned char week)
\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
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
299 | ((day % 10) << 24)
\r
300 | ((day / 10) << 28);
\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
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
318 unsigned int alarm = 0;
\r
320 SANITY_CHECK(!pMonth || ((*pMonth >= 1) && (*pMonth <= 12)));
\r
321 SANITY_CHECK(!pDay || ((*pDay >= 1) && (*pDay <= 31)));
\r
323 trace_LOG(trace_DEBUG, "-D- RTC_SetDateAlarm()\n\r");
\r
325 // Compute alarm field value
\r
328 alarm |= AT91C_RTC_MONTHEN | ((*pMonth / 10) << 20) | ((*pMonth % 10) << 16);
\r
332 alarm |= AT91C_RTC_DATEEN | ((*pDay / 10) << 28) | ((*pDay % 10) << 24);
\r
336 AT91C_BASE_RTC->RTC_CALALR = alarm;
\r