Enhanced code that finds radio serial ports. Added error reporting to

the user if serial port isn't opening. Added command-line arguments for
serial port (example: "-p /dev/ttyUSB0" or "--port /dev/ttyUSB0").
Cleaned up some of the debug messages. wfview also will now tell the
user what radio was found in the status bar of the main window.

Added the begininning of code to determine the waveform type (center or
fixed). rigcommander now knows which is which. The next step is to emit
a signal when this changes, which then causes the main window to check
or uncheck the box (without triggering any other code).

Added some TODO remarks on mode (DV, DD).

Added some command line arguments that are not used at this time for --
host and --civ.
merge-requests/1/head
Elliott Liggett 2021-02-02 01:05:59 -08:00
rodzic add5c0d3b2
commit 65f9a70ee9
8 zmienionych plików z 214 dodań i 64 usunięć

Wyświetl plik

@ -131,6 +131,7 @@ commHandler::~commHandler()
void commHandler::setupComm()
{
serialError = false;
port->setPortName(portName);
port->setBaudRate(baudrate);
port->setStopBits(QSerialPort::OneStop);// OneStop is other option
@ -264,6 +265,8 @@ void commHandler::openPort()
// debug?
qDebug() << "Could not open serial port " << portName << " , please restart.";
isConnected = false;
serialError = true;
emit haveSerialPortError(portName, "Could not open port. Please restart.");
return;
}

Wyświetl plik

@ -17,6 +17,7 @@ class commHandler : public QObject
public:
commHandler();
commHandler(QString portName, quint32 baudRate);
bool serialError;
~commHandler();
@ -30,6 +31,7 @@ signals:
void haveTextMessage(QString message); // status, debug only
void sendDataOutToPort(const QByteArray &writeData); // not used
void haveDataFromPort(QByteArray data); // emit this when we have data, connect to rigcommander
void haveSerialPortError(const QString port, const QString error);
private:
void setupComm();

Wyświetl plik

@ -1,7 +1,8 @@
#include "wfmain.h"
#include <QApplication>
#include <iostream>
// Copytight 2017-2020 Elliott H. Liggett
// Copytight 2017-2021 Elliott H. Liggett
int main(int argc, char *argv[])
@ -9,14 +10,70 @@ int main(int argc, char *argv[])
QApplication a(argc, argv);
//a.setStyle( "Fusion" );
a.setOrganizationName("eliggett");
a.setOrganizationDomain("nodomain");
a.setApplicationName("wfview");
QString serialPortCL;
QString hostCL;
QString civCL;
QString currentArg;
const QString helpText = QString("Usage: -p --port /dev/port, -h --host remotehostname, -c --civ 0xAddr"); // TODO...
for(int c=1; c<argc; c++)
{
//qDebug() << "Argc: " << c << " argument: " << argv[c];
currentArg = QString(argv[c]);
if((currentArg == "-p") || currentArg == "--port")
{
if(argc > c)
{
serialPortCL = argv[c+1];
c+=1;
}
} else if ((currentArg == "-h") || (currentArg == "--host"))
{
if(argc > c)
{
hostCL = argv[c+1];
c+=1;
}
} else if ((currentArg == "-c") || (currentArg == "--civ"))
{
if(argc > c)
{
civCL = argv[c+1];
c+=1;
}
} else if ((currentArg == "--help"))
{
std::cout << helpText.toStdString();
return 0;
} else {
std::cout << "Unrecognized option: " << currentArg.toStdString();
std::cout << helpText.toStdString();
return -1;
}
}
#ifdef QT_DEBUG
qDebug() << "SerialPortCL as set by parser: " << serialPortCL;
qDebug() << "remote host as set by parser: " << hostCL;
qDebug() << "CIV as set by parser: " << civCL;
#endif
a.setWheelScrollLines(1); // one line per wheel click
wfmain w;
wfmain w( serialPortCL, hostCL);
w.show();
return a.exec();
}

Wyświetl plik

