]> cloudbase.mooo.com Git - z180-stamp.git/blob - avr/i2c.c
Add date rtc i2c
[z180-stamp.git] / avr / i2c.c
1
2 /*
3 * I2C (TWI) master interface.
4 */
5
6 #include "common.h"
7 #include <avr/interrupt.h>
8 #include <util/delay.h>
9 #include <string.h>
10
11 #include "config.h"
12 #include "timer.h"
13 #include "debug.h"
14 #include "i2c.h"
15
16 #ifdef DEBUG
17 //# define DEBUG_I2C
18 #endif
19
20 /* General TWI Master status codes */
21 #define TWI_START 0x08 /* START has been transmitted */
22 #define TWI_REP_START 0x10 /* Repeated START has been transmitted */
23 #define TWI_ARB_LOST 0x38 /* Arbitration lost */
24
25 /* TWI Master Transmitter status codes */
26 #define TWI_MTX_ADR_ACK 0x18 /* SLA+W has been transmitted and ACK received */
27 #define TWI_MTX_ADR_NACK 0x20 /* SLA+W has been transmitted and NACK received */
28 #define TWI_MTX_DATA_ACK 0x28 /* Data byte has been transmitted and ACK received */
29 #define TWI_MTX_DATA_NACK 0x30 /* Data byte has been transmitted and NACK received */
30
31 /* TWI Master Receiver status codes */
32 #define TWI_MRX_ADR_ACK 0x40 /* SLA+R has been transmitted and ACK received */
33 #define TWI_MRX_ADR_NACK 0x48 /* SLA+R has been transmitted and NACK received */
34 #define TWI_MRX_DATA_ACK 0x50 /* Data byte has been received and ACK transmitted */
35 #define TWI_MRX_DATA_NACK 0x58 /* Data byte has been received and NACK transmitted */
36
37 /* TWI Miscellaneous status codes */
38 #define TWI_NO_STATE 0xF8 /* No relevant state information available */
39 #define TWI_BUS_ERROR 0x00 /* Bus error due to an illegal START or STOP condition */
40
41
42 /*
43 * TWINT: TWI Interrupt Flag
44 * TWEA: TWI Enable Acknowledge Bit
45 * TWSTA: TWI START Condition Bit
46 * TWSTO: TWI STOP Condition Bit
47 * TWEN: TWI Enable Bit
48 * TWIE: TWI Interrupt Enable
49 *
50 * (1<<TWEN)|(1<<TWIE)|(1<<TWINT)
51 * (1<<TWEN)|(1<<TWIE)|(1<<TWINT)| (1<<TWEA)
52 * (1<<TWEN)|(1<<TWIE)|(1<<TWINT)
53 *
54 * default:
55 * (1<<TWEN)| (1<<TWINT)| (1<<TWSTO)
56 *
57 * Init:
58 * (1<<TWEN)
59 *
60 * start read/write:
61 * (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWSTA)
62 * (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWSTA)
63 * (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWSTA)
64 * (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWSTA)
65 *
66 * wait ready:
67 * (1<<TWIE)|(1<<TWSTO)
68 *
69 *
70 *
71 *i2c_result
72 *
73 * 0b10000000 Busy (Transmission in progress)
74 * 0b01000000 Timeout
75 * 0b00001000 Start transmitted
76 * 0b00000100 Slave acknowledged address
77 * 0b00000010 Data byte(s) transmitted/received
78 * 0b00000001 Transmission completed
79 *
80 *
81 *----------------------------------------------------------------------
82 */
83
84 #define TWI_C_DISABLE 0x00
85 #define TWI_C_ENABLE (1<<TWEN)
86
87
88
89 typedef struct i2c_msg_s {
90 uint8_t stat;
91 #define XMIT_DONE (1<<0)
92 #define DATA_ACK (1<<1)
93 #define ADDR_ACK (1<<2)
94 #define START (1<<3)
95 #define TIMEOUT (1<<6)
96 #define BUSY (1<<7)
97 uint8_t idx;
98 uint8_t len;
99 uint8_t buf[CONFIG_SYS_I2C_BUFSIZE];
100 } i2c_msg_t;
101
102 static i2c_msg_t xmit;
103
104 ISR(TWI_vect)
105 {
106 uint8_t next_twcr;
107 uint8_t tmp_idx;
108
109 uint8_t twsr = TWSR;
110
111 switch (twsr & 0xf8) {
112
113 case TWI_START:
114 case TWI_REP_START:
115 xmit.idx = 0; /* reset xmit_buf index */
116 xmit.stat = BUSY | START;
117
118 tmp_idx = xmit.idx;
119 if (tmp_idx < xmit.len) { /* all bytes transmited? */
120 TWDR = xmit.buf[tmp_idx];
121 xmit.idx = ++tmp_idx;
122 next_twcr = (1<<TWEN)|(1<<TWIE)|(1<<TWINT);
123 } else {
124 xmit.stat |= XMIT_DONE;
125 xmit.stat &= ~BUSY;
126 next_twcr = (1<<TWEN)|(0<<TWIE)|(1<<TWINT)|(1<<TWSTO);
127 }
128 break;
129
130 case TWI_MTX_ADR_ACK:
131 xmit.stat |= ADDR_ACK;
132
133 tmp_idx = xmit.idx;
134 if (tmp_idx < xmit.len) { /* all bytes transmited? */
135 TWDR = xmit.buf[tmp_idx];
136 xmit.idx = ++tmp_idx;
137 next_twcr = (1<<TWEN)|(1<<TWIE)|(1<<TWINT);
138 } else {
139 xmit.stat |= XMIT_DONE;
140 xmit.stat &= ~BUSY;
141 next_twcr = (1<<TWEN)|(0<<TWIE)|(1<<TWINT)|(1<<TWSTO);
142 }
143 break;
144
145 case TWI_MTX_DATA_ACK:
146 xmit.stat |= DATA_ACK;
147
148 tmp_idx = xmit.idx;
149 if (tmp_idx < xmit.len) { /* all bytes transmited? */
150 TWDR = xmit.buf[tmp_idx];
151 xmit.idx = ++tmp_idx;
152 next_twcr = (1<<TWEN)|(1<<TWIE)|(1<<TWINT);
153 } else {
154 xmit.stat |= XMIT_DONE;
155 xmit.stat &= ~BUSY;
156 next_twcr = (1<<TWEN)|(0<<TWIE)|(1<<TWINT)|(1<<TWSTO);
157 }
158
159 break;
160
161 case TWI_MTX_DATA_NACK:
162 xmit.stat |= XMIT_DONE;
163 xmit.stat &= ~BUSY;
164 next_twcr = (1<<TWEN)|(0<<TWIE)|(1<<TWINT)|(1<<TWSTO);
165 break;
166
167 case TWI_MRX_ADR_ACK:
168 xmit.stat |= ADDR_ACK;
169 tmp_idx = xmit.idx;
170 if (tmp_idx < xmit.len-1) {
171 next_twcr = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWEA);
172 } else {
173 next_twcr = (1<<TWEN)|(1<<TWIE)|(1<<TWINT);
174 }
175 break;
176
177 case TWI_MRX_DATA_ACK:
178 xmit.stat |= DATA_ACK;
179 tmp_idx = xmit.idx;
180 xmit.buf[tmp_idx] = TWDR;
181 xmit.idx = ++tmp_idx;
182 if (tmp_idx < xmit.len-1) {
183 next_twcr = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWEA);
184 } else {
185
186 next_twcr = (1<<TWEN)|(1<<TWIE)|(1<<TWINT);
187 }
188 break;
189
190 case TWI_MRX_DATA_NACK:
191 xmit.stat |= ADDR_ACK | DATA_ACK;
192
193 tmp_idx = xmit.idx;
194 xmit.buf[tmp_idx] = TWDR;
195 xmit.idx = ++tmp_idx;
196 /* fall thru */
197
198 default:
199 xmit.stat &= ~BUSY;
200 next_twcr = (1<<TWEN)|(0<<TWIE)|(1<<TWINT)|(1<<TWSTO);
201 break;
202 }
203
204 #ifdef DEBUG_I2C
205 debug("|%02x", twsr);
206 #endif
207 TWCR = next_twcr;
208 }
209
210
211 /*------------------------------------------------------------------*/
212
213 static uint8_t twps;
214 static uint8_t twbr;
215
216
217 static void _init(void)
218 {
219 xmit.stat = 0;
220 #ifdef DEBUG_I2C
221 memset((void *) xmit.buf, 0xdf, sizeof(xmit.buf));
222 #endif
223
224 /* Disable TWI, disable TWI interrupt. */
225 /* (Reset TWI hardware state machine.) */
226 TWCR = TWI_C_DISABLE;
227 _delay_us(5);
228
229 TWBR = twbr;
230 TWDR = 0xff;
231 TWCR = TWI_C_ENABLE + twps;
232 }
233
234 void i2c_init(uint32_t speed)
235 {
236 twps = 0;
237 uint32_t tmptwbr = F_CPU /2 / speed - 8;
238
239 while (tmptwbr > 255) {
240 tmptwbr >>= 4;
241 twps += 1;
242 }
243 debug_cond((twps > 3), "TWCLK too low: %lu Hz\n", speed);
244
245 twbr = (uint8_t) tmptwbr;
246 _init();
247 }
248
249
250 int_fast8_t i2c_waitready(void)
251 {
252 uint32_t timer = get_timer(0);
253 uint8_t timeout = 0;
254
255 do {
256 if (get_timer(timer) >= 30) {
257 timeout = TIMEOUT;
258 _init();
259 }
260 } while ((TWCR & ((1<<TWIE)|(1<<TWSTO))) != 0 && !timeout);
261
262 xmit.stat |= timeout;
263
264 #ifdef DEBUG_I2C
265 dump_ram((uint8_t *) &xmit, 4, "=== i2c_wait ready: (done)");
266 _delay_ms(30);
267 #endif
268 return xmit.stat;
269 }
270
271 //static
272 int i2c_send(uint8_t chip, uint16_t addr, uint8_t alen, uint8_t *buffer, int8_t len)
273 {
274 uint8_t i, n;
275 uint8_t rc;
276
277 rc = i2c_waitready();
278 if ((rc & (BUSY | TIMEOUT)) != 0)
279 return rc;
280
281 xmit.stat = BUSY;
282 xmit.buf[0] = chip<<1;
283 for (i = 1; i < alen+1; i++) {
284 xmit.buf[i] = (uint8_t) addr;
285 addr >>= 8;
286 }
287 for (n = len + i; i < n; i++)
288 xmit.buf[i] = *buffer++;
289 xmit.len = i;
290
291 #ifdef DEBUG_I2C
292 dump_ram((uint8_t *) &xmit, 0x20, "=== i2c_send");
293 _delay_ms(30);
294 #endif
295 /* Enable TWI, TWI int and initiate start condition */
296 TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWSTA);
297
298 rc = xmit.stat;
299
300 return rc;
301 }
302
303 //static
304 int i2c_recv(uint8_t chip, uint8_t *buffer, int8_t len)
305 {
306 uint8_t rc;
307
308 rc = i2c_waitready();
309 if ((rc & (BUSY | TIMEOUT)) != 0)
310 return rc;
311
312 xmit.stat = BUSY;
313 xmit.len = len + 1;
314 xmit.buf[0] = (chip<<1) | 1;
315
316 #ifdef DEBUG_I2C
317 dump_ram((uint8_t *) &xmit, 0x20, "=== i2c_recv: before start");
318 _delay_ms(30);
319 #endif
320 /* Enable TWI, TWI int and initiate start condition */
321 TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWSTA);
322 rc = i2c_waitready();
323
324 #ifdef DEBUG_I2C
325 dump_ram((uint8_t *) &xmit, 0x20, "=== i2c_recv: after completion");
326 _delay_ms(30);
327 #endif
328 if (rc & DATA_ACK) {
329 /* at least 1 byte received */
330 for (uint8_t i=1, n=xmit.idx; i < n; i++)
331 *buffer++ = xmit.buf[i];
332 }
333
334 return rc;
335 }
336
337 /*
338 * Read/Write interface:
339 * chip: I2C chip address, range 0..127
340 * addr: Memory (register) address within the chip
341 * alen: Number of bytes to use for addr (typically 1, 2 for larger
342 * memories, 0 for register type devices with only one
343 * register)
344 * buffer: Where to read/write the data
345 * len: How many bytes to read/write
346 *
347 * Returns: 0 on success, not 0 on failure
348 */
349
350 int i2c_write(uint8_t chip, unsigned int addr, uint_fast8_t alen,
351 uint8_t *buffer, uint_fast8_t len)
352 {
353 int rc;
354
355 if ((alen > 2) || (1 + alen + len > CONFIG_SYS_I2C_BUFSIZE)) {
356 debug("** i2c_write: buffer overflow, alen: %u, len: %u\n",
357 alen, len);
358 return -1;
359 }
360
361 i2c_send(chip, addr, alen, buffer, len);
362 rc = i2c_waitready();
363 debug("** i2c_write: result=0x%02x\n",rc);
364
365 return (rc & XMIT_DONE) != 0;
366 }
367
368 int i2c_read(uint8_t chip, unsigned int addr, uint_fast8_t alen,
369 uint8_t *buffer, uint_fast8_t len)
370 {
371 int rc;
372
373 if ((alen > 2) || (1 + len > CONFIG_SYS_I2C_BUFSIZE)) {
374 debug("** i2c_read: parameter error: alen: %u, len: %u\n",
375 alen, len);
376 return -1;
377 }
378
379 if (alen != 0) {
380 i2c_send(chip, addr, alen, NULL, 0);
381 }
382 rc = i2c_recv(chip, buffer, len);
383 debug("** i2c_read: result=0x%02x\n",rc);
384
385 return !((rc & (XMIT_DONE|DATA_ACK)) == (XMIT_DONE|DATA_ACK));
386 }
387
388
389