The unified diff between revisions [7ac10cd3..] and [dcfa34d1..] is displayed below. It can also be downloaded as a raw diff.
This diff has been restricted to the following files: 'i2c.c'
# # old_revision [7ac10cd34167baa43683a09e9e9e6778e691171d] # new_revision [dcfa34d1bbf576aab0f0d0ed1b0c64dc6160ee5b] # # add_file "i2c.c" # content [1d978ba6c211e6b68c567fa852d9cbefe8ebad13] # ============================================================ --- /dev/null +++ i2c.c 1d978ba6c211e6b68c567fa852d9cbefe8ebad13 @@ -0,0 +1,120 @@ + +#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(unsigned 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(unsigned 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. */ +} +