/*! \brief TWI slave write interrupt handler. * * Handles TWI slave write transactions and responses. * * \param twi The TWI_Slave_t struct instance. */ void TWI_SlaveWriteHandler(TWI_Slave_t *twi) { /* If NACK, slave write transaction finished. */ if ((twi->bytesSent > 0) && (twi->interface->SLAVE.STATUS & TWI_SLAVE_RXACK_bm)) { twi->interface->SLAVE.CTRLB = TWI_SLAVE_CMD_COMPTRANS_gc; TWI_SlaveTransactionFinished(twi, TWIS_RESULT_OK); } /* If ACK, master expects more data. */ else { if (twi->bytesSent < TWIS_SEND_BUFFER_SIZE) { uint8_t data = twi->sendData[twi->bytesSent]; twi->interface->SLAVE.DATA = data; twi->bytesSent++; /* Send data, wait for data interrupt. */ twi->interface->SLAVE.CTRLB = TWI_SLAVE_CMD_RESPONSE_gc; } /* If buffer overflow. */ else { twi->interface->SLAVE.CTRLB = TWI_SLAVE_CMD_COMPTRANS_gc; TWI_SlaveTransactionFinished(twi, TWIS_RESULT_BUFFER_OVERFLOW); } } }
/**************************************************************************//** \brief TWI slave read interrupt handler. Handles TWI slave read transactions and responses. \param twi The TWI_Slave_t struct instance. ******************************************************************************/ static void TWI_SlaveReadHandler(TWI_Slave_t *twi) { /* Enable stop interrupt. */ uint8_t currentCtrlA = twi->interface->SLAVE.CTRLA; twi->interface->SLAVE.CTRLA = currentCtrlA | TWI_SLAVE_PIEN_bm; /* If free space in buffer. */ if (twi->bytesReceived < TWIS_RECEIVE_BUFFER_SIZE) { /* Fetch data */ uint8_t data = twi->interface->SLAVE.DATA; twi->receivedData[twi->bytesReceived] = data; twi->bytesReceived++; /* If application signalling need to abort (error occured), * complete transaction and wait for next START. Otherwise * send ACK and wait for data interrupt. */ if (twi->abort) { twi->interface->SLAVE.CTRLB = TWI_SLAVE_CMD_COMPTRANS_gc; TWI_SlaveTransactionFinished(twi, TWIS_RESULT_ABORTED); twi->abort = false; } else { twi->interface->SLAVE.CTRLB = TWI_SLAVE_CMD_RESPONSE_gc; } } /* If buffer overflow, send NACK and wait for next START. Set * result buffer overflow. */ else { twi->interface->SLAVE.CTRLB = TWI_SLAVE_ACKACT_bm | TWI_SLAVE_CMD_COMPTRANS_gc; TWI_SlaveTransactionFinished(twi, TWIS_RESULT_BUFFER_OVERFLOW); } }
/*! \brief TWI stop condition interrupt handler. * * \param twi The TWI_Slave_t struct instance. */ static void TWI_SlaveStopHandler(TWI_Slave_t *twi) { /* Disable stop interrupt. */ uint8_t currentCtrlA = twi->interface->SLAVE.CTRLA; twi->interface->SLAVE.CTRLA = currentCtrlA & ~TWI_SLAVE_PIEN_bm; uint8_t currentStatus = twi->interface->SLAVE.STATUS; twi->interface->SLAVE.STATUS = currentStatus | TWI_SLAVE_APIF_bm; TWI_SlaveTransactionFinished(twi, TWIS_RESULT_OK); }
/*! \brief TWI slave write interrupt handler. * * Handles TWI slave write transactions and responses. * * \param twi The TWI_Slave_t struct instance. */ static void TWI_SlaveWriteHandler(TWI_Slave_t *twi) { /* If NACK, slave write transaction finished. */ if ((twi->bytesSent > 0) && (twic_status_reg & TWI_SLAVE_RXACK_bm)) { //init first byte to write twic_data_reg = twi->sendData[0]; TWI_SlaveTransactionFinished(twi, TWIS_RESULT_OK); } /* If ACK, master expects more data. */ else { if (twi->bytesSent < TWIS_SEND_BUFFER_SIZE) { twi->bytesSent++; uint8_t data = twi->sendData[twi->bytesSent]; twic_data_reg = data; } else { /* If buffer overflow. */ TWI_SlaveTransactionFinished(twi, TWIS_RESULT_BUFFER_OVERFLOW); } } }
/*! \brief TWI stop condition interrupt handler. * * \param twi The TWI_Slave_t struct instance. */ void TWI_SlaveStopHandler(TWI_Slave_t * twi) { /* Disable stop interrupt. */ uint8_t currentCtrlA = twi->interface->SLAVE.CTRLA; twi->interface->SLAVE.CTRLA = currentCtrlA & ~TWI_SLAVE_PIEN_bm; /* Clear APIF, according to flowchart don't ACK or NACK */ uint8_t currentStatus = twi->interface->SLAVE.STATUS; twi->interface->SLAVE.STATUS = currentStatus | TWI_SLAVE_APIF_bm; TWI_SlaveTransactionFinished(twi, TWIS_RESULT_OK); }
/*! \brief Common TWI slave interrupt service routine. * * Handles all TWI transactions and responses to address match, data reception, * data transmission, bus error and data collision. * * \param twi The TWI_Slave_t struct instance. */ void TWI_SlaveInterruptHandler(TWI_Slave_t *twi) { //static uint8_t sent_NACK = 0; //!< Holds whether NACK has been transmitted uint8_t currentStatus = twi->interface->SLAVE.STATUS; twi->interface->SLAVE.CTRLB &= ~TWI_SLAVE_ACKACT_bm; //!< Clear ACKACT /* If bus error. */ if (currentStatus & TWI_SLAVE_BUSERR_bm) { twi->bytesReceived = 0; twi->bytesSent = 0; twi->result = TWIS_RESULT_BUS_ERROR; twi->status = TWIS_STATUS_READY; } /* If transmit collision. */ else if (currentStatus & TWI_SLAVE_COLL_bm) { twi->bytesReceived = 0; twi->bytesSent = 0; twi->result = TWIS_RESULT_TRANSMIT_COLLISION; twi->status = TWIS_STATUS_READY; } /* If address match. */ else if ((currentStatus & TWI_SLAVE_APIF_bm) && (currentStatus & TWI_SLAVE_AP_bm)) { TWI_SlaveAddressMatchHandler(twi); } /* If stop (only enabled through slave read transaction). */ else if (currentStatus & TWI_SLAVE_APIF_bm) { TWI_SlaveStopHandler(twi); } /* If data interrupt. */ else if (currentStatus & TWI_SLAVE_DIF_bm) { TWI_SlaveDataHandler(twi); } /* If unexpected state. */ else { TWI_SlaveTransactionFinished(twi, TWIS_RESULT_FAIL); } }
/**************************************************************************//** \brief TWI stop condition interrupt handler. \param twi The TWI_Slave_t struct instance. ******************************************************************************/ static void TWI_SlaveStopHandler(TWI_Slave_t *twi) { /* Disable stop interrupt. */ uint8_t currentCtrlA = twi->interface->SLAVE.CTRLA; twi->interface->SLAVE.CTRLA = currentCtrlA & ~TWI_SLAVE_PIEN_bm; /* Clear APIF, according to flowchart don't ACK or NACK */ uint8_t currentStatus = twi->interface->SLAVE.STATUS; twi->interface->SLAVE.STATUS = currentStatus | TWI_SLAVE_APIF_bm; // Process the received data. TwiDataParser(twiSlave); TWI_SlaveTransactionFinished(twi, TWIS_RESULT_OK); // Flush the buffers used. flush_Twibuffer(); }
/*! \brief TWI address match interrupt handler. * * Prepares TWI module for transaction when an address match occures. * * \param twi The TWI_Slave_t struct instance. */ void TWI_SlaveAddressMatchHandler(TWI_Slave_t *twi) { /* If application signalling need to abort (error occured). */ if (twi->abort) { twi->interface->SLAVE.CTRLB = TWI_SLAVE_CMD_COMPTRANS_gc; TWI_SlaveTransactionFinished(twi, TWIS_RESULT_ABORTED); twi->abort = false; } else { twi->status = TWIS_STATUS_BUSY; twi->result = TWIS_RESULT_UNKNOWN; /* Disable stop interrupt. */ uint8_t currentCtrlA = twi->interface->SLAVE.CTRLA; twi->interface->SLAVE.CTRLA = currentCtrlA & ~TWI_SLAVE_PIEN_bm; twi->bytesReceived = 0; twi->bytesSent = 0; /* Send ACK, wait for data interrupt. */ twi->interface->SLAVE.CTRLB = TWI_SLAVE_CMD_RESPONSE_gc; } }