Added support for various spectrum sizes and rig capability support.

wfview has been tested with the following Icom radios over USB port:
IC-7300, IC-7610, IC-7851 (and IC-7850), and IC-9700. It likely works
fine with the IC-705 as well. At this time, the rig's CIV address must
be changed in the preference file to indicate the rig you are using, and
this must be in integer, not hex.
merge-requests/1/head
Elliott Liggett 2021-01-24 16:16:38 -08:00
rodzic eee5f6e31f
commit 655ea0ac0e
6 zmienionych plików z 251 dodań i 30 usunięć

Wyświetl plik

@ -37,6 +37,8 @@ rigCommander::rigCommander(unsigned char rigCivAddr, QString rigSerialPort, quin
civAddr = rigCivAddr; // address of the radio. Decimal is 148.
setCIVAddr(civAddr);
usingNativeLAN = false; // TODO: set to true if we are connected over ethernet to the rig
spectSeqMax = 0; // this is now set after rig ID determined
//compCivAddr = 0xE1;
//payloadPrefix = QByteArray("\xFE\xFE\x94\xE0");
payloadPrefix = QByteArray("\xFE\xFE");
@ -533,6 +535,10 @@ void rigCommander::parseCommand()
// qDebug() << "Have rig ID: " << (unsigned int)payloadIn[2];
// printHex(payloadIn, false, true);
model = determineRadioModel(payloadIn[2]);
determineRigCaps();
qDebug() << "Have rig ID: decimal: " << (unsigned int)model;
break;
case '\x26':
if((int)payloadIn[1] == 0)
@ -794,7 +800,6 @@ void rigCommander::parseDetailedRegisters1A05()
void rigCommander::parseWFData()
{
float freqSpan = 0.0;
switch(payloadIn[1])
{
case 0:
@ -846,8 +851,85 @@ void rigCommander::parseWFData()
}
}
void rigCommander::determineRigCaps()
{
//TODO: Add if(usingNativeLAN) condition
//TODO: Determine available bands (low priority, rig will reject out of band requests anyway)
switch(model){
case model7300:
rigCaps.hasSpectrum = true;
rigCaps.spectSeqMax = 11;
rigCaps.spectAmpMax = 160;
rigCaps.spectLenMax = 475;
rigCaps.hasLan = false;
rigCaps.hasEthernet = false;
rigCaps.hasWiFi = false;
break;
case model9700:
rigCaps.hasSpectrum = true;
rigCaps.spectSeqMax = 11;
rigCaps.spectAmpMax = 160;
rigCaps.spectLenMax = 475;
rigCaps.hasLan = true;
rigCaps.hasEthernet = true;
rigCaps.hasWiFi = false;
break;
case model7610:
rigCaps.hasSpectrum = true;
rigCaps.spectSeqMax = 15;
rigCaps.spectAmpMax = 200;
rigCaps.spectLenMax = 689;
rigCaps.hasLan = true;
rigCaps.hasEthernet = true;
rigCaps.hasWiFi = false;
break;
case model7850:
rigCaps.hasSpectrum = true;
rigCaps.spectSeqMax = 15;
rigCaps.spectAmpMax = 136;
rigCaps.spectLenMax = 689;
rigCaps.hasLan = true;
rigCaps.hasEthernet = true;
rigCaps.hasWiFi = false;
break;
case model705:
rigCaps.hasSpectrum = true;
rigCaps.spectSeqMax = 11;
rigCaps.spectAmpMax = 160;
rigCaps.spectLenMax = 475;
rigCaps.hasLan = true;
rigCaps.hasEthernet = false;
rigCaps.hasWiFi = true;
break;
default:
rigCaps.hasSpectrum = false;
rigCaps.spectSeqMax = 0;
rigCaps.spectAmpMax = 0;
rigCaps.spectLenMax = 0;
rigCaps.hasLan = false;
rigCaps.hasEthernet = false;
rigCaps.hasWiFi = false;
break;
}
haveRigCaps = true;
emit haveRigID(rigCaps);
}
void rigCommander::parseSpectrum()
{
if(!haveRigCaps)
{
qDebug() << "Spectrum received in rigCommander, but rigID is incomplete.";
return;
}
if(rigCaps.spectSeqMax == 0)
{
// there is a chance this will happen with rigs that support spectrum. Once our RigID query returns, we will parse correctly.
qDebug() << "Warning: Spectrum sequence max was zero, yet spectrum was received.";
return;
}
// Here is what to expect:
// payloadIn[00] = '\x27';
// payloadIn[01] = '\x00';
@ -906,16 +988,16 @@ void rigCommander::parseSpectrum()
spectrumStartFreq -= spectrumEndFreq;
spectrumEndFreq = spectrumStartFreq + 2*(spectrumEndFreq);
}
} else if ((sequence > 1) && (sequence < 11))
} else if ((sequence > 1) && (sequence < rigCaps.spectSeqMax))
{
// spectrum from index 05 to index 54, length is 55 per segment. Length is 56 total. Pixel data is 50 pixels.
// sequence numbers 2 through 10, 50 pixels each. Total after sequence 10 is 450 pixels.
payloadIn.chop(1);
spectrumLine.insert(spectrumLine.length(), payloadIn.right(payloadIn.length() - 5)); // write over the FD, last one doesn't, oh well.
//qDebug() << "sequence: " << sequence << "spec index: " << (sequence-2)*55 << " payloadPosition: " << payloadIn.length() - 5 << " payload length: " << payloadIn.length();
} else if (sequence == 11)
} else if (sequence == rigCaps.spectSeqMax)
{
// last spectrum, a little bit different (last 25 pixels). Total at end is 475 pixels.
// last spectrum, a little bit different (last 25 pixels). Total at end is 475 pixels (7300).
payloadIn.chop(1);
spectrumLine.insert(spectrumLine.length(), payloadIn.right(payloadIn.length() - 5));
//qDebug() << "sequence: " << sequence << " spec index: " << (sequence-2)*55 << " payloadPosition: " << payloadIn.length() - 5 << " payload length: " << payloadIn.length();

Wyświetl plik

@ -64,6 +64,7 @@ public slots:
signals:
void haveSpectrumData(QByteArray spectrum, double startFreq, double endFreq); // pass along data to UI
void haveRigID(rigCapabilities rigCaps);
void haveFrequency(double frequencyMhz);
void haveMode(QString mode);
void haveDataMode(bool dataModeEnabled);
@ -106,6 +107,7 @@ private:
void prepDataAndSend(QByteArray data);
void debugMe();
void printHex(const QByteArray &pdata, bool printVert, bool printHoriz);
void determineRigCaps();
commHandler * comm;
QByteArray payloadIn;
QByteArray echoPerfix;
@ -121,7 +123,14 @@ private:
double spectrumStartFreq;
double spectrumEndFreq;
struct rigCapabilities rigCaps;
bool haveRigCaps;
model_kind model;
quint8 spectSeqMax;
quint16 spectAmpMax;
quint16 spectLenMax;
bool usingNativeLAN; // indicates using OEM LAN connection (705,7610,9700,7850)
double frequencyMhz;
unsigned char civAddr; // 0x94 is default = 148decimal

Wyświetl plik

@ -1,5 +1,6 @@
#include "rigidentities.h"
// Copytight 2017-2020 Elliott H. Liggett
// Copytight 2017-2021 Elliott H. Liggett
model_kind determineRadioModel(unsigned char rigID)
{
@ -32,6 +33,12 @@ model_kind determineRadioModel(unsigned char rigID)
case model7850:
rig = model7850;
break;
case model9700:
rig = model9700;
break;
case model705:
rig = model705;
break;
default:
rig = modelUnknown;
break;
@ -39,3 +46,8 @@ model_kind determineRadioModel(unsigned char rigID)
return rig;
}

Wyświetl plik

@ -1,6 +1,8 @@
#ifndef RIGIDENTITIES_H
#define RIGIDENTITIES_H
#include <QtNumeric>
// Credit:
// http://www.docksideradio.com/Icom%20Radio%20Hex%20Addresses.htm
@ -15,12 +17,27 @@ enum model_kind {
model7700 = 0x74,
model7800 = 0x6A,
model7850 = 0x8E,
model9700 = 0xA2,
model705 = 0xA4,
modelUnknown = 0xFF
};
model_kind determineRadioModel(unsigned char rigID);
struct rigCapabilities {
//model_kind model;
bool hasLan; // OEM ethernet or wifi connection
bool hasEthernet;
bool hasWiFi;
bool hasSpectrum;
quint8 spectSeqMax;
quint16 spectAmpMax;
quint16 spectLenMax;
};
#endif // RIGIDENTITIES_H

Wyświetl plik

@ -20,6 +20,8 @@ wfmain::wfmain(QWidget *parent) :
setWindowTitle(QString("wfview"));
haveRigCaps = false;
ui->bandStkLastUsedBtn->setVisible(false);
ui->bandStkVoiceBtn->setVisible(false);
ui->bandStkDataBtn->setVisible(false);
@ -180,17 +182,17 @@ wfmain::wfmain(QWidget *parent) :
tracer->setBrush(Qt::green);
tracer->setSize(30);
spectWidth = 475; // fixed for now
wfLength = 160; // fixed for now
// spectWidth = 475; // fixed for now
// wfLength = 160; // fixed for now, time-length of waterfall
// Initialize before use!
// // Initialize before use!
QByteArray empty((int)spectWidth, '\x01');
spectrumPeaks = QByteArray( (int)spectWidth, '\x01' );
for(quint16 i=0; i<wfLength; i++)
{
wfimage.append(empty);
}
// QByteArray empty((int)spectWidth, '\x01');
// spectrumPeaks = QByteArray( (int)spectWidth, '\x01' );
// for(quint16 i=0; i<wfLength; i++)
// {
// wfimage.append(empty);
// }
// 0 1 2 3 4
modes << "LSB" << "USB" << "AM" << "CW" << "RTTY";
@ -225,6 +227,7 @@ wfmain::wfmain(QWidget *parent) :
connect(rig, SIGNAL(finished()), rigThread, SLOT(quit()));
rigThread->start();
qRegisterMetaType<rigCapabilities>();
connect(rig, SIGNAL(haveFrequency(double)), this, SLOT(receiveFreq(double)));
connect(this, SIGNAL(getFrequency()), rig, SLOT(getFrequency()));
@ -266,8 +269,9 @@ wfmain::wfmain(QWidget *parent) :
connect(this, SIGNAL(getATUStatus()), rig, SLOT(getATUStatus()));
connect(this, SIGNAL(getRigID()), rig, SLOT(getRigID()));
connect(rig, SIGNAL(haveATUStatus(unsigned char)), this, SLOT(receiveATUStatus(unsigned char)));
connect(rig, SIGNAL(haveRigID(rigCapabilities)), this, SLOT(receiveRigID(rigCapabilities)));
// Speech (emitted from IC-7300 speaker)
// Speech (emitted from rig speaker)
connect(this, SIGNAL(sayAll()), rig, SLOT(sayAll()));
connect(this, SIGNAL(sayFrequency()), rig, SLOT(sayFrequency()));
connect(this, SIGNAL(sayMode()), rig, SLOT(sayMode()));
@ -295,16 +299,20 @@ 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);
// 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);
@ -547,6 +555,43 @@ void wfmain::saveSettings()
settings.sync(); // Automatic, not needed (supposedly)
}
void wfmain::prepareWf()
{
// All this code gets moved in from the constructor of wfmain.
if(haveRigCaps)
{
// do things
spectWidth = rigCaps.spectLenMax; // was fixed at 475
wfLength = 160; // fixed for now, time-length of waterfall
// Initialize before use!
QByteArray empty((int)spectWidth, '\x01');
spectrumPeaks = QByteArray( (int)spectWidth, '\x01' );
for(quint16 i=0; i<wfLength; i++)
{
wfimage.append(empty);
}
// from line 305-313:
colorMap->data()->setValueRange(QCPRange(0, wfLength-1));
colorMap->data()->setKeyRange(QCPRange(0, spectWidth-1));
colorMap->setDataRange(QCPRange(0, rigCaps.spectAmpMax));
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);
} else {
qDebug() << "Cannot prepare WF view without rigCaps. Waiting on this.";
return;
}
}
// Key shortcuts (hotkeys)
@ -742,7 +787,7 @@ void wfmain::getInitialRigState()
// the polling interval is set at 100ms. Faster is possible but slower
// computers will glitch occassionally.
cmdOutQue.append(cmdGetRigID); // This may be used in the future.
cmdOutQue.append(cmdGetRigID);
cmdOutQue.append(cmdGetFreq);
cmdOutQue.append(cmdGetMode);
@ -759,6 +804,11 @@ void wfmain::getInitialRigState()
// get TX level
// get Scope reference Level
cmdOutQue.append(cmdNone);
cmdOutQue.append(cmdGetRigID);
cmdOutQue.append(cmdNone);
cmdOutQue.append(cmdGetRigID);
cmdOutQue.append(cmdDispEnable);
cmdOutQue.append(cmdSpecOn);
@ -962,9 +1012,35 @@ void wfmain::runDelayedCommand()
}
}
void wfmain::receiveRigID(rigCapabilities rigCaps)
{
// Note: We intentionally request rigID several times
// because without rigID, we can't do anything with the waterfall.
if(haveRigCaps)
{
return;
} else {
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;
this->rigCaps = rigCaps;
this->spectWidth = rigCaps.spectLenMax; // used once haveRigCaps is true.
haveRigCaps = true;
prepareWf();
// Adding these here because clearly at this point we have valid
// rig comms. In the future, we should establish comms and then
// do all the initial grabs. For now, this hack of adding them here and there:
cmdOutQue.append(cmdGetFreq);
cmdOutQue.append(cmdGetMode);
}
}
void wfmain::receiveFreq(double freqMhz)
{
//qDebug() << "Frequency: " << freqMhz;
//qDebug() << "HEY WE GOT A Frequency: " << freqMhz;
ui->freqLabel->setText(QString("%1").arg(freqMhz, 0, 'f'));
this->freqMhz = freqMhz;
this->knobFreqMhz = freqMhz;
@ -979,6 +1055,12 @@ void wfmain::receivePTTstatus(bool pttOn)
void wfmain::receiveSpectrumData(QByteArray spectrum, double startFreq, double endFreq)
{
if(!haveRigCaps)
{
qDebug() << "Spectrum received, but RigID incomplete.";
return;
}
if((startFreq != oldLowerFreq) || (endFreq != oldUpperFreq))
{
// If the frequency changed and we were drawing peaks, now is the time to clearn them
@ -996,9 +1078,14 @@ void wfmain::receiveSpectrumData(QByteArray spectrum, double startFreq, double e
//qDebug() << "start: " << startFreq << " end: " << endFreq;
quint16 specLen = spectrum.length();
//qDebug() << "Spectrum data received at UI! Length: " << specLen;
if(specLen != 475)
//if( (specLen != 475) || (specLen!=689) )
if( specLen != rigCaps.spectLenMax )
{
//qDebug () << "Unusual spectrum: length: " << specLen;
qDebug() << "-------------------------------------------";
qDebug() << "------ Unusual spectrum received, length: " << specLen;
qDebug() << "------ Expected spectrum length: " << rigCaps.spectLenMax;
qDebug() << "------ This should happen once at most. ";
return; // safe. Using these unusual length things is a problem.
}
@ -1208,7 +1295,11 @@ void wfmain::receiveDataModeStatus(bool dataEnabled)
void wfmain::on_clearPeakBtn_clicked()
{
spectrumPeaks = QByteArray( (int)spectWidth, '\x01' );
if(haveRigCaps)
{
spectrumPeaks = QByteArray( (int)spectWidth, '\x01' );
}
return;
}
void wfmain::on_drawPeakChk_clicked(bool checked)

Wyświetl plik

@ -8,11 +8,14 @@
#include <QTimer>
#include <QSettings>
#include <QShortcut>
#include <QMetaType>
#include "commhandler.h"
#include "rigcommander.h"
#include "freqmemory.h"
#include "rigidentities.h"
#include <qcustomplot.h>
#include <qserialportinfo.h>
@ -111,7 +114,7 @@ private slots:
void receiveAfGain(unsigned char level);
void receiveSql(unsigned char level);
void receiveATUStatus(unsigned char atustatus);
void receiveRigID(rigCapabilities rigCaps);
void handlePlotClick(QMouseEvent *);
void handlePlotDoubleClick(QMouseEvent *);
void handleWFClick(QMouseEvent *);
@ -240,6 +243,7 @@ private:
//commHandler *comm;
void setAppTheme(bool isDark);
void setPlotTheme(QCustomPlot *plot, bool isDark);
void prepareWf();
void getInitialRigState();
QWidget * theParent;
QStringList portList;
@ -366,10 +370,16 @@ private:
int oldFreqDialVal;
rigCapabilities rigCaps;
bool haveRigCaps;
void bandStackBtnClick();
bool waitingForBandStackRtn;
char bandStkBand;
char bandStkRegCode;
};
Q_DECLARE_METATYPE(struct rigCapabilities) ;
#endif // WFMAIN_H