/*
*
* RxReceive routine.It will receive the data from the FIFO.
*
* @param	InstancePtr is a pointer to the instance of the
*		XLlFifo instance.
*
* @param	DestinationAddr is the address where to copy the received data.
*
* @return	-XST_SUCCESS to indicate success
*		-XST_FAILURE to indicate failure
*
* @note		None
*
******************************************************************************/
int RxReceive (XLlFifo *InstancePtr, u32* DestinationAddr)
{

	int i;
	int Status;
	u32 RxWord;
	static u32 ReceiveLength;
	
	xil_printf(" Receiving data ....\n\r");
	/* Read Recieve Length */
	ReceiveLength = (XLlFifo_iRxGetLen(InstancePtr))/WORD_SIZE;

	/* Start Receiving */
	for ( i=0; i < ReceiveLength; i++){
		RxWord = 0;
		RxWord = XLlFifo_RxGetWord(InstancePtr);
		
		if(XLlFifo_iRxOccupancy(InstancePtr)){
			RxWord = XLlFifo_RxGetWord(InstancePtr);
		}
		*(DestinationAddr+i) = RxWord;
	}

	Status = XLlFifo_IsRxDone(InstancePtr);
	if(Status != TRUE){
		xil_printf("Failing in receive complete ... \r\n");
		return XST_FAILURE;
	}

	return XST_SUCCESS;
}
/**
*
* This is the Receive handler callback function.
*
* @param	InstancePtr is a reference to the Fifo device instance.
*
* @return	None.
*
* @note		None.
*
******************************************************************************/
static void FifoRecvHandler(XLlFifo *InstancePtr)
{
	int i;
	u32 RxWord;
	static u32 ReceiveLength;

	xil_printf("Receiving Data... \n\r");

	/* Read Recieve Length */
	ReceiveLength = (XLlFifo_iRxGetLen(InstancePtr))/WORD_SIZE;

	while(XLlFifo_iRxOccupancy(InstancePtr)) {
		for (i=0; i < ReceiveLength; i++) {
				RxWord = XLlFifo_RxGetWord(InstancePtr);
				*(DestinationBuffer+i) = RxWord;
		}
	}
}
/**
*
* This function demonstrates the usage Traffic Generator
* It does the following:
*       - Set up the output terminal if UART16550 is in the hardware build
*       - Initialize the AXI Traffic Generator device
*       - Initialize the Streaming FIFO device
*	- Set the Desired Transfer Count and Transfer Length
*	- Enable the Traffic Genration on the Core
*	- Check for the Streaming data on the FIFO 
*       - Return test status and exit
*
* @param	InstancePtr is a pointer to the instance of the
*		XTrafGen component.
* @param	DeviceId is Device ID of the Axi Traffic Generator Device,
*
*
* @param	InstancePtr is a pointer to the instance of the
*			XTrafGen component.
* @param	DeviceId is Device ID of the Axi Traffic Generator Device,
*			typically XPAR_<TRAFGEN_instance>_DEVICE_ID value from
*			xparameters.h.
*
* @return	-XST_SUCCESS to indicate success
*			-XST_FAILURE to indicate failure
*
******************************************************************************/
int XTrafGenStremingModeMasterExample(XTrafGen *InstancePtr, u16 DeviceId)
{

	XTrafGen_Config *Config;
	int Status = XST_SUCCESS;
	u32 Len; 
	u32 TransferCnt;
	u32 AtgPacket;
	u32 FifoOcy;
	u32 FifoLen;
	
        /* Initial setup for Uart16550 */
#ifdef XPAR_UARTNS550_0_BASEADDR

	Uart550_Setup();

#endif

	/* Initialize the Device Configuration Interface driver */
	Config = XTrafGen_LookupConfig(DeviceId);
	if (!Config) {
		xil_printf("No config found for %d\r\n", DeviceId);
		return XST_FAILURE;
	}

	/*
	 * This is where the virtual address would be used, this example
	 * uses physical address.
	 */
	Status = XTrafGen_CfgInitialize(InstancePtr, Config,
				Config->BaseAddress);
	if (Status != XST_SUCCESS) {
		xil_printf("Initialization failed\n\r");
		return Status;
	}
	
	/* Check for the Streaming Mode */
	if(InstancePtr->OperatingMode != XTG_MODE_STREAMING) {
		return XST_FAILURE;
	}
	
	/* Initialize the Fifo Instance */
	XLlFifo_Initialize(&XLlFifoInstance , STR_FIFO0_ADDR);
	Status = XLlFifo_Status(&XLlFifoInstance);
	XLlFifo_IntClear(&XLlFifoInstance,0xffffffff);
	Status = XLlFifo_Status(&XLlFifoInstance);
	if(Status != 0x0) {
		xil_printf("\n ERROR : Reset value of ISR0 : 0x%x\t"
			    "Expected : 0x0\n\r",
			    XLlFifo_Status(&XLlFifoInstance));
		return XST_FAILURE;
	}
	
	/* 
	 * Set the Required trasaction length 
	 * and required transaction count
	 */
	XTrafGen_ResetStreamingRandomLen(InstancePtr);
	XTrafGen_SetStreamingTransLen(InstancePtr , 3);
	XTrafGen_SetStreamingTransCnt(InstancePtr , 2);
	
	Len = XTrafGen_GetStreamingTransLen(InstancePtr);
	TransferCnt = XTrafGen_GetStreamingTransCnt(InstancePtr);

	/* 
	 * Calculate the ATG data that is sent on the 
	 * CORE when Streaming is Enabled 
	 */
	AtgPacket = (Len +1) * TransferCnt;
		
	/* Enable the traffic genration */
	XTrafGen_StreamEnable(InstancePtr);
	
	FifoOcy = XLlFifo_iRxOccupancy(&XLlFifoInstance);
	if(FifoOcy != AtgPacket) {
		xil_printf("\n ERROR : Not received complete packets : 0x%x \t"
			"Expected : 0x%x \n\r",
			XLlFifo_iRxOccupancy(&XLlFifoInstance), AtgPacket);
		return XST_FAILURE;
	}
	
	FifoLen = XLlFifo_iRxGetLen(&XLlFifoInstance);
	if(FifoLen != (AtgPacket*4/TransferCnt)) {
		xil_printf("\n ERROR : Not received complete bytes : 0x%x \t"
			"Expected : 0x%x \n\n\r",
			XLlFifo_iRxGetLen(&XLlFifoInstance),Len);
		return XST_FAILURE;
	}
	while(XLlFifo_iRxGetLen(&XLlFifoInstance)) {
		xil_printf("Recived packet DATA: 0x%x \n\r",
				XLlFifo_RxGetWord(&XLlFifoInstance));
	}
	
	if(XLlFifo_iRxOccupancy(&XLlFifoInstance) != 0) {
		xil_printf("\n ERROR : RDFO is not becoming Empty : 0x%x \t"
				"Expected : 0x0 \n\n\r",
				XLlFifo_iRxOccupancy(&XLlFifoInstance));
		return XST_FAILURE;
	}
	
	if(XLlFifo_iRxGetLen(&XLlFifoInstance) != 0) {
		xil_printf("\n ERROR : RLR is not becoming Empty : 0x%x \t"
				"Expected : 0x0 \n\n\r",
				XLlFifo_iRxGetLen(&XLlFifoInstance));
		return XST_FAILURE;
	}
	
	return XST_SUCCESS;
}