#include <stdio.h>
#include "system.h"
#include "io.h"
#include "sys/alt_flash.h"
#include "sys/alt_flash_dev.h"
#include "altera_avalon_pio_regs.h"
#include "altera_avalon_uart_regs.h"
#include <string.h>
#include <stdlib.h>
#include "sys/alt_stdio.h"
#include "uart.h"
#include "modbus.h"
#include "timer.h"

//alt_u8 data_tmp[1024] = {0};//ڽյʱ
extern alt_u8 uart0_tx_state;//0״̬
//extern alt_u32 timer_done;
//int main()
//{
//	alt_u8 rx_len = 0;//յݳ
//	//ʼ
//	uart0_tx_state = UART_TX_IDLE;//ʼ״̬־Ϊ
//	UART_HANDLE hUART0;
//	hUART0 = UART_Init(
//			UART_BASE,
//			UART_IRQ_INTERRUPT_CONTROLLER_ID,
//			UART_IRQ,
//			(IRRDY_IRQ_MASK),//򿪽жʹ0X80
//			115200,//ڲ
//			(alt_isr_func)UART0_isr
//		);
//	if (!hUART0) {
////		printf("Failed to init UART0\n");
//	}
//
//	 //ʼʱ
//	CoreCourse_TIMER *pTimer;
//	pTimer = Timer_Init(
//			TIMER_0_BASE,
//			TIMER_0_IRQ_INTERRUPT_CONTROLLER_ID,
//			TIMER_0_IRQ
//			);
//	if (!pTimer) {
//		//printf("Failed to init Timer\n");
//	}
//	while(1)
//	{
//		ModBus_ReceieveCMD(hUART0); //ڽж
////		if(timer_done)
////		{
////			Judge_ETB();
////			timer_done = 0;
////		}
//	}
//}

