int I2C::write(int address, const char *data, int length, bool repeated) { unsigned char addr = (unsigned char)address>>1; for (int i = 0; i < length; i++) I2CMasterTXBuffer[i] = *data++; I2C_MstSend( LPC_I2C, address, (uint8_t *)I2CMasterTXBuffer, length); return length; }
/***************************************************************************** ** Function name: I2C_MstSendRcv ** ** Descriptions: Send a block of data to the I2C port combining master ** send and master recevie with repeated start in the middle. ** ** parameters: Dev addr. TX ptr, TX length, RX ptr, and RX length. ** Returned value: None ** *****************************************************************************/ void I2C_MstSendRcv( LPC_I2C_TypeDef *I2Cx, uint32_t addr, uint8_t *tx, uint32_t txlen, uint8_t *rx, uint32_t rxlen ) { uint32_t i; I2Cx->MSTDAT = addr; I2Cx->MSTCTL = CTL_MSTSTART; #if I2C_INTERRUPT msttxrdy = mstrxrdy = 0; I2Cx->INTENSET = STAT_MSTPEND; #endif for ( i = 0; i < txlen; i++ ) { #if I2C_INTERRUPT while(!msttxrdy) { if ( I2C_CheckError(I2Cx) ) { I2C_CheckIdle(I2Cx); /* Recursive call here. Be very careful with stack over flow if come here, especially when the other master trys to grab the bus all the time. */ // while ( 1 ); I2C_MstSend( I2Cx, addr, tx, txlen ); return; } } msttxrdy = 0; I2Cx->MSTDAT = *tx++; I2Cx->MSTCTL = CTL_MSTCONTINUE; I2Cx->INTENSET = STAT_MSTPEND; #else /* Move only if TXRDY is ready */ while (!(I2Cx->STAT & STAT_MSTPEND)); if((I2Cx->STAT & MASTER_STATE_MASK) != STAT_MSTTX) while(1); I2Cx->MSTDAT = *tx++; I2Cx->MSTCTL = CTL_MSTCONTINUE; #endif } /* Wait for the last TX to finish before setting repeated start. */ #if I2C_INTERRUPT while(!msttxrdy) { if ( I2C_CheckError(I2Cx) ) { I2C_CheckIdle(I2Cx); /* Recursive call here. Be very careful with stack over flow if come here. especially when the other master trys to grab the bus all the time. */ // while ( 1 ); I2C_MstSend( I2Cx, addr, tx, txlen ); return; } } msttxrdy = 0; #else /* Move on only if TXRDY is ready */ while (!(I2Cx->STAT & STAT_MSTPEND)); if((I2Cx->STAT & MASTER_STATE_MASK) != STAT_MSTTX) while(1); #endif /* Repeated Start */ I2Cx->MSTDAT = addr|RD_BIT; I2Cx->MSTCTL = CTL_MSTSTART|CTL_MSTCONTINUE; #if I2C_INTERRUPT I2Cx->INTENSET = STAT_MSTPEND; #endif for ( i = 0; i < rxlen; i++ ) { #if I2C_INTERRUPT while(!mstrxrdy) { if ( I2C_CheckError(I2Cx) ) { I2C_CheckIdle(I2Cx); /* Recursive call here. Be very careful with stack over flow if come here, especially when the other master trys to grab the bus all the time. */ // while ( 1 ); I2C_MstReceive( I2Cx, addr|RD_BIT, rx, rxlen ); return; } } mstrxrdy = 0; *rx++ = I2Cx->MSTDAT; if ( i != rxlen-1 ) { I2Cx->MSTCTL = CTL_MSTCONTINUE; I2Cx->INTENSET = STAT_MSTPEND; } #else /* Slave address has been sent, master receive is ready. */ while (!(I2Cx->STAT & STAT_MSTPEND)); if((I2Cx->STAT & MASTER_STATE_MASK) != STAT_MSTRX) while(1); *rx++ = I2Cx->MSTDAT; if ( i != rxlen-1 ) { I2Cx->MSTCTL = CTL_MSTCONTINUE; } #endif } I2Cx->MSTCTL = CTL_MSTSTOP | CTL_MSTCONTINUE; I2C_CheckIdle(I2Cx); return; }
/***************************************************************************** ** Function name: I2C_MstSend ** ** Descriptions: Send a block of data to the I2C port, the ** first parameter is the device addre, the 2nd is buffer ** pointer, the 3rd is the block length. ** ** parameters: device addr, buffer pointer, and the block length ** Returned value: None ** *****************************************************************************/ void I2C_MstSend( LPC_I2C_TypeDef *I2Cx, uint32_t addr, uint8_t *tx, uint32_t Length ) { uint32_t i; I2Cx->MSTDAT = addr; I2Cx->MSTCTL = CTL_MSTSTART; #if I2C_INTERRUPT msttxrdy = 0; I2Cx->INTENSET = STAT_MSTPEND; #endif #if I2C_INTERRUPT for ( i = 0; i < Length; i++ ) { while(!msttxrdy) { if ( I2C_CheckError(I2Cx) ) { I2C_CheckIdle(I2Cx); /* Recursive call here. Be very careful with stack over flow if come here, especially when the other master trys to grab the bus all the time. */ // while ( 1 ); I2C_MstSend( I2Cx, addr, tx, Length ); return; } } msttxrdy = 0; I2Cx->MSTDAT = tx[i]; I2Cx->MSTCTL = CTL_MSTCONTINUE; I2Cx->INTENSET = STAT_MSTPEND; } /* Wait for the last one to go out. */ while(!msttxrdy) { if ( I2C_CheckError(I2Cx) ) { I2C_CheckIdle(I2Cx); /* Recursive call here. Be very careful with stack over flow if come here. especially when the other master trys to grab the bus all the time. */ // while ( 1 ); I2C_MstSend( I2Cx, addr, tx, Length ); return; } } msttxrdy = 0; #else for ( i = 0; i < Length; i++ ) { /* Move only if TXRDY is ready */ while (!(I2Cx->STAT & STAT_MSTPEND)); if((I2Cx->STAT & MASTER_STATE_MASK) != STAT_MSTTX) while(1); I2Cx->MSTDAT = *tx++; I2Cx->MSTCTL = CTL_MSTCONTINUE; } /* Wait for the last one to go out. */ while (!(I2Cx->STAT & STAT_MSTPEND)); if((I2Cx->STAT & MASTER_STATE_MASK) != STAT_MSTTX) while(1); #endif /* Send STOP condition. */ I2Cx->MSTCTL = CTL_MSTSTOP | CTL_MSTCONTINUE; I2C_CheckIdle(I2Cx); return; }