#include "modbus.h"

MODH_T g_tModH;

extern uint8_t FLAG_FrameData;
extern UART_HANDLE hUART0;
volatile uint8_t flag = 0;

uint16_t  Time = 0;

uint32_t Flash_Address;

uint8_t Time_1[] = "ʱ5!!!\n";
uint8_t Time_2[] = "ʱ4!!!\n";
uint8_t Time_3[] = "ʱ3!!!\n";
uint8_t Time_4[] = "ʱ2!!!\n";
uint8_t Time_5[] = "ʱ1!!!\n";
uint8_t Time_6[] = "ڽû!!!\n";
uint8_t app_x = 1;
int Hardware1_StartAddress, Hardware1_EndAddress, Hardware_StartSector;
int Hardware2_StartAddress = 0, Hardware2_EndAddress = 0, Hardware_EndSector = 0;
extern volatile uint8_t count;
extern volatile uint8_t FLAG_StartFlowData;

//ַ־ź
uint8_t erase_startAddr_flag = 0;
uint8_t get_app2_startAddr_flag = 0;

static void MODH_Read_01H(void);
static void MODH_Read_02H(void);
static void MODH_Read_03H(void);
static void MODH_Read_04H(void);
static void MODH_Read_10H(void);
extern alt_u8 uart0_tx_state;//0״̬
extern uint8_t CocheData[64];      //ʱݻ
extern uint8_t FLAG_FlowData;

/*ݴݻ洢*/
char CopyCocheData(uint8_t *dat, uint16_t len) {
	uint8_t i;

	if(len>=count){                   //ȽϽճ;len ַ count ʵʽյַ
		i = count;
	  count = 0;
	for (char j = 0; j < i; j++)
		dat[j] = CocheData[j];        //ݴӻⱻһ֡ƻʱڴͷŻ
	return i;                         //ؽյݳ
	}
	else{
	  i=len;
		count = 0;
		for(char j=0;j<len;j++)
		  dat[j] = CocheData[j];
	return i;
	}
}

void ModBus_ReceieveCMD(UART_HANDLE hUART0)
{
//	uint8_t i;
//	uint8_t count;
//	uart0_tx_state = UART_TX_BUSY;//Ǵ0״̬Ϊæ
//	count = UARTx_Rx(hUART0,(alt_u8 *)g_tModH.RxBuf); //Ӵڽյ
//	if (count == 8) {  //ڽյһ֡
//		flag = 1;  //״̬־λ
//		Time = 0;
//		FLAG_FrameData = 0;
//		if(g_tModH.RxBuf[0] == SlaveAddr){ //⴮ڽյĵһλǷΪӻַ
//			MODH_AnalyzeApp(hUART0); //յ
//		}
//		else
//			UARTx_Tx(hUART0,(alt_u8 *)"Slave Address error!\n",sizeof("Slave Address error!\n")-1);
//		}
	uint8_t i;
	if (FLAG_FrameData) {  //ڽյһ֡
		flag = 1;  //״̬־λ
		FLAG_FrameData = 0;
		CopyCocheData(g_tModH.RxBuf,sizeof(g_tModH.RxBuf) - 1); //Ӵڽյ
		if(g_tModH.RxBuf[0] == SlaveAddr){ //⴮ڽյĵһλǷΪӻַ
			MODH_AnalyzeApp(hUART0); //յ
		}
		else
			printf("Slave Address error!\n");
		}
	else if(Time == 0 && flag == 0){
		UARTx_Tx(hUART0, Time_1, sizeof(Time_1)-1);
		uart0_tx_state = UART_TX_BUSY;//Ǵ0״̬Ϊæ
		usleep(1000000);    //ʱ1S
		Time = Time +1;
	}
	else if(Time == 1 && flag == 0){ //ʱʱ1Sδ״̬
		UARTx_Tx(hUART0, Time_2, sizeof(Time_2)-1);
		uart0_tx_state = UART_TX_BUSY;//Ǵ0״̬Ϊæ
		usleep(1000000);    //ʱ1S
		Time = Time +1;
	}
	else if(Time == 2 && flag == 0){ //ʱʱ2Sδ״̬
		UARTx_Tx(hUART0, Time_3, sizeof(Time_3)-1);
		uart0_tx_state = UART_TX_BUSY;//Ǵ0״̬Ϊæ
		usleep(1000000);    //ʱ1S
		Time = Time +1;
	}
	else if(Time == 3 && flag == 0){ //ʱʱ3Sδ״̬
		UARTx_Tx(hUART0, Time_4, sizeof(Time_4)-1);
		uart0_tx_state = UART_TX_BUSY;//Ǵ0״̬Ϊæ
		usleep(1000000);    //ʱ1S
		Time = Time +1;
	}
	else if(Time == 4 && flag == 0){ //ʱʱ4Sδ״̬
		UARTx_Tx(hUART0, Time_5, sizeof(Time_5)-1);
		uart0_tx_state = UART_TX_BUSY;//Ǵ0״̬Ϊæ
		usleep(1000000);    //ʱ1S
		Time = Time +1;
	}
	else if(Time == 5 && flag == 0){ //ʱ5Sûнյκָûڸ״̬ʱĬϽûAPP1
		UARTx_Tx(hUART0, Time_6, sizeof(Time_6)-1);
		uart0_tx_state = UART_TX_BUSY;//Ǵ0״̬Ϊæ
		usleep(1000);    //ʱ
		Hardware1_StartAddress		= Hardware1_StA;
		jump_hardware1();
		Time = 0;
	}
}
//תAPP1ĳ
void jump_hardware1()
{
	printf("תAPP1!!!\n");
	Hardware1_StartAddress		= Hardware1_StA;
	IOWR(REMOTE_UPDATE_BASE, 0x0C, 0); //
	//Write start address
	IOWR(REMOTE_UPDATE_BASE, 0x10, Hardware1_StartAddress); //3
	//Trigger reconfiguration
	IOWR(REMOTE_UPDATE_BASE, 0x1D, 1); // 6
}

//תAPP2ĳ
void jump_hardware2()
{
	IOWR(REMOTE_UPDATE_BASE, 0x0C, 0); //
	//Write start address
	IOWR(REMOTE_UPDATE_BASE, 0x10, Hardware2_StartAddress); //3
	//Trigger reconfiguration
	IOWR(REMOTE_UPDATE_BASE, 0x1D, 1); // 6
}
/*
*********************************************************************************************************
*	  : MODH_AnalyzeApp
*	˵: ӦòЭ顣Ӧ
*	    : 
*	  ֵ: 
*********************************************************************************************************
*/
void MODH_AnalyzeApp(UART_HANDLE hUART0)
{	
	switch (g_tModH.RxBuf[1])			/* 2ֽ  */
	{
		case 0x01:	/* ȡȦ״̬ */
			MODH_Read_01H();
			break;
		case 0x02:	/* ȡ״̬ */
			MODH_Read_02H();
			break;
		case 0x03:	/* ȡּĴ һּĴȡõǰĶֵ */
			MODH_Read_03H();
			break;
		case 0x04:	/* ȡĴ */
			MODH_Read_04H();
			break;
		case 0x05:	/* ǿƵȦ */
			MODH_Read_05H(hUART0);
			break;
		case 0x06:	/* дĴ */
			MODH_Read_06H(hUART0);
			break;	
		case 0x10:	/* дĴ */
			MODH_Read_10H();
			break;		
		default:
			printf("Function error!\n");
//			UARTx_Tx(hUART0, (alt_u8 *)"Function error!\n",sizeof("Function error!\n"));
			break;
	}
}
/*
*********************************************************************************************************
*	  : MODH_Read_01H
*	˵: 01HָӦ
*	    : 
*	  ֵ: 
*********************************************************************************************************
*/
static void MODH_Read_01H(void)
{

}

/*
*********************************************************************************************************
*	  : MODH_Read_02H
*	˵: 02HָӦ
*	    : 
*	  ֵ: 
*********************************************************************************************************
*/
static void MODH_Read_02H(void)
{
	
}

/*
*********************************************************************************************************
*	  : MODH_Read_04H
*	˵: 04HָӦ
*	    : 
*	  ֵ: 
*********************************************************************************************************
*/
static void MODH_Read_04H(void)
{
	
}