@ -58,6 +58,7 @@ rigCommander::rigCommander(unsigned char rigCivAddr, QString rigSerialPort, quin
// lrwxrwxrwx 1 root root 13 Nov 24 21:43 pci-0000:00:12.0-usb-0:2.1:1.0-port0 -> ../../ttyUSB0
// comm = new commHandler("/dev/ttyUSB0");
this->rigSerialPort = rigSerialPort;
comm = new commHandler(rigSerialPort, rigBaudRate);
// data from the comm port to the program:
@ -66,8 +67,11 @@ rigCommander::rigCommander(unsigned char rigCivAddr, QString rigSerialPort, quin
// data from the program to the comm port:
connect(this, SIGNAL(dataForComm(QByteArray)), comm, SLOT(receiveDataFromUserToRig(QByteArray)));
connect(comm, SIGNAL(haveSerialPortError(QString,QString)), this, SLOT(handleSerialPortError(QString,QString)));
connect(this, SIGNAL(getMoreDebug()), comm, SLOT(debugThis()));
pttAllowed = true; // This is for developing, set to false for "safe" debugging. Set to true for deployment.
}
rigCommander::~rigCommander()
@ -77,7 +81,17 @@ rigCommander::~rigCommander()
void rigCommander::process()
{
// new thread enters here. Do nothing.
// new thread enters here. Do nothing but do check for errors.
if(comm->serialError)
{
emit haveSerialPortError(rigSerialPort, QString("Error from commhandler. Check serial port."));
}
}
void rigCommander::handleSerialPortError(const QString port, const QString errorText)
{
qDebug() << "Error using port " << port << " message: " << errorText;
emit haveSerialPortError(port, errorText);
}
void rigCommander::findRigs()
@ -469,7 +483,7 @@ void rigCommander::parseData(QByteArray dataInput)
//return;
}
incommingCIVAddr = data[03]; // track the CIV of the sender.
incomingCIVAddr = data[03]; // track the CIV of the sender.
switch(data[02])
{
// case civAddr: // can't have a variable here :-(
@ -888,10 +902,11 @@ void rigCommander::determineRigCaps()
rigCaps.model = model;
rigCaps.modelID = model; // may delete later
rigCaps.civ = incommingCIVAddr;
rigCaps.civ = incomingCIVAddr;
switch(model){
case model7300:
rigCaps.modelName = QString("IC-7300");
rigCaps.hasSpectrum = true;
rigCaps.spectSeqMax = 11;
rigCaps.spectAmpMax = 160;
@ -901,6 +916,7 @@ void rigCommander::determineRigCaps()
rigCaps.hasWiFi = false;
break;
case model9700:
rigCaps.modelName = QString("IC-9700");
rigCaps.hasSpectrum = true;
rigCaps.spectSeqMax = 11;
rigCaps.spectAmpMax = 160;
@ -910,6 +926,7 @@ void rigCommander::determineRigCaps()
rigCaps.hasWiFi = false;
break;
case model7610:
rigCaps.modelName = QString("IC-7610");
rigCaps.hasSpectrum = true;
rigCaps.spectSeqMax = 15;
rigCaps.spectAmpMax = 200;
@ -919,6 +936,7 @@ void rigCommander::determineRigCaps()
rigCaps.hasWiFi = false;
break;
case model7850:
rigCaps.modelName = QString("IC-785x");
rigCaps.hasSpectrum = true;
rigCaps.spectSeqMax = 15;
rigCaps.spectAmpMax = 136;
@ -928,6 +946,7 @@ void rigCommander::determineRigCaps()
rigCaps.hasWiFi = false;
break;
case model705:
rigCaps.modelName = QString("IC-705");
rigCaps.hasSpectrum = true;
rigCaps.spectSeqMax = 11;
rigCaps.spectAmpMax = 160;
@ -937,6 +956,7 @@ void rigCommander::determineRigCaps()
rigCaps.hasWiFi = true;
break;
default:
rigCaps.modelName = QString("IC-unknown");
rigCaps.hasSpectrum = false;
rigCaps.spectSeqMax = 0;
rigCaps.spectAmpMax = 0;
@ -952,14 +972,16 @@ void rigCommander::determineRigCaps()
{
lookingForRig = false;
foundRig = true;
#ifdef QT_DEBUG
qDebug() << "---Rig FOUND from broadcast query:";
this->civAddr = incommingCIVAddr; // Override and use immediately.
#endif
this->civAddr = incomingCIVAddr; // Override and use immediately.
payloadPrefix = QByteArray("\xFE\xFE");
payloadPrefix.append(civAddr);
payloadPrefix.append(compCivAddr);
// if there is a compile-time error, remove the hex printout prefix from below .
qDebug() << "Using incommingCIVAddr: (int): " << this->civAddr << " hex: " << hex << this->civAddr;
// if there is a compile-time error, remove the following line, the "hex" part is the issue:
qDebug() << "Using incomingCIVAddr: (int): " << this->civAddr << " hex: " << hex << this->civAddr;
emit discoveredRigID(rigCaps);
} else {
emit haveRigID(rigCaps);
@ -970,7 +992,9 @@ void rigCommander::parseSpectrum()
{
if(!haveRigCaps)
{
#ifdef QT_DEBUG
qDebug() << "Spectrum received in rigCommander, but rigID is incomplete.";
#endif
return;
}
if(rigCaps.spectSeqMax == 0)
@ -1014,6 +1038,14 @@ void rigCommander::parseSpectrum()
unsigned char sequence = bcdHexToDecimal(payloadIn[03]);
//unsigned char sequenceMax = bcdHexToDecimal(payloadIn[04]);
unsigned char scopeMode = bcdHexToDecimal(payloadIn[05]);
if(scopeMode != oldScopeMode)
{
//TODO:
// emit haveNewScopeMode(scopeMode);
oldScopeMode = scopeMode;
}
// unsigned char waveInfo = payloadIn[06]; // really just one byte?
//qDebug() << "Spectrum Data received: " << sequence << "/" << sequenceMax << " mode: " << scopeMode << " waveInfo: " << waveInfo << " length: " << payloadIn.length();
@ -1146,6 +1178,9 @@ void rigCommander::parseMode()
// USB:
//"INDEX: 00 01 02 03 "
//"DATA: 01 01 02 fd "
//TODO: D-Star DV and DD modes.
switch(payloadIn[01])
{
case '\x00':

Wyświetl plik

@ -59,6 +59,7 @@ public slots:
void findRigs();
void setCIVAddr(unsigned char civAddr);
void handleNewData(const QByteArray &data);
void handleSerialPortError(const QString port, const QString errorText);
void sayFrequency();
void sayMode();
void sayAll();
@ -68,6 +69,7 @@ signals:
void haveSpectrumData(QByteArray spectrum, double startFreq, double endFreq); // pass along data to UI
void haveRigID(rigCapabilities rigCaps);
void discoveredRigID(rigCapabilities rigCaps);
void haveSerialPortError(const QString port, const QString errorText);
void haveFrequency(double frequencyMhz);
void haveMode(QString mode);
void haveDataMode(bool dataModeEnabled);
@ -132,6 +134,7 @@ private:
quint8 spectSeqMax;
quint16 spectAmpMax;
quint16 spectLenMax;
unsigned char oldScopeMode;
bool usingNativeLAN; // indicates using OEM LAN connection (705,7610,9700,7850)
bool lookingForRig;
@ -139,10 +142,12 @@ private:
double frequencyMhz;
unsigned char civAddr; // IC-7300: 0x94 is default = 148decimal
unsigned char incommingCIVAddr; // place to store the incoming CIV.
unsigned char incomingCIVAddr; // place to store the incoming CIV.
//const unsigned char compCivAddr = 0xE1; // 0xE1 is new default, 0xE0 was before.
bool pttAllowed;
QString rigSerialPort;
QString serialPortError;
};

Wyświetl plik

@ -2,6 +2,7 @@
#define RIGIDENTITIES_H
#include <QtNumeric>
#include <QString>
// Credit:
// http://www.docksideradio.com/Icom%20Radio%20Hex%20Addresses.htm
@ -31,6 +32,8 @@ struct rigCapabilities {
quint8 civ;
quint8 modelID;
QString modelName;
bool hasLan; // OEM ethernet or wifi connection
bool hasEthernet;
bool hasWiFi;

Wyświetl plik

@ -7,7 +7,7 @@
// This code is copyright 2017-2020 Elliott H. Liggett
// All rights reserved
wfmain::wfmain(QWidget *parent) :
wfmain::wfmain(const QString serialPortCL, const QString hostCL, QWidget *parent ) :
QMainWindow(parent),
ui(new Ui::wfmain)
{
@ -20,6 +20,9 @@ wfmain::wfmain(QWidget *parent) :
setWindowTitle(QString("wfview"));
this->serialPortCL = serialPortCL;
this->hostCL = hostCL;
haveRigCaps = false;
ui->bandStkLastUsedBtn->setVisible(false);
@ -216,7 +219,7 @@ wfmain::wfmain(QWidget *parent) :
ui->afGainSlider->setSingleStep(100);
ui->statusBar->showMessage("Almost ready", 2000);
ui->statusBar->showMessage("Connecting to rig...", 1000);
delayedCommand = new QTimer(this);
delayedCommand->setInterval(250); // 250ms until we find rig civ and id, then 100ms.
@ -225,15 +228,6 @@ wfmain::wfmain(QWidget *parent) :
openRig();
// rig = new rigCommander(prefs.radioCIVAddr, serialPortRig, prefs.serialPortBaud);
// rigThread = new QThread(this);
// rig->moveToThread(rigThread);
// connect(rigThread, SIGNAL(started()), rig, SLOT(process()));
// connect(rig, SIGNAL(finished()), rigThread, SLOT(quit()));
// rigThread->start();
qRegisterMetaType<rigCapabilities>();
connect(rig, SIGNAL(haveFrequency(double)), this, SLOT(receiveFreq(double)));
@ -306,20 +300,7 @@ wfmain::wfmain(QWidget *parent) :
wf->addPlottable(colorMap);
#endif
//TRY moving to prepareWf():
colorScale = new QCPColorScale(wf);
// colorMap->data()->setValueRange(QCPRange(0, wfLength-1));
// colorMap->data()->setKeyRange(QCPRange(0, spectWidth-1));
// colorMap->setDataRange(QCPRange(0, 160));
// colorMap->setGradient(QCPColorGradient::gpJet); // TODO: Add preference
// colorMapData = new QCPColorMapData(spectWidth, wfLength, QCPRange(0, spectWidth-1), QCPRange(0, wfLength-1));
// colorMap->setData(colorMapData);
// spectRowCurrent = 0;
// wf->yAxis->setRangeReversed(true);
// wf->xAxis->setVisible(false);
// end TRY
ui->tabWidget->setCurrentIndex(0);
@ -332,10 +313,7 @@ wfmain::wfmain(QWidget *parent) :
ui->freqMhzLineEdit->setValidator( new QDoubleValidator(0, 100, 6, this));
// delayedCommand = new QTimer(this);
// delayedCommand->setInterval(100); // ms. 250 was fine. TODO: Find practical maximum with margin on pi
// delayedCommand->setSingleShot(true);
// connect(delayedCommand, SIGNAL(timeout()), this, SLOT(runDelayedCommand()));
;
pttTimer = new QTimer(this);
pttTimer->setInterval(180*1000); // 3 minute max transmit time in ms
@ -398,29 +376,68 @@ void wfmain::openRig()
// TODO: How do we know if the setting was loaded?
if(prefs.serialPortRadio == QString("auto"))
// TODO: Use these if they are found
#ifdef QT_DEBUG
if(!serialPortCL.isEmpty())
{
// Find the ICOM IC-7300.
qDebug() << "Searching for serial port...";
QDirIterator it("/dev/serial", QStringList() << "*IC-7300*", QDir::Files, QDirIterator::Subdirectories);
QDirIterator it97("/dev/serial", QStringList() << "*IC-9700*", QDir::Files, QDirIterator::Subdirectories);
while (it.hasNext())
qDebug() << it.next();
while(it97.hasNext())
qDebug() << it97.next();
// if (it.isEmpty()) // fail or default to ttyUSB0 if present
// iterator might not make sense
serialPortRig = it.filePath(); // first? last?
if(serialPortRig.isEmpty())
{
qDebug() << "Cannot find IC-7300 serial port. Trying /dev/ttyUSB0";
serialPortRig = QString("/dev/ttyUSB0");
}
// end finding the 7300 code
qDebug() << "Serial port specified by user: " << serialPortCL;
} else {
serialPortRig = prefs.serialPortRadio;
qDebug() << "Serial port not specified. ";
}
if(!hostCL.isEmpty())
{
qDebug() << "Remote host name specified by user: " << hostCL;
}
#endif
if( (prefs.serialPortRadio == QString("auto")) && (serialPortCL.isEmpty()))
{
// Find the ICOM
// qDebug() << "Searching for serial port...";
QDirIterator it73("/dev/serial", QStringList() << "*IC-7300*", QDir::Files, QDirIterator::Subdirectories);
QDirIterator it97("/dev/serial", QStringList() << "*IC-9700*A*", QDir::Files, QDirIterator::Subdirectories);
QDirIterator it785x("/dev/serial", QStringList() << "*IC-785*A*", QDir::Files, QDirIterator::Subdirectories);
QDirIterator it705("/dev/serial", QStringList() << "*IC-705*A", QDir::Files, QDirIterator::Subdirectories);
if(!it73.filePath().isEmpty())
{
// use
serialPortRig = it73.filePath(); // first
} else if(!it97.filePath().isEmpty())
{
// IC-9700 port
serialPortRig = it97.filePath();
} else if(!it785x.filePath().isEmpty())
{
// IC-785x port
serialPortRig = it785x.filePath();
} else if(!it705.filePath().isEmpty())
{
// IC-705
serialPortRig = it705.filePath();
} else {
//fall back:
qDebug() << "Could not find Icom serial port. Falling back to OS default. Use --port to specify, or modify preferences.";
#ifdef Q_OS_MAC
serialPortRig = QString("/dev/tty.SLAB_USBtoUART");
#endif
#ifdef Q_OS_LINUX
serialPortRig = QString("/dev/ttyUSB0");
#endif
#ifdef Q_OS_UNIX
serialPortRig = QString("/dev/ttyUSB0");
#endif
}
} else {
if(serialPortCL.isEmpty())
{
serialPortRig = prefs.serialPortRadio;
} else {
serialPortRig = serialPortCL;
}
}
// Here, the radioCIVAddr is being set from a default preference, whihc is for the 7300.
@ -433,14 +450,17 @@ void wfmain::openRig()
rig->moveToThread(rigThread);
connect(rigThread, SIGNAL(started()), rig, SLOT(process()));
connect(rig, SIGNAL(finished()), rigThread, SLOT(quit()));
connect(rig, SIGNAL(haveSerialPortError(QString,QString)), this, SLOT(receiveSerialPortError(QString,QString)));
rigThread->start();
connect(this, SIGNAL(getRigCIV()), rig, SLOT(findRigs()));
connect(rig, SIGNAL(discoveredRigID(rigCapabilities)), this, SLOT(receiveFoundRigID(rigCapabilities)));
ui->statusBar->showMessage(QString("Connecting to rig using serial port ").append(serialPortRig), 1000);
if(prefs.radioCIVAddr == 0)
{
// tell rigCommander to broadcast a request for all rig IDs.
qDebug() << "Beginning search from wfview for rigCIV (auto-detection broadcast)";
// qDebug() << "Beginning search from wfview for rigCIV (auto-detection broadcast)";
ui->statusBar->showMessage(QString("Searching CIV bus for connected radios."), 1000);
emit getRigCIV();
cmdOutQue.append(cmdGetRigCIV);
delayedCommand->start();
@ -456,13 +476,25 @@ void wfmain::receiveFoundRigID(rigCapabilities rigCaps)
{
// Entry point for unknown rig being identified at the start of the program.
//now we know what the rig ID is:
qDebug() << "In wfview, we now have a reply to our request for rig identity sent to CIV BROADCAST.";
//qDebug() << "In wfview, we now have a reply to our request for rig identity sent to CIV BROADCAST.";
delayedCommand->setInterval(100); // faster polling is ok now.
receiveRigID(rigCaps);
getInitialRigState();
QString message = QString("Found model: ").append(rigCaps.modelName);
ui->statusBar->showMessage(message, 1500);
return;
}
void wfmain::receiveSerialPortError(QString port, QString errorText)
{
qDebug() << "wfmain: received serial port error for port: " << port << " with message: " << errorText;
ui->statusBar->showMessage(QString("ERROR: using port ").append(port).append(": ").append(errorText), 10000);
// TODO: Dialog box, exit, etc
}
void wfmain::setDefPrefs()
{
@ -1120,11 +1152,14 @@ void wfmain::receiveRigID(rigCapabilities rigCaps)
{
return;
} else {
#ifdef QT_DEBUG
qDebug() << "Rig name: " << rigCaps.modelName;
qDebug() << "Has LAN capabilities: " << rigCaps.hasLan;
qDebug() << "Rig ID received into wfmain: spectLenMax: " << rigCaps.spectLenMax;
qDebug() << "Rig ID received into wfmain: spectAmpMax: " << rigCaps.spectAmpMax;
qDebug() << "Rig ID received into wfmain: spectSeqMax: " << rigCaps.spectSeqMax;
qDebug() << "Rig ID received into wfmain: hasSpectrum: " << rigCaps.hasSpectrum;
#endif
this->rigCaps = rigCaps;
this->spectWidth = rigCaps.spectLenMax; // used once haveRigCaps is true.
haveRigCaps = true;
@ -1156,7 +1191,9 @@ void wfmain::receiveSpectrumData(QByteArray spectrum, double startFreq, double e
{
if(!haveRigCaps)
{
#ifdef QT_DEBUG
qDebug() << "Spectrum received, but RigID incomplete.";
#endif
return;
}
@ -1181,10 +1218,12 @@ void wfmain::receiveSpectrumData(QByteArray spectrum, double startFreq, double e
if( specLen != rigCaps.spectLenMax )
{
#ifdef QT_DEBUG
qDebug() << "-------------------------------------------";
qDebug() << "------ Unusual spectrum received, length: " << specLen;
qDebug() << "------ Expected spectrum length: " << rigCaps.spectLenMax;
qDebug() << "------ This should happen once at most. ";
#endif
return; // safe. Using these unusual length things is a problem.
}
@ -1302,12 +1341,15 @@ void wfmain::handleWFScroll(QWheelEvent *we)
// .y() and is +/- 120.
// We will click the dial once for every 120 received.
//QPoint delta = we->angleDelta();
// TODO: Use other method, knob has too few positions to be useful for large steps.
int steps = we->angleDelta().y() / 120;
Qt::KeyboardModifiers key= we->modifiers();
if (key == Qt::ShiftModifier)
{
// TODO: Zoom
steps *=20;
} else if (key == Qt::ControlModifier)
{
steps *=10;

Wyświetl plik

@ -28,7 +28,9 @@ class wfmain : public QMainWindow
Q_OBJECT
public:
explicit wfmain(QWidget *parent = 0);
explicit wfmain(const QString serialPortCL, const QString hostCL, QWidget *parent = 0);
QString serialPortCL;
QString hostCL;
~wfmain();
signals:
@ -117,6 +119,7 @@ private slots:
void receiveATUStatus(unsigned char atustatus);
void receiveRigID(rigCapabilities rigCaps);
void receiveFoundRigID(rigCapabilities rigCaps);
void receiveSerialPortError(QString port, QString errorText);
void handlePlotClick(QMouseEvent *);
void handlePlotDoubleClick(QMouseEvent *);
void handleWFClick(QMouseEvent *);