#include <stdio.h>
#include <time.h>
#include <windows.h>

#define VC_EXTRALEAN
#include <string.h>

// Flow control flags

#define FC_DTRDSR 0x01
#define FC_RTSCTS 0x02
#define FC_XONXOFF 0x04

// ascii definitions

#define ASCII_BEL 0x07
#define ASCII_BS 0x08
#define ASCII_LF 0x0A
#define ASCII_CR 0x0D
#define ASCII_XON 0x11
#define ASCII_XOFF 0x13

BOOL bPortReady;
DCB dcb;
COMMTIMEOUTS CommTimeouts;
BOOL bWriteRC;
BOOL bReadRC;
DWORD iBytesWritten;
DWORD iBytesRead;


unsigned atohex(str)
char *str; {

    unsigned n = 0;

    while (*str)
    {
		if (isdigit(*str))
		{
			n=16*n + *str - '0';
		}
	    else if (*str >= 'a' && *str <= 'f')
	    {
			n = 16*n + *str - 'a' + 10;
		}
	    else if( (*str == 'x') || (*str == 'X'))
    	{
    	}
    	else
    	{
   	        printf("Invalid hex number");
	        return(0);
	    }
	    str++;
    }
    return(n);
}


char SerialGetc(HANDLE hCom)
{
     BOOL bReadRC;
     char ret[4];

     static DWORD iBytesRead = -1;

     bReadRC = ReadFile(hCom, ret, 1,&iBytesRead,NULL);

     return ret[0];
}



void SerialPutc(HANDLE hCom, char txchar)
{
    BOOL bWriteRC;
    static DWORD iBytesWritten = -1;

    bWriteRC = WriteFile(hCom, &txchar, 1, &iBytesWritten,NULL);

    return;
}


int main(int argc, char *argv[])
{
   DCB dcb;
   HANDLE hCom;
   HANDLE *ptr;
   char letter;
   FILE *fp;
   long size,result, length,address;

   char filename[100];
   char buffer[1030];
   char ret[8];
   BOOL bReadRC;

   static DWORD iBytesRead = -1;


   BOOL fSuccess;
   char pcCommPort[5]="COM";

   if(argc <5)
   {

      	printf("Usage for spiflash: A2F_Mem_SPIFlash_Loader.exe spi address filename comportnumber\n");
	  	printf("Address reange is from 0 to 0x7FFFFF\n\n");

	    return 0;
   }


   strcat(pcCommPort,argv[4]);
   hCom = CreateFile( pcCommPort,
                      GENERIC_READ | GENERIC_WRITE,
                      0, // must be opened with exclusive-access
                      NULL, // no security attributes
                      OPEN_EXISTING, // must use OPEN_EXISTING
                      0, // not overlapped I/O
                      NULL // hTemplate must be NULL for comm devices
                     );

   if (hCom == INVALID_HANDLE_VALUE)
   {
     // Handle the error.
       printf ("Cann't open UART port, Please close if the port is open by other application %d.\n", GetLastError());
       return (1);
   }

// Build on the current configuration, and skip setting the size
// of the input and output buffers with SetupComm.

   fSuccess = GetCommState(hCom, &dcb);

   if (!fSuccess)
   {
       // Handle the error.
       printf ("Cann't open UART port, Please close if the port is open by other application %d.\n", GetLastError());
       return (2);
   }

// Fill in DCB: 57,600 bps, 8 data bits, no parity, and 1 stop bit.

   dcb.BaudRate = CBR_57600; // set the baud rate
   dcb.ByteSize = 8; // data size, xmit, and rcv
   dcb.Parity = NOPARITY; // no parity bit
   dcb.StopBits = ONESTOPBIT; // one stop bit

   fSuccess = SetCommState(hCom, &dcb);

   if (!fSuccess)
   {
     // Handle the error.
       printf ("Cann't set the UART port Settings %d.\n", GetLastError());
        return (3);
   }

   printf ("Serial port %s successfully reconfigured.\n", pcCommPort);
   printf("\n\nPlease make sure smart fusion dev kit is running \n");
   printf("target loader before launching host loader\n\n");
   printf("Handshaking with Smartfusion F2 uart \n");


   SerialPutc(hCom,'h');
   ret[0] = SerialGetc(hCom);
   if (ret[0] == 'a')
   {
      SerialPutc(hCom,'n');
   }
   else
   {
      printf("Handshake fail\n");
      printf("Please restart the target loader and \n");
	  printf("restart the hostloader with correct perameters \n");
	  return 0;

   }

   ret[0] = SerialGetc(hCom);

   if (ret[0] == 'd')
   {
	   SerialPutc(hCom,'s');
   }
   else
   {
       printf("Handshake fail\n");
       printf("Please restart the target loader and \n");
       printf("restart the hostloader with correct perameters \n");
       return 0;

   }

   ret[0] = SerialGetc(hCom);

   if (ret[0] == 'h')
   {
      SerialPutc(hCom,'a');
   }
   else
   {
	   printf("Handshake fail\n");
       printf("Please restart the target loader and \n");
       printf("restart the hostloader with correct perameters \n");
       return 0;

   }

   ret[0] = SerialGetc(hCom);

   if (ret[0] == 'k')
   {
	   SerialPutc(hCom,'e');
   }
   else
   {
	   printf("Handshake fail\n");
       printf("Please restart the target loader and \n");
       printf("restart the hostloader with correct perameters \n");
       return 0;

   }

   printf("HAND SHAKE is fine \n");


/* verifying the address validity and sending the flash and
   address detatils to the Smartfusion */
   if(!strcmp("spi",argv[1]))
   {
	   address = atohex(argv[2]);
	   printf("Address =0x%x\n",address);

	   if( (address <0) || (address > 0x7FFFFF) )
       {

         	printf("Usage for spiflash: ASF2memoryloader.exe spi address filename comportnumber\n");
    	  	printf("Address reange is from 0 to 0x7FFFFF\n\n");

            return 0;
       }
	   SerialPutc(hCom,'s');
	}
	else if(!strcmp("emc",argv[1]))
	{
		address = atohex(argv[2]);
		printf("Address =0x%x\n",address);

		if( (address <0x74000000) || (address > 0x74FFFFFF) )
        {

    	  	printf("Usage for emcflash: ASF2memoryloader.exe emc address filename comportnumber\n");
    	    printf("Address reange is from 0x74000000 to 0x0x74FFFFFF\n\n");

    	    return 0;
        }
        SerialPutc(hCom,'e');
	}
/*********************************************************************
************* added for I2C EEPROM Loader  ***************************
********************************************************************** */
    else if(!strcmp("i2c",argv[1]))
    {
	   address = atohex(argv[2]);
	   printf("Address =0x%x\n",address);

	   if( (address <0) || (address > 0xFFFF) )
       {

         	printf("Usage for I2C EEPROM: ASF2memoryloader.exe i2c address filename comportnumber\n");
    	  	printf("Address reange is from 0 to 0xFFFF\n\n");

            return 0;
       }
	   SerialPutc(hCom,'i');
   }
   else
   {

      	printf("Usage for spiflash: ASF2memoryloader.exe spi address filename comportnumber\n");
	  	printf("Address reange is from 0 to 0x7FFFFF\n\n");

	  	printf("Usage for emcflash: ASF2memoryloader.exe emc address filename comportnumber\n");
	    printf("Address reange is from 0x74000000 to 0x0x74FFFFFF\n\n");


	// i2c eeprom
 	    printf("Usage for I2C EEPROM: ASF2memoryloader.exe i2c address filename comportnumber\n");
	    printf("Address reange is from 0x0 to 0xFFFF\n\n");

	    return 0;
    }
    strcpy(filename, argv[3]);
    fp = fopen(filename,"rb");

    // obtain file size:
    fseek (fp , 0 , SEEK_END);
    size = ftell (fp);
    rewind (fp);

    printf("size = %d\n", size);

    /* Send the sixe of the file to Smartfusion */
    bWriteRC = WriteFile(hCom, (char *)&size, 4, &iBytesWritten,NULL);

    printf("\n.....Erasing the Flash .....\n");

    /* Read back adn compare the size sent is correct? */
    size =0;
    bReadRC = ReadFile(hCom, (char *)&size, 4,&iBytesRead,NULL);

    printf("read back size =%d\n", size);

    /* send the address to target */
    bWriteRC = WriteFile(hCom, (char *)&address, 4, &iBytesWritten,NULL);

    /* Read back adn compare the address sent is correct? */
    address = 0;
    bReadRC = ReadFile(hCom, (char *)&address, 4,&iBytesRead,NULL);
    printf("Writing address =0x%x\n", address);
    printf("Wrting Data\n");

    /* Sending the file to Smartfusion
       Splitting the file into 1KB blocks and sending the blocks with
       proper acknowledgement */

    while(size > 0 )
    {
       if (size > 1024)
       {
    	  length  = 1024;
       }
       else
       {
		   length = size;
	   }

       printf("----");

       result = fread (buffer,1,length,fp);
       if (result != length)
       {
		   printf("Can't open Input file: Please check the path of the file: Reading error\n");
		   exit (3);
	   }

       bWriteRC = WriteFile(hCom, buffer, length, &iBytesWritten,NULL);

       bReadRC = ReadFile(hCom, ret, 1,&iBytesRead,NULL);

       size -= length;
     }
     bReadRC = ReadFile(hCom, ret, 1,&iBytesRead,NULL);

     printf("Bytes written =%d", ftell(fp));


if(ret[0] == 'y')
{
    printf("\n.....Flash Programming is Successful.....\n");
    if(!strcmp("emc",argv[1]))
    {
		printf("\n Please check the content of EMC Flash in Memory Moniter for validity ...\n");
	}
}
else
{
    printf("\n.....Flash Programming Failed.....\n");
}

return (0);


}
