/*
 * LPC845 version
 1.ACK
 2.LPC_SWM->PINENABLE0 &= ~((1<<13)|(1<<12)); 
 */

#include "chip.h"
#include "sl_common.h"
//#include <string.h>
#include "chip_setup.h"


#include "swm.h"
#include "i2c.h"
#define LED_BLUE_ON  GPIOSetDir( 1, 15, 1 );\
					GPIOSetBitValue(1, 15, 0);
					
#define LED_BLUE_OFF GPIOSetDir( 1, 15, 1 );\
					GPIOSetBitValue(1, 15, 1);

#define LED_RED_ON  GPIOSetDir( 0, 12, 1 );\
					GPIOSetBitValue(0, 12, 0);
					
#define LED_RED_OFF GPIOSetDir( 0, 12, 1 );\
					GPIOSetBitValue(0, 12, 1);
					
#define LED_GREEN_ON  GPIOSetDir( 0, 0, 1 );\
					GPIOSetBitValue(0, 0, 0);
					
#define LED_GREEN_OFF GPIOSetDir( 0, 0, 1 );\
					GPIOSetBitValue(0, 0, 1);
					
//--Adision
//--LED_OUTPUT (1.LED_GREEN_ON 00; 2LED_RED_ON 0_12 ; 3LED_BLUE_ON , 1_15)
//			LPC_GPIO_PORT->DIRSET[0] = (1<<0); //--GREEN--can not works
//			LPC_GPIO_PORT->CLR[0] = (1<<0);
//			LPC_GPIO_PORT->DIRSET[0] = (1<<12);//--RED
//			LPC_GPIO_PORT->CLR[0] = (1<<12);
//			LPC_GPIO_PORT->DIRSET[1] = (1<<15);//--BLUE_ON
//			LPC_GPIO_PORT->CLR[1] = 1<<15;
//      LPC_GPIO_PORT->SET[1] = 1<<15;     //--BLUE_OFF
/*****************************************************************************
 * Private types/enumerations/variables
 ****************************************************************************/

typedef void (*loopHostIfFunc)(int pNum);
loopHostIfFunc loopI2C_pFunc;

/*****************************************************************************
 * Public types/enumerations/variables
 ****************************************************************************/

SL_HOSTIF_PACKET_T sendBuff, recvBuff;

IMG_HEADER_T *pImageHeader1 = (IMG_HEADER_T *) (SL_BOOTAPP_ADDR1 + SL_BOOTAPP_IMGHDR_OFS);
IMG_HEADER_T *pImageHeader2 = (IMG_HEADER_T *) (SL_BOOTAPP_ADDR2 + SL_BOOTAPP_IMGHDR_OFS);

static SL_PINSETUP_T *pinCfgData = (SL_PINSETUP_T *) SL_ADDRESS_APPPINDATA;
static uint32_t *pushAppFlag = (uint32_t *) SL_ADDRESS_APPCALLEDFL;

uint32_t *FW_VERSION1=(uint32_t *) 0x2114;
uint32_t *FW_VERSION2=(uint32_t *) 0x5114;

uint8_t App_CRC_Flag1=0;
uint8_t App_CRC_Flag2=0;


/*****************************************************************************
 * Private functions
 
 ****************************************************************************/

/* It is recommended to call this function on system boot or transfer to
   the app. */
void CleanUpSystem(void)
{
	/* Disable peripheral clocks for host IF */
	switch (slIfConfig.ifSel) {
	case SL_I2C2:
		shutdownInterfaceI2C(2);
		break;

	case SL_I2C1:
		shutdownInterfaceI2C(1);
		break;

	case SL_I2C0:
		shutdownInterfaceI2C(0);
		break;
	
	default:
		break;
	}
	
	Chip_GPIO_DeInit();
	Disable_Periph_Clock(CLK_IOCON);
	
	LPC_SYSCON->MAINCLKSEL        = MAINCLKSEL_VAL;     // Update the actual register
	LPC_SYSCON->MAINCLKUEN        = 0;                  // Toggle update register
	LPC_SYSCON->MAINCLKUEN        = 1;
	
}

void hostifAutoDetect(void)
{
	int i;

	/* All I2C interfaces are enabled for now. Initial port detection uses the I2C interrupts. */	   
	Enable_Periph_Clock(CLK_SWM);
	
	//--LPC845_I2C0
		setupMuxingI2C(0);					//--Init I2C configuration
		setupInterfaceI2C(0);       //--Configure LPC_I2C0 address and pending bit Enable
	  startHostIfI2C(0);          //--Enable Slave fuction : SLEVEN

	NVIC_EnableIRQ(I2C0_IRQn);
	NVIC_EnableIRQ(I2C1_IRQn);

	/* Wait forever for any I2C to be detected */
#if 0
	while ((slIfConfig.ifSel == SL_AUTO) ) {
		/* I2C detection occurs in the I2C interrupt handlers */
	}
#endif
	/* Shut down I2C ports and disable IRQs */
	NVIC_DisableIRQ(I2C0_IRQn);
	NVIC_DisableIRQ(I2C1_IRQn);

//	for (i = 0; i < 2; i++) {
//		shutdownInterfaceI2C(i);
//	}

}

Bool boot_App_ImageCheck(uint8_t app_number)
{
	IMG_HEADER_T *pImageHeader;
	Bool boot = FALSE;
	
	if(app_number==1)
		pImageHeader=pImageHeader1;
	else
		pImageHeader=pImageHeader2;
		
	/* check if there is a image header in flash or else don't boot */
	if ((pImageHeader->header_marker == IMG_HEADER_MARKER) &&
		(pinCheckValidHostif(&pImageHeader->hostifPinCfg) != FALSE)) {	/* Check if a valid ping config information is programmed in the image header */

		switch (pImageHeader->hostifPinCfg.img_type) {
		case IMG_AP_WAIT:
			/* goto secondary boot loader and wait for AP BOOT command */
			boot = FALSE;
			break;

		default:
		case IMG_NO_CRC:
		case IMG_NORMAL:
			/* check if host wants us to bypass boot due to bad image */
			/* check host requesting us to halt boot through IRQ line (pulled low after reset) */

//		    GPIOSetDir(PINCFG_GET_PORT(pImageHeader->hostifPinCfg.hostIrqPortPin), PINCFG_GET_PIN(pImageHeader->hostifPinCfg.hostIrqPortPin),0 );
//		
//		    if(GPIOGetPinValue( PINCFG_GET_PORT(pImageHeader->hostifPinCfg.hostIrqPortPin),PINCFG_GET_PIN(pImageHeader->hostifPinCfg.hostIrqPortPin)) == false) {
//--AZ
		
		    GPIOSetDir(0, 14,0 );
		
		    if(GPIOGetPinValue( 0,14) == false) {

				/* go to secondary boot loader */
				boot = FALSE;
				break;
			}
			/* skip CRC check if image type is IMG_NO_CRC */
			if (pImageHeader->hostifPinCfg.img_type == IMG_NO_CRC) {
				/* no more checks just boot */
				boot = TRUE;
				break;
			}

		case IMG_NO_WAIT:
			/* Perform a CRC check of the FLASH where the application is located. Jump
			   to it if it is valid, but only if this wasn't called from the
			   application. */
			if (checkAppCRC(app_number) == 0) {
				/* Valid application exists in application FLASH, so it's ok to boot the
				   application. */				
				boot = TRUE;
			}

			break;

		}
	}
	return boot;

}

void boot_ImageCheck(void)
{

	/*If IRQ pin is pulled low by host, skip app CRC check and don't boot app.*/
	App_CRC_Flag1=boot_App_ImageCheck(1);
	
	if(App_CRC_Flag1==TRUE)
	{
			doCleanBoot(SL_BOOTAPP_ADDR1);
	}

}
#if 0
void boot_ImageCheck(void)
{

	/*If IRQ pin is pulled low by host, skip app CRC check and don't boot app.*/
	App_CRC_Flag1=boot_App_ImageCheck(1);
	App_CRC_Flag2=boot_App_ImageCheck(2);
	
	if(App_CRC_Flag1==TRUE && App_CRC_Flag2==TRUE)
	{
		if(*FW_VERSION1>=*FW_VERSION2)
			doCleanBoot(SL_BOOTAPP_ADDR1);
		else
			doCleanBoot(SL_BOOTAPP_ADDR2);
	}
	else if(App_CRC_Flag1==TRUE)
		doCleanBoot(SL_BOOTAPP_ADDR1);
	else if(App_CRC_Flag2==TRUE)
		doCleanBoot(SL_BOOTAPP_ADDR2);
}

#endif
/*****************************************************************************
 * Public functions
 ****************************************************************************/

 void doCleanBoot(uint32_t appBootAddr)
{
	/* Cleanup before going to app */
	CleanUpSystem();

	bootValidApp(appBootAddr);
	/***** Control should never come here *****/

}

static uint8_t isbootFromReset(void)
{
	/* Was loader booted from app (1) or from FLASH on reset (0x44)? */
	if((uint8_t)*pushAppFlag == 0x44){
		return 1;
	}

	return 0;
}

static void I2C_Interface_Detect(void)
{
//hostifAutoDetect();		
	if (isbootFromReset()) {	
		
		/* Host interface pin setup not provided by app */		
		/*Configurate IRQ pin*/			                     //--P0_14 Input OR output?
		IRQ_Pin_Config(&slIfConfig.hostIrqPortPin);
		
		/*Dectect which I2C is used*/
		hostifAutoDetect();																//--Finish all IIC init configuration										
	}
	else {
		if(pinCheckValidHostif(pinCfgData))
		{
			/* App provided the host interface pin setup, so use it to set the version this app uses */		   
			slIfConfig.ifSel = pinCfgData->ifSel;

			/* App defined pins--IRQ pin*/
			parsePortData(&slIfConfig.hostIrqPortPin, pinCfgData->hostIrqPortPin);
		}
	}
	
	/*Set IRQ Pin as OUTPUT*/  //--means want send host command ?
	GPIOSetDir( slIfConfig.hostIrqPortPin.port, slIfConfig.hostIrqPortPin.pin, 1 );
	Hostif_AssertIRQ();
}

static uint8_t I2C_Interface_Config()
{
	uint8_t i2c_num=0;
	/* Based on the selected or detected host interface, setup specific           //--I2C0, Reconfigure all IIC function ?
	   pin muxing, the interrupt enable, and the peripheral */
	switch (1){
	case SL_I2C1:
		i2c_num = 1;
		setupMuxingI2C(i2c_num);
		setupInterfaceI2C(i2c_num);
		startHostIfI2C(i2c_num);
		loopI2C_pFunc = &loopHostIfI2C;
		slIfConfig.pI2C = LPC_I2C1;
		break;

	case SL_I2C0:
		i2c_num = 0;
		setupMuxingI2C(i2c_num);											//--init I2C function,SCL,SDA,H_Clock...No Slave_enable
		setupInterfaceI2C(i2c_num);										//--Set slave address & Interrupt enabled 
		startHostIfI2C(i2c_num);											//--CallBacks & IIC_Slave Enabled.
		loopI2C_pFunc = &loopHostIfI2C;								//--View (STAT_SLVPEND | STAT_SLVDESEL) .
		slIfConfig.pI2C = LPC_I2C0;
		break;
	}
	return i2c_num;
}


#if 1
/**
 * @brief	main routine for Secondary loader
 * @return	Function should not exit
 */
int main(void)
{
	IRQn_Type irqNum;	
	int pNum;
	
	Enable_Periph_Clock(CLK_SWM);
	Enable_Periph_Clock(CLK_IOCON);
	Enable_Periph_Clock(CLK_I2C0);

	Enable_Periph_Clock(CLK_GPIO0);

	
	GPIOInit(); //--Enable GPIO0/1 Clock								

//	LED_BLUE_OFF;
//--What ?	
	if (isbootFromReset()) {	          
		/* Check image in flash and boot *///  Maybe jump to application area.
		boot_ImageCheck();
	}
//--Why?	
	/* Disable sysTick */
	SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
//--What?
	/* Disable all NVIC interrupts in case this loader is called from the user application */	   
	for (irqNum = SPI0_IRQn; irqNum <= PININT7_IRQn; irqNum++) {
		NVIC_DisableIRQ(irqNum);
	}

	/* Enable core interrupts */
	__enable_irq();

	/* Update core clock variable */
	SystemCoreClockUpdate();
	
//--What? Wondering if <SL_AUTO=0,not  SL_I2C0=1> has influence?
	/* Initialize host interface */
	Hostif_Init();

	/*Detect which I2C is used*/                                  //--Configurate( 1.IRQ pin, P0_14; 2.finish all IIC configuration ;3.disable IIC interrput)
  I2C_Interface_Detect();

	/*Configurate I2C Interface*///--pNum=0
	pNum=I2C_Interface_Config();																	//--Reconfigure IIC and judge wether code receive data from IIC .store data setup specific pin muxing, the interrupt enable, and the peripheral

//	LED_BLUE_ON;

	/********************************************************/
	/****** Start of main host interface handling */
	/********************************************************/

	/* Wait for packets from the host, process the packet, and then respond to the host */
	while (1) {
//--What ?		
		loopI2C_pFunc(pNum);

		/* Is packet pending? */
		if (hostIfPacketPending() == true) {
			/* Send packet to parser and get new packet */
			processHostIfPacket(&recvBuff, &sendBuff);

			/* Handle response */
			while (hostIfPacketPending() != true) {
				loopI2C_pFunc(pNum);
			}
		}
	}

	/********************************************************/
	/****** End of main host interface handling */
	/********************************************************/

	/* Never called */
	return 0;
}
#endif

#if 0
#define slave_board_address 0x18
int main(void) {

  int k;
  uint32_t * addr = (uint32_t *)LPC_IOCON_BASE;

  // Enable clocks to relevant peripherals
					Enable_Periph_Clock(CLK_I2C0);
					Enable_Periph_Clock(CLK_SWM);
					Enable_Periph_Clock(CLK_GPIO0);
					Enable_Periph_Clock(CLK_IOCON);
			GPIOInit();
	
  // SWM settings for I2C0 (slave):
	LPC_SWM->PINENABLE0 &= ~((1<<13)|(1<<12));  //--!!!Adision changed according UM_P143:P0.10 = I2C0_SCL;P0.11 = I2C0_SDA
		
  // Give I2C a reset
  LPC_SYSCON->PRESETCTRL0 &=  (I2C0_RST_N);
  LPC_SYSCON->PRESETCTRL0 |= ~(I2C0_RST_N);

  // Enable main_clk as function clock to I2C
  LPC_SYSCON->I2C0CLKSEL = FCLKSEL_MAIN_CLK;
  
  // Get main_clk frequency
  SystemCoreClockUpdate();  //??
 
	//--AZ get clock		SCL rate = I2C clock / (SCL_H+SCL_L) = 30000000 / 75 =400KHz .
	LPC_I2C0->MSTTIME &= 0XFFFFFF81;   //--L_0x1_3clock;H_0x0_2clock
	LPC_I2C0->CLKDIV = 5;						   //--SCL high time = (CLKDIV + 1) * (MSTSCLHIGH + 2) = 6*2 = 12 ; SCL_Low = 18 ;


  // Configure the I2C CFG register:
  // Slave enable = true
  LPC_I2C0->CFG = CFG_SLVENA;

  // Give the slave an address in one of its four address regs, and activate it
  LPC_I2C0->SLVADR3 = (slave_board_address<<1) | 0;

  // Enable the I2C slave pending interrupt
  LPC_I2C0->INTENSET = STAT_SLVPEND;							//--8:This flag will cause an interrupt when set if enabled via INTENSET.

		LED_BLUE_ON;
  while(1) {
		
//--Copy from LPC804	
//--polling judge
//		if ((pI2CINST->STAT & SLAVE_STATE_MASK) == STAT_SLVRX) {
		
		while( (LPC_I2C0->INTSTAT & ~I2C_INTSTAT_RESERVED) & (STAT_SLVPEND | STAT_SLVDESEL) )//--wait bit 8 /15 set 1
		{
				//pI2CINST->SLVCTL = CTL_SLVCONTINUE;                     // ACK the data
				LED_RED_ON;//--AZ		
		}

//--Copy from LPC845		
//		if ((LPC_I2C0->STAT & SLAVE_STATE_MASK) == STAT_SLVADDR) {
//			LPC_I2C0->SLVCTL = CTL_SLVCONTINUE;                     // ACK the address
//		}
//		if ((LPC_I2C0->STAT & SLAVE_STATE_MASK) == STAT_SLVRX) {
//			LPC_I2C0->SLVCTL = CTL_SLVCONTINUE;                     // ACK the data
//			LED_RED_ON;												//--AZ	
//		}
  } 

} // end of main
#endif