 #include "system.h"
//#include "define.h"
#include "common.h"
#include "environment.h"
#include "timer.h"
#include "hardware.h"
//#include "rs232.h"
//#include "CISCam.h"
#include "system_setup.h"
#include "system_control.h"
#include "SPB_Processing.h"
#include "spb_system.h"
#include "system_setup.h"
#include "spb6457cfg.h"
#include "DMAScheduler.h"
#include "nfa_camera.h"
#include "image_control.h"

#include <soc.h>
#include <csl.h>
#include <csl_mcbsp.h>
#include <csl_emifa.h>
#include <csl_emifaAux.h>
#include <csl_intc.h>
#include <csl_intcAux.h>
#include <cslr_dev.h>
#include <csl_psc.h>
#include <csl_ddr2.h>
#include <csl_pllc.h>
#include <csl_cache.h>
#include <csl_edma3.h>
#include <stdio.h>
#define EMIFA_MEMTYPE_ASYNC    0
#define EMIFA_MEMTYPE_SYNC     1

volatile int temp1;
CSL_EmifaHandle    hEmifa;
CSL_IntcEventHandlerRecord  Record[15]; 
CSL_IntcContext     IntcContext;
CSL_Ddr2Handle    hDdr2;
CSL_PllcHandle           hPllc = NULL;

CSL_Edma3Obj                			NFAEdmaObj;
CSL_Edma3Handle 				hNFAEdma;
CSL_Edma3HwDmaChannelSetup  		NFADmaHwSetup[CSL_EDMA3_NUM_DMACH] = CSL_EDMA3_DMACHANNELSETUP_DEFAULT;
CSL_Edma3HwQdmaChannelSetup			NFAQdmahwSetup[CSL_EDMA3_NUM_QDMACH] = CSL_EDMA3_QDMACHANNELSETUP_DEFAULT;
CSL_Edma3HwSetup            		NFAHwSetup;

int led_count =0;
int init_complete;
int camonoff_test = 0;
int caminit_test = 0;
extern int cam_init_complete;
void SetPscModule(CSL_PscPowerDomain pwrDmn, CSL_PscPeripherals module);
void InitPsc()
{
    SetPscModule(CSL_PSC_PWRDMN_ALWAYSON, CSL_PSC_MODULE_EMIF64);
    SetPscModule(CSL_PSC_PWRDMN_ALWAYSON, CSL_PSC_MODULE_HPI);
    SetPscModule(CSL_PSC_PWRDMN_ALWAYSON, CSL_PSC_MODULE_UTOPIA);
    SetPscModule(CSL_PSC_PWRDMN_PROXYA, CSL_PSC_MODULE_SRIO);
    SetPscModule(CSL_PSC_PWRDMN_PROXYB, CSL_PSC_MODULE_TCP2_0);
    SetPscModule(CSL_PSC_PWRDMN_PROXYC, CSL_PSC_MODULE_TCP2_1);
    SetPscModule(CSL_PSC_PWRDMN_PROXYD, CSL_PSC_MODULE_VCP2);
}

void InitPllc_850M()
{
    CSL_PllcObj              pllcObj;
    CSL_Status               status;
    CSL_PllcHwSetup          hwSetup;
    CSL_PllcHwSetup          hwSetupRead;
    CSL_PllcDivideControl    arg;
    CSL_PllcDivRatio         arg1;
    CSL_BitMask32            response;   
    CSL_BitMask32            argPllCtrl;    

    /* Initialize the PLLC CSL module */
    status = CSL_pllcInit(NULL);

    /* Clear local data structures */
    memset(&pllcObj, 0, sizeof(CSL_PllcObj));

    /* Open the PLLC CSL module */
    hPllc = CSL_pllcOpen (&pllcObj, CSL_PLLC_1, NULL, &status);

    /* Setup PLLC hardware parameters */
    hwSetup.divEnable  = (CSL_BitMask32) CSL_PLLC_DIVEN_POSTDIV | 
							CSL_PLLC_DIVEN_PLLDIV3 | CSL_PLLC_DIVEN_PLLDIV6 | 
							CSL_PLLC_DIVEN_PLLDIV7 | CSL_PLLC_DIVEN_PLLDIV8;

    hwSetup.postDiv    = (Uint32) 0x00000001;
    hwSetup.pllM       = (Uint32) 0x00000011;
	hwSetup.pllMode    = (Uint32) 0x00000001;
    hwSetup.pllDiv3    = (Uint32) 0x00000003;
    hwSetup.pllDiv6    = (Uint32) 0x0000000A;
	hwSetup.pllDiv7    = (Uint32) 0x00000008;
    hwSetup.pllDiv8    = (Uint32) 0x0000000A;

    status = CSL_pllcHwSetup (hPllc, &hwSetup);

    /* Read back */
    status = CSL_pllcGetHwSetup (hPllc, &hwSetupRead);

    /* Change divider settings for PLLDIV4 */

    /* Wait if another GO operation is currently in progress.*/
    do 
	{
        CSL_pllcGetHwStatus (hPllc, CSL_PLLC_QUERY_STATUS, &response);
    } while (response & CSL_PLLC_STATUS_GO);

 
    /* Close the module */
//    status = CSL_pllcClose (hPllc);

    return;
}

void SetPscModule(CSL_PscPowerDomain pwrDmn, CSL_PscPeripherals module)
{
    CSL_PscObj pscObj;
    CSL_PscHandle hPsc;
    CSL_Status status;
    CSL_PscPwrDmnTransState response;

    memset(&pscObj, 0, sizeof(CSL_PscObj));      

    /* Init PSC module */
    CSL_pscInit(NULL);

    /* Open PSC module to get a Handle */
    hPsc = CSL_pscOpen(&pscObj, CSL_PSC, NULL, &status);

	module = CSL_PSC_MODULE_EMIF64;
    /* Enable power domain for EMIFA */
    CSL_pscHwControl(hPsc, CSL_PSC_CMD_ENABLE_PWRDMN, &pwrDmn);

    /* Enable clock for the specified module EMIFA */
    CSL_pscHwControl(hPsc, CSL_PSC_CMD_ENABLE_MODULE, &module);
	
    /* Enable EMIFA Power domain GO transition */
    CSL_pscHwControl(hPsc, CSL_PSC_CMD_PWRDMN_TRNS, &pwrDmn);

    response.pwrDmn = CSL_PSC_PWRDMN_ALWAYSON;
    response.status = 0x0; 
    do{
        CSL_pscGetHwStatus(hPsc, CSL_PSC_QUERY_PWRDMN_TRANS_STAT, (void *)&response);
        (response.status) &= (1 << CSL_PSC_PWRDMN_ALWAYSON);
    }while((response.status) != 0x0);

	module = CSL_PSC_MODULE_SRIO;
    /* Enable power domain for EMIFA */
    CSL_pscHwControl(hPsc, CSL_PSC_CMD_ENABLE_PWRDMN, &pwrDmn);

    /* Enable clock for the specified module EMIFA */
    CSL_pscHwControl(hPsc, CSL_PSC_CMD_ENABLE_MODULE, &module);
	
    /* Enable EMIFA Power domain GO transition */
    CSL_pscHwControl(hPsc, CSL_PSC_CMD_PWRDMN_TRNS, &pwrDmn);

    response.pwrDmn = CSL_PSC_PWRDMN_ALWAYSON;
    response.status = 0x0; 
    do{
        CSL_pscGetHwStatus(hPsc, CSL_PSC_QUERY_PWRDMN_TRANS_STAT, (void *)&response);
        (response.status) &= (1 << CSL_PSC_PWRDMN_ALWAYSON);
    }while((response.status) != 0x0);

    /* Close the PSC module */
 //   CSL_pscClose(hPsc);
}

