]>
cloudbase.mooo.com Git - z180-stamp.git/blob - avr/i2c.c
df97fea36da267a86d853310f67052fdbd9760e5
3 * I2C (TWI) master interface.
7 #include <avr/interrupt.h>
8 #include <util/delay.h>
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 */
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 */
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 */
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 */
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
50 * (1<<TWEN)|(1<<TWIE)|(1<<TWINT)
51 * (1<<TWEN)|(1<<TWIE)|(1<<TWINT)| (1<<TWEA)
52 * (1<<TWEN)|(1<<TWIE)|(1<<TWINT)
55 * (1<<TWEN)| (1<<TWINT)| (1<<TWSTO)
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)
67 * (1<<TWIE)|(1<<TWSTO)
73 * 0b10000000 Busy (Transmission in progress)
75 * 0b00001000 Start transmitted
76 * 0b00000100 Slave acknowledged address
77 * 0b00000010 Data byte(s) transmitted/received
78 * 0b00000001 Transmission completed
81 *----------------------------------------------------------------------
84 #define TWI_C_DISABLE 0x00
85 #define TWI_C_ENABLE (1<<TWEN)
89 typedef struct i2c_msg_s
{
91 #define XMIT_DONE (1<<0)
92 #define DATA_ACK (1<<1)
93 #define ADDR_ACK (1<<2)
95 #define TIMEOUT (1<<6)
99 uint8_t buf
[CONFIG_SYS_I2C_BUFSIZE
];
102 static i2c_msg_t xmit
;
111 switch (twsr
& 0xf8) {
115 xmit
.idx
= 0; /* reset xmit_buf index */
116 xmit
.stat
= BUSY
| START
;
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
);
124 xmit
.stat
|= XMIT_DONE
;
126 next_twcr
= (1<<TWEN
)|(0<<TWIE
)|(1<<TWINT
)|(1<<TWSTO
);
130 case TWI_MTX_ADR_ACK
:
131 xmit
.stat
|= ADDR_ACK
;
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
);
139 xmit
.stat
|= XMIT_DONE
;
141 next_twcr
= (1<<TWEN
)|(0<<TWIE
)|(1<<TWINT
)|(1<<TWSTO
);
145 case TWI_MTX_DATA_ACK
:
146 xmit
.stat
|= DATA_ACK
;
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
);
154 xmit
.stat
|= XMIT_DONE
;
156 next_twcr
= (1<<TWEN
)|(0<<TWIE
)|(1<<TWINT
)|(1<<TWSTO
);
161 case TWI_MTX_DATA_NACK
:
162 xmit
.stat
|= XMIT_DONE
;
164 next_twcr
= (1<<TWEN
)|(0<<TWIE
)|(1<<TWINT
)|(1<<TWSTO
);
167 case TWI_MRX_ADR_ACK
:
168 xmit
.stat
|= ADDR_ACK
;
170 if (tmp_idx
< xmit
.len
-1) {
171 next_twcr
= (1<<TWEN
)|(1<<TWIE
)|(1<<TWINT
)|(1<<TWEA
);
173 next_twcr
= (1<<TWEN
)|(1<<TWIE
)|(1<<TWINT
);
177 case TWI_MRX_DATA_ACK
:
178 xmit
.stat
|= DATA_ACK
;
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
);
186 next_twcr
= (1<<TWEN
)|(1<<TWIE
)|(1<<TWINT
);
190 case TWI_MRX_DATA_NACK
:
191 xmit
.stat
|= ADDR_ACK
| DATA_ACK
;
194 xmit
.buf
[tmp_idx
] = TWDR
;
195 xmit
.idx
= ++tmp_idx
;
200 next_twcr
= (1<<TWEN
)|(0<<TWIE
)|(1<<TWINT
)|(1<<TWSTO
);
205 debug("|%02x", twsr
);
211 /*------------------------------------------------------------------*/
217 static void _init(void)
221 memset((void *) xmit
.buf
, 0xdf, sizeof(xmit
.buf
));
224 /* Disable TWI, disable TWI interrupt. */
225 /* (Reset TWI hardware state machine.) */
226 TWCR
= TWI_C_DISABLE
;
231 TWCR
= TWI_C_ENABLE
+ twps
;
234 void i2c_init(uint32_t speed
)
237 uint32_t tmptwbr
= F_CPU
/2 / speed
- 8;
239 while (tmptwbr
> 255) {
243 debug_cond((twps
> 3), "TWCLK too low: %lu Hz\n", speed
);
245 twbr
= (uint8_t) tmptwbr
;
250 int_fast8_t i2c_waitready(void)
252 uint32_t timer
= get_timer(0);
256 if (get_timer(timer
) >= 30) {
260 } while ((TWCR
& ((1<<TWIE
)|(1<<TWSTO
))) != 0 && !timeout
);
262 xmit
.stat
|= timeout
;
265 dump_ram((uint8_t *) &xmit
, 4, "=== i2c_wait ready: (done)");
272 int i2c_send(uint8_t chip
, uint16_t addr
, uint8_t alen
, uint8_t *buffer
, int8_t len
)
277 rc
= i2c_waitready();
278 if ((rc
& (BUSY
| TIMEOUT
)) != 0)
282 xmit
.buf
[0] = chip
<<1;
283 for (i
= 1; i
< alen
+1; i
++) {
284 xmit
.buf
[i
] = (uint8_t) addr
;
287 for (n
= len
+ i
; i
< n
; i
++)
288 xmit
.buf
[i
] = *buffer
++;
292 dump_ram((uint8_t *) &xmit
, 0x20, "=== i2c_send");
295 /* Enable TWI, TWI int and initiate start condition */
296 TWCR
= (1<<TWEN
)|(1<<TWIE
)|(1<<TWINT
)|(1<<TWSTA
);
304 int i2c_recv(uint8_t chip
, uint8_t *buffer
, int8_t len
)
308 rc
= i2c_waitready();
309 if ((rc
& (BUSY
| TIMEOUT
)) != 0)
314 xmit
.buf
[0] = (chip
<<1) | 1;
317 dump_ram((uint8_t *) &xmit
, 0x20, "=== i2c_recv: before start");
320 /* Enable TWI, TWI int and initiate start condition */
321 TWCR
= (1<<TWEN
)|(1<<TWIE
)|(1<<TWINT
)|(1<<TWSTA
);
322 rc
= i2c_waitready();
325 dump_ram((uint8_t *) &xmit
, 0x20, "=== i2c_recv: after completion");
329 /* at least 1 byte received */
330 for (uint8_t i
=1, n
=xmit
.idx
; i
< n
; i
++)
331 *buffer
++ = xmit
.buf
[i
];
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
344 * buffer: Where to read/write the data
345 * len: How many bytes to read/write
347 * Returns: 0 on success, not 0 on failure
350 int i2c_write(uint8_t chip
, unsigned int addr
, uint_fast8_t alen
,
351 uint8_t *buffer
, uint_fast8_t len
)
355 if ((alen
> 2) || (1 + alen
+ len
> CONFIG_SYS_I2C_BUFSIZE
)) {
356 debug("** i2c_write: buffer overflow, alen: %u, len: %u\n",
361 i2c_send(chip
, addr
, alen
, buffer
, len
);
362 rc
= i2c_waitready();
363 debug("** i2c_write: result=0x%02x\n",rc
);
365 return (rc
& XMIT_DONE
) != 0;
368 int i2c_read(uint8_t chip
, unsigned int addr
, uint_fast8_t alen
,
369 uint8_t *buffer
, uint_fast8_t len
)
373 if ((alen
> 2) || (1 + len
> CONFIG_SYS_I2C_BUFSIZE
)) {
374 debug("** i2c_read: parameter error: alen: %u, len: %u\n",
380 i2c_send(chip
, addr
, alen
, NULL
, 0);
382 rc
= i2c_recv(chip
, buffer
, len
);
383 debug("** i2c_read: result=0x%02x\n",rc
);
385 return !((rc
& (XMIT_DONE
|DATA_ACK
)) == (XMIT_DONE
|DATA_ACK
));