Skip to content

Instantly share code, notes, and snippets.

@jasin
Created March 7, 2015 03:41
Show Gist options
  • Save jasin/adf969a34e654c5eac82 to your computer and use it in GitHub Desktop.
Save jasin/adf969a34e654c5eac82 to your computer and use it in GitHub Desktop.
//#include "stdafx.h"
#include "serial.h"
Serial::Serial(const TCHAR *pchPort, HWND &hwnd) // Constructor
{
SetOnEventHandle(hwnd);
SetPort(pchPort);
m_bIsConnected = false;
}
Serial::~Serial() // Destructor
{
delete m_pBuffer;
delete[] m_pchPort;
CloseHandle(m_hSerial);
}
int Serial::UnInit()
{
/* Kill the worker thread, clean up */
SignalObjectAndWait(m_hThreadTerminator, m_hThread, INFINITE, FALSE);
m_bIsConnected = false;
return 0;
}
int Serial::Init()
{
m_hSerial = CreateFile(m_pchPort,
GENERIC_READ | GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
0);
if (m_hSerial == INVALID_HANDLE_VALUE)
{
if (GetLastError() == ERROR_FILE_NOT_FOUND)
{
// Serial port does not exist.
return -1;
}
// Error occurred
return -1;
}
else
{
DCB dcbSerialParams = {0};
dcbSerialParams.DCBlength = sizeof(dcbSerialParams);
if (!GetCommState(m_hSerial, &dcbSerialParams))
{
// error getting the connection, report to user
return -1;
}
dcbSerialParams.BaudRate = CBR_115200;
dcbSerialParams.ByteSize = 8;
dcbSerialParams.StopBits = ONESTOPBIT;
dcbSerialParams.Parity = NOPARITY;
if(!SetCommState(m_hSerial, &dcbSerialParams))
{
// error setting state of COM port, report to user
return -1;
}
// Not sure if the below code needs to be included or not with checking the status of the COM queue
COMMTIMEOUTS timeouts = {0};
timeouts.ReadIntervalTimeout=MAXDWORD;
timeouts.ReadTotalTimeoutConstant=0;
timeouts.ReadTotalTimeoutMultiplier=0;
timeouts.WriteTotalTimeoutConstant=0;
timeouts.WriteTotalTimeoutMultiplier=0;
if(!SetCommTimeouts(m_hSerial, &timeouts)){
//error inform the user
return -1;
}
if (!SetCommMask(m_hSerial, EV_RXCHAR | EV_TXEMPTY))
{
//error occurred inform the user
return -1;
}
// Create thread terminator
m_hThreadTerminator = CreateEvent(0, 0, 0, 0);
// Create an event that will be signaled w/(SetEvent()) in the worker thread.
m_hThreadRunning = CreateEvent(0, 0, 0, 0);
// Begin worker thread
m_hThread = (HANDLE)_beginthreadex(0, 0, &WorkThread, (void*) this, 0, 0);
// Wait for event, see that the thread is running. Clean up a possible handle leak.
DWORD dwWait = WaitForSingleObject(m_hThreadRunning, INFINITE);
assert(dwWait == WAIT_OBJECT_0);
m_bIsConnected = true;
m_pBuffer = new Buffer();
CloseHandle(m_hThreadRunning);
return 0;
}
}
unsigned int __stdcall Serial::WorkThread(void* pvParam)
{
// This is a pointer to the 'this' serial class.
// Needed to be able to set members of the class in a static class function
Serial * cThis = (Serial*) pvParam;
// Set up the overlapped event
OVERLAPPED ov;
memset(&ov, 0, sizeof(ov));
ov.hEvent = CreateEvent(0, true, false, 0);
DWORD dwEventMask = 0;
DWORD dwWait;
HANDLE aHandles[2];
aHandles[0] = cThis->m_hThreadTerminator;
aHandles[1] = ov.hEvent;
SetEvent(cThis->m_hThreadRunning);
while (true)
{
if (!WaitCommEvent(cThis->m_hSerial, &dwEventMask, &ov))
{
assert(GetLastError() == ERROR_IO_PENDING);
}
dwWait = WaitForMultipleObjects(2, aHandles, FALSE, INFINITE);
switch(dwWait)
{
case WAIT_OBJECT_0:
{
_endthreadex(1);
}
case WAIT_OBJECT_0 + 1:
{
if (dwEventMask & EV_TXEMPTY)
{
ResetEvent(ov.hEvent);
}
else if (dwEventMask & EV_RXCHAR)
{
// read data here
DWORD dwBytesRead = 0;
OVERLAPPED ovRead = { 0 };
ovRead.hEvent = CreateEvent(0, true, false, 0);
// Get the Bytes in queue
//wstring str;
do
{
byte szBuf;
//memset(szBuf, 0x00, sizeof(szBuf));
if (ReadFile(cThis->m_hSerial, &szBuf, 1, NULL, &ovRead))
{
GetOverlappedResult(cThis->m_hSerial, &ovRead, &dwBytesRead, FALSE);
//if(szBuf[0] != '\r')
cThis->m_pBuffer->AddData(szBuf);
}
else
{
DWORD err = GetLastError();
(void)err;
}
} while (dwBytesRead > 0);
CloseHandle(ovRead.hEvent); // clean up!!!
}
// Reset the overlapped event
ResetEvent(ov.hEvent);
}
break;
}//switch
}
return 0;
}
bool Serial::WriteData(byte *byteBuffer, DWORD dwSize)
{
//TODO: Write data to the serial port from the buffer.
OVERLAPPED ov = { 0 };
ov.hEvent = CreateEvent(0, true, false, 0);
DWORD dwBytesWritten = 0;
if (!WriteFile(m_hSerial, byteBuffer, dwSize, &dwBytesWritten, &ov))
if (GetLastError() == ERROR_IO_PENDING)
WaitForSingleObject(ov.hEvent, INFINITE);
CloseHandle(ov.hEvent);
return 0;
}
bool Serial::IsConnected()
{
return m_bIsConnected;
}
TCHAR Serial::GetPort()
{
return * m_pchPort;
}
void Serial::SetPort(const TCHAR *pchPort)
{
m_nLength = _tcslen(pchPort)+1; // Get the length of the string
m_pchPort = new TCHAR[m_nLength]; // Allocate memory
_tcscpy_s(m_pchPort, m_nLength, pchPort); // Copy to internal buffer
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment