#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 <string.h>
#include <stdlib.h>
#include "sys/alt_stdio.h"

int main()
{
	char user_input='0';
	int state=0;
	int image1_StartAddress, image1_EndAddress, image1_StartSector, image1_EndSector;
	int image2_StartAddress, image2_EndAddress, image2_StartSector, image2_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 ******
	image1_StartAddress		= 0x400000;
	image1_EndAddress 		= 0x45AFFF;
	image1_StartSector		= (image1_StartAddress & 0xFFFF0000) >> 16;
	image1_EndSector		= (image1_EndAddress & 0xFFFF0000) >> 16;
	software1_StartAddress	= 0x7C0000;
	software1_EndAddress	= 0x7FFFFF;
	software1_StartSector	= (software1_StartAddress & 0xFFFF0000) >> 16;
	software1_EndSector		= (software1_EndAddress & 0xFFFF0000) >> 16;
	image2_StartAddress		= 0x800000;
	image2_EndAddress		= 0xBBFFFF;
	image2_StartSector		= (image2_StartAddress & 0xFFFF0000) >> 16;
	image2_EndSector		= (image2_EndAddress & 0xFFFF0000) >> 16;
	software2_StartAddress	= 0xBC0000;
	software2_EndAddress	= 0xBFFFFF;
	software2_StartSector	= (software2_StartAddress & 0xFFFF0000) >> 16;
	software2_EndSector		= (software2_EndAddress & 0xFFFF0000) >> 16;

//	printf("Factory software running...\n");
//	printf("System ID: 0x%X\n", IORD(SYSID_BASE, 0));
	//IOWR(LED_BASE, 0, 0x01);
	IOWR_ALTERA_AVALON_PIO_DATA(LED_BASE, 0x01);
//	printf("RU_RECONFIG_TRIGGER_CONDITIONS: 0x%08x\n", IORD(REMOTE_UPDA``TE_BASE, 0x0));
//	printf("RU_WATCHDOG_TIMEOUT: 0x%08x\n", IORD(REMOTE_UPDATE_BASE, 0x1));
//	printf("RU_WATCHDOG_ENABLE: 0x%08x\n", IORD(REMOTE_UPDATE_BASE, 0x2));
//	printf("RU_PAGE_SELECT: 0x%08x\n", IORD(REMOTE_UPDATE_BASE, 0x3));
//	printf("RU_CONFIGURATION_MODE: 0x%08x\n\n", IORD(REMOTE_UPDATE_BASE, 0x4));

	//****** 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 Image\r\n");
				printf("2: Upgrade Application 1 Software\r\n");
				printf("3: Upgrade Application 2 Image\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 Image ******
				if(user_input == '1')
				{
					printf("ʼ...\r\n");

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

					//Erase sector
					for(i=image1_StartSector; i<=image1_EndSector; i++)
					{
						eraseSector = (eraseSector & 0) | (i << 8) | 0x02;
						printf("Erasing image 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=image1_StartAddress; writeAddress<=image1_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("!\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 Image ******
				if(user_input == '3')
				{
					printf("Application 2 Image 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=image2_StartSector; i<=image2_EndSector; i++)
					{
						eraseSector = (eraseSector & 0) | (i << 8) | 0x02;
						printf("Erasing Application 2 Image 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=image2_StartAddress; writeAddress<=image2_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 Image 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, image1_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, image2_StartAddress);

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

					printf("completed\r\n");

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

				*/

				printf("Ч,\n\n");
				state = 0;

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

  return 0;
}



