#include "i2c.h" #define I2CBASE 0xE001C000 #define I2CONSET 0x00 #define I2STAT 0x04 #define I2DAT 0x08 #define I2ADR 0x0c #define I2SCLH 0x10 #define I2SCLL 0x14 #define I2CONCLR 0x18 #define IREG(x) (((volatile unsigned char *)I2CBASE)[x]) #define IWREG(x) (((volatile unsigned int *)I2CBASE)[(x)/sizeof(unsigned int)]) #define AAFLAG (1<<2) #define SIFLAG (1<<3) #define STOFLAG (1<<4) #define STAFLAG (1<<5) #define SI (IREG(I2CONSET) & SIFLAG) void init_i2c(void) { IREG(I2CONSET) = 0x40; /* Enable I2C ready for Master Tx */ /* Set up for just under 400kHz */ #if 0 IWREG(I2SCLL) = (25 * 100); IWREG(I2SCLH) = (12 * 100); #else # if 0 IWREG(I2SCLL) = 1475; /* ~5kHz */ IWREG(I2SCLH) = 1475; # else IWREG(I2SCLL) = 73; /* ~100kHz */ IWREG(I2SCLH) = 73; # endif #endif } int i2cstat; int i2c_wait(void) { int stat; while (!SI); stat = IREG(I2STAT); i2cstat = stat; return stat; } int i2c_conreg(void) { return IREG(I2CONSET); } int i2c_statreg(void) { return IREG(I2STAT); } bool i2c_send_start(void) { IREG(I2CONCLR) = STOFLAG | STAFLAG; IREG(I2CONSET) = STAFLAG; switch (i2c_wait()) { case 0x08: case 0x10: return TRUE; default: i2c_send_stop(); return FALSE; } } bool i2c_send_address(int addr, bool write) { return i2c_send_data((addr<<1) + (write?0:1)); } bool i2c_send_data(int data) { IREG(I2DAT) = data; IREG(I2CONCLR) = STAFLAG | STOFLAG | SIFLAG; switch (i2c_wait()) { case 0x18: case 0x28: case 0x40: return TRUE; default: i2c_send_stop(); return FALSE; } } bool i2c_receive_data(int *data, bool last) { if (!last) IREG(I2CONSET) = AAFLAG; IREG(I2CONCLR) = STAFLAG | STOFLAG | SIFLAG | (last?AAFLAG:0); switch (i2c_wait()) { case 0x50: case 0x58: *data = IREG(I2DAT); return TRUE; default: i2c_send_stop(); return FALSE; } } void i2c_send_stop(void) { IREG(I2CONCLR) = STAFLAG | AAFLAG; IREG(I2CONSET) = STOFLAG; IREG(I2CONCLR) = SIFLAG; /* Don't think we need to wait here. Could be wrong. */ }