void TWI1_IrqHandler(void) { unsigned int status = TWI_GetStatus(TWI_STACK); if(((status & TWI_SR_SVACC) == TWI_SR_SVACC) && (eeprom.acquire == 0)) { TWI_DisableIt(TWI_STACK, TWI_IER_SVACC); TWI_EnableIt(TWI_STACK, TWI_IER_RXRDY | TWI_IER_GACC | TWI_IER_NACK | TWI_IER_EOSACC | TWI_IER_SCL_WS); eeprom.acquire++; eeprom.page = 0; eeprom.offset = 0; } if(((status & TWI_SR_SVACC) == TWI_SR_SVACC) && ((status & TWI_SR_GACC) == 0) && ((status & TWI_SR_RXRDY) == TWI_SR_RXRDY)) { if(eeprom.acquire == 1) { // Acquire LSB address eeprom.page = (TWI_ReadByte(TWI_STACK) & 0xFF); eeprom.acquire++; } else if(eeprom.acquire == 2) { // Acquire MSB address eeprom.page |= (TWI_ReadByte(TWI_STACK) & 0xFF) << 8; eeprom.acquire++; } else { // Read one byte of data from master to slave device uint16_t addr = I2C_EEPROM_PAGE_SIZE*eeprom.page + eeprom.offset; i2c_eeprom_slave_set_memory(addr, TWI_ReadByte(TWI_STACK) & 0xFF); eeprom.offset++; } } else if(((status & TWI_SR_TXRDY) == TWI_SR_TXRDY) && ((status & TWI_SR_TXCOMP) == TWI_SR_TXCOMP) && ((status & TWI_SR_EOSACC) == TWI_SR_EOSACC)) { // End of transfer, end of slave access eeprom.offset = 0; eeprom.acquire = 0; eeprom.page = 0; TWI_EnableIt(TWI_STACK, TWI_IER_SVACC); TWI_DisableIt(TWI_STACK, TWI_IER_RXRDY | TWI_IDR_GACC | TWI_IDR_NACK | TWI_IER_EOSACC | TWI_IER_SCL_WS); } else if(((status & TWI_SR_SVACC) == TWI_SR_SVACC) && ((status & TWI_SR_GACC) == 0) && (eeprom.acquire == 3) && ((status & TWI_SR_SVREAD) == TWI_SR_SVREAD) && ((status & TWI_SR_NACK) == 0)) { // Write one byte of data from slave to master device uint16_t addr = I2C_EEPROM_PAGE_SIZE*eeprom.page + eeprom.offset; TWI_WriteByte(TWI_STACK, i2c_eeprom_slave_get_memory(addr)); eeprom.offset++; } }
//------------------------------------------------------------------------------ /// Interrupt handler for a TWI peripheral. Manages asynchronous transfer /// occuring on the bus. This function MUST be called by the interrupt service /// routine of the TWI peripheral if asynchronous read/write are needed. /// \param pTwid Pointer to a Twid instance. //------------------------------------------------------------------------------ void TWID_Handler(Twid *pTwid) { unsigned char status; AsyncTwi *pTransfer = (AsyncTwi *) pTwid->pTransfer; AT91S_TWI *pTwi = pTwid->pTwi; SANITY_CHECK(pTwid); // Retrieve interrupt status status = TWI_GetMaskedStatus(pTwi); // Byte received if (TWI_STATUS_RXRDY(status)) { pTransfer->pData[pTransfer->transferred] = TWI_ReadByte(pTwi); pTransfer->transferred++; // Transfer finished ? if (pTransfer->transferred == pTransfer->num) { TWI_DisableIt(pTwi, AT91C_TWI_RXRDY); TWI_EnableIt(pTwi, AT91C_TWI_TXCOMP); } // Last byte ? else if (pTransfer->transferred == (pTransfer->num - 1)) { TWI_Stop(pTwi); } } // Byte sent else if (TWI_STATUS_TXRDY(status)) { // Transfer finished ? if (pTransfer->transferred == pTransfer->num) { TWI_DisableIt(pTwi, AT91C_TWI_TXRDY); TWI_EnableIt(pTwi, AT91C_TWI_TXCOMP); TWI_SendSTOPCondition(pTwi); } // Bytes remaining else { TWI_WriteByte(pTwi, pTransfer->pData[pTransfer->transferred]); pTransfer->transferred++; } } // Transfer complete else if (TWI_STATUS_TXCOMP(status)) { TWI_DisableIt(pTwi, AT91C_TWI_TXCOMP); pTransfer->status = 0; if (pTransfer->callback) { pTransfer->callback((Async *) pTransfer); } pTwid->pTransfer = 0; } }
void TwoWire::onService(void) { // Retrieve interrupt status uint32_t sr = TWI_GetStatus(twi); if (status == SLAVE_IDLE && TWI_STATUS_SVACC(sr)) { TWI_DisableIt(twi, TWI_IDR_SVACC); TWI_EnableIt(twi, TWI_IER_RXRDY | TWI_IER_GACC | TWI_IER_NACK | TWI_IER_EOSACC | TWI_IER_SCL_WS | TWI_IER_TXCOMP); srvBufferLength = 0; srvBufferIndex = 0; // Detect if we should go into RECV or SEND status // SVREAD==1 means *master* reading -> SLAVE_SEND if (!TWI_STATUS_SVREAD(sr)) { status = SLAVE_RECV; } else { status = SLAVE_SEND; // Alert calling program to generate a response ASAP if (onRequestCallback) onRequestCallback(); else // create a default 1-byte response write((uint8_t) 0); } } if (status != SLAVE_IDLE) { if (TWI_STATUS_TXCOMP(sr) && TWI_STATUS_EOSACC(sr)) { if (status == SLAVE_RECV && onReceiveCallback) { // Copy data into rxBuffer // (allows to receive another packet while the // user program reads actual data) for (uint8_t i = 0; i < srvBufferLength; ++i) rxBuffer[i] = srvBuffer[i]; rxBufferIndex = 0; rxBufferLength = srvBufferLength; // Alert calling program onReceiveCallback( rxBufferLength); } // Transfer completed TWI_EnableIt(twi, TWI_SR_SVACC); TWI_DisableIt(twi, TWI_IDR_RXRDY | TWI_IDR_GACC | TWI_IDR_NACK | TWI_IDR_EOSACC | TWI_IDR_SCL_WS | TWI_IER_TXCOMP); status = SLAVE_IDLE; } } if (status == SLAVE_RECV) { if (TWI_STATUS_RXRDY(sr)) { if (srvBufferLength < BUFFER_LENGTH) srvBuffer[srvBufferLength++] = TWI_ReadByte(twi); } } if (status == SLAVE_SEND) { if (TWI_STATUS_TXRDY(sr) && !TWI_STATUS_NACK(sr)) { uint8_t c = 'x'; if (srvBufferIndex < srvBufferLength) c = srvBuffer[srvBufferIndex++]; TWI_WriteByte(twi, c); } } }
/** * \brief Interrupt handler for a TWI peripheral. Manages asynchronous transfer * occuring on the bus. This function MUST be called by the interrupt service * routine of the TWI peripheral if asynchronous read/write are needed. * \param pTwid Pointer to a Twid instance. */ void TWID_Handler( Twid *pTwid ) { uint8_t status; AsyncTwi *pTransfer ; Twi *pTwi ; assert( pTwid != NULL ) ; pTransfer = (AsyncTwi*)pTwid->pTransfer ; assert( pTransfer != NULL ) ; pTwi = pTwid->pTwi ; assert( pTwi != NULL ) ; /* Retrieve interrupt status */ status = TWI_GetMaskedStatus(pTwi); /* Byte received */ if (TWI_STATUS_RXRDY(status)) { pTransfer->pData[pTransfer->transferred] = TWI_ReadByte(pTwi); pTransfer->transferred++; /* check for transfer finish */ if (pTransfer->transferred == pTransfer->num) { TWI_DisableIt(pTwi, TWI_IDR_RXRDY); TWI_EnableIt(pTwi, TWI_IER_TXCOMP); } /* Last byte? */ else if (pTransfer->transferred == (pTransfer->num - 1)) { TWI_Stop(pTwi); } } /* Byte sent*/ else if (TWI_STATUS_TXRDY(status)) { /* Transfer finished ? */ if (pTransfer->transferred == pTransfer->num) { TWI_DisableIt(pTwi, TWI_IDR_TXRDY); TWI_EnableIt(pTwi, TWI_IER_TXCOMP); TWI_SendSTOPCondition(pTwi); } /* Bytes remaining */ else { TWI_WriteByte(pTwi, pTransfer->pData[pTransfer->transferred]); pTransfer->transferred++; } } /* Transfer complete*/ else if (TWI_STATUS_TXCOMP(status)) { TWI_DisableIt(pTwi, TWI_IDR_TXCOMP); pTransfer->status = 0; pTwid->pTransfer = 0; if (pTransfer->callback) { pTransfer->callback((Async *) pTransfer); } } }