// SPI_Sample.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "SPI_Sample.h"

#include "../../Dll/HidDeviceSDKApi.h"

#ifdef _WIN64
#pragma comment(lib, "../../Dll/x64/HidDeviceSdk.lib")
#else
#pragma comment(lib, "../../Dll/x86/HidDeviceSdk.lib")
#endif

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// The one and only application object

CWinApp theApp;

using namespace std;

int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
	int nRetCode = 0;
	// initialize MFC and print and error on failure
	if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
	{
		// TODO: change error code to suit your needs
		_tprintf(_T("Fatal Error: MFC initialization failed\n"));
		nRetCode = 1;
	}
	else
	{
		// TODO: code your application's behavior here.
		//Step1: Enum Device
		uint32_t nHidDeviceCount = 0;
		HANDLE hDeviceHandle = INVALID_HANDLE_VALUE;
		uint32_t nRet = 0;
		if( ERROR_SUCCESS == EnumDeviceByVid(&nHidDeviceCount, PROLIFIC_VID) ) {
			if(nHidDeviceCount > 0) {
				//Step2: Open Hid Device Array index, ex: 0
				nRet = OpenDeviceHandle(0, &hDeviceHandle);
				if( ERROR_SUCCESS == nRet ) {
					//Step3: Set SPI Frequency(MAX 4.8 MHZ)
					//nSPIFreqDiv = 4, SPI Frequency(KHz) = 24000/(4+1) = 4.8 Mhz(Max)
					//nSPIFreqDiv = 254, SPI Frequency(KHz) = 24000/(254+1) = 94 Khz(Min)
					uint8_t nSPIFreqDiv = 19;	//SPI Frequency(KHz) = 24000/(19+1) = 1,200 KHz
					nRet = SetSPIFrequency(hDeviceHandle, nSPIFreqDiv, SPI_MODE3);

					SPI_SELECT nSpiSelect = SPI_SELECT0;
					uint8_t nSpiCommand;
					uint16_t nRealDataLen;
					uint32_t nTimeOutMs = 1000;	//Unit: ms

					uint16_t nNumberOfBytesToRead;
					//Send Read Identification(RDID) 0x9F Command
					BYTE byReadBuffer[10];
					memset(&byReadBuffer[0], 0, 10);
					nSpiCommand = 0x9f;
					nNumberOfBytesToRead = 3;
					nRealDataLen = 0;
					nRet = SPIWriteRead(hDeviceHandle, nSpiSelect, &nSpiCommand, 0x01, byReadBuffer, 
										nNumberOfBytesToRead, &nRealDataLen, nTimeOutMs);
					if(ERROR_SUCCESS == nRet) {
						printf("ManufactureId=0x%x, MemoryType=0x%x, MemoryDenisty=0x%x\n", byReadBuffer[0], byReadBuffer[1], byReadBuffer[2]);
					} else {
						printf("SPI Read Identification(RDID) Command Fail!\n");
					}

					//Send Read Status Register(RDSR) 0x05 Command
					nSpiCommand = 0x05;
					nNumberOfBytesToRead = 1;
					nRealDataLen = 0;
					nRet = SPIWriteRead(hDeviceHandle, nSpiSelect, &nSpiCommand, 0x01, byReadBuffer, 
										nNumberOfBytesToRead, &nRealDataLen, nTimeOutMs);
					if(ERROR_SUCCESS == nRet) {
						printf("SPI Status=0x%x\n", byReadBuffer[0]);
					} else {
						printf("SPI Read Status Register(RDSR) Command Fail!\n");
					}

					//Send write Enable(WREN) 0x06 Command
					nSpiCommand = 0x06;		//SPI Write Enable Command
					nNumberOfBytesToRead = 1;
					nRealDataLen = 0;
					nRet = SPIWrite(hDeviceHandle, nSpiSelect, &nSpiCommand, 0x01, &nRealDataLen, nTimeOutMs);
					//SPIWrite Sample (Send SPI Write Enable Command)
					if(ERROR_SUCCESS == nRet) {
						printf("SPI Write Enable Command Success!\n");
					} else {
						printf("SPI Write Enable Command Fail!\n");
					}

					//Send Read Status Register(RDSR) 0x05 Command
					nSpiCommand = 0x05;
					nNumberOfBytesToRead = 1;
					nRealDataLen = 0;
					#define STATUS_WEL_WRITE_ENABLE					0x02		//WEL
					for(uint32_t n=0; n<10; n++) {
						nRet = SPIWriteRead(hDeviceHandle, nSpiSelect, &nSpiCommand, 0x01, byReadBuffer, 
											nNumberOfBytesToRead, &nRealDataLen, nTimeOutMs);
						if(ERROR_SUCCESS == nRet) {
							printf("SPI Status=0x%x\n", byReadBuffer[0]);
						} else {
							printf("SPI Read Status Register(RDSR) Command Fail!\n");
						}
						//check Write Enable (WEL bit1 = 1)
						if(STATUS_WEL_WRITE_ENABLE == (byReadBuffer[0] & STATUS_WEL_WRITE_ENABLE) ) {
							printf("SPI Write Enable Success!\n");
							break;
						} else {
							Sleep(100);
						}
					}
					//Send Erase Command and Page Program Command

					//Send Read Status Register(RDSR) 0x05 Command and Wait WIP bit0 = 0

					//Send read data(Read) 0x03 Command
					BYTE byWriteBuffer[10];
					memset(&byWriteBuffer[0], 0, 10);
					memset(&byReadBuffer[0], 0, 10);
					byWriteBuffer[0] = 0x03;	//Read Data Command
					byWriteBuffer[1] = 0x00;	//AD1
					byWriteBuffer[2] = 0x00;	//AD2
					byWriteBuffer[3] = 0x00;	//AD3

					nNumberOfBytesToRead = 10;
					nRealDataLen = 0;
					nRet = SPIWriteRead(hDeviceHandle, nSpiSelect, &byWriteBuffer[0], 0x04, byReadBuffer, 
										nNumberOfBytesToRead, &nRealDataLen, nTimeOutMs);
					if(ERROR_SUCCESS == nRet) {
						printf("Read Data: ");
						for(uint32_t n=0; n<10; n++) { 
							printf("0x%02X ", byReadBuffer[n]);
						}
						printf("\n");
					} else {
						printf("SPI Read Data Command Fail!\n");
					}
				} else {
					printf("Open device Fail!\n");
				}
				//Step6: Close Hid Device
				nRet = CloseDeviceHandle(hDeviceHandle);
			} else {
				printf("No match Hid device!\n");
			}
		} else {
			printf("EnumDeviceByVid fail\n");
		}
	}
	system("pause");
	return nRetCode;
}
