#include "StdAfx.h"
#include "Serial.h"


Serial::Serial(  Status *pStatus, char *commPort ) :
	m_pStatus( pStatus )
{
	strcpy_s( m_chCommPort, 48, commPort );
}


Serial::~Serial(void)
{

	if( m_hCom )
		CloseHandle( m_hCom );

}


bool Serial::Init()
{
	bool bRtn = true;
	BOOL bSuccess1;


	 m_hCom = CreateFile( m_chCommPort,
		 GENERIC_READ | GENERIC_WRITE, //GENERIC_ALL
		 0,    // exclusive access 
		 NULL, // no security attributes 
		 OPEN_EXISTING,
		 0, //FILE_FLAG_OVERLAPPED, //0
		 NULL
		 );

	if (m_hCom == INVALID_HANDLE_VALUE) 
	{
		bRtn = false;
		m_pStatus->PrintStatus( "     ERROR: opening %s\n", m_chCommPort );
		return false;
	}

	// Build on the current configuration, and skip setting the size
	// of the input and output buffers with SetupComm.

	DCB dcb;

   //  Initialize the DCB structure.
   SecureZeroMemory(&dcb, sizeof(DCB));
   dcb.DCBlength = sizeof(DCB);

	bSuccess1 = GetCommState(m_hCom, &dcb);

	if (!bSuccess1) 
	{
      m_pStatus->PrintStatus( "     GetCommState failed with error: %d\n", GetLastError() );
	   CloseHandle( m_hCom );
		bRtn = false;
    }

	dcb.BaudRate = CBR_115200;     // set the baud rate
	dcb.ByteSize = 8;             // data size, xmit, and rcv
	dcb.Parity   = ODDPARITY;     // odd parity bit
	dcb.StopBits = ONESTOPBIT;    // one stop bit

	bSuccess1 = SetCommState(m_hCom, &dcb);
	if (!bSuccess1) 
	{
      m_pStatus->PrintStatus( "     SetCommState failed with error: %d\n", GetLastError() );
	   CloseHandle( m_hCom );
		bRtn = false;
   }

	COMMTIMEOUTS commTimeOut;
	BOOL flag = GetCommTimeouts( m_hCom, &commTimeOut );


	// from MSDN:
	//    If an application sets ReadIntervalTimeout and ReadTotalTimeoutMultiplier to MAXDWORD and sets ReadTotalTimeoutConstant 
	//    to a value greater than zero and less than MAXDWORD, one of the following occurs when the ReadFile function is called:
	//    If there are any bytes in the input buffer, ReadFile returns immediately with the bytes in the buffer.
	//    If there are no bytes in the input buffer, ReadFile waits until a byte arrives and then returns immediately.
	//    If no bytes arrive within the time specified by ReadTotalTimeoutConstant, ReadFile times out.
	commTimeOut.ReadIntervalTimeout = MAXDWORD;
	commTimeOut.ReadTotalTimeoutConstant = 10000;
	commTimeOut.ReadTotalTimeoutMultiplier = MAXDWORD;
	SetCommTimeouts( m_hCom, &commTimeOut );

	bSuccess1 = SetupComm(m_hCom,1024,1024);
	if (!bSuccess1) 
	{
      m_pStatus->PrintStatus( "     SetupComm failed with error: %d\n", GetLastError() );
	   CloseHandle( m_hCom );
		bRtn = false;
   }

	PurgeComm( m_hCom, PURGE_RXCLEAR | PURGE_TXCLEAR );

	return bRtn;

}

bool Serial::WriteString( char *cmd )
{
	BOOL bSuccess;
	DWORD bytesWritten;

	int len = strlen(cmd);
	bSuccess = WriteFile( m_hCom, cmd, len, &bytesWritten, NULL );

	return bytesWritten == len;
}
bool Serial::WriteString( char *cmd, UINT8 len )
{
	BOOL bSuccess;
	DWORD bytesWritten;

	bSuccess = WriteFile( m_hCom, cmd, len, &bytesWritten, NULL );

	return bytesWritten == len;
}
bool Serial::ReadString( char *cmd, UINT32 *bytesRead )
{
	BOOL bSuccess = false;
	DWORD br;

	bSuccess = ReadFile( m_hCom, cmd, 1024, &br, NULL );
	if( bSuccess )
	{
		*bytesRead = br;
		cmd[*bytesRead] = 0;
	}

	return bSuccess ? true : false;
}

bool Serial::ReadString( char *cmd, UINT32 bytesToRead, UINT32 *bytesRead )
{
	bool bRtn = false;
	BOOL bSuccess = false;
	DWORD br = 0;
	DWORD totalbr = 0;
	DWORD bytesLeftToRead = bytesToRead;

	// read all bytes requested
	while( true )
	{
		bSuccess = ReadFile( m_hCom, cmd+totalbr, bytesLeftToRead, &br, NULL );

		// quick return case for single byte reads 
		if( bSuccess && bytesToRead == 1 && br == 1 ) { *bytesRead = 1; return true; }

		// general case for multibyte reads
		if( bSuccess )
		{
			totalbr += br;
			if( totalbr >= bytesToRead )
			{
				*bytesRead   = totalbr;
				cmd[totalbr] = 0;
				bRtn         = true;
				break;
			}
			bytesLeftToRead -= br;
		}
		else
		{
			break;
		}
	}
			
	return bRtn;
}

