//---------------------------------------------------------------------------
#ifdef WIN32
#include "stdafx.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#ifdef _QNX
#include <i86.h>
#include "Syslog.h"
#endif
#include "PicServo.h"

//---------------------------------------------------------------------------
// Global variables
//---------------------------------------------------------------------------
int CPicServo::SimpleMsgBox(char *msgstr)
{
#ifdef WIN32
return MessageBox(NULL, msgstr,"",MB_TASKMODAL | MB_SETFOREGROUND);
#endif
#ifdef _QNX
 Syslog::write(msgstr);
 return True;
#endif
}

//---------------------------------------------------------------------------
void CPicServo::ErrorPrinting(int f)
{
printerrors = f;
}

//---------------------------------------------------------------------------
int CPicServo::ErrorMsgBox(char *msgstr)
{
#ifdef WIN32
if (printerrors)  
	return MessageBox(NULL, msgstr,"",MB_TASKMODAL | MB_SETFOREGROUND);
else return(0);
#endif
#ifdef _QNX
if (printerrors) 
  Syslog::write(msgstr);
return True; 
#endif
}

//---------------------------------------------------------------------------
//Opens "COM1:" thru "COM4:", returns a handle to be used by other
//SIO operations.  Sets up read and write timeouts.
//*** Add parameter for baud rate ***
#ifdef WIN32
void CPicServo::SioOpen(char *name, unsigned int baudrate)
{
BOOL RetStat;
COMMCONFIG cc;
COMMTIMEOUTS ct;
DWORD winrate;
char msgstr[50];

//Open COM port as a file
ComPort = CreateFile(name, GENERIC_READ | GENERIC_WRITE ,0, NULL,
			           OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL , NULL);


while (TRUE)
	{
	if (ComPort == INVALID_HANDLE_VALUE)
		{
        sprintf(msgstr,"COM%d failed to open ",port);
		ErrorMsgBox(msgstr);
        break;
    	}

    switch (baudrate) {
		case 9600: 		winrate = CBR_9600; break;
		case 19200: 	winrate = CBR_19200; break;
		case 38400: 	winrate = CBR_38400; break;
		case 57600: 	winrate = CBR_57600; break;
		case 115200: 	winrate = CBR_115200; break;
    	default:		ErrorMsgBox("Baud rate not supported - using default of 19200");
    					winrate = CBR_19200;
    	}

    //Fill in COM port config. structure & set config.
    cc.dwSize = sizeof(DCB) + sizeof(WCHAR) + 20;
    cc.wVersion = 1;

    cc.dcb.DCBlength = sizeof(DCB);
    cc.dcb.BaudRate = winrate;
    cc.dcb.fBinary = 1;
    cc.dcb.fParity = 0;
    cc.dcb.fOutxCtsFlow = 0;
    cc.dcb.fOutxDsrFlow = 0;
    cc.dcb.fDtrControl = DTR_CONTROL_DISABLE;
    cc.dcb.fDsrSensitivity = 0;
    cc.dcb.fTXContinueOnXoff = 0;
    cc.dcb.fOutX = 0;
    cc.dcb.fInX = 0;
    cc.dcb.fErrorChar = 0;
    cc.dcb.fNull = 0;
    cc.dcb.fRtsControl = RTS_CONTROL_DISABLE;
    cc.dcb.fAbortOnError = 0;
    cc.dcb.XonLim = 100;
    cc.dcb.XoffLim = 100;
    cc.dcb.ByteSize = 8;
    cc.dcb.Parity = NOPARITY;
    cc.dcb.StopBits = ONESTOPBIT;
    cc.dcb.XonChar = 'x';
    cc.dcb.XoffChar = 'y';
    cc.dcb.ErrorChar = 0;
    cc.dcb.EofChar = 0;
    cc.dcb.EvtChar = 0;

    cc.dwProviderSubType = PST_RS232;
    cc.dwProviderOffset = 0;
    cc.dwProviderSize = 0;

    RetStat = SetCommConfig(ComPort, &cc, sizeof(cc));
	if (RetStat == 0)
    	{
    	ErrorMsgBox("Failed to set COMM configuration");
        break;
        }

    //Set read/write timeout values for the file
    ct.ReadIntervalTimeout = MAXDWORD;  		//ignore interval timing
    ct.ReadTotalTimeoutMultiplier = 2; 	//ingore cumulative interval timeout
    ct.ReadTotalTimeoutConstant = 50;  		//use a total timeout of 50 msec
    ct.WriteTotalTimeoutMultiplier = 2;	//Set max time per char written
    ct.WriteTotalTimeoutConstant = 50;	//plus additional time

	RetStat = SetCommTimeouts(ComPort, &ct);
    if (RetStat == 0)
    	{
        ErrorMsgBox("Failed to set Comm timeouts");
        break;
        }

    break;
	}
}
#endif //WIN32

#ifdef _QNX
void CPicServo::SioOpen(char *portName, unsigned int baudrate)
{
  ComPort = new SerialDevice(portName);
  if (ComPort == (SerialDevice *)NULL) {
    Syslog::write("SioOpen(): unable to open port %s\n", portName);
    return;
  }

  if (ComPort->setLineFormat(baudrate, 8, 1, "NONE") != OK) {
    Syslog::write("SioOpen() - unable to set port parameters\n");
  }
}
#endif

#ifdef WIN32
//---------------------------------------------------------------------------
//Change the baud rate to the specified values.  Valid rates are:
//9600, 19200, 38400, 57600, 115200.  Returns TRUE on success.
BOOL CPicServo::SioChangeBaud(unsigned int baudrate)
{
BOOL RetStat;
DWORD winrate;
DCB cs;

RetStat = GetCommState(&cs);
if (RetStat == false) return RetStat;
switch (baudrate) {
	case 9600:	winrate = CBR_9600; break;
	case 19200: 	winrate = CBR_19200; break;
	case 38400: 	winrate = CBR_38400; break;
	case 57600: 	winrate = CBR_57600; break;
	case 115200: 	winrate = CBR_115200; break;
    default:		ErrorMsgBox("Baud rate not supported");
    				return false;
    }
cs.BaudRate = winrate;
RetStat = SetCommState(ComPort, &cs);
if (RetStat == false) return RetStat;
return true;
}
#endif
#ifdef _QNX
BOOL CPicServo::SioChangeBaud(unsigned int baudrate)
{
  if (ComPort->setLineFormat(baudrate,8,1,"NONE") != OK)
    return False;
  else
    return True;
}
#endif
//---------------------------------------------------------------------------
//Write out N chars to the comport, returns only after chas have been sent
//return 0 on failure, non-zero on success
#ifdef WIN32
BOOL CPicServo::SioPutChars(char *stuff, int n)
{
BOOL RetStat;
DWORD nums;

RetStat = WriteFile(ComPort, stuff,n, &nums, NULL);
if (RetStat == 0) ErrorMsgBox("SioPutChars failed");
return RetStat;
}
#endif
#ifdef _QNX
BOOL CPicServo::SioPutChars(char *stuff, int n)
{
  delay(1);
  if (ComPort->write(stuff,n) != n) {
    return False;
  } else {
    return True;
  }
}
#endif

//---------------------------------------------------------------------------
//Read n chars into the array stuff (not null terminated)
//Function returns the number of chars actually read.
#ifdef WIN32
DWORD CPicServo::SioGetChars(char *stuff, int n)
{
BOOL RetStat;
DWORD numread;

tcdrain(ComPort->getFD());
delay(5);
RetStat = ReadFile(ComPort, stuff, n, &numread, NULL);
if (RetStat == 0) ErrorMsgBox("SioReadChars failed");

return numread;
}
#endif
#ifdef _QNX
DWORD CPicServo::SioGetChars(char *stuff, int n)
{
  tcdrain(ComPort->getFd());
  delay(4);
  return ComPort->readNChars(stuff,n,100);
}
#endif

//---------------------------------------------------------------------------
//Returns the number of chars in a port's input buffer
#ifdef _WIN32
DWORD CPicServo::SioTest()
{
COMSTAT cs;
DWORD Errors;
BOOL RetStat;

RetStat = ClearCommError(ComPort, &Errors, &cs);
if (RetStat == 0) ErrorMsgBox("SioTest failed");
return cs.cbInQue;
}
#endif
#ifdef _QNX
DWORD CPicServo::SioTest()
{
  return ComPort->nRecvdBytes();
}
#endif

//---------------------------------------------------------------------------
//Purge all chars from the input buffer
#ifdef WIN32
BOOL CPicServo::SioClrInbuf()
{
BOOL RetStat;

RetStat = PurgeComm(ComPort, PURGE_RXCLEAR);
if (RetStat == 0) ErrorMsgBox("SioClrInbuf failed");

return RetStat;
}
#endif
#ifdef _QNX
BOOL CPicServo::SioClrInbuf()
{
  ComPort->clearPort();
  return True;
}
#endif

//---------------------------------------------------------------------------
//Close a previously opened COM port
#ifdef WIN32
BOOL CPicServo::SioClose()
{
	BOOL bRet=FALSE;
	try{
		if (ComPort!=INVALID_HANDLE_VALUE)
			bRet=CloseHandle(ComPort);
		TRACE("%d\n",bRet);
	}
	catch(...)
	{
		bRet=FALSE;
	}
	ComPort=INVALID_HANDLE_VALUE;
return bRet;
}
#endif
#ifdef _QNX
BOOL CPicServo::SioClose()
{
  delete ComPort;
  ComPort = INVALID_HANDLE_VALUE;
  return True;
}
#endif
//---------------------------------------------------------------------------



