/**
*
* This function does a minimal test on the UartNs550 device and driver as a
* design example. The purpose of this function is to illustrate how to use the
* XUartNs550 component.
*
*
* @param	DeviceId is the XPAR_<uartns550_instance>_DEVICE_ID value from
*		xparameters.h.
*
* @return	XST_SUCCESS if succesful, otherwise XST_FAILURE.
*
* @note		None.
*
****************************************************************************/
int UartNs550SelfTestExample(u16 DeviceId)
{
	int Status;

	/*
	 * Initialize the UartNs550 driver so that it's ready to use
	 */
	Status = XUartNs550_Initialize(&UartNs550, DeviceId);
	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	/*
	 * Perform a self-test to ensure that the hardware was built correctly
	 */
	Status = XUartNs550_SelfTest(&UartNs550);
	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	return XST_SUCCESS;
}
/**
*
* This function does a minimal test on the UartNs550 device and driver as a
* design example. The purpose of this function is to illustrate how to use the
* XUartNs550 component.
*
* This function transmits data and expects to receive the same data through the
* UART using the local loopback of the hardware.
*
* This function uses interrupt driver mode of the UART.
*
* @param	IntcInstancePtr is a pointer to the instance of the
*		Interrupt Controller.
* @param	UartInstancePtr is a pointer to the instance of the UART .
* @param	UartDeviceId is the device Id and is typically
*		XPAR_<UARTNS550_instance>_DEVICE_ID value from  xparameters.h.
* @param	UartIntrId is the interrupt Id and is typically
*		XPAR_<INTC_instance>_<UARTNS550_instance>_IP2INTC_IRPT_INTR
*		value from xparameters.h.
*
* @return	XST_SUCCESS if successful, otherwise XST_FAILURE.
*
* @note
*
* This function contains an infinite loop such that if interrupts are not
* working it may never return.
*
*******************************************************************************/
int UartNs550IntrExample(XIntc *IntcInstancePtr,
			XUartNs550 *UartInstancePtr,
			u16 UartDeviceId,
			u16 UartIntrId)
{
	int Status;
	u32 Index;
	u16 Options;
	u32 BadByteCount = 0;


	/*
	 * Initialize the UART driver so that it's ready to use.
	 */
	Status = XUartNs550_Initialize(UartInstancePtr, UartDeviceId);
	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	/*
	 * Perform a self-test to ensure that the hardware was built correctly.
	 */
	Status = XUartNs550_SelfTest(UartInstancePtr);
	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	/*
	 * Connect the UART to the interrupt subsystem such that interrupts can
	 * occur. This function is application specific.
	 */
	Status = UartNs550SetupIntrSystem(IntcInstancePtr,
						UartInstancePtr,
						UartIntrId);
	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	/*
	 * Setup the handlers for the UART that will be called from the
	 * interrupt context when data has been sent and received, specify a
	 * pointer to the UART driver instance as the callback reference so
	 * the handlers are able to access the instance data.
	 */
	XUartNs550_SetHandler(UartInstancePtr, UartNs550IntrHandler,
			  UartInstancePtr);

	/*
	 * Enable the interrupt of the UART so interrupts will occur, setup
	 * a local loopback so data that is sent will be received, and keep the
	 * FIFOs enabled.
	 */
	Options = XUN_OPTION_DATA_INTR | XUN_OPTION_LOOPBACK |
			XUN_OPTION_FIFOS_ENABLE;
	XUartNs550_SetOptions(UartInstancePtr, Options);


	/*
	 * Initialize the send buffer bytes with a pattern to send and the
	 * the receive buffer bytes to zero to allow the receive data to be
	 * verified.
	 */
	for (Index = 0; Index < TEST_BUFFER_SIZE; Index++) {
		SendBuffer[Index] = Index + 'A';
		RecvBuffer[Index] = 0;
	}

	/*
	 * Start receiving data before sending it since there is a loopback,
	 * ignoring the number of bytes received as the return value since we
	 * know it will be zero and we are using interrupt mode.
	 */
	XUartNs550_Recv(UartInstancePtr, RecvBuffer, TEST_BUFFER_SIZE);

	/*
	 * Send the buffer using the UART and ignore the number of bytes sent
	 * as the return value since we are using it in interrupt mode.
	 */
	XUartNs550_Send(UartInstancePtr, SendBuffer, TEST_BUFFER_SIZE);

	/*
	 * Wait for the entire buffer to be received, letting the interrupt
	 * processing work in the background, this function may get locked
	 * up in this loop if the interrupts are not working correctly.
	 */
	while ((TotalReceivedCount != TEST_BUFFER_SIZE) ||
		(TotalSentCount != TEST_BUFFER_SIZE)) {
	}

	/*
	 * Verify the entire receive buffer was successfully received.
	 */
	for (Index = 0; Index < TEST_BUFFER_SIZE; Index++) {
		if (RecvBuffer[Index] != SendBuffer[Index]) {
			BadByteCount++;
		}
	}

	/*
	 * Disable the UartNs550 interrupt.
	 */
	UartNs550DisableIntrSystem(IntcInstancePtr, UartIntrId);


	/*
	 * If any bytes were not correct, return an error.
	 */
	if (BadByteCount != 0) {
		return XST_FAILURE;
	}

	return XST_SUCCESS;
}
/**
*
* This function does a minimal test on the UART 16450/550 device and driver as a
* design example.  The purpose of this function is to illustrate how to use
* the XUartNs550 component.
*
* This function sends data and expects to receive the data thru the UART
* using the local loopback mode of the UART hardware.
*
* This function polls the UART and does not require the use of interrupts.
*
* @param	DeviceId is the XPAR_<uartns550_instance>_DEVICE_ID value from
*		xparameters.h.
*
* @return	XST_SUCCESS if successful, XST_FAILURE if unsuccessful.
*
* @note		This function polls the UART such that it may be not return
*		if the hardware is not working correctly.
*
****************************************************************************/
int UartNs550PolledExample(u16 DeviceId)
{
	int Status;
	unsigned int SentCount;
	unsigned int ReceivedCount = 0;
	u16 Index;
	u16 Options;

	/*
	 * Initialize the UART Lite driver so that it's ready to use,
	 * specify the device ID that is generated in xparameters.h
	 */
	Status = XUartNs550_Initialize(&UartNs550, DeviceId);
	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	/*
	 * Perform a self-test to ensure that the hardware was built  correctly
	 */
	Status = XUartNs550_SelfTest(&UartNs550);
	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	/*
	 * Enable the local loopback so data that is sent will be received,
	 * and keep the FIFOs enabled
	 */
	Options = XUN_OPTION_LOOPBACK | XUN_OPTION_FIFOS_ENABLE;
	XUartNs550_SetOptions(&UartNs550, Options);

	/*
	 * Initialize the send buffer bytes with a pattern to send and the
	 * the receive buffer bytes to zero
	 */
	for (Index = 0; Index < TEST_BUFFER_SIZE; Index++) {
		SendBuffer[Index] = '0' + Index;
		RecvBuffer[Index] = 0;
	}

	/*
	 * Send the buffer thru the UART waiting till the data can be
	 * sent (block), if the specified number of bytes was not sent
	 * successfully, then an error occurred
	 */
	SentCount = XUartNs550_Send(&UartNs550, SendBuffer, TEST_BUFFER_SIZE);
	if (SentCount != TEST_BUFFER_SIZE) {
		return XST_FAILURE;
	}

	/*
	 * Receive the number of bytes which is transfered.
	 * Data may be received in fifo with some delay hence we continuously
	 * check the receive fifo for valid data and update the receive buffer
	 * accordingly.
	 */
	while (1) {
	   ReceivedCount += XUartNs550_Recv(&UartNs550,
					   RecvBuffer + ReceivedCount,
					   TEST_BUFFER_SIZE - ReceivedCount);
	   if (ReceivedCount == TEST_BUFFER_SIZE)
	   {
		break;
           }
        }

	/*
	 * Check the receive buffer data against the send buffer and verify the
	 * data was correctly received
	 */
	for (Index = 0; Index < TEST_BUFFER_SIZE; Index++) {
		if (SendBuffer[Index] != RecvBuffer[Index]) {
			return XST_FAILURE;
		}
	}

	/*
	 * Clean up the options
	 */
	Options = XUartNs550_GetOptions(&UartNs550);
	Options = Options & ~(XUN_OPTION_LOOPBACK | XUN_OPTION_FIFOS_ENABLE);
	XUartNs550_SetOptions(&UartNs550, Options);

	return XST_SUCCESS;
}