in lib/cmsis/CMSIS/Pack/Example/CMSIS_Driver/I2C_LPC18xx.c [720:834]
static uint32_t I2Cx_SlaveHandler (I2C_RESOURCES *i2c) {
uint32_t conset = 0;
uint32_t event = 0;
switch (i2c->reg->STAT & 0xF8) {
case I2C_STAT_SL_ALOST_GC:
/* Arbitration lost in General call */
i2c->ctrl->status.arbitration_lost = 1;
case I2C_STAT_SL_GCA_A:
/* General address recvd, ACK returned */
i2c->ctrl->status.general_call = 1;
goto slaw_a;
case I2C_STAT_SL_ALOST_MW:
/* Arbitration lost SLA+W */
i2c->ctrl->status.arbitration_lost = 1;
case I2C_STAT_SL_SLAW_A:
/* SLA+W received, ACK returned */
slaw_a:
/* Stalled Slave receiver also resumes here */
if (!i2c->ctrl->snum || !(i2c->ctrl->flags & I2C_FLAG_SLAVE_RX)) {
/* Receive buffer unavailable */
if (i2c->ctrl->stalled) {
/* Already stalled, abort transaction to prevent dead-loops */
event = ARM_I2C_EVENT_TRANSFER_DONE |
ARM_I2C_EVENT_TRANSFER_INCOMPLETE;
conset = I2C_CON_STO | i2c->ctrl->con_aa;
break;
}
/* Stall I2C transaction */
NVIC_DisableIRQ (i2c->i2c_ev_irq);
i2c->ctrl->stalled = I2C_SLAVE_RX;
return (ARM_I2C_EVENT_SLAVE_RECEIVE);
}
i2c->ctrl->status.direction = 1;
i2c->ctrl->status.busy = 1;
i2c->ctrl->cnt = 0;
i2c->ctrl->stalled = 0;
conset = I2C_CON_AA;
break;
case I2C_STAT_SL_DRGC_A:
/* Data recvd General call, ACK returned */
case I2C_STAT_SL_DR_A:
/* Data received, ACK returned */
i2c->ctrl->sdata[i2c->ctrl->cnt++] = i2c->reg->DAT;
i2c->ctrl->snum--;
if (i2c->ctrl->snum) {
conset = I2C_CON_AA;
}
break;
case I2C_STAT_SL_ALOST_MR:
/* Arbitration lost SLA+R */
i2c->ctrl->status.arbitration_lost = 1;
case I2C_STAT_SL_SLAR_A:
/* SLA+R received, ACK returned */
/* Stalled Slave transmitter also resumes here */
if (!i2c->ctrl->snum || (i2c->ctrl->flags & I2C_FLAG_SLAVE_RX)) {
/* Transmit buffer unavailable */
if (i2c->ctrl->stalled) {
/* Already stalled, abort transaction to prevent dead-loops */
event = ARM_I2C_EVENT_TRANSFER_DONE |
ARM_I2C_EVENT_TRANSFER_INCOMPLETE;
conset = I2C_CON_STO | i2c->ctrl->con_aa;
break;
}
NVIC_DisableIRQ (i2c->i2c_ev_irq);
i2c->ctrl->stalled = I2C_SLAVE_TX;
return (ARM_I2C_EVENT_SLAVE_TRANSMIT);
}
i2c->ctrl->status.direction = 0;
i2c->ctrl->status.busy = 1;
i2c->ctrl->cnt = 0;
i2c->ctrl->stalled = 0;
case I2C_STAT_SL_DT_A:
/* Data transmitted, ACK received */
i2c->reg->DAT = i2c->ctrl->sdata[i2c->ctrl->cnt++];
i2c->ctrl->snum--;
if (i2c->ctrl->snum) {
conset = I2C_CON_AA;
}
break;
case I2C_STAT_SL_DT_NA:
/* Data transmitted, no ACK received */
case I2C_STAT_SL_LDT_A:
/* Last data transmitted, ACK received */
case I2C_STAT_SL_DR_NA:
/* Data received, no ACK returned */
case I2C_STAT_SL_DRGC_NA:
/* Data recvd General call, no ACK returned */
case I2C_STAT_SL_STOP:
/* STOP received while addressed */
i2c->ctrl->status.busy = 0;
/* Slave operation completed, generate events */
event = ARM_I2C_EVENT_TRANSFER_DONE;
if (i2c->ctrl->status.arbitration_lost) {
event |= ARM_I2C_EVENT_ARBITRATION_LOST;
}
if (i2c->ctrl->status.general_call) {
event |= ARM_I2C_EVENT_GENERAL_CALL;
}
if (i2c->ctrl->snum) {
event |= ARM_I2C_EVENT_TRANSFER_INCOMPLETE;
}
conset = i2c->ctrl->con_aa;
break;
}
/* Set/clear control flags */
i2c->reg->CONSET = conset;
i2c->reg->CONCLR = conset ^ I2C_CON_FLAGS;
return (event);
}