/******************************************************************************
 
   Copyright (C), 2013, Texas Instrument.
 
  ******************************************************************************
   File Name	 : SPI_Loopback_TEST.c
   Version		 : Initial Draft
   Author		 : Brighton Feng
   Created		 : 2013-3-5
   Last Modified : 
   Description	 : KeyStone2 SPI demo code
   History		 :
   1.Date		 : 2013-3-5
   Author 	 	 : Brighton Feng
   Modification: Created file
 
 ******************************************************************************/
#include <stdio.h>
#include <csl_types.h>
#include <cslr_device.h>
#include "K2_common.h"
#include "SPI_loopback_TEST.h"

Uint16 spiRxBuf[SPI_LOOP_TEST_BUF_SIZE/2];
Uint16 spiTxBuf[SPI_LOOP_TEST_BUF_SIZE/2];

/*data format for loopback test*/
SPI_Data_Format loopbackDataFormat =
{
	/*.delayBetweenTrans_ns = */0,
	/*.ShifDirection        = */SPI_MSB_SHIFT_FIRST,
	/*.disable_CS_timing    = */1,
	/*.clockPolarity        = */SPI_CLOCK_LOW_INACTIVE,
	/*.clockPhase           = */0,
	/*.clockSpeedKHz        = */66000,
	/*.wordLength           = */16
};

SPI_Transfer_Param loopbackTransferParam =
{
	0,     /*Chip select number*/
	1,  /*select one of the 4 SPI formats*/
	SPI_CS_NO_LAST_HOLD, /*hold CS between multiple words*/
	FALSE,  /*Enable the delay counter at the end of the current transaction*/
	2   /*number of bytes per SPI word*/
};

int SPI_loopback_test_one_time(Uint32 SPI_idx, Uint16 dataPattern)
{
	int i, iByteSuccess;
	Uint32 startCCNT, cycles, throughput;
	
	for(i=0; i<SPI_LOOP_TEST_BUF_SIZE/2; i++)
	{
		spiTxBuf[i]= dataPattern;
		spiRxBuf[i]= ~dataPattern;
	}

	startCCNT= CP15_read_CCNT();
	iByteSuccess= K2_SPI_TxRx(SPI_idx, (Uint8 *) spiTxBuf, 0, 
		SPI_LOOP_TEST_BUF_SIZE, (Uint8 *) spiRxBuf, 0, 
		SPI_LOOP_TEST_BUF_SIZE, &loopbackTransferParam);
	cycles= CCNT_count_cycle_from(startCCNT);

	if(iByteSuccess!=SPI_LOOP_TEST_BUF_SIZE)
	{
		printf("SPI loopback test failed. TX %d bytes, RX %d bytes!\n",
			SPI_LOOP_TEST_BUF_SIZE, iByteSuccess);
		return iByteSuccess;
	}
		
	for(i=0; i<SPI_LOOP_TEST_BUF_SIZE/2; i++)
	{
		if(spiTxBuf[i]!=spiRxBuf[i])
		{
			printf("SPI loopback test failed at word %d: TX 0x%x, RX 0x%x\n",
				i, spiTxBuf[i], spiRxBuf[i]);
			return i;
		}
	}

    throughput = (unsigned long long)SPI_LOOP_TEST_BUF_SIZE*8*gMain_Core_Speed_Hz/
    	((unsigned long long)cycles*1000000);

	printf("SPI loopback test passed with data pattern 0x%x. Throughput= %dMbps\n",
		dataPattern, throughput);
		
	return SPI_LOOP_TEST_BUF_SIZE;
}

void SPI_interrupt_test(Uint32 SPI_idx)
{
	CSL_SpiRegs * spiRegs= gpSPI_regs[SPI_idx];

	if(CSL_SPI_PER_CNT<=SPI_idx)
	{
		puts("Invalid SPI port number!");
		return;
	}

	printf("SPI%d interrupt test: manually generate RX overrun error...\n", SPI_idx);
	
	//write three data at TX side without read at RX side to generate RX overrun error
	spiRegs->SPIDAT0= 0x5a5a;
	delay_ms(1);
	spiRegs->SPIDAT0= 0xa5a5;
	delay_ms(1);
	spiRegs->SPIDAT0= 0xffff;
	delay_ms(100);
}

void SPI_loopback_test(Uint32 SPI_idx)
{
	SPI_loopback_test_one_time(SPI_idx, 0);
	SPI_loopback_test_one_time(SPI_idx, 0xFFFF);
	SPI_loopback_test_one_time(SPI_idx, 0x5555);
	SPI_interrupt_test(SPI_idx);
}

