Exemple #1
0
void TWI_WriteBytes(uint8_t SLA, uint8_t address ,uint8_t size, uint8_t* buffer)
{
	TWI_Start();
	TWI_Write_SLA(SLA);
	TWI_WriteByte(address);
	while (size--) TWI_WriteByte(*buffer++);
	TWI_Stop();
}
Exemple #2
0
//
//	Originally, 'endTransmission' was an f(void) function.
//	It has been modified to take one parameter indicating
//	whether or not a STOP should be performed on the bus.
//	Calling endTransmission(false) allows a sketch to
//	perform a repeated start.
//
//	WARNING: Nothing in the library keeps track of whether
//	the bus tenure has been properly ended with a STOP. It
//	is very possible to leave the bus in a hung state if
//	no call to endTransmission(true) is made. Some I2C
//	devices will behave oddly if they do not see a STOP.
//
uint8_t TwoWire::endTransmission(uint8_t sendStop) {
	uint8_t error = 0;
	// transmit buffer (blocking)
	TWI_StartWrite(twi, txAddress, 0, 0, txBuffer[0]);
	if (!TWI_WaitByteSent(twi, XMIT_TIMEOUT))
		error = 2;	// error, got NACK on address transmit
	
	if (error == 0) {
		uint16_t sent = 1;
		while (sent < txBufferLength) {
			TWI_WriteByte(twi, txBuffer[sent++]);
			if (!TWI_WaitByteSent(twi, XMIT_TIMEOUT))
				error = 3;	// error, got NACK during data transmmit
		}
	}
	
	if (error == 0) {
		TWI_Stop(twi);
		if (!TWI_WaitTransferComplete(twi, XMIT_TIMEOUT))
			error = 4;	// error, finishing up
	}

	txBufferLength = 0;		// empty buffer
	status = MASTER_IDLE;
	return error;
}
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++;
    }
}
Exemple #4
0
/**
 * @ Brief  	Starts illuminance measurement.
 * @ Parameter  mode: measurement mode.
 * @ Retval 	None
 */
void BH1750_Start(uint8_t mode)
{
	mode_ = mode;
	TWI_Start();
	TWI_Write_SLA(BH1750_SLA);
	TWI_WriteByte(mode_);
	TWI_Stop();
}
Exemple #5
0
//------------------------------------------------------------------------------
/// 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;
    }
}
Exemple #6
0
/**
 * @ Brief  	Switches the sensor to power down mode.
 * @ Parameter  None.
 * @ Retval 	None
 */
void BH1750_PowerDown()
{
	//BH1750_DVI_PORT &= ~(BH1750_Power_OFF << BH1750_DVI_PIN);
	state_ = BH1750_Power_OFF;
	TWI_Start();
	TWI_Write_SLA(BH1750_SLA);
	TWI_WriteByte(BH1750_Power_OFF);
	TWI_Stop();
}
Exemple #7
0
/**
 * @ Brief  	Switches the sensor to power on mode.
 * @ Parameter  None.
 * @ Retval 	None
 */
void BH1750_PowerOn()
{
	_delay_us(5);
	//BH1750_DVI_PORT |= BH1750_Power_ON << BH1750_DVI_PIN;
	state_ = BH1750_Power_ON;
	TWI_Start();
	TWI_Write_SLA(BH1750_SLA);
	TWI_WriteByte(BH1750_Power_ON);
	TWI_Stop();
}
Exemple #8
0
/**
 * @ Brief  	Resets the BH1750 data register. After that, switches
 * 				sensor to power down mode.
 * @ Parameter  None.
 * @ Retval 	None.
 */
void BH1750_ResetDR()
{
	if(state_ == BH1750_Power_OFF) BH1750_PowerOn();

	TWI_Start();
	TWI_Write_SLA(BH1750_SLA);
	TWI_WriteByte(BH1750_RESET);
	TWI_Stop();

	BH1750_PowerDown();
}
Exemple #9
0
/**
 * \brief Asynchronously sends data to a slave on the TWI bus. An optional callback
 * function is invoked whenever the transfer is complete.
 * \param pTwid  Pointer to a Twid instance.
 * \param address  TWI slave address.
 * \param iaddress  Optional slave internal address.
 * \param isize  Number of internal address bytes.
 * \param pData  Data buffer for storing received bytes.
 * \param num  Data buffer to send.
 * \param pAsync  Asynchronous transfer descriptor.
 * \return 0 if the transfer has been started; otherwise returns a TWI error code.
 */
uint8_t TWID_Write(
    Twi *pTwi,
    uint8_t address,
    uint32_t iaddress,
    uint8_t isize,
    uint8_t *pData,
    uint32_t num)
{
    //Twi *pTwi = pTwid->pTwi;
    uint32_t timeout;

    assert( pTwi != NULL ) ;
    assert( (address & 0x80) == 0 ) ;
    assert( (iaddress & 0xFF000000) == 0 ) ;
    assert( isize < 4 ) ;


    /* Synchronous transfer*/
    // Start write
    TWI_StartWrite(pTwi, address, iaddress, isize, *pData++);
    num--;

    /* Send all bytes */
    while (num > 0) {

        /* Wait before sending the next byte */
        timeout = 0;
        while( !TWI_ByteSent(pTwi) && (++timeout<TWITIMEOUTMAX) );
        if (timeout == TWITIMEOUTMAX) {
            TRACE_ERROR("TWID Timeout BS\n\r");
        }

        TWI_WriteByte(pTwi, *pData++);
        num--;
    }

    /* Wait for actual end of transfer */
    timeout = 0;

    /* Send a STOP condition */
    TWI_SendSTOPCondition(pTwi);

    while( !TWI_TransferComplete(pTwi) && (++timeout<TWITIMEOUTMAX) );
    if (timeout == TWITIMEOUTMAX) {
        TRACE_ERROR("TWID Timeout TC2\n\r");
    }

    return 0;
}
bool i2c_eeprom_master_write(Twi *twi,
                             const uint16_t internal_address,
                             const char *data,
                             const uint16_t length) {
	uint32_t timeout;

	mutex_take(mutex_twi_bricklet, MUTEX_BLOCKING);

    // Start write
	TWI_StartWrite(twi,
	               bricklet_eeprom_address,
	               internal_address,
	               I2C_EEPROM_INTERNAL_ADDRESS_BYTES,
	               data[0]);

    for(uint16_t i = 1; i < length; i++) {
    	timeout = 0;
    	// Wait until byte is sent, otherwise return false
		while(!TWI_ByteSent(twi) && (++timeout < I2C_EEPROM_TIMEOUT)) {}

		if(timeout == I2C_EEPROM_TIMEOUT) {
			logieew("write timeout (nothing sent)\n\r");
			mutex_give(mutex_twi_bricklet);
			return false;
		}
        TWI_WriteByte(twi, data[i]);
    }

    // Send STOP
    TWI_SendSTOPCondition(twi);

    timeout = 0;
	// Wait for transfer to be complete
	while(!TWI_TransferComplete(twi) && (++timeout < I2C_EEPROM_TIMEOUT)) {}

	if (timeout == I2C_EEPROM_TIMEOUT) {
		logieew("write timeout (transfer incomplete)\n\r");
		mutex_give(mutex_twi_bricklet);
		return false;
	}

	// Wait at least 5ms between writes (see m24128-bw.pdf)
	SLEEP_MS(5);

	mutex_give(mutex_twi_bricklet);
	return true;
}
/**********************************************
 * \brief 
 *
 *
 * \return none
 */
