kopia lustrzana https://github.com/xdsopl/qsstv
486 wiersze
14 KiB
C++
486 wiersze
14 KiB
C++
/**************************************************************************
|
|
* Copyright (C) 2000-2019 by Johan Maes *
|
|
* on4qz@telenet.be *
|
|
* http://users.telenet.be/on4qz *
|
|
* *
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
* it under the terms of the GNU General Public License as published by *
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
* (at your option) any later version. *
|
|
* *
|
|
* 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., *
|
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
|
***************************************************************************/
|
|
#include "rigcontrol.h"
|
|
#include "appglobal.h"
|
|
#include <QSplashScreen>
|
|
#include <QApplication>
|
|
#include <sys/ioctl.h>
|
|
#include <unistd.h>
|
|
#include <fcntl.h>
|
|
#include "mainwindow.h"
|
|
#include <QMessageBox>
|
|
#include "txwidget.h"
|
|
#include "configparams.h"
|
|
#include "dispatcher.h"
|
|
|
|
|
|
#define MAXCONFLEN 128
|
|
|
|
|
|
QList<const rig_caps *> capsList;
|
|
bool radiolistLoaded=false;
|
|
|
|
|
|
|
|
|
|
int collect(const rig_caps *caps,rig_ptr_t)
|
|
{
|
|
capsList.append(caps);
|
|
return 1;
|
|
}
|
|
|
|
rigControl::rigControl(int radioIndex)
|
|
{
|
|
rigControlEnabled=false;
|
|
catParams.configLabel=QString("radio%1").arg(radioIndex);
|
|
rig_set_debug(RIG_DEBUG_NONE);
|
|
getRadioList();
|
|
serialP=0;
|
|
lastFrequency=0.0;
|
|
xmlModes<<"USB"<<"LSB"<<"FM"<<"AM";
|
|
}
|
|
|
|
rigControl::~rigControl()
|
|
{
|
|
rig_close(my_rig); /* close port */
|
|
rig_cleanup(my_rig); /* if you care about memory */
|
|
}
|
|
|
|
bool rigControl::init()
|
|
{
|
|
int retcode;
|
|
if(!catParams.enableCAT) return false;
|
|
|
|
catParams.radioModelNumber=getModelNumber(getRadioModelIndex());
|
|
my_rig = rig_init(catParams.radioModelNumber);
|
|
if(!my_rig)
|
|
{
|
|
addToLogDebug(QString("Error in connection using radio model %1").arg(catParams.radioModel),LOGALL);
|
|
initError=QString("Error in connection using radio model %1").arg(catParams.radioModel);
|
|
return false;
|
|
}
|
|
|
|
if(QString(my_rig->caps->mfg_name)=="Icom")
|
|
{
|
|
if(!catParams.civAddress.isEmpty())
|
|
{
|
|
rig_set_conf(my_rig, rig_token_lookup(my_rig, "civaddr"), catParams.civAddress.toLatin1());
|
|
}
|
|
}
|
|
if(!catParams.serialPort.isEmpty())
|
|
{
|
|
strncpy(my_rig->state.rigport.pathname,(const char *)catParams.serialPort.toLatin1().data(),FILPATHLEN);
|
|
}
|
|
// strncpy(my_rig->state.pttport.pathname,(const char *)catParams.serialPort.toLatin1().data(),FILPATHLEN);
|
|
my_rig->state.rigport.parm.serial.rate = catParams.baudrate;
|
|
my_rig->state.rigport.parm.serial.data_bits=catParams.databits;
|
|
my_rig->state.rigport.parm.serial.stop_bits=catParams.stopbits;
|
|
if(catParams.parity=="Even") my_rig->state.rigport.parm.serial.parity= RIG_PARITY_EVEN;
|
|
else if (catParams.parity=="Odd") my_rig->state.rigport.parm.serial.parity = RIG_PARITY_ODD;
|
|
else my_rig->state.rigport.parm.serial.parity = RIG_PARITY_NONE;
|
|
if(catParams.handshake=="XOn/Xoff") my_rig->state.rigport.parm.serial.handshake = RIG_HANDSHAKE_XONXOFF;
|
|
if(catParams.handshake=="Hardware") my_rig->state.rigport.parm.serial.handshake = RIG_HANDSHAKE_HARDWARE;
|
|
else my_rig->state.rigport.parm.serial.handshake = RIG_HANDSHAKE_NONE;
|
|
my_rig->state.pttport.type.ptt = catParams.pttType;
|
|
|
|
addToLog(QString("rigcontrol:init rigport.pathname: %1").arg(my_rig->state.rigport.pathname),LOGRIGCTRL);
|
|
retcode = rig_open(my_rig);
|
|
if (retcode != RIG_OK )
|
|
{
|
|
addToLogDebug(QString("CAT Error: %1").arg(QString(rigerror(retcode))),LOGALL);
|
|
initError=QString("CAT Error: %1").arg(QString(rigerror(retcode)));
|
|
return false;
|
|
}
|
|
addToLog("rigcontroller successfully opened",LOGRIGCTRL);
|
|
rigControlEnabled=true;
|
|
|
|
|
|
|
|
// int verbose=0;
|
|
// rig_set_debug(verbose<2 ? RIG_DEBUG_NONE: (rig_debug_level_e)verbose);
|
|
// rig_debug(RIG_DEBUG_VERBOSE, "rigctl, %s\n", hamlib_version);
|
|
// test if we can contact the tranceiver
|
|
|
|
canSetFreq=(my_rig->caps->set_freq != NULL);
|
|
canGetFreq=(my_rig->caps->get_freq != NULL);
|
|
canSetMode=(my_rig->caps->set_mode != NULL);
|
|
canGetMode=(my_rig->caps->get_mode != NULL);
|
|
canSetPTT=(my_rig->caps->set_ptt != NULL);
|
|
canGetPTT=(my_rig->caps->get_ptt != NULL);
|
|
|
|
|
|
double fr;
|
|
if(!getFrequency(fr))
|
|
{
|
|
// rigControlEnabled=false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool rigControl::getFrequency(double &frequency)
|
|
{
|
|
int retcode;
|
|
if(catParams.enableXMLRPC)
|
|
{
|
|
frequency=xmlIntfPtr->getFrequency();
|
|
return true;
|
|
}
|
|
|
|
if(!rigControlEnabled || !canGetFreq) return false;
|
|
retcode = rig_get_freq(my_rig, RIG_VFO_CURR, &frequency);
|
|
for(int i=0;i<RIGCMDTRIES;i++)
|
|
{
|
|
retcode = rig_get_freq(my_rig, RIG_VFO_CURR, &frequency);
|
|
if (retcode==RIG_OK)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
// errorMessage(retcode,"getFrequency");
|
|
frequency=lastFrequency;
|
|
return false;
|
|
|
|
}
|
|
|
|
bool rigControl::setFrequency(double frequency)
|
|
{
|
|
int retcode=-1;
|
|
if(catParams.enableXMLRPC)
|
|
{
|
|
xmlIntfPtr->setFrequency(frequency);
|
|
return true;
|
|
}
|
|
if(!rigControlEnabled || !canSetFreq) return false;
|
|
// retcode = rig_set_vfo(my_rig, RIG_VFO_CURR);
|
|
// if (retcode != RIG_OK ) {errorMessage(retcode,"setVFO"); return false; }
|
|
|
|
for(int i=0;i<RIGCMDTRIES;i++)
|
|
{
|
|
retcode = rig_set_freq(my_rig, RIG_VFO_CURR, frequency);
|
|
if (retcode==RIG_OK)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
errorMessage(retcode,"setFrequency");
|
|
return false;
|
|
}
|
|
|
|
void rigControl::disable()
|
|
{
|
|
if(rigControlEnabled)
|
|
{
|
|
rig_close(my_rig); /* close port */
|
|
rig_cleanup(my_rig);
|
|
rigControlEnabled=false;
|
|
}
|
|
}
|
|
|
|
bool rigControl::getMode(QString &mode)
|
|
{
|
|
if(catParams.enableXMLRPC)
|
|
{
|
|
mode =xmlIntfPtr->getMode();
|
|
return true;
|
|
}
|
|
|
|
rmode_t rmode;
|
|
pbwidth_t width;
|
|
int retcode;
|
|
if(!rigControlEnabled || !canGetMode) return false;
|
|
|
|
for(int i=0;i<RIGCMDTRIES;i++)
|
|
{
|
|
retcode = rig_get_mode(my_rig, RIG_VFO_CURR, &rmode, &width);
|
|
if (retcode==RIG_OK)
|
|
{
|
|
mode=QString(rig_strrmode(rmode));
|
|
return true;
|
|
}
|
|
}
|
|
errorMessage(retcode,"getMode");
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
bool rigControl::setMode(QString mode,QString passBand)
|
|
{
|
|
QString orgMode;
|
|
int pb;
|
|
int i;
|
|
int pos=-1;
|
|
if(catParams.enableXMLRPC)
|
|
{
|
|
orgMode=xmlIntfPtr->getMode();
|
|
for(i=0;i<xmlModes.count();i++)
|
|
{
|
|
pos=orgMode.indexOf(xmlModes.at(i),Qt::CaseInsensitive);
|
|
if(pos>=0)
|
|
{
|
|
orgMode.replace(xmlModes.at(i),mode);
|
|
break;
|
|
}
|
|
}
|
|
if(pos>=0) xmlIntfPtr->setMode(orgMode);
|
|
return true;
|
|
}
|
|
|
|
rmode_t rmode=rig_parse_mode(mode.toLatin1().data());
|
|
if(passBand=="Narrow")
|
|
{
|
|
pb=rig_passband_narrow(my_rig,rmode);
|
|
}
|
|
else if(passBand=="Wide")
|
|
{
|
|
pb=rig_passband_wide(my_rig,rmode);
|
|
}
|
|
else
|
|
{
|
|
pb=rig_passband_normal(my_rig,rmode);
|
|
}
|
|
int retcode;
|
|
if(!rigControlEnabled || !canSetMode) return false;
|
|
|
|
for(int i=0;i<RIGCMDTRIES;i++)
|
|
{
|
|
retcode = rig_set_mode(my_rig, RIG_VFO_CURR, rmode, pb);
|
|
if (retcode==RIG_OK)
|
|
{
|
|
mode=QString(rig_strrmode(rmode));
|
|
return true;
|
|
}
|
|
}
|
|
errorMessage(retcode,"setMode");
|
|
return false;
|
|
}
|
|
|
|
|
|
bool rigControl::setPTT(bool on)
|
|
{
|
|
int retcode;
|
|
ptt_t ptt;
|
|
/* Hamlib will fall back to RIG_PTT_ON if RIG_PTT_ON_DATA is not available in current hamlib configuration */
|
|
if(on) ptt=RIG_PTT_ON_DATA; else ptt=RIG_PTT_OFF;
|
|
if(!rigControlEnabled || !canSetPTT) return false;
|
|
|
|
for(int i=0;i<RIGCMDTRIES;i++)
|
|
{
|
|
retcode = rig_set_ptt (my_rig, RIG_VFO_CURR,ptt);
|
|
if (retcode==RIG_OK)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
errorMessage(retcode,"setPTT");
|
|
return false;
|
|
}
|
|
|
|
|
|
|
|
void rigControl::errorMessage(int errorCode,QString command)
|
|
{
|
|
displayMBoxEvent *stmb;
|
|
stmb= new displayMBoxEvent("Cat interface",QString("Error in connection: %1\n%2").arg(QString(rigerror(errorCode))).arg(command));
|
|
QApplication::postEvent( dispatcherPtr, stmb );
|
|
|
|
// QMessageBox::information(0,"Cat interface",QString("Error in connection: %1\n%2").arg(QString(rigerror(errorCode))).arg(command));
|
|
}
|
|
|
|
void rigControl::getRadioList()
|
|
{
|
|
if(!radiolistLoaded)
|
|
{
|
|
capsList.clear();
|
|
rig_load_all_backends();
|
|
rig_list_foreach(collect,0);
|
|
std::sort(capsList.begin(),capsList.end(),model_Sort);
|
|
radiolistLoaded=true;
|
|
}
|
|
}
|
|
|
|
bool rigControl::getRadioList(QComboBox *cb)
|
|
{
|
|
int i;
|
|
if(capsList.count()==0) return false;
|
|
QStringList sl;
|
|
for (i=0;i<capsList.count();i++)
|
|
{
|
|
QString t;
|
|
t= QString::number(capsList.at(i)->rig_model);
|
|
t=t.rightJustified(5,' ')+" ";
|
|
t+= capsList.at(i)->mfg_name;
|
|
t+=",";
|
|
t+=capsList.at(i)->model_name;
|
|
sl << t;
|
|
}
|
|
cb->addItems(sl);
|
|
return true;
|
|
}
|
|
|
|
int rigControl::getModelNumber(int idx)
|
|
{
|
|
if(idx<0) return 0;
|
|
return capsList.at(idx)->rig_model;
|
|
}
|
|
|
|
int rigControl::getRadioModelIndex()
|
|
{
|
|
int i;
|
|
QString t=catParams.radioModel;
|
|
t=t.remove(0,5);
|
|
t=t.simplified();
|
|
QStringList sl=t.split(",");
|
|
if(sl.count()==1) sl.append("");
|
|
for(i=0;i<capsList.count();i++)
|
|
{
|
|
if((capsList.at(i)->mfg_name==sl.at(0)) && (capsList.at(i)->model_name==sl.at(1)))
|
|
{
|
|
return i;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
bool model_Sort(const rig_caps *caps1,const rig_caps *caps2)
|
|
{
|
|
if(caps1->mfg_name==caps2->mfg_name)
|
|
{
|
|
if (QString::compare(caps1->model_name,caps2->model_name)<0) return true;
|
|
return false;
|
|
}
|
|
if (QString::compare(caps1->mfg_name,caps2->mfg_name)<0) return true;
|
|
return false;
|
|
}
|
|
|
|
void rigControl::activatePTT(bool b)
|
|
{
|
|
int modemlines;
|
|
if(catParams.enableSerialPTT)
|
|
{
|
|
if (catParams.pttSerialPort.isEmpty()) return;
|
|
if(serialP==0)
|
|
{
|
|
serialP=::open(catParams.pttSerialPort.toLatin1().data(),O_RDWR);
|
|
if (serialP<=0)
|
|
{
|
|
QMessageBox::warning(txWidgetPtr,"Serial Port Error",
|
|
QString("Unable to open serial port %1\ncheck Options->Configuration\n"
|
|
"make sure that you have read/write permission\nIf you do not have a serial port,\n"
|
|
"then disable -Serial PTT- option in the configuration").arg(catParams.pttSerialPort) ,
|
|
QMessageBox::Ok,0 );
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
ioctl(serialP,TIOCMGET,&modemlines);
|
|
if(catParams.activeDTR) modemlines &= ~TIOCM_DTR;
|
|
if(catParams.activeRTS)modemlines &= ~TIOCM_RTS;
|
|
if(catParams.nactiveDTR) modemlines |= ~TIOCM_DTR;
|
|
if(catParams.nactiveRTS)modemlines |= ~TIOCM_RTS;
|
|
ioctl(serialP,TIOCMSET,&modemlines);
|
|
}
|
|
}
|
|
if(serialP>0)
|
|
{
|
|
if(b)
|
|
{
|
|
ioctl(serialP,TIOCMGET,&modemlines);
|
|
if(catParams.activeDTR) modemlines |= TIOCM_DTR;
|
|
if(catParams.activeRTS)modemlines |= TIOCM_RTS;
|
|
if(catParams.nactiveDTR) modemlines &= ~TIOCM_DTR;
|
|
if(catParams.nactiveRTS)modemlines &= ~TIOCM_RTS;
|
|
ioctl(serialP,TIOCMSET,&modemlines);
|
|
//ioctl(serial,TIOCMBIS,&t);
|
|
}
|
|
else
|
|
{
|
|
ioctl(serialP,TIOCMGET,&modemlines);
|
|
if(catParams.activeDTR) modemlines &= ~TIOCM_DTR;
|
|
if(catParams.activeRTS) modemlines &= ~TIOCM_RTS;
|
|
if(catParams.nactiveDTR) modemlines |= ~TIOCM_DTR;
|
|
if(catParams.nactiveRTS)modemlines |= ~TIOCM_RTS;
|
|
ioctl(serialP,TIOCMSET,&modemlines);
|
|
// ioctl(serial,TIOCMBIC,&t);
|
|
|
|
}
|
|
}
|
|
}
|
|
else if(catParams.enableXMLRPC)
|
|
{
|
|
xmlIntfPtr->activatePTT(b);
|
|
}
|
|
else rigControllerPtr->setPTT(b); // does nothing if rigController is disabled
|
|
mainWindowPtr->setPTT(b);
|
|
if(b)
|
|
{
|
|
addToLog("dispatcher: PTT activated",LOGDISPATCH);
|
|
}
|
|
else
|
|
{
|
|
addToLog("dispatcher: PTT deactivated",LOGDISPATCH);
|
|
}
|
|
}
|
|
|
|
|
|
int rigControl::rawCommand(QByteArray ba)
|
|
{
|
|
int i;
|
|
bool result;
|
|
char rxBuffer[100];
|
|
|
|
QString command="w ";
|
|
QByteArray cmdBa;
|
|
if(!rigControlEnabled) return 0;
|
|
struct rig_state *rs;
|
|
rs = &my_rig->state;
|
|
// check if backend via rigctld
|
|
if(catParams.radioModelNumber==2)
|
|
{
|
|
// we need to send this as a command string
|
|
if(additionalCommandHex)
|
|
{
|
|
for(i=0;i<ba.count();i++)
|
|
{
|
|
|
|
command+="\\0x";
|
|
command+=QString::number((unsigned char)ba.at(i),16);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
command+=ba;
|
|
}
|
|
|
|
command+="\n";
|
|
cmdBa=command.toLatin1();
|
|
result=write_block(&rs->rigport,cmdBa.constData(), cmdBa.count());
|
|
|
|
}
|
|
else
|
|
{
|
|
result=write_block(&rs->rigport,ba.constData(), ba.count());
|
|
}
|
|
read_block(&rs->rigport,rxBuffer,99);
|
|
return result;
|
|
|
|
}
|