diff --git a/ChangeLog b/ChangeLog index 12b3ccda..3d2c3d14 100644 --- a/ChangeLog +++ b/ChangeLog @@ -15754,3 +15754,7 @@ 2017-05-02 Fred Gleason * Fixed a bug that caused RDCartSlots to fail to rotate cuts when replaying a cart without a reload. +2017-05-03 Fred Gleason + * Added an 'RDMatrix::Modbus' element to the 'RDMatrix::Type enum. + * Implemented a Modbus TCP switcher driver in 'ripcd/modbus.cpp' and + 'ripcd/modbus.h'. diff --git a/docs/SWITCHERS.txt b/docs/SWITCHERS.txt index 1a12f688..f7d95f5e 100644 --- a/docs/SWITCHERS.txt +++ b/docs/SWITCHERS.txt @@ -24,6 +24,7 @@ LiveWire LWRP GPIO LiveWire Multicast GPIO Local Audio Adapter Logitek vGuest +Modbus TCP Quartz Electronics Type 1 Routing Protocol Ross NK Video Switchers (via SCP/A Serial Interface) Serial Port Modem Control Lines @@ -580,6 +581,19 @@ such as faders feeds, not just GPIO) are mapped to logical Rivendell GPIO lines by means of their Logitek Engine, Device and Buss numbers. +---------------------------------------------------------------------------- +Driver Name: Modbus TCP + +Supported RML Commands: + GPI Enable ('GE') + GPI Set ('GI') + +GENERAL NOTES: +This driver supports GPI devices that use the industry-standard Modbus TCP +protocol at TCP port 502. The device to be controlled should be configured +to use Modbus ID #1. For more information on Modbus, see http://www.modbus.org/. + + ---------------------------------------------------------------------------- Quartz Electronics Type 1 Routing Protocol diff --git a/lib/rdmatrix.cpp b/lib/rdmatrix.cpp index 2c5c8951..2941c8f9 100644 --- a/lib/rdmatrix.cpp +++ b/lib/rdmatrix.cpp @@ -66,7 +66,8 @@ bool __mx_primary_controls[RDMatrix::LastType][RDMatrix::LastControl]= {0,1,1,1,0,0,1,1,0,0,0,1,1,0,0,0,1,1,1,1,0,0,0,0,1,0,0,0,0}, // SAS 16000 {0,1,0,0,0,0,0,0,1,0,0,1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0}, // Ross NK/SCP {0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0}, // BT ADMS 44.22 - {0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0} // BT SS 4.1 MLR + {0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0}, // BT SS 4.1 MLR + {0,0,1,1,0,0,0,0,0,0,0,0,0,1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0} // Modbus }; bool __mx_backup_controls[RDMatrix::LastType][RDMatrix::LastControl]= { @@ -109,7 +110,8 @@ bool __mx_backup_controls[RDMatrix::LastType][RDMatrix::LastControl]= {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, // SAS 16000 {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, // ROSS NK/SCP {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, // BT ADMS 44.22 - {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} // BT SS 4.1 MLR + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, // BT SS 4.1 MLR + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} // Modbus }; int __mx_default_values[RDMatrix::LastType][RDMatrix::LastControl]= @@ -153,7 +155,8 @@ int __mx_default_values[RDMatrix::LastType][RDMatrix::LastControl]= {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0}, // SAS 16000 {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0}, // Ross NK/SCP {0,0,0,0,0,0,0,0,0,0,0,8,2,16,13,0,0,0,0,0,0,0,0,0,0,0,0,1,0}, // BT ADMS 44.22 - {0,0,0,0,0,0,0,0,0,0,0,4,1,8,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0} // BT SS 4.1 MLR + {0,0,0,0,0,0,0,0,0,0,0,4,1,8,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0}, // BT SS 4.1 MLR + {1,0,0,502,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0} // Modbus }; RDMatrix::RDMatrix(const QString &station,int matrix) @@ -717,6 +720,10 @@ QString RDMatrix::typeString(RDMatrix::Type type) return QString("BroadcastTools SS 4.1 MLR"); break; + case RDMatrix::Modbus: + return QString("Modbus TCP"); + break; + default: return QString("Unknown Type"); break; diff --git a/lib/rdmatrix.h b/lib/rdmatrix.h index 7be22d73..fa9866af 100644 --- a/lib/rdmatrix.h +++ b/lib/rdmatrix.h @@ -2,7 +2,7 @@ // // Abstract a Rivendell Switcher Matrix // -// (C) Copyright 2002-2016 Fred Gleason +// (C) Copyright 2002-2017 Fred Gleason // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License version 2 as @@ -38,7 +38,7 @@ class RDMatrix BtSrc16=24,Harlond=25,Acu1p=26,LiveWireMcastGpio=27,Am16=28, LiveWireLwrpGpio=29,BtSentinel4Web=30,BtGpi16=31,ModemLines=32, SoftwareAuthority=33,Sas16000=34,RossNkScp=35,BtAdms4422=36, - BtSs41Mlr=37,LastType=38}; + BtSs41Mlr=37,Modbus=38,LastType=39}; enum Endpoint {Input=0,Output=1}; enum Mode {Stereo=0,Left=1,Right=2}; enum VguestAttribute {VguestEngine=0,VguestDevice=1,VguestSurface=2, diff --git a/ripcd/Makefile.am b/ripcd/Makefile.am index e9c82a01..188132fb 100644 --- a/ripcd/Makefile.am +++ b/ripcd/Makefile.am @@ -57,6 +57,7 @@ dist_ripcd_SOURCES = acu1p.cpp acu1p.h\ local_gpio.cpp local_gpio.h\ local_macros.cpp maint_routines.cpp\ loaddrivers.cpp\ + modbus.cpp modbus.h\ modemlines.cpp modemlines.h\ quartz1.cpp quartz1.h\ ripcd.cpp ripcd.h globals.h\ @@ -100,6 +101,7 @@ nodist_ripcd_SOURCES = moc_am16.cpp\ moc_livewire_mcastgpio.cpp\ moc_local_audio.cpp\ moc_local_gpio.cpp\ + moc_modbus.cpp\ moc_modemlines.cpp\ moc_quartz1.cpp\ moc_ripcd.cpp\ diff --git a/ripcd/loaddrivers.cpp b/ripcd/loaddrivers.cpp index c1f91593..7a46f6e7 100644 --- a/ripcd/loaddrivers.cpp +++ b/ripcd/loaddrivers.cpp @@ -47,6 +47,7 @@ #include #include #include +#include #include #include #include @@ -165,6 +166,10 @@ bool MainObject::LoadSwitchDriver(int matrix_num) ripcd_switcher[matrix_num]=new VGuest(matrix,this); break; + case RDMatrix::Modbus: + ripcd_switcher[matrix_num]=new Modbus(matrix,this); + break; + case RDMatrix::ModemLines: ripcd_switcher[matrix_num]=new ModemLines(matrix,this); break; diff --git a/ripcd/modbus.cpp b/ripcd/modbus.cpp new file mode 100644 index 00000000..83c46ee6 --- /dev/null +++ b/ripcd/modbus.cpp @@ -0,0 +1,250 @@ +// modbus.cpp +// +// A Rivendell switcher driver for Modbus TCP +// +// (C) Copyright 2017 Fred Gleason +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as +// published by the Free Software Foundation. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public +// License along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#include + +#include "modbus.h" + +Modbus::Modbus(RDMatrix *matrix,QObject *parent) + : Switcher(matrix,parent) +{ + modbus_istate=0; + modbus_watchdog_active=false; + + modbus_gpis=matrix->gpis(); + modbus_input_bytes=modbus_gpis/8; + if((modbus_gpis%8)!=0) { + modbus_input_bytes++; + } + for(int i=0;igpos(); + modbus_ip_address=matrix->ipAddress(RDMatrix::Primary); + modbus_ip_port=matrix->ipPort(RDMatrix::Primary); + + modbus_socket=new QSocket(this); + connect(modbus_socket,SIGNAL(connected()),this,SLOT(connectedData())); + connect(modbus_socket,SIGNAL(readyRead()),this,SLOT(readyReadData())); + connect(modbus_socket,SIGNAL(error(int)),this,SLOT(errorData(int))); + modbus_socket->connectToHost(modbus_ip_address.toString(),modbus_ip_port); + + modbus_watchdog_timer=new QTimer(this); + connect(modbus_watchdog_timer,SIGNAL(timeout()),this,SLOT(watchdogData())); +} + + +Modbus::~Modbus() +{ + delete modbus_watchdog_timer; + delete modbus_socket; +} + + +RDMatrix::Type Modbus::type() +{ + return RDMatrix::Modbus; +} + + +unsigned Modbus::gpiQuantity() +{ + return modbus_gpis; +} + + +unsigned Modbus::gpoQuantity() +{ + return modbus_gpos; +} + + +bool Modbus::primaryTtyActive() +{ + return false; +} + + +bool Modbus::secondaryTtyActive() +{ + return false; +} + + +void Modbus::processCommand(RDMacro *cmd) +{ +} + + +void Modbus::connectedData() +{ + syslog(LOG_INFO, + "connection to Modbus device at %s:%u established", + (const char *)modbus_ip_address.toString(),0xffff&modbus_ip_port); + modbus_watchdog_active=false; + PollInputs(); +} + + +void Modbus::readyReadData() +{ + char data[1501]; + int n; + char byte; + uint16_t len; + // char id; + char count=0; + int base=0; + + while((n=modbus_socket->readBlock(data,1500))>0) { + for(int i=0;iclose(); + modbus_socket->connectToHost(modbus_ip_address.toString(),modbus_ip_port); +} + + +void Modbus::ProcessInputByte(char byte,int base) +{ + char mask=byte^modbus_input_states[base]; + for(int i=0;i<8;i++) { + if(((1<>8); // Quantity of Inputs + msg[11]=0xff&modbus_gpis; + + modbus_socket->writeBlock(msg,12); + modbus_watchdog_timer->stop(); + modbus_watchdog_timer->start(MODBUS_WATCHDOG_INTERVAL,true); + printf("HERE2\n"); +} diff --git a/ripcd/modbus.h b/ripcd/modbus.h new file mode 100644 index 00000000..e379219c --- /dev/null +++ b/ripcd/modbus.h @@ -0,0 +1,72 @@ +// modbus.h +// +// A Rivendell switcher driver for Modbus TCP +// +// (C) Copyright 2017 Fred Gleason +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as +// published by the Free Software Foundation. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public +// License along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#ifndef MODBUS_H +#define MODBUS_H + +#include + +#include +#include + +#include +#include +#include + +#include + +#define MODBUS_WATCHDOG_INTERVAL 1000 + +class Modbus : public Switcher +{ + Q_OBJECT + public: + Modbus(RDMatrix *matrix,QObject *parent=0); + ~Modbus(); + RDMatrix::Type type(); + unsigned gpiQuantity(); + unsigned gpoQuantity(); + bool primaryTtyActive(); + bool secondaryTtyActive(); + void processCommand(RDMacro *cmd); + + private slots: + void connectedData(); + void readyReadData(); + void errorData(int err); + void watchdogData(); + + private: + void ProcessInputByte(char byte,int base); + void PollInputs(); + int modbus_istate; + int modbus_input_bytes; + std::vector modbus_input_states; + QSocket *modbus_socket; + QTimer *modbus_watchdog_timer; + bool modbus_watchdog_active; + QHostAddress modbus_ip_address; + uint16_t modbus_ip_port; + int modbus_gpis; + int modbus_gpos; +}; + + +#endif // MODBUS_H