/******************************************************************************
*
* This function fills the FIFO using the occupancy register to determine the
* available space to be filled. When the repeated start option is on, the last
* byte is withheld to allow the control register to be properly set on the last
* byte.
*
* @param    InstancePtr is a pointer to the XIic instance to be worked on.
*
* @param    Role indicates the role of this IIC device, a slave or a master, on
*           the IIC bus (XIIC_SLAVE_ROLE or XIIC_MASTER_ROLE)
*
* @return
*
* None.
*
* @note
*
* None.
*
******************************************************************************/
void XIic_TransmitFifoFill(XIic * InstancePtr, int Role)
{
	u8 AvailBytes;
	int LoopCnt;
	int NumBytesToSend;

	/* Determine number of bytes to write to FIFO. Number of bytes that can be
	 * put into the FIFO is (FIFO depth) - (current occupancy + 1)
	 * When more room in FIFO than msg bytes put all of message in the FIFO.
	 */
	AvailBytes = IIC_TX_FIFO_DEPTH -
		(XIo_In8(InstancePtr->BaseAddress + XIIC_TFO_REG_OFFSET) + 1);

	if (InstancePtr->SendByteCount > AvailBytes) {
		NumBytesToSend = AvailBytes;
	}
	else {
		/* More space in FIFO than bytes in message
		 */
		if ((InstancePtr->Options & XII_REPEATED_START_OPTION) ||
		    (Role == XIIC_SLAVE_ROLE)) {
			NumBytesToSend = InstancePtr->SendByteCount;
		}
		else {
			NumBytesToSend = InstancePtr->SendByteCount - 1;
		}
	}

	/* fill FIFO with amount determined above */

	for (LoopCnt = 0; LoopCnt < NumBytesToSend; LoopCnt++) {
		XIic_mWriteSendByte(InstancePtr);
	}
}
Exemple #2
0
/******************************************************************************
*
* When the IIC Tx FIFO/register goes empty, this routine is called by the
* interrupt service routine to fill the transmit FIFO with data to be sent.
*
* This function also is called by the Tx ½ empty interrupt as the data handling
* is identical when you don't assume the FIFO is empty but use the Tx_FIFO_OCY
* register to indicate the available free FIFO bytes.
*
* @param    InstancePtr is a pointer to the XIic instance to be worked on.
*
* @return
*
* None.
*
* @note
*
* None.
*
******************************************************************************/
static void SendMasterData(XIic * InstancePtr)
{
	u8 CntlReg;

	/* The device is a master on the bus.  If there is still more address bytes
	 * to send when in master receive operation and the slave device is 10 bit
	 * addressed. This requires the lower 7 bits of address to be resent when
	 * the mode switches to Read instead of write (while sending addresses).
	 */
	if (InstancePtr->TxAddrMode & XIIC_TX_ADDR_MSTR_RECV_MASK) {
		/* Send the 1st byte of the slave address in the read operation
		 * and change the state to indicate this has been done
		 */
		SendSlaveAddr(InstancePtr);
		InstancePtr->TxAddrMode = XIIC_TX_ADDR_SENT;
	}

	/* In between 1st and last byte of message, fill the FIFO with more data
	 * to send, disable the 1/2 empty interrupt based upon data left to send
	 */
	else if (InstancePtr->SendByteCount > 1) {
		XIic_TransmitFifoFill(InstancePtr, XIIC_MASTER_ROLE);

		if (InstancePtr->SendByteCount < 2) {
			XIic_mDisableIntr(InstancePtr->BaseAddress,
					  XIIC_INTR_TX_HALF_MASK);
		}
	}
	/*
	 * If there is only one byte left to send, processing differs between
	 * repeated start and normal messages
	 */
	else if (InstancePtr->SendByteCount == 1) {
		/* When using repeated start, another interrupt is expected after the
		 * last byte has been sent, so the message is not done yet
		 */
		if (InstancePtr->Options & XII_REPEATED_START_OPTION) {
			XIic_mWriteSendByte(InstancePtr);
		}

		/* When not using repeated start, the stop condition must be generated
		 * after the last byte is written. The bus is throttled waiting for the last
		 * byte.
		 */
		else {
			/* Set the stop condition before sending the last byte of data so that
			 * the stop condition will be generated immediately following the data
			 * another transmit interrupt is not expected so the message is done
			 */

			CntlReg =
			    XIo_In8(InstancePtr->BaseAddress +
				    XIIC_CR_REG_OFFSET);
			CntlReg &= ~XIIC_CR_MSMS_MASK;
			XIo_Out8(InstancePtr->BaseAddress + XIIC_CR_REG_OFFSET,
				 CntlReg);

			XIic_mWriteSendByte(InstancePtr);

			/* Wait for bus to not be busy before declaring message has
			 * been sent for the no repeated start operation. The callback
			 * will be called from the BusNotBusy part of the Interrupt
			 * handler to ensure that the message is completely sent.
			 * Disable the TX interrupts and enable the BNB interrupt
			 */

			InstancePtr->BNBOnly = FALSE;
			XIic_mDisableIntr(InstancePtr->BaseAddress,
					  XIIC_TX_INTERRUPTS);
			XIic_mEnableIntr(InstancePtr->BaseAddress,
					 XIIC_INTR_BNB_MASK);

		}
	} else {
		if (InstancePtr->Options & XII_REPEATED_START_OPTION) {
			/* The message being sent has completed. When using repeated start
			 * with no more bytes to send repeated start needs to be set in
			 * the control register so that the bus will still be held by this
			 * master
			 */

			CntlReg =
			    XIo_In8(InstancePtr->BaseAddress +
				    XIIC_CR_REG_OFFSET);
			CntlReg |= XIIC_CR_REPEATED_START_MASK;
			XIo_Out8(InstancePtr->BaseAddress + XIIC_CR_REG_OFFSET,
				 CntlReg);

			/* If the message that was being sent has finished, disable all
			 *transmit interrupts and call the callback that was setup to
			 * indicate the message was sent, with 0 bytes remaining
			 */

			XIic_mDisableIntr(InstancePtr->BaseAddress,
					  XIIC_TX_INTERRUPTS);
			InstancePtr->SendHandler(InstancePtr->SendCallBackRef,
						 0);
		}
	}

	return;
}