avr: initial commit
[z80.git] / avr / i2c.c
1 /* I2C communication */
2
3 #include <stdio.h>
4
5 #include <util/twi.h>
6
7 #include "i2c.h"
8
9 //#define I2C_DEBUG { printf("<0x%02x>", (TWSR & 0xF8)); }
10 #define I2C_DEBUG
11
12 void i2c_init(void)
13 {
14         TWSR = 0;       /* Prescaler 1 */
15         TWBR = 12;      /* 72 = 100 kHz @ 16 MHz, 12 = 400 kHz @ 16 MHz */
16         TWCR = (1 << TWEN);     /* enable I2C pins */
17
18         /* test low address PCF8574 */
19         i2c_write(I2C_ALOW, 0x33); if(i2c_read(I2C_ALOW) != 0x33) while(1);
20         i2c_write(I2C_ALOW, 0x55); if(i2c_read(I2C_ALOW) != 0x55) while(1);
21         i2c_write(I2C_ALOW, 0xAA); if(i2c_read(I2C_ALOW) != 0xAA) while(1);
22         i2c_write(I2C_ALOW, 0xFF); if(i2c_read(I2C_ALOW) != 0xFF) while(1);
23
24         /* test high address PCF8574 */
25         i2c_write(I2C_AHIGH, 0x33); if(i2c_read(I2C_AHIGH) != 0x33) while(1);
26         i2c_write(I2C_AHIGH, 0x55); if(i2c_read(I2C_AHIGH) != 0x55) while(1);
27         i2c_write(I2C_AHIGH, 0xAA); if(i2c_read(I2C_AHIGH) != 0xAA) while(1);
28         i2c_write(I2C_AHIGH, 0xFF); if(i2c_read(I2C_AHIGH) != 0xFF) while(1);
29
30         /* test data PCF8574 */
31         i2c_write(I2C_DATA, 0x33); if(i2c_read(I2C_DATA) != 0x33) while(1);
32         i2c_write(I2C_DATA, 0x55); if(i2c_read(I2C_DATA) != 0x55) while(1);
33         i2c_write(I2C_DATA, 0xAA); if(i2c_read(I2C_DATA) != 0xAA) while(1);
34         i2c_write(I2C_DATA, 0xFF); if(i2c_read(I2C_DATA) != 0xFF) while(1);
35 }
36
37 static void i2c_start(void)
38 {
39         TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN);       /* START */
40         while(!(TWCR & (1 << TWINT)));                          /* wait */
41         I2C_DEBUG;
42 }
43
44 static void i2c_stop(void)
45 {
46         TWCR = (1 << TWINT) | (1 << TWSTO) | (1 << TWEN);       /* STOP */
47         I2C_DEBUG;
48 }
49
50 uint8_t i2c_read(uint8_t addr)
51 {
52         uint8_t data;
53
54         i2c_start();
55         TWDR = (addr << 1) | 0x01;              /* target address */
56         TWCR = (1 << TWINT) | (1 << TWEN);      /* start transmission */
57         while(!(TWCR & (1 << TWINT)));          /* wait until done */
58         I2C_DEBUG;
59         TWCR = (1 << TWINT) | (1 << TWEN);      /* read date, NAK */
60         while(!(TWCR & (1 << TWINT)));          /* wait until done */
61         data = TWDR;
62         i2c_stop();
63
64         return(data);
65 }
66
67 void i2c_write(uint8_t addr, uint8_t data)
68 {
69         i2c_start();
70         TWDR = (addr << 1);                     /* target address */
71         TWCR = (1 << TWINT) | (1 << TWEN);      /* start transmission */
72         while(!(TWCR & (1 << TWINT)));          /* wait until done */
73         I2C_DEBUG;
74         TWDR = data;
75         TWCR = (1 << TWINT) | (1 << TWEN);      /* receive data with NAK */
76         while(!(TWCR & (1 << TWINT)));          /* wait until done */
77         I2C_DEBUG;
78         i2c_stop();
79 }
80