/*
*********************************************************************************************************
*	  : MODH_Read_05H
*	˵: 05HָӦ
*	    : 
*	  ֵ: 
*********************************************************************************************************
*/
void MODH_Read_05H(UART_HANDLE hUART0)
{
	uint32_t erase_addr_sta = 0,erase_addr_end = 0;     //flashҪĵַ
	int eraseSector;
	int Hardware_StartSector;
	int Hardware_EndSector;
	int i;
	if(erase_startAddr_flag)     //մڴҪʼַ
	{
		erase_startAddr_flag = 0;
		erase_addr_sta = ((g_tModH.RxBuf[2] << 8) | g_tModH.RxBuf[3]) << 8 | g_tModH.RxBuf[4];
		erase_addr_end = ((g_tModH.RxBuf[5] << 8) | g_tModH.RxBuf[6]) << 8 | g_tModH.RxBuf[7];
		printf("\nstart Erase: 0x%X\n",erase_addr_sta);
		Hardware_StartSector = (erase_addr_sta & 0xFFFF0000) >> 16;
		Hardware_EndSector = (erase_addr_end & 0xFFFF0000) >> 16;
		for(i=Hardware_StartSector; i<=Hardware_EndSector; i++)
		{
			eraseSector = (eraseSector & 0) | (i << 8) | 0x02;
			printf("Erasing Application 1 Hardware sector %d\r\n", i);
			IOWR(EPCQ_CONTROLLER_AVL_CSR_BASE, 0x3, eraseSector);
		}
		printf("Eease ok!!!\n\r");
		//ж֮սbuffer¿ʼ
		for(i = 0;i < 12;i++){
			g_tModH.RxBuf[i] = 0;
			i++;
		}
	}
	else if(get_app2_startAddr_flag)
	{
		get_app2_startAddr_flag = 0;
		Hardware2_StartAddress = ((g_tModH.RxBuf[2] << 8) | g_tModH.RxBuf[3]) << 8 | g_tModH.RxBuf[4];
		//ж֮սbuffer¿ʼ
		if(Hardware2_StartAddress > Hardware1_StA)
		{
			printf("\nAPP2 start addr: 0x%X\n",Hardware2_StartAddress);
			app_x = 0;
		}
		else
		{
			printf("\nAPP2ʼַϹ涨\n\r");
		}
		for(i = 0;i < 12;i++){
			g_tModH.RxBuf[i] = 0;
			i++;
		}
	}
	else if(g_tModH.RxBuf[2] == 2)
	{
		printf("ɹлAPP2");
		app_x = 2;
	}
	else if(g_tModH.RxBuf[2] == 1)
	{
		app_x = 1;
	}

}


void write_flash(uint32_t add)
{
    uint8_t len;
    uint8_t receivedHex[4];            //ʱݻ
    int byte,i;
    FLAG_FlowData = 1;  //1ģʽ,λ1ʾյݶļе
    while(FLAG_StartFlowData != 1);
    while(FLAG_StartFlowData == 1)   //ģʽ
    {
    	if (count >= 4)
    	{
    		len = CopyCocheData(receivedHex, 4);//յݿʱݴ洢
    		//Swap LSB with MSB
    		for(byte=0; byte<4; byte++)
    		{
    			receivedHex[byte] = ((receivedHex[byte] & 0xAA) >> 1) | ((receivedHex[byte] & 0x55) << 1);
    			receivedHex[byte] = ((receivedHex[byte] & 0xCC) >> 2) | ((receivedHex[byte] & 0x33) << 2);
    			receivedHex[byte] = ((receivedHex[byte] & 0xF0) >> 4) | ((receivedHex[byte] & 0x0F) << 4);
    		}

    		for(i=0; i<4; i++)
    		{
    			IOWR_8DIRECT(EPCQ_CONTROLLER_AVL_MEM_BASE, add, receivedHex[i]);
    			add++;
    		}
    	}
    }
    /*ģʽʣµдflash*/
	len = CopyCocheData(receivedHex, 4);
	if (len != 0) {
		    //Swap LSB with MSB
            for(byte=0; byte<4; byte++)
            {
                receivedHex[byte] = ((receivedHex[byte] & 0xAA) >> 1) | ((receivedHex[byte] & 0x55) << 1);
                receivedHex[byte] = ((receivedHex[byte] & 0xCC) >> 2) | ((receivedHex[byte] & 0x33) << 2);
                receivedHex[byte] = ((receivedHex[byte] & 0xF0) >> 4) | ((receivedHex[byte] & 0x0F) << 4);
            }

            for(i=0; i<4; i++)
            {
                IOWR_8DIRECT(EPCQ_CONTROLLER_AVL_MEM_BASE, add, receivedHex[i]);
                add++;
            }
	}
    FLAG_FlowData = 0;     //ݴ
}