void InitDDR2()
{ 
	CSL_Ddr2Obj         ddr2Obj;
	CSL_Status          status;
	CSL_Ddr2HwSetup     hwSetup ;    
	CSL_Ddr2Timing1  tim1 = CSL_DDR2_TIMING1_DEFAULTS;
	CSL_Ddr2Timing2  tim2 = CSL_DDR2_TIMING2_DEFAULTS;
	CSL_Ddr2Settings set  = CSL_DDR2_SETTING_DEFAULTS;
	 /* Clear local data structures */   
	memset(&ddr2Obj, 0, sizeof(CSL_Ddr2Obj));      
	memset(&hwSetup, 0, sizeof(CSL_Ddr2HwSetup));
    
	tim1.trfc = 0x1F;
	tim1.trp = 0x3;
	tim1.trcd = 0x3;
	tim1.twr = 0x3;
	tim1.tras = 0x9;
	tim1.trc = 0xd;
	tim1.trrd = 0x2;
	tim1.twtr = 0x1;

	tim2.todt = 0x1;
	tim2.tsxnr = 0x22;
	tim2.tsxrd = 0x31;
	tim2.trtp = 0x1;
	tim2.tcke = 0x2;
    
	/* setup the hardware parameters */
	hwSetup.refreshRate = SDRAM_REFRESH_RATE;
	hwSetup.readLatncy = 0x5;
	hwSetup.timing1Param = &tim1;
	hwSetup.timing2Param = &tim2;
	set.narrowMode = CSL_DDR2_NORMAL_MODE;
	set.casLatncy = CSL_DDR2_CAS_LATENCY_4;
	set.ddr2En = 0x1;
	set.ddrEn = 0x1;
	set.ibank = CSL_DDR2_8_SDRAM_BANKS;
	set.pageSize = CSL_DDR2_1024WORD_10COL_ADDR;
	set.sdramEn = 0x1;
	set.ddr2Ddqs = CSL_DDR2_SINGLE_ENDED_DQS; 
	set.ddr2Term0 = 0x1;
	set.ddr2Term1 = 0x0;
	set.ddrDisDll = 0x0;
	set.sdramDrive0 = CSL_DDR2_SDRAM_NORMAL;
	hwSetup.setParam = &set;    
        
	/* Initialize DDR2 CSL module */
	status = CSL_ddr2Init(NULL);

    /* Opening the DDR2 instance */
    hDdr2 =  CSL_ddr2Open(&ddr2Obj, CSL_DDR2, NULL, &status);

    /* Setting up configuration parameter using HwSetup */
    status =  CSL_ddr2HwSetup(hDdr2, &hwSetup);             
}
void InitEMIFA(){
	CSL_EmifaObj          emifaObj;
	CSL_Status            status;
	CSL_EmifaHwSetup      hwSetup ;   

	CSL_EmifaMemType      ce2Val,ce3Val,ce4Val,ce5Val;
	CSL_EmifaAsyncWait    	asyncWait = CSL_EMIFA_ASYNCWAIT_DEFAULTS; 
	CSL_EmifaAsync			ce2Config,ce3Config = CSL_EMIFA_ASYNCCFG_DEFAULTS ,ce5Config;
	CSL_EmifaSync         	ce4Config = CSL_EMIFA_SYNCCFG_DEFAULTS;
	/* Clear local data structures */   
	memset(&emifaObj, 0, sizeof(CSL_EmifaObj));      
	memset(&hwSetup, 0, sizeof(CSL_EmifaHwSetup));
	
	/* setting for asynchronous type */

	ce2Config.selectStrobe = 0x0;
	ce2Config.weMode = 0x0;       
	ce2Config.asyncRdyEn = 0x1;
	ce2Config.wSetup = 0;
	ce2Config.wStrobe = 2;  
	ce2Config.wHold = 1; 
	ce2Config.rSetup = 1;    
	ce2Config.rStrobe = 5;
	ce2Config.rHold = 2;     
	ce2Config.asize = 2;

	ce5Config.selectStrobe = 0x0;
	ce5Config.weMode = 0x0;       
	ce5Config.asyncRdyEn = 0x0;
	ce5Config.wSetup = 2;
	ce5Config.wStrobe = 5;
	ce5Config.wHold = 2;
	ce5Config.rSetup = 1;    
	ce5Config.rStrobe = 7;  
	ce5Config.rHold = 1;      
	ce5Config.asize = 1;

	ce4Config.readEn = 1;
	ce4Config.r_ltncy = 3;
	ce4Config.w_ltncy = 1;
	ce4Config.sbsize = 3;


	ce2Val.ssel = CSL_EMIFA_MEMTYPE_ASYNC;
	ce2Val.async = &ce2Config;
	ce2Val.sync = NULL;

	ce3Val.ssel = CSL_EMIFA_MEMTYPE_ASYNC;
	ce3Val.async = &ce3Config;
	ce3Val.sync = NULL;

	ce4Val.ssel = CSL_EMIFA_MEMTYPE_SYNC;
	ce4Val.async = NULL;
	ce4Val.sync = &ce4Config;

	ce5Val.ssel = CSL_EMIFA_MEMTYPE_ASYNC;
	ce5Val.async = &ce5Config;
	ce5Val.sync = NULL;
	/* setting for synchronous type */
	asyncWait.asyncRdyPol = 0x0;

	hwSetup.asyncWait = &asyncWait;
	hwSetup.ceCfg[0] = &ce2Val;   	//Ce2	HPI					0xA0000000
	hwSetup.ceCfg[1] = &ce3Val;		//Ce3	Flash_spansion		0xB0000000
	hwSetup.ceCfg[2] = &ce4Val;		//Ce4	FIFO				0xC0000000
	hwSetup.ceCfg[3] = &ce5Val; 	//Ce5	Flash_samsung		0XD0000000

	status = CSL_emifaInit(NULL);
	hEmifa =  CSL_emifaOpen(&emifaObj, CSL_EMIFA, NULL, &status);
//	CSL_emifaAsyncClear(hEmifa);
	status =  CSL_emifaHwSetup(hEmifa, &hwSetup); 	
//	CSL_emifaPrioRaise(hEmifa,0x01);
}
void InitIntc()
{
	
	IntcContext.numEvtEntries = 15;
    IntcContext.eventhandlerRecord = Record;

	CSL_intcInit(&IntcContext);
}
void initEDMA()
{
	CSL_Edma3Context            context;
	CSL_Status                  status; 
	int handlerIndex;

	CSL_edma3Init(&context);
	hNFAEdma =  CSL_edma3Open(&NFAEdmaObj,CSL_EDMA3,NULL,&status);
	/* Module setup */
	NFAHwSetup.dmaChaSetup = &NFADmaHwSetup[0];
	NFAHwSetup.qdmaChaSetup = &NFAQdmahwSetup[0];
	CSL_edma3HwSetup(hNFAEdma,&NFAHwSetup);	


	/* clear Parameter RAM of EDMA */
	EDMA_clearPram(0x00000000);

	CSL_intcInterruptEnable(CSL_INTC_VECTID_15);			//capture edma

	EDMAInterruptHandler.HandlerCount = 0;
	for (handlerIndex = 0; handlerIndex < MAX_EDMA_HANDLER_COUNT; handlerIndex++)
	{
		EDMAEventHandler[handlerIndex] = DefaultEDMAEventHandler;
	}		
}


int InitSystem()
{
	
	int size;
	int dip_sw;
	TErrorCode ec;
	unsigned int checkS1=0,checkS2=0;

	CSL_IntcGlobalEnableState 	state;
	CSL_Edma3Context            	context;
	WHDOG = 0;
	init_complete = 0;
	ProgramVersion.MajorVersion = PROGRAM_MAJOR_VERSION;
	ProgramVersion.MinorVersion = PROGRAM_MINOR_VERSION;
	ProgramVersion.Date = PROGRAM_RELEASE_DATE;
	ProgramVersion.Type = PROGRAM_TARGET_SYSTEM;
    	CSL_intcGlobalDisable(NULL);
	SysLibInit();
	InitPsc();
	dip_sw = ReadDIP();
	if (dip_sw == 0xF)
	{
		BoardID = BOARD_ID_SPB(1);	
		G_SPB_INDEX = 1;
	}
	else
	{
		BoardID = BOARD_ID_SPB(dip_sw + 1);	
		G_SPB_INDEX = dip_sw + 1;	
	}
	
	InitPllc_850M();
	InitEMIFA();
	InitDDR2();
	InitGPIO();
//	NFA_CAMERA_RESET = 1;
	initEDMA();
	FlashReadProductId();
	
   	if (!FlashReadFileSystem())	FlashFormat();	
	LampInit();
	InitTimer();
	InitImageInfo();
	Calib_Reset();
	InitMCBSP();
	LaserMcbspInit();
	System_Sleep_ms(1000);
	MasterInit();
	IntCapture_Init();


	SystemSetup_InitDefault();
	SPBProgramHeader.ProjectID = PROJECT_ID_ELMA_100;
	SPBProgramHeader.ProgramRev = SPB_PROGRAM_REV;
	strcpy(SPBProgramHeader.ProjectName, PROJECT_NAME_ELMA_100); 	// for sw matching

	ec = ReadFromFlash(PID_SPB_DB_HEADER, (unsigned char *)&SPBDBHeader, sizeof(TSPBDBHeader), &size);
	checkS1 = CheckSumByte((unsigned char *)&SPBDBHeader,sizeof(TSPBDBHeader));

	ec = ReadFromFlash(PID_SPB_DB_HEADER, (unsigned char *)&SPBDBHeader, sizeof(TSPBDBHeader), &size);
	checkS2 = CheckSumByte((unsigned char *)&SPBDBHeader,sizeof(TSPBDBHeader));
	if(checkS1 != checkS2)
	{
		//printf("CheckSum Error!! SPBDBHeader\n");
		ec = ReadFromFlash(PID_SPB_DB_HEADER, (unsigned char *)&SPBDBHeader, sizeof(TSPBDBHeader), &size);
		ErrorUnit_Put(BoardID, ERROR_TYPE_DEBUG,ERROR_CODE_FLASH_READ,PID_SPB_DB_HEADER,0,0);
	}		
	if (ec != ERROR_CODE_NONE || size != sizeof(TSPBDBHeader))
	{
		WriteToFlash(PID_SPB_DB_HEADER, (unsigned char *)&SPBDBHeader, sizeof(TSPBDBHeader), 0);
	}
	

	ec = ReadFromFlash(PID_ENVIRONMENT, (unsigned char *)&SystemSetupData, sizeof(TSPBSystemSetupData), &size);
	checkS1 = CheckSumByte((unsigned char *)&SystemSetupData,sizeof(TSPBSystemSetupData));
	ec = ReadFromFlash(PID_ENVIRONMENT, (unsigned char *)&SystemSetupData, sizeof(TSPBSystemSetupData), &size);
	checkS2 = CheckSumByte((unsigned char *)&SystemSetupData,sizeof(TSPBSystemSetupData));
	if(checkS1 != checkS2)
	{
		//printf("CheckSum Error!! SystemSetupData\n");
		ec = ReadFromFlash(PID_ENVIRONMENT, (unsigned char *)&SystemSetupData, sizeof(TSPBSystemSetupData), &size);
		ErrorUnit_Put(BoardID, ERROR_TYPE_DEBUG,ERROR_CODE_FLASH_READ,PID_ENVIRONMENT,0,0);
	}	
	
	if (ec != ERROR_CODE_NONE || size != sizeof(TSPBSystemSetupData))
	{
		SystemSetup_InitDefault();

		WriteToFlash(PID_ENVIRONMENT, (unsigned char *)&SystemSetupData, sizeof(TSPBSystemSetupData), 0);
	}
	
	ApplySystemSetup();
	SystemInfo_InitDefault();
	ec = ReadFromFlash(PID_SYSTEM, (unsigned char *)&SPBSystemInfo, sizeof(TSPBSystemInfo), &size);
	checkS1 = CheckSumByte((unsigned char *)&SPBSystemInfo,sizeof(TSPBSystemInfo));
	ec = ReadFromFlash(PID_SYSTEM, (unsigned char *)&SPBSystemInfo, sizeof(TSPBSystemInfo), &size);
	checkS2 = CheckSumByte((unsigned char *)&SPBSystemInfo,sizeof(TSPBSystemInfo));


	if(checkS1 != checkS2)
	{
		ec = ReadFromFlash(PID_SYSTEM, (unsigned char *)&SPBSystemInfo, sizeof(TSPBSystemInfo), &size);
		ErrorUnit_Put(BoardID, ERROR_TYPE_DEBUG,ERROR_CODE_FLASH_READ,PID_SYSTEM,0,0);
	}	
	
	if (ec != ERROR_CODE_NONE || size != sizeof(TSPBSystemInfo))
	{
		SystemInfo_InitDefault();
		WriteToFlash(PID_SYSTEM, (unsigned char *)&SPBSystemInfo, sizeof(TSPBSystemInfo), 0);
	}
	ApplySystemInfo();
	InitCapture();
	InitDMAScheduler();
	DataTransferInit();
	BuildCalibrationImageInfo();
	BuildProcessingImageInfo();
	System_Control_Init();
	ApplySystemSetup();
//	NFA_CAMERA_RESET = 0;
//	System_Sleep_ms(5000);
	CSL_intcGlobalNmiEnable();
	
	CSL_intcGlobalEnable(&state);
	return 0;
}

int AllocEDMAInterruptHandler(TEDMAEventHandler edmaEventHandler, int index)
{

	EDMAEventHandler[index] = edmaEventHandler;
	return index;
}

void DefaultEDMAEventHandler(void)
{
	return;
}

int InitModule()
{
	
	unsigned char Lamp_SW = 0;
	unsigned int VerChkl,VerChk2; //sjm Add
	int f_count=0;
	int i;
	CSL_IntcGlobalEnableState 	state;
        CSL_intcInterruptDisable(CSL_INTC_VECTID_14);
	InitSystem();
	EnvironmentInit();

	Srio_Master_Init();

	if(!(NFA_CAMERA_CONTROL_TRIG&0x8000)){
		NFACamera_Init();
	}

	InitSPBSystem();
	SPB_Module_Init();
	SPB_Test_Init();	
	SPBCompatibility.TargetSPBBoardKind = SPB_BOARD_KIND_SPB06;
	CPB_Auto_Boot();

	#ifdef FPGA220
	//	MMIO_VERSION_FPGA_V5L = 0xFA; 
	//	MMIO_VERSION_FPGA_V5H = 0xFA;
		FPGAnewVersion2.VersionL = MMIO_VERSION_INFO_L;
		FPGAnewVersion2.VersionH = MMIO_VERSION_INFO_H;
		VerChk2 =(MMIO_VERSION_INFO_L & 0xf0) >> 4;
		VerChkl =(MMIO_VERSION_INFO_H & 0x0f);	
	#endif
	ErrorUnit_Put(BoardID, ERROR_TYPE_DEBUG,ERROR_CODE_NONE,123,456,789);
	CSL_intcInterruptEnable(CSL_INTC_VECTID_14);
	CSL_intcInterruptEnable(CSL_INTC_VECTID_8);
	CSL_intcInterruptEnable(CSL_INTC_VECTID_9);

	if(SrioRunInfo.RunSW)
	{
		Cpb_Boot_Process();
	}

	Calib_Capture_Stop_All();
	NFACmeraBootCheck();
	init_complete = 1;

	return 0;
}

int MainLoopwait()
{

	led_count++;	
	if(init_complete)
	{
		SPB_Processing_Main();
		if(led_count%2000==0)
		{
			SPB_TestProcess();
			led_count = 0;
		}
		System_Process_Loop();
		System_Idle_Process();	
	}
	return 0;
}

void edmaIsr()
{
	register int eventIndex;
	CSL_Edma3Context            context;
	CSL_Status                  status;
	CSL_Edma3Obj                edmaObj;
	CSL_IntcGlobalEnableState 	state;
	CSL_intcGlobalDisable(&state);
//	CSL_intcInterruptDisable(CSL_INTC_VECTID_5);
	for (eventIndex = 0; eventIndex < MAX_EDMA_HANDLER_COUNT; eventIndex++)
	{
		if ((CSL_FEXT(hNFAEdma->regs->IPR,EDMA3CC_IPR_REG) & (0x00000001 << eventIndex)))
		{
			hNFAEdma->regs->ICR ^= (0x00000001 << eventIndex);
			EDMAEventHandler[eventIndex]();
		}
	}
//	CSL_intcInterruptEnable(CSL_INTC_VECTID_5);
	CSL_intcGlobalEnable(&state);
}
