void I2C0_IRQHandler(void){
uint8_t done = 0;
volatile static struct I2C_MESSAGE rx_msg;
volatile static uint8_t data_ptr = 0;
uint8_t error_flag = 0;
switch(LPC_I2C0->I2STAT){
case I2C_START:
case I2C_REP_START:
//Send address
LPC_I2C0->I2DAT = (twi_msg.address << 1) | ((twi_msg.rw == I2C_READ) ? 1 : 0);
//Send SLA + R or W
if(twi_msg.rw == I2C_READ){
//Signal read
//LPC_I2C0->I2CONCLR = ((1<<I2C_SI)|(1<<I2C_STA));
LPC_I2C0->I2CONCLR = ((1<<I2C_SI)|(1<<I2C_STO));
}else{
//Reset data pointer
data_ptr = 0;
//LPC_I2C0->I2CONCLR = ((1<<I2C_SI)|(1<<I2C_STA));
LPC_I2C0->I2CONCLR = ((1<<I2C_SI)|(1<<I2C_STO));
}
break;
case I2C_MT_SLA_ACK:
if((data_ptr < TWI_DATA_SIZE) && (--twi_msg.size >= 0)){
LPC_I2C0->I2DAT = twi_msg.data[data_ptr++];
LPC_I2C0->I2CONCLR = (1 << I2C_STA) | (1 << I2C_STO) | (1 << I2C_SI);
}else{
//flag error
twi_error = TWI_TX_SIZE_MISMATCH;
//load next message
if(read_tx_queue(&twi_msg) == I2C_SUCCESS){
I2C_GEN_I2C_START();
}else{
I2C_GEN_I2C_STOP();
in_use = 0;
}
}
break;
case I2C_MT_SLA_NACK:
//flag error
twi_error = TWI_WRITE_ADDRESS_NACK;
error_flag = 1;
case I2C_MR_SLA_NACK:
//flag error
if(!error_flag){
twi_error = TWI_READ_ADDRESS_NACK;
}
//load next message
if(read_tx_queue(&twi_msg) == I2C_SUCCESS){
I2C_GEN_I2C_START();
}else{
I2C_GEN_I2C_STOP();
in_use = 0;
}
break;
case I2C_MT_DATA_ACK:
if(((--twi_msg.size) >= 0) && (data_ptr < TWI_DATA_SIZE)){
LPC_I2C0->I2DAT = twi_msg.data[data_ptr++];
LPC_I2C0->I2CONCLR = (1 << I2C_STA) | (1 << I2C_STO) | (1 << I2C_SI);
}else if(read_tx_queue(&twi_msg) == I2C_SUCCESS){
//flag error because the size expected did not match
twi_error = TWI_TX_SIZE_MISMATCH;
I2C_GEN_I2C_START();
}else{
//flag error because the size expected did not match
twi_error = TWI_TX_SIZE_MISMATCH;
I2C_GEN_I2C_STOP();
in_use = 0;
}
break;
case I2C_MT_DATA_NACK:
//Check if nack is normal
if(twi_msg.size != 0){
//flag error
twi_error = TWI_TX_SIZE_MISMATCH;
}
//load next message
if(read_tx_queue(&twi_msg) == I2C_SUCCESS){
I2C_GEN_I2C_START();
}else{
I2C_GEN_I2C_STOP();
in_use = 0;
}
break;
case I2C_MT_ARB_LOST:
//case I2C_MR_ARB_LOST:
//flag error
twi_error = TWI_ARBITRATION_LOST;
//Try transmission again
I2C_GEN_I2C_START();
break;
case I2C_MR_SLA_ACK:
if(twi_msg.size > 1){
LPC_I2C0->I2CONSET = (1<<I2C_AA);
LPC_I2C0->I2CONCLR = (1 << I2C_STA) | (1 << I2C_STO) | (1 << I2C_SI);
}else{
LPC_I2C0->I2CONCLR = ((1 << I2C_STA) | (1 << I2C_STO) | (1 << I2C_SI) | (1 << I2C_AA));
}
rx_msg.address = twi_msg.address;
break;
case I2C_MR_DATA_ACK:
//Save message data
rx_msg.data[rx_msg.size++] = LPC_I2C0->I2DAT;
//Reduce size to receive
if(--twi_msg.size){
if(twi_msg.size > 1){
LPC_I2C0->I2CONSET = (1<<I2C_AA);
LPC_I2C0->I2CONCLR = (1 << I2C_STA) | (1 << I2C_STO) | (1 << I2C_SI);
}else{
LPC_I2C0->I2CONCLR = ((1 << I2C_STA) | (1 << I2C_STO) | (1 << I2C_SI) | (1 << I2C_AA));
}
}else if(read_tx_queue(&twi_msg) == I2C_SUCCESS){
//flag error because the size expected did not match
twi_error = TWI_RX_SIZE_MISMATCH;
//Flag rx message done
done = 1;
//Restart
I2C_GEN_I2C_START();
}else{
//flag error because the size expected did not match
twi_error = TWI_RX_SIZE_MISMATCH;
//Flag rx message done
done = 1;
//Stop
I2C_GEN_I2C_STOP();
in_use = 0;
}
if(done){
write_rx_queue((struct I2C_MESSAGE*)&rx_msg);
rx_msg.size = 0;
}
break;
case I2C_MR_DATA_NACK:
//Store data
rx_msg.data[rx_msg.size++] = LPC_I2C0->I2DAT;
//Check if all expected data was received
if(--twi_msg.size){
twi_error = TWI_RX_SIZE_MISMATCH;
}
//Push rx message in queue
write_rx_queue((struct I2C_MESSAGE*)&rx_msg);
rx_msg.size = 0;
//load next message
if(read_tx_queue(&twi_msg) == I2C_SUCCESS){
I2C_GEN_I2C_START();
}else{
I2C_GEN_I2C_STOP();
in_use = 0;
}
break;
default:
//Save message data
rx_msg.data[rx_msg.size++] = LPC_I2C0->I2DAT;
//flag error
twi_error = TWI_UNEXPECTED_ERROR;
//load next message
if(read_tx_queue(&twi_msg) == I2C_SUCCESS){
I2C_GEN_I2C_START();
}else{
I2C_GEN_I2C_STOP();
in_use = 0;
}
break;
} |