#include <stdio.h>
#include <MX1_def.h>
#include "Common.h"
#include "ZZhang_define.h"  		// SPI config 

U16	int_flag;

// interrupt subroutines
void CSPI1_ISR(void)
{
	int_flag = SPIINTCS1;
	SPIINTCS1 = 0x00ff;
	#ifdef Monitor
//		printf("This is CSPI1 interrupt %x!\n", int_flag);
	#endif 
}

void CSPI2_ISR(void)
{
	int_flag = SPIINTCS2 >> 8;
	SPIINTCS2 = 0x00ff;
	#ifdef Monitor
//		printf("This is CSPI2 interrupt %x!\n", int_flag);
	#endif 
}

// normal subroutines

void CSPI_GPIO_configure(int mode)
{
	PC_GIUS &= 0xFFFC1FFF;	// ** SPI1; Primary
	PC_GPR  &= 0xFFFC1FFF;
	
	// ** SPI2 PD configure	
	if (mode == 1)
	{
		PD_GIUS 	|= 0x00000780;	
		PD_OCR1 	&= 0xFFCC3FFF;
		PD_DDR  	|= 0x00000580;		
		
		PD_ICONFA1 	&= 0xFFF3FFFF;
		PD_DDR  	&= 0xFFFFFDFF;
		FMCR		|= 0x00000100;
		
		#ifdef Monitor
			printf ("PD_GIUS = %x.\n", PD_GIUS);
			printf ("PD_OCR1 = %x.\n", PD_OCR1);
			printf ("PD_DDR = %x.\n", PD_DDR);			
			printf ("PD_ICONFA1 = %x.\n", PD_ICONFA1);
			printf ("FMCR = %x.\n", FMCR);
		#endif
	}
	if (mode == 2)
	{
		PA_GIUS |= 0x00020003;	// ** SPI2 PA & PD configure
		PD_GIUS |= 0x80000000;
		PA_OCR1 &= 0xFFFFFFF0;
		PA_OCR2 &= 0xFFFFFFFC;
		PD_OCR2 &= 0x3FFFFFFF;
		PA_DDR	|= 0x00020001;
		PA_DDR	&= 0xFFFFFFFD;
		PD_DDR	|= 0x80000000;
	}
	if (mode == 3)
	{
		PA_GIUS		|= 0x00000001;
		PA_ICONFA1 	&= ~0x0000000c;
		PA_DDR  	&= ~0x00000001;
		FMCR		&= ~0x00000100;
	}
}
	
int CSPI_reg_rw(U32 addr, U16 data, U16 expect)
{
	int flag = 0;
	U16 reg = 0;
	char * status = "pass";
	
	*(P_U32) addr = data;
	reg = *(P_U32) addr;
	if (reg != expect) flag = 1;
	#ifdef	Monitor 
		if (flag == 1) status = "fail";
		printf("Read/Write Test %s : Expect %4x and Read %4x.\n", status, expect, reg); 
	#endif
	return flag;
}

int CSPI_reg_reset(U32 addr, U16 expect)
{
	int flag = 0;
	U16 reg = 0;
	char * status = "pass";
	
	reg = *(P_U32) addr;
	if (reg != expect) flag = 1;
	#ifdef	Monitor 
		if (flag == 1) status = "fail";
		printf("Reset Test %s : Expect %4x and Read %4x.\n", status, expect, reg); 
	#endif
	return flag;
}

