// CSerialComm.cpp // ////////////////////////////////////////////////////////////////////// #include "StdAfx.h" #include #include "SerialComm.h" #include "serial/SerialMFC.h" #include // This string is used to signal a failed read to SlControl. const string READFAILURE = "Read failure."; CSerialComm::CSerialComm() { // m_Serial represents one COM port. m_Serial=new CSerialMFC(); // Load settings from port.cfg if it exists, use default settings if not. ifstream file("port.cfg"); if (!file) { m_sPort="COM1"; m_sBaudrate="9600"; m_sDatabits="8"; m_sParity="None"; m_sStopbits="1"; m_sHandshaking="None"; return; } string line; if (getline (file,line)) m_sPort=line; if (getline (file,line)) m_sBaudrate=line; if (getline (file,line)) m_sDatabits=line; if (getline (file,line)) m_sParity=line; if (getline (file,line)) m_sStopbits=line; if (getline (file,line)) m_sHandshaking=line; file.close(); } CSerialComm::~CSerialComm() { // Save settings, overwriting port.cfg. ofstream file("port.cfg"); if (!file) return; file << m_sPort.c_str() << endl; file << m_sBaudrate.c_str() << endl; file << m_sDatabits.c_str() << endl; file << m_sParity.c_str() << endl; file << m_sStopbits.c_str() << endl; file << m_sHandshaking.c_str() << endl; file.close(); // Kill the port. delete m_Serial; } /* The following six methods are used by the port setting dialog to read the present port setting variables (which are stored here, not in the dialog class). Nothing special here. */ string CSerialComm::GetPort(){ return m_sPort; } string CSerialComm::GetBaudrate(){ return m_sBaudrate; } string CSerialComm::GetDatabits(){ return m_sDatabits; } string CSerialComm::GetParity(){ return m_sParity; } string CSerialComm::GetStopbits(){ return m_sStopbits; } string CSerialComm::GetHandshaking(){ return m_sHandshaking; } /* The following six methods are used by the port setting dialog to set the port setting variables. */ void CSerialComm::SetPort(string sNewPort){ m_sPort = sNewPort; } void CSerialComm::SetBaudrate(string sNewBaudrate){ m_sBaudrate = sNewBaudrate; } void CSerialComm::SetDatabits(string sNewDatabits){ m_sDatabits = sNewDatabits; } void CSerialComm::SetParity(string sNewParity){ m_sParity = sNewParity; } void CSerialComm::SetStopbits(string sNewStopbits){ m_sStopbits = sNewStopbits; } void CSerialComm::SetHandshaking(string sNewHandshaking){ m_sHandshaking = sNewHandshaking; } /* InitComms opens and configures the COM port. */ void CSerialComm::InitComms(CWnd* pMainDlg){ // Open the port, bind events to given dialog using default event mask. The helper class CSerialWnd // starts the listener thread at this point. Whenever the listener thread detects a port anomaly, it // posts a message in the window at pMainDlg. m_Serial->Open(m_sPort.c_str(), pMainDlg); // Configure the port. CSerial::EBaudrate eBaudrate = CSerial::EBaudUnknown; if (m_sBaudrate == "110") eBaudrate = CSerial::EBaud110; if (m_sBaudrate == "300") eBaudrate = CSerial::EBaud300; if (m_sBaudrate == "1200") eBaudrate = CSerial::EBaud1200; if (m_sBaudrate == "2400") eBaudrate = CSerial::EBaud2400; if (m_sBaudrate == "4800") eBaudrate = CSerial::EBaud4800; if (m_sBaudrate == "9600") eBaudrate = CSerial::EBaud9600; if (m_sBaudrate == "14400") eBaudrate = CSerial::EBaud14400; if (m_sBaudrate == "19200") eBaudrate = CSerial::EBaud19200; if (m_sBaudrate == "38400") eBaudrate = CSerial::EBaud38400; if (m_sBaudrate == "56000") eBaudrate = CSerial::EBaud56000; if (m_sBaudrate == "57600") eBaudrate = CSerial::EBaud57600; if (m_sBaudrate == "115200") eBaudrate = CSerial::EBaud115200; CSerial::EDataBits eDataBits = CSerial::EDataUnknown; if (m_sDatabits == "5") eDataBits = CSerial::EData5; if (m_sDatabits == "6") eDataBits = CSerial::EData6; if (m_sDatabits == "7") eDataBits = CSerial::EData7; if (m_sDatabits == "8") eDataBits = CSerial::EData8; CSerial::EParity eParity = CSerial::EParUnknown; if (m_sParity == "None") eParity = CSerial::EParNone; if (m_sParity == "Odd") eParity = CSerial::EParOdd; if (m_sParity == "Even") eParity = CSerial::EParEven; if (m_sParity == "Mark") eParity = CSerial::EParMark; if (m_sParity == "Space") eParity = CSerial::EParSpace; CSerial::EStopBits eStopBits = CSerial::EStopUnknown; if (m_sStopbits == "1") eStopBits = CSerial::EStop1; if (m_sStopbits == "1.5") eStopBits = CSerial::EStop1_5; if (m_sStopbits == "2") eStopBits = CSerial::EStop2; CSerial::EHandshake eHandshake = CSerial::EHandshakeUnknown; if (m_sHandshaking == "None") eHandshake = CSerial::EHandshakeOff; if (m_sHandshaking == "XON/XOFF") eHandshake = CSerial::EHandshakeSoftware; if (m_sHandshaking == "Hardware") eHandshake = CSerial::EHandshakeHardware; m_Serial->Setup(eBaudrate,eDataBits,eParity,eStopBits); // Setup handshaking. m_Serial->SetupHandshaking(eHandshake); // Set m_Serial into nonblocking mode. m_Serial->SetupReadTimeouts(CSerial::EReadTimeoutNonblocking); }; /* CloseComms closes the port. */ void CSerialComm::CloseComms(){ // Close the port. CSerialWnd takes care of all the necessary cleanup and kills the listener thread. m_Serial->Close(); }; /* SendString writes the specified string to the COM port. */ LONG CSerialComm::SendString(string MsgToBeSent){ return m_Serial->Write(MsgToBeSent.c_str()); }; /* ReceiveString method handles all returning traffic. */ string CSerialComm::ReceiveString(){ // Create a clean buffer. DWORD dwBytesRead = 0; char szBuffer[101]; // The size could be anything above 2, but 100 is a nice round number. string response = READFAILURE; // Read data until there is nothing left. do { // Read data from the port. m_Serial->Read(szBuffer,sizeof(szBuffer)-1,&dwBytesRead); if (dwBytesRead > 0) { // Finalize the data so that it's a valid string. szBuffer[dwBytesRead] = '\0'; // If response not null, append it to the previous one. if (response == READFAILURE) // Actually, in practice thís bit of code doesn't seem to be ever reached, // but better safe than sorry. response = szBuffer; else response = response + szBuffer; } } while (dwBytesRead == sizeof(szBuffer)-1); return response; }; /* IsConnectionReady returns TRUE if the port has been successfully opened. */ BOOL CSerialComm::IsConnectionReady(){ return m_Serial->IsOpen(); };