// Copyright (c) 2009  Future Technology Devices International Ltd.
//
// Module Name
//
//     FT2232HSPIC++NETTestApp.cpp
//
// Abstract:
//
//    C++ console program, to test the FTCSPI.DLL. The FTCSPI.DLL is used to control the FT2232H dual hi-speed device
//    and the FT4232H quad hi-speed device to simulate the Serial Peripheral Interface(SPI) synchronous serial protocol
//    to communicate with SPI devices connected to FT2232H dual hi-speed devices and FT4232H quad hi-speed devices.
//
// Revision History:
//
//   26/08/08       Rev 1
//   21/08/09		Rev 2
//
// FT2232HSPIC++NETTestApp.cpp : Defines the entry point for the console application.
//

#include "stdio.h"
#include "conio.h"
#include <time.h>
#include "windows.h"
#include <string.h>

#include "stdafx.h"

#include <windows.h>

#include "FTCSPI.h"

#define MAX_SPI_93LC56B_CHIP_SIZE_IN_WORDS 128

// To communicate with the 93LC56(2048 word) EEPROM, the maximum frequency the clock can be set is 1MHz
#define MAX_FREQ_93LC56B_CLOCK_DIVISOR 1 // defualt is 29 equivalent to 1MHz

const BYTE SPI_EWEN_CMD = '\x9F'; // set up write enable command
const BYTE SPI_EWDS_CMD = '\x87'; // set up write disable command
const BYTE SPI_ERAL_CMD = '\x97'; // set up erase all command

#define NUM_93LC56B_CMD_CONTOL_BITS 8*255  //Number of bits required for 93C56 Control operations
#define NUM_93LC56B_CMD_CONTOL_BYTES 255

#define NUM_93LC56B_CMD_DATA_BITS 8*4 // Number of bits required for 93C56 Data operations
#define NUM_93LC56B_CMD_DATA_BYTES 4

#define MAX_READ_DATA_WORDS_BUFFER_SIZE 65536  // Maximum Number of Data words

typedef WORD ReadDataWordBuffer[MAX_READ_DATA_WORDS_BUFFER_SIZE];
typedef ReadDataWordBuffer *PReadDataWordBuffer;

void sendSPIData(FTC_HANDLE ftHandle, WriteDataByteBuffer *buff, unsigned int length)
{
    WriteDataByteBuffer WriteDataBuffer;
	WriteControlByteBuffer WriteControlBuffer;
	FTC_INIT_CONDITION WriteStartCondition;
    FTC_WAIT_DATA_WRITE WaitDataWriteComplete;
    FTH_HIGHER_OUTPUT_PINS HighPinsWriteActiveStates;
    WriteDataByteBuffer tempBuff;
	FTC_STATUS Status = FTC_SUCCESS;
	int i =0;


//	WriteDataByteBuffer *tempBuff = buff;
tempBuff[0] = i;
tempBuff[1] = '\FF';
            WriteStartCondition.bClockPinState = false;
            WriteStartCondition.bDataOutPinState = false;
            WriteStartCondition.bChipSelectPinState = false; // Makes Chip Select active high
            WriteStartCondition.dwChipSelectPin = ADBUS3ChipSelect; // Assigns ADBUS3 as Chip Select

            WaitDataWriteComplete.bWaitDataWriteComplete = false;

            // Set the 8 general purpose higher input/output pins
            HighPinsWriteActiveStates.bPin1ActiveState = false;
            HighPinsWriteActiveStates.bPin1State = false;
            HighPinsWriteActiveStates.bPin2ActiveState = false;
            HighPinsWriteActiveStates.bPin2State = false;
            HighPinsWriteActiveStates.bPin3ActiveState = false;
            HighPinsWriteActiveStates.bPin3State = false;
            HighPinsWriteActiveStates.bPin4ActiveState = false;
            HighPinsWriteActiveStates.bPin4State = false;
            HighPinsWriteActiveStates.bPin5ActiveState = false;
            HighPinsWriteActiveStates.bPin5State = false;
            HighPinsWriteActiveStates.bPin6ActiveState = false;
            HighPinsWriteActiveStates.bPin6State = false;
            HighPinsWriteActiveStates.bPin7ActiveState = false;
            HighPinsWriteActiveStates.bPin7State = false;
            HighPinsWriteActiveStates.bPin8ActiveState = false;
            HighPinsWriteActiveStates.bPin8State = false;


	while(length > 0)
	{
#if 1
	        	WriteControlBuffer[0] = SPI_ERAL_CMD;  // This is the opcode to "Erase All" for the 93C56
		      WriteControlBuffer[1] = '\FF';


              Status = SPI_WriteHiSpeedDevice(ftHandle, &WriteStartCondition, true, false,
                                              NUM_93LC56B_CMD_CONTOL_BITS, &WriteControlBuffer, NUM_93LC56B_CMD_CONTOL_BYTES,
                                              false, 0, &WriteDataBuffer, 0, &WaitDataWriteComplete, &HighPinsWriteActiveStates);
Sleep(700);


              WriteDataBuffer[0] = SPI_ERAL_CMD;  // This is the opcode to "Erase All" for the 93C56
		      WriteDataBuffer[1] = '\FF';
#endif
		             Status = SPI_WriteHiSpeedDevice(ftHandle, &WriteStartCondition, true, false,
                                              0, &WriteControlBuffer, 0,
                                              true, NUM_93LC56B_CMD_DATA_BITS, (PWriteDataByteBuffer)&tempBuff, NUM_93LC56B_CMD_DATA_BYTES,
                                              &WaitDataWriteComplete, &HighPinsWriteActiveStates);
         length--;i++;
		 tempBuff[0] = i;
	}

}