result_t HalExpansionPortClass::writePcaPorts(uint32_t iRegister, uint8_t *pBuffer, uint32_t bufLength) {

uint32_t bufCnt=bufLength;
uint32_t breakOut_cnt=0;
result_t retResult=SUCCESS;

	TWI_StartWrite(HW_ADDR_TWI_PCA9698,HW_PCA9698_TwiAddr, iRegister,HW_PCA9698_InternalAddrLen,*pBuffer);
	pBuffer++;
	bufCnt--;

	while(bufCnt >0) {
		//if no NACK and Byte sent, then transmit next one
		if (TWI_SR_NACK & TWI_GetStatus(HW_ADDR_TWI_PCA9698)) {
						  dbgOut1(eDbgAll_errEvt,'B',"HalTwiPca Unexpected NACK ",bufCnt);
			retResult=FAIL;
			break;
		}
		if (!TWI_ByteSent(HW_ADDR_TWI_PCA9698)) {
		   if (90000 < ++breakOut_cnt) {
			  dbgOut1(eDbgAll_errEvt,'B',"HalTwiPca TWI_SR_TXRDY exceeded ",bufCnt);
			  retResult=FAIL;
			  break; //Out while
			}
			continue;				
		}
		breakOut_cnt = 0;
		TWI_WriteByte(HW_ADDR_TWI_PCA9698,*pBuffer);
		pBuffer++;
		bufCnt--;
	}
	
TWI_Stop(HW_ADDR_TWI_PCA9698);
while (!TWI_TransferComplete(HW_ADDR_TWI_PCA9698)) {
	if (90000 < ++breakOut_cnt) {
	   dbgOut(eDbgAll_errEvt,'B',"HalTwiPca TWI_SR_TXCOMP exceeded ");
	   break; //Out while
	}
}
 
 return retResult;
 }//portInit
Exemple #12
0
void TWI_ReadBytes(uint8_t SLA, uint8_t address ,uint8_t size, uint8_t* buffer)
{
	TWI_Start();
	TWI_Write_SLA(SLA);
	TWI_WriteByte(address);
	TWI_RStart();
	TWI_Write_SLA(SLA+1);
	//while (size--) *buffer++ = size ? TWI_ReadByte_ACK() : ( len ? ACK : NACK );
	while(size--)
	{
		*buffer++ = size ? TWI_ReadByte_ACK() : TWI_ReadByte_NACK();
	}


	/*
	for (uint8_t i=0; i<size-1; i++) {
		buffer[i] = TWI_ReadByte_ACK();
	}
	buffer[size-1]=TWI_ReadByte_NACK();
	*/
}
Exemple #13
0
//
//	Originally, 'endTransmission' was an f(void) function.
//	It has been modified to take one parameter indicating
//	whether or not a STOP should be performed on the bus.
//	Calling endTransmission(false) allows a sketch to
//	perform a repeated start.
//
//	WARNING: Nothing in the library keeps track of whether
//	the bus tenure has been properly ended with a STOP. It
//	is very possible to leave the bus in a hung state if
//	no call to endTransmission(true) is made. Some I2C
//	devices will behave oddly if they do not see a STOP.
//
uint8_t TwoWire::endTransmission(uint8_t sendStop) {
	// transmit buffer (blocking)
	TWI_StartWrite(twi, txAddress, 0, 0, txBuffer[0]);
	TWI_WaitByteSent(twi, XMIT_TIMEOUT);
	
	int sent = 1;
	
	while (sent < txBufferLength) {
		TWI_WriteByte(twi, txBuffer[sent++]);
		TWI_WaitByteSent(twi, XMIT_TIMEOUT);
	}
	
	TWI_Stop( twi);
	TWI_WaitTransferComplete(twi, XMIT_TIMEOUT);
	
	// empty buffer
	txBufferLength = 0;

	status = MASTER_IDLE;
	return sent;
}
Exemple #14
0
unsigned char WriteAccelData(unsigned int iaddress, char *bytes, unsigned int num)
{
	unsigned int timeout;
	
	// wait for TWI bus to be ready
	while(!(TWI_TransferComplete(AT91C_BASE_TWI))) nop();
	
	// Start Writing
	TWI_StartWrite(AT91C_BASE_TWI,ACCELADDR,iaddress,1,*bytes++);
	num--;
	
	while(num > 0){
		// Wait before sending the next byte
		timeout = 0;
		while(!TWI_ByteSent(AT91C_BASE_TWI) && (++timeout<TWITIMEOUTMAX)) nop();
		if(timeout == TWITIMEOUTMAX) return 1;
		TWI_WriteByte(AT91C_BASE_TWI, *bytes++);
		num--;
	}
	
	return 0;
}
//-----------------------------------------------------------------------------
/// Starts a write operation on the TWI to access the selected slave, then
/// returns immediately. A byte of data must be provided to start the write;
/// other bytes are written next.
/// \param pTwi  Pointer to an AT91S_TWI instance.
/// \param address  Address of slave to acccess on the bus.
/// \param iaddress  Optional slave internal address.
/// \param isize  Number of internal address bytes.
/// \param byte  First byte to send.
//-----------------------------------------------------------------------------
void TWI_StartWrite(
    AT91S_TWI *pTwi,
    unsigned char address,
    unsigned int iaddress,
    unsigned char isize,
    unsigned char byte)
{
    trace_LOG(trace_DEBUG, "-D- TWI_StartWrite()\n\r");
    SANITY_CHECK(pTwi);
    SANITY_CHECK((address & 0x80) == 0);
    SANITY_CHECK((iaddress & 0xFF000000) == 0);
    SANITY_CHECK(isize < 4);

    // Set slave address and number of internal address bytes
    pTwi->TWI_MMR = (isize << 8) | (address << 16);

    // Set internal address bytes
    pTwi->TWI_IADR = iaddress;

    // Write first byte to send
    TWI_WriteByte(pTwi, byte);
}
Exemple #16
0
/**
 * \brief Starts a write operation on the TWI to access the selected slave, then
 *  returns immediately. A byte of data must be provided to start the write;
 * other bytes are written next.
 * after that to send the remaining bytes.
 * \param pTwi  Pointer to an Twi instance.
 * \param address  Address of slave to acccess on the bus.
 * \param iaddress  Optional slave internal address.
 * \param isize  Number of internal address bytes.
 * \param byte  First byte to send.
 */
void TWI_StartWrite(
    Twi *pTwi,
    uint8_t address,
    uint32_t iaddress,
    uint8_t isize,
    uint8_t byte)
{
    assert( pTwi != NULL ) ;
    assert( (address & 0x80) == 0 ) ;
    assert( (iaddress & 0xFF000000) == 0 ) ;
    assert( isize < 4 ) ;

    /* Set slave address and number of internal address bytes. */
    pTwi->TWI_MMR = 0;
    pTwi->TWI_MMR = (isize << 8) | (address << 16);

    /* Set internal address bytes. */
    pTwi->TWI_IADR = 0;
    pTwi->TWI_IADR = iaddress;

    /* Write first byte to send.*/
    TWI_WriteByte(pTwi, byte);
}
Exemple #17
0
/**
 * \brief Asynchronously sends data to a slave on the TWI bus. An optional callback
 * function is invoked whenever the transfer is complete.
 * \param pTwid  Pointer to a Twid instance.
 * \param address  TWI slave address.
 * \param iaddress  Optional slave internal address.
 * \param isize  Number of internal address bytes.
 * \param pData  Data buffer for storing received bytes.
 * \param num  Data buffer to send.
 * \param pAsync  Asynchronous transfer descriptor.
 * \return 0 if the transfer has been started; otherwise returns a TWI error code.
 */
uint8_t TWID_Write(
    Twid *pTwid,
    uint8_t address,
    uint32_t iaddress,
    uint8_t isize,
    uint8_t *pData,
    uint32_t num,
    Async *pAsync)
{
    Twi *pTwi = pTwid->pTwi;
    AsyncTwi *pTransfer = (AsyncTwi *) pTwid->pTransfer;
    uint32_t timeout;

    assert( pTwi != NULL ) ;
    assert( (address & 0x80) == 0 ) ;
    assert( (iaddress & 0xFF000000) == 0 ) ;
    assert( isize < 4 ) ;

    /* Check that no transfer is already pending */
    if (pTransfer) {

        TRACE_ERROR("TWI_Write: A transfer is already pending\n\r");
        return TWID_ERROR_BUSY;
    }

    /* Asynchronous transfer */
    if (pAsync) {

        /* Update the transfer descriptor */
        pTwid->pTransfer = pAsync;
        pTransfer = (AsyncTwi *) pAsync;
        pTransfer->status = ASYNC_STATUS_PENDING;
        pTransfer->pData = pData;
        pTransfer->num = num;
        pTransfer->transferred = 1;

        /* Enable write interrupt and start the transfer */
        TWI_StartWrite(pTwi, address, iaddress, isize, *pData);
        TWI_EnableIt(pTwi, TWI_IER_TXRDY);
    }
    /* Synchronous transfer*/
    else {

        // Start write
        TWI_StartWrite(pTwi, address, iaddress, isize, *pData++);
        num--;

        /* Send all bytes */
        while (num > 0) {

            /* Wait before sending the next byte */
            timeout = 0;
            while( !TWI_ByteSent(pTwi) && (++timeout<TWITIMEOUTMAX) );
            if (timeout == TWITIMEOUTMAX) {
                TRACE_ERROR("TWID Timeout BS\n\r");
            }

            TWI_WriteByte(pTwi, *pData++);
            num--;
        }

        /* Wait for actual end of transfer */
        timeout = 0;

        /* Send a STOP condition */
        TWI_SendSTOPCondition(pTwi);

        while( !TWI_TransferComplete(pTwi) && (++timeout<TWITIMEOUTMAX) );
        if (timeout == TWITIMEOUTMAX) {
            TRACE_ERROR("TWID Timeout TC2\n\r");
        }

    }

    return 0;
}
Exemple #18
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);
		}
	}
}
Exemple #19
0
//------------------------------------------------------------------------------
/// Asynchronously sends data to a slave on the TWI bus. An optional callback
/// function is invoked whenever the transfer is complete.
/// \param pTwid  Pointer to a Twid instance.
/// \param address  Slave address.
/// \param iaddress  Optional slave internal address.
/// \param isize  Number of internal address bytes.
/// \param pData  Data buffer to send.
/// \param num  Number of bytes to send.
/// \param pAsync  Pointer to an Asynchronous transfer descriptor.
//------------------------------------------------------------------------------
unsigned char TWID_Write(
    Twid *pTwid,
    unsigned char address,
    unsigned int iaddress,
    unsigned char isize,
    unsigned char *pData,
    unsigned int num,
    Async *pAsync)
{
    AT91S_TWI *pTwi = pTwid->pTwi;
    AsyncTwi *pTransfer = (AsyncTwi *) pTwid->pTransfer;
    unsigned int timeout;

    //TRACE_DEBUG("TWID_Write()\n\r");
    //TRACE_DEBUG("0x%X\n\r", pData[0]);
    SANITY_CHECK(pTwi);
    SANITY_CHECK((address & 0x80) == 0);
    SANITY_CHECK((iaddress & 0xFF000000) == 0);
    SANITY_CHECK(isize < 4);

    // Check that no transfer is already pending
    if (pTransfer) {

        TRACE_ERROR("TWI_Write: A transfer is already pending\n\r");
        return TWID_ERROR_BUSY;
    }

    // Asynchronous transfer
    if (pAsync) {
    
        // Update the transfer descriptor
        pTwid->pTransfer = pAsync;
        pTransfer = (AsyncTwi *) pAsync;
        pTransfer->status = ASYNC_STATUS_PENDING;
        pTransfer->pData = pData;
        pTransfer->num = num;
        pTransfer->transferred = 1;
    
        // Enable write interrupt and start the transfer
        TWI_StartWrite(pTwi, address, iaddress, isize, *pData);
        TWI_EnableIt(pTwi, AT91C_TWI_TXRDY);
    }
    // Synchronous transfer
    else {

        // Start write
        TWI_StartWrite(pTwi, address, iaddress, isize, *pData++);
        num--;

        // Send all bytes
        while (num > 0) {
        
            // Wait before sending the next byte
            timeout = 0;
            while( !TWI_ByteSent(pTwi) && (++timeout<TWITIMEOUTMAX) );
            if (timeout == TWITIMEOUTMAX) {
                TRACE_ERROR("TWID Timeout BS\n\r");
                return TWID_ERROR_TIMEOUT;
            }

            TWI_WriteByte(pTwi, *pData++);
            num--;
        }

        // Wait for actual end of transfer
        timeout = 0;

#ifdef TWI_V3XX
        // Send a STOP condition
        TWI_SendSTOPCondition(pTwi);
#endif

        while( !TWI_TransferComplete(pTwi) && (++timeout<TWITIMEOUTMAX) );
        if (timeout == TWITIMEOUTMAX) {
            TRACE_ERROR("TWID Timeout TC2\n\r");
            return TWID_ERROR_TIMEOUT;
        }

    }
    
    return 0;
}
Exemple #20
0
/**
 * \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);
        }
    }
}