301 lines
7.9 KiB
C++
301 lines
7.9 KiB
C++
/*
|
|
* PortCore.cpp
|
|
*
|
|
* Created on: 13 May 2016
|
|
* Author: wentzelc
|
|
*/
|
|
|
|
// redA Libraries
|
|
#include "PortCore.h"
|
|
#include "TimingCore.h"
|
|
#include "LogCore.h"
|
|
|
|
// Standard C/C++ Libraries
|
|
#include <stdio.h>
|
|
#include <unistd.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include <fcntl.h>
|
|
#include <termios.h>
|
|
#include <sys/ioctl.h>
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
CPortCore::CPortCore( const char * PortName, const int PortInBufLen ) : InBufLen( PortInBufLen )
|
|
{
|
|
// Port File Handle
|
|
Handle = -1;
|
|
|
|
// Copy Port name
|
|
if (PortName) {
|
|
Name = (char*)malloc( strlen( PortName)+ 1);
|
|
strcpy( Name, PortName );
|
|
}
|
|
else {
|
|
Name = NULL;
|
|
}
|
|
|
|
// In buffer
|
|
InBuffer = (char *)malloc( InBufLen );
|
|
InLen = 0;
|
|
BytesRead = 0;
|
|
|
|
// In buffer Timer
|
|
InStart.tv_sec = 0;
|
|
InStart.tv_usec = 0;
|
|
InTimeout = 100; // millisecs
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
|
|
CPortCore::~CPortCore()
|
|
{
|
|
// Destroy pointers
|
|
if (Name) {
|
|
free( Name );
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
|
|
bool CPortCore::Open()
|
|
{
|
|
// Check if valid port name
|
|
if (!Name) {
|
|
return false;
|
|
}
|
|
|
|
// Check if port exits
|
|
if (access( Name, F_OK ) != 0)
|
|
{
|
|
printf( "Port: %s -> Could not find port\n", Name );
|
|
return false;
|
|
}
|
|
|
|
// Open Port
|
|
Handle = open( Name, O_RDWR );
|
|
if (Handle == -1)
|
|
{
|
|
printf( "Port: %s -> Could not open port\n", Name );
|
|
return false;
|
|
}
|
|
|
|
// Confirm open
|
|
printf( "Port: %s -> Port opened\n", Name );
|
|
return true;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
|
|
bool CPortCore::Close()
|
|
{
|
|
int result;
|
|
|
|
// Check if valid port
|
|
if (Handle == -1) {
|
|
return true;
|
|
}
|
|
|
|
// Close port
|
|
result = close( Handle );
|
|
if (result) {
|
|
printf( "Port: %s -> Port not closed properly\n", Name );
|
|
return false;
|
|
}
|
|
|
|
// Port closed
|
|
printf( "Port: %s -> Port closed\n", Name );
|
|
return true;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
|
|
// Set serial port configuration parameters
|
|
bool CPortCore::Config( int Baud, short DataBits, short StopBits, short Parity, short FlowCtrl, int Wait )
|
|
{
|
|
struct termios newtio;
|
|
int flags = 0;
|
|
speed_t _baud = 0;
|
|
int mcs = 0;
|
|
|
|
// Flush Data from port
|
|
tcflush( Handle, TCIFLUSH );
|
|
|
|
// Set Open flags
|
|
flags = fcntl( Handle, F_GETFL, 0 );
|
|
fcntl( Handle, F_SETFL, flags & ~O_NDELAY );
|
|
|
|
// Read options
|
|
if (tcgetattr( Handle, &newtio ) != 0)
|
|
return false;
|
|
|
|
// Process the baud rate
|
|
switch (Baud)
|
|
{
|
|
case 921600: _baud = B921600; break;
|
|
case 576000: _baud = B576000; break;
|
|
case 460800: _baud = B460800; break;
|
|
case 230400: _baud = B230400; break;
|
|
//case 128000: _baud = B128000; break;
|
|
case 115200: _baud = B115200; break;
|
|
//case 76800: _baud = B76800; break;
|
|
case 57600: _baud = B57600; break;
|
|
case 38400: _baud = B38400; break;
|
|
//case 28800: _baud = B28800; break;
|
|
case 19200: _baud = B19200; break;
|
|
//case 14400: _baud = B14400; break;
|
|
case 9600: _baud = B9600; break;
|
|
case 4800: _baud = B4800; break;
|
|
case 2400: _baud = B2400; break;
|
|
case 1800: _baud = B1800; break;
|
|
case 1200: _baud = B1200; break;
|
|
case 600: _baud = B600; break;
|
|
case 300: _baud = B300; break;
|
|
case 200: _baud = B200; break;
|
|
case 150: _baud = B150; break;
|
|
case 134: _baud = B134; break;
|
|
case 110: _baud = B110; break;
|
|
case 75: _baud = B75; break;
|
|
case 50: _baud = B50; break;
|
|
|
|
default: _baud = B9600; break;
|
|
}
|
|
|
|
// Set Baud rate
|
|
cfsetospeed( &newtio, (speed_t)_baud );
|
|
cfsetispeed( &newtio, (speed_t)_baud );
|
|
|
|
// Generate Mark/Space parity
|
|
if ((DataBits == 7) && ((Parity == MARK_PARITY) || (Parity == SPACE_PARITY)))
|
|
DataBits = 8;
|
|
|
|
// Process the data bits
|
|
newtio.c_cflag &= ~CSIZE;
|
|
switch (DataBits)
|
|
{
|
|
case 5: newtio.c_cflag |= CS5; break;
|
|
case 6: newtio.c_cflag |= CS6; break;
|
|
case 7: newtio.c_cflag |= CS7; break;
|
|
case 8: newtio.c_cflag |= CS8; break;
|
|
|
|
default: newtio.c_cflag |= CS8; break;
|
|
}
|
|
|
|
// Set other flags
|
|
newtio.c_cflag |= CLOCAL | CREAD;
|
|
|
|
// Process Parity
|
|
newtio.c_cflag &= ~(PARENB | PARODD);
|
|
if (Parity == EVEN_PARITY)
|
|
newtio.c_cflag |= PARENB;
|
|
else if (Parity == ODD_PARITY)
|
|
newtio.c_cflag |= (PARENB | PARODD);
|
|
|
|
// Flow Control (for now)
|
|
newtio.c_cflag &= ~CRTSCTS;
|
|
|
|
// Process Stop Bits
|
|
if (StopBits == 2)
|
|
newtio.c_cflag |= CSTOPB;
|
|
else
|
|
newtio.c_cflag &= ~CSTOPB;
|
|
|
|
newtio.c_iflag = IGNBRK;
|
|
|
|
// Software Flow Control
|
|
if (FlowCtrl == SW_FLOWCTRL)
|
|
newtio.c_iflag |= IXON | IXOFF;
|
|
else
|
|
newtio.c_iflag &= ~(IXON | IXOFF | IXANY);
|
|
|
|
// Set RAW input & output
|
|
newtio.c_lflag=0;
|
|
newtio.c_oflag=0;
|
|
|
|
// Set wait parameters
|
|
newtio.c_cc[VTIME] = Wait; // Blocking: Allow at least a tenth of a second to wait for data
|
|
newtio.c_cc[VMIN] = 0; // Non-blocking: Don't set min bytes to receive
|
|
|
|
// Set Options (first time)
|
|
//tcflush( Handle, TCIFLUSH);
|
|
if (tcsetattr( Handle, TCSANOW, &newtio)!=0)
|
|
return false;
|
|
|
|
// Set Terminal options
|
|
ioctl( Handle, TIOCMGET, &mcs);
|
|
mcs |= TIOCM_RTS;
|
|
ioctl( Handle, TIOCMSET, &mcs);
|
|
|
|
// Get Options (again)
|
|
if (tcgetattr( Handle, &newtio) != 0)
|
|
return false;
|
|
|
|
// Process Hardware Flow Control
|
|
if (FlowCtrl == HW_FLOWCTRL)
|
|
newtio.c_cflag |= CRTSCTS;
|
|
else
|
|
newtio.c_cflag &= ~CRTSCTS;
|
|
|
|
// Set Options (second time)
|
|
if (tcsetattr( Handle, TCSANOW, &newtio ) != 0)
|
|
{
|
|
printf( "Port: %s -> Could not configure port\n", Name );
|
|
return false;
|
|
}
|
|
|
|
// Port configured
|
|
printf( "Port: %s -> Port configured\n", Name );
|
|
return true;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
|
|
bool CPortCore::Read()
|
|
{
|
|
// Handle read event
|
|
BytesRead = read( Handle, &InBuffer[InLen], InBufLen-InLen );
|
|
if (BytesRead > 0)
|
|
{
|
|
// Process Reply
|
|
InLen += BytesRead;
|
|
|
|
// Reset timer
|
|
SetStartTime( &InStart );
|
|
}
|
|
return true;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
|
|
bool CPortCore::Maintain( int SocketHandle )
|
|
{
|
|
// Misc
|
|
long Duration = 0;
|
|
int BytesWritten = 0;
|
|
int StartWrite = 0;
|
|
|
|
if (InLen > 0)
|
|
{
|
|
// Check duration since last PortIn
|
|
Duration = TimePassed( InStart );
|
|
if (Duration > InTimeout)
|
|
{
|
|
// Handle buffer as packet
|
|
InBuffer[ InLen ] = 0;
|
|
ShowOutput( "Port In", OUT_NORMAL|OUT_HEX, InBuffer, InLen );
|
|
|
|
// Write output to Port
|
|
BytesWritten = 0;
|
|
StartWrite = 0;
|
|
if (SocketHandle != -1) {
|
|
while (StartWrite < InLen) {
|
|
BytesWritten = write( SocketHandle, &InBuffer[StartWrite], InLen );
|
|
StartWrite += BytesWritten;
|
|
}
|
|
}
|
|
|
|
// Reset buffer and timer
|
|
InLen = 0;
|
|
SetInterval( &InStart, 0 );
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|