int _tmain(int argc, _TCHAR* argv[])
{
  FTC_STATUS Status = FTC_SUCCESS;
  DWORD dwNumHiSpeedDevices = 0;
  char szDeviceName[100];
  char szChannel[5];
  DWORD dwLocationID = 0;
  DWORD dwHiSpeedDeviceType = 0;
  DWORD dwHiSpeedDeviceIndex = 0;
  FTC_HANDLE ftHandle = 0;
  char szDeviceDetails[150];
  BYTE timerValue = 0;
  DWORD dwClockFrequencyHz = 0;
  BOOL bPerformCommandSequence = false;
  FTC_CHIP_SELECT_PINS ChipSelectsDisableStates;
  FTH_INPUT_OUTPUT_PINS HighInputOutputPins;
  FTH_LOW_HIGH_PINS HighPinsInputData;
  FTC_INIT_CONDITION WriteStartCondition;
  WriteControlByteBuffer WriteControlBuffer;
  WriteDataByteBuffer WriteDataBuffer;
  DWORD dwNumDataBytesToWrite = 0;
  FTC_WAIT_DATA_WRITE WaitDataWriteComplete;
  FTH_HIGHER_OUTPUT_PINS HighPinsWriteActiveStates;
  FTC_CLOSE_FINAL_STATE_PINS CloseFinalStatePinsData;
  DWORD dwDataWordInitValue = 0;
  DWORD dwDataWordValue = 0;
  DWORD dwWriteDataWordAddress = 0;
  DWORD dwControlLocAddress1 = 0;
  DWORD dwControlLocAddress2 = 0;
  FTC_INIT_CONDITION ReadStartCondition;
  DWORD dwReadDataWordAddress = 0;
  DWORD dwReadWordValue = 0;
  ReadDataWordBuffer ReadWordData;
  DWORD dwNumDataBytesReturned = 0;
  DWORD dwDataWordWritten = 0;
  DWORD dwCharCntr = 0;
  ReadDataByteBuffer ReadDataBuffer;
  DWORD dwReadDataIndex = 0;
  ReadCmdSequenceDataByteBuffer ReadCmdSequenceDataBuffer;
  int MsgBoxKeyPressed = 0;
  DWORD dwLoopCntr = 0;

  WriteControlByteBuffer data;

  char szDllVersion[10];
  char szTitleErrorMessage[100];
  char szStatusErrorMessage[100];
  char szErrorMessage[200];
  char szMismatchMessage[100];

  long size,index,Uart_receive_size;
  FILE *fp, *fp_read;
  unsigned char buffer[5129];
  char pcCommPort[5]="COM3";
  HANDLE hCom;
  	BOOL fSuccess;
	DCB dcb;
    static DWORD iBytesRead = -1;
	char read_buffer[5129];




  for (dwCharCntr = 0; (dwCharCntr < 100); dwCharCntr++)
    szMismatchMessage[dwCharCntr] = '\0';

  Status = SPI_GetDllVersion(szDllVersion, 10);   // Get version of DLL file
  MessageBox(NULL, szDllVersion, "FTCSPI DLL Version", MB_OK);

  Status = SPI_GetNumHiSpeedDevices(&dwNumHiSpeedDevices);

  if ((Status == FTC_SUCCESS) && (dwNumHiSpeedDevices > 0))
  {
    do
    {

	// This gets the name and location identifier for any FTDI HiSpeed device connected to the host.

      Status = SPI_GetHiSpeedDeviceNameLocIDChannel(dwHiSpeedDeviceIndex, szDeviceName, 100, &dwLocationID, szChannel, 5, &dwHiSpeedDeviceType);

      dwHiSpeedDeviceIndex = dwHiSpeedDeviceIndex + 1; // Increment to look for other HiSpeed device connected to host.
    }
    while ((Status == FTC_SUCCESS) && (dwHiSpeedDeviceIndex < dwNumHiSpeedDevices) && (strcmp(szChannel, "A") != 0));

    if (Status == FTC_SUCCESS)
    {
      if (strcmp(szChannel, "A") != 0)
        Status = FTC_DEVICE_IN_USE;
    }

    if (Status == FTC_SUCCESS) {

	// Opens a handle to the Hi Speed device and initializes the device to default state.

      Status = SPI_OpenHiSpeedDevice(szDeviceName, dwLocationID, szChannel, &ftHandle);
      if (Status == FTC_SUCCESS) {

	// Returns the device type, either FT2232H or FT4232H.

        Status = SPI_GetHiSpeedDeviceType(ftHandle, &dwHiSpeedDeviceType);
        if (Status == FTC_SUCCESS) {

          strcpy_s(szDeviceDetails, "Type = ");

          if (dwHiSpeedDeviceType == FT4232H_DEVICE_TYPE)  // Is the device a FT4232H ?
            strcat_s(szDeviceDetails, "FT4232H");

          else if (dwHiSpeedDeviceType == FT2232H_DEVICE_TYPE) // Is the device a FT222H ?
		  {
            strcat_s(szDeviceDetails, "FT2232H");
			printf("FT2232H Device \n");
				//getchar();
		  }

          strcat_s(szDeviceDetails, ", Name = ");
          strcat_s(szDeviceDetails, szDeviceName);

          MessageBox(NULL, szDeviceDetails, "Hi Speed Device", MB_OK);
        }
      }
    }
  }

  if ((Status == FTC_SUCCESS) && (ftHandle != 0))
  {

  // Resets the device, initialize the MPSSE, clear buffers, set clock frequency for data in and data out.
    Status = SPI_InitDevice(ftHandle, MAX_FREQ_93LC56B_CLOCK_DIVISOR);

    if (Status == FTC_SUCCESS) {
      if ((Status = SPI_GetDeviceLatencyTimer(ftHandle, &timerValue)) == FTC_SUCCESS) {
        if ((Status = SPI_SetDeviceLatencyTimer(ftHandle, 50)) == FTC_SUCCESS) {
          Status = SPI_GetDeviceLatencyTimer(ftHandle, &timerValue);

          Status = SPI_SetDeviceLatencyTimer(ftHandle, 16);

          Status = SPI_GetDeviceLatencyTimer(ftHandle, &timerValue);
        }
      }
    }

    if (Status == FTC_SUCCESS)
    {
      if ((Status = SPI_GetHiSpeedDeviceClock(0, &dwClockFrequencyHz)) == FTC_SUCCESS)
      {
        if ((Status = SPI_TurnOnDivideByFiveClockingHiSpeedDevice(ftHandle)) == FTC_SUCCESS)
        {
          Status = SPI_GetHiSpeedDeviceClock(0, &dwClockFrequencyHz);

	// Sets frequency  of SCLK by applying clock divisor.
          if ((Status = SPI_SetClock(ftHandle, MAX_FREQ_93LC56B_CLOCK_DIVISOR, &dwClockFrequencyHz)) == FTC_SUCCESS)
          {
	// Turning off divide by five clocking allows SCLK to be set up to 30 Mhz for FT2232H and FT4232H.
            if ((Status = SPI_TurnOffDivideByFiveClockingHiSpeedDevice(ftHandle)) == FTC_SUCCESS)
              Status = SPI_SetClock(ftHandle, MAX_FREQ_93LC56B_CLOCK_DIVISOR, &dwClockFrequencyHz);
          }
        }
      }
    }

    if (Status == FTC_SUCCESS)
    {
      Status = SPI_SetLoopback(ftHandle, false);

      if (Status == FTC_SUCCESS)
      {
        bPerformCommandSequence = false;

        if (bPerformCommandSequence == true)
        {
            if (Status == FTC_SUCCESS)
              Status = SPI_ClearDeviceCmdSequence(ftHandle);
        }

        if (Status == FTC_SUCCESS)
        {
          // Must set the chip select disable states for all the SPI devices connected to a FT2232H hi-speed dual
          // device or FT4332H hi-speed quad device
#if 0
			ChipSelectsDisableStates.bADBUS3ChipSelectPinState = false;  // default is false This makes CS active high
          ChipSelectsDisableStates.bADBUS4GPIOL1PinState = false;
          ChipSelectsDisableStates.bADBUS5GPIOL2PinState = false;
          ChipSelectsDisableStates.bADBUS6GPIOL3PinState = false;
          ChipSelectsDisableStates.bADBUS7GPIOL4PinState = false;
#endif
          ChipSelectsDisableStates.bADBUS3ChipSelectPinState = true;  // default is false This makes CS active high
          ChipSelectsDisableStates.bADBUS4GPIOL1PinState = false;
          ChipSelectsDisableStates.bADBUS5GPIOL2PinState = false;
          ChipSelectsDisableStates.bADBUS6GPIOL3PinState = false;
          ChipSelectsDisableStates.bADBUS7GPIOL4PinState = false;


		  // Configure the logic states of the 8 GPIO pins.
          HighInputOutputPins.bPin1InputOutputState = true;
          HighInputOutputPins.bPin1LowHighState = false;
          HighInputOutputPins.bPin2InputOutputState = true;
          HighInputOutputPins.bPin2LowHighState = false;
          HighInputOutputPins.bPin3InputOutputState = true;
          HighInputOutputPins.bPin3LowHighState = false;
          HighInputOutputPins.bPin4InputOutputState = true;
          HighInputOutputPins.bPin4LowHighState = false;

          HighInputOutputPins.bPin5InputOutputState = true;
          HighInputOutputPins.bPin5LowHighState = false;
          HighInputOutputPins.bPin6InputOutputState = true;
          HighInputOutputPins.bPin6LowHighState = false;
          HighInputOutputPins.bPin7InputOutputState = true;
          HighInputOutputPins.bPin7LowHighState = false;
          HighInputOutputPins.bPin8InputOutputState = true;
          HighInputOutputPins.bPin8LowHighState = false;

          Status = SPI_SetHiSpeedDeviceGPIOs(ftHandle, &ChipSelectsDisableStates, &HighInputOutputPins); //NULL

          if (Status == FTC_SUCCESS)
          {
            Sleep(200);

            Status = SPI_GetHiSpeedDeviceGPIOs(ftHandle, &HighPinsInputData); //NULL);

            Sleep(200);
          }
        }

        do
        {
          if (Status == FTC_SUCCESS)
          {

            WriteStartCondition.bClockPinState = false;
            WriteStartCondition.bDataOutPinState = false;
//            WriteStartCondition.bChipSelectPinState = false; // Makes Chip Select active high
            WriteStartCondition.bChipSelectPinState = true; // Makes Chip Select active low
            WriteStartCondition.dwChipSelectPin = ADBUS3ChipSelect; // Assigns ADBUS3 as Chip Select

            WaitDataWriteComplete.bWaitDataWriteComplete = false;

            // Set the 8 general purpose higher input/output pins
            HighPinsWriteActiveStates.bPin1ActiveState = false;
            HighPinsWriteActiveStates.bPin1State = false;
            HighPinsWriteActiveStates.bPin2ActiveState = false;
            HighPinsWriteActiveStates.bPin2State = false;
            HighPinsWriteActiveStates.bPin3ActiveState = false;
            HighPinsWriteActiveStates.bPin3State = false;
            HighPinsWriteActiveStates.bPin4ActiveState = false;
            HighPinsWriteActiveStates.bPin4State = false;
            HighPinsWriteActiveStates.bPin5ActiveState = false;
            HighPinsWriteActiveStates.bPin5State = false;
            HighPinsWriteActiveStates.bPin6ActiveState = false;
            HighPinsWriteActiveStates.bPin6State = false;
            HighPinsWriteActiveStates.bPin7ActiveState = false;
            HighPinsWriteActiveStates.bPin7State = false;
            HighPinsWriteActiveStates.bPin8ActiveState = false;
            HighPinsWriteActiveStates.bPin8State = false;

          }

for(char ii =0; ii<0x7F; ii++)
{
#if 0
	for(int i =0; i<= 256; i++)
	{
		data[i] = i;

	}
#endif
#if 0
			data[0] = ii;
			data[1] = ii + 1;
			data[2] = ii + 2;
			data[3] = ii + 3;

#endif

//	temp_buffer = buffer[0];


			// Setup Erase Opcode
//              WriteControlBuffer[0] = ii;  // This is the opcode to "Erase All" for the 93C56
//		      WriteControlBuffer[1] = '\FF';

              /* Erase the entire 93C56 EEPROM. This is a control command. No data is sent. The WriteDataBuffer boolean is set to false.
              WriteStartCondition true,false indicates data is clocked MSB first, with SPI Mode 0 selected. */

              Status = SPI_WriteHiSpeedDevice(ftHandle, &WriteStartCondition, true, false,
                                              NUM_93LC56B_CMD_CONTOL_BITS, &data, NUM_93LC56B_CMD_CONTOL_BYTES,
                                              false, 0, &WriteDataBuffer, 0, &WaitDataWriteComplete, &HighPinsWriteActiveStates);

#if 0
			  //ForReadTest
              ReadStartCondition.bClockPinState = false;
              ReadStartCondition.bDataOutPinState = false;
              ReadStartCondition.bChipSelectPinState = true; //Chip Select is active low.
              ReadStartCondition.dwChipSelectPin = ADBUS3ChipSelect;
while(1)
{
                  Status = SPI_ReadHiSpeedDevice(ftHandle, &ReadStartCondition, true, false, 0,
                                                 &WriteControlBuffer, NUM_93LC56B_CMD_CONTOL_BYTES, true, false, NUM_93LC56B_CMD_DATA_BITS,
                                                 &ReadDataBuffer, &dwNumDataBytesReturned, &HighPinsWriteActiveStates);

                  if (Status == FTC_SUCCESS)
                  {

					 dwReadWordValue = ((ReadDataBuffer[1] * 256) | ReadDataBuffer[0]);
					// Returns value of address and data to console window.

                    printf("For Bytes read = %d , Data Read = %d, %d , %d, %d\n ", dwNumDataBytesReturned, ReadDataBuffer[0], ReadDataBuffer[1], ReadDataBuffer[2],ReadDataBuffer[3]);

					getchar();
                  }
}
#endif

/* File reading operion and data collection from file */
	printf("Opening file\n");
	fp = fopen("test.txt","rb");
	printf("file Opened %d\n", fp);

    // obtain file size:
    fseek (fp , 0 , SEEK_END);
    size = ftell (fp);
    rewind (fp);
    printf("size of the file = %d\n", size);
	fread (buffer,1,size,fp);
	Uart_receive_size = size;
	index = 0;
	int bytesToSend= 252;
	while(size > 0 )
    {
       if (size >= bytesToSend)
       {

	      for(int i = 0; i<bytesToSend; i++)
		  {
		    data[i] = buffer[i+index];
		  }
		   Status = SPI_WriteHiSpeedDevice(ftHandle, &WriteStartCondition, true, false,
                                              bytesToSend*8, &data, bytesToSend,
                                              false, 0, &WriteDataBuffer, 0, &WaitDataWriteComplete, &HighPinsWriteActiveStates);

		   size  = size-bytesToSend;
		  index = index + bytesToSend;
	   }
       else
       {
	      for(int i = 0; i<size; i++)
		  {
		    data[i] = buffer[i+index];
		  }
		   Status = SPI_WriteHiSpeedDevice(ftHandle, &WriteStartCondition, true, false,
                                              size*8, &data, size,
                                              false, 0, &WriteDataBuffer, 0, &WaitDataWriteComplete, &HighPinsWriteActiveStates);

		   size = size-size;
	   }
	}


	printf("Initialising the UART to read the data from eSRAM\n");

	//Refer the flash loader tool for UART Fucntion
	//Rx for (length);
	//Open new file
	//fill the file with above data
	//close file();




   //strcat(pcCommPort,COM_NUMBER);
   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);
	ReadFile(hCom, (char *)&read_buffer, Uart_receive_size,&iBytesRead,NULL);
    printf ("reading data from eSRAM is DONE\n");

	fp_read = fopen("read_file.txt","w+");
    printf ("Opening file is done %d\n",fp_read);

//	fwrite(read_buffer,2048,4096,fp_read);
	fwrite(read_buffer,1,Uart_receive_size,fp_read);
    printf ("writing to file is done\n");

	fclose(fp_read);
	printf("Done\n");
	printf("Enter character\n");	
	getchar();



			  //          Sleep(700);
}

          {
            WaitDataWriteComplete.bWaitDataWriteComplete = true;
            WaitDataWriteComplete.dwWaitDataWritePin = ADBUS2DataIn;
            WaitDataWriteComplete.bDataWriteCompleteState = true;
            WaitDataWriteComplete.dwDataWriteTimeoutmSecs = 5000;  //def is 5000

				int i, j = 1, bytes;

	for( i =1; i<= 256; i++)
	{
		data[i-1] = i;

	}

    for(;;)
	{
		bytes = 0;
//		ftStatus = FT_Write(ftHandle, &data, (DWORD)sizeof(data), &bytes);
//sendSPIData(ftHandle, &data, 255);
//	    if (ftStatus != FTC_SUCCESS)
//	    {
//		    printf("Can't Write\n");
//	    }
		//if ( bytes < 1024 )
		{
			printf("Bytes Writen = %d\n",bytes);
		}

		//		Sleep(10);
	}

//while(1)
//{
//	printf("writing\n");
            dwWriteDataWordAddress = 0;

            do
            {
	         printf("writing\n");
				// Set up Write Enable Opcodes
			 WriteControlBuffer[0] = 0xAA;//SPI_EWEN_CMD;
             WriteControlBuffer[1] = 0xFA;

			  /* Enable writing. Since this is a control command, the boolean for &WriteDataBuffer is set to false – no data is sent, just the mode
              command at the start of the data stream. WriteStartCondition true,false indicates data is clocked MSB first with SPI Mode 0 selected. */

              Status = SPI_WriteHiSpeedDevice(ftHandle, &WriteStartCondition, true, false,
                                          NUM_93LC56B_CMD_CONTOL_BITS, &WriteControlBuffer, NUM_93LC56B_CMD_CONTOL_BYTES,
                                          false, 0, &WriteDataBuffer, 0, &WaitDataWriteComplete, &HighPinsWriteActiveStates);

              // Set up write command opcode and address
              dwControlLocAddress1 = 160; //'\xA0';
              dwControlLocAddress1 = (dwControlLocAddress1 | ((dwWriteDataWordAddress / 8) & '\x0F'));

              // Shift left 5 bits ie make bottom 3 bits the 3 MSB's
              dwControlLocAddress2 = ((dwWriteDataWordAddress & '\x07') * 32);

              WriteControlBuffer[0] = (dwControlLocAddress1 & '\xFF');
              WriteControlBuffer[1] = (dwControlLocAddress2 & '\xFF');

              if (dwDataWordInitValue == 0)
                dwDataWordValue = dwWriteDataWordAddress;
              else
                dwDataWordValue = dwDataWordInitValue;

              // write data
//              WriteDataBuffer[0] = (dwDataWordValue & '\xFF');
//              WriteDataBuffer[1] = ((dwDataWordValue / 256) & '\xFF');

              WriteDataBuffer[0] = 0xAB;
              WriteDataBuffer[1] = 0xCD;

			  /* The SPI write hi speed command includes both a command section and a data section.The Write Data boolean is set true.
              WriteStartCondition true,false indicates data is clocked MSB first with SPI Mode 0 selected. */

              Status = SPI_WriteHiSpeedDevice(ftHandle, &WriteStartCondition, true, false,
                                              0, &WriteControlBuffer, 0,
                                              true, NUM_93LC56B_CMD_DATA_BITS, &WriteDataBuffer, NUM_93LC56B_CMD_DATA_BYTES,
                                              &WaitDataWriteComplete, &HighPinsWriteActiveStates);

                // Disable Writing until next cycle. This is recommended to ensure data integrity after a write.

				WriteControlBuffer[0] = SPI_EWDS_CMD;

                /* Disable writing. This is a control command. No data is sent. WriteStartCondition true,false indicates data is clocked
			    MSB first with SPI Mode 0 selected. */

                Status = SPI_WriteHiSpeedDevice(ftHandle, &WriteStartCondition, true, false,
                                                NUM_93LC56B_CMD_CONTOL_BITS, &WriteControlBuffer, NUM_93LC56B_CMD_CONTOL_BYTES,
                                                false, 0, &WriteDataBuffer, 0, &WaitDataWriteComplete, &HighPinsWriteActiveStates);



				dwWriteDataWordAddress++;  // Increment data address.

            }

			//Write data until eeprom size is met. (128 words for 93C56)

            while ((dwWriteDataWordAddress < MAX_SPI_93LC56B_CHIP_SIZE_IN_WORDS) && (Status == FTC_SUCCESS));
//			}//while(1)
			Sleep(200);

            if (Status == FTC_SUCCESS)
            {
              ReadStartCondition.bClockPinState = false;
              ReadStartCondition.bDataOutPinState = false;
              ReadStartCondition.bChipSelectPinState = false; //Chip Select is active high.
              ReadStartCondition.dwChipSelectPin = ADBUS3ChipSelect;

              dwReadDataWordAddress = 0;

              do
              {
                // set up read command and address
                dwControlLocAddress1 = 192; //'\xC0';  Read Opcode for 93C56
                dwControlLocAddress1 = (dwControlLocAddress1 | ((dwReadDataWordAddress / 8) & '\x0F'));

                // shift left 5 bits ie make bottom 3 bits the 3 MSB's
                dwControlLocAddress2 = ((dwReadDataWordAddress & '\x07') * 32);

                WriteControlBuffer[0] = (dwControlLocAddress1 & '\xFF');
                WriteControlBuffer[1] = (dwControlLocAddress2 & '\xFF');

                if (bPerformCommandSequence == false)
                {
				/* For SPI Read, read command and memory address are applied to data stream. WriteControlBuffer contains
                dwReadDataWordAddress, which is shifted to format the data stream. ReadStartCondition true,false indicates data is clocked MSB
                first with SPI Mode 0 selected */

                  Status = SPI_ReadHiSpeedDevice(ftHandle, &ReadStartCondition, true, false, NUM_93LC56B_CMD_CONTOL_BITS,
                                                 &WriteControlBuffer, NUM_93LC56B_CMD_CONTOL_BYTES, true, false, NUM_93LC56B_CMD_DATA_BITS,
                                                 &ReadDataBuffer, &dwNumDataBytesReturned, &HighPinsWriteActiveStates);

                  if (Status == FTC_SUCCESS)
                  {
                    dwReadWordValue = ((ReadDataBuffer[1] * 256) | ReadDataBuffer[0]);

                    ReadWordData[dwReadDataWordAddress] = dwReadWordValue;

					// Returns value of address and data to console window.

                    printf("For Address = %d , Data Read = %d\n ", dwReadDataWordAddress, dwReadWordValue);
                  }
                }
                else

				// AddHiSpeedread allows multiple read operations to be staged.
				// The remainder of the code is for error detection and reporting.

                  Status = SPI_AddHiSpeedDeviceReadCmd(ftHandle, &ReadStartCondition, true, false, NUM_93LC56B_CMD_CONTOL_BITS,
                                                       &WriteControlBuffer, NUM_93LC56B_CMD_CONTOL_BYTES, true, false, NUM_93LC56B_CMD_DATA_BITS,
                                                       &HighPinsWriteActiveStates);

                dwReadDataWordAddress++;
              }
              while ((dwReadDataWordAddress < MAX_SPI_93LC56B_CHIP_SIZE_IN_WORDS) && (Status == FTC_SUCCESS));

              MsgBoxKeyPressed = IDOK;

              if (Status == FTC_SUCCESS)
              {
                if (bPerformCommandSequence == true)
                {
                  Status = SPI_ExecuteDeviceCmdSequence(ftHandle, &ReadCmdSequenceDataBuffer, &dwNumDataBytesReturned);

                  if (Status == FTC_SUCCESS)
                  {
                    if (dwNumDataBytesReturned > 0)
                    {
                      dwReadDataWordAddress = 0;

                      dwReadDataIndex = 0;

                      do
                      {
						//Scrolls through the read data buffer

                        dwReadWordValue = ((ReadCmdSequenceDataBuffer[(dwReadDataIndex + 1)] * 256) | ReadCmdSequenceDataBuffer[dwReadDataIndex]);

                        ReadWordData[dwReadDataWordAddress] = dwReadWordValue;

                        dwReadDataIndex = (dwReadDataIndex + 2);

						//Increment address counter.

                        dwReadDataWordAddress++;
                      }
                      while (dwReadDataIndex < dwNumDataBytesReturned);
                    }
                    else
					//Useful for debugging code. (when configuring opcodes for different size EEPROMs)
                      MsgBoxKeyPressed = MessageBox(NULL, "No data returned.", "SPI Execute Command Sequence", MB_OK | MB_OKCANCEL);
                  }
                }

                if ((Status == FTC_SUCCESS) && (MsgBoxKeyPressed == IDOK))
                {
                  for (dwReadDataIndex = 0; ((dwReadDataIndex < MAX_SPI_93LC56B_CHIP_SIZE_IN_WORDS) && (MsgBoxKeyPressed == IDOK)); dwReadDataIndex++)
                  {
                    if (dwDataWordInitValue != 0)
                      dwDataWordWritten = dwDataWordInitValue;
                    else
                      dwDataWordWritten = (dwReadDataIndex & '\xFF');

                    if (((ReadWordData[dwReadDataIndex] != dwDataWordWritten) && (dwDataWordValue != 0)) ||
                        ((ReadWordData[dwReadDataIndex] != dwDataWordWritten) && (dwDataWordValue == 0)))
                    {
                      for (dwCharCntr = 0; (dwCharCntr < 100); dwCharCntr++)
                        szMismatchMessage[dwCharCntr] = '\0';

					// If read data does not equal address counter value, an error has occured.

                      sprintf(szMismatchMessage, "SPI 93LC56B Read/Write mismatch, Loop = %i, Address = %i, Write Value = %X, Read Value = %X", dwLoopCntr, dwReadDataIndex, dwDataWordWritten, ReadWordData[dwReadDataIndex]);
                      MsgBoxKeyPressed = MessageBox(NULL, szMismatchMessage, "SPI Read Error Message", MB_OK | MB_OKCANCEL);
                    }
                  }
                }
              }
            }
          }

          dwLoopCntr++;
        }
		/* Number of iterations - ie: one pass equals 128 read/write cycles. Multiple iterations are
		useful for showing SPI signals on scope.  This example shows 10 iterations. */

        while ((dwLoopCntr < 10) && (Status == FTC_SUCCESS) && (MsgBoxKeyPressed == IDOK));
      }
    }
  }

  if (ftHandle != 0)
  {
    SPI_Close(ftHandle);
    ftHandle = 0;
  }

  if ((Status != FTC_SUCCESS) || (dwNumHiSpeedDevices == 0) || (strlen(szMismatchMessage) > 0))
  {
    if (Status != FTC_SUCCESS)

	// Detect and report miscellaneous errors.
    {
      sprintf_s(szErrorMessage, "Status Code(%u) - ", Status);

      Status = SPI_GetErrorCodeString("EN", Status, szStatusErrorMessage, 100);

      strcat_s(szErrorMessage, szStatusErrorMessage);

      MessageBox(NULL, szErrorMessage, "FTCSPI DLL Error Status Message", MB_OK);
    } else {
      if (dwNumHiSpeedDevices == 0)
        strcpy_s(szErrorMessage, "There are no devices connected.");
      else
        strcpy_s(szErrorMessage, szMismatchMessage);

      MessageBox(NULL, szErrorMessage, "FTCSPI DLL Error Message", MB_OK);
    }
  }
  else

  // No errors detected. You Pass !
  {
    Status = SPI_GetDllVersion(szDllVersion, 10);


    strcpy_s(szErrorMessage, "You have passed the EEPROM test");

    MessageBox(NULL, szErrorMessage, "FTCSPI DLL Message", MB_OK);
  }

	return 0;
}

