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; } |