avr: initial commit
[z80.git] / avr / i2c.c
diff --git a/avr/i2c.c b/avr/i2c.c
new file mode 100644 (file)
index 0000000..a970a38
--- /dev/null
+++ b/avr/i2c.c
@@ -0,0 +1,80 @@
+/* I2C communication */
+
+#include <stdio.h>
+
+#include <util/twi.h>
+
+#include "i2c.h"
+
+//#define I2C_DEBUG { printf("<0x%02x>", (TWSR & 0xF8)); }
+#define I2C_DEBUG
+
+void i2c_init(void)
+{
+       TWSR = 0;       /* Prescaler 1 */
+       TWBR = 12;      /* 72 = 100 kHz @ 16 MHz, 12 = 400 kHz @ 16 MHz */
+       TWCR = (1 << TWEN);     /* enable I2C pins */
+
+       /* test low address PCF8574 */
+       i2c_write(I2C_ALOW, 0x33); if(i2c_read(I2C_ALOW) != 0x33) while(1);
+       i2c_write(I2C_ALOW, 0x55); if(i2c_read(I2C_ALOW) != 0x55) while(1);
+       i2c_write(I2C_ALOW, 0xAA); if(i2c_read(I2C_ALOW) != 0xAA) while(1);
+       i2c_write(I2C_ALOW, 0xFF); if(i2c_read(I2C_ALOW) != 0xFF) while(1);
+
+       /* test high address PCF8574 */
+       i2c_write(I2C_AHIGH, 0x33); if(i2c_read(I2C_AHIGH) != 0x33) while(1);
+       i2c_write(I2C_AHIGH, 0x55); if(i2c_read(I2C_AHIGH) != 0x55) while(1);
+       i2c_write(I2C_AHIGH, 0xAA); if(i2c_read(I2C_AHIGH) != 0xAA) while(1);
+       i2c_write(I2C_AHIGH, 0xFF); if(i2c_read(I2C_AHIGH) != 0xFF) while(1);
+
+       /* test data PCF8574 */
+       i2c_write(I2C_DATA, 0x33); if(i2c_read(I2C_DATA) != 0x33) while(1);
+       i2c_write(I2C_DATA, 0x55); if(i2c_read(I2C_DATA) != 0x55) while(1);
+       i2c_write(I2C_DATA, 0xAA); if(i2c_read(I2C_DATA) != 0xAA) while(1);
+       i2c_write(I2C_DATA, 0xFF); if(i2c_read(I2C_DATA) != 0xFF) while(1);
+}
+
+static void i2c_start(void)
+{
+       TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN);       /* START */
+       while(!(TWCR & (1 << TWINT)));                          /* wait */
+       I2C_DEBUG;
+}
+
+static void i2c_stop(void)
+{
+       TWCR = (1 << TWINT) | (1 << TWSTO) | (1 << TWEN);       /* STOP */
+       I2C_DEBUG;
+}
+
+uint8_t i2c_read(uint8_t addr)
+{
+       uint8_t data;
+
+       i2c_start();
+       TWDR = (addr << 1) | 0x01;              /* target address */
+       TWCR = (1 << TWINT) | (1 << TWEN);      /* start transmission */
+       while(!(TWCR & (1 << TWINT)));          /* wait until done */
+       I2C_DEBUG;
+       TWCR = (1 << TWINT) | (1 << TWEN);      /* read date, NAK */
+       while(!(TWCR & (1 << TWINT)));          /* wait until done */
+       data = TWDR;
+       i2c_stop();
+
+       return(data);
+}
+
+void i2c_write(uint8_t addr, uint8_t data)
+{
+       i2c_start();
+       TWDR = (addr << 1);                     /* target address */
+       TWCR = (1 << TWINT) | (1 << TWEN);      /* start transmission */
+       while(!(TWCR & (1 << TWINT)));          /* wait until done */
+       I2C_DEBUG;
+       TWDR = data;
+       TWCR = (1 << TWINT) | (1 << TWEN);      /* receive data with NAK */
+       while(!(TWCR & (1 << TWINT)));          /* wait until done */
+       I2C_DEBUG;
+       i2c_stop();
+}
+