/*
*********************************************************************************************************
*	  : MODH_Read_06H
*	˵: 06HָӦ
*	    : 
*	  ֵ: 
*********************************************************************************************************
*/
void MODH_Read_06H(UART_HANDLE hUART0)
{
	uint16_t RX_Command;
	uint16_t CRC;
	uint8_t i;
	int writeAddress, tempAddress, byte;
	uint8_t receivedHex[64];            //ʱݻ
    RX_Command = ((uint16_t)g_tModH.RxBuf[4] << 8) | g_tModH.RxBuf[5];  //ԤõĵĴֵ
	CRC = ((uint16_t)g_tModH.RxBuf[6] << 8) | g_tModH.RxBuf[7]; //Уֵ
	if(((g_tModH.RxBuf[2] << 8) |  g_tModH.RxBuf[3]) == REG_Address){  //жϽյļĴַǷȷ
		switch(RX_Command << 8 | CRC)
		{
			case Erase_FlashSector << 8 | Erase_FlashSector_CRC:
			{
				count =0;
				//ж֮սbuffer¿ʼ
				for(i = 0;i < 12;i++){
					g_tModH.RxBuf[i] = 0;
					i++;
				}
				erase_startAddr_flag = 1;
				printf("Ҫʼͽַ01 05 ʼַ(3ֽ) ַ(3ֽ)");

				break;
			}

			case Get_App2_addr << 8 | Get_App2_addr_CRC:     //ûAPP2ʼַ
			{
				get_app2_startAddr_flag = 1;
				printf("û2ʼַ01 05 ʼַ(3ֽ)");
				break;
			}

			case Write_Flash << 8 | Write_Flash_CRC:  //Flashд
			{
				if(app_x == 1)
				{
					printf("\nAPP1дŵĹ\n");
					Hardware1_StartAddress		= Hardware1_StA;
					if(Hardware2_StartAddress <= Hardware1_StartAddress) //˵ûֻҪAPP1ҪAPP2
					{
						Hardware1_EndAddress = 0x7BFFFF;
						printf("\nupdate start addr: 0x%X\n",Hardware1_StartAddress);
						printf("\nupdate start end: 0x%X\n",Hardware1_EndAddress);
					}
					else
					{
						printf("\nupdate start addr: 0x%X\n",Hardware1_StartAddress);
						printf("\nupdate start end: 0x%X\n",Hardware1_EndAddress);
					}
					printf("\nEnter programming file...\r\n");

					write_flash(Hardware1_StartAddress);
					IOWR(EPCQ_CONTROLLER_AVL_CSR_BASE, 0x3, 0x00001903);
					printf("\nApplication Hardware1 upgrade completed!\r\n");
				}
				else if(app_x == 2)    //ҪµAPP2
				{
					printf("\nAPP2дŵĹ\n");
					if(Hardware2_StartAddress <= Hardware1_StartAddress) //˵û֮ǰûиAPP2ĵַ
					{
						printf("\nȸAPP2ʼַ!!!\n\r");
					}
					else
					{
						Hardware2_EndAddress = Hardware2_End;
						printf("\nupdate start addr: 0x%X\n",Hardware2_StartAddress);
						printf("\nupdate start end: 0x%X\n",Hardware2_EndAddress);

						printf("\nEnter programming file...\r\n");
						write_flash(Hardware2_StartAddress);
						printf("Application Hardware2 upgrade completed!\r\n");
					}
				}
				else {
					printf("\nȷҪµû01 05 01:APP1;02:APP2\n");
				}
				break;
			}

			case Start_APP1 << 8 | Start_APP1_CRC:  //״̬תû
			{
				jump_hardware1();
				break;
			}

			case Start_APP2 << 8 | Start_APP2_CRC:  //״̬תû
			{
				jump_hardware2();
				break;
			}

			default:
				//ж֮սbuffer¿ʼ
				for(i = 0;i < 8;i++){
					g_tModH.RxBuf[i] = 0;
					i++;
				}
				printf("Preset Data or CRC error!\n");
				break;
		}
	}
	else
		printf("Register address error!\n");
}

/*
*********************************************************************************************************
*	  : MODH_Read_03H
*	˵: 03HָӦ
*	    : 
*	  ֵ: 
*********************************************************************************************************
*/
void MODH_Read_03H(void)
{
	
}

/*
*********************************************************************************************************
*	  : MODH_Read_10H
*	˵: 10HָӦ
*	    : 
*	  ֵ: 
*********************************************************************************************************
*/
void MODH_Read_10H(void)
{
	
}

void delay(uint32_t t)
{
	t= t*250;
	while(t--);
}
