#include <sysreg.h>
#include "hal_1967VN044.h"

// Data Bus 16-bit
#define SDRAM_MODEL_48LC16M16
// Data Bus 32-bit
//#define SDRAM_MODEL_48LC32M16

#ifdef SDRAM_MODEL_48LC16M16
	#define SDRCON_PG	    SDRCON_PG512
    #define DATA_BUS_WIDTH  16
	#define SYS_BUS         SYS_BUS_16b
	#define SDRAM_SIZE	 	0x00800000  // 8 MWord (32 MByte)

#elif SDRAM_MODEL_48LC32M16
	#define SDRCON_PG	    SDRCON_PG512
    #define DATA_BUS_WIDTH  32
	#define SYS_BUS         SYS_BUS_32b
	#define SDRAM_SIZE	 	0x01000000  // 16 MWord (64 MByte)
#endif

#define BusClk_kHz		80000
#define CoreClk_kHz		200000
#define SDRAM_START  	0x40000000	// start address of SDRAM

//#define FOREVER_REPEAT
#define NUM_OF_REPEAT	2


unsigned int errFlag = 0, i;

void SYSCON_BusConfig(int BusSize){
	int tmp;
	switch(BusSize){
	case 16:
		tmp = __builtin_sysreg_read(__SYSCON);
		tmp |= (1<<19);
		__builtin_sysreg_write(__SYSCON,tmp);
		break;
	case 32:
		tmp = __builtin_sysreg_read(__SYSCON);
		tmp &= ~(1<<19);
		__builtin_sysreg_write(__SYSCON,tmp);
		break;
	}
}

void ErrorStop(unsigned int testNumber){
	errFlag = testNumber;
	if (testNumber) __builtin_sysreg_write(__FLAGREG,0xCF);
	while(1);
}

int main(void)
{
	unsigned int testCounter = 0, NumOfRepeat;
	unsigned int *sdramPointer = (unsigned int *) SDRAM_START;
	int sdrconValue, tmp;

	HAL_PLL_CoreSetup(CoreClk_kHz);
	HAL_PLL_BusSetup(BusClk_kHz);

	NumOfRepeat = NUM_OF_REPEAT;
	HAL_SYS_FlagEnable();
	__builtin_sysreg_write(__FLAGREG, 0xEF); 	//Test Start

	//Multiple write to SYSCON/SDRCON enable
	LX_CMU->CFG1.b.SYS_WE = 1;
	//SDRCON Configure
	sdrconValue = SDRCON_INIT | SDRCON_RAS2PC5 | SDRCON_PC2RAS2 |
            	  SDRCON_REF1100 | SDRCON_PG | SDRCON_CLAT2 | SDRCON_ENBL;
	//SYSCON Bus and GPIO
	SYSCON_BusConfig(DATA_BUS_WIDTH);
	HAL_SYS_ExtBusEnable(SYS_BUS);

	HAL_SYS_SDRAMEnable(sdrconValue);

#ifdef FOREVER_REPEAT
while(1){
#else
while(NumOfRepeat--){
#endif

	//----------------------------------------------------------------------------------------------------//
	//Test 1. Rotation 0x00000000 and 0xFFFFFFFF
	testCounter++;
	for(i=0;i<SDRAM_SIZE/2;i+=2){
		*(sdramPointer + i) = 0x00000000;
		*(sdramPointer + i + 1) = 0xFFFFFFFF;
	}
	//Check test 1
	for(i=0;i<SDRAM_SIZE/2;i+=2){
		if (( *(sdramPointer + i) != 0x00000000 ) || ( *(sdramPointer + i + 1) != 0xFFFFFFFF ))
		 ErrorStop(testCounter);
	}
	//----------------------------------------------------------------------------------------------------//

	//----------------------------------------------------------------------------------------------------//
	//Test 2. Rotation 0xAAAAAAAA and 0x55555555
	testCounter++;
	for(i=0;i<SDRAM_SIZE/2;i+=2){
		*(sdramPointer + i) = 0xAAAAAAAA;
		*(sdramPointer + i + 1) = 0x55555555;
	}
	//Check test 2
	for(i=0;i<SDRAM_SIZE/2;i+=2){
		if (( *(sdramPointer + i) != 0xAAAAAAAA ) || ( *(sdramPointer + i + 1) != 0x55555555 ))
		 ErrorStop(testCounter);
	}
	//----------------------------------------------------------------------------------------------------//

	//----------------------------------------------------------------------------------------------------//
	//Test 3. Rotation 0x0000FFFF and 0xFFFF0000
	testCounter++;
	for(i=0;i<SDRAM_SIZE/2;i+=2){
		*(sdramPointer + i) = 0x0000FFFF;
		*(sdramPointer + i + 1) = 0xFFFF0000;
	}
	//Check test 3
	for(i=0;i<SDRAM_SIZE/2;i+=2){
		if (( *(sdramPointer + i) != 0x0000FFFF ) || ( *(sdramPointer + i + 1) != 0xFFFF0000 ))
		 ErrorStop(testCounter);
	}
	//----------------------------------------------------------------------------------------------------//

	//----------------------------------------------------------------------------------------------------//
	//Test 4. All bits = 0
	testCounter++;
	for(i=0;i<SDRAM_SIZE;i++){
		*(sdramPointer + i) = 0x00000000;
	}
	//Check test 4
	for(i=0;i<SDRAM_SIZE;i++){
		if ( *(sdramPointer + i) != 0x00000000 )
		 ErrorStop(testCounter);
	}
	//----------------------------------------------------------------------------------------------------//

	//----------------------------------------------------------------------------------------------------//
	//Test 5. All bits = 1
	testCounter++;
	for(i=0;i<SDRAM_SIZE;i++){
		*(sdramPointer + i) = 0xFFFFFFFF;
	}
	//Check test 5
	for(i=0;i<SDRAM_SIZE;i++){
		if ( *(sdramPointer + i) != 0xFFFFFFFF )
		 ErrorStop(testCounter);
	}
	//----------------------------------------------------------------------------------------------------//

	//----------------------------------------------------------------------------------------------------//
	//Test 6. Write/Read Address
	testCounter++;
	for(i=0;i<SDRAM_SIZE;i++){
		*(sdramPointer + i) = (unsigned int) sdramPointer + i;
	}
	//Check test 6
	for(i=0;i<SDRAM_SIZE;i++){
		if (*(sdramPointer + i) != (unsigned int) sdramPointer + i)
		 ErrorStop(testCounter);
	}
	//----------------------------------------------------------------------------------------------------//

	//----------------------------------------------------------------------------------------------------//
	//Test 7. Null Shifter
	testCounter++;
	for(i=0;i<SDRAM_SIZE;i++){
		*(sdramPointer + i) =  ~(1<<(i&0x1F));
	}
	//Check test 7
	for(i=0;i<SDRAM_SIZE;i++){
		if (*(sdramPointer + i) !=  ~(1<<(i&0x1F)))
		 ErrorStop(testCounter);
	}
	//----------------------------------------------------------------------------------------------------//

	//----------------------------------------------------------------------------------------------------//
	//Test 8. One Shifter
	testCounter++;
	for(i=0;i<SDRAM_SIZE;i++){
		*(sdramPointer + i) =  (1<<(i&0x1F));
	}
	//Check test 8
	for(i=0;i<SDRAM_SIZE;i++){
		if (*(sdramPointer + i) !=  (1<<(i&0x1F)))
		 ErrorStop(testCounter);
	}
	//----------------------------------------------------------------------------------------------------//

	//----------------------------------------------------------------------------------------------------//
	//Test 9. Pseudo-random counter
	testCounter++;
	for(i=0;i<SDRAM_SIZE;i++)
		*(sdramPointer + i) = (i<<24)+(i<<18)+i;
	//check
	for(i=0;i<SDRAM_SIZE;i++){
		if(*(sdramPointer + i) != (i<<24)+(i<<18)+i)
			ErrorStop(testCounter);
	}

	//Check pointer
	testCounter++;
	if ((unsigned int) sdramPointer != 0x40000000) ErrorStop(testCounter);
}

	//End all tests
	__builtin_sysreg_write(__FLAGREG, 0x0F); //Test passed
	while(1);
}