int main()
{
	char user_input='0';
	int state=0;
	int Hardware1_StartAddress, Hardware1_EndAddress, Hardware1_StartSector, Hardware1_EndSector;
	int Hardware2_StartAddress, Hardware2_EndAddress, Hardware2_StartSector, Hardware2_EndSector;
	int software1_StartAddress, software1_EndAddress, software1_StartSector, software1_EndSector;
	int software2_StartAddress, software2_EndAddress, software2_StartSector, software2_EndSector;
	int i=0, eraseSector, writeAddress, tempAddress, receivedHex[4], byte;

	//****** Define all the Start & End address/sector ******
	Hardware1_StartAddress		= 0x400000;
	Hardware1_EndAddress 		= 0x7BFFFF;
	Hardware1_StartSector		= (Hardware1_StartAddress & 0xFFFF0000) >> 16;
	Hardware1_EndSector		= (Hardware1_EndAddress & 0xFFFF0000) >> 16;
	software1_StartAddress	= 0x7C0000;
	software1_EndAddress	= 0x7FFFFF;
	software1_StartSector	= (software1_StartAddress & 0xFFFF0000) >> 16;
	software1_EndSector		= (software1_EndAddress & 0xFFFF0000) >> 16;
	Hardware2_StartAddress		= 0x800000;
	Hardware2_EndAddress		= 0xBBFFFF;
	Hardware2_StartSector		= (Hardware2_StartAddress & 0xFFFF0000) >> 16;
	Hardware2_EndSector		= (Hardware2_EndAddress & 0xFFFF0000) >> 16;
	software2_StartAddress	= 0xBC0000;
	software2_EndAddress	= 0xBFFFFF;
	software2_StartSector	= (software2_StartAddress & 0xFFFF0000) >> 16;
	software2_EndSector		= (software2_EndAddress & 0xFFFF0000) >> 16;

	IOWR_ALTERA_AVALON_PIO_DATA(LED_BASE, 0x01);

		//ʼ
		uart0_tx_state = UART_TX_IDLE;//ʼ״̬־Ϊ
		UART_HANDLE hUART0;
		hUART0 = UART_Init(
				UART_BASE,
				UART_IRQ_INTERRUPT_CONTROLLER_ID,
				UART_IRQ,
				(IRRDY_IRQ_MASK),//򿪽жʹ0X80
				115200,//ڲ
				(alt_isr_func)UART0_isr
			);
		if (!hUART0) {
	//		printf("Failed to init UART0\n");
		}

	//****** Protect Factory & Application sectors ******
	//FLASH_MEM_OP - XXXXXXXX:XXXXXXXX:XXX11001:XXXXXX11
//	IOWR(EPCQ_CONTROLLER_AVL_CSR_BASE, 0x3, 0x00001903);

	while(1)
	{
		switch(state)
		{
			case 0:
				printf("boot from factory\r\n");
				printf("1: Upgrade Application 1 Hardware\r\n");
				printf("2: Upgrade Application 1 Software\r\n");
				printf("3: Upgrade Application 2 Hardware\r\n");
				printf("4: Upgrade Application 2 Software\r\n");
				printf("5: Trigger reconfiguration to Application 1\r\n");
				printf("6: Trigger reconfiguration to Application 2\r\n");
				//scanf("%s", &user_input);
				  user_input='0';
				  user_input=alt_getchar();
				printf("\r\n",user_input);
				state = 1;
			break;

			case 1:
				//****** Upgrade Application 1 Hardware ******
				if(user_input == '1')
				{
					printf("Application 1 Hardware upgrade in progress...\r\n");

					//Unprotect Application sectors
					//FLASH_MEM_OP - XXXXXXXX:XXXXXXXX:XXX10111:XXXXXX11
//					IOWR(EPCQ_CONTROLLER_AVL_CSR_BASE, 0x3, 0x00001703);

					//Erase sector
					for(i=Hardware1_StartSector; i<=Hardware1_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("Erase completed!\r\n");
					printf("Enter programming file...\r\n");
					for(writeAddress=Hardware1_StartAddress; writeAddress<=Hardware1_EndAddress; writeAddress=writeAddress+4)
					{
						//Get 4 bytes from UART terminal
						//scanf("%2x%2x%2x%2x", &receivedHex[0], &receivedHex[1], &receivedHex[2], &receivedHex[3]);

						for(int i=0;i<4;i++)
								receivedHex[i]=alt_getchar();
						//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);
						}

						//Write into flash
						tempAddress = writeAddress;
						for(i=0; i<4; i++)
						{
							IOWR_8DIRECT(EPCQ_CONTROLLER_AVL_MEM_BASE, tempAddress, receivedHex[i]);
							tempAddress++;
						}
					}

					//****** Protect Factory & Application sectors ******
					//FLASH_MEM_OP - XXXXXXXX:XXXXXXXX:XXX11001:XXXXXX11
					IOWR(EPCQ_CONTROLLER_AVL_CSR_BASE, 0x3, 0x00001903);

					printf("Application 1 Hardware upgrade completed!\r\n");
					state = 0;
					user_input='0';
					break;
				}
				//****** Upgrade Application 1 Software ******
				if(user_input == '2')
				{
					printf("Application 1 Software upgrade in progress...\r\n");

					//Unprotect Application sectors
					//FLASH_MEM_OP - XXXXXXXX:XXXXXXXX:XXX10111:XXXXXX11
					IOWR(EPCQ_CONTROLLER_AVL_CSR_BASE, 0x3, 0x00001703);

					//Erase sector
					for(i=software1_StartSector; i<=software1_EndSector; i++)
					{
						eraseSector = (eraseSector & 0) | (i << 8) | 0x02;
						printf("Erasing Application 1 Software sector %d\r\n", i);
						IOWR(EPCQ_CONTROLLER_AVL_CSR_BASE, 0x3, eraseSector);
					}

					printf("Erase completed!\r\n");
					printf("Enter programming file...\r\n");
					for(writeAddress=software1_StartAddress; writeAddress<=software1_EndAddress; writeAddress=writeAddress+4)
					{
						//Get 4 bytes from UART terminal
						//scanf("%2x%2x%2x%2x", &receivedHex[0], &receivedHex[1], &receivedHex[2], &receivedHex[3]);
						for(int i=0;i<4;i++)
						receivedHex[i]=alt_getchar();
						//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);
						}

						//Write into flash
						tempAddress = writeAddress;
						for(i=0; i<4; i++)
						{
							IOWR_8DIRECT(EPCQ_CONTROLLER_AVL_MEM_BASE, tempAddress, receivedHex[i]);
							tempAddress++;
						}
					}

					//****** Protect Factory & Application sectors ******
					//FLASH_MEM_OP - XXXXXXXX:XXXXXXXX:XXX11001:XXXXXX11
					IOWR(EPCQ_CONTROLLER_AVL_CSR_BASE, 0x3, 0x00001903);

					printf("Application 1 Software upgrade completed!\r\n");
					state = 0;
					user_input='0';
					break;
				}
				//****** Upgrade Application 2 Hardware ******
				if(user_input == '3')
				{
					printf("Application 2 Hardware upgrade in progress...\r\n");

					//Unprotect Application sectors
					//FLASH_MEM_OP - XXXXXXXX:XXXXXXXX:XXX10111:XXXXXX11
					IOWR(EPCQ_CONTROLLER_AVL_CSR_BASE, 0x3, 0x00001703);

					//Erase sector
					for(i=Hardware2_StartSector; i<=Hardware2_EndSector; i++)
					{
						eraseSector = (eraseSector & 0) | (i << 8) | 0x02;
						printf("Erasing Application 2 Hardware sector %d\r\n", i);
						IOWR(EPCQ_CONTROLLER_AVL_CSR_BASE, 0x3, eraseSector);
					}

					printf("Erase completed!\r\n");
					printf("Enter programming file...\r\n");

					for(writeAddress=Hardware2_StartAddress; writeAddress<=Hardware2_EndAddress; writeAddress=writeAddress+4)
					{
						//Get 4 bytes from UART terminal
						//scanf("%2x%2x%2x%2x", &receivedHex[0], &receivedHex[1], &receivedHex[2], &receivedHex[3]);
						for(int i=0;i<4;i++)
													receivedHex[i]=alt_getchar();

		    			//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);
						}

						//Write into flash
						tempAddress = writeAddress;
						for(i=0; i<4; i++)
						{
							IOWR_8DIRECT(EPCQ_CONTROLLER_AVL_MEM_BASE, tempAddress, receivedHex[i]);
							tempAddress++;
						}
					}

					//****** Protect Factory & Application sectors ******
					//FLASH_MEM_OP - XXXXXXXX:XXXXXXXX:XXX11001:XXXXXX11
					IOWR(EPCQ_CONTROLLER_AVL_CSR_BASE, 0x3, 0x00001903);

					printf("Application 2 Hardware upgrade completed!\r\n");
					state = 0;
					user_input='0';
					break;
				}
				//****** Upgrade Application 2 Software ******
				if(user_input == '4')
				{
					printf("Application 2 Software upgrade in progress...\r\n");

					//Unprotect Application sectors
					//FLASH_MEM_OP - XXXXXXXX:XXXXXXXX:XXX10111:XXXXXX11
					IOWR(EPCQ_CONTROLLER_AVL_CSR_BASE, 0x3, 0x00001703);

					//Erase sector
					for(i=software2_StartSector; i<=software2_EndSector; i++)
					{
						eraseSector = (eraseSector & 0) | (i << 8) | 0x02;
						printf("Erasing Application 2 Software sector %d\r\n", i);
						IOWR(EPCQ_CONTROLLER_AVL_CSR_BASE, 0x3, eraseSector);
					}

					printf("Erase completed!\n\n");
					printf("Enter programming file...\r\n");

					for(writeAddress=software2_StartAddress; writeAddress<=software2_EndAddress; writeAddress=writeAddress+4)
					{
						//Get 4 bytes from UART terminal
						//scanf("%2x%2x%2x%2x", &receivedHex[0], &receivedHex[1], &receivedHex[2], &receivedHex[3]);
						for(int i=0;i<4;i++)
			            	receivedHex[i]=alt_getchar();
						//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);
						}

						//Write into flash
						tempAddress = writeAddress;
						for(i=0; i<4; i++)
						{
							IOWR_8DIRECT(EPCQ_CONTROLLER_AVL_MEM_BASE, tempAddress, receivedHex[i]);
							tempAddress++;
						}
					}

					//****** Protect Factory & Application sectors ******
					//FLASH_MEM_OP - XXXXXXXX:XXXXXXXX:XXX11001:XXXXXX11
					IOWR(EPCQ_CONTROLLER_AVL_CSR_BASE, 0x3, 0x00001903);

					printf("Application 2 Software upgrade completed!\r\n");
					state = 0;
					user_input='0';
					break;
				}

				//****** Trigger reconfiguration to Application 1 ******
				if(user_input == '5')
				{
					//printf("completed1\n\n");
					//Set configuration mode to application page
					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
				//	state = 0;
				//	user_input='0';
					break;
				}
				//****** Trigger reconfiguration to Application 2
				if(user_input == '6')
				{
					//Set configuration mode to application page
					IOWR(REMOTE_UPDATE_BASE, 0xC, 0);

					//Write start address
					IOWR(REMOTE_UPDATE_BASE, 0x10, Hardware2_StartAddress);

					//Trigger reconfiguration
					IOWR(REMOTE_UPDATE_BASE, 0x1D, 1);

					printf("completed\r\n");

					//state = 0;
					//user_input='0';
					break;
				}



				printf("input invalid\n\n");
				state = 0;

				user_input='0';
				break;
			default:state = 0;
		}
	}

  return 0;
}
