3 #include <avr/interrupt.h>
31 ST_ARBLOST_MATCH = 0x68,
33 ST_ARBLOST_GENMATCH = 0x78,
34 ST_SLAVE_RD_ACK = 0x80,
35 ST_SLAVE_RD_NACK = 0x88,
36 ST_SLAVE_GENRD_ACK = 0x90,
37 ST_SLAVE_GENRD_NACK = 0x98,
38 ST_SLAVE_STARTSTOP = 0xa0,
39 ST_SLAVE_SLA_WR_ACK = 0xa8,
40 ST_SLAVE_ARBLOST_WR_ACK = 0xb0,
41 ST_SLAVE_WR_ACK = 0xb8,
42 ST_SLAVE_WR_NACK = 0xc0,
43 ST_SLAVE_LAST_WR_ACK = 0xc8
55 #define TWINT_BIT (1 << TWINT)
56 #define TWEA_BIT (1 << TWEA)
57 #define TWSTA_BIT (1 << TWSTA)
58 #define TWSTO_BIT (1 << TWSTO)
59 #define TWEN_BIT (1 << TWEN)
60 #define TWIE_BIT (1 << TWIE)
62 #define I2C_START() (TWCR = TWINT_BIT | TWSTA_BIT | TWEN_BIT | TWIE_BIT)
63 #define I2C_STOP() (TWCR = TWINT_BIT | TWSTO_BIT | TWEN_BIT | TWIE_BIT)
64 #define I2C_WRITE() (TWCR = TWINT_BIT | TWEN_BIT | TWIE_BIT)
65 #define I2C_READ_ACK() (TWCR = TWINT_BIT | TWEA_BIT | TWEN_BIT | TWIE_BIT)
66 #define I2C_READ_NACK() (TWCR = TWINT_BIT | TWEN_BIT | TWIE_BIT)
68 static unsigned char i2c_addr, i2c_subaddr;
69 static volatile unsigned char i2c_mode;
70 static int i2c_seq, i2c_ndata;
71 static unsigned char *i2c_data;
73 static void (*async_func)(void);
77 TWBR = 10; /* 10 with 1x prescaler should make it about 100khz */
78 TWSR = 0; /* prescaler 1x */
81 TWCR = 0; /* I2C disabled by default */
87 void i2c_write(unsigned char addr, unsigned char subaddr, unsigned char *data, int ndata)
89 i2c_addr = addr & 0xfe;
90 i2c_subaddr = subaddr;
91 i2c_mode = I2C_MASTER_WRITE;
98 void i2c_read(unsigned char addr, unsigned char subaddr, unsigned char *buf, int size)
100 i2c_addr = addr & 0xfe;
101 i2c_subaddr = subaddr;
102 i2c_mode = I2C_MASTER_READ;
109 void i2c_handle_send(void)
111 unsigned char state = TWSR & 0xf8;
116 case ST_REP_START: /* 0x10 */
117 /* repeated start, same as start, but also increment i2c_seq */
119 case ST_START: /* 0x8 */
120 /* start initiated, write the slave address */
121 //printf("DBG i2c SLA: %x\n", (unsigned int)i2c_addr);
126 case ST_SLA_W_ACK: /* 0x18 */
127 /* slave addr sent and ACKed, send subaddr or data */
129 /* this is the first packet, send subaddr */
138 /* done sending, send stop */
145 case ST_SLA_W_NACK: /* 0x20 */
146 /* slave addr sent but not ACKed, abort */
149 printf("i2c: NACK after SLA+W\n");
152 case ST_WR_ACK: /* 0x28 */
153 /* data (or subaddr) sent and ACKed, send more data (or restart) if available */
156 /* subaddr was sent, send repeated start */
160 /* data was sent, send more data or stop */
171 case ST_WR_NACK: /* 0x30 */
172 /* data (or subaddr) sent but not ACKed */
174 /* NACK after subaddr, abort */
175 printf("i2c: NACK after subaddr\n");
177 /* NACK after data */
179 printf("i2c: NACK with %d pending\n", i2c_ndata);
186 case ST_ARBLOST: /* 0x38 */
187 /* arbitration lost */
188 printf("i2c: arb lost\n");
192 case ST_INVALID: /* 0 */
193 printf("i2c: invalid start/stop\n");
199 printf("i2c: unexpected state (W): 0x%x\n", state);
205 void i2c_handle_recv(void)
207 unsigned char state = TWSR & 0xf8;
212 case ST_START: /* 0x8 */
213 TWDR = i2c_addr; /* start a *write* (we need to send the subaddress before reading) */
217 case ST_REP_START: /* 0x10 */
218 /* repeated start, now we can issue the actual read */
223 case ST_SLA_W_ACK: /* 0x18 */
224 /* SLA+W means we just started the write part, need to send the subaddress */
230 /* slave addr sent but not ACKed, abort */
233 printf("i2c: NACK after SLA+W (R)\n");
236 case ST_WR_ACK: /* 0x28 */
237 /* the subaddress write was ACKed, rep-start to issue the read */
242 /* the subaddress write was not ACKed, abort */
245 printf("i2c: NACK after subaddr (R)\n");
248 case ST_SLA_R_ACK: /* 0x40 */
249 /* SLA+R was ACKed send ACK to start receiving */
253 case ST_RD_ACK: /* 0x50 */
254 /* ... or last read was ACKed, again read next and ACK for more */
256 if(--i2c_ndata > 0) {
263 case ST_SLA_R_NACK: /* 0x48 */
264 /* SLA+R was sent but ACK was not received, abort */
267 printf("i2c: NACK after SLA+R\n");
270 case ST_RD_NACK: /* 0x58 */
271 /* read without ACK, we get this after we send a NACK, or this is the last byte (?) */
280 case ST_ARBLOST: /* 0x38 */
281 /* arbitration lost */
282 printf("i2c: arb lost\n");
286 case ST_INVALID: /* 0 */
287 printf("i2c: invalid start/stop\n");
293 printf("i2c: unexpected state (R): 0x%x\n", state);
302 case I2C_MASTER_WRITE:
306 case I2C_MASTER_READ:
317 void i2c_async(void (*donecb)(void))
322 void i2c_check_async(void)
324 if(async_func && i2c_mode == I2C_IDLE) {
332 TWCR = 0; /* make sure the AVR i2c hardware is disabled */
333 DDRC |= PC_SCL; /* ... and drive SCL pin low */
339 void i2c_release(void)
346 unsigned char i2c_isheld(void)
348 return i2c_mode == I2C_HOLD;
353 if(i2c_mode != I2C_IDLE) {