int i2c_slave_read(i2c_t *obj, char *data, int length) { int count = 0; int status; do { i2c_clear_SI(obj); i2c_wait_SI(obj); status = i2c_status(obj); if((status == 0x80) || (status == 0x90)) { data[count] = I2C_DAT(obj) & 0xFF; } count++; } while (((status == 0x80) || (status == 0x90) || (status == 0x060) || (status == 0x70)) && (count < length)); // Clear old status and wait for Serial Interrupt. i2c_clear_SI(obj); i2c_wait_SI(obj); // Obtain new status. status = i2c_status(obj); if(status != 0xA0) { i2c_stop(obj); } i2c_clear_SI(obj); return count; }
int i2c_write(i2c_t *obj, int address, const char *data, int length, int stop) { int i, status; status = i2c_start(obj); if ((status != 0x10) && (status != 0x08)) { i2c_stop(obj); return status; } status = i2c_do_write(obj, (address & 0xFE), 1); if (status != 0x18) { i2c_stop(obj); return status; } for (i=0; i<length; i++) { status = i2c_do_write(obj, data[i], 0); if(status != 0x28) { i2c_stop(obj); return status; } } i2c_clear_SI(obj); // If not repeated start, send stop. if (stop) { i2c_stop(obj); } return 0; }
inline int i2c_start(i2c_t *obj) { int status = 0; int isInterrupted = I2C_CONSET(obj) & (1 << 3); // 8.1 Before master mode can be entered, I2CON must be initialised to: // - I2EN STA STO SI AA - - // - 1 0 0 x x - - // if AA = 0, it can't enter slave mode i2c_conclr(obj, 1, 1, 0, 1); // The master mode may now be entered by setting the STA bit // this will generate a start condition when the bus becomes free i2c_conset(obj, 1, 0, 0, 1); // Clearing SI bit when it wasn't set on entry can jump past state // 0x10 or 0x08 and erroneously send uninitialized slave address. if (isInterrupted) i2c_clear_SI(obj); i2c_wait_SI(obj); status = i2c_status(obj); // Clear start bit now that it's transmitted i2c_conclr(obj, 1, 0, 0, 0); return status; }
int i2c_write(i2c_t *obj, int address, const char *data, int length, int stop) { int i, status; status = i2c_start(obj); if ((status != 0x10) && (status != 0x08)) { i2c_stop(obj); return status; } status = i2c_do_write(obj, (address & 0xFE)); if (status != 0x18) { i2c_stop(obj); return status; } for (i=0; i<length; i++) { status = i2c_do_write(obj, data[i]); if(status != 0x28) { i2c_stop(obj); return status; } } i2c_clear_SI(obj); if (stop) { if(i2c_stop(obj) == 1) return 1; } return 0; }
inline void i2c_stop(i2c_t *obj) { // write the stop bit i2c_conset(obj, 0, 1, 0, 0); i2c_clear_SI(obj); // wait for STO bit to reset while(I2C_CONSET(obj) & (1 << 4)); }
static inline int i2c_do_write(i2c_t *obj, int value, uint8_t addr) { // write the data I2C_DAT(obj) = value; // clear SI to init a send i2c_clear_SI(obj); // wait and return status i2c_wait_SI(obj); return i2c_status(obj); }
int i2c_slave_read(i2c_t *obj, char *data, int length) { int count = 0; int status; do { i2c_clear_SI(obj); i2c_wait_SI(obj); status = i2c_status(obj); if((status == 0x80) || (status == 0x90)) { data[count] = I2C_DAT(obj) & 0xFF; } count++; } while (((status == 0x80) || (status == 0x90) || (status == 0x060) || (status == 0x70)) && (count < length)); if(status != 0xA0) { i2c_stop(obj); } i2c_clear_SI(obj); return count; }
inline int i2c_stop(i2c_t *obj) { int timeout = 0; // write the stop bit i2c_conset(obj, 0, 1, 0, 0); i2c_clear_SI(obj); // wait for STO bit to reset while(I2C_CONSET(obj) & (1 << 4)) { timeout ++; if (timeout > 100000) return 1; } return 0; }
static inline int i2c_do_read(i2c_t *obj, int last) { // we are in state 0x40 (SLA+R tx'd) or 0x50 (data rx'd and ack) if(last) { i2c_conclr(obj, 0, 0, 0, 1); // send a NOT ACK } else { i2c_conset(obj, 0, 0, 0, 1); // send a ACK } // accept byte i2c_clear_SI(obj); // wait for it to arrive i2c_wait_SI(obj); // return the data return (I2C_DAT(obj) & 0xFF); }
int i2c_slave_write(i2c_t *obj, const char *data, int length) { int count = 0; int status; if(length <= 0) { return(0); } do { status = i2c_do_write(obj, data[count], 0); count++; } while ((count < length) && (status == 0xB8)); if ((status != 0xC0) && (status != 0xC8)) { i2c_stop(obj); } i2c_clear_SI(obj); return(count); }