#pragma once

#include <stdio.h>
#include <Windows.h>
#include "imechatronics.h"

#pragma warning( disable : 4996)


	typedef FT_STATUS (WINAPI *PtrToOpen)(PVOID, FT_HANDLE *); 
	PtrToOpen m_pOpen; 

	FT_STATUS Open(PVOID pvDevice)
	{
		if (!m_pOpen)
		{
			return FT_INVALID_HANDLE;
		}
		
		return (*m_pOpen)(pvDevice, &m_ftHandle );
	}	;


	typedef FT_STATUS (WINAPI *PtrToOpenEx)(PVOID, DWORD, FT_HANDLE *); 
	PtrToOpenEx m_pOpenEx; 
	FT_STATUS OpenEx(PVOID pArg1, DWORD dwFlags)
	{
		if (!m_pOpenEx)
		{
			return FT_INVALID_HANDLE;
		}
		
		return (*m_pOpenEx)(pArg1, dwFlags, &m_ftHandle);
	}	;


	typedef FT_STATUS (WINAPI *PtrToListDevices)(PVOID, PVOID, DWORD);
	PtrToListDevices m_pListDevices; 
	FT_STATUS ListDevices(PVOID pArg1, PVOID pArg2, DWORD dwFlags)
	{
		if (!m_pListDevices)
		{
			return FT_INVALID_HANDLE;
		}
		
		return (*m_pListDevices)(pArg1, pArg2, dwFlags);
	}	;


	typedef FT_STATUS (WINAPI *PtrToClose)(FT_HANDLE);
	PtrToClose m_pClose;
	FT_STATUS UCIDrvClose()
	{
		if (!m_pClose)
		{
			return FT_INVALID_HANDLE;
		}
		
		return (*m_pClose)(m_ftHandle);
	}	;


	typedef FT_STATUS (WINAPI *PtrToRead)(FT_HANDLE, LPVOID, DWORD, LPDWORD);
	PtrToRead m_pRead;
	FT_STATUS Read(LPVOID lpvBuffer, DWORD dwBuffSize, LPDWORD lpdwBytesRead)
	{
		if (!m_pRead)
		{
			return FT_INVALID_HANDLE;
		}

		return (*m_pRead)(m_ftHandle, lpvBuffer, dwBuffSize, lpdwBytesRead);
	}	;


	typedef FT_STATUS (WINAPI *PtrToWrite)(FT_HANDLE, LPVOID, DWORD, LPDWORD);
	PtrToWrite m_pWrite;
	FT_STATUS Write(LPVOID lpvBuffer, DWORD dwBuffSize, LPDWORD lpdwBytes)
	{
		if (!m_pWrite)
		{
			return FT_INVALID_HANDLE;
		}
		
		return (*m_pWrite)(m_ftHandle, lpvBuffer, dwBuffSize, lpdwBytes);
	}	

	typedef FT_STATUS (WINAPI *PtrToResetDevice)(FT_HANDLE);
	PtrToResetDevice m_pResetDevice;
	FT_STATUS ResetDevice()
	{
		if (!m_pResetDevice)
		{
			return FT_INVALID_HANDLE;
		}
		
		return (*m_pResetDevice)(m_ftHandle);
	}	
	
	typedef FT_STATUS (WINAPI *PtrToPurge)(FT_HANDLE, ULONG);
	PtrToPurge m_pPurge;
	FT_STATUS Purge(ULONG dwMask)
	{
		if (!m_pPurge)
		{
			return FT_INVALID_HANDLE;
		}

		return (*m_pPurge)(m_ftHandle, dwMask);
	}	;

	
	typedef FT_STATUS (WINAPI *PtrToSetTimeouts)(FT_HANDLE, ULONG, ULONG);
	PtrToSetTimeouts m_pSetTimeouts;
	FT_STATUS SetTimeouts(ULONG dwReadTimeout, ULONG dwWriteTimeout)
	{
		if (!m_pSetTimeouts)
		{
			return FT_INVALID_HANDLE;
		}

		return (*m_pSetTimeouts)(m_ftHandle, dwReadTimeout, dwWriteTimeout);
	}	;

	typedef FT_STATUS (WINAPI *PtrToGetQueueStatus)(FT_HANDLE, LPDWORD);
	PtrToGetQueueStatus m_pGetQueueStatus;
	FT_STATUS GetQueueStatus(LPDWORD lpdwAmountInRxQueue)
	{
		if (!m_pGetQueueStatus)
		{
			return FT_INVALID_HANDLE;
		}

		return (*m_pGetQueueStatus)(m_ftHandle, lpdwAmountInRxQueue);
	}	;

	int InitDrv()
	{
		m_hmodule = LoadLibraryA("Ftd2xx.dll");	
		if(m_hmodule == NULL)
		{
			return -1;
		}

		m_pWrite = (PtrToWrite)GetProcAddress(m_hmodule, "FT_Write");
		if (m_pWrite == NULL)
		{
			return -1;
		}

		m_pRead = (PtrToRead)GetProcAddress(m_hmodule, "FT_Read");
		if (m_pRead == NULL)
		{
			return -1;
		}

		m_pOpen = (PtrToOpen)GetProcAddress(m_hmodule, "FT_Open");
		if (m_pOpen == NULL)
		{
			return -1;
		}

		m_pOpenEx = (PtrToOpenEx)GetProcAddress(m_hmodule, "FT_OpenEx");
		if (m_pOpenEx == NULL)
		{			
			return -1;
		}

		m_pListDevices = (PtrToListDevices)GetProcAddress(m_hmodule, "FT_ListDevices");
		if(m_pListDevices == NULL)
		{
			return -1;
		}

		m_pClose = (PtrToClose)GetProcAddress(m_hmodule, "FT_Close");
		if (m_pClose == NULL)
		{
			return -1;
		}

		m_pResetDevice = (PtrToResetDevice)GetProcAddress(m_hmodule, "FT_ResetDevice");
		if (m_pResetDevice == NULL)
		{
			return -1;
		}

		m_pPurge = (PtrToPurge)GetProcAddress(m_hmodule, "FT_Purge");
		if (m_pPurge == NULL)
		{
			return -1;
		}

		m_pSetTimeouts = (PtrToSetTimeouts)GetProcAddress(m_hmodule, "FT_SetTimeouts");
		if (m_pSetTimeouts == NULL)
		{
			return -1;
		}

		m_pGetQueueStatus = (PtrToGetQueueStatus)GetProcAddress(m_hmodule, "FT_GetQueueStatus");
		if (m_pGetQueueStatus == NULL)
		{
			return -1;
		}
		return 1;
	};

	FT_STATUS OpenBy()		
	{

		FT_STATUS status;
		sprintf(m_NameNmbr, "USB <-> Serial");		 
		ULONG x=0;
		status = OpenEx((PVOID)(LPCSTR)m_NameNmbr, FT_OPEN_BY_DESCRIPTION);
	
		return status;
	};
	
	int UCIDrvInit()
	{
		unsigned char txbuf[25];
		//open the device
		FT_STATUS status = OpenBy();
		if(status)
		{
			board_present=0;
			return -1;
		}
		else
		{
			ResetDevice();
			Purge(FT_PURGE_RX || FT_PURGE_TX);
			
			//test for presence of board
			txbuf[0] = 0x80;
			board_present=1;
			
		}

		return 1;

	};


	void Outputb(int PPI, int add)
	{

		unsigned char tx[10] = {0,};

		char ttt[4] = {0,};
		
		DWORD ret_bytes = 0;

		if(!board_present)
			return;

		bus_busy=1;//keep the timer function from grabbing return data

		//clear the ports of any data
		//Purge(FT_PURGE_RX || FT_PURGE_TX);


		tx[0] = '$';
		tx[1] = 'W';

		
		sprintf(ttt,"%02x",PPI);

		tx[2] = ttt[0];  // 1
		tx[3] = ttt[1]; 

		sprintf(ttt,"%02x",add);

		tx[4] = ttt[0]; 
		tx[5] = ttt[1];	
		

		tx[6] = '\r';
		tx[7] = '\n';

		Write(tx, 8, &ret_bytes);
		bus_busy=0;
	};

	
	unsigned char HexASC_TO_INT(char* str)
	{
		int i;
		unsigned char iTemp_val[2];
		unsigned char iConv_result;

		for(i=0;i<2;i++)
		{
			if(str[i] > 47 && str[i] < 58) iTemp_val[i]  = str[i] - 48;
			else
			{
				switch(str[i])
				{
				  case 'A':
				  case 'a':
					 iTemp_val[i] = 10;
					 break;
				  case 'B':
				  case 'b':
					 iTemp_val[i] = 11;
					 break;
				  case 'C':
				  case 'c':
					 iTemp_val[i] = 12;
					 break;
				  case 'D':
				  case 'd':
					 iTemp_val[i] = 13;
					 break;
				  case 'E':
				  case 'e':
					 iTemp_val[i] = 14;
					 break;
				  case 'F':
				  case 'f':
					 iTemp_val[i] = 15;
					 break;
				  default :
		      		iTemp_val[i] = 0;
		      		break;
				}
			}
		}
	   iConv_result = (iTemp_val[0] * 16) + iTemp_val[1];
	   return iConv_result;
	}


	int Inputb(int PPI)
	{

		unsigned char tx[10], rx[10];
		char tinput[3];

		char ttt[3] = {0,};
		
		DWORD ret_bytes;

		if(!board_present)
			return -1;

		bus_busy=1;//keep the timer function from grabbing return data

		//clear the ports of any data
		//Purge(FT_PURGE_RX || FT_PURGE_TX);

		tx[0] = '$';
		tx[1] = 'R';
		
		sprintf(ttt,"%02x",PPI);

		tx[2] = ttt[0];  // 1
		tx[3] = ttt[1]; 

		tx[4] = '0'; 
		tx[5] = '0';	
		
		tx[6] = '\r';
		tx[7] = '\n';

		Write(tx, 8, &ret_bytes);


		Read(rx, 8, &ret_bytes);
		
		bus_busy=0;

//--+6		CStringA tsts;
//		tsts= (UCHAR)rx[4] <<(UCHAR)8 & (UCHAR)rx[5];
		
		tinput[0]=rx[4];
		tinput[1]=rx[5];
		tinput[2]=0;

		int retvalue;
		retvalue=HexASC_TO_INT(tinput);

		return retvalue;


	};



	int CalCulBit(int data, int BitNum) 
	{
		// TODO: Add your control notification handler code here

		int BitValue;

		BitValue= (data>> (BitNum-1) ) & 0x01;

		return BitValue;
	}
