Subversion Repositories svnkaklik

Rev

Details | Last modification | View Log

Rev Author Line No. Line
507 kaklik 1
/*--------------------------------------------------------------------------*/
2
/*  RTC controls                                                            */
3
 
4
#include <avr/io.h>
5
#include <string.h>
6
#include "rtc.h"
7
 
8
 
9
 
10
#define SCL_LOW()	DDRE |=	0x04			/* SCL = LOW */
11
#define SCL_HIGH()	DDRE &=	0xFB			/* SCL = High-Z */
12
#define	SCL_VAL		((PINE & 0x04) ? 1 : 0)	/* SCL input level */
13
#define SDA_LOW()	DDRE |=	0x08			/* SDA = LOW */
14
#define SDA_HIGH()	DDRE &=	0xF7			/* SDA = High-Z */
15
#define	SDA_VAL		((PINE & 0x08) ? 1 : 0)	/* SDA input level */
16
 
17
 
18
 
19
static
20
void iic_delay (void)
21
{
22
	int n;
23
	BYTE d;
24
 
25
	for (n = 4; n; n--) d = PINE;
26
}
27
 
28
 
29
/* Generate start condition on the IIC bus */
30
static
31
void iic_start (void)
32
{
33
	SDA_HIGH();
34
	iic_delay();
35
	SCL_HIGH();
36
	iic_delay();
37
	SDA_LOW();
38
	iic_delay();
39
	SCL_LOW();
40
	iic_delay();
41
}
42
 
43
 
44
/* Generate stop condition on the IIC bus */
45
static
46
void iic_stop (void)
47
{
48
	SDA_LOW();
49
	iic_delay();
50
	SCL_HIGH();
51
	iic_delay();
52
	SDA_HIGH();
53
	iic_delay();
54
}
55
 
56
 
57
/* Send a byte to the IIC bus */
58
static
59
BOOL iic_send (BYTE dat)
60
{
61
	BYTE b = 0x80;
62
	BOOL ack;
63
 
64
 
65
	do {
66
		if (dat & b)	 {	/* SDA = Z/L */
67
			SDA_HIGH();
68
		} else {
69
			SDA_LOW();
70
		}
71
		iic_delay();
72
		SCL_HIGH();
73
		iic_delay();
74
		SCL_LOW();
75
		iic_delay();
76
	} while (b >>= 1);
77
	SDA_HIGH();
78
	iic_delay();
79
	SCL_HIGH();
80
	ack = SDA_VAL ? FALSE : TRUE;	/* Sample ACK */
81
	iic_delay();
82
	SCL_LOW();
83
	iic_delay();
84
	return ack;
85
}
86
 
87
 
88
/* Receive a byte from the IIC bus */
89
static
90
BYTE iic_rcvr (BOOL ack)
91
{
92
	UINT d = 1;
93
 
94
 
95
	do {
96
		d <<= 1;
97
		SCL_HIGH();
98
		if (SDA_VAL) d++;
99
		iic_delay();
100
		SCL_LOW();
101
		iic_delay();
102
	} while (d < 0x100);
103
	if (ack) {		/* SDA = ACK */
104
		SDA_LOW();
105
	} else {
106
		SDA_HIGH();
107
	}
108
	iic_delay();
109
	SCL_HIGH();
110
	iic_delay();
111
	SCL_LOW();
112
	SDA_HIGH();
113
	iic_delay();
114
 
115
	return (BYTE)d;
116
}
117
 
118
 
119
 
120
 
121
BOOL rtc_read (
122
	UINT adr,		/* Read start address */
123
	UINT cnt,		/* Read byte count */
124
	void* buff		/* Read data buffer */
125
)
126
{
127
	BYTE *rbuff = buff;
128
	int n;
129
 
130
 
131
	if (!cnt) return FALSE;
132
 
133
	n = 10;
134
	do {							/* Select DS1338 (0xD0) */
135
		iic_start();
136
	} while (!iic_send(0xD0) && --n);
137
	if (!n) return FALSE;
138
 
139
	if (iic_send((BYTE)adr)) {		/* Set start address */
140
		iic_start();				/* Reselect DS1338 in read mode (0xD1) */
141
		if (iic_send(0xD1)) {
142
			do {					/* Receive data */
143
				cnt--;
144
				*rbuff++ = iic_rcvr(cnt ? TRUE : FALSE);
145
			} while (cnt);
146
		}
147
	}
148
 
149
	iic_stop();						/* Deselect device */
150
 
151
	return cnt ? FALSE : TRUE;
152
}
153
 
154
 
155
 
156
 
157
BOOL rtc_write (
158
	UINT adr,			/* Write start address */
159
	UINT cnt,			/* Write byte count */
160
	const void* buff	/* Data to be written */
161
)
162
{
163
	const BYTE *wbuff = buff;
164
	int n;
165
 
166
 
167
	if (!cnt) return FALSE;
168
 
169
	n = 10;
170
	do {							/* Select DS1338 (0xD0) */
171
		iic_start();
172
	} while (!iic_send(0xD0) && --n);
173
	if (!n) return FALSE;
174
 
175
	if (iic_send((BYTE)adr)) {		/* Set start address */
176
		do {						/* Send data */
177
			if (!iic_send(*wbuff++)) break;
178
		} while (--cnt);
179
	}
180
 
181
	iic_stop();						/* Deselect device */
182
 
183
	return cnt ? FALSE : TRUE;
184
}
185
 
186
 
187
 
188
 
189
BOOL rtc_gettime (RTC *rtc)
190
{
191
	BYTE buf[8];
192
 
193
 
194
	if (!rtc_read(0, 7, buf)) return FALSE;
195
 
196
	rtc->sec = (buf[0] & 0x0F) + ((buf[0] >> 4) & 7) * 10;
197
	rtc->min = (buf[1] & 0x0F) + (buf[1] >> 4) * 10;
198
	rtc->hour = (buf[2] & 0x0F) + ((buf[2] >> 4) & 3) * 10;
199
	rtc->mday = (buf[4] & 0x0F) + ((buf[4] >> 4) & 3) * 10;
200
	rtc->month = (buf[5] & 0x0F) + ((buf[5] >> 4) & 1) * 10;
201
	rtc->year = 2000 + (buf[6] & 0x0F) + (buf[6] >> 4) * 10;
202
 
203
	return TRUE;
204
}
205
 
206
 
207
 
208
 
209
BOOL rtc_settime (const RTC *rtc)
210
{
211
 
212
	BYTE buf[8];
213
 
214
 
215
	buf[0] = rtc->sec / 10 * 16 + rtc->sec % 10;
216
	buf[1] = rtc->min / 10 * 16 + rtc->min % 10;
217
	buf[2] = rtc->hour / 10 * 16 + rtc->hour % 10;
218
	buf[3] = 0;
219
	buf[4] = rtc->mday / 10 * 16 + rtc->mday % 10;
220
	buf[5] = rtc->month / 10 * 16 + rtc->month % 10;
221
	buf[6] = (rtc->year - 2000) / 10 * 16 + (rtc->year - 2000) % 10;
222
	rtc_write(0, 7, buf);
223
 
224
	return TRUE;
225
}
226
 
227
 
228
 
229
 
230
BOOL rtc_init (void)
231
{
232
	BYTE buf[8];	/* RTC R/W buffer */
233
	UINT n;
234
 
235
 
236
	/* Read RTC registers */
237
	if (!rtc_read(0, 8, buf)) return FALSE;	/* IIC error */
238
 
239
	if (buf[7] & 0x20) {	/* When RTC data has been broken, set default time */
240
		/* Reset time to Jan 1, '08 */
241
		memset(buf, 0, 8);
242
		buf[4] = 1; buf[5] = 1; buf[6] = 8;
243
		rtc_write(0, 8, buf);
244
		/* Clear data memory */
245
		memset(buf, 0, 8);
246
		for (n = 8; n < 64; n += 8)
247
			rtc_write(n, 8, buf);
248
		return FALSE;
249
	}
250
	return TRUE;
251
}
252