source: rtems/c/src/lib/libbsp/arm/nds/libnds/source/arm7/clock.c @ 32b8506

4.104.115
Last change on this file since 32b8506 was 32b8506, checked in by Ralf Corsepius <ralf.corsepius@…>, on 11/29/09 at 14:53:02

Whitespace removal.

  • Property mode set to 100644
File size: 7.3 KB
Line 
1/*---------------------------------------------------------------------------------
2        $Id$
3
4        Copyright (C) 2005
5                Michael Noland (Joat)
6                Jason Rogers (Dovoto)
7                Dave Murphy (WinterMute)
8
9        This software is provided 'as-is', without any express or implied
10        warranty.  In no event will the authors be held liable for any
11        damages arising from the use of this software.
12
13        Permission is granted to anyone to use this software for any
14        purpose, including commercial applications, and to alter it and
15        redistribute it freely, subject to the following restrictions:
16
17        1.      The origin of this software must not be misrepresented; you
18                        must not claim that you wrote the original software. If you use
19                        this software in a product, an acknowledgment in the product
20                        documentation would be appreciated but is not required.
21        2.      Altered source versions must be plainly marked as such, and
22                        must not be misrepresented as being the original software.
23        3.      This notice may not be removed or altered from any source
24                        distribution.
25
26---------------------------------------------------------------------------------*/
27
28#include "nds/bios.h"
29#include "nds/arm7/clock.h"
30#include "nds/interrupts.h"
31#include "nds/ipc.h"
32
33#include <time.h>
34
35
36
37// Delay (in swiDelay units) for each bit transfer
38#define RTC_DELAY 48
39
40// Pin defines on RTC_CR
41#define CS_0    (1<<6)
42#define CS_1    ((1<<6) | (1<<2))
43#define SCK_0   (1<<5)
44#define SCK_1   ((1<<5) | (1<<1))
45#define SIO_0   (1<<4)
46#define SIO_1   ((1<<4) | (1<<0))
47#define SIO_out (1<<4)
48#define SIO_in  (1)
49
50//---------------------------------------------------------------------------------
51void BCDToInteger(uint8 * data, uint32 length) {
52//---------------------------------------------------------------------------------
53        u32 i;
54        for (i = 0; i < length; i++) {
55                data[i] = (data[i] & 0xF) + ((data[i] & 0xF0)>>4)*10;
56        }
57}
58
59
60//---------------------------------------------------------------------------------
61void integerToBCD(uint8 * data, uint32 length) {
62//---------------------------------------------------------------------------------
63        u32 i;
64        for (i = 0; i < length; i++) {
65                int high, low;
66                swiDivMod(data[i], 10, &high, &low);
67                data[i] = (high<<4) | low;
68        }
69}
70
71//---------------------------------------------------------------------------------
72void rtcTransaction(uint8 * command, uint32 commandLength, uint8 * result, uint32 resultLength) {
73//---------------------------------------------------------------------------------
74        uint32 bit;
75        uint8 data;
76
77        // Raise CS
78        RTC_CR8 = CS_0 | SCK_1 | SIO_1;
79        swiDelay(RTC_DELAY);
80        RTC_CR8 = CS_1 | SCK_1 | SIO_1;
81        swiDelay(RTC_DELAY);
82
83        // Write command byte (high bit first)
84                data = *command++;
85
86                for (bit = 0; bit < 8; bit++) {
87                        RTC_CR8 = CS_1 | SCK_0 | SIO_out | (data>>7);
88                        swiDelay(RTC_DELAY);
89
90                        RTC_CR8 = CS_1 | SCK_1 | SIO_out | (data>>7);
91                        swiDelay(RTC_DELAY);
92
93                        data = data << 1;
94                }
95        // Write parameter bytes (low bit first)
96        for ( ; commandLength > 1; commandLength--) {
97                data = *command++;
98
99                for (bit = 0; bit < 8; bit++) {
100                        RTC_CR8 = CS_1 | SCK_0 | SIO_out | (data & 1);
101                        swiDelay(RTC_DELAY);
102
103                        RTC_CR8 = CS_1 | SCK_1 | SIO_out | (data & 1);
104                        swiDelay(RTC_DELAY);
105
106                        data = data >> 1;
107                }
108        }
109
110        // Read result bytes (low bit first)
111        for ( ; resultLength > 0; resultLength--) {
112                data = 0;
113
114                for (bit = 0; bit < 8; bit++) {
115                        RTC_CR8 = CS_1 | SCK_0;
116                        swiDelay(RTC_DELAY);
117
118                        RTC_CR8 = CS_1 | SCK_1;
119                        swiDelay(RTC_DELAY);
120
121                        if (RTC_CR8 & SIO_in) data |= (1 << bit);
122                }
123                *result++ = data;
124        }
125
126        // Finish up by dropping CS low
127        RTC_CR8 = CS_0 | SCK_1;
128        swiDelay(RTC_DELAY);
129}
130
131
132//---------------------------------------------------------------------------------
133void rtcReset(void) {
134//---------------------------------------------------------------------------------
135        uint8 status;
136        uint8 command[2];
137
138        // Read the first status register
139        command[0] = READ_STATUS_REG1;
140        rtcTransaction(command, 1, &status, 1);
141
142        // Reset the RTC if needed
143        if (status & (STATUS_POC | STATUS_BLD)) {
144                command[0] = WRITE_STATUS_REG1;
145                command[1] = status | STATUS_RESET;
146                rtcTransaction(command, 2, 0, 0);
147        }
148}
149
150
151//---------------------------------------------------------------------------------
152void rtcGetTimeAndDate(uint8 * time) {
153//---------------------------------------------------------------------------------
154        uint8 command, status;
155
156        command = READ_TIME_AND_DATE;
157        rtcTransaction(&command, 1, time, 7);
158
159        command = READ_STATUS_REG1;
160        rtcTransaction(&command, 1, &status, 1);
161
162        if ( status & STATUS_24HRS ) {
163                time[4] &= 0x3f;
164        } else {
165
166        }
167        BCDToInteger(time,7);
168}
169
170//---------------------------------------------------------------------------------
171void rtcSetTimeAndDate(uint8 * time) {
172//---------------------------------------------------------------------------------
173        uint8 command[8];
174
175        int i;
176        for ( i=0; i< 8; i++ ) {
177                command[i+1] = time[i];
178        }
179        command[0] = WRITE_TIME_AND_DATE;
180        // fixme: range checking on the data we tell it
181        rtcTransaction(command, 8, 0, 0);
182}
183
184//---------------------------------------------------------------------------------
185void rtcGetTime(uint8 * time) {
186//---------------------------------------------------------------------------------
187        uint8 command, status;
188
189        command = READ_TIME;
190        rtcTransaction(&command, 1, time, 3);
191
192        command = READ_STATUS_REG1;
193        rtcTransaction(&command, 1, &status, 1);
194        if ( status & STATUS_24HRS ) {
195                time[0] &= 0x3f;
196        } else {
197
198        }
199        BCDToInteger(time,3);
200
201}
202
203//---------------------------------------------------------------------------------
204void rtcSetTime(uint8 * time) {
205//---------------------------------------------------------------------------------
206        uint8 command[4];
207
208        int i;
209        for ( i=0; i< 3; i++ ) {
210                command[i+1] = time[i];
211        }
212        command[0] = WRITE_TIME;
213        // fixme: range checking on the data we tell it
214        rtcTransaction(command, 4, 0, 0);
215}
216
217//---------------------------------------------------------------------------------
218void syncRTC() {
219//---------------------------------------------------------------------------------
220        if (++IPC->time.rtc.seconds == 60 ) {
221                IPC->time.rtc.seconds = 0;
222                if (++IPC->time.rtc.minutes == 60) {
223                        IPC->time.rtc.minutes  = 0;
224                        if (++IPC->time.rtc.hours == 24) {
225                                rtcGetTimeAndDate((uint8 *)&(IPC->time.rtc.year));
226                        }
227                }
228        }
229
230        IPC->unixTime++;
231}
232
233//---------------------------------------------------------------------------------
234void initClockIRQ() {
235//---------------------------------------------------------------------------------
236
237        REG_RCNT = 0x8100;
238        irqSet(IRQ_NETWORK, syncRTC);
239        // Reset the clock if needed
240        rtcReset();
241
242        uint8 command[4];
243        command[0] = READ_STATUS_REG2;
244        rtcTransaction(command, 1, &command[1], 1);
245
246        command[0] = WRITE_STATUS_REG2;
247        command[1] = 0x41;
248        rtcTransaction(command, 2, 0, 0);
249
250        command[0] = WRITE_INT_REG1;
251        command[1] = 0x01;
252        rtcTransaction(command, 2, 0, 0);
253
254        command[0] = WRITE_INT_REG2;
255        command[1] = 0x00;
256        command[2] = 0x21;
257        command[3] = 0x35;
258        rtcTransaction(command, 4, 0, 0);
259
260        // Read all time settings on first start
261        rtcGetTimeAndDate((uint8 *)&(IPC->time.rtc.year));
262
263
264        struct tm currentTime;
265
266        currentTime.tm_sec  = IPC->time.rtc.seconds;
267        currentTime.tm_min  = IPC->time.rtc.minutes;
268        currentTime.tm_hour = IPC->time.rtc.hours;
269
270        currentTime.tm_mday = IPC->time.rtc.day;
271        currentTime.tm_mon  = IPC->time.rtc.month - 1;
272        currentTime.tm_year = IPC->time.rtc.year + 100;
273
274        currentTime.tm_isdst = -1;
275
276        IPC->unixTime = mktime(&currentTime);
277}
278
Note: See TracBrowser for help on using the repository browser.