int	CSPI_reg_test(void)
{
	int error_count = 0;
	
	#ifdef	Monitor 
		printf("CSPI1 register read/write test.\n"); 
	#endif
	if (CSPI_reg_reset(CSPI_SPIRXD, 	0x0000)) error_count++;
	if (CSPI_reg_reset(CSPI_SPITXD, 	0x0000)) error_count++;
	if (CSPI_reg_reset(CSPI_INTCS, 		0x0000)) error_count++;
	if (CSPI_reg_reset(CSPI_SPIDMA, 	0x0000)) error_count++;
	if (CSPI_reg_reset(CSPI_SPISPCR, 	0x0000)) error_count++;
	if (CSPI_reg_reset(CSPI_SPITEST, 	0x0000)) error_count++;
	if (CSPI_reg_reset(CSPI_SPICONT1, 	0x0000)) error_count++;
	if (CSPI_reg_reset(CSPI_SPIRESET, 	0x0000)) error_count++;

	if (CSPI_reg_rw(CSPI_SPIRXD,	0xffff, 0x0000)) error_count++;
	if (CSPI_reg_rw(CSPI_SPIRXD,	0x0000, 0x0000)) error_count++;
	if (CSPI_reg_rw(CSPI_SPITXD, 	0xffff, 0x0000)) error_count++;
	if (CSPI_reg_rw(CSPI_SPITXD, 	0x0000, 0x0000)) error_count++;
	if (CSPI_reg_rw(CSPI_INTCS, 	0xffff, 0xff00)) error_count++;
	if (CSPI_reg_rw(CSPI_INTCS, 	0x0000, 0x0000)) error_count++;
	if (CSPI_reg_rw(CSPI_SPIDMA, 	0xffff, 0xf000)) error_count++;
	if (CSPI_reg_rw(CSPI_SPIDMA, 	0x0000, 0x0000)) error_count++;
	if (CSPI_reg_rw(CSPI_SPISPCR, 	0xffff, 0xffff)) error_count++;
	if (CSPI_reg_rw(CSPI_SPISPCR, 	0x0000, 0x0000)) error_count++;
	if (CSPI_reg_rw(CSPI_SPITEST, 	0xffff, 0xf000)) error_count++;
	if (CSPI_reg_rw(CSPI_SPITEST,	0x0000, 0x0000)) error_count++;
	if (CSPI_reg_rw(CSPI_SPICONT1, 	0xffff, 0xfeff)) error_count++;
	SPICONT1 = 0x0000;
	SPICONT1 = 0x0000;
	SPICONT1 = 0x0000;
	if (CSPI_reg_rw(CSPI_SPICONT1, 	0x0000, 0x0000)) error_count++;
	if (CSPI_reg_rw(CSPI_SPIRESET, 	0xffff, 0x0000)) error_count++;
	if (CSPI_reg_rw(CSPI_SPIRESET, 	0x0000, 0x0000)) error_count++;

	#ifdef	Monitor 
		printf("CSPI2 register read/write test.\n"); 
	#endif
	if (CSPI_reg_reset(CSPI_2_SPIRXD, 	0x0000)) error_count++;
	if (CSPI_reg_reset(CSPI_2_SPITXD, 	0x0000)) error_count++;
	if (CSPI_reg_reset(CSPI_2_INTCS, 	0x0000)) error_count++;
	if (CSPI_reg_reset(CSPI_2_SPIDMA, 	0x0000)) error_count++;
	if (CSPI_reg_reset(CSPI_2_SPISPCR, 	0x0000)) error_count++;
	if (CSPI_reg_reset(CSPI_2_SPITEST, 	0x0000)) error_count++;
	if (CSPI_reg_reset(CSPI_2_SPICONT1, 0x0400)) error_count++;
	if (CSPI_reg_reset(CSPI_2_SPIRESET, 0x0000)) error_count++;

	if (CSPI_reg_rw(CSPI_2_SPIRXD,		0xffff, 0x0000)) error_count++;
	if (CSPI_reg_rw(CSPI_2_SPIRXD,		0x0000, 0x0000)) error_count++;
	if (CSPI_reg_rw(CSPI_2_SPITXD, 		0xffff, 0x0000)) error_count++;
	if (CSPI_reg_rw(CSPI_2_SPITXD, 		0x0000, 0x0000)) error_count++;
	if (CSPI_reg_rw(CSPI_2_INTCS, 		0xffff, 0xff00)) error_count++;
	if (CSPI_reg_rw(CSPI_2_INTCS, 		0x0000, 0x0000)) error_count++;
	if (CSPI_reg_rw(CSPI_2_SPIDMA, 		0xffff, 0xf000)) error_count++;
	if (CSPI_reg_rw(CSPI_2_SPIDMA, 		0x0000, 0x0000)) error_count++;
	if (CSPI_reg_rw(CSPI_2_SPISPCR, 	0xffff, 0xffff)) error_count++;
	if (CSPI_reg_rw(CSPI_2_SPISPCR, 	0x0000, 0x0000)) error_count++;
	if (CSPI_reg_rw(CSPI_2_SPITEST, 	0xffff, 0xf000)) error_count++;
	if (CSPI_reg_rw(CSPI_2_SPITEST,		0x0000, 0x0000)) error_count++;
	if (CSPI_reg_rw(CSPI_2_SPICONT1, 	0xffff, 0xfeff)) error_count++;
	SPICONT2 = 0x0000;
	if (CSPI_reg_rw(CSPI_2_SPICONT1, 	0x0000, 0x0400)) error_count++;
	if (CSPI_reg_rw(CSPI_2_SPIRESET, 	0xffff, 0x0000)) error_count++;
	if (CSPI_reg_rw(CSPI_2_SPIRESET, 	0x0000, 0x0000)) error_count++;
	return error_count;

}

void CSPI_Tx_Fill(int spi, U16 size, U16 data_seed)
{
	int i;
	U16 write_value;
	
	if (spi == 1) for (i = 1; i <= size; i++) {
		write_value = data_seed * i;
		SPITXD1 = write_value;
	}
	if (spi == 2) for (i = 1; i <= size; i++) {
		write_value = data_seed * i;
		SPITXD2 = write_value;
	}
	#ifdef Monitor
		if ((spi != 1) && (spi != 2))
		{
			printf("Invalid CSPI TxFIFO with %d.\n", spi);
		}
		else
		{
			for (i = 1; i <= size; i++) {
				write_value = data_seed * i;
				printf("Write %4x to CSPI%d TxFIFO at %d\n", write_value, spi, i);
			}
		}
		printf("\n");
	#endif
}

int CSPI_Rx_Comp(int spi, U16 size, U16 data_seed, U16 bit_count)
{
	U16	read_value;
	U16 expect_value;
	int error_count = 0;
	int i;
	char *state;
	
	if (spi == 1) for (i = 1; i <= size; i++)
	{
		expect_value = (data_seed * i) & (0xFFFF >> (15 - bit_count));
		read_value = SPIRXD1 & (0xFFFF >> (15 - bit_count));
		if (expect_value != read_value) 
		{
			error_count++;
			state = "fail";
		}
		else
		{
			state = "pass";
		}		
		#ifdef Monitor
			printf("CSPI1 RxFIFO Test %s: Read %4x and Expected %4x.\n", state, read_value, expect_value);
		#endif
	}
	if (spi == 2) for (i = 1; i <= size; i++)
	{
		expect_value = (data_seed * i) & (0xFFFF >> (15 - bit_count));
		read_value = SPIRXD2 & (0xFFFF >> (15 - bit_count));
		if (expect_value != read_value)
		{
			error_count++;
			state = "fail";
		}
		else
		{
			state = "pass";
		}
		#ifdef Monitor
			printf("CSPI2 RxFIFO Test %s: Read %4x and Expected %4x.\n", state, read_value, expect_value);
		#endif
	}
	#ifdef Monitor
		if ((spi != 1) && (spi != 2)) printf("Invalid CSPI RxFIFO with %d.\n", spi);
		printf("\n");
	#endif
	return error_count;
}

void CSPI_DMA_configure (int channel, U32 Source, U32 Destination, U8 Port, U16 Burst, U16 Size, U32 Control)
{
	U32 address;
	switch (channel)
	{
		case 0 :	address = DMA_CH0_BASE; break;
		case 1 :	address = DMA_CH1_BASE; break;
		case 2 :	address = DMA_CH2_BASE; break;
		case 3 :	address = DMA_CH3_BASE; break;
		case 4 :	address = DMA_CH4_BASE; break;
		case 5 :	address = DMA_CH5_BASE; break;
		case 6 :	address = DMA_CH6_BASE; break;
		case 7 :	address = DMA_CH7_BASE; break;
		case 8 :	address = DMA_CH8_BASE; break;
		case 9 :	address = DMA_CH9_BASE; break;
		case 10 :	address = DMA_CH10_BASE; break;
		default :	return;
	}
	*(P_U32) (address+0x0c) = 0x0000;
	*(P_U32) (address+0x18) = 0x0000;
	*(P_U32) (address+0x1c) = 0x0008;
	*(P_U32) (address+0x00) = Source;
	*(P_U32) (address+0x04) = Destination;
	*(P_U32) (address+0x10) = Port;
	*(P_U32) (address+0x14) = Burst;
	*(P_U32) (address+0x08) = Size;
	*(P_U32) (address+0x0c) = Control;
	
	#ifdef Monitor
		printf("Configure DMA Channel %d.\n", channel);
		printf("Baseaddress	= %x.\n", address);
		printf("Source    	= %x.\n", *(P_U32) (address+0x00));
		printf("Destination = %x.\n", *(P_U32) (address+0x04));
		printf("Port 		= %x.\n", *(P_U32) (address+0x10));
		printf("Burst 		= %x.\n", *(P_U32) (address+0x14));
		printf("Size 		= %x.\n", *(P_U32) (address+0x08));
		printf("Control 	= %x.\n", *(P_U32) (address+0x0c));
	#endif
}
	
void CSPI_FILL_RAM(U32 address, U16 size, U16 data_seed)
{
	int i;
	U32 addr = address;
	U16 write_value;
	
	for (i = 1; i <= size; i++)
	{
		write_value = (data_seed * i);
		*(P_U16) addr = write_value;
		#ifdef Monitor
			printf("Write RAM(%x) = %x.\n", addr, write_value);
		#endif
		addr = addr + 2;
	}
}

int CSPI_CMP_RAM(U32 address, U16 size, U16 data_seed, U16 bit_count)
{
	int i;
	int error_count = 0;
	U32	addr = address;
	U16 read_value;
	U16 expect_data;
	char *state;
	
	#ifdef Monitor
		printf("Read RAM from %x to %x.\n", address, (address + size));
	#endif
	
	for (i = 1; i <= size; i++)
	{
		read_value = (*(P_U16) addr) & (0xFFFF >> (15 - bit_count));
		expect_data = (data_seed * i) & (0xFFFF >> (15 - bit_count));
		if (read_value != data_seed * i)
		{ 
			error_count++;
			state = "fail";
		}
		else
		{
			state = "pass";
		}
		#ifdef Monitor
			printf("RAM(%x) Test %s: Read %x and Expected %x.\n", addr, state, read_value, expect_data);
		#endif
		addr = addr + 2;
	}
	return error_count;
}

int CSPI_RxFIFO_Overflow(void)
{
	int error_count = 0;
	int delay;
	int i;
	int_flag = 0x00;
	
	SetIntType(41,0);
	EnableIntSource(41);
	EnableIRQ();	

	PC_GIUS &= ~0x0000c000;		// configure SCLK SSB
	PC_GPR  &= ~0x0000c000;
	
	PC_GIUS |= 0x00022000;		// SPI_DRY -> SCLK; MOSI -> SSB
	PC_OCR1	|= 0x0C000000;
	PC_OCR1 |= 0x0000000C;
	PC_DR	|= 0x00020000;
	PC_DDR  |= 0x00022000;		
		
	SPIINTCS1 = 0x8000;
	SPICONT1 = 0x024f;
	
	delay = 100;
	while(delay--);
	PC_DR	&= ~0x00002000;		// SCLK down
	delay = 100;
	while(delay--);
	PC_DR	&= ~0x00020000;		// SSB down
	for (i = 0; i <= 17; i++)
	{
		delay = 100;
		while(delay--);
		PC_DR	|= 0x00002000;		// SCLK up
		delay = 100;
		while(delay--);
		PC_DR 	&= ~0x00002000;		// SCLK down
	}
	delay = 100;
	while(delay--);
	PC_DR	|= 0x00020000;		// SSB UP
		
	if ((int_flag & 0x0080) != 0)
	{
		printf("CSPI1 RxFIFO Bitcount Overflow interrupt generated. Intstatus = %x.\n", int_flag);
	}
	else
	{
		 printf("CSPI1 RxFIFO Bitcount Overflow interrupt failed. Intstatus = %x.\n", int_flag);
		 error_count++;
	}
	return error_count;
}
	
int CSPI_INT_TEST(void)
{
	int error_count = 0;
	int_flag = 0x00;
	
	SetIntType(41,0);
	EnableIntSource(41);
	EnableIRQ();	

	SPICONT1 = 0x060f;
	SPIRST1  = 0x0001;
	SPICONT1 = 0x260f;
	SPITEST1 = 0x4000;

	SPIINTCS1 = 0x01ff;
	if (int_flag & 0x0001) 
	{
		printf("CSPI1 TxFIFO Empty interrupt generated. Intstatus = %x.\n", int_flag);
	}
	else
	{
		 printf("CSPI1 TxFIFO Empty interrupt failed. Intstatus = %x.\n", int_flag);
		 error_count++;
	}
	
	SPIINTCS1 = 0x02ff;
	CSPI_Tx_Fill(1, 4, 0x1234);
	if ((int_flag & 0x0002) != 0)
	{
		printf("CSPI1 TxFIFO Half interrupt generated. Intstatus = %x.\n", int_flag);
	}
	else
	{
		 printf("CSPI1 TxFIFO Half interrupt failed. Intstatus = %x.\n", int_flag);
		 error_count++;
	}
	
	SPIINTCS1 = 0x04ff;
	CSPI_Tx_Fill(1, 4, 0x1234);
	if ((int_flag & 0x0004) != 0)
	{
		printf("CSPI1 TxFIFO Full interrupt generated. Intstatus = %x.\n", int_flag);
	}
	else
	{
		 printf("CSPI1 TxFIFO Full interrupt failed. Intstatus = %x.\n", int_flag);
		 error_count++;
	}

	SPIINTCS1 = 0x0800;
	SPICONT1 |= 0x0100;
	while ((SPITEST1 & 0x000f) != 0);
	while (SPICONT1 == 0x270f);
	if ((int_flag & 0x0008) != 0)
	{
		printf("CSPI1 RxFIFO Ready interrupt generated. Intstatus = %x.\n", int_flag);
	}
	else
	{
		 printf("CSPI1 RxFIFO Ready interrupt failed. Intstatus = %x.\n", int_flag);
		 error_count++;
	}
	error_count = error_count + CSPI_Rx_Comp(1, 4, 0x1234, 0x0f);
	error_count = error_count + CSPI_Rx_Comp(1, 4, 0x1234, 0x0f);
	
	SPIINTCS1 = 0x1000;
	CSPI_Tx_Fill(1, 4, 0x4321);
	SPICONT1 |= 0x0100;
	while ((SPITEST1 & 0x000f) != 0);
	while (SPICONT1 == 0x270f);	
	if ((int_flag & 0x0010) != 0)
	{
		printf("CSPI1 RxFIFO Half interrupt generated. Intstatus = %x.\n", int_flag);
	}
	else
	{
		 printf("CSPI1 RxFIFO Half interrupt failed. Intstatus = %x.\n", int_flag);
		 error_count++;
	}
	
	SPIINTCS1 = 0x2000;
	CSPI_Tx_Fill(1, 4, 0x4321);
	SPICONT1 |= 0x0100;
	while ((SPITEST1 & 0x000f) != 0);
	while (SPICONT1 == 0x270f);	
	if ((int_flag & 0x0020) != 0)
	{
		printf("CSPI1 RxFIFO Full interrupt generated. Intstatus = %x.\n", int_flag);
	}
	else
	{
		 printf("CSPI1 RxFIFO Full interrupt failed. Intstatus = %x.\n", int_flag);
		 error_count++;
	}
	
	SPIINTCS1 = 0x4000;
	CSPI_Tx_Fill(1, 2, 0x1234);
	SPICONT1 |= 0x0100;
	while ((SPITEST1 & 0x000f) != 0);
	while (SPICONT1 == 0x270f);	
	if ((int_flag & 0x0040) != 0)
	{
		printf("CSPI1 RxFIFO Overflow interrupt generated. Intstatus = %x.\n", int_flag);
	}
	else
	{
		 printf("CSPI1 RxFIFO Overflow interrupt failed. Intstatus = %x.\n", int_flag);
		 error_count++;
	}
	error_count = error_count + CSPI_Rx_Comp(1, 4, 0x4321, 0x0f);
	error_count = error_count + CSPI_Rx_Comp(1, 4, 0x4321, 0x0f);
	
	// CSPI2 int test
	SetIntType(40,0);
	EnableIntSource(40);
	EnableIRQ();	

	SPICONT2 = 0x060f;
	SPIRST2  = 0x0001;
	SPICONT2 = 0x260f;
	SPITEST2 = 0x4000;

	SPIINTCS2 = 0x01ff;
	if (int_flag & 0x0001) 
	{
		printf("CSPI2 TxFIFO Empty interrupt generated. Intstatus = %x.\n", int_flag);
	}
	else
	{
		 printf("CSPI2 TxFIFO Empty interrupt failed. Intstatus = %x.\n", int_flag);
		 error_count++;
	}
	
	SPIINTCS2 = 0x02ff;
	CSPI_Tx_Fill(2, 4, 0x1234);
	if ((int_flag & 0x0002) != 0)
	{
		printf("CSPI2 TxFIFO Half interrupt generated. Intstatus = %x.\n", int_flag);
	}
	else
	{
		 printf("CSPI2 TxFIFO Half interrupt failed. Intstatus = %x.\n", int_flag);
		 error_count++;
	}
	
	SPIINTCS2 = 0x04ff;
	CSPI_Tx_Fill(2, 4, 0x1234);
	if ((int_flag & 0x0004) != 0)
	{
		printf("CSPI2 TxFIFO Full interrupt generated. Intstatus = %x.\n", int_flag);
	}
	else
	{
		 printf("CSPI2 TxFIFO Full interrupt failed. Intstatus = %x.\n", int_flag);
		 error_count++;
	}

	SPIINTCS2 = 0x0800;
	SPICONT2 |= 0x0100;
	while ((SPITEST2 & 0x000f) != 0);
	while (SPICONT2 == 0x270f);
	if ((int_flag & 0x0008) != 0)
	{
		printf("CSPI2 RxFIFO Ready interrupt generated. Intstatus = %x.\n", int_flag);
	}
	else
	{
		 printf("CSPI2 RxFIFO Ready interrupt failed. Intstatus = %x.\n", int_flag);
		 error_count++;
	}
	error_count = error_count + CSPI_Rx_Comp(2, 4, 0x1234, 0x0f);
	error_count = error_count + CSPI_Rx_Comp(2, 4, 0x1234, 0x0f);
	
	SPIINTCS2 = 0x1000;
	CSPI_Tx_Fill(2, 4, 0x4321);
	SPICONT2 |= 0x0100;
	while ((SPITEST2 & 0x000f) != 0);
	while (SPICONT2 == 0x270f);	
	if ((int_flag & 0x0010) != 0)
	{
		printf("CSPI2 RxFIFO Half interrupt generated. Intstatus = %x.\n", int_flag);
	}
	else
	{
		 printf("CSPI2 RxFIFO Half interrupt failed. Intstatus = %x.\n", int_flag);
		 error_count++;
	}
	
	SPIINTCS2 = 0x2000;
	CSPI_Tx_Fill(2, 4, 0x4321);
	SPICONT2 |= 0x0100;
	while ((SPITEST2 & 0x000f) != 0);
	while (SPICONT2 == 0x270f);	
	if ((int_flag & 0x0020) != 0)
	{
		printf("CSPI2 RxFIFO Full interrupt generated. Intstatus = %x.\n", int_flag);
	}
	else
	{
		 printf("CSPI2 RxFIFO Full interrupt failed. Intstatus = %x.\n", int_flag);
		 error_count++;
	}
	
	SPIINTCS2 = 0x4000;
	CSPI_Tx_Fill(2, 2, 0x1234);
	SPICONT2 |= 0x0100;
	while ((SPITEST2 & 0x000f) != 0);
	while (SPICONT2 == 0x270f);	
	if ((int_flag & 0x0040) != 0)
	{
		printf("CSPI2 RxFIFO Overflow interrupt generated. Intstatus = %x.\n", int_flag);
	}
	else
	{
		 printf("CSPI2 RxFIFO Overflow interrupt failed. Intstatus = %x.\n", int_flag);
		 error_count++;
	}
	error_count = error_count + CSPI_Rx_Comp(2, 4, 0x4321, 0x0f);
	error_count = error_count + CSPI_Rx_Comp(2, 4, 0x4321, 0x0f);

	if (error_count) printf("CSPI INT test found fail:%d. \n", error_count);
	return error_count;
}
	
int CSPI_DMA_TEST(void)
{
	int errors = 0;
	
	DMA_DCR_v = 0x00000002;	
	DMA_DCR_v = 0x00000001;	

	SPICONT1 = 0x060f;
	SPIRST1  = 0x0001;
	SPICONT1 = 0x260f;
	SPITEST1 = 0x4000;

	CSPI_FILL_RAM(Table0, 12, 0x1234);
	CSPI_FILL_RAM(Table1, 12, 0x0000);

	CSPI_DMA_configure(1, Table0, CSPI_SPITXD, 0xf, 0x10, 0x10, 0x2089);
	CSPI_DMA_configure(2, CSPI_SPIRXD, Table1, 0xe, 0x10, 0x10, 0x0829);
	SPIDMA1 = 0xa000;
	while ((SPITEST1 & 0x000f) < 8);
	SPICONT1 |= 0x0100;
	while ((SPITEST1 & 0x000f) != 0);
	while (SPICONT1 != 0x260f);
	errors = errors + CSPI_CMP_RAM(Table1, 8, 0x1234, 0x000f);
	
	CSPI_FILL_RAM(Table0, 12, 0x0000);
	CSPI_DMA_configure(1, Table1, CSPI_SPITXD, 0xf, 0x08, 0x08, 0x2089);
	CSPI_DMA_configure(2, CSPI_SPIRXD, Table0, 0xe, 0x08, 0x08, 0x0829);
	SPIDMA1 = 0x4000;
	while ((SPITEST1 & 0x000f) < 4);
	SPICONT1 |= 0x0100;
	while ((SPITEST1 & 0x000f) != 0);
	while (SPICONT1 != 0x260f);
	SPIDMA1 = 0x1000;
	
	CSPI_DMA_configure(1, Table1 + 8, CSPI_SPITXD, 0xf, 0x08, 0x08, 0x2089);
	CSPI_DMA_configure(2, CSPI_SPIRXD, Table0 + 8, 0xe, 0x08, 0x08, 0x0829);
	SPIDMA1 = 0x4000;
	while ((SPITEST1 & 0x000f) < 4);
	SPICONT1 |= 0x0100;
	while ((SPITEST1 & 0x000f) != 0);
	while (SPICONT1 != 0x260f);
	SPIDMA1 = 0x1000;
 	errors = errors + CSPI_CMP_RAM(Table0, 8, 0x1234, 0x000f);
	if (errors) printf("CSPI DMA test found fail:%d. \n", errors);
	
	DMA_DCR_v = 0x00000002;
	return errors;
}

int CSPI_TwoBoard_SPI1_to_SPI1_Master (void)
{
	int errors = 0;
	int local_errors;
	U16	data_seed1;
	U16 data_seed2;
	U16 control;
	int i, j, k, f;
	
	printf("Two Board (SPI1 -> SPI1) No DataReady Test.\n\n");
	PA_GIUS 	|= 0x00000010;
	PA_OCR1 	|= 0x00000300;			// PA4 CSI_D0 output A2	
	PA_DR		&= ~0x00000010;
	PA_DDR  	|= 0x00000010;		
		
	PA_GIUS 	|= 0x00000020;
	PA_ICONFA1 	&= ~0x00000C00;			// PA5 CSI_D1 input C2
	PA_DDR  	&= ~0x00000020;
	
	for (f = 0; f <= 7; f++)
	{
		for (i = 0; i <= 15; i++)
		{
			for (j = 0; j <= 15; j++)
			{
				control = ((0x0700 + j) | (f << 13)) + (0x0010 * i);
				local_errors = 0;
				for (k = 1; k <= 100; k++)
				{
					data_seed1 = 0x1234 * k;
					data_seed2 = 0x4321 * k;
					while ((PA_SSR & 0x00000020) != 0);	// Slave Idle
					SPICONT1 = (control & 0xfeff);
					CSPI_Tx_Fill(1, 9, data_seed2);
					PA_DR |= 0x0010;				// Master ready
					while ((PA_SSR & 0x00000020) != 0x0020);	// Wait for Slave ready
					SPICONT1 |= 0x0100;
					while ((SPITEST1 & 0x000f) != 0);
					while (SPICONT1 != (control & 0xfeff));		
					PA_DR &= ~0x0010;				// Transfer complished
					local_errors = local_errors + CSPI_Rx_Comp(1, 8, data_seed1, (control & 0x000f));
				}
				printf("SPI1(0x%x) -> SPI1(0x0%x) Errors: %d\n", (control & 0xfeff), (control & 0x0aff), local_errors);
				errors = errors + local_errors;
			}
			SPIRST1 = 0x0001;
		}
	}
	return errors;	
}

