]> cloudbase.mooo.com Git - z180-stamp.git/blob - avr/i2c.c
3ab222aebc50dcbf0d60822738bb80d34c11668f
[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 volatile i2c_msg_t xmit;
103
104 ISR(TWI_vect)
105 {
106 uint8_t tmp_stat;
107 uint8_t tmp_idx;
108 uint8_t next_twcr;
109 uint8_t n;
110
111 tmp_idx = xmit.idx;
112 tmp_stat = xmit.stat;
113
114 uint8_t twsr = TWSR;
115
116 switch (twsr & 0xf8) {
117
118 case TWI_START:
119 case TWI_REP_START:
120 tmp_stat = BUSY | START;
121 tmp_idx = 0; /* reset xmit_buf index */
122
123 if (tmp_idx < xmit.len) { /* all bytes transmited? */
124 TWDR = xmit.buf[tmp_idx];
125 ++tmp_idx;
126 next_twcr = (1<<TWEN)|(1<<TWIE)|(1<<TWINT);
127 } else {
128 tmp_stat |= XMIT_DONE;
129 tmp_stat &= ~BUSY;
130 next_twcr = (1<<TWEN)|(0<<TWIE)|(1<<TWINT)|(1<<TWSTO);
131 }
132 break;
133
134 case TWI_MTX_ADR_ACK:
135 tmp_stat |= ADDR_ACK;
136
137 if (tmp_idx < xmit.len) { /* all bytes transmited? */
138 TWDR = xmit.buf[tmp_idx];
139 ++tmp_idx;
140 next_twcr = (1<<TWEN)|(1<<TWIE)|(1<<TWINT);
141 } else {
142 tmp_stat |= XMIT_DONE;
143 tmp_stat &= ~BUSY;
144 next_twcr = (1<<TWEN)|(0<<TWIE)|(1<<TWINT)|(1<<TWSTO);
145 }
146 break;
147
148 case TWI_MTX_DATA_ACK:
149 tmp_stat |= DATA_ACK;
150
151 if (tmp_idx < xmit.len) { /* all bytes transmited? */
152 TWDR = xmit.buf[tmp_idx];
153 ++tmp_idx;
154 next_twcr = (1<<TWEN)|(1<<TWIE)|(1<<TWINT);
155 } else {
156 tmp_stat |= XMIT_DONE;
157 tmp_stat &= ~BUSY;
158 next_twcr = (1<<TWEN)|(0<<TWIE)|(1<<TWINT)|(1<<TWSTO);
159 }
160
161 break;
162
163 case TWI_MTX_DATA_NACK:
164 tmp_stat |= XMIT_DONE;
165 tmp_stat &= ~BUSY;
166 next_twcr = (1<<TWEN)|(0<<TWIE)|(1<<TWINT)|(1<<TWSTO);
167 break;
168
169 case TWI_MRX_ADR_ACK:
170 tmp_stat |= ADDR_ACK;
171 n = xmit.len-1;
172 if (tmp_idx < n) {
173 next_twcr = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWEA);
174 } else {
175 next_twcr = (1<<TWEN)|(1<<TWIE)|(1<<TWINT);
176 }
177 break;
178
179 case TWI_MRX_DATA_ACK:
180 tmp_stat |= DATA_ACK;
181 xmit.buf[tmp_idx] = TWDR;
182 ++tmp_idx;
183 n = xmit.len-1;
184 if (tmp_idx < n) {
185 next_twcr = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWEA);
186 } else {
187
188 next_twcr = (1<<TWEN)|(1<<TWIE)|(1<<TWINT);
189 }
190 break;
191
192 case TWI_MRX_DATA_NACK:
193 tmp_stat |= ADDR_ACK | DATA_ACK;
194
195 xmit.buf[tmp_idx] = TWDR;
196 ++tmp_idx;
197 /* fall thru */
198
199 default:
200 tmp_stat &= ~BUSY;
201 next_twcr = (1<<TWEN)|(0<<TWIE)|(1<<TWINT)|(1<<TWSTO);
202 break;
203 }
204
205 xmit.stat = tmp_stat;
206 xmit.idx = tmp_idx;
207
208 #ifdef DEBUG_I2C
209 debug("|%02x", twsr);
210 #endif
211 TWCR = next_twcr;
212 }
213
214
215 /*------------------------------------------------------------------*/
216
217 static uint8_t twps;
218 static uint8_t twbr;
219
220
221 static void _init(void)
222 {
223 xmit.stat = 0;
224
225 /* Disable TWI, disable TWI interrupt. */
226 /* (Reset TWI hardware state machine.) */
227 TWCR = TWI_C_DISABLE;
228 _delay_us(5);
229 #ifdef DEBUG_I2C
230 memset((void *) xmit.buf, 0xdf, sizeof(xmit.buf));
231 #endif
232
233 TWDR = 0xff;
234 TWBR = twbr;
235 TWSR = twps & 0x03;
236 TWCR = TWI_C_ENABLE;
237 }
238
239 void i2c_init(uint32_t speed)
240 {
241 twps = 0;
242 uint32_t tmp_twbr = F_CPU /2 / speed - 8;
243
244 while (tmp_twbr > 255) {
245 tmp_twbr >>= 4;
246 twps += 1;
247 }
248 debug_cond((twps > 3), "*** TWCLK too low: %lu Hz\n", speed);
249
250 twbr = (uint8_t) tmp_twbr;
251
252 debug("*** i2c_init: i2c_speed: %lu, twbr: %u, twps: %u\n",
253 speed, twbr, twps);
254
255 _init();
256 }
257
258
259 int_fast8_t i2c_waitready(void)
260 {
261 uint32_t timer = get_timer(0);
262 uint8_t timeout = 0;
263
264 do {
265 if (get_timer(timer) >= 30) {
266 timeout = TIMEOUT;
267 _init();
268 }
269 } while ((TWCR & ((1<<TWIE)|(1<<TWSTO))) != 0 && !timeout);
270
271 xmit.stat |= timeout;
272
273 #ifdef DEBUG_I2C
274 dump_ram((uint8_t *) &xmit, 4, "=== i2c_wait ready: (done)");
275 _delay_ms(30);
276 #endif
277 return xmit.stat;
278 }
279
280 //static
281 int i2c_send(uint8_t chip, uint16_t addr, uint8_t alen, uint8_t *buffer, int8_t len)
282 {
283 uint8_t i, n;
284 uint8_t rc;
285
286 rc = i2c_waitready();
287 if ((rc & (BUSY | TIMEOUT)) != 0)
288 return rc;
289
290 xmit.stat = BUSY;
291 xmit.buf[0] = chip<<1;
292 for (i = 1; i < alen+1; i++) {
293 xmit.buf[i] = (uint8_t) addr;
294 addr >>= 8;
295 }
296 for (n = len + i; i < n; i++)
297 xmit.buf[i] = *buffer++;
298 xmit.len = i;
299
300 #ifdef DEBUG_I2C
301 dump_ram((uint8_t *) &xmit, 0x20, "=== i2c_send");
302 _delay_ms(30);
303 #endif
304 /* Enable TWI, TWI int and initiate start condition */
305 TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWSTA);
306
307 rc = xmit.stat;
308
309 return rc;
310 }
311
312 //static
313 int i2c_recv(uint8_t chip, uint8_t *buffer, int8_t len)
314 {
315 uint8_t rc;
316
317 rc = i2c_waitready();
318 if ((rc & (BUSY | TIMEOUT)) != 0)
319 return rc;
320
321 xmit.stat = BUSY;
322 xmit.len = len + 1;
323 xmit.buf[0] = (chip<<1) | 1;
324
325 #ifdef DEBUG_I2C
326 dump_ram((uint8_t *) &xmit, 0x20, "=== i2c_recv: before start");
327 _delay_ms(30);
328 #endif
329 /* Enable TWI, TWI int and initiate start condition */
330 TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWSTA);
331 rc = i2c_waitready();
332
333 #ifdef DEBUG_I2C
334 dump_ram((uint8_t *) &xmit, 0x20, "=== i2c_recv: after completion");
335 _delay_ms(30);
336 #endif
337 if (rc & DATA_ACK) {
338 /* at least 1 byte received */
339 for (uint8_t i=1, n=xmit.idx; i < n; i++)
340 *buffer++ = xmit.buf[i];
341 }
342
343 return rc;
344 }
345
346 /*
347 * Read/Write interface:
348 * chip: I2C chip address, range 0..127
349 * addr: Memory (register) address within the chip
350 * alen: Number of bytes to use for addr (typically 1, 2 for larger
351 * memories, 0 for register type devices with only one
352 * register)
353 * buffer: Where to read/write the data
354 * len: How many bytes to read/write
355 *
356 * Returns: 0 on success, not 0 on failure
357 */
358
359 int i2c_write(uint8_t chip, unsigned int addr, uint_fast8_t alen,
360 uint8_t *buffer, uint_fast8_t len)
361 {
362 int rc;
363
364 if ((alen > 2) || (1 + alen + len > CONFIG_SYS_I2C_BUFSIZE)) {
365 debug("** i2c_write: buffer overflow, alen: %u, len: %u\n",
366 alen, len);
367 return -1;
368 }
369
370 i2c_send(chip, addr, alen, buffer, len);
371 rc = i2c_waitready();
372 debug("** i2c_write: result=0x%02x\n",rc);
373
374 return (rc & XMIT_DONE) != 0;
375 }
376
377 int i2c_read(uint8_t chip, unsigned int addr, uint_fast8_t alen,
378 uint8_t *buffer, uint_fast8_t len)
379 {
380 int rc;
381
382 if ((alen > 2) || (1 + len > CONFIG_SYS_I2C_BUFSIZE)) {
383 debug("** i2c_read: parameter error: alen: %u, len: %u\n",
384 alen, len);
385 return -1;
386 }
387
388 if (alen != 0) {
389 i2c_send(chip, addr, alen, NULL, 0);
390 }
391 rc = i2c_recv(chip, buffer, len);
392 debug("** i2c_read: result=0x%02x\n",rc);
393
394 return !((rc & (XMIT_DONE|DATA_ACK)) == (XMIT_DONE|DATA_ACK));
395 }
396
397
398