예제 #1
0
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++;
    }
}
예제 #2
0
파일: twid.c 프로젝트: NissankaW/Mariokart3
//------------------------------------------------------------------------------
/// 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;
    }
}
예제 #3
0
파일: Wire.cpp 프로젝트: ektor5/Arduino
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);
		}
	}
}
예제 #4
0
파일: twid.c 프로젝트: copterpilot/bricklib
/**
 * \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);
        }
    }
}