int CSPI_TwoBoard_SPI1_to_SPI1_Master_1 (void)
{
	int errors = 0;
	int local_errors;
	U16	data_seed1;
	U16 data_seed2;
	U16 control;
	int i, j, k, f;
	
	printf("Two Board (SPI1 -> SPI1) Low level DataReady Test.\n\n");
	PA_GIUS 	|= 0x00000010;
	PA_OCR1 	|= 0x00000300;			// PA4 CSI_D0 output A2	
	PA_DR		&= ~0x00000010;
	PA_DDR  	|= 0x00000010;		
		
	PA_GIUS 	|= 0x00000020;
	PA_ICONFA1 	&= ~0x00000C00;			// PA5 CSI_D1 input C2
	PA_DDR  	&= ~0x00000020;
	
	for (f = 0; f <= 7; f++)
	{
		for (i = 0; i <= 15; i++)
		{
			for (j = 0; j <= 15; j++)
			{
				control = ((0x1700 + j) | (f << 13)) + (0x0010 * i);
				local_errors = 0;
				for (k = 1; k <= 100; k++)
				{
					data_seed1 = 0x1234 * k;
					data_seed2 = 0x4321 * k;
					while ((PA_SSR & 0x00000020) != 0);	// Slave Idle
					SPICONT1 = (control & 0xfeff);
					CSPI_Tx_Fill(1, 9, data_seed2);
					PA_DR |= 0x0010;				// Master ready
					while ((PA_SSR & 0x00000020) != 0x0020);	// Wait for Slave ready
					SPICONT1 |= 0x0100;
					while ((SPITEST1 & 0x000f) != 0);
					while (SPICONT1 != (control & 0xfeff));		
					PA_DR &= ~0x0010;				// Transfer complished
					local_errors = local_errors + CSPI_Rx_Comp(1, 8, data_seed1, (control & 0x000f));
				}
				printf("SPI1(0x%x) -> SPI1(0x0%x) Errors: %d\n", (control & 0xfeff), (control & 0x0aff), local_errors);
				errors = errors + local_errors;
			}
			SPIRST1 = 0x0001;
		}
	}
	return errors;	
}

int CSPI_TwoBoard_SPI1_to_SPI1_Master_2 (void)
{
	int errors = 0;
	int local_errors;
	U16	data_seed1;
	U16 data_seed2;
	U16 control;
	int i, j, k, f;
	
	printf("Two Board (SPI1 -> SPI1) negedge DataReady Test.\n\n");
	PA_GIUS 	|= 0x00000010;
	PA_OCR1 	|= 0x00000300;			// PA4 CSI_D0 output A2	
	PA_DR		&= ~0x00000010;
	PA_DDR  	|= 0x00000010;		
		
	PA_GIUS 	|= 0x00000020;
	PA_ICONFA1 	&= ~0x00000C00;			// PA5 CSI_D1 input C2
	PA_DDR  	&= ~0x00000020;
	
	for (f = 0; f <= 7; f++)
	{
		for (i = 0; i <= 15; i++)
		{
			for (j = 15; j <= 15; j++)
			{
				control = ((0x0f00 + j) | (f << 13)) + (0x0010 * i);
				local_errors = 0;
				for (k = 1; k <= 8; k++)
				{
					data_seed1 = 0x1234 * k;
					data_seed2 = 0x4321 * k;
					while ((PA_SSR & 0x00000020) != 0);		// Slave Idle
					SPICONT1 = (control & 0xfeff);
					CSPI_Tx_Fill(1, 9, data_seed2);
					PA_DR |= 0x0010;						// Master ready
//					while((PA_SSR & 0x0020) != 0x0020);
					SPICONT1 |= 0x0100;
					while ((SPITEST1 & 0x000f) != 0);
					while (SPICONT1 != (control & 0xfeff));		
					PA_DR &= ~0x0010;						// Transfer complished
					local_errors = local_errors + CSPI_Rx_Comp(1, 8, data_seed1, (control & 0x000f));
				}
				printf("SPI1(0x%x) -> SPI1(0x0%x) Errors: %d\n", (control & 0xfeff), (control & 0x0aff), local_errors);
				errors = errors + local_errors;
			}
			SPIRST1 = 0x0001;
		}
	}
	return errors;	
}

int CSPI_TwoBoard_SPI2_to_SPI1_Master (void)
{
	int errors = 0;
	int local_errors;
	U16	data_seed1;
	U16 data_seed2;
	U16 control;
	int i, j, k, f;
	
	printf("Two Board (SPI2 -> SPI1) Test.\n\n");
	PA_GIUS 	|= 0x00000010;
	PA_OCR1 	|= 0x00000300;			// PA4 CSI_D0 output A2	
	PA_DR		&= ~0x00000010;
	PA_DDR  	|= 0x00000010;		
		
	PA_GIUS 	|= 0x00000020;
	PA_ICONFA1 	&= ~0x00000C00;			// PA5 CSI_D1 input C2
	PA_DDR  	&= ~0x00000020;
	
	for (f = 0; f <= 7; f++)
	{
		for (i = 0; i <= 15; i++)
		{
			for (j = 0; j <= 15; j++)
			{
				control = ((0x0700 + j) | (f << 13)) + (0x0010 * i);
				local_errors = 0;
				for (k = 1; k <= 100; k++)
				{
					data_seed1 = 0x1234 * k;
					data_seed2 = 0x4321 * k;
					while ((PA_SSR & 0x00000020) != 0);	// Slave Idle
					SPICONT2 = (control & 0xfeff);
					CSPI_Tx_Fill(2, 9, data_seed2);
					PA_DR |= 0x0010;				// Master ready
					while ((PA_SSR & 0x00000020) != 0x0020);	// Wait for Slave ready
					SPICONT2 |= 0x0100;
					while ((SPITEST2 & 0x000f) != 0);
					while (SPICONT2 != (control & 0xfeff));		
					PA_DR &= ~0x0010;				// Transfer complished
					local_errors = local_errors + CSPI_Rx_Comp(2, 8, data_seed1, (control & 0x000f));
				}
				printf("SPI2(0x%x) -> SPI1(0x0%x) Errors: %d\n", (control & 0xfeff), (control & 0x0aff), local_errors);
				errors = errors + local_errors;
			}
			SPIRST1 = 0x0001;
		}
	}
	return errors;	
}

int CSPI_TwoBoard_SPI1_to_SPI1_Slave (void)
{
	int errors = 0;
	int local_errors;
	U16	data_seed1;
	U16 data_seed2;
	U16 control;
	int i, j, k, f;
	
	printf("Two Board (SPI1 -> SPI1) No DataReady Test.\n\n");	
	PA_GIUS 	|= 0x00000010;			// PA4 CSI_D0 input A2
	PA_ICONFA1 	&= ~0x00000300;			
	PA_DDR  	&= ~0x00000010;
		
	PA_GIUS		|= 0x00000020;			// PA5 CSI_D1 output C2	
	PA_OCR1 	|= 0x00000C00;			
	PA_DR		&= ~0x00000020;
	PA_DDR  	|= 0x00000020;		
	
	for (f = 0; f <= 7; f++)
	{
		for (i = 0; i <= 15; i++)
		{
			for (j = 0; j <= 15; j++)
			{ 
				control = ((0x0700 + j) | (f << 13)) + (0x0010 * i);
				local_errors = 0;
				for (k = 1; k <= 100; k++)
				{
					data_seed1 = 0x1234 * k;
					data_seed2 = 0x4321 * k;					
					while((PA_SSR & 0x00000010) != 0x0010);	// Wait for Master Ready
 					SPICONT1 = (control & 0x0aff);
					CSPI_Tx_Fill(1, 9, data_seed1);
					PA_DR |= 0x000020;				// Slave ready
 					while ((PA_SSR & 0x0000010) != 0);	// Wait for Master transfer done
					local_errors = local_errors + CSPI_Rx_Comp(1, 8, data_seed2, (control & 0x000f));
					PA_DR &= ~0x000020;				// Clear Slave ready
				}
				printf("SPI1(0x%x) -> SPI1(0x0%x) Errors: %d\n", (control & 0xfeff), (control & 0x0aff), local_errors);
				errors = errors + local_errors;
			}
			SPIRST1 = 0x0001;
		}
	}
	return errors;	
}

int CSPI_TwoBoard_SPI1_to_SPI1_Slave_1 (void)
{
	int errors = 0;
	int local_errors;
	U16	data_seed1;
	U16 data_seed2;
	U16 control;
	int i, j, k, f;
	
	printf("Two Board (SPI1 -> SPI1) Low level DataReady Test.\n\n");
		
	PC_GIUS		|= 0x00002000;			// B4 (SPI_DRY pc13) output	
	PC_OCR1 	|= 0x0C000000;			
	PC_DR		|= 0x00002000;
	PC_DDR  	|= 0x00002000;		
	
	PA_GIUS 	|= 0x00000010;			// PA4 CSI_D0 input A2
	PA_ICONFA1 	&= ~0x00000300;			
	PA_DDR  	&= ~0x00000010;

	PA_GIUS		|= 0x00000020;			// PA5 CSI_D1 output C2	
	PA_OCR1 	|= 0x00000C00;			
	PA_DR		&= ~0x00000020;
	PA_DDR  	|= 0x00000020;		
			
	for (f = 0; f <= 7; f++)
	{
		for (i = 0; i <= 15; i++)
		{
			for (j = 0; j <= 15; j++)
			{ 
				control = ((0x1700 + j) | (f << 13)) + (0x0010 * i);
				local_errors = 0;
				for (k = 1; k <= 100; k++)
				{
					data_seed1 = 0x1234 * k;
					data_seed2 = 0x4321 * k;	
					while((PA_SSR & 0x00000010) != 0x0010);	// Wait for Master Ready
 					SPICONT1 = (control & 0x0aff);
					CSPI_Tx_Fill(1, 9, data_seed1);
					PA_DR |= 0x000020;				// Slave ready
					PC_DR &= ~0x2000;
 					while ((PA_SSR & 0x0000010) != 0);	// Wait for Master transfer done
					local_errors = local_errors + CSPI_Rx_Comp(1, 8, data_seed2, (control & 0x000f));
					PA_DR &= ~0x000020;				// Clear Slave ready
				}
				printf("SPI1(0x%x) -> SPI1(0x0%x) Errors: %d\n", (control & 0xfeff), (control & 0x0aff), local_errors);
				errors = errors + local_errors;
			}
			SPIRST1 = 0x0001;
		}
	}
	return errors;	
}

int CSPI_TwoBoard_SPI1_to_SPI1_Slave_2 (void)
{
	int errors = 0;
	int local_errors;
	U16	data_seed1;
	U16 data_seed2;
	U16 control;
	int i, j, k, l, m, f;
	
	printf("Two Board (SPI1 -> SPI1) Negedge DataReady Test.\n\n");
		
	PC_GIUS		|= 0x00002000;			// B4 (SPI_DRY pc13) output	
	PC_OCR1 	|= 0x0C000000;			
	PC_DR		|= 0x00002000;
	PC_DDR  	|= 0x00002000;		
	
	PA_GIUS 	|= 0x00000010;			// PA4 CSI_D0 input A2
	PA_ICONFA1 	&= ~0x00000300;			
	PA_DDR  	&= ~0x00000010;

	PA_GIUS		|= 0x00000020;			// PA5 CSI_D1 output C2	
	PA_OCR1 	|= 0x00000C00;			
	PA_DR		&= ~0x00000020;
	PA_DDR  	|= 0x00000020;		
			
	for (f = 0; f <= 7; f++)
	{
		for (i = 0; i <= 15; i++)
		{
			for (j = 15; j <= 15; j++)
			{ 
				control = ((0x0f00 + j) | (f << 13)) + (0x0010 * i);
				local_errors = 0;
				for (k = 1; k <= 8; k++)
				{
					data_seed1 = 0x1234 * k;
					data_seed2 = 0x4321 * k;	
					while((PA_SSR & 0x00000010) != 0x0010);	// Wait for Master Ready
 					SPICONT1 = (control & 0x0aff);
					CSPI_Tx_Fill(1, 9, data_seed1);
					PA_DR |= 0x000020;				// Slave ready
					for (l = 1; l <= 8; l++)
					{
						for(m = 0; m <= 1000; m++); 	// need some delay for master to retrieve data ready
						PC_DR &= ~0x2000;
						PC_DR |= 0x2000;
						while(((SPITEST1 & 0xf0) >> 4) != l);
					}
 					while ((PA_SSR & 0x0000010) != 0);	// Wait for Master transfer done
					local_errors = local_errors + CSPI_Rx_Comp(1, 8, data_seed2, (control & 0x000f));
					PA_DR &= ~0x000020;				// Clear Slave ready
				}
				printf("SPI1(0x%x) -> SPI1(0x0%x) Errors: %d\n", (control & 0xfeff), (control & 0x0aff), local_errors);
				errors = errors + local_errors;
			}
			SPIRST1 = 0x0001;
		}
	}
	return errors;	
}

int CSPI_TwoBoard_SPI2_to_SPI1_Slave (void)
{
	int errors = 0;
	int local_errors;
	U16	data_seed1;
	U16 data_seed2;
	U16 control;
	int i, j, k, f;
	
	printf("Two Board (SPI2 -> SPI1) No DataReady Test.\n\n");	
	PA_GIUS 	|= 0x00000010;			// PA4 CSI_D0 input A2
	PA_ICONFA1 	&= ~0x00000300;			
	PA_DDR  	&= ~0x00000010;
		
	PA_GIUS		|= 0x00000020;			// PA5 CSI_D1 output C2	
	PA_OCR1 	|= 0x00000C00;			
	PA_DR		&= ~0x00000020;
	PA_DDR  	|= 0x00000020;		
	
	for (f = 0; f <= 7; f++)
	{
		for (i = 0; i <= 15; i++)
		{
			for (j = 15; j <= 15; j++)
			{ 
				control = ((0x0700 + j) | (f << 13)) + (0x0010 * i);
				local_errors = 0;
				for (k = 1; k <= 100; k++)
				{
					data_seed1 = 0x1234 * k;
					data_seed2 = 0x4321 * k;					
					while((PA_SSR & 0x00000010) != 0x0010);	// Wait for Master Ready
 					SPICONT1 = (control & 0x0aff);
					CSPI_Tx_Fill(1, 9, data_seed1);
					PA_DR |= 0x000020;				// Slave ready
 					while ((PA_SSR & 0x0000010) != 0);	// Wait for Master transfer done
					local_errors = local_errors + CSPI_Rx_Comp(1, 8, data_seed2, (control & 0x000f));
					PA_DR &= ~0x000020;				// Clear Slave ready
				}
				printf("SPI1(0x%x) -> SPI1(0x0%x) Errors: %d\n", (control & 0xfeff), (control & 0x0aff), local_errors);
				errors = errors + local_errors;
			}
			SPIRST1 = 0x0001;
		}
	}
	return errors;	
}

int	CSPI_Oneboard_SPI2_to_SPI1(void)
{
	int errors = 0;
	int local_errors;
	U16	data_seed1;
	U16 data_seed2;
	U16 control;
	int i, j, k, f;

	printf("One Board (SPI2 -> SPI1) Test.\n\n");
	for (f = 0; f <= 7; f++)
	{
		for (i = 0; i <= 15; i++)
		{
			for (j = 0; j <= 15; j++)
			{
				control = ((0x0700 + j) | (f << 13)) + (0x0010 * i);
				local_errors = 0;
				for (k = 1; k <= 100; k++)
				{
					data_seed1 = 0x1234 * k;
					data_seed2 = 0x4321 * k;
					SPICONT2 = (control & 0xfeff);
					CSPI_Tx_Fill(2, 9, data_seed2);
					SPICONT1 = (control & 0x0aff);
					CSPI_Tx_Fill(1, 9, data_seed1);
					SPICONT2 |= 0x0100;
					while ((SPITEST2 & 0x000f) != 0);
					while (SPICONT2 != (control & 0xfeff));		
					local_errors = local_errors + CSPI_Rx_Comp(2, 8, data_seed1, (control & 0x000f));
					local_errors = local_errors + CSPI_Rx_Comp(1, 8, data_seed2, (control & 0x000f));
				}
				printf("SPI2(0x%x) -> SPI1(0x0%x) Errors: %d\n", (control & 0xfeff), (control & 0x0aff), local_errors);
				errors = errors + local_errors;
			}
			SPIRST1 = 0x0001;
			SPIRST2 = 0x0001;
		}
	}
	return errors;
}