Initial DMX (Enttec OpenDMX USB) support and serial_port improvements
* Support DMX RGB lights (PAR lights, spotlights, wash lights, etc) * Configurable R/G/B channel and Brightness/Master channel * Add configurable parameters to serial_port needed to configure a port for DMX * Add DMX tab to settings
This commit is contained in:
parent
8b4b2bacbc
commit
81aaf67ff0
14 changed files with 1318 additions and 48 deletions
|
|
@ -17,9 +17,13 @@
|
|||
serial_port::serial_port()
|
||||
{
|
||||
/*-----------------------------------------------------*\
|
||||
| Set a default baud rate |
|
||||
| Set default port configuration but do not open |
|
||||
\*-----------------------------------------------------*/
|
||||
baud_rate = 9600;
|
||||
baud_rate = 9600;
|
||||
parity = SERIAL_PORT_PARITY_NONE;
|
||||
size = SERIAL_PORT_SIZE_8;
|
||||
stop_bits = SERIAL_PORT_STOP_BITS_1;
|
||||
flow_control = true;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
|
|
@ -29,7 +33,44 @@ serial_port::serial_port()
|
|||
\*---------------------------------------------------------*/
|
||||
serial_port::serial_port(const char * name, unsigned int baud)
|
||||
{
|
||||
serial_open(name, baud);
|
||||
/*-----------------------------------------------------*\
|
||||
| Set default port configuration and open |
|
||||
\*-----------------------------------------------------*/
|
||||
baud_rate = baud;
|
||||
parity = SERIAL_PORT_PARITY_NONE;
|
||||
size = SERIAL_PORT_SIZE_8;
|
||||
stop_bits = SERIAL_PORT_STOP_BITS_1;
|
||||
flow_control = true;
|
||||
|
||||
serial_open(name);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| serial_port (constructor) |
|
||||
| When created with port information, the constructor |
|
||||
| will automatically open port <name> at baud rate <baud>|
|
||||
| with the given port configuration |
|
||||
\*---------------------------------------------------------*/
|
||||
serial_port::serial_port
|
||||
(
|
||||
const char * name,
|
||||
unsigned int baud,
|
||||
serial_port_parity parity,
|
||||
serial_port_size size,
|
||||
serial_port_stop_bits stop_bits,
|
||||
bool flow_control
|
||||
)
|
||||
{
|
||||
/*-----------------------------------------------------*\
|
||||
| Set default port configuration and open |
|
||||
\*-----------------------------------------------------*/
|
||||
this->baud_rate = baud;
|
||||
this->parity = parity;
|
||||
this->size = size;
|
||||
this->stop_bits = stop_bits;
|
||||
this->flow_control = flow_control;
|
||||
|
||||
serial_open(name);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
|
|
@ -58,6 +99,9 @@ bool serial_port::serial_open()
|
|||
char full_path[100];
|
||||
snprintf(full_path, sizeof(full_path), "\\\\.\\%s", port_name);
|
||||
|
||||
/*-----------------------------------------*\
|
||||
| Open the port read/write |
|
||||
\*-----------------------------------------*/
|
||||
file_descriptor = CreateFile(full_path, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
|
||||
|
||||
if((int)file_descriptor < 0)
|
||||
|
|
@ -65,29 +109,106 @@ bool serial_port::serial_open()
|
|||
return false;
|
||||
}
|
||||
|
||||
/*-----------------------------------------*\
|
||||
| Get the port configuration options |
|
||||
\*-----------------------------------------*/
|
||||
SetupComm(file_descriptor, 1, 128);
|
||||
GetCommState(file_descriptor, &dcb);
|
||||
|
||||
dcb.BaudRate = baud_rate; //Set baud rate
|
||||
dcb.ByteSize = 8; //8 data bits
|
||||
dcb.Parity = NOPARITY; //Parity = none
|
||||
dcb.StopBits = ONESTOPBIT; //One stop bit
|
||||
dcb.fAbortOnError = TRUE; //Abort on error
|
||||
/*-----------------------------------------*\
|
||||
| Configure baud rate |
|
||||
\*-----------------------------------------*/
|
||||
dcb.BaudRate = baud_rate;
|
||||
|
||||
/*-----------------------------------------*\
|
||||
| Configure parity |
|
||||
\*-----------------------------------------*/
|
||||
switch(parity)
|
||||
{
|
||||
case SERIAL_PORT_PARITY_NONE:
|
||||
dcb.Parity = NOPARITY;
|
||||
break;
|
||||
|
||||
case SERIAL_PORT_PARITY_ODD:
|
||||
dcb.Parity = ODDPARITY;
|
||||
break;
|
||||
|
||||
case SERIAL_PORT_PARITY_EVEN:
|
||||
dcb.Parity = EVENPARITY;
|
||||
break;
|
||||
}
|
||||
|
||||
/*-----------------------------------------*\
|
||||
| Configure size |
|
||||
\*-----------------------------------------*/
|
||||
switch(size)
|
||||
{
|
||||
case SERIAL_PORT_SIZE_8:
|
||||
dcb.ByteSize = 8;
|
||||
break;
|
||||
|
||||
case SERIAL_PORT_SIZE_7:
|
||||
dcb.ByteSize = 7;
|
||||
break;
|
||||
|
||||
case SERIAL_PORT_SIZE_6:
|
||||
dcb.ByteSize = 6;
|
||||
break;
|
||||
|
||||
case SERIAL_PORT_SIZE_5:
|
||||
dcb.ByteSize = 5;
|
||||
break;
|
||||
}
|
||||
|
||||
/*-----------------------------------------*\
|
||||
| Configure stop bits |
|
||||
\*-----------------------------------------*/
|
||||
if(stop_bits == SERIAL_PORT_STOP_BITS_2)
|
||||
{
|
||||
dcb.StopBits = TWOSTOPBITS;
|
||||
}
|
||||
else
|
||||
{
|
||||
dcb.StopBits = ONESTOPBIT;
|
||||
}
|
||||
|
||||
/*-----------------------------------------*\
|
||||
| Configure flow control |
|
||||
\*-----------------------------------------*/
|
||||
if(flow_control)
|
||||
{
|
||||
dcb.fRtsControl = RTS_CONTROL_ENABLE;
|
||||
}
|
||||
else
|
||||
{
|
||||
dcb.fRtsControl = RTS_CONTROL_DISABLE;
|
||||
}
|
||||
|
||||
/*-----------------------------------------*\
|
||||
| Configure additional parameters |
|
||||
\*-----------------------------------------*/
|
||||
dcb.fAbortOnError = FALSE; //Abort on error
|
||||
dcb.fOutX = FALSE; //XON/XOFF off for transmit
|
||||
dcb.fInX = FALSE; //XON/XOFF off for receive
|
||||
dcb.fOutxCtsFlow = FALSE; //Turn off CTS flow control
|
||||
dcb.fRtsControl = RTS_CONTROL_DISABLE; //Options DISABLE, ENABLE, HANDSHAKE
|
||||
dcb.fOutxDsrFlow = FALSE; //Turn off DSR flow control
|
||||
dcb.fDtrControl = DTR_CONTROL_DISABLE; //Disable DTR control
|
||||
|
||||
/*-----------------------------------------*\
|
||||
| Set the port configuration options |
|
||||
\*-----------------------------------------*/
|
||||
SetCommState(file_descriptor, &dcb);
|
||||
|
||||
COMMTIMEOUTS timeouts = {0};
|
||||
timeouts.ReadIntervalTimeout = 50;
|
||||
timeouts.ReadTotalTimeoutConstant=50;
|
||||
timeouts.ReadTotalTimeoutMultiplier=10;
|
||||
timeouts.WriteTotalTimeoutConstant=50;
|
||||
timeouts.WriteTotalTimeoutMultiplier=10;
|
||||
/*-----------------------------------------*\
|
||||
| Set the port timeouts |
|
||||
\*-----------------------------------------*/
|
||||
COMMTIMEOUTS timeouts = {0};
|
||||
timeouts.ReadIntervalTimeout = 50;
|
||||
timeouts.ReadTotalTimeoutConstant = 50;
|
||||
timeouts.ReadTotalTimeoutMultiplier = 10;
|
||||
timeouts.WriteTotalTimeoutConstant = 50;
|
||||
timeouts.WriteTotalTimeoutMultiplier = 10;
|
||||
|
||||
SetCommTimeouts(file_descriptor, &timeouts);
|
||||
#endif
|
||||
|
||||
|
|
@ -95,6 +216,9 @@ bool serial_port::serial_open()
|
|||
| Linux-specific code path for serial port opening |
|
||||
\*-----------------------------------------------------*/
|
||||
#ifdef __linux__
|
||||
/*-----------------------------------------*\
|
||||
| Open the port read/write with no delay |
|
||||
\*-----------------------------------------*/
|
||||
file_descriptor = open(port_name, O_RDWR | O_NOCTTY | O_NDELAY);
|
||||
|
||||
if(file_descriptor < 0)
|
||||
|
|
@ -102,19 +226,105 @@ bool serial_port::serial_open()
|
|||
return false;
|
||||
}
|
||||
|
||||
/*-----------------------------------------*\
|
||||
| Get the port configuration options |
|
||||
\*-----------------------------------------*/
|
||||
struct termios2 options;
|
||||
ioctl(file_descriptor, TCGETS2, &options);
|
||||
|
||||
/*-----------------------------------------*\
|
||||
| Configure baud rate |
|
||||
\*-----------------------------------------*/
|
||||
options.c_cflag &= ~CBAUD;
|
||||
options.c_cflag |= BOTHER;
|
||||
options.c_cflag |= CBAUDEX;
|
||||
|
||||
options.c_ispeed = baud_rate;
|
||||
options.c_ospeed = baud_rate;
|
||||
|
||||
/*-----------------------------------------*\
|
||||
| Configure parity |
|
||||
\*-----------------------------------------*/
|
||||
switch(parity)
|
||||
{
|
||||
case SERIAL_PORT_PARITY_NONE:
|
||||
options.c_cflag &= ~PARENB;
|
||||
options.c_cflag &= ~PARODD;
|
||||
break;
|
||||
|
||||
case SERIAL_PORT_PARITY_ODD:
|
||||
options.c_cflag |= PARENB;
|
||||
options.c_cflag |= PARODD;
|
||||
break;
|
||||
|
||||
case SERIAL_PORT_PARITY_EVEN:
|
||||
options.c_cflag |= PARENB;
|
||||
options.c_cflag &= ~PARODD;
|
||||
break;
|
||||
}
|
||||
|
||||
/*-----------------------------------------*\
|
||||
| Configure size |
|
||||
\*-----------------------------------------*/
|
||||
options.c_cflag &= ~CSIZE;
|
||||
|
||||
switch(size)
|
||||
{
|
||||
case SERIAL_PORT_SIZE_8:
|
||||
options.c_cflag |= CS8;
|
||||
break;
|
||||
|
||||
case SERIAL_PORT_SIZE_7:
|
||||
options.c_cflag |= CS7;
|
||||
break;
|
||||
|
||||
case SERIAL_PORT_SIZE_6:
|
||||
options.c_cflag |= CS6;
|
||||
break;
|
||||
|
||||
case SERIAL_PORT_SIZE_5:
|
||||
options.c_cflag |= CS5;
|
||||
break;
|
||||
}
|
||||
|
||||
/*-----------------------------------------*\
|
||||
| Configure stop bits |
|
||||
\*-----------------------------------------*/
|
||||
if(stop_bits == SERIAL_PORT_STOP_BITS_2)
|
||||
{
|
||||
options.c_cflag |= CSTOPB;
|
||||
}
|
||||
else
|
||||
{
|
||||
options.c_cflag &= ~CSTOPB;
|
||||
}
|
||||
|
||||
/*-----------------------------------------*\
|
||||
| Configure flow control |
|
||||
\*-----------------------------------------*/
|
||||
if(flow_control)
|
||||
{
|
||||
options.c_cflag |= CRTSCTS;
|
||||
}
|
||||
else
|
||||
{
|
||||
options.c_cflag &= ~CRTSCTS;
|
||||
}
|
||||
|
||||
/*-----------------------------------------*\
|
||||
| Configure additional parameters |
|
||||
\*-----------------------------------------*/
|
||||
options.c_lflag &= ~ICANON;
|
||||
options.c_lflag &= ~ECHO; // Disable echo
|
||||
options.c_lflag &= ~ECHOE; // Disable erasure
|
||||
options.c_lflag &= ~ECHONL; // Disable new-line echo
|
||||
options.c_lflag &= ~ISIG; // Disable interpretation of INTR, QUIT and SUSP
|
||||
|
||||
options.c_iflag &= ~(IXON | IXOFF | IXANY); // Turn off s/w flow ctrl
|
||||
options.c_ispeed = baud_rate;
|
||||
options.c_ospeed = baud_rate;
|
||||
options.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL); // Disable any special handling of received bytes
|
||||
|
||||
/*-----------------------------------------*\
|
||||
| Set the port configuration options |
|
||||
\*-----------------------------------------*/
|
||||
ioctl(file_descriptor, TCSETS2, &options);
|
||||
#endif
|
||||
|
||||
|
|
@ -122,6 +332,9 @@ bool serial_port::serial_open()
|
|||
| MacOS-specific code path for serial port opening |
|
||||
\*-----------------------------------------------------*/
|
||||
#ifdef __APPLE__
|
||||
/*-----------------------------------------*\
|
||||
| Open the port read/write with no delay |
|
||||
\*-----------------------------------------*/
|
||||
file_descriptor = open(port_name, O_RDWR | O_NOCTTY | O_NDELAY);
|
||||
|
||||
if(file_descriptor < 0)
|
||||
|
|
@ -129,53 +342,107 @@ bool serial_port::serial_open()
|
|||
return false;
|
||||
}
|
||||
|
||||
/*-----------------------------------------*\
|
||||
| Get the port configuration options |
|
||||
\*-----------------------------------------*/
|
||||
struct termios options;
|
||||
tcgetattr(file_descriptor, &options);
|
||||
switch(baud_rate)
|
||||
|
||||
/*-----------------------------------------*\
|
||||
| Configure parity |
|
||||
\*-----------------------------------------*/
|
||||
switch(parity)
|
||||
{
|
||||
case 9600:
|
||||
cfsetispeed(&options, B9600);
|
||||
cfsetospeed(&options, B9600);
|
||||
case SERIAL_PORT_PARITY_NONE:
|
||||
options.c_cflag &= ~PARENB;
|
||||
options.c_cflag &= ~PARODD;
|
||||
break;
|
||||
case 19200:
|
||||
cfsetispeed(&options, B19200);
|
||||
cfsetospeed(&options, B19200);
|
||||
|
||||
case SERIAL_PORT_PARITY_ODD:
|
||||
options.c_cflag |= PARENB;
|
||||
options.c_cflag |= PARODD;
|
||||
break;
|
||||
case 115200:
|
||||
cfsetispeed(&options, B115200);
|
||||
cfsetospeed(&options, B115200);
|
||||
break;
|
||||
case 38400:
|
||||
cfsetispeed(&options, B38400);
|
||||
cfsetospeed(&options, B38400);
|
||||
break;
|
||||
case 57600:
|
||||
cfsetispeed(&options, B57600);
|
||||
cfsetospeed(&options, B57600);
|
||||
break;
|
||||
default:
|
||||
cfsetispeed(&options, B9600);
|
||||
cfsetospeed(&options, B9600);
|
||||
|
||||
case SERIAL_PORT_PARITY_EVEN:
|
||||
options.c_cflag |= PARENB;
|
||||
options.c_cflag &= ~PARODD;
|
||||
break;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Configure other settings |
|
||||
\*-----------------------------------------------------*/
|
||||
/*-----------------------------------------*\
|
||||
| Configure size |
|
||||
\*-----------------------------------------*/
|
||||
options.c_cflag &= ~CSIZE;
|
||||
|
||||
switch(size)
|
||||
{
|
||||
case SERIAL_PORT_SIZE_8:
|
||||
options.c_cflag |= CS8;
|
||||
break;
|
||||
|
||||
case SERIAL_PORT_SIZE_7:
|
||||
options.c_cflag |= CS7;
|
||||
break;
|
||||
|
||||
case SERIAL_PORT_SIZE_6:
|
||||
options.c_cflag |= CS6;
|
||||
break;
|
||||
|
||||
case SERIAL_PORT_SIZE_5:
|
||||
options.c_cflag |= CS5;
|
||||
break;
|
||||
}
|
||||
|
||||
/*-----------------------------------------*\
|
||||
| Configure stop bits |
|
||||
\*-----------------------------------------*/
|
||||
if(stop_bits == SERIAL_PORT_STOP_BITS_2)
|
||||
{
|
||||
options.c_cflag |= CSTOPB;
|
||||
}
|
||||
else
|
||||
{
|
||||
options.c_cflag &= ~CSTOPB;
|
||||
}
|
||||
|
||||
/*-----------------------------------------*\
|
||||
| Configure flow control |
|
||||
\*-----------------------------------------*/
|
||||
if(flow_control)
|
||||
{
|
||||
options.c_cflag |= CRTSCTS;
|
||||
}
|
||||
else
|
||||
{
|
||||
options.c_cflag &= ~CRTSCTS;
|
||||
}
|
||||
|
||||
/*-----------------------------------------*\
|
||||
| Configure additional parameters |
|
||||
\*-----------------------------------------*/
|
||||
options.c_lflag &= ~(ICANON | ISIG | ECHO);
|
||||
|
||||
options.c_iflag &= ~(INLCR | ICRNL);
|
||||
options.c_iflag |= IGNPAR | IGNBRK;
|
||||
|
||||
options.c_oflag &= ~(OPOST | ONLCR | OCRNL);
|
||||
options.c_cflag &= ~(PARENB | PARODD | CSTOPB | CSIZE | CRTSCTS);
|
||||
options.c_cflag |= CLOCAL | CREAD | CS8;
|
||||
options.c_lflag &= ~(ICANON | ISIG | ECHO);
|
||||
|
||||
options.c_cc[VTIME] = 1;
|
||||
options.c_cc[VMIN] = 0;
|
||||
|
||||
/*-----------------------------------------*\
|
||||
| Set the port configuration options |
|
||||
\*-----------------------------------------*/
|
||||
if(tcsetattr(file_descriptor, TCSANOW, &options) < 0)
|
||||
{
|
||||
close(file_descriptor);
|
||||
return false;
|
||||
}
|
||||
|
||||
/*-----------------------------------------*\
|
||||
| Configure baud rate |
|
||||
\*-----------------------------------------*/
|
||||
ioctl(file_descriptor, IOSSIOSPEED, &baud_rate);
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
|
|
@ -357,3 +624,85 @@ void serial_port::serial_flush_tx()
|
|||
tcflush(file_descriptor, TCOFLUSH);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| serial_break |
|
||||
\*---------------------------------------------------------*/
|
||||
void serial_port::serial_break()
|
||||
{
|
||||
/*-----------------------------------------------------*\
|
||||
| Windows-specific code path for serial break |
|
||||
\*-----------------------------------------------------*/
|
||||
#ifdef _WIN32
|
||||
SetCommBreak(file_descriptor);
|
||||
Sleep(1);
|
||||
ClearCommBreak(file_descriptor);
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Linux-specific code path for serial break |
|
||||
\*-----------------------------------------------------*/
|
||||
#ifdef __linux__
|
||||
//Send break for at least 1 ms
|
||||
ioctl(file_descriptor, TIOCSBRK);
|
||||
usleep(1000);
|
||||
ioctl(file_descriptor, TIOCCBRK);
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| MacOS-specific code path for serial break |
|
||||
\*-----------------------------------------------------*/
|
||||
#ifdef __APPLE__
|
||||
//Send break for at least 1 ms
|
||||
ioctl(file_descriptor, TIOCSBRK);
|
||||
usleep(1000);
|
||||
ioctl(file_descriptor, TIOCCBRK);
|
||||
#endif
|
||||
}
|
||||
|
||||
void serial_port::serial_set_rts(bool rts)
|
||||
{
|
||||
/*-----------------------------------------------------*\
|
||||
| Windows-specific code path for serial set RTS |
|
||||
\*-----------------------------------------------------*/
|
||||
#ifdef _WIN32
|
||||
if(rts)
|
||||
{
|
||||
EscapeCommFunction(file_descriptor, SETRTS);
|
||||
}
|
||||
else
|
||||
{
|
||||
EscapeCommFunction(file_descriptor, CLRRTS);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Linux-specific code path for serial set RTS |
|
||||
\*-----------------------------------------------------*/
|
||||
#ifdef __linux__
|
||||
const int RTSFLAG = TIOCM_RTS;
|
||||
if(rts)
|
||||
{
|
||||
ioctl(file_descriptor, TIOCMBIS, &RTSFLAG);
|
||||
}
|
||||
else
|
||||
{
|
||||
ioctl(file_descriptor, TIOCMBIC, &RTSFLAG);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| MacOS-specific code path for serial set RTS |
|
||||
\*-----------------------------------------------------*/
|
||||
#ifdef __APPLE__
|
||||
const int RTSFLAG = TIOCM_RTS;
|
||||
if(rts)
|
||||
{
|
||||
ioctl(file_descriptor, TIOCMBIS, &RTSFLAG);
|
||||
}
|
||||
else
|
||||
{
|
||||
ioctl(file_descriptor, TIOCMBIC, &RTSFLAG);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue