rendered paste body/* I2C Module */#define I2C_FLAG_TX_DONE 0x1#define I2C_FLAG_RX_DONE 0x2#define I2C_FLAG_ERROR 0x80//#define I2C_LOG 1#ifdef I2C_LOG#define i2c_log(x) log(x, 0);#else#define i2c_log(x)#endif#define I2C_PROTOCOL_STATE 1#ifdef I2C_PROTOCOL_STATE#define I2C_STATE_S_TX 0x01#define I2C_STATE_TX_D1 0x02#define I2C_STATE_TX_DX 0x04#define I2C_STATE_S_RX 0x08#define I2C_STATE_RX_D1 0x10#define I2C_STATE_RX_DX 0x20#define I2C_STATE_P 0x40volatile uint8_t i2c_state = 0;#define i2c_resetState (i2c_state=0)#define i2c_state(x) (i2c_state|=(x))#else#define i2c_resetState(x)#define i2c_state(x)#endifvolatile uint8_t i2c_flags = 0;volatile const uint8_t* i2c_txBuffer;volatile uint8_t* i2c_rxBuffer;volatile uint8_t i2c_inBufferIndex = 0;volatile uint8_t i2c_txLength = 0;volatile uint8_t i2c_rxLength = 0;int i2c_TXRX(const uint8_t* txData, uint8_t txDataLength, uint8_t* rxData, uint8_t rxDataLength) { i2c_log("I2C TXRX\r\n"); i2c_txBuffer = txData; i2c_rxBuffer = rxData; i2c_txLength = txDataLength; i2c_rxLength = rxDataLength; i2c_inBufferIndex = 0; i2c_flags = 0; i2c_resetState; i2c_log(" I2C <-TX START-\r\n"); UCB0CTL1 |= UCTR; // Transmitter mode trigger(); while( UCB0STAT & UCBBUSY) ; i2c_state(I2C_STATE_S_TX); UCB0CTL1 |= UCTXSTT; // START condition while( 1 ) if( i2c_flags & I2C_FLAG_ERROR ) return 0; else if( i2c_flags & I2C_FLAG_RX_DONE ) return 1;}void i2cTransmitInterrupt() { IFG2 &= ~UCB0TXIFG; // Clear USCI_B0 TX interrupt flag i2c_log("\r\n >> I2C TX IR\r\n"); if( !(i2c_flags & I2C_FLAG_ERROR) && !(i2c_flags & I2C_FLAG_TX_DONE) ) { if( !(i2c_flags & I2C_FLAG_TX_DONE) && i2c_txLength > 0 ) { // TX if( i2c_inBufferIndex < i2c_txLength ) { uint16_t data = i2c_txBuffer[i2c_inBufferIndex++]; //while( !(UCB0STAT & UCSCLLOW) ) // Wait for SCL _held_ low // ; //__delay_cycles(140); <- DOESN"T WORK WITHOUT THOSE UCB0TXBUF = data; //__delay_cycles(140); <- DOESN"T WORK WITHOUT THOSE i2c_state(i2c_inBufferIndex == 1 ? I2C_STATE_TX_D1 : I2C_STATE_TX_DX);#ifdef I2C_LOG char text[32]; sprintf(text, " I2C <-%d/0x%x-\r\n", data, data); log(text, 1);#endif } if( i2c_inBufferIndex == i2c_txLength ) { // Last TX byte i2c_flags |= I2C_FLAG_TX_DONE; if( i2c_rxLength < 1 ) { i2c_log(" I2C <-TX STOP-\r\n"); UCB0CTL1 &= UCTXSTP; // STOP condition i2c_state(i2c_inBufferIndex == 1 ? I2C_STATE_TX_D1 : I2C_STATE_TX_DX); } } } if( !(UCB0CTL1 & UCTXSTT) && i2c_rxLength > 0 && (i2c_flags & I2C_FLAG_TX_DONE) ) { i2c_inBufferIndex = 0; i2c_log(" I2C <-RX START-\r\n"); UCB0CTL1 &= ~UCTR; // Receiver mode while( UCB0STAT & UCBBUSY) ; UCB0CTL1 |= UCTXSTT; // START condition IFG2 &= ~UCB0TXIFG; // Clear USCI_B0 TX interrupt flag i2c_state(I2C_STATE_P); if( i2c_rxLength == 1 ) { // Special case: send stop during RX while( UCB0CTL1 & UCTXSTT ) // Wait until RX starts ; i2c_log(" I2C <-RX STOP-\r\n"); UCB0CTL1 |= UCTXSTP; // STOP condition i2c_state(I2C_STATE_P); } } } i2c_log(" << I2C TX IR\r\n");}void i2cReceiveInterrupt() { IFG2 &= ~UCB0RXIFG; // Clear USCI_B0 RX interrupt flag i2c_log("\r\n >> I2C RX IR\r\n"); if( !(i2c_flags & I2C_FLAG_ERROR) ) { if( i2c_inBufferIndex >= i2c_rxLength ) { // Unexpected RX byte i2c_flags |= I2C_FLAG_ERROR; i2c_log(" I2C ERROR: extra RX byte\r\n"); } else { uint16_t data = UCB0RXBUF; i2c_state(i2c_inBufferIndex < 1 ? I2C_STATE_RX_D1 : I2C_STATE_RX_DX); i2c_rxBuffer[i2c_inBufferIndex++] = data;#ifdef I2C_LOG char text[32]; sprintf(text, " I2C -%d/0x%x-> \r\n", data, data); log(text, 1);#endif if( i2c_inBufferIndex == i2c_rxLength - 1 ) { // Last RX set up if( i2c_rxLength != 1 ) { // If 1 then this was already handled by i2cTransmitInterrupt() i2c_log(" I2C <-RX STOP-\r\n"); UCB0CTL1 |= UCTXSTP; // STOP condition i2c_state(I2C_STATE_P); } } else if( i2c_inBufferIndex == i2c_rxLength ) // Last RX byte received i2c_flags |= I2C_FLAG_RX_DONE; } } i2c_log(" << I2C RX IR\r\n");}void i2cNotAckInterrupt() { i2c_flags |= I2C_FLAG_ERROR; i2c_log("I2C ERROR: NACK\r\n"); UCB0STAT &= ~UCNACKIFG;}void i2cArbitrationLostInterrupt() { i2c_flags |= I2C_FLAG_ERROR; i2c_log("I2C ERROR: ARB LOST\r\n"); UCB0STAT &= ~UCALIFG;}/* End I2C Module */