From d800c3a5941d6f2252ab22f47bee451f2e5c6015 Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Wed, 24 May 2023 19:50:01 +0100 Subject: [PATCH] Lots of changes/fixes inc rewrite rigctld and move more commands. --- cachingqueue.cpp | 49 +- cachingqueue.h | 1 + commhandler.h | 1 - cwsender.cpp | 88 +- cwsender.h | 3 + cwsidetone.cpp | 6 +- cwsidetone.h | 3 +- repeatersetup.cpp | 43 +- repeatersetup.h | 6 +- rigcommander.cpp | 260 +++-- rigcommander.h | 12 +- rigcreator.cpp | 30 +- rigcreator.h | 4 + rigcreator.ui | 30 +- rigctld.cpp | 2329 +++++++++++++++++---------------------------- rigctld.h | 151 +-- rigidentities.h | 4 +- usbcontroller.cpp | 120 +-- usbcontroller.h | 3 - wfmain.cpp | 334 +++---- wfmain.h | 8 +- wfmain.ui | 19 +- wfviewtypes.h | 87 +- 23 files changed, 1555 insertions(+), 2036 deletions(-) diff --git a/cachingqueue.cpp b/cachingqueue.cpp index 494306f..3a9407b 100644 --- a/cachingqueue.cpp +++ b/cachingqueue.cpp @@ -70,16 +70,19 @@ void cachingQueue::run() prio = priorityLowest; } counter++; + QMutableMultiMapIterator itt(queue); + auto it = queue.find(prio); if (it != queue.end()) { auto item = it.value(); - emit haveCommand(item.type, item.command,item.param); - - it=queue.erase(it); - while (it.key()==prio) - it++; + it = queue.erase(it); + it = queue.end(); + //if (it != queue.end()) { + // while (it != queue.end() && it.key()==prio) + // it++; + //} // Add it back into the queue if (item.recurring) { queue.insert(it,prio,item); @@ -125,6 +128,7 @@ void cachingQueue::add(queuePriority prio ,queueItem item) } else { queue.insert(prio, item); updateCache(false,item.command,item.param); + // Update cache with sent data (will be replaced if found to be invalid.) if (item.recurring) qInfo() << "adding" << funcString[item.command] << "recurring" << item.recurring << "priority" << prio; } } @@ -218,15 +222,24 @@ void cachingQueue::receiveValue(funcs func, QVariant value) void cachingQueue::updateCache(bool reply, funcs func, QVariant value) { + /* if (func == funcFreqGet || func == funcFreqTR || func == funcSelectedFreq || func == funcUnselectedFreq) + func = funcVFOFrequency; // This is a composite function. + if (func == funcModeGet || func == funcModeTR || func == funcSelectedMode || func == funcUnselectedMode) + func = funcVFOMode; // This is a composite function. */ + // Mutex MUST be locked by the calling function. auto cv = cache.find(func); if (cv != cache.end()) { if (reply) { cv->reply = QDateTime::currentDateTime(); - cv->value = value; } else { cv->req = QDateTime::currentDateTime(); } + // If we are sending an actual value, update the cache with it + // Value will be replaced if invalid on next get() + if (value.isValid()) + cv->value = value; + return; } @@ -234,23 +247,33 @@ void cachingQueue::updateCache(bool reply, funcs func, QVariant value) c.command = func; if (reply) { c.reply = QDateTime::currentDateTime(); - c.value = value; } else { c.req = QDateTime::currentDateTime(); } + // If we are sending an actual value, update the cache with it + // Value will be replaced if invalid on next get() + if (value.isValid()) + c.value = value; cache.insert(func,c); } cacheItem cachingQueue::getCache(funcs func) { - QMutexLocker locker(&mutex); - auto it = cache.find(func); - if (it != cache.end()) - { - return it.value(); + cacheItem ret; + if (func != funcNone) { + QMutexLocker locker(&mutex); + auto it = cache.find(func); + if (it != cache.end()) + ret = cacheItem(*it); } - return cacheItem(); + // If the cache is more than 5-20 seconds old, re-request it as it may be stale (maybe make this a config option?) + // Using priorityhighest WILL slow down the S-Meter when a command intensive client is connected to rigctl + if (func != funcNone && (!ret.value.isValid() || ret.reply.addSecs(QRandomGenerator::global()->bounded(5,20)) <= QDateTime::currentDateTime())) { + //qInfo() << "No (or expired) cache found for" << funcString[func] << "requesting"; + add(priorityHighest,func); + } + return ret; } //Calling function MUST call unlockMutex() once finished with data diff --git a/cachingqueue.h b/cachingqueue.h index 198b3a2..2ece3bb 100644 --- a/cachingqueue.h +++ b/cachingqueue.h @@ -12,6 +12,7 @@ #include #include #include +#include #include "wfviewtypes.h" #include "rigidentities.h" diff --git a/commhandler.h b/commhandler.h index 1e8b972..b51fe4b 100644 --- a/commhandler.h +++ b/commhandler.h @@ -90,7 +90,6 @@ private: quint8 spectrumDivisionMax; quint8 spectrumCenterOrFixed; quint8 spectrumInformation; - quint8 spectrumOutOfRange; quint8 lastSpectrum = 0; QTime lastDataReceived; }; diff --git a/cwsender.cpp b/cwsender.cpp index 469fec2..64c2382 100644 --- a/cwsender.cpp +++ b/cwsender.cpp @@ -18,6 +18,7 @@ cwSender::cwSender(QWidget *parent) : ui->statusbar->setToolTipDuration(3000); this->setToolTipDuration(3000); connect(ui->textToSendEdit->lineEdit(), &QLineEdit::textEdited, this, &cwSender::textChanged); + queue = cachingQueue::getInstance(this); } cwSender::~cwSender() @@ -30,11 +31,11 @@ cwSender::~cwSender() toneThread = Q_NULLPTR; tone = Q_NULLPTR; /* Finally disconnect all connections */ - for (auto conn: connections) - { - disconnect(conn); - } - connections.clear(); + //for (auto conn: connections) + //{ + // disconnect(conn); + //} + //connections.clear(); } delete ui; @@ -272,22 +273,65 @@ void cwSender::on_sidetoneEnableChk_clicked(bool clicked) tone->moveToThread(toneThread); toneThread->start(); - connections.append(connect(toneThread, &QThread::finished, - [=]() { tone->deleteLater(); })); - connections.append(connect(this, &cwSender::sendCW, - [=](const QString& text) { tone->send(text); ui->sidetoneEnableChk->setEnabled(false); })); - connections.append(connect(this, &cwSender::setKeySpeed, - [=](const unsigned char& wpm) { tone->setSpeed(wpm); })); - connections.append(connect(this, &cwSender::setDashRatio, - [=](const unsigned char& ratio) { tone->setRatio(ratio); })); - connections.append(connect(this, &cwSender::setPitch, - [=](const unsigned char& pitch) { tone->setFrequency(pitch); })); - connections.append(connect(this, &cwSender::setLevel, - [=](const unsigned char& level) { tone->setLevel(level); })); - connections.append(connect(this, &cwSender::stopCW, - [=]() { tone->stopSending(); })); - connections.append(connect(tone, &cwSidetone::finished, - [=]() { ui->sidetoneEnableChk->setEnabled(true); })); + connect(this,SIGNAL(initTone()),tone,SLOT(init())); + + connect(toneThread, &QThread::finished, tone, + [=]() { tone->deleteLater(); }); + + connect(this, &cwSender::sendCW, tone, [=](const QString& text) { + tone->send(text); ui->sidetoneEnableChk->setEnabled(false); + }); + + connect(this, &cwSender::sendCW, queue, [=](const QString &cwMessage) { + queue->add(priorityImmediate,queueItem(funcSendCW,QVariant::fromValue(cwMessage))); + }); + + connect(this, &cwSender::stopCW, queue, [=]() { + queue->add(priorityImmediate,queueItem(funcSendCW,QVariant::fromValue(QChar(0xff)))); + }); + + connect(this, &cwSender::setBreakInMode, queue, [=](const unsigned char &bmode) { + queue->add(priorityImmediate,queueItem(funcBreakIn,QVariant::fromValue(bmode))); + }); + + connect(this, &cwSender::setKeySpeed, queue, [=](const unsigned char& wpm) { + queue->add(priorityImmediate,queueItem(funcKeySpeed,QVariant::fromValue(wpm))); + }); + + connect(this, &cwSender::setDashRatio, queue, [=](const unsigned char& ratio) { + queue->add(priorityImmediate,queueItem(funcDashRatio,QVariant::fromValue(ratio))); + }); + + connect(this, &cwSender::setPitch, queue, [=](const unsigned char& pitch) { + queue->add(priorityImmediate,queueItem(funcSendCW,QVariant::fromValue(pitch))); + }); + + connect(this, &cwSender::getCWSettings, queue, [=]() { + queue->add(priorityImmediate,funcKeySpeed); + queue->add(priorityImmediate,funcBreakIn); + queue->add(priorityImmediate,funcCwPitch); + queue->add(priorityImmediate,funcDashRatio); + }); + + connect(this, &cwSender::setKeySpeed, tone, + [=](const unsigned char& wpm) { tone->setSpeed(wpm); }); + + connect(this, &cwSender::setDashRatio, tone, + [=](const unsigned char& ratio) { tone->setRatio(ratio); }); + + connect(this, &cwSender::setPitch, tone, + [=](const unsigned char& pitch) { tone->setFrequency(pitch); }); + + connect(this, &cwSender::setLevel, tone, + [=](const unsigned char& level) { tone->setLevel(level); }); + + connect(this, &cwSender::stopCW, tone, + [=]() { tone->stopSending(); }); + + connect(tone, &cwSidetone::finished, this, + [=]() { ui->sidetoneEnableChk->setEnabled(true); }); + + emit initTone(); } else if (!clicked && toneThread != Q_NULLPTR) { /* disconnect all connections */ @@ -295,11 +339,13 @@ void cwSender::on_sidetoneEnableChk_clicked(bool clicked) toneThread->wait(); toneThread = Q_NULLPTR; tone = Q_NULLPTR; +/* for (auto conn: connections) { disconnect(conn); } connections.clear(); +*/ } } diff --git a/cwsender.h b/cwsender.h index 97c6461..d1fa935 100644 --- a/cwsender.h +++ b/cwsender.h @@ -11,6 +11,7 @@ #include #include "cwsidetone.h" #include "wfviewtypes.h" +#include "cachingqueue.h" namespace Ui { class cwSender; @@ -47,6 +48,7 @@ signals: void pitchChanged(int val); void dashChanged(int val); void wpmChanged(int val); + void initTone(); public slots: void handleKeySpeed(unsigned char wpm); @@ -114,6 +116,7 @@ private: QThread* toneThread = Q_NULLPTR; bool sidetoneWasEnabled=false; QList connections; + cachingQueue* queue; }; #endif // CWSENDER_H diff --git a/cwsidetone.cpp b/cwsidetone.cpp index 0bfecd4..e61975e 100644 --- a/cwsidetone.cpp +++ b/cwsidetone.cpp @@ -10,7 +10,8 @@ cwSidetone::cwSidetone(int level, int speed, int freq, double ratio, QWidget* pa ratio(ratio) { - /* + qInfo(logCW()) << "Starting sidetone. Thread=" << QThread::currentThreadId(); + /* * Characters to match Icom table * Unknown characters will return '?' */ @@ -68,7 +69,7 @@ cwSidetone::cwSidetone(int level, int speed, int freq, double ratio, QWidget* pa cwTable[' '] = " "; - init(); + //init(); } cwSidetone::~cwSidetone() @@ -80,6 +81,7 @@ cwSidetone::~cwSidetone() void cwSidetone::init() { + qInfo(logCW()) << "Sidetone init() Thread=" << QThread::currentThreadId(); format.setSampleRate(44100); format.setChannelCount(1); #if (QT_VERSION < QT_VERSION_CHECK(6,0,0)) diff --git a/cwsidetone.h b/cwsidetone.h index 5fb9436..0cad4f7 100644 --- a/cwsidetone.h +++ b/cwsidetone.h @@ -8,6 +8,7 @@ #include #include #include +#include #if (QT_VERSION < QT_VERSION_CHECK(6,0,0)) #include @@ -45,8 +46,8 @@ public slots: void setRatio(unsigned char ratio); void setLevel(int level); void stopSending(); -private: void init(); +private: void generateMorse(QString morse); QByteArray generateData(qint64 len, qint64 freq); diff --git a/repeatersetup.cpp b/repeatersetup.cpp index a49dc05..e674ed4 100644 --- a/repeatersetup.cpp +++ b/repeatersetup.cpp @@ -509,7 +509,7 @@ void repeaterSetup::on_rptToneCombo_activated(int tindex) { quint16 tone=0; tone = (quint16)ui->rptToneCombo->itemData(tindex).toUInt(); - rptrTone_t rt; + toneInfo rt; rt.tone = tone; bool updateSub = ui->setSplitRptrToneChk->isEnabled() && ui->setSplitRptrToneChk->isChecked(); if(ui->toneTone->isChecked()) @@ -517,7 +517,7 @@ void repeaterSetup::on_rptToneCombo_activated(int tindex) emit setTone(rt); if(updateSub) { - rt.useSecondaryVFO = true; + //rt.useSecondaryVFO = true; emit setTone(rt); } @@ -525,7 +525,7 @@ void repeaterSetup::on_rptToneCombo_activated(int tindex) emit setTSQL(rt); if(updateSub) { - rt.useSecondaryVFO = true; + //rt.useSecondaryVFO = true; emit setTone(rt); } } @@ -533,11 +533,11 @@ void repeaterSetup::on_rptToneCombo_activated(int tindex) void repeaterSetup::on_rptDTCSCombo_activated(int index) { - quint16 dcode=0; - bool tinv = ui->rptDTCSInvertTx->isChecked(); - bool rinv = ui->rptDTCSInvertRx->isChecked(); - dcode = (quint16)ui->rptDTCSCombo->itemData(index).toUInt(); - emit setDTCS(dcode, tinv, rinv); + toneInfo tone; + tone.tinv = ui->rptDTCSInvertTx->isChecked(); + tone.rinv = ui->rptDTCSInvertRx->isChecked(); + tone.tone = (quint16)ui->rptDTCSCombo->itemData(index).toUInt(); + emit setDTCS(tone); } void repeaterSetup::on_toneNone_clicked() @@ -562,7 +562,7 @@ void repeaterSetup::on_toneTone_clicked() rptrAccessData rd; rm = ratrTN; rd.accessMode = rm; - rptrTone_t rt; + toneInfo rt; rt.tone = (quint16)ui->rptToneCombo->currentData().toUInt(); emit setRptAccessMode(rd); emit setTone(rt); @@ -571,8 +571,8 @@ void repeaterSetup::on_toneTone_clicked() if(updateSub) { - rd.useSecondaryVFO = true; - rt.useSecondaryVFO = true; + //rd.useSecondaryVFO = true; + //rt.useSecondaryVFO = true; emit setRptAccessMode(rd); emit setTone(rt); } @@ -583,7 +583,7 @@ void repeaterSetup::on_toneTSQL_clicked() rptAccessTxRx_t rm; rptrAccessData rd; rm = ratrTT; - rptrTone_t rt; + toneInfo rt; rt.tone = (quint16)ui->rptToneCombo->currentData().toUInt(); rd.accessMode = rm; emit setRptAccessMode(rd); @@ -592,8 +592,8 @@ void repeaterSetup::on_toneTSQL_clicked() if(updateSub) { - rd.useSecondaryVFO = true; - rt.useSecondaryVFO = true; + //rd.useSecondaryVFO = true; + //rt.useSecondaryVFO = true; emit setRptAccessMode(rd); emit setTone(rt); } @@ -602,15 +602,14 @@ void repeaterSetup::on_toneTSQL_clicked() void repeaterSetup::on_toneDTCS_clicked() { rptrAccessData rd; - quint16 dcode=0; rd.accessMode = ratrDD; emit setRptAccessMode(rd); - - bool tinv = ui->rptDTCSInvertTx->isChecked(); - bool rinv = ui->rptDTCSInvertRx->isChecked(); - dcode = (quint16)ui->rptDTCSCombo->currentData().toUInt(); - emit setDTCS(dcode, tinv, rinv); + toneInfo tone; + tone.tinv = ui->rptDTCSInvertTx->isChecked(); + tone.rinv = ui->rptDTCSInvertRx->isChecked(); + tone.tone = (quint16)ui->rptDTCSCombo->currentData().toUInt(); + emit setDTCS(tone); // TODO: DTCS with subband } @@ -785,9 +784,9 @@ void repeaterSetup::on_setToneSubVFOBtn_clicked() // Perhaps not needed // Set the secondary VFO to the selected tone // TODO: DTCS - rptrTone_t rt; + toneInfo rt; rt.tone = (quint16)ui->rptToneCombo->currentData().toUInt(); - rt.useSecondaryVFO = true; + //rt.useSecondaryVFO = true; emit setTone(rt); } diff --git a/repeatersetup.h b/repeatersetup.h index 792ba24..88a089e 100644 --- a/repeatersetup.h +++ b/repeatersetup.h @@ -23,9 +23,9 @@ public: signals: void getDuplexMode(); void setDuplexMode(duplexMode_t dm); - void setTone(rptrTone_t tone); - void setTSQL(rptrTone_t tsql); - void setDTCS(quint16 dcode, bool tinv, bool rinv); + void setTone(toneInfo tone); + void setTSQL(toneInfo tsql); + void setDTCS(toneInfo tsql); void getTone(); void getTSQL(); void getDTCS(); diff --git a/rigcommander.cpp b/rigcommander.cpp index a4784b8..dad12c8 100644 --- a/rigcommander.cpp +++ b/rigcommander.cpp @@ -456,7 +456,7 @@ void rigCommander::setSpectrumBounds(double startFreq, double endFreq, unsigned unsigned char range = 1; QByteArray payload; - if (getCommand(funcScopeFixedFreq,payload,edgeNumber)) + if (getCommand(funcScopeFixedEdgeFreq,payload,edgeNumber)) { // Each band should be configured with a maximum range, except for the ICR8600 which doesn't really have "bands" for (bandType band: rigCaps.bands) @@ -480,7 +480,7 @@ void rigCommander::getScopeMode() // center or fixed QByteArray payload; unsigned char cmd = '\x00'; - if (getCommand(funcScopeCenterFixed,payload,cmd)) + if (getCommand(funcScopeMainMode,payload,cmd)) { payload.append(cmd); prepDataAndSend(payload); @@ -491,7 +491,7 @@ void rigCommander::getScopeEdge() { QByteArray payload; unsigned char cmd = '\x00'; - if (getCommand(funcScopeEdgeNumber,payload,cmd)) + if (getCommand(funcScopeMainEdge,payload,cmd)) { payload.append(cmd); prepDataAndSend(payload); @@ -503,7 +503,7 @@ void rigCommander::setScopeEdge(char edge) // 1 2 or 3 (check command definition) QByteArray payload; unsigned char vfo = '\x00'; - if (getCommand(funcScopeEdgeNumber,payload,edge)) + if (getCommand(funcScopeMainEdge,payload,edge)) { payload.append(vfo); payload.append(edge); @@ -519,7 +519,7 @@ void rigCommander::getScopeSpan() void rigCommander::getScopeSpan(bool isSub) { QByteArray payload; - if (getCommand(funcScopeCenterSpan,payload,static_cast(isSub))) + if (getCommand(funcScopeMainSpan,payload,static_cast(isSub))) { payload.append(static_cast(isSub)); prepDataAndSend(payload); @@ -534,7 +534,7 @@ void rigCommander::setScopeSpan(char span) QByteArray payload; unsigned char vfo = '\x00'; - if (getCommand(funcScopeCenterSpan,payload,span)) + if (getCommand(funcScopeMainSpan,payload,span)) { payload.append(vfo); payload.append("\x00"); // 10Hz/1Hz @@ -557,7 +557,7 @@ void rigCommander::setspectrumMode_t(spectrumMode_t spectMode) { QByteArray payload; unsigned char vfo = '\x00'; - if (getCommand(funcScopeCenterFixed,payload,static_cast(spectMode))) + if (getCommand(funcScopeMainMode,payload,static_cast(spectMode))) { payload.append(vfo); payload.append(static_cast(spectMode) ); @@ -573,7 +573,7 @@ void rigCommander::getSpectrumRefLevel() void rigCommander::getSpectrumRefLevel(unsigned char mainSub) { QByteArray payload; - if (getCommand(funcScopeRef,payload,static_cast(mainSub))) + if (getCommand(funcScopeMainRef,payload,static_cast(mainSub))) { payload.append(mainSub); prepDataAndSend(payload); @@ -585,7 +585,7 @@ void rigCommander::setSpectrumRefLevel(int level) // -30 to +10 unsigned char vfo = 0x0; QByteArray payload; - if (getCommand(funcScopeRef,payload,level)) + if (getCommand(funcScopeMainRef,payload,level)) { bool isNegative = false; if(level < 0) @@ -604,7 +604,7 @@ void rigCommander::setSpectrumRefLevel(int level) void rigCommander::getSpectrumCenterMode() { QByteArray payload; - if (getCommand(funcScopeCenterFixed,payload)) + if (getCommand(funcScopeMainMode,payload)) { prepDataAndSend(payload); } @@ -613,7 +613,7 @@ void rigCommander::getSpectrumCenterMode() void rigCommander::getspectrumMode_t() { QByteArray payload; - if (getCommand(funcScopeCenterFixed,payload)) + if (getCommand(funcScopeMainMode,payload)) { prepDataAndSend(payload); } @@ -950,7 +950,7 @@ void rigCommander::setSplit(bool splitEnabled) void rigCommander::setDuplexMode(duplexMode_t dm) { QByteArray payload; - if (getCommand(funcDuplexStatus,payload,static_cast(dm))) + if (getCommand(funcSplitStatus,payload,static_cast(dm))) { payload.append(static_cast(dm)); prepDataAndSend(payload); @@ -964,7 +964,7 @@ void rigCommander::setDuplexMode(duplexMode_t dm) void rigCommander::getDuplexMode() { QByteArray payload; - if (getCommand(funcDuplexStatus,payload)) + if (getCommand(funcSplitStatus,payload)) { prepDataAndSend(payload); } @@ -1145,17 +1145,17 @@ void rigCommander::getTransmitFrequency() void rigCommander::setTone(quint16 tone) { - rptrTone_t t; + toneInfo t; t.tone = tone; setTone(t); } -void rigCommander::setTone(rptrTone_t t) +void rigCommander::setTone(toneInfo t) { QByteArray payload; if (getCommand(funcMainSubPrefix,payload)) { - payload.append(static_cast(t.useSecondaryVFO)); + //payload.append(static_cast(t.useSecondaryVFO)); } if (getCommand(funcToneFreq,payload,static_cast(t.tone))) @@ -1167,17 +1167,17 @@ void rigCommander::setTone(rptrTone_t t) void rigCommander::setTSQL(quint16 t) { - rptrTone_t tn; + toneInfo tn; tn.tone = t; setTSQL(tn); } -void rigCommander::setTSQL(rptrTone_t t) +void rigCommander::setTSQL(toneInfo t) { QByteArray payload; if (getCommand(funcMainSubPrefix,payload)) { - payload.append(static_cast(t.useSecondaryVFO)); + //payload.append(static_cast(t.useSecondaryVFO)); } if (getCommand(funcTSQLFreq,payload,static_cast(t.tone))) @@ -2000,7 +2000,7 @@ void rigCommander::parseCommand() switch (func) { case funcFreqGet: - case funcfreqTR: + case funcFreqTR: case funcReadTXFreq: { value.setValue(parseFrequency()); @@ -2075,12 +2075,15 @@ void rigCommander::parseCommand() value.setValue(parseFrequencyRptOffset(payloadIn)); break; // These return a single byte that we convert to a uchar (0-99) - case funcSplitStatus: - case funcDuplexStatus: case funcTuningStep: case funcAttenuator: + case funcBreakIn: // This is 0,1 or 2 value.setValue(uchar(payloadIn[1])); break; + // Return a duplexMode_t for split or duplex (same function) + case funcSplitStatus: + value.setValue(duplexMode_t(payloadIn[1])); + break; case funcAntenna: { antennaInfo ant; @@ -2094,6 +2097,8 @@ void rigCommander::parseCommand() case funcAfGain: if (udp == Q_NULLPTR) { value.setValue(bcdHexToUChar(payloadIn[2],payloadIn[3])); + } else { + value.setValue(localVolume); } break; // The following group are 2 bytes converted to uchar (0-255) @@ -2169,7 +2174,11 @@ void rigCommander::parseCommand() // 0x19 it automatically added. case funcTransceiverId: value.setValue(static_cast(payloadIn[2])); - model = determineRadioModel(payloadIn[2]); // verify this is the model not the CIV + if (rigList.contains(uchar(payloadIn[2]))) + { + this->model = rigList.find(uchar(payloadIn[2])).key(); + } + //model = determineRadioModel(payloadIn[2]); // verify this is the model not the CIV rigCaps.modelID = payloadIn[2]; determineRigCaps(); qInfo(logRig()) << "Have rig ID: " << QString::number(rigCaps.modelID,16); @@ -2265,10 +2274,11 @@ void rigCommander::parseCommand() break; ritHz = f.Hz*((payloadIn.at(4)=='\x01')?-1:1); value.setValue(ritHz); + qInfo() << "Have RIT" << ritHz; break; } // 0x27 - case funcScopeWaveData: + case funcScopeMainWaveData: { scopeData d; if (parseSpectrum(d)) @@ -2288,37 +2298,37 @@ void rigCommander::parseCommand() case funcScopeSingleDual: // This tells us whether we are receiving single or dual scopes break; - case funcScopeCenterFixed: + case funcScopeMainMode: // fixed or center // [1] 0x14 // [2] 0x00 // [3] 0x00 (center), 0x01 (fixed), 0x02, 0x03 value.setValue(static_cast(uchar(payloadIn[3]))); - //emit havespectrumMode_t(static_cast((unsigned char)payloadIn[3])); break; - case funcScopeCenterSpan: + case funcScopeMainSpan: { freqt f = parseFrequency(payloadIn, 6); - f.VFO = static_cast((uchar)payloadIn[2]); - value.setValue(f); - // read span in center mode - // [1] 0x15 - // [2] to [8] is spastatic_cast(payloadIn.at(2)n encoded as a frequency - //emit haveScopeSpan(parseFrequency(payloadIn, 6), static_cast(payloadIn.at(2))); + foreach (auto s, rigCaps.scopeCenterSpans) + { + if (s.freq == f.Hz) + { + value.setValue(s); + } + } break; } - case funcScopeEdgeNumber: + case funcScopeMainEdge: // read edge mode center in edge mode // [1] 0x16 // [2] 0x01, 0x02, 0x03: Edge 1,2,3 value.setValue(bcdHexToUChar(payloadIn[2])); //emit haveScopeEdge((char)payloadIn[2]); break; - case funcScopeHold: + case funcScopeMainHold: // Hold status (only 9700?) value.setValue(static_cast(payloadIn[2])); break; - case funcScopeRef: + case funcScopeMainRef: { // scope reference level // [1] 0x19 @@ -2335,12 +2345,12 @@ void rigCommander::parseCommand() value.setValue(ref); break; } - case funcScopeSpeed: + case funcScopeMainSpeed: case funcScopeDuringTX: case funcScopeCenterType: - case funcScopeVBW: - case funcScopeFixedFreq: - case funcScopeRBW: + case funcScopeMainVBW: + case funcScopeFixedEdgeFreq: + case funcScopeMainRBW: break; // 0x28 case funcVoiceTX: @@ -2360,7 +2370,7 @@ void rigCommander::parseCommand() break; } - if( (func != funcScopeWaveData) && (payloadIn[00] != '\x15') ) + if(func != funcScopeMainWaveData && func != funcScopeSubWaveData && payloadIn[00] != '\x15') { // We do not log spectrum and meter data, // as they tend to clog up any useful logging. @@ -5552,29 +5562,27 @@ bool rigCommander::parseSpectrum(scopeData& d) if(payloadIn.length() >= 15) { d.oor=(bool)payloadIn[16]; - if(d.oor != wasOutOfRange) - { - emit haveScopeOutOfRange(d.oor); - wasOutOfRange = d.oor; - return false; + if (d.oor) { + d.data = QByteArray(rigCaps.spectLenMax,'\0'); + return true; } } // wave information spectrumLine.clear(); + + // For Fixed, and both scroll modes, the following produces correct information: fStart = parseFrequency(payloadIn, 9); - spectrumStartFreq = fStart.MHzDouble; + d.startFreq = fStart.MHzDouble; fEnd = parseFrequency(payloadIn, 14); - spectrumEndFreq = fEnd.MHzDouble; + d.endFreq = fEnd.MHzDouble; + if(scopeMode == spectModeCenter) { // "center" mode, start is actual center, end is bandwidth. - spectrumStartFreq -= spectrumEndFreq; - spectrumEndFreq = spectrumStartFreq + 2*(spectrumEndFreq); - d.startFreq = spectrumStartFreq; - d.endFreq = spectrumEndFreq; - // emit haveSpectrumCenterSpan(span); + d.startFreq -= d.endFreq; + d.endFreq = d.startFreq + 2*(d.endFreq); } if (payloadIn.length() > 400) // Must be a LAN packet. @@ -5582,7 +5590,6 @@ bool rigCommander::parseSpectrum(scopeData& d) payloadIn.chop(1); d.data.append(payloadIn.right(payloadIn.length()-17)); // write over the FD, last one doesn't, oh well. ret = true; - //emit haveSpectrumData(spectrumLine, spectrumStartFreq, spectrumEndFreq); } } else if ((sequence > 1) && (sequence < rigCaps.spectSeqMax)) @@ -5880,7 +5887,12 @@ modeInfo rigCommander::parseMode(quint8 mode, quint8 filter) qInfo(logRig()) << QString("parseMode() Couldn't find a matching mode %0 with filter %1").arg(mode).arg(filter); cacheItem item = queue->getCache(funcFilterWidth); - if (!item.value.isValid()) { + + if (item.value.isValid()) { + mi.pass = item.value.toInt(); + } + else + { /* We haven't got a valid passband from the rig so we need to create a 'fake' one from default values @@ -6288,11 +6300,13 @@ void rigCommander::setRigID(unsigned char rigID) // this->civAddr comes from how rigCommander is setup and should be accurate. this->incomingCIVAddr = this->civAddr; - this->model = determineRadioModel(rigID); + if (rigList.contains(rigID)) this->model = rigID; rigCaps.modelID = rigID; - rigCaps.model = determineRadioModel(rigID); - + rigCaps.model = this->model; determineRigCaps(); + + //this->model = determineRadioModel(rigID); + //rigCaps.model = determineRadioModel(rigID); } void rigCommander::changeLatency(const quint16 value) @@ -6873,16 +6887,48 @@ void rigCommander::receiveCommand(queueItemType type, funcs func, QVariant value //qInfo() << "Got command:" << funcString[func]; int val=INT_MIN; - if (value.isValid()) { - val = value.value() & 0xffff; + if (value.isValid() && value.canConvert()) { + // Used to validate payload, otherwise ignore. + val = value.value(); //qInfo(logRig()) << "Got value" << QString(value.typeName()); + if (func == funcMemoryContents || func == funcMemoryClear || func == funcMemoryWrite) + { + // Strip out group number from memory for validation purposes. + val = val & 0xffff; + } } - if (func == funcSelectVFO) { + if (func == funcSendCW) + { + val = value.value().length(); + } + + if (func == funcAfGain && value.isValid() && udp != Q_NULLPTR) { + // Ignore the AF Gain command, just queue it for processing + emit haveSetVolume(static_cast(value.toInt())); + queue->receiveValue(func,value); + return; + } + + // Need to work out what to do with older dual-VFO rigs. + if ((func == funcSelectedFreq || func == funcUnselectedFreq) && !rigCaps.commands.contains(func)) + { + if (value.isValid()) + func = funcFreqSet; + else + func = funcFreqGet; + } else if ((func == funcSelectedMode || func == funcUnselectedMode) && !rigCaps.commands.contains(func)) + { + if (value.isValid()) + func = funcModeSet; + else + func = funcModeGet; + } else if (func == funcSelectVFO) { // Special command vfo_t vfo = value.value(); func = (vfo == vfoA)?funcVFOASelect:(vfo == vfoB)?funcVFOBSelect:(vfo == vfoMain)?funcVFOMainSelect:funcVFOSubSelect; value.clear(); + val = INT_MIN; } QByteArray payload; @@ -6890,11 +6936,38 @@ void rigCommander::receiveCommand(queueItemType type, funcs func, QVariant value { if (value.isValid()) { - if (!strcmp(value.typeName(),"bool")) { payload.append(value.value()); } + if (!strcmp(value.typeName(),"QString")) + { + QString text = value.value(); + if (pttAllowed && func == funcSendCW) + { + QByteArray textData = text.toLocal8Bit(); + unsigned char p=0; + for(int c=0; c < textData.length(); c++) + { + p = textData.at(c); + if( ( (p >= 0x30) && (p <= 0x39) ) || + ( (p >= 0x41) && (p <= 0x5A) ) || + ( (p >= 0x61) && (p <= 0x7A) ) || + (p==0x2F) || (p==0x3F) || (p==0x2E) || + (p==0x2D) || (p==0x2C) || (p==0x3A) || + (p==0x27) || (p==0x28) || (p==0x29) || + (p==0x3D) || (p==0x2B) || (p==0x22) || + (p==0x40) || (p==0x20) ) + { + // Allowed character, continue + } else { + qWarning(logRig()) << "Invalid character detected in CW message at position " << c << ", the character is " << text.at(c); + textData[c] = 0x3F; // "?" + } + } + payload.append(textData); + } + } else if (!strcmp(value.typeName(),"uchar")) { payload.append(bcdEncodeChar(value.value())); @@ -6906,6 +6979,25 @@ void rigCommander::receiveCommand(queueItemType type, funcs func, QVariant value else payload.append(bcdEncodeInt(value.value())); } + else if (!strcmp(value.typeName(),"short")) + { + // Currently only used for RIT (I think) + bool isNegative = false; + short val = value.value(); + qInfo() << "Setting rit to " << val; + if(val < 0) + { + isNegative = true; + val *= -1; + } + freqt f; + QByteArray freqBytes; + f.Hz = val; + freqBytes = makeFreqPayload(f); + freqBytes.truncate(2); + payload.append(freqBytes); + payload.append(QByteArray(1,(char)isNegative)); + } else if (!strcmp(value.typeName(),"uint") && (func == funcMemoryContents || func == funcMemoryMode)) { // Format is different for all radios! @@ -6949,7 +7041,8 @@ void rigCommander::receiveCommand(queueItemType type, funcs func, QVariant value else if(!strcmp(value.typeName(),"antennaInfo")) { payload.append(value.value().antenna); - payload.append(value.value().rx); + if (rigCaps.commands.contains(funcRXAntenna)) + payload.append(value.value().rx); } else if(!strcmp(value.typeName(),"rigInput")) { @@ -6959,16 +7052,55 @@ void rigCommander::receiveCommand(queueItemType type, funcs func, QVariant value { payload.append(setMemory(value.value())); } + else if (!strcmp(value.typeName(),"spectrumBounds")) + { + spectrumBounds s = value.value(); + uchar range=1; + for (bandType band: rigCaps.bands) + { + if (band.range != 0.0 && s.start > band.range) + range++; + } + payload.append(range); + payload.append(s.edge); + payload.append(makeFreqPayload(s.start)); + payload.append(makeFreqPayload(s.end)); + qInfo() << "Bounds" << range << s.edge << s.start << s.end << payload.toHex(); + } + else if (!strcmp(value.typeName(),"duplexMode_t")) + { + payload.append(static_cast(value.value())); + } + else if (!strcmp(value.typeName(),"spectrumMode_t")) + { + payload.append(static_cast(value.value())); + } + else if (!strcmp(value.typeName(),"centerSpanData")) + { + centerSpanData span = value.value(); + double freq = double(span.freq/1000000.0); + payload.append(makeFreqPayload(freq)); + } + else if (!strcmp(value.typeName(),"toneInfo")) + { + toneInfo t = value.value(); + payload.append(encodeTone(t.tone, t.tinv, t.rinv)); + } else { qInfo(logRig()) << "Got unknown value type" << QString(value.typeName()); + return; } + // This was a set command, so queue a get straight after to retrieve the updated value + // will fail on some commands so they would need to be added here: + if (func != funcScopeFixedEdgeFreq && func != funcSpeech) + queue->addUnique(priorityImmediate,func); } prepDataAndSend(payload); } else { - qInfo() << "cachingQueue(): unimplemented command" << funcString[func]; + qDebug(logRig()) << "cachingQueue(): unimplemented command" << funcString[func]; } } diff --git a/rigcommander.h b/rigcommander.h index 5700202..ffa91d5 100644 --- a/rigcommander.h +++ b/rigcommander.h @@ -153,8 +153,8 @@ public slots: void getDuplexMode(); void setQuickSplit(bool qsOn); void getTransmitFrequency(); - void setTone(rptrTone_t t); - void setTSQL(rptrTone_t t); + void setTone(toneInfo t); + void setTSQL(toneInfo t); void setTone(quint16 t); void setTSQL(quint16 t); void getTSQL(); @@ -315,7 +315,6 @@ signals: void havespectrumMode_t(spectrumMode_t spectmode); void haveScopeEdge(char edge); void haveSpectrumRefLevel(int level); - void haveScopeOutOfRange(bool outOfRange); // Rig ID: void haveRigID(rigCapabilities rigCaps); @@ -485,20 +484,19 @@ private: QByteArray rigData; QByteArray spectrumLine; - double spectrumStartFreq; - double spectrumEndFreq; + //double spectrumStartFreq; + //double spectrumEndFreq; struct rigCapabilities rigCaps; rigstate state; bool haveRigCaps=false; - model_kind model; + quint8 model = 0; // Was model_kind but that makes no sense when users can create their own rigs! quint8 spectSeqMax; quint16 spectAmpMax; quint16 spectLenMax; spectrumMode_t oldScopeMode; - bool wasOutOfRange = false; bool usingNativeLAN; // indicates using OEM LAN connection (705,7610,9700,7850) bool lookingForRig; diff --git a/rigcreator.cpp b/rigcreator.cpp index fcd5db7..150c698 100644 --- a/rigcreator.cpp +++ b/rigcreator.cpp @@ -14,13 +14,27 @@ rigCreator::rigCreator(QWidget *parent) : commandsList = new tableCombobox(createModel(commandsModel, funcString),true,ui->commands); ui->commands->setItemDelegateForColumn(0, commandsList); - ui->commands->setColumnWidth(0,145); - ui->commands->setColumnWidth(1,125); + ui->commands->setColumnWidth(0,120); + ui->commands->setColumnWidth(1,115); ui->commands->setColumnWidth(2,50); ui->commands->setColumnWidth(3,50); + ui->commands->setColumnWidth(4,25); + connect(ui->commands,SIGNAL(rowAdded(int)),this,SLOT(commandRowAdded(int))); } +void rigCreator::commandRowAdded(int row) +{ + if (ui->commands->item(row,4) == NULL) { + // Add checkbox + QTableWidgetItem * item = new QTableWidgetItem(); + item->setFlags(Qt::ItemFlag::ItemIsEnabled | Qt::ItemFlag::ItemIsUserCheckable); + item->setCheckState(Qt::Unchecked); + ui->commands->setItem(row,4,item); + } +} + + rigCreator::~rigCreator() { qInfo() << "Deleting instance of rigCreator()"; @@ -77,6 +91,8 @@ void rigCreator::on_loadFile_clicked(bool clicked) void rigCreator::loadRigFile(QString file) { + ui->loadFile->setEnabled(false); + ui->defaultRigs->setEnabled(false); this->currentFile = file; QSettings* settings = new QSettings(file, QSettings::Format::IniFormat); @@ -127,6 +143,16 @@ void rigCreator::loadRigFile(QString file) { settings->setArrayIndex(c); ui->commands->insertRow(ui->commands->rowCount()); + // Add checkbox for row 4 (command 39) + QTableWidgetItem * item = new QTableWidgetItem(); + item->setFlags(item->flags() | Qt::ItemIsUserCheckable); + if (settings->value("Command39",false).toBool()) + item->setCheckState(Qt::Checked); + else + item->setCheckState(Qt::Unchecked); + ui->commands->setItem(c,4,item); + + ui->commands->model()->setData(ui->commands->model()->index(c,0),settings->value("Type", "").toString()); ui->commands->model()->setData(ui->commands->model()->index(c,1),settings->value("String", "").toString()); ui->commands->model()->setData(ui->commands->model()->index(c,2),QString::number(settings->value("Min", 0).toInt(),16)); diff --git a/rigcreator.h b/rigcreator.h index 3b0031f..f1e5dcc 100644 --- a/rigcreator.h +++ b/rigcreator.h @@ -32,12 +32,16 @@ private slots: void on_defaultRigs_clicked(bool clicked); void loadRigFile(QString filename); void saveRigFile(QString filename); + void commandRowAdded(int row); + private: Ui::rigCreator *ui; QMenu* context; tableCombobox* commandsList; + tableCheckbox* command39; QStandardItemModel* commandsModel; + QStandardItemModel* command36Model; QStandardItemModel* createModel(QStandardItemModel* model, QString strings[]); QString currentFile; diff --git a/rigcreator.ui b/rigcreator.ui index 315f775..78e461e 100644 --- a/rigcreator.ui +++ b/rigcreator.ui @@ -161,7 +161,7 @@ 830 - 200 + 230 141 131 @@ -632,7 +632,7 @@ 0 - 4 + 5 false @@ -672,6 +672,11 @@ Max + + + 29 + + @@ -680,7 +685,7 @@ 830 50 141 - 151 + 181 @@ -764,6 +769,19 @@ HasFDComms + + + + 10 + 150 + 121 + 20 + + + + Has Command 29 + + @@ -974,9 +992,9 @@ 770 - 330 + 360 191 - 211 + 181 @@ -988,7 +1006,7 @@ 0 30 191 - 181 + 151 diff --git a/rigctld.cpp b/rigctld.cpp index 15a2c5f..95d3949 100644 --- a/rigctld.cpp +++ b/rigctld.cpp @@ -2,49 +2,273 @@ #include "logcategories.h" + static struct { quint64 mode; + rigMode_t mk; const char* str; + uchar data=0; } mode_str[] = { - { RIG_MODE_AM, "AM" }, - { RIG_MODE_CW, "CW" }, - { RIG_MODE_USB, "USB" }, - { RIG_MODE_LSB, "LSB" }, - { RIG_MODE_RTTY, "RTTY" }, - { RIG_MODE_FM, "FM" }, - { RIG_MODE_WFM, "WFM" }, - { RIG_MODE_CWR, "CWR" }, - { RIG_MODE_RTTYR, "RTTYR" }, - { RIG_MODE_AMS, "AMS" }, - { RIG_MODE_PKTLSB, "PKTLSB" }, - { RIG_MODE_PKTUSB, "PKTUSB" }, - { RIG_MODE_PKTFM, "PKTFM" }, - { RIG_MODE_PKTFMN, "PKTFMN" }, - { RIG_MODE_ECSSUSB, "ECSSUSB" }, - { RIG_MODE_ECSSLSB, "ECSSLSB" }, - { RIG_MODE_FAX, "FAX" }, - { RIG_MODE_SAM, "SAM" }, - { RIG_MODE_SAL, "SAL" }, - { RIG_MODE_SAH, "SAH" }, - { RIG_MODE_DSB, "DSB"}, - { RIG_MODE_FMN, "FMN" }, - { RIG_MODE_PKTAM, "PKTAM"}, - { RIG_MODE_P25, "P25"}, - { RIG_MODE_DSTAR, "D-STAR"}, - { RIG_MODE_DPMR, "DPMR"}, - { RIG_MODE_NXDNVN, "NXDN-VN"}, - { RIG_MODE_NXDN_N, "NXDN-N"}, - { RIG_MODE_DCR, "DCR"}, - { RIG_MODE_AMN, "AMN"}, - { RIG_MODE_PSK, "PSK"}, - { RIG_MODE_PSKR, "PSKR"}, - { RIG_MODE_C4FM, "C4FM"}, - { RIG_MODE_SPEC, "SPEC"}, - { RIG_MODE_NONE, "" }, + { RIG_MODE_AM, modeAM, "AM" }, + { RIG_MODE_CW, modeCW, "CW" }, + { RIG_MODE_USB, modeUSB, "USB" }, + { RIG_MODE_LSB, modeLSB, "LSB" }, + { RIG_MODE_RTTY, modeRTTY, "RTTY" }, + { RIG_MODE_FM, modeFM, "FM" }, + { RIG_MODE_WFM, modeWFM, "WFM" }, + { RIG_MODE_CWR, modeCW_R, "CWR" }, + { RIG_MODE_RTTYR, modeRTTY_R, "RTTYR" }, + { RIG_MODE_AMS, modeUnknown, "AMS" }, + { RIG_MODE_PKTLSB, modeLSB, "PKTLSB", 1U}, + { RIG_MODE_PKTUSB, modeUSB, "PKTUSB" , 1U}, + { RIG_MODE_PKTFM, modeFM, "PKTFM", true}, + { RIG_MODE_PKTFMN, modeUnknown, "PKTFMN", 1U}, + { RIG_MODE_ECSSUSB, modeUnknown, "ECSSUSB" }, + { RIG_MODE_ECSSLSB, modeUnknown, "ECSSLSB" }, + { RIG_MODE_FAX, modeUnknown, "FAX" }, + { RIG_MODE_SAM, modeUnknown, "SAM" }, + { RIG_MODE_SAL, modeUnknown, "SAL" }, + { RIG_MODE_SAH, modeUnknown, "SAH" }, + { RIG_MODE_DSB, modeUnknown, "DSB"}, + { RIG_MODE_FMN, modeUnknown, "FMN" }, + { RIG_MODE_PKTAM, modeUnknown, "PKTAM"}, + { RIG_MODE_P25, modeP25, "P25"}, + { RIG_MODE_DSTAR, modeDV, "D-STAR"}, + { RIG_MODE_DPMR, modedPMR, "DPMR"}, + { RIG_MODE_NXDNVN, modeNXDN_VN, "NXDN-VN"}, + { RIG_MODE_NXDN_N, modeNXDN_N, "NXDN-N"}, + { RIG_MODE_DCR, modeUnknown, "DCR"}, + { RIG_MODE_AMN, modeUnknown, "AMN"}, + { RIG_MODE_PSK, modePSK, "PSK"}, + { RIG_MODE_PSKR, modePSK_R, "PSKR"}, + { RIG_MODE_C4FM, modeUnknown, "C4FM"}, + { RIG_MODE_SPEC, modeUnknown, "SPEC"}, + { RIG_MODE_NONE, modeUnknown, "" }, }; + +static const subCommandStruct levels_str[] = +{ + {"PREAMP",funcPreamp,'g'}, + {"ATT",funcAttenuator,'i'}, + {"VOXDELAY",funcVOXDelay,'f'}, + {"AF",funcAfGain,'f'}, + {"RF",funcRfGain,'f'}, + {"SQL",funcSquelch,'f'}, + {"IF",funcIFFilterWidth,'f'}, + {"APF",funcAPFLevel,'f'}, + {"NR",funcNRLevel,'f'}, + {"PBT_IN",funcPBTInner,'f'}, + {"PBT_OUT",funcPBTOuter,'f'}, + {"CWPITCH",funcCwPitch,'f'}, + {"RFPOWER",funcRFPower,'f'}, + {"MICGAIN",funcMicGain,'f'}, + {"KEYSPD",funcKeySpeed,'h'}, + {"NOTCHF",funcNotchFilter,'i'}, + {"COMP",funcCompressorLevel,'f'}, + {"AGC",funcAGCTime,'f'}, + {"BKINDL",funcBreakInDelay,'f'}, + {"BAL",funcNone,'f'}, + {"METER",funcNone,'f'}, + {"VOXGAIN",funcVoxGain,'f'}, + {"ANTIVOX",funcAntiVoxGain,'f'}, + {"SLOPE_LOW",funcNone,'f'}, + {"SLOPE_HIGH",funcNone,'f'}, + {"BKIN_DLYMS",funcBreakInDelay,'f'}, + {"RAWSTR",funcNone,'f'}, + {"SWR",funcSMeter,'f'}, + {"ALC",funcALCMeter,'f'}, + {"STRENGTH",funcSMeter,'f'}, + {"RFPOWER_METER",funcPowerMeter,'f'}, + {"COMPMETER",funcCompMeter,'f'}, + {"VD_METER",funcVdMeter,'f'}, + {"ID_METER",funcIdMeter,'f'}, + {"NOTCHF_RAW",funcNone,'f'}, + {"MONITOR_GAIN",funcMonitorGain,'f'}, + {"NQ",funcNone,'f'}, + {"RFPOWER_METER_WATT",funcNone,'f'}, + {"SPECTRUM_MDOE",funcNone,'f'}, + {"SPECTRUM_SPAN",funcNone,'f'}, + {"SPECTRUM_EDGE_LOW",funcNone,'f'}, + {"SPECTRUM_EDGE_HIGH",funcNone,'f'}, + {"SPECTRUM_SPEED",funcNone,'f'}, + {"SPECTRUM_REF",funcNone,'f'}, + {"SPECTRUM_AVG",funcNone,'f'}, + {"SPECTRUM_ATT",funcNone,'f'}, + {"TEMP_METER",funcNone,'f'}, + {"BAND_SELECT",funcNone,'f'}, + {"USB_AF",funcNone,'f'}, + {"",funcNone,'\x0'} +}; + +static const subCommandStruct functions_str[] = +{ + {"FAGC",funcAGCTime,'i'}, + {"NB",funcNoiseBlanker,'b'}, + {"COMP",funcCompressor,'b'}, + {"VOX",funcVox,'b'}, + {"TONE",funcRepeaterTone,'b'}, + {"TQSL",funcRepeaterTSQL,'b'}, + {"SBKIN",funcBreakIn,'i'}, + {"FBKIN",funcBreakIn,'i'}, + {"ANF",funcAutoNotch,'b'}, + {"NR",funcNoiseReduction,'b'}, + {"AIP",funcNone,'b'}, + {"APF",funcAPFType,'b'}, + {"MON",funcMonitor,'b'}, + {"MN",funcManualNotch,'b'}, + {"RF",funcNone,'b'}, + {"ARO",funcNone,'b'}, + {"LOCK",funcLockFunction,'b'}, + {"MUTE",funcAFMute,'b'}, + {"VSC",funcNone,'b'}, + {"REV",funcNone,'b'}, + {"SQL",funcSquelch,'b'}, // Actually an integer as ICOM doesn't provide on/off for squelch + {"ABM",funcNone,'b'}, + {"VSC",funcNone,'b'}, + {"REV",funcNone,'b'}, + {"BC",funcNone,'b'}, + {"MBC",funcNone,'b'}, + {"RIT",funcRitStatus,'b'}, + {"AFC",funcNone,'b'}, + {"SATMODE",funcSatelliteMode,'b'}, + {"SCOPE",funcScopeOnOff,'b'}, + {"RESUME",funcNone,'b'}, + {"TBURST",funcNone,'b'}, + {"TUNER",funcTunerStatus,'b'}, + {"XIT",funcNone,'b'}, + {"",funcNone,'b'} +}; + +static const subCommandStruct params_str[] = +{ + {"ANN",funcNone,'i'}, + {"APO",funcNone,'i'}, + {"BACKLIGHT",funcBackLight,'i'}, + {"BEEP",funcNone,'i'}, + {"TIME",funcTime,'i'}, + {"BAT",funcNone,'i'}, + {"KEYLIGHT",funcNone,'i'}, + {"",funcNone} +}; + +#define ARG_IN1 0x01 +#define ARG_OUT1 0x02 +#define ARG_IN2 0x04 +#define ARG_OUT2 0x08 +#define ARG_IN3 0x10 +#define ARG_OUT3 0x20 +#define ARG_IN4 0x40 +#define ARG_OUT4 0x80 +#define ARG_OUT5 0x100 +#define ARG_NONE 0 +#define ARG_IN (ARG_IN1|ARG_IN2|ARG_IN3|ARG_IN4) +#define ARG_OUT (ARG_OUT1|ARG_OUT2|ARG_OUT3|ARG_OUT4) +#define ARG_IN_LINE 0x4000 +#define ARG_NOVFO 0x8000 +#define MAXNAMESIZE 32 + +static const commandStruct commands_list[] = +{ + { 'F', "set_freq", funcFreqSet, 'x', ARG_IN, "Frequency" }, + { 'f', "get_freq", funcFreqGet, 'x', ARG_OUT, "Frequency" }, + { 'M', "set_mode", funcModeSet, 'm', ARG_IN, "Mode", "Passband" }, + { 'm', "get_mode", funcModeGet, 'm', ARG_OUT, "Mode", "Passband" }, + { 'I', "set_split_freq", funcSendFreqOffset, 'x', ARG_IN, "TX Frequency" }, + { 'i', "get_split_freq", funcReadFreqOffset, 'x', ARG_OUT, "TX Frequency" }, + { 'X', "set_split_mode", funcSplitStatus, 'm', ARG_IN, "TX Mode", "TX Passband" }, + { 'x', "get_split_mode", funcSplitStatus, 'm', ARG_OUT, "TX Mode", "TX Passband" }, + { 'K', "set_split_freq_mode", funcNone, 'x', ARG_IN, "TX Frequency", "TX Mode", "TX Passband" }, + { 'k', "get_split_freq_mode", funcNone, 'x', ARG_OUT, "TX Frequency", "TX Mode", "TX Passband" }, + { 'S', "set_split_vfo", funcNone, 'x', ARG_IN, "Split", "TX VFO" }, + { 's', "get_split_vfo", funcNone, 'x', ARG_OUT, "Split", "TX VFO" }, + { 'N', "set_ts", funcTuningStep, 'i', ARG_IN, "Tuning Step" }, + { 'n', "get_ts", funcTuningStep, 'i', ARG_OUT, "Tuning Step" }, + { 'L', "set_level", funcRigctlLevel, 'z', ARG_IN, "Level", "Level Value" }, + { 'l', "get_level", funcRigctlLevel, 'z', ARG_IN1 | ARG_OUT2, "Level", "Level Value" }, + { 'U', "set_func", funcRigctlFunction, 'z', ARG_IN, "Func", "Func Status" }, + { 'u', "get_func", funcRigctlFunction, 'z', ARG_IN1 | ARG_OUT2, "Func", "Func Status" }, + { 'P', "set_parm", funcRigctlParam, 'z', ARG_IN1 | ARG_NOVFO, "Parm", "Parm Value" }, + { 'p', "get_parm", funcRigctlParam, 'z', ARG_IN1 | ARG_OUT2, "Parm", "Parm Value" }, + { 'G', "vfo_op", funcSelectVFO, 'i', ARG_IN, "Mem/VFO Op" }, + { 'g', "scan", funcScanning, 'i', ARG_IN, "Scan Fct", "Scan Channel" }, + { 'A', "set_trn", funcCIVTransceive, 'i', ARG_IN | ARG_NOVFO, "Transceive" }, + { 'a', "get_trn", funcCIVTransceive, 'i', ARG_OUT | ARG_NOVFO, "Transceive" }, + { 'R', "set_rptr_shift", funcSendFreqOffset, 'i', ARG_IN, "Rptr Shift" }, + { 'r', "get_rptr_shift", funcReadFreqOffset, 'i', ARG_OUT, "Rptr Shift" }, + { 'O', "set_rptr_offs", funcSendFreqOffset, 'i', ARG_IN, "Rptr Offset" }, + { 'o', "get_rptr_offs", funcReadFreqOffset, 'i', ARG_OUT, "Rptr Offset" }, + { 'C', "set_ctcss_tone", funcToneFreq, 'i', ARG_IN, "CTCSS Tone" }, + { 'c', "get_ctcss_tone", funcToneFreq, 'i', ARG_OUT, "CTCSS Tone" }, + { 'D', "set_dcs_code", funcDTCSCode, 'i', ARG_IN, "DCS Code" }, + { 'd', "get_dcs_code", funcDTCSCode, 'i', ARG_OUT, "DCS Code" }, + { 0x90, "set_ctcss_sql", funcTSQLFreq, 'i', ARG_IN, "CTCSS Sql" }, + { 0x91, "get_ctcss_sql", funcTSQLFreq, 'i', ARG_OUT, "CTCSS Sql" }, + { 0x92, "set_dcs_sql", funcCSQLCode, 'i', ARG_IN, "DCS Sql" }, + { 0x93, "get_dcs_sql", funcCSQLCode, 'i', ARG_OUT, "DCS Sql" }, + { 'V', "set_vfo", funcSelectVFO, 'v', ARG_IN | ARG_NOVFO, "VFO" }, + { 'v', "get_vfo", funcSelectVFO, 'v', ARG_NOVFO | ARG_OUT, "VFO" }, + { 'T', "set_ptt", funcTransceiverStatus, 'i', ARG_IN, "PTT" }, + { 't', "get_ptt", funcTransceiverStatus, 'i', ARG_OUT, "PTT" }, + { 'E', "set_mem", funcMemoryContents, 'm', ARG_IN, "Memory#" }, + { 'e', "get_mem", funcMemoryContents, 'm', ARG_OUT, "Memory#" }, + { 'H', "set_channel", funcMemoryMode, 'i', ARG_IN | ARG_NOVFO, "Channel"}, + { 'h', "get_channel", funcMemoryMode, 'i', ARG_IN | ARG_NOVFO, "Channel", "Read Only" }, + { 'B', "set_bank", funcMemoryGroup, 'i', ARG_IN, "Bank" }, + { '_', "get_info", funcNone, 'i', ARG_OUT | ARG_NOVFO, "Info" }, + { 'J', "set_rit", funcRITFreq, 's', ARG_IN, "RIT" }, + { 'j', "get_rit", funcRITFreq, 's', ARG_OUT, "RIT" }, + { 'Z', "set_xit", funcNone, 's', ARG_IN, "XIT" }, + { 'z', "get_xit", funcNone, 's', ARG_OUT, "XIT" }, + { 'Y', "set_ant", funcAntenna, 'i', ARG_IN, "Antenna", "Option" }, + { 'y', "get_ant", funcAntenna, 'i', ARG_IN1 | ARG_OUT2 | ARG_NOVFO, "AntCurr", "Option", "AntTx", "AntRx" }, + { 0x87, "set_powerstat", funcPowerControl, 'b', ARG_IN | ARG_NOVFO, "Power Status" }, + { 0x88, "get_powerstat", funcPowerControl, 'b', ARG_OUT | ARG_NOVFO, "Power Status" }, + { 0x89, "send_dtmf", funcNone, 'i', ARG_IN, "Digits" }, + { 0x8a, "recv_dtmf", funcNone, 'i', ARG_OUT, "Digits" }, + { '*', "reset", funcNone, 'i', ARG_IN, "Reset" }, + { 'w', "send_cmd", funcNone, 'i', ARG_IN1 | ARG_IN_LINE | ARG_OUT2 | ARG_NOVFO, "Cmd", "Reply" }, + { 'W', "send_cmd_rx", funcNone, 'i', ARG_IN | ARG_OUT2 | ARG_NOVFO, "Cmd", "Reply"}, + { 'b', "send_morse", funcSendCW, 'i', ARG_IN | ARG_NOVFO | ARG_IN_LINE, "Morse" }, + { 0xbb, "stop_morse", funcSendCW, 'i', }, + { 0xbc, "wait_morse", funcSendCW, 'i', }, + { 0x94, "send_voice_mem", funcNone, 'i', ARG_IN, "Voice Mem#" }, + { 0x8b, "get_dcd", funcNone, 'i', ARG_OUT, "DCD" }, + { 0x8d, "set_twiddle", funcNone, 'i', ARG_IN | ARG_NOVFO, "Timeout (secs)" }, + { 0x8e, "get_twiddle", funcNone, 'i', ARG_OUT | ARG_NOVFO, "Timeout (secs)" }, + { 0x97, "uplink", funcNone, 'i', ARG_IN | ARG_NOVFO, "1=Sub, 2=Main" }, + { 0x95, "set_cache", funcNone, 'i', ARG_IN | ARG_NOVFO, "Timeout (msecs)" }, + { 0x96, "get_cache", funcNone, 'i', ARG_OUT | ARG_NOVFO, "Timeout (msecs)" }, + { '2', "power2mW", funcNone, 'i', ARG_IN1 | ARG_IN2 | ARG_IN3 | ARG_OUT1 | ARG_NOVFO, "Power [0.0..1.0]", "Frequency", "Mode", "Power mW" }, + { '4', "mW2power", funcNone, 'i', ARG_IN1 | ARG_IN2 | ARG_IN3 | ARG_OUT1 | ARG_NOVFO, "Pwr mW", "Freq", "Mode", "Power [0.0..1.0]" }, + { '1', "dump_caps", funcNone, 'i', ARG_NOVFO }, + { '3', "dump_conf", funcNone, 'i', ARG_NOVFO }, + { 0x8f, "dump_state", funcNone, 'i', ARG_OUT | ARG_NOVFO }, + { 0xf0, "chk_vfo", funcSelectVFO, 'v', ARG_NOVFO, "ChkVFO" }, /* rigctld only--check for VFO mode */ + { 0xf2, "set_vfo_opt", funcNone, 'i', ARG_NOVFO | ARG_IN, "Status" }, /* turn vfo option on/off */ + { 0xf3, "get_vfo_info", funcNone, 'i', ARG_IN1 | ARG_NOVFO | ARG_OUT5, "VFO", "Freq", "Mode", "Width", "Split", "SatMode" }, /* get several vfo parameters at once */ + { 0xf5, "get_rig_info", funcNone, 'i', ARG_NOVFO | ARG_OUT, "RigInfo" }, /* get several vfo parameters at once */ + { 0xf4, "get_vfo_list", funcNone, 'i', ARG_OUT | ARG_NOVFO, "VFOs" }, + { 0xf6, "get_modes", funcNone, 'i', ARG_OUT | ARG_NOVFO, "Modes" }, + { 0xf9, "get_clock", funcTime, 'i', ARG_NOVFO }, + { 0xf8, "set_clock", funcTime, 'i', ARG_IN | ARG_NOVFO, "YYYYMMDDHHMMSS.sss+ZZ" }, + { 0xf1, "halt", funcNone, 'i', ARG_NOVFO }, /* rigctld only--halt the daemon */ + { 0x8c, "pause", funcNone, 'i', ARG_IN, "Seconds" }, + { 0x98, "password", funcNone, 'i', ARG_IN | ARG_NOVFO, "Password" }, + { 0xf7, "get_mode_bandwidths", funcNone, 'i', ARG_IN | ARG_NOVFO, "Mode" }, + { 0xa0, "set_separator", funcSeparator, 'i', ARG_IN | ARG_NOVFO, "Separator" }, + { 0xa1, "get_separator", funcSeparator, 'i', ARG_NOVFO, "Separator" }, + { 0xa2, "set_lock_mode", funcLockFunction, 'i', ARG_IN | ARG_NOVFO, "Locked" }, + { 0xa3, "get_lock_mode", funcLockFunction, 'i', ARG_NOVFO, "Locked" }, + { 0xa4, "send_raw", funcNone, 'i', ARG_NOVFO | ARG_IN1 | ARG_IN2 | ARG_OUT3, "Terminator", "Command", "Send raw answer" }, + { 0xa5, "client_version", funcNone, 'i', ARG_NOVFO | ARG_IN1, "Version", "Client version" }, + { 0x00, "", funcNone, 0x0 }, +}; + + + rigCtlD::rigCtlD(QObject* parent) : QTcpServer(parent) { @@ -126,15 +350,18 @@ void rigCtlClient::socketReadyRead() commandBuffer.append(data); QStringList commandList(commandBuffer.split('\n')); QString sep = "\n"; - static int num = 0; + + int ret = -RIG_EINVAL; + + bool setCommand = false; + QStringList response; for (QString &commands : commandList) { - bool longReply = false; - char responseCode = 0; - QStringList response; - bool setCommand = false; - //commands.chop(1); // Remove \n + bool extended = false; + bool longCommand = false; + restart: + if (commands.endsWith('\r')) { commands.chop(1); // Remove \n character @@ -145,1392 +372,123 @@ void rigCtlClient::socketReadyRead() continue; } - qDebug(logRigCtlD()) << sessionId << "RX:" << commands; - // We have a full line so process command. - if (rigState == Q_NULLPTR) + if (commands[0] == ';' || commands[0] == '|' || commands[0] == ',') { - qInfo(logRigCtlD()) << "no rigState!"; - return; + sep = commands[0].toLatin1(); + commands.remove(0,1); } - - if (commands[num] == ';' || commands[num] == '|' || commands[num] == ',') + else if (commands[0] == '+') { - sep = commands[num].toLatin1(); - num++; - } - else if (commands[num] == '+') - { - longReply = true; + extended = true; sep = "\n"; - num++; + commands.remove(0,1); } - else if (commands[num] == '#') + else if (commands[0] == '#') { continue; } - else if (commands[num].toLower() == 'q') + else if (commands[0].toLower() == 'q') { closeSocket(); return; } - if (commands[num] == '\\') + + if (commands[0] == '\\') { - num++; + commands.remove(0,1); + longCommand = true; } - QStringList command = commands.mid(num).split(" "); - if (command[0] == "F" || command[0] == "set_freq") + QStringList command = commands.split(" "); + for (int i=0; commands_list[i].sstr != 0x00; i++) { - setCommand = true; - freqt freq; - bool ok=false; - double newFreq=0.0f; - quint8 vfo=0; - if (command.length() == 2) + if ((longCommand && !strncmp(command[0].toLocal8Bit(), commands_list[i].str,MAXNAMESIZE)) || + (!longCommand && !commands.isNull() && commands[0].toLatin1() == commands_list[i].sstr)) { - newFreq = command[1].toDouble(&ok); - } - else if (command.length() == 3) // Includes VFO - { - newFreq = command[2].toDouble(&ok); - if (command[1] == "VFOB") + command.removeFirst(); // Remove the actual command so it only contains params + + if (((commands_list[i].flags & ARG_IN) == ARG_IN)) { - vfo = 1; + // For debugging only REMOVE next line + qInfo(logRigCtlD()) << "Received set command" << commands; + setCommand=true; } - } - if (ok) { - freq.Hz = static_cast(newFreq); - qDebug(logRigCtlD()) << QString("Set frequency: %1 (%2)").arg(freq.Hz).arg(command[1]); - if (vfo == 0) { - rigState->set(VFOAFREQ, (quint64)freq.Hz,true); - } - else { - rigState->set(VFOBFREQ, (quint64)freq.Hz,true); - } - } - } - else if (command[0] == "f" || command[0] == "get_freq") - { - QString resp; - if (longReply) { - resp.append(QString("Frequency: ")); - } - - if (rigState->getChar(CURRENTVFO)==0) { - resp.append(QString("%1").arg(rigState->getInt64(VFOAFREQ))); - } - else { - resp.append(QString("%1").arg(rigState->getInt64(VFOBFREQ))); - } - - response.append(resp); - } - else if (command[0] == "M" || command[0] == "set_mode") - { - // Set mode - setCommand = true; - quint8 width = 0; - quint16 passband = 0; - QString vfo = "VFOA"; - QString mode = "USB"; - if (command.length() == 2) { - mode = command[1]; - } - else if (command.length() == 3) { - passband = command[2].toInt(); - mode = command[1]; - } - else if (command.length() == 4) { - passband = command[3].toInt(); - mode = command[2]; - vfo = command[1]; - } - - qDebug(logRigCtlD()) << "setting mode: VFO:" << vfo << getMode(mode) << mode << "passband" << passband << "command:" << commands; - - if (!mode.isEmpty()) - { - rigState->set(MODE, getMode(mode), true); - if (mode.mid(0, 3) == "PKT") { - rigState->set(DATAMODE, true, true); - } - else { - rigState->set(DATAMODE, false, true); - } - } - - if (passband > 0) - { - switch ((rigMode_t)getMode(mode)) { - - case modeAM: - if (passband > 6000) { - width = 1; - } - else if (passband > 3000 && passband <= 6000) { - width = 2; - } - else if (passband <= 3000) { - width = 3; - } - break; - - case modeFM: - if (passband > 10000) { - width = 1; - } - else if (passband > 7000 && passband <= 10000) { - width = 2; - } - else if (passband <= 7000) { - width = 3; - } - break; - - case modeCW: - case modeRTTY: - case modeCW_R: - case modeRTTY_R: - case modePSK: - if (passband > 500) { - width = 1; - } - else if (passband > 250 && passband <= 500) { - width = 2; - } - else if (passband <= 250) { - width = 3; - } - break; - - default: - if (passband > 2400) { - width = 1; - } - else if (passband > 1800 && passband <= 2400) { - width = 2; - } - else if (passband <= 1800) { - width = 3; - } - break; - - } - rigState->set(FILTER, width, true); - rigState->set(PASSBAND, passband, true); - } - } - else if (command[0] == "m" || command[0] == "get_mode") - { - if (longReply) { - response.append(QString("TX Mode: %1").arg(getMode(rigState->getChar(MODE), rigState->getBool(DATAMODE)))); - response.append(QString("TX Passband: %1").arg(rigState->getUInt16(PASSBAND))); - } - else { - response.append(QString("%1").arg(getMode(rigState->getChar(MODE), rigState->getBool(DATAMODE)))); - response.append(QString("%1").arg(rigState->getUInt16(PASSBAND))); - } - //qDebug(logRigCtlD()) << QString("get_mode: %1 passband: %2").arg(getMode(rigState->getChar(MODE), rigState->getBool(DATAMODE))).arg(rigState->getUInt16(PASSBAND)); - } - else if (command.length() > 1 && (command[0] == "V" || command[0] == "set_vfo")) - { - setCommand = true; - if (command[1] == "?") { - response.append("set_vfo: ?"); - response.append("VFOA"); - response.append("VFOB"); - response.append("Sub"); - response.append("Main"); - response.append("MEM"); - } - else if (command[1] == "VFOA" || command[1] == "Main") - { - rigState->set(CURRENTVFO, (quint8)0, true); - } - else if (command[1] == "VFOB" || command[1] == "Sub") - { - rigState->set(CURRENTVFO, (quint8)1, true); - } - else if (command[1] == "MEM") - { - rigState->set(CURRENTVFO, (quint8)2, true); - } - } - else if (command[0] == "v" || command[0] == "v\nv" || command[0] == "get_vfo") - { - QString resp; - if (longReply) { - resp.append("VFO: "); - } - - if (rigState->getChar(CURRENTVFO) == 0) { - resp.append("VFOA"); - } - else if (rigState->getChar(CURRENTVFO) == 1) { - resp.append("VFOB"); - } - else if (rigState->getChar(CURRENTVFO) == 2) { - resp.append("MEM"); - } - - response.append(resp); - } - else if (command[0] == "J" || command[0] == "set_rit") - { - rigState->set(RITVALUE, command[1].toInt(),true); - setCommand = true; - } - else if (command[0] == "j" || command[0] == "get_rit") - { - QString resp; - if (longReply) { - resp.append("RIT: "); - } - resp.append(QString("%1").arg(rigState->getInt32(RITVALUE))); - response.append(resp); - } - else if (command[0] == "Z" || command[0] == "set_xit") - { - setCommand = true; - } - else if (command[0] == "z" || command[0] == "get_xit") - { - QString resp; - if (longReply) { - resp.append("XIT: "); - } - resp.append(QString("%1").arg(0)); - response.append(resp); - } - else if (command.length() > 1 && (command[0] == "T" || command[0] == "set_ptt")) - { - setCommand = true; - if(rigCaps.commands.contains(funcTransceiverStatus)) { - rigState->set(PTT, (bool)command[1].toInt(), true); - } - else - { - responseCode = -1; - } - } - else if (command[0] == "t" || command[0] == "get_ptt") - { - if(rigCaps.commands.contains(funcTransceiverStatus)) { - QString resp; - if (longReply) { - resp.append(QString("PTT: ")); - } - resp.append(QString("%1").arg(rigState->getBool(PTT))); - response.append(resp); - } - else - { - responseCode = -1; - } - } - else if (command.length() > 0 && (command[0] == "0x0b" || command[0] == "get_dcd")) - { - response.append(QString("%1").arg((float)rigState->getChar(SQUELCH) / 255.0)); - } - else if (command.length() > 0 && (command[0] == "R" || command[0] == "set_rptr_shift")) - { - responseCode = -11; - } - else if (command.length() > 0 && (command[0] == "r" || command[0] == "get_rptr_shift")) - { - responseCode = -11; - } - else if (command.length() > 0 && (command[0] == "O" || command[0] == "set_rptr_offs")) - { - responseCode = -11; - } - else if (command.length() > 0 && (command[0] == "o" || command[0] == "get_rptr_offs")) - { - responseCode = -11; - } - else if (command.length() > 0 && (command[0] == "C" || command[0] == "set_ctcss_tone")) - { - responseCode = -11; - } - else if (command.length() > 0 && (command[0] == "c" || command[0] == "get_ctcss_tone")) - { - responseCode = -11; - } - else if (command.length() > 0 && (command[0] == "D" || command[0] == "set_dcs_tone")) - { - responseCode = -11; - } - else if (command.length() > 0 && (command[0] == "d" || command[0] == "get_dcs_tone")) - { - responseCode = -11; - } - else if (command.length() > 0 && (command[0] == "\x90" || command[0] == "set_ctcss_sql")) - { - responseCode = -11; - } - else if (command.length() > 0 && (command[0] == "\x91" || command[0] == "get_ctcss_sql")) - { - responseCode = -11; - } - else if (command.length() > 0 && (command[0] == "\x92" || command[0] == "set_dcs_sql")) - { - responseCode = -11; - } - else if (command.length() > 0 && (command[0] == "\x93" || command[0] == "get_dcs_sql")) - { - responseCode = -11; - } - else if (command[0] == "i" || command[0] == "get_split_freq") - { - QString resp; - if (longReply) { - resp.append("TX VFO: "); - } - - if (rigState->getInt64(CURRENTVFO) == 0) { - resp.append(QString("%1").arg(rigState->getInt64(VFOBFREQ))); - } - else { - resp.append(QString("%1").arg(rigState->getInt64(VFOAFREQ))); - } - - response.append(resp); - } - else if (command.length() > 1 && (command[0] == "I" || command[0] == "set_split_freq")) - { - setCommand = true; - bool ok = false; - double newFreq = 0.0f; - newFreq = command[1].toDouble(&ok); - if (ok) { - qDebug(logRigCtlD()) << QString("set_split_freq: %1 (%2)").arg(newFreq).arg(command[1]); - rigState->set(VFOBFREQ, static_cast(newFreq),false); - } - } - else if (command.length() > 2 && (command[0] == "X" || command[0] == "set_split_mode")) - { - setCommand = true; - } - - else if (command.length() > 0 && (command[0] == "x" || command[0] == "get_split_mode")) - { - if (longReply) { - response.append(QString("TX Mode: %1").arg(getMode(rigState->getChar(MODE), rigState->getBool(DATAMODE)))); - response.append(QString("TX Passband: %1").arg(rigState->getUInt16(PASSBAND))); - } - else { - response.append(QString("%1").arg(getMode(rigState->getChar(MODE), rigState->getBool(DATAMODE)))); - response.append(QString("%1").arg(rigState->getUInt16(PASSBAND))); - } - } - else if (command.length() > 1 && (command[0] == "S" || command[0] == "set_split_vfo")) - { - setCommand = true; - - if (command[1] == "1") - { - rigState->set(DUPLEX, dmSplitOn, true); - } - else { - rigState->set(DUPLEX, dmSplitOff, true); - } - } - else if (command[0] == "s" || command[0] == "get_split_vfo") - { - - if (longReply) { - response.append(QString("Split: %1").arg(rigState->getChar(DUPLEX))); - } - else { - response.append(QString("%1").arg(rigState->getChar(DUPLEX))); - } - - QString resp; - if (longReply) { - resp.append("TX VFO: "); - } - - - if (rigState->getChar(CURRENTVFO) == 0) - { - resp.append(QString("%1").arg("VFOB")); - } - else { - resp.append(QString("%1").arg("VFOA")); - } - - response.append(resp); - } - else if (command.length() > 0 && (command[0] == "N" || command[0] == "set_ts")) - { - responseCode = -11; - } - else if (command.length() > 0 && (command[0] == "n" || command[0] == "get_ts")) - { - responseCode = -11; - } - else if (command.length() >2 && (command[0] == "U" || command[0] == "set_func")) - { - setCommand = true; - - if (command[1] == "FAGC") - { - rigState->set(FAGCFUNC, (quint8)command[2].toInt(), true); - } - else if (command[1] == "NB") - { - rigState->set(NBFUNC, (quint8)command[2].toInt(), true); - } - else if (command[1] == "COMP") - { - rigState->set(COMPFUNC, (quint8)command[2].toInt(), true); - } - else if (command[1] == "VOX") - { - rigState->set(VOXFUNC, (quint8)command[2].toInt(), true); - } - else if (command[1] == "TONE") - { - rigState->set(TONEFUNC, (quint8)command[2].toInt(), true); - } - else if (command[1] == "TSQL") - { - rigState->set(TSQLFUNC, (quint8)command[2].toInt(), true); - } - else if (command[1] == "SBKIN") - { - rigState->set(SBKINFUNC, (quint8)command[2].toInt(), true); - } - else if (command[1] == "FBKIN") - { - rigState->set(FBKINFUNC, (quint8)command[2].toInt(), true); - } - else if (command[1] == "ANF") - { - rigState->set(ANFFUNC, (quint8)command[2].toInt(), true); - } - else if (command[1] == "NR") - { - rigState->set(NRFUNC, (quint8)command[2].toInt(), true); - } - else if (command[1] == "AIP") - { - rigState->set(AIPFUNC, (quint8)command[2].toInt(), true); - } - else if (command[1] == "APF") - { - rigState->set(APFFUNC, (quint8)command[2].toInt(), true); - } - else if (command[1] == "MON") - { - rigState->set(MONFUNC, (quint8)command[2].toInt(), true); - } - else if (command[1] == "MN") - { - rigState->set(MNFUNC, (quint8)command[2].toInt(), true); - } - else if (command[1] == "RF") - { - rigState->set(RFFUNC, (quint8)command[2].toInt(), true); - } - else if (command[1] == "ARO") - { - rigState->set(AROFUNC, (quint8)command[2].toInt(), true); - } - else if (command[1] == "MUTE") - { - rigState->set(MUTEFUNC, (quint8)command[2].toInt(), true); - } - else if (command[1] == "VSC") - { - rigState->set(VSCFUNC, (quint8)command[2].toInt(), true); - } - else if (command[1] == "REV") - { - rigState->set(REVFUNC, (quint8)command[2].toInt(), true); - } - else if (command[1] == "SQL") - { - rigState->set(SQLFUNC, (quint8)command[2].toInt(), true); - } - else if (command[1] == "ABM") - { - rigState->set(ABMFUNC, (quint8)command[2].toInt(), true); - } - else if (command[1] == "BC") - { - rigState->set(BCFUNC, (quint8)command[2].toInt(), true); - } - else if (command[1] == "MBC") - { - rigState->set(MBCFUNC, (quint8)command[2].toInt(), true); - } - else if (command[1] == "RIT") - { - rigState->set(RITFUNC, (quint8)command[2].toInt(), true); - } - else if (command[1] == "AFC") - { - rigState->set(AFCFUNC, (quint8)command[2].toInt(), true); - } - else if (command[1] == "SATMODE") - { - rigState->set(SATMODEFUNC, (quint8)command[2].toInt(), true); - } - else if (command[1] == "SCOPE") - { - rigState->set(SCOPEFUNC, (quint8)command[2].toInt(), true); - } - else if (command[1] == "RESUME") - { - rigState->set(RESUMEFUNC, (quint8)command[2].toInt(), true); - } - else if (command[1] == "TBURST") - { - rigState->set(TBURSTFUNC, (quint8)command[2].toInt(), true); - } - else if (command[1] == "TUNER") - { - rigState->set(TUNERFUNC, (quint8)command[2].toInt(), true); - } - else if (command[1] == "LOCK") - { - rigState->set(LOCKFUNC, (quint8)command[2].toInt(), true); - } - else { - qInfo(logRigCtlD()) << "Unimplemented func:" << command[0] << command[1] << command[2]; - } - - qInfo(logRigCtlD()) << "Setting:" << command[1] << command[2]; - } - else if (command.length()>1 && (command[0] == "u" || command[0] == "get_func")) - { - QString resp=""; - bool result = 0; - if (longReply) { - resp.append(QString("Func Status: ")); - } - if (command[1] == "FAGC") - { - result=rigState->getBool(FAGCFUNC); - } - else if (command[1] == "NB") - { - result = rigState->getBool(NBFUNC); - } - else if (command[1] == "COMP") - { - result=rigState->getBool(COMPFUNC); - } - else if (command[1] == "VOX") - { - result = rigState->getBool(VOXFUNC); - } - else if (command[1] == "TONE") - { - result = rigState->getBool(TONEFUNC); - } - else if (command[1] == "TSQL") - { - result = rigState->getBool(TSQLFUNC); - } - else if (command[1] == "SBKIN") - { - result = rigState->getBool(SBKINFUNC); - } - else if (command[1] == "FBKIN") - { - result = rigState->getBool(FBKINFUNC); - } - else if (command[1] == "ANF") - { - result = rigState->getBool (ANFFUNC); - } - else if (command[1] == "NR") - { - result = rigState->getBool(NRFUNC); - } - else if (command[1] == "AIP") - { - result = rigState->getBool(AIPFUNC); - } - else if (command[1] == "APF") - { - result = rigState->getBool(APFFUNC); - } - else if (command[1] == "MON") - { - result = rigState->getBool(MONFUNC); - } - else if (command[1] == "MN") - { - result = rigState->getBool(MNFUNC); - } - else if (command[1] == "RF") - { - result = rigState->getBool(RFFUNC); - } - else if (command[1] == "ARO") - { - result = rigState->getBool(AROFUNC); - } - else if (command[1] == "MUTE") - { - result = rigState->getBool(MUTEFUNC); - } - else if (command[1] == "VSC") - { - result = rigState->getBool(VSCFUNC); - } - else if (command[1] == "REV") - { - result = rigState->getBool(REVFUNC); - } - else if (command[1] == "SQL") - { - result = rigState->getBool(SQLFUNC); - } - else if (command[1] == "ABM") - { - result = rigState->getBool(ABMFUNC); - } - else if (command[1] == "BC") - { - result = rigState->getBool(BCFUNC); - } - else if (command[1] == "MBC") - { - result = rigState->getBool(MBCFUNC); - } - else if (command[1] == "RIT") - { - result = rigState->getBool(RITFUNC); - } - else if (command[1] == "AFC") - { - result = rigState->getBool(AFCFUNC); - } - else if (command[1] == "SATMODE") - { - result = rigState->getBool(SATMODEFUNC); - } - else if (command[1] == "SCOPE") - { - result = rigState->getBool(SCOPEFUNC); - } - else if (command[1] == "RESUME") - { - result = rigState->getBool(RESUMEFUNC); - } - else if (command[1] == "TBURST") - { - result = rigState->getBool(TBURSTFUNC); - } - else if (command[1] == "TUNER") - { - result = rigState->getBool(TUNERFUNC); - } - else if (command[1] == "LOCK") - { - result = rigState->getBool(LOCKFUNC); - } - else { - qInfo(logRigCtlD()) << "Unimplemented func:" << command[0] << command[1]; - } - - resp.append(QString("%1").arg(result)); - response.append(resp); - } - else if (command.length() > 2 && (command[0] == "L" || command[0] == "set_level")) - { - int value=0; - setCommand = true; - if (command[1] == "AF") { - value = command[2].toFloat() * 255; - rigState->set(AFGAIN, quint8(value), true); - } - else if (command[1] == "RF") { - value = command[2].toFloat() * 255; - rigState->set(RFGAIN, quint8(value), true); - } - else if (command[1] == "RFPOWER") { - value = command[2].toFloat() * 255; - rigState->set(RFPOWER, quint8(value), true); - } - else if (command[1] == "SQL") { - value = command[2].toFloat() * 255; - rigState->set(SQUELCH, quint8(value), true); - } - else if (command[1] == "COMP") { - value = command[2].toFloat() * 255; - rigState->set(COMPLEVEL, quint8(value), true); - } - else if (command[1] == "MICGAIN") { - value = command[2].toFloat() * 255; - rigState->set(MICGAIN, quint8(value), true); - } - else if (command[1] == "MON") { - value = command[2].toFloat() * 255; - rigState->set(MONITORLEVEL, quint8(value), true); - } - else if (command[1] == "VOXGAIN") { - value = command[2].toFloat() * 255; - rigState->set(VOXGAIN, quint8(value), true); - } - else if (command[1] == "ANTIVOX") { - value = command[2].toFloat() * 255; - rigState->set(ANTIVOXGAIN, quint8(value), true); - } - else if (command[1] == "ATT") { - value = command[2].toInt(); - rigState->set(ATTENUATOR, quint8(value), true); - } - else if (command[1] == "PREAMP") { - value = command[2].toFloat() / 10; - rigState->set(PREAMP, quint8(value), true); - } - else if (command[1] == "AGC") { - value = command[2].toFloat() * 255; - rigState->set(AGC, quint8(value), true); - } - else if (command[1] == "CWPITCH") { - value = command[2].toInt(); - rigState->set(CWPITCH, value, true); - } - else if (command[1] == "NOTCHF") { - value = command[2].toInt(); - rigState->set(NOTCHF, value, true); - } - else if (command[1] == "IF") { - value = command[2].toInt(); - rigState->set(IF, qint16(value), true); - } - else if (command[1] == "PBT_IN") { - value = command[2].toFloat() * 255; - rigState->set(PBTIN, quint8(value), true); - } - else if (command[1] == "PBT_OUT") { - value = command[2].toFloat() * 255; - rigState->set(PBTOUT, quint8(value), true); - } - else if (command[1] == "APF") { - value = command[2].toFloat() * 255; - rigState->set(APF, quint8(value), true); - } - else if (command[1] == "NR") { - value = command[2].toFloat() * 255; - rigState->set(NR, quint8(value), true); - } - else if (command[1] == "BAL") { - value = command[2].toFloat() * 255; - rigState->set(BAL, quint8(value), true); - } - else if (command[1] == "KEYSPD") { - value = command[2].toInt() * 5.1; - rigState->set(KEYSPD, quint8(value), true); - } - - qInfo(logRigCtlD()) << "Setting:" << command[1] << command[2] << value; - - } - else if (command.length() > 1 && (command[0] == "l" || command[0] == "get_level")) - { - QString resp; - int value = 0; - if (longReply) { - resp.append("Level Value: "); - } - - if (command[1] == "STRENGTH") { - - if (rigCaps.model == model7610) - value = getCalibratedValue(rigState->getChar(SMETER), IC7610_STR_CAL); - else if (rigCaps.model == model7850) - value = getCalibratedValue(rigState->getChar(SMETER), IC7850_STR_CAL); - else - value = getCalibratedValue(rigState->getChar(SMETER), IC7300_STR_CAL); - //qInfo(logRigCtlD()) << "Calibration IN:" << rigState->sMeter << "OUT" << value; - resp.append(QString("%1").arg(value)); - } - - else if (command[1] == "AF") { - resp.append(QString("%1").arg((float)rigState->getChar(AFGAIN) / 255.0)); - } - else if (command[1] == "RF") { - resp.append(QString("%1").arg((float)rigState->getChar(RFGAIN) / 255.0)); - } - else if (command[1] == "SQL") { - resp.append(QString("%1").arg((float)rigState->getChar(SQUELCH) / 255.0)); - } - else if (command[1] == "COMP") { - resp.append(QString("%1").arg((float)rigState->getChar(COMPLEVEL) / 255.0)); - } - else if (command[1] == "MICGAIN") { - resp.append(QString("%1").arg((float)rigState->getChar(MICGAIN) / 255.0)); - } - else if (command[1] == "MON") { - resp.append(QString("%1").arg((float)rigState->getChar(MONITORLEVEL) / 255.0)); - } - else if (command[1] == "VOXGAIN") { - resp.append(QString("%1").arg((float)rigState->getChar(VOXGAIN) / 255.0)); - } - else if (command[1] == "ANTIVOX") { - resp.append(QString("%1").arg((float)rigState->getChar(ANTIVOXGAIN) / 255.0)); - } - else if (command[1] == "RFPOWER") { - resp.append(QString("%1").arg((float)rigState->getChar(RFPOWER) / 255.0)); - } - else if (command[1] == "PREAMP") { - resp.append(QString("%1").arg(rigState->getChar(PREAMP)*10)); - } - else if (command[1] == "ATT") { - resp.append(QString("%1").arg(rigState->getChar(ATTENUATOR))); - } - else if (command[1] == "CWPITCH") { - resp.append(QString("%1").arg(rigState->getInt16(CWPITCH))); - } - else if (command[1] == "NOTCHF") { - resp.append(QString("%1").arg(rigState->getInt16(NOTCHF))); - } - else if (command[1] == "IF") { - resp.append(QString("%1").arg(rigState->getInt16(IF))); - } - else if (command[1] == "PBT_IN") { - resp.append(QString("%1").arg((float)rigState->getChar(PBTIN) / 255.0)); - } - else if (command[1] == "PBT_OUT") { - resp.append(QString("%1").arg((float)rigState->getChar(PBTOUT) / 255.0)); - } - else if (command[1] == "APF") { - resp.append(QString("%1").arg((float)rigState->getChar(APF) / 255.0)); - } - else if (command[1] == "NR") { - resp.append(QString("%1").arg((float)rigState->getChar(NR) / 255.0)); - } - else if (command[1] == "BAL") { - resp.append(QString("%1").arg((float)rigState->getChar(BAL) / 255.0)); - } - else if (command[1] == "KEYSPD") { - resp.append(QString("%1").arg(rigState->getChar(KEYSPD)/5.1)); - } - else { - resp.append(QString("%1").arg(value)); - } - - response.append(resp); - } - - else if (command.length() > 2 && (command[0] == "P" || command[0] == "set_parm")) - { - int value=0; - setCommand = true; - if (command[1] == "ANN") { - value = command[2].toInt(); - rigState->set(ANN, quint8(value), true); - } - else if (command[1] == "APO") { - value = command[2].toInt(); - rigState->set(APO, quint8(value), true); - } - else if (command[1] == "BACKLIGHT") { - value = command[2].toFloat() * 255; - rigState->set(BACKLIGHT, quint8(value), true); - } - else if (command[1] == "BEEP") { - value = command[2].toInt(); - rigState->set(BEEP, quint8(value), true); - } - else if (command[1] == "TIME") { - value = command[2].toLongLong(); - rigState->set(TIME, value, true); - } - else if (command[1] == "BAT") { - value = command[2].toFloat() * 255; - rigState->set(BAT, quint8(value), true); - } - else if (command[1] == "KEYLIGHT") { - value = command[2].toFloat() * 255; - rigState->set(KEYLIGHT, quint8(value), true); - } - else { - qInfo(logRigCtlD()) << "Unimplemented parm:" << command[0] << command[1]; - } - - qInfo(logRigCtlD()) << "Setting:" << command[1] << command[2] << value; - - } - else if (command.length() > 1 && (command[0] == "p" || command[0] == "get_parm")) - { - QString resp; - if (longReply) { - resp.append(QString("get_parm: %1%2").arg(command[1]).arg(sep)); - } - - if (command[1] == "ANN") { - resp.append(QString("%1").arg(rigState->getChar(ANN))); - } - else if (command[1] == "APO") { - resp.append(QString("%1").arg(rigState->getChar(APO))); - } - else if (command[1] == "BACKLIGHT") { - resp.append(QString("%1").arg((float)rigState->getChar(BACKLIGHT) / 255.0)); - } - else if (command[1] == "BEEP") { - resp.append(QString("%1").arg(rigState->getChar(BEEP))); - } - else if (command[1] == "TIME") { - resp.append(QString("%1").arg(rigState->getInt64(TIME))); - } - else if (command[1] == "BAT") { - resp.append(QString("%1").arg((float)rigState->getChar(BAT) / 255.0)); - } - else if (command[1] == "KEYLIGHT") { - resp.append(QString("%1").arg((float)rigState->getChar(KEYLIGHT) / 255.0)); - } - else { - qInfo(logRigCtlD()) << "Unimplemented parm:" << command[0] << command[1]; - } - - response.append(resp); - } - else if (command.length() > 0 && (command[0] == "B" || command[0] == "set_bank")) - { - responseCode = -11; - } - else if (command.length() > 0 && (command[0] == "b" || command[0] == "get_bank")) - { - responseCode = -11; - } - else if (command.length() > 0 && (command[0] == "E" || command[0] == "set_mem")) - { - responseCode = -11; - } - else if (command.length() > 0 && (command[0] == "e" || command[0] == "get_mem")) - { - responseCode = -11; - } - else if (command.length() > 0 && (command[0] == "G" || command[0] == "vfo_op")) - { - responseCode = -11; - } - else if (command.length() > 0 && (command[0] == "g" || command[0] == "scan")) - { - responseCode = -11; - } - else if (command.length() > 0 && (command[0] == "H" || command[0] == "set_channel")) - { - responseCode = -11; - } - else if (command.length() > 0 && (command[0] == "A" || command[0] == "set_trn")) - { - responseCode = -11; - } - else if (command.length() > 0 && (command[0] == "a" || command[0] == "get_trn")) - { - responseCode = -11; - } - else if (command.length() > 1 && (command[0] == "Y" || command[0] == "set_ant")) - { - setCommand = true; - qInfo(logRigCtlD()) << "set_ant:" << command[1]; - rigState->set(ANTENNA,antFromName(command[1]),true); - } - else if (command[0] == "y" || command[0] == "get_ant") - { - qInfo(logRigCtlD()) << "get_ant:"; - - if (command.length() > 1) { - if (longReply) { - response.append(QString("AntCurr: %1").arg(getAntName((quint8)command[1].toInt()))); - response.append(QString("Option: %1").arg(0)); - response.append(QString("AntTx: %1").arg(getAntName(rigState->getChar(ANTENNA)))); - response.append(QString("AntRx: %1").arg(getAntName(rigState->getChar(ANTENNA)))); - } - else { - response.append(QString("%1").arg(getAntName((quint8)command[1].toInt()))); - response.append(QString("%1").arg(0)); - response.append(QString("%1").arg(getAntName(rigState->getChar(ANTENNA)))); - response.append(QString("%1").arg(getAntName(rigState->getChar(ANTENNA)))); - } - } - } - else if (command.length() > 0 && (command[0] == "*" || command[0] == "reset")) - { - responseCode = -11; //Unimplemented - } - else if (command.length() > 0 && (command[0] == "b" || command[0] == "send_morse")) - { - responseCode = -11; //Unimplemented - } - else if (command.length() > 1 && (command[0] == '\x87' || command[0] == "set_powerstat")) - { - setCommand = true; - if (command[1] == "0") - { - rigState->set(POWERONOFF, false, true); - } - else { - rigState->set(POWERONOFF, true, true); - } - } - else if (command.length() > 0 && (command[0] == '\x88' || command[0] == "get_powerstat")) - { - - QString resp; - if (longReply) { - resp.append(QString("Power Status: ")); - } - resp.append(QString("%1").arg(1)); // Always reply with ON - response.append(resp); - - } - else if (command.length() > 0 && (command[0] == "\x89" || command[0] == "send_dtmf")) - { - responseCode = -11; //Unimplemented - } - else if (command.length() > 0 && (command[0] == "\x8a" || command[0] == "recv_dtmf")) - { - responseCode = -11; //Unimplemented - } - else if (command.length() > 0 && (command[0] == "_" || command[0] == "get_info")) - { - response.append("None"); - } - else if (command.length() > 0 && (command[0] == '\xf5' || command[0] == "get_rig_info")) - { - duplexMode_t split = rigState->getDuplex(DUPLEX); - quint8 rxa = 1; - quint8 txa = split == 0; - quint8 rxb = !rxa; - quint8 txb = split == 1; - QString resp = QString("VFO=%0 Freq=%1 Mode=%2 Width=%3 RX=%4 TX=%5\nVFO=%6 Freq=%7 Mode=%8 Width=%9 RX=%10 TX=%11\nSplit=%12 SatMode=%13\nRig=%14\nApp=wfview\nVersion=%15\n") - .arg(getVfoName(0)).arg(rigState->getInt64(VFOAFREQ)).arg(getMode(rigState->getChar(MODE), rigState->getBool(DATAMODE))).arg(rigState->getUInt16(PASSBAND)).arg(rxa).arg(txa) - .arg(getVfoName(1)).arg(rigState->getInt64(VFOBFREQ)).arg(getMode(rigState->getChar(MODE), rigState->getBool(DATAMODE))).arg(rigState->getUInt16(PASSBAND)).arg(rxb).arg(txb) - .arg(split).arg(rigState->getChar(SATMODEFUNC)).arg(rigCaps.modelName).arg(WFVIEW_VERSION); - unsigned long crc = doCrc((unsigned char*)resp.toStdString().c_str(), resp.length()); - resp = resp + QString("CRC=0x%0").arg(crc, 8, 16, QLatin1Char('0')); - response.append(resp); - } - else if (command[0] == "\xf3" || command[0] == "get_vfo_info") - { - if (longReply) { - if (command[1] == "?") { - if (rigState->getChar(CURRENTVFO) == 0) { - response.append(QString("set_vfo: VFOA")); - } - else - { - response.append(QString("set_vfo: VFOB")); - } - } - if (command[1] == "VFOB") { - response.append(QString("Freq: %1").arg(rigState->getInt64(VFOBFREQ))); - } - else { - response.append(QString("Freq: %1").arg(rigState->getInt64(VFOAFREQ))); - } - response.append(QString("Mode: %1").arg(getMode(rigState->getChar(MODE), rigState->getBool(DATAMODE)))); - response.append(QString("Width: %1").arg(rigState->getUInt16(PASSBAND))); - - response.append(QString("Split: %1").arg(rigState->getDuplex(DUPLEX))); - response.append(QString("SatMode: %1").arg(0)); // Need to get satmode - } - else { - if (command[1] == "VFOB") { - response.append(QString("%1").arg(rigState->getInt64(VFOBFREQ))); - } - else { - response.append(QString("%1").arg(rigState->getInt64(VFOAFREQ))); - } - response.append(QString("%1").arg(getMode(rigState->getChar(MODE), rigState->getBool(DATAMODE)))); - response.append(QString("%1").arg(rigState->getUInt16(PASSBAND))); - - } - } - else if (command[0] == "dump_state") - { - quint64 modes = getRadioModes(); - - // rigctld protocol version - response.append("1"); - // Radio model - response.append(QString("%1").arg(rigCaps.rigctlModel)); - // Print something (used to be ITU region) - response.append("0"); - // Supported RX bands (startf,endf,modes,low_power,high_power,vfo,ant) - quint32 lowFreq = 0; - quint32 highFreq = 0; - for (bandType band : rigCaps.bands) - { - if (lowFreq == 0 || band.lowFreq < lowFreq) - lowFreq = band.lowFreq; - if (band.highFreq > highFreq) - highFreq = band.highFreq; - } - response.append(QString("%1.000000 %2.000000 0x%3 %4 %5 0x%6 0x%7").arg(lowFreq).arg(highFreq) - .arg(modes, 0, 16).arg(-1).arg(-1).arg(0x16000000, 0, 16).arg(getAntennas(), 0, 16)); - response.append("0 0 0 0 0 0 0"); - - if (rigCaps.hasTransmit) { - // Supported TX bands (startf,endf,modes,low_power,high_power,vfo,ant) - for (bandType band : rigCaps.bands) + if (commands_list[i].func == funcRigctlFunction) { - response.append(QString("%1.000000 %2.000000 0x%3 %4 %5 0x%6 0x%7").arg(band.lowFreq).arg(band.highFreq) - .arg(modes, 0, 16).arg(2000).arg(100000).arg(0x16000000, 0, 16).arg(getAntennas(), 0, 16)); - } - } - response.append("0 0 0 0 0 0 0"); - - response.append(QString("0x%1 1").arg(modes, 0, 16)); - response.append(QString("0x%1 10").arg(modes, 0, 16)); - response.append(QString("0x%1 100").arg(modes, 0, 16)); - response.append(QString("0x%1 1000").arg(modes, 0, 16)); - response.append(QString("0x%1 2500").arg(modes, 0, 16)); - response.append(QString("0x%1 5000").arg(modes, 0, 16)); - response.append(QString("0x%1 6125").arg(modes, 0, 16)); - response.append(QString("0x%1 8333").arg(modes, 0, 16)); - response.append(QString("0x%1 10000").arg(modes, 0, 16)); - response.append(QString("0x%1 12500").arg(modes, 0, 16)); - response.append(QString("0x%1 25000").arg(modes, 0, 16)); - response.append(QString("0x%1 100000").arg(modes, 0, 16)); - response.append(QString("0x%1 250000").arg(modes, 0, 16)); - response.append(QString("0x%1 1000000").arg(modes, 0, 16)); - response.append("0 0"); - - modes = getRadioModes("SB"); - if (modes) { - response.append(QString("0x%1 3000").arg(modes, 0, 16)); - response.append(QString("0x%1 2400").arg(modes, 0, 16)); - response.append(QString("0x%1 1800").arg(modes, 0, 16)); - } - modes = getRadioModes("AM"); - if (modes) { - response.append(QString("0x%1 9000").arg(modes, 0, 16)); - response.append(QString("0x%1 6000").arg(modes, 0, 16)); - response.append(QString("0x%1 3000").arg(modes, 0, 16)); - } - modes = getRadioModes("CW"); - if (modes) { - response.append(QString("0x%1 1200").arg(modes, 0, 16)); - response.append(QString("0x%1 500").arg(modes, 0, 16)); - response.append(QString("0x%1 200").arg(modes, 0, 16)); - } - modes = getRadioModes("FM"); - if (modes) { - response.append(QString("0x%1 15000").arg(modes, 0, 16)); - response.append(QString("0x%1 10000").arg(modes, 0, 16)); - response.append(QString("0x%1 7000").arg(modes, 0, 16)); - } - modes = getRadioModes("RTTY"); - if (modes) { - response.append(QString("0x%1 2400").arg(modes, 0, 16)); - response.append(QString("0x%1 500").arg(modes, 0, 16)); - response.append(QString("0x%1 250").arg(modes, 0, 16)); - } - modes = getRadioModes("PSK"); - if (modes) { - response.append(QString("0x%1 1200").arg(modes, 0, 16)); - response.append(QString("0x%1 500").arg(modes, 0, 16)); - response.append(QString("0x%1 250").arg(modes, 0, 16)); - } - response.append("0 0"); - response.append("9900"); - response.append("9900"); - response.append("10000"); - response.append("0"); - QString preamps=""; - if(rigCaps.commands.contains(funcPreamp)) { - foreach (auto pre, rigCaps.preamps) + ret = getSubCommand(response, extended, commands_list[i], functions_str, command); + commands.clear(); + break; + } else if (commands_list[i].func == funcRigctlLevel) { - if (pre.num == 0) - continue; - preamps.append(QString("%1 ").arg(pre.num*10,0,16)); - } - if (preamps.endsWith(" ")) - preamps.chop(1); - } - else { - preamps = "0"; - } - response.append(preamps); - - QString attens = ""; - if(rigCaps.commands.contains(funcAttenuator)) { - for (auto att : rigCaps.attenuators) + ret = getSubCommand(response, extended, commands_list[i], levels_str, command); + commands.clear(); + break; + } else if (commands_list[i].func == funcRigctlParam) { - if (att == 0) - continue; - attens.append(QString("%1 ").arg(att,0,16)); + ret = getSubCommand(response, extended, commands_list[i], params_str, command); + commands.clear(); + break; + } else if (commands_list[i].sstr == 0x8f) + { + ret = dumpState(response, extended); + break; + } else if (commands_list[i].sstr == '1') + { + ret = dumpCaps(response, extended); + setCommand=true; + break; + } else if (commands_list[i].sstr == '3') + { + response.append("Model: WFVIEW"); + ret = RIG_OK; + break; + } else if (commands_list[i].sstr == 0xf0) + { + chkVfoEecuted = true; + //ret = RIG_OK; + //break; } - if (attens.endsWith(" ")) - attens.chop(1); + // Special commands are funcNone so will not get called here + if (commands_list[i].func != funcNone) { + ret = getCommand(response, extended, commands_list[i],command); + } + break; } - else { - attens = "0"; - } - response.append(attens); - - response.append("0xffffffffffffffff"); - response.append("0xffffffffffffffff"); - response.append("0xffffffffffffffff"); - response.append("0xffffffffffffffff"); - response.append("0xffffffffffffffff"); - response.append("0xffffffffffffffff"); - - if (chkVfoEecuted) { - response.append(QString("vfo_ops=0x%1").arg(255, 0, 16)); - response.append(QString("ptt_type=0x%1").arg(rigCaps.hasTransmit, 0, 16)); - response.append(QString("has_set_vfo=0x%1").arg(1, 0, 16)); - response.append(QString("has_get_vfo=0x%1").arg(1, 0, 16)); - response.append(QString("has_set_freq=0x%1").arg(1, 0, 16)); - response.append(QString("has_get_freq=0x%1").arg(1, 0, 16)); - response.append(QString("has_set_conf=0x%1").arg(1, 0, 16)); - response.append(QString("has_get_conf=0x%1").arg(1, 0, 16)); - response.append(QString("has_power2mW=0x%1").arg(1, 0, 16)); - response.append(QString("has_mW2power=0x%1").arg(1, 0, 16)); - response.append(QString("timeout=0x%1").arg(1000, 0, 16)); - response.append("done"); - } - } - - /* Fake command to resolve parsing error */ - else if (command[0] == "fmv") { - QString resp; - - if (rigState->getChar(CURRENTVFO) == 0) { - resp.append(QString("%1").arg(rigState->getInt64(VFOAFREQ))); - } - else { - resp.append(QString("%1").arg(rigState->getInt64(VFOBFREQ))); - } - response.append(resp); - resp = ""; - response.append(QString("%1").arg(getMode(rigState->getChar(MODE), rigState->getBool(DATAMODE)))); - response.append(QString("%1").arg(rigState->getUInt16(PASSBAND))); - - if (rigState->getChar(CURRENTVFO) == 0) { - resp.append("VFOA"); - } - else { - resp.append("VFOB"); - } - response.append(resp); - } - else if (command[0] == "1" || command[0] == "dump_caps") - { - response.append(QString("Caps dump for model: %1").arg(rigCaps.modelID)); - response.append(QString("Model Name:\t%1").arg(rigCaps.modelName)); - response.append(QString("Mfg Name:\tIcom")); - response.append(QString("Backend version:\t0.1")); - response.append(QString("Backend copyright:\t2021")); - if (rigCaps.hasTransmit) { - response.append(QString("Rig type:\tTransceiver")); - } - else - { - response.append(QString("Rig type:\tReceiver")); - } - if(rigCaps.commands.contains(funcTransceiverStatus)) { - response.append(QString("PTT type:\tRig capable")); - } - response.append(QString("DCD type:\tRig capable")); - response.append(QString("Port type:\tNetwork link")); - } - else if (command.length() > 0 && (command[0] == "2" || command[0] == "power2mW")) - { - responseCode = -11; //Unimplemented - } - else if (command.length() > 0 && (command[0] == "3" || command[0] == "mW2power")) - { - responseCode = -11; //Unimplemented - } - else if (command.length() > 0 && (command[0] == "set_clock")) - { - responseCode = -11; //Unimplemented - } - else if (command.length() > 0 && (command[0] == "get_clock")) - { - responseCode = -11; //Unimplemented - } - else if (command[0] == '\xf0' || command[0] == "chk_vfo") - { - chkVfoEecuted = true; - QString resp; - if (longReply) { - resp.append(QString("ChkVFO: ")); - } - resp.append(QString("%1").arg(rigState->getChar(CURRENTVFO))); - response.append(resp); - } - else if (command.length() > 0 && (command[0] == "set_vfo_opt")) - { - responseCode = -11; //Unimplemented - } - else if (command.length() > 0 && (command[0] == '\xa2' || command[0] == "set_lock_mode")) - { - responseCode = -11; //Unimplemented - } - else if (command.length() > 0 && (command[0] == '\xa3' || command[0] == "get_lock_mode")) - { - QString resp; - if (longReply) { - resp.append(QString("Locked: ")); - } - resp.append(QString("%1").arg(0)); // Always reply with RIG_OK (0) - response.append(resp); - } - - else if (command.length() > 0 && (command[0] == "w" || command[0] == "send_cmd")) - { - responseCode = -11; //Unimplemented - } - else { - qInfo(logRigCtlD()) << "Unimplemented command" << commands; - } - if (longReply) { - if (command.length() == 2) - sendData(QString("%1: %2%3").arg(command[0]).arg(command[1]).arg(sep)); - if (command.length() == 3) - sendData(QString("%1: %2 %3%4").arg(command[0]).arg(command[1]).arg(command[2]).arg(sep)); - if (command.length() == 4) - sendData(QString("%1: %2 %3 %4%5").arg(command[0]).arg(command[1]).arg(command[2]).arg(command[3]).arg(sep)); } if (setCommand) { - // This was a set command so state has likely been updated. - emit parent->stateUpdated(); + break; // Cannot be a compound command so just output result. } - if (setCommand || responseCode != 0 || longReply) { - if (responseCode == 0) { - response.append(QString("RPRT 0")); - } - else { - response.append(QString("RPRT %1").arg(responseCode)); - } - } - - for (QString str : response) - { - if (str != "") - sendData(QString("%1%2").arg(str).arg(sep)); - } - if (sep != "\n") { - sendData(QString("\n")); + if (!longCommand && !commands.isEmpty()){ + commands.remove(0,1); + goto restart; // Need to restart loop without going to next command incase of compound command } sep = "\n"; - num = 0; } + + // We have finished parsing all commands and have a response to send (hopefully) commandBuffer.clear(); + foreach (QString str, response) + { + if (!str.isEmpty()) + sendData(QString("%1%2").arg(str,sep)); + } + + if (sep != "\n") { + sendData(QString("\n")); + } + if (ret < 0 || setCommand ) + sendData(QString("RPRT %1\n").arg(ret)); } void rigCtlClient::socketDisconnected() @@ -1616,108 +574,43 @@ QString rigCtlClient::getFilter(quint8 mode, quint8 filter) { return QString(""); } -QString rigCtlClient::getMode(quint8 mode, bool datamode) { - - QString ret; - - - switch (mode) { - case modeLSB: - if (datamode) { ret = "PKT"; } - ret.append("LSB"); - break; - case modeUSB: - if (datamode) { ret = "PKT"; } - ret.append("USB"); - break; - case modeAM: - if (datamode) { ret = "PKT"; } - ret.append("AM"); - break; - case modeCW: - ret.append("CW"); - break; - case modeRTTY: - ret.append("RTTY"); - break; - case modeFM: - if (datamode) { ret = "PKT"; } - ret.append("FM"); - break; - case modeWFM: - ret.append("WFM"); - break; - case modeCW_R: - ret.append("CWR"); - break; - case modeRTTY_R: - ret.append("RTTYR"); - break; - case modePSK: - if (datamode) { ret = "PKT"; } - ret.append("USB"); - break; - case modeDV: - if (datamode) { ret = "PKT"; } - ret.append("LSB"); - break; - case 22: // We don't seem to have a mode for this? - if (datamode) { ret = "PKT"; } - ret.append("FM"); - break; +QString rigCtlClient::getMode(modeInfo mode) +{ + for (int i = 0; mode_str[i].str[0] != '\0'; i++) + { + if (mode_str[i].mk == mode.mk && mode_str[i].data == mode.data) + { + return(QString(mode_str[i].str)); + } } - return ret; + return("UNKNOWN"); } -quint8 rigCtlClient::getMode(QString modeString) { - - if (modeString == QString("LSB")) { - return 0; +bool rigCtlClient::getMode(QString modeString, modeInfo& mode) +{ + for (int i = 0; mode_str[i].str[0] != '\0'; i++) + { + if (QString(mode_str[i].str) == modeString) + { + foreach (auto m, rigCaps.modes) + { + if (m.mk == mode_str[i].mk) + { + mode = modeInfo(m); + mode.data = mode_str[i].data; + return true; + } + } + } } - else if (modeString == QString("USB")) { - return 1; - } - else if (modeString == QString("AM")) { - return 2; - } - else if (modeString == QString("CW")) { - return 3; - } - else if (modeString == QString("RTTY")) { - return 4; - } - else if (modeString == QString("FM")) { - return 5; - } - else if (modeString == QString("WFM")) { - return 6; - } - else if (modeString == QString("CWR")) { - return 7; - } - else if (modeString == QString("RTTYR")) { - return 8; - } - else if (modeString == QString("PKTUSB")) { - return 1; - } - else if (modeString == QString("PKTLSB")) { - return 0; - } - else if (modeString == QString("PKTFM")) { - return 22; - } - else { - return 0; - } - return 0; + return false; } quint8 rigCtlClient::getAntennas() { quint8 ant=0; - for (auto i : rigCaps.antennas) + foreach (auto i, rigCaps.antennas) { ant |= 1<(params[0].toInt())); + } + if (cmd.type == 's') { + val.setValue(static_cast(params[0].toInt())); + qInfo(logRigCtlD()) << "Setting short value" << val << "original" << params[0]; + } + else if (cmd.type == 'f') { + val.setValue(static_cast(float(params[0].toFloat() * 255.0))); // rigctl sends 0.0-1.0, we expect 0-255 + qInfo(logRigCtlD()) << "Setting float value" << val << "original" << params[0]; + } + else if (cmd.type == 'g') { + val.setValue(static_cast(float(params[0].toFloat() / 10.0))); + } + else if (cmd.type == 'h') { + val.setValue(static_cast(float(params[0].toFloat() * 5.1))); + } + else if (cmd.type == 'b') { + val.setValue(static_cast(params[0].toInt())); + } + else if (cmd.type == 'x') { + freqt f; + f.Hz = static_cast(params[0].toFloat()); + f.VFO = activeVFO; + f.MHzDouble = f.Hz/1000000.0; + val.setValue(f); + qInfo(logRigCtlD()) << "Setting" << funcString[func] << "to" << f.Hz << "on VFO" << f.VFO << "with" << params[0]; + } + else if (cmd.type == 'm') { + modeInfo mi; + if (getMode(params[0],mi)) + { + val.setValue(mi); + } + } + else + { + qInfo(logRigCtlD()) << "Unable to parse value of type" << cmd.type; + return -RIG_EINVAL; + } + queue->addUnique(priorityImmediate, queueItem(func, val)); + + } else { + // Simple get command + cacheItem item = queue->getCache(func); + ret = RIG_OK; + if (cmd.type == 'b') { + bool b = item.value.toBool(); + if (extended) + { + if (cmd.arg1 != NULL) + response.append(QString("%0: %1").arg(cmd.arg1, b)); + } + else + { + response.append(QString::number(b)); + } + } + else if (cmd.type == 'i' || cmd.type == 's') { + int i = item.value.toInt(); + if (extended) + { + if (cmd.arg1 != NULL) + response.append(QString("%0: %1").arg(cmd.arg1, i)); + } + else + { + response.append(QString::number(i)); + } + } + else if (cmd.type == 'f') { + float f = item.value.toFloat() / 255.0; + if (extended) + { + if (cmd.arg1 != NULL) + response.append(QString("%0: %1").arg(cmd.arg1, f)); + } + else + { + response.append(QString::number(f,'F',6)); + } + } + else if (cmd.type == 'g') { + float f = item.value.toFloat() * 10; + if (extended) + { + if (cmd.arg1 != NULL) + response.append(QString("%0: %1").arg(cmd.arg1, f)); + } + else + { + response.append(QString::number(f,'F',6)); + } + } + else if (cmd.type == 'h') { + float f = item.value.toFloat() / 5.1; + if (extended) + { + if (cmd.arg1 != NULL) + response.append(QString("%0: %1").arg(cmd.arg1, f)); + } + else + { + response.append(QString::number(f,'F',6)); + } + } + else if (cmd.type == 'x') { // Frequency + freqt f = item.value.value(); + //qInfo(logRigCtlD()) << "Got Freq" << funcString[func] << f.Hz << "on VFO" << f.VFO; + if (extended) + { + if (cmd.arg1 != NULL) + response.append(QString("%0: %1").arg(cmd.arg1, f.Hz)); + } + else + { + response.append(QString::number(f.Hz,'F',6)); + } + } + else if (cmd.type == 'v') { // VFO + uchar v = item.value.value(); + if (extended) + { + if (cmd.arg1 != NULL) + response.append(QString("%0: %1").arg(cmd.arg1, getVfoName(v))); + } + else + { + response.append(getVfoName(v)); + } + } + else if (cmd.type == 'm') { // Mode + modeInfo m = item.value.value(); + if (extended) + { + + if (cmd.arg1 != NULL) + response.append(QString("%0: %1").arg(cmd.arg1, getMode(m))); + if (cmd.arg2 != NULL) + response.append(QString("%0: %1").arg(cmd.arg2, m.pass)); + } + else + { + response.append(QString("%0").arg(getMode(m))); + response.append(QString("%0").arg(m.pass)); + } + } else { + qInfo(logRigCtlD()) << "Unsupported type (FIXME):" << item.value.typeName(); + ret = -RIG_EINVAL; + return ret; + } + + } + + return ret; +} + + +int rigCtlClient::getSubCommand(QStringList& response, bool extended, const commandStruct cmd, const subCommandStruct sub[], QStringList params) +{ + int ret = -RIG_EINVAL; + + QString resp; + // Get the required subCommand and process it + if (params.isEmpty()) + { + return ret; + } + + if (params[0][0].toLatin1() == '?') + { + for (int i=0; sub[i].str[0] != '\0' ;i++) + { + if (sub[i].func != funcNone && rigCaps.commands.contains(sub[i].func)) { + resp.append(sub[i].str); + resp.append(" "); + } + } + } + else + { + for (int i = 0 ; sub[i].str[0] != '\0'; i++) + { + if (!strncmp(params[0].toLocal8Bit(),sub[i].str,MAXNAMESIZE)) + { + ret = RIG_OK; + + if (((cmd.flags & ARG_IN) == ARG_IN) && params.size() > 1) + { + // We are expecting a second argument to the command + QVariant val; + if (sub[i].type == 'i') { + uchar v = static_cast(params[1].toInt()); + if (params[0] == "FBKIN") + v = (v << 1) & 0x02; // BREAKIN is not bool! + val.setValue(v); + } + else if (sub[i].type == 'f') { + val.setValue(static_cast(float(params[1].toFloat() * 255.0))); // rigctl sends 0.0-1.0, we expect 0-255 + qInfo(logRigCtlD()) << "Setting float value" << params[0] << "to" << val << "original" << params[1]; + } + else if (sub[i].type == 'g') { + val.setValue(static_cast(float(params[1].toFloat() / 10.0))); + } + else if (sub[i].type == 'h') { + val.setValue(static_cast(float(params[1].toFloat() * 5.1))); + } + else if (sub[i].type == 'b') { + val.setValue(static_cast(params[1].toInt())); + } + else + { + qInfo(logRigCtlD()) << "Unable to parse value of type" << sub[i].type; + return -RIG_EINVAL; + } + queue->addUnique(priorityImmediate, queueItem(sub[i].func, val)); + } else if (params.size() == 1){ + // Not expecting a second argument as it is a get so dump the cache + cacheItem item = queue->getCache(sub[i].func); + int val = 0; + // Special situation for S-Meter + if (params[0] == "STRENGTH") { + if (rigCaps.model == model7610) + val = getCalibratedValue(item.value.toUInt(), IC7610_STR_CAL); + else if (rigCaps.model == model7850) + val = getCalibratedValue(item.value.toUInt(), IC7850_STR_CAL); + else + val = getCalibratedValue(item.value.toUInt(), IC7300_STR_CAL); + resp.append(QString("%1").arg(val)); + } + else + { + if (sub[i].type == 'b') { + resp.append(QString("%1").arg(item.value.toBool())); + } + else if (sub[i].type == 'i') { + int val = item.value.toInt(); + if (params[0] == "FBKIN") + val = (val >> 1) & 0x01; + resp.append(QString::number(val,16)); // Base 16 + } + else if (sub[i].type == 'f') { + resp.append(QString::number(item.value.toFloat() / 255.0,'F',6)); + } + else if (sub[i].type == 'g') { + resp.append(QString::number(item.value.toFloat() * 10.0,'F',6)); + } + else if (sub[i].type == 'h') { + resp.append(QString::number(item.value.toFloat()/5.1,'F',6)); + } else { + qInfo(logRigCtlD()) << "Unhandled:" << item.value.toUInt() << "OUT" << val; + ret = -RIG_EINVAL; + } + } + if (extended && cmd.arg2 != NULL) + { + response.append(QString("%0: %1").arg(cmd.str, params[0])); + response.append(QString("%0: %1").arg(cmd.arg2, resp)); + } + else + { + response.append(resp); + } + } else { + qInfo(logRigCtlD()) << "Invalid number of params" << params.size(); + ret = -RIG_EINVAL; + } + break; + } + } + } + return ret; +} + + +int rigCtlClient::dumpState(QStringList &response, bool extended) +{ + Q_UNUSED(extended) + + quint64 modes = getRadioModes(); + + // rigctld protocol version + response.append("1"); + // Radio model + response.append(QString::number(rigCaps.rigctlModel)); + // Print something (used to be ITU region) + response.append("0"); + // Supported RX bands (startf,endf,modes,low_power,high_power,vfo,ant) + quint32 lowFreq = 0; + quint32 highFreq = 0; + for (bandType band : rigCaps.bands) + { + if (lowFreq == 0 || band.lowFreq < lowFreq) + lowFreq = band.lowFreq; + if (band.highFreq > highFreq) + highFreq = band.highFreq; + } + response.append(QString("%1.000000 %2.000000 0x%3 %4 %5 0x%6 0x%7").arg(lowFreq).arg(highFreq) + .arg(modes, 0, 16).arg(-1).arg(-1).arg(0x16000000, 0, 16).arg(getAntennas(), 0, 16)); + response.append("0 0 0 0 0 0 0"); + + if (rigCaps.hasTransmit) { + // Supported TX bands (startf,endf,modes,low_power,high_power,vfo,ant) + for (bandType band : rigCaps.bands) + { + response.append(QString("%1.000000 %2.000000 0x%3 %4 %5 0x%6 0x%7").arg(band.lowFreq).arg(band.highFreq) + .arg(modes, 0, 16).arg(2000).arg(100000).arg(0x16000000, 0, 16).arg(getAntennas(), 0, 16)); + } + } + response.append("0 0 0 0 0 0 0"); + foreach (auto step, rigCaps.steps) + { + if (step.num > 0) + response.append(QString("0x%1 %2").arg(modes, 0, 16).arg(step.hz)); + } + response.append("0 0"); + + modes = getRadioModes("SB"); + if (modes) { + response.append(QString("0x%1 3000").arg(modes, 0, 16)); + response.append(QString("0x%1 2400").arg(modes, 0, 16)); + response.append(QString("0x%1 1800").arg(modes, 0, 16)); + } + modes = getRadioModes("AM"); + if (modes) { + response.append(QString("0x%1 9000").arg(modes, 0, 16)); + response.append(QString("0x%1 6000").arg(modes, 0, 16)); + response.append(QString("0x%1 3000").arg(modes, 0, 16)); + } + modes = getRadioModes("CW"); + if (modes) { + response.append(QString("0x%1 1200").arg(modes, 0, 16)); + response.append(QString("0x%1 500").arg(modes, 0, 16)); + response.append(QString("0x%1 200").arg(modes, 0, 16)); + } + modes = getRadioModes("FM"); + if (modes) { + response.append(QString("0x%1 15000").arg(modes, 0, 16)); + response.append(QString("0x%1 10000").arg(modes, 0, 16)); + response.append(QString("0x%1 7000").arg(modes, 0, 16)); + } + modes = getRadioModes("RTTY"); + if (modes) { + response.append(QString("0x%1 2400").arg(modes, 0, 16)); + response.append(QString("0x%1 500").arg(modes, 0, 16)); + response.append(QString("0x%1 250").arg(modes, 0, 16)); + } + modes = getRadioModes("PSK"); + if (modes) { + response.append(QString("0x%1 1200").arg(modes, 0, 16)); + response.append(QString("0x%1 500").arg(modes, 0, 16)); + response.append(QString("0x%1 250").arg(modes, 0, 16)); + } + response.append("0 0"); + response.append("9900"); + response.append("9900"); + response.append("10000"); + response.append("0"); + QString preamps=""; + if(rigCaps.commands.contains(funcPreamp)) { + foreach (auto pre, rigCaps.preamps) + { + if (pre.num == 0) + continue; + preamps.append(QString("%1 ").arg(pre.num*10)); + } + if (preamps.endsWith(" ")) + preamps.chop(1); + } + else { + preamps = "0"; + } + response.append(preamps); + + QString attens = ""; + if(rigCaps.commands.contains(funcAttenuator)) { + for (auto att : rigCaps.attenuators) + { + if (att == 0) + continue; + attens.append(QString("%1 ").arg(att,0,16)); + } + if (attens.endsWith(" ")) + attens.chop(1); + } + else { + attens = "0"; + } + response.append(attens); + + qulonglong hasFuncs=0; + qulonglong hasLevels=0; + qulonglong hasParams=0; + for (int i = 0 ; functions_str[i].str[0] != '\0'; i++) + { + if (functions_str[i].func != funcNone && rigCaps.commands.contains(functions_str[i].func)) + { + hasFuncs |= 1ULL << i; + } + } + response.append(QString("0x%0").arg(hasFuncs,16,16,QChar('0'))); + response.append(QString("0x%0").arg(hasFuncs,16,16,QChar('0'))); + + for (int i = 0 ; levels_str[i].str[0] != '\0'; i++) + { + if (levels_str[i].func != funcNone && rigCaps.commands.contains(levels_str[i].func)) + { + hasLevels |= 1ULL << i; + } + } + response.append(QString("0x%0").arg(hasLevels,16,16,QChar('0'))); + response.append(QString("0x%0").arg(hasLevels,16,16,QChar('0'))); + + for (int i = 0 ; params_str[i].str[0] != '\0'; i++) + { + if (params_str[i].func != funcNone && rigCaps.commands.contains(params_str[i].func)) + { + hasParams |= 1ULL << i; + } + } + response.append(QString("0x%0").arg(hasParams,16,16,QChar('0'))); + response.append(QString("0x%0").arg(hasParams,16,16,QChar('0'))); + + if (chkVfoEecuted) { + response.append(QString("vfo_ops=0x%1").arg(255, 0, 16)); + response.append(QString("ptt_type=0x%1").arg(rigCaps.hasTransmit, 0, 16)); + response.append(QString("has_set_vfo=0x%1").arg(1, 0, 16)); + response.append(QString("has_get_vfo=0x%1").arg(1, 0, 16)); + response.append(QString("has_set_freq=0x%1").arg(1, 0, 16)); + response.append(QString("has_get_freq=0x%1").arg(1, 0, 16)); + response.append(QString("has_set_conf=0x%1").arg(1, 0, 16)); + response.append(QString("has_get_conf=0x%1").arg(1, 0, 16)); + response.append(QString("has_power2mW=0x%1").arg(1, 0, 16)); + response.append(QString("has_mW2power=0x%1").arg(1, 0, 16)); + response.append(QString("timeout=0x%1").arg(1000, 0, 16)); + response.append("done"); + } + + return RIG_OK; +} + +int rigCtlClient::dumpCaps(QStringList &response, bool extended) +{ + Q_UNUSED(extended) + response.append(QString("Caps dump for model: %1").arg(rigCaps.modelID)); + response.append(QString("Model Name:\t%1").arg(rigCaps.modelName)); + response.append(QString("Mfg Name:\tIcom")); + response.append(QString("Backend version:\t0.1")); + response.append(QString("Backend copyright:\t2021")); + if (rigCaps.hasTransmit) { + response.append(QString("Rig type:\tTransceiver")); + } + else + { + response.append(QString("Rig type:\tReceiver")); + } + if(rigCaps.commands.contains(funcTransceiverStatus)) { + response.append(QString("PTT type:\tRig capable")); + } + response.append(QString("DCD type:\tRig capable")); + response.append(QString("Port type:\tNetwork link")); + return RIG_OK; +} diff --git a/rigctld.h b/rigctld.h index 02e6ca7..c64ce63 100644 --- a/rigctld.h +++ b/rigctld.h @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -61,105 +62,50 @@ #define RIG_MODE_PKTFMN CONSTANT_64BIT_FLAG (34) /*!< \c Yaesu DATA-FM-N */ #define RIG_MODE_SPEC CONSTANT_64BIT_FLAG (35) /*!< \c Unfiltered as in PowerSDR */ -#define RIG_LEVEL_NONE 0 /*!< '' -- No Level */ -#define RIG_LEVEL_PREAMP CONSTANT_64BIT_FLAG(0) /*!< \c PREAMP -- Preamp, arg int (dB) */ -#define RIG_LEVEL_ATT CONSTANT_64BIT_FLAG(1) /*!< \c ATT -- Attenuator, arg int (dB) */ -#define RIG_LEVEL_VOXDELAY CONSTANT_64BIT_FLAG(2) /*!< \c VOXDELAY -- VOX delay, arg int (tenth of seconds) */ -#define RIG_LEVEL_AF CONSTANT_64BIT_FLAG(3) /*!< \c AF -- Volume, arg float [0.0 ... 1.0] */ -#define RIG_LEVEL_RF CONSTANT_64BIT_FLAG(4) /*!< \c RF -- RF gain (not TX power) arg float [0.0 ... 1.0] */ -#define RIG_LEVEL_SQL CONSTANT_64BIT_FLAG(5) /*!< \c SQL -- Squelch, arg float [0.0 ... 1.0] */ -#define RIG_LEVEL_IF CONSTANT_64BIT_FLAG(6) /*!< \c IF -- IF, arg int (Hz) */ -#define RIG_LEVEL_APF CONSTANT_64BIT_FLAG(7) /*!< \c APF -- Audio Peak Filter, arg float [0.0 ... 1.0] */ -#define RIG_LEVEL_NR CONSTANT_64BIT_FLAG(8) /*!< \c NR -- Noise Reduction, arg float [0.0 ... 1.0] */ -#define RIG_LEVEL_PBT_IN CONSTANT_64BIT_FLAG(9) /*!< \c PBT_IN -- Twin PBT (inside) arg float [0.0 ... 1.0] */ -#define RIG_LEVEL_PBT_OUT CONSTANT_64BIT_FLAG(10) /*!< \c PBT_OUT -- Twin PBT (outside) arg float [0.0 ... 1.0] */ -#define RIG_LEVEL_CWPITCH CONSTANT_64BIT_FLAG(11) /*!< \c CWPITCH -- CW pitch, arg int (Hz) */ -#define RIG_LEVEL_RFPOWER CONSTANT_64BIT_FLAG(12) /*!< \c RFPOWER -- RF Power, arg float [0.0 ... 1.0] */ -#define RIG_LEVEL_MICGAIN CONSTANT_64BIT_FLAG(13) /*!< \c MICGAIN -- MIC Gain, arg float [0.0 ... 1.0] */ -#define RIG_LEVEL_KEYSPD CONSTANT_64BIT_FLAG(14) /*!< \c KEYSPD -- Key Speed, arg int (WPM) */ -#define RIG_LEVEL_NOTCHF CONSTANT_64BIT_FLAG(15) /*!< \c NOTCHF -- Notch Freq., arg int (Hz) */ -#define RIG_LEVEL_COMP CONSTANT_64BIT_FLAG(16) /*!< \c COMP -- Compressor, arg float [0.0 ... 1.0] */ -#define RIG_LEVEL_AGC CONSTANT_64BIT_FLAG(17) /*!< \c AGC -- AGC, arg int (see enum agc_level_e) */ -#define RIG_LEVEL_BKINDL CONSTANT_64BIT_FLAG(18) /*!< \c BKINDL -- BKin Delay, arg int (tenth of dots) */ -#define RIG_LEVEL_BALANCE CONSTANT_64BIT_FLAG(19) /*!< \c BAL -- Balance (Dual Watch) arg float [0.0 ... 1.0] */ -#define RIG_LEVEL_METER CONSTANT_64BIT_FLAG(20) /*!< \c METER -- Display meter, arg int (see enum meter_level_e) */ -#define RIG_LEVEL_VOXGAIN CONSTANT_64BIT_FLAG(21) /*!< \c VOXGAIN -- VOX gain level, arg float [0.0 ... 1.0] */ -#define RIG_LEVEL_ANTIVOX CONSTANT_64BIT_FLAG(22) /*!< \c ANTIVOX -- anti-VOX level, arg float [0.0 ... 1.0] */ -#define RIG_LEVEL_SLOPE_LOW CONSTANT_64BIT_FLAG(23) /*!< \c SLOPE_LOW -- Slope tune, low frequency cut, arg int (Hz) */ -#define RIG_LEVEL_SLOPE_HIGH CONSTANT_64BIT_FLAG(24) /*!< \c SLOPE_HIGH -- Slope tune, high frequency cut, arg int (Hz) */ -#define RIG_LEVEL_BKIN_DLYMS CONSTANT_64BIT_FLAG(25) /*!< \c BKIN_DLYMS -- BKin Delay, arg int Milliseconds */ +struct commandStruct +{ + uchar sstr; + const char *str; + funcs func; + char type; + int flags; + const char* arg1; + const char* arg2; + const char* arg3; + const char* arg4; + const char* arg5; + const char* arg6; +}; -/*!< These are not settable */ -#define RIG_LEVEL_RAWSTR CONSTANT_64BIT_FLAG(26) /*!< \c RAWSTR -- Raw (A/D) value for signal strength, specific to each rig, arg int */ -//#define RIG_LEVEL_SQLSTAT CONSTANT_64BIT_FLAG(27) /*!< \c SQLSTAT -- SQL status, arg int (open=1/closed=0). Deprecated, use get_dcd instead */ -#define RIG_LEVEL_SWR CONSTANT_64BIT_FLAG(28) /*!< \c SWR -- SWR, arg float [0.0 ... infinite] */ -#define RIG_LEVEL_ALC CONSTANT_64BIT_FLAG(29) /*!< \c ALC -- ALC, arg float */ -#define RIG_LEVEL_STRENGTH CONSTANT_64BIT_FLAG(30) /*!< \c STRENGTH -- Effective (calibrated) signal strength relative to S9, arg int (dB) */ - /* RIG_LEVEL_BWC (1<<31) */ /*!< Bandwidth Control, arg int (Hz) */ -#define RIG_LEVEL_RFPOWER_METER CONSTANT_64BIT_FLAG(32) /*!< \c RFPOWER_METER -- RF power output meter, arg float [0.0 ... 1.0] (percentage of maximum power) */ -#define RIG_LEVEL_COMP_METER CONSTANT_64BIT_FLAG(33) /*!< \c COMP_METER -- Audio output level compression meter, arg float (dB) */ -#define RIG_LEVEL_VD_METER CONSTANT_64BIT_FLAG(34) /*!< \c VD_METER -- Input voltage level meter, arg float (V, volts) */ -#define RIG_LEVEL_ID_METER CONSTANT_64BIT_FLAG(35) /*!< \c ID_METER -- Current draw meter, arg float (A, amperes) */ -#define RIG_LEVEL_NOTCHF_RAW CONSTANT_64BIT_FLAG(36) /*!< \c NOTCHF_RAW -- Notch Freq., arg float [0.0 ... 1.0] */ -#define RIG_LEVEL_MONITOR_GAIN CONSTANT_64BIT_FLAG(37) /*!< \c MONITOR_GAIN -- Monitor gain (level for monitoring of transmitted audio) arg float [0.0 ... 1.0] */ -#define RIG_LEVEL_NB CONSTANT_64BIT_FLAG(38) /*!< \c NB -- Noise Blanker level, arg float [0.0 ... 1.0] */ -#define RIG_LEVEL_RFPOWER_METER_WATTS CONSTANT_64BIT_FLAG(39) /*!< \c RFPOWER_METER_WATTS -- RF power output meter, arg float [0.0 ... MAX] (output power in watts) */ -#define RIG_LEVEL_SPECTRUM_MODE CONSTANT_64BIT_FLAG(40) /*!< \c SPECTRUM_MODE -- Spectrum scope mode, arg int (see enum rig_spectrum_mode_e). Supported modes defined in rig caps. */ -#define RIG_LEVEL_SPECTRUM_SPAN CONSTANT_64BIT_FLAG(41) /*!< \c SPECTRUM_SPAN -- Spectrum scope span in center mode, arg int (Hz). Supported spans defined in rig caps. */ -#define RIG_LEVEL_SPECTRUM_EDGE_LOW CONSTANT_64BIT_FLAG(42) /*!< \c SPECTRUM_EDGE_LOW -- Spectrum scope low edge in fixed mode, arg int (Hz) */ -#define RIG_LEVEL_SPECTRUM_EDGE_HIGH CONSTANT_64BIT_FLAG(43) /*!< \c SPECTRUM_EDGE_HIGH -- Spectrum scope high edge in fixed mode, arg int (Hz) */ -#define RIG_LEVEL_SPECTRUM_SPEED CONSTANT_64BIT_FLAG(44) /*!< \c SPECTRUM_SPEED -- Spectrum scope update speed, arg int (highest is fastest, define rig-specific granularity) */ -#define RIG_LEVEL_SPECTRUM_REF CONSTANT_64BIT_FLAG(45) /*!< \c SPECTRUM_REF -- Spectrum scope reference display level, arg float (dB, define rig-specific granularity) */ -#define RIG_LEVEL_SPECTRUM_AVG CONSTANT_64BIT_FLAG(46) /*!< \c SPECTRUM_AVG -- Spectrum scope averaging mode, arg int (see struct rig_spectrum_avg_mode). Supported averaging modes defined in rig caps. */ -#define RIG_LEVEL_SPECTRUM_ATT CONSTANT_64BIT_FLAG(47) /*!< \c SPECTRUM_ATT -- Spectrum scope attenuator, arg int (dB). Supported attenuator values defined in rig caps. */ -#define RIG_LEVEL_TEMP_METER CONSTANT_64BIT_FLAG(48) /*!< \c TEMP_METER -- arg int (C, centigrade) */ +struct subCommandStruct +{ + const char *str; + funcs func; + char type; +}; + + +enum rig_errcode_e { + RIG_OK=0, /*!< No error, operation completed successfully */ + RIG_EINVAL, /*!< invalid parameter */ + RIG_ECONF, /*!< invalid configuration (serial,..) */ + RIG_ENOMEM, /*!< memory shortage */ + RIG_ENIMPL, /*!< function not implemented, but will be */ + RIG_ETIMEOUT, /*!< communication timed out */ + RIG_EIO, /*!< IO error, including open failed */ + RIG_EINTERNAL, /*!< Internal Hamlib error, huh! */ + RIG_EPROTO, /*!< Protocol error */ + RIG_ERJCTED, /*!< Command rejected by the rig */ + RIG_ETRUNC, /*!< Command performed, but arg truncated */ + RIG_ENAVAIL, /*!< function not available */ + RIG_ENTARGET, /*!< VFO not targetable */ + RIG_BUSERROR, /*!< Error talking on the bus */ + RIG_BUSBUSY, /*!< Collision on the bus */ + RIG_EARG, /*!< NULL RIG handle or any invalid pointer parameter in get arg */ + RIG_EVFO, /*!< Invalid VFO */ + RIG_EDOM /*!< Argument out of domain of func */ +}; -#define RIG_FUNC_NONE 0 /*!< '' -- No Function */ -#define RIG_FUNC_FAGC CONSTANT_64BIT_FLAG (0) /*!< \c FAGC -- Fast AGC */ -#define RIG_FUNC_NB CONSTANT_64BIT_FLAG (1) /*!< \c NB -- Noise Blanker */ -#define RIG_FUNC_COMP CONSTANT_64BIT_FLAG (2) /*!< \c COMP -- Speech Compression */ -#define RIG_FUNC_VOX CONSTANT_64BIT_FLAG (3) /*!< \c VOX -- Voice Operated Relay */ -#define RIG_FUNC_TONE CONSTANT_64BIT_FLAG (4) /*!< \c TONE -- CTCSS Tone TX */ -#define RIG_FUNC_TSQL CONSTANT_64BIT_FLAG (5) /*!< \c TSQL -- CTCSS Activate/De-activate RX */ -#define RIG_FUNC_SBKIN CONSTANT_64BIT_FLAG (6) /*!< \c SBKIN -- Semi Break-in (CW mode) */ -#define RIG_FUNC_FBKIN CONSTANT_64BIT_FLAG (7) /*!< \c FBKIN -- Full Break-in (CW mode) */ -#define RIG_FUNC_ANF CONSTANT_64BIT_FLAG (8) /*!< \c ANF -- Automatic Notch Filter (DSP) */ -#define RIG_FUNC_NR CONSTANT_64BIT_FLAG (9) /*!< \c NR -- Noise Reduction (DSP) */ -#define RIG_FUNC_AIP CONSTANT_64BIT_FLAG (10) /*!< \c AIP -- RF pre-amp (AIP on Kenwood, IPO on Yaesu, etc.) */ -#define RIG_FUNC_APF CONSTANT_64BIT_FLAG (11) /*!< \c APF -- Auto Passband/Audio Peak Filter */ -#define RIG_FUNC_MON CONSTANT_64BIT_FLAG (12) /*!< \c MON -- Monitor transmitted signal */ -#define RIG_FUNC_MN CONSTANT_64BIT_FLAG (13) /*!< \c MN -- Manual Notch */ -#define RIG_FUNC_RF CONSTANT_64BIT_FLAG (14) /*!< \c RF -- RTTY Filter */ -#define RIG_FUNC_ARO CONSTANT_64BIT_FLAG (15) /*!< \c ARO -- Auto Repeater Offset */ -#define RIG_FUNC_LOCK CONSTANT_64BIT_FLAG (16) /*!< \c LOCK -- Lock */ -#define RIG_FUNC_MUTE CONSTANT_64BIT_FLAG (17) /*!< \c MUTE -- Mute */ -#define RIG_FUNC_VSC CONSTANT_64BIT_FLAG (18) /*!< \c VSC -- Voice Scan Control */ -#define RIG_FUNC_REV CONSTANT_64BIT_FLAG (19) /*!< \c REV -- Reverse transmit and receive frequencies */ -#define RIG_FUNC_SQL CONSTANT_64BIT_FLAG (20) /*!< \c SQL -- Turn Squelch Monitor on/off */ -#define RIG_FUNC_ABM CONSTANT_64BIT_FLAG (21) /*!< \c ABM -- Auto Band Mode */ -#define RIG_FUNC_BC CONSTANT_64BIT_FLAG (22) /*!< \c BC -- Beat Canceller */ -#define RIG_FUNC_MBC CONSTANT_64BIT_FLAG (23) /*!< \c MBC -- Manual Beat Canceller */ -#define RIG_FUNC_RIT CONSTANT_64BIT_FLAG (24) /*!< \c RIT -- Receiver Incremental Tuning */ -#define RIG_FUNC_AFC CONSTANT_64BIT_FLAG (25) /*!< \c AFC -- Auto Frequency Control ON/OFF */ -#define RIG_FUNC_SATMODE CONSTANT_64BIT_FLAG (26) /*!< \c SATMODE -- Satellite mode ON/OFF */ -#define RIG_FUNC_SCOPE CONSTANT_64BIT_FLAG (27) /*!< \c SCOPE -- Simple bandscope ON/OFF */ -#define RIG_FUNC_RESUME CONSTANT_64BIT_FLAG (28) /*!< \c RESUME -- Scan auto-resume */ -#define RIG_FUNC_TBURST CONSTANT_64BIT_FLAG (29) /*!< \c TBURST -- 1750 Hz tone burst */ -#define RIG_FUNC_TUNER CONSTANT_64BIT_FLAG (30) /*!< \c TUNER -- Enable automatic tuner */ -#define RIG_FUNC_XIT CONSTANT_64BIT_FLAG (31) /*!< \c XIT -- Transmitter Incremental Tuning */ -#define RIG_FUNC_NB2 CONSTANT_64BIT_FLAG (32) /*!< \c NB2 -- 2nd Noise Blanker */ -#define RIG_FUNC_CSQL CONSTANT_64BIT_FLAG (33) /*!< \c CSQL -- DCS Squelch setting */ -#define RIG_FUNC_AFLT CONSTANT_64BIT_FLAG (34) /*!< \c AFLT -- AF Filter setting */ -#define RIG_FUNC_ANL CONSTANT_64BIT_FLAG (35) /*!< \c ANL -- Noise limiter setting */ -#define RIG_FUNC_BC2 CONSTANT_64BIT_FLAG (36) /*!< \c BC2 -- 2nd Beat Cancel */ -#define RIG_FUNC_DUAL_WATCH CONSTANT_64BIT_FLAG (37) /*!< \c DUAL_WATCH -- Dual Watch / Sub Receiver */ -#define RIG_FUNC_DIVERSITY CONSTANT_64BIT_FLAG (38) /*!< \c DIVERSITY -- Diversity receive */ -#define RIG_FUNC_DSQL CONSTANT_64BIT_FLAG (39) /*!< \c DSQL -- Digital modes squelch */ -#define RIG_FUNC_SCEN CONSTANT_64BIT_FLAG (40) /*!< \c SCEN -- scrambler/encryption */ -#define RIG_FUNC_SLICE CONSTANT_64BIT_FLAG (41) /*!< \c Rig slice selection -- Flex */ -#define RIG_FUNC_TRANSCEIVE CONSTANT_64BIT_FLAG (42) /*!< \c TRANSCEIVE -- Send radio state changes automatically ON/OFF */ -#define RIG_FUNC_SPECTRUM CONSTANT_64BIT_FLAG (43) /*!< \c SPECTRUM -- Spectrum scope data output ON/OFF */ -#define RIG_FUNC_SPECTRUM_HOLD CONSTANT_64BIT_FLAG (44) /*!< \c SPECTRUM_HOLD -- Pause spectrum scope updates ON/OFF */ #if 0 @@ -366,7 +312,6 @@ signals: void setAntiVoxGain(quint8); void setSpectrumRefLevel(int); - public slots: virtual void incomingConnection(qintptr socketDescriptor); void receiveRigCaps(rigCapabilities caps); @@ -375,6 +320,7 @@ public slots: private: rigstate* rigState = Q_NULLPTR; + }; @@ -408,8 +354,8 @@ private: unsigned long crcTable[256]; unsigned long doCrc(unsigned char* p, size_t n); void genCrc(unsigned long crcTable[]); - QString getMode(quint8 mode, bool datamode); - quint8 getMode(QString modeString); + QString getMode(modeInfo mode); + bool getMode(QString modeString, modeInfo& mode); QString getFilter(quint8 mode, quint8 filter); quint8 getAntennas(); quint64 getRadioModes(QString mode = ""); @@ -417,7 +363,10 @@ private: quint8 antFromName(QString name); quint8 vfoFromName(QString vfo); QString getVfoName(quint8 vfo); - + int getCommand(QStringList& respone, bool extended, const commandStruct cmd, QStringList params ); + int getSubCommand(QStringList& response, bool extended, const commandStruct cmd, const subCommandStruct sub[], QStringList params); + int dumpState(QStringList &response, bool extended); + int dumpCaps(QStringList &response, bool extended); int getCalibratedValue(quint8 meter,cal_table_t cal); }; diff --git a/rigidentities.h b/rigidentities.h index 1dc325f..0cf57fa 100644 --- a/rigidentities.h +++ b/rigidentities.h @@ -162,7 +162,7 @@ struct genericType { model_kind determineRadioModel(unsigned char rigID); struct rigCapabilities { - model_kind model; + quint8 model; quint8 civ; quint8 modelID = 0; QString filename; @@ -220,7 +220,7 @@ struct rigCapabilities { std::vector filters; std::vector scopeCenterSpans; std::vector bands; - std::vector spans; + //std::vector spans; std::vector steps; unsigned char bsr[24] = {0}; diff --git a/usbcontroller.cpp b/usbcontroller.cpp index 3b8d60c..92ed580 100644 --- a/usbcontroller.cpp +++ b/usbcontroller.cpp @@ -804,7 +804,7 @@ void usbController::receivePTTStatus(bool on) { for (auto devIt = devices->begin(); devIt != devices->end(); devIt++) { auto dev = &devIt.value(); - if (dev->lcd != cmdLCDSpectrum && dev->lcd != cmdLCDWaterfall) { + if (dev->lcd != funcLCDSpectrum && dev->lcd != funcLCDWaterfall) { if (on && !ptt) { lastColour = currentColour; QColor newColor = QColor(255,0,0); @@ -1079,7 +1079,7 @@ void usbController::sendRequest(USBDEVICE *dev, usbFeatureType feature, int val, } if (text != "**REMOVE**") { dev->knobValues[val].lastChanged = QDateTime::currentMSecsSinceEpoch(); - if (dev->lcd != cmdLCDSpectrum && dev->lcd != cmdLCDWaterfall) + if (dev->lcd != funcLCDSpectrum && dev->lcd != funcLCDWaterfall) QTimer::singleShot(2000, this, [=]() { sendRequest(dev,usbFeatureType::featureGraph,val,"**REMOVE**",Q_NULLPTR,&dev->color); }); } @@ -1585,38 +1585,38 @@ void usbController::loadCommands() int num = 0; // Important commands at the top! commands.append(COMMAND(num++, "None", commandAny, cmdNone, (quint8)0x0)); - commands.append(COMMAND(num++, "PTT On", commandButton, funcTransceiverStatus, funcTransceiverStatus, (quint8)0x1)); - commands.append(COMMAND(num++, "PTT Off", commandButton, funcTransceiverStatus, funcTransceiverStatus, (quint8)0x0)); - commands.append(COMMAND(num++, "VFOA", commandKnob, funcFreqSet, funcFreqSet, (quint8)0x0)); - commands.append(COMMAND(num++, "VFOB", commandKnob, funcFreqSet, funcFreqSet, (quint8)0x1)); - commands.append(COMMAND(num++, "Freq Down", commandButton, funcFreqSet, funcFreqSet, (int)-1)); - commands.append(COMMAND(num++, "Freq Up", commandButton, funcFreqSet, funcFreqSet, (int)1)); - commands.append(COMMAND(num++, "PTT Off", commandButton, funcTransceiverStatus, funcTransceiverStatus, (quint8)0x0)); - commands.append(COMMAND(num++, "PTT Toggle", commandButton, funcTransceiverStatus, funcTransceiverStatus, (quint8)0x0)); + commands.append(COMMAND(num++, "PTT On", commandButton, funcTransceiverStatus, (quint8)0x1)); + commands.append(COMMAND(num++, "PTT Off", commandButton, funcTransceiverStatus, (quint8)0x0)); + commands.append(COMMAND(num++, "VFOA", commandKnob, funcSelectedFreq, (quint8)0x0)); + commands.append(COMMAND(num++, "VFOB", commandKnob, funcUnselectedFreq, (quint8)0x1)); + commands.append(COMMAND(num++, "Freq Down", commandButton, funcSelectedFreq,(int)-1)); + commands.append(COMMAND(num++, "Freq Up", commandButton, funcSelectedFreq, (int)1)); + commands.append(COMMAND(num++, "PTT Off", commandButton, funcTransceiverStatus, (quint8)0x0)); + commands.append(COMMAND(num++, "PTT Toggle", commandButton, funcTransceiverStatus, (quint8)0x0)); commands.append(COMMAND(num++, "Span/Step", commandKnob, funcSeparator, (quint8)0x0)); commands.append(COMMAND(num++, "Tune", commandButton, funcTunerStatus, (quint8)0x0)); commands.append(COMMAND(num++, "Span/Step", commandButton, funcSeparator, (quint8)0x0)); commands.append(COMMAND(num++, "Step+", commandButton, funcTuningStep, 100)); commands.append(COMMAND(num++, "Step-", commandButton, funcTuningStep, -100)); - commands.append(COMMAND(num++, "Span+", commandButton, funcScopeCenterSpan, 100)); - commands.append(COMMAND(num++, "Span-", commandButton, funcScopeCenterSpan, -100)); + commands.append(COMMAND(num++, "Span+", commandButton, funcScopeMainSpan, 100)); + commands.append(COMMAND(num++, "Span-", commandButton, funcScopeMainSpan, -100)); commands.append(COMMAND(num++, "Modes", commandButton, funcSeparator, (quint8)0x0)); - commands.append(COMMAND(num++, "Mode+", commandButton, funcModeSet, 100)); - commands.append(COMMAND(num++, "Mode-", commandButton, funcModeSet, -100)); - commands.append(COMMAND(num++, "Mode LSB", commandButton, funcModeSet, modeLSB)); - commands.append(COMMAND(num++, "Mode USB", commandButton, funcModeSet, modeUSB)); - commands.append(COMMAND(num++, "Mode LSBD", commandButton, funcModeSet, modeLSB_D)); - commands.append(COMMAND(num++, "Mode USBD", commandButton, funcModeSet, modeUSB_D)); - commands.append(COMMAND(num++, "Mode CW", commandButton, funcModeSet, modeCW)); - commands.append(COMMAND(num++, "Mode CWR", commandButton, funcModeSet, modeCW_R)); - commands.append(COMMAND(num++, "Mode FM", commandButton, funcModeSet, modeFM)); - commands.append(COMMAND(num++, "Mode AM", commandButton, funcModeSet, modeAM)); - commands.append(COMMAND(num++, "Mode RTTY", commandButton, funcModeSet, modeRTTY)); - commands.append(COMMAND(num++, "Mode RTTYR", commandButton, funcModeSet, modeRTTY_R)); - commands.append(COMMAND(num++, "Mode PSK", commandButton, funcModeSet, modePSK)); - commands.append(COMMAND(num++, "Mode PSKR", commandButton, funcModeSet, modePSK_R)); - commands.append(COMMAND(num++, "Mode DV", commandButton, funcModeSet, modeDV)); - commands.append(COMMAND(num++, "Mode DD", commandButton, funcModeSet, modeDD)); + commands.append(COMMAND(num++, "Mode+", commandButton, funcSelectedMode, 100)); + commands.append(COMMAND(num++, "Mode-", commandButton, funcSelectedMode, -100)); + commands.append(COMMAND(num++, "Mode LSB", commandButton, funcSelectedMode, modeLSB)); + commands.append(COMMAND(num++, "Mode USB", commandButton, funcSelectedMode, modeUSB)); + commands.append(COMMAND(num++, "Mode LSBD", commandButton, funcSelectedMode, modeLSB_D)); + commands.append(COMMAND(num++, "Mode USBD", commandButton, funcSelectedMode, modeUSB_D)); + commands.append(COMMAND(num++, "Mode CW", commandButton, funcSelectedMode, modeCW)); + commands.append(COMMAND(num++, "Mode CWR", commandButton, funcSelectedMode, modeCW_R)); + commands.append(COMMAND(num++, "Mode FM", commandButton, funcSelectedMode, modeFM)); + commands.append(COMMAND(num++, "Mode AM", commandButton, funcSelectedMode, modeAM)); + commands.append(COMMAND(num++, "Mode RTTY", commandButton, funcSelectedMode, modeRTTY)); + commands.append(COMMAND(num++, "Mode RTTYR", commandButton, funcSelectedMode, modeRTTY_R)); + commands.append(COMMAND(num++, "Mode PSK", commandButton, funcSelectedMode, modePSK)); + commands.append(COMMAND(num++, "Mode PSKR", commandButton, funcSelectedMode, modePSK_R)); + commands.append(COMMAND(num++, "Mode DV", commandButton, funcSelectedMode, modeDV)); + commands.append(COMMAND(num++, "Mode DD", commandButton, funcSelectedMode, modeDD)); commands.append(COMMAND(num++, "Bands", commandButton, funcSeparator, (quint8)0x0)); commands.append(COMMAND(num++, "Band+", commandButton, funcBandStackReg, 100)); commands.append(COMMAND(num++, "Band-", commandButton, funcBandStackReg, -100)); @@ -1641,19 +1641,19 @@ void usbController::loadCommands() commands.append(COMMAND(num++, "Band 2200m", commandButton, funcBandStackReg, band2200m)); commands.append(COMMAND(num++, "Band GEN", commandButton, funcBandStackReg, bandGen)); commands.append(COMMAND(num++, "NB/NR", commandButton, funcSeparator, (quint8)0x0)); - commands.append(COMMAND(num++, "NR On", commandButton, funcNoiseReduction, cmdGetNR, (quint8)0x01)); - commands.append(COMMAND(num++, "NR Off", commandButton, funcNoiseReduction, cmdGetNR, (quint8)0x0)); - commands.append(COMMAND(num++, "NB On", commandButton, funcNoiseBlanker, cmdGetNB, (quint8)0x01)); - commands.append(COMMAND(num++, "NB Off", commandButton, funcNoiseBlanker, cmdGetNB, (quint8)0x0)); - commands.append(COMMAND(num++, "Moni On", commandButton, funcMonitor, cmdGetMonitor, (quint8)0x01)); - commands.append(COMMAND(num++, "Moni Off", commandButton, funcMonitor, cmdGetMonitor, (quint8)0x0)); - commands.append(COMMAND(num++, "Comp On", commandButton, funcCompressor, cmdGetComp, (quint8)0x01)); - commands.append(COMMAND(num++, "Comp Off", commandButton, funcCompressor, cmdGetComp, (quint8)0x0)); - commands.append(COMMAND(num++, "Vox On", commandButton, funcVox, cmdGetVox, (quint8)0x01)); - commands.append(COMMAND(num++, "Vox Off", commandButton, funcVox, cmdGetVox, (quint8)0x0)); + commands.append(COMMAND(num++, "NR On", commandButton, funcNoiseReduction, (quint8)0x01)); + commands.append(COMMAND(num++, "NR Off", commandButton, funcNoiseReduction, (quint8)0x0)); + commands.append(COMMAND(num++, "NB On", commandButton, funcNoiseBlanker, (quint8)0x01)); + commands.append(COMMAND(num++, "NB Off", commandButton, funcNoiseBlanker, (quint8)0x0)); + commands.append(COMMAND(num++, "Moni On", commandButton, funcMonitor, (quint8)0x01)); + commands.append(COMMAND(num++, "Moni Off", commandButton, funcMonitor, (quint8)0x0)); + commands.append(COMMAND(num++, "Comp On", commandButton, funcCompressor, (quint8)0x01)); + commands.append(COMMAND(num++, "Comp Off", commandButton, funcCompressor, (quint8)0x0)); + commands.append(COMMAND(num++, "Vox On", commandButton, funcVox, (quint8)0x01)); + commands.append(COMMAND(num++, "Vox Off", commandButton, funcVox, (quint8)0x0)); commands.append(COMMAND(num++, "Split", commandButton, funcSeparator, (quint8)0x0)); - commands.append(COMMAND(num++, "Split On", commandButton, funcQuickSplit, cmdGetDuplexMode, (quint8)0x01)); - commands.append(COMMAND(num++, "Split Off", commandButton, funcQuickSplit, cmdGetDuplexMode, (quint8)0x0)); + commands.append(COMMAND(num++, "Split On", commandButton, funcQuickSplit, (quint8)0x01)); + commands.append(COMMAND(num++, "Split Off", commandButton, funcQuickSplit, (quint8)0x0)); commands.append(COMMAND(num++, "Swap VFO AB", commandButton, funcVFOSwapAB, (quint8)0x0)); commands.append(COMMAND(num++, "Swap VFO MS", commandButton, funcVFOSwapMS, (quint8)0x0)); commands.append(COMMAND(num++, "Scope", commandButton, funcSeparator, (quint8)0x0)); @@ -1664,26 +1664,26 @@ void usbController::loadCommands() commands.append(COMMAND(num++, "Page Down", commandButton, funcPageDown, (quint8)0x0)); commands.append(COMMAND(num++, "Page Up", commandButton, funcPageUp, (quint8)0x0)); - commands.append(COMMAND(num++, "AF Gain", commandKnob, funcAfGain, funcAfGain, (quint8)0xff)); - commands.append(COMMAND(num++, "RF Gain", commandKnob, funcRfGain, funcRfGain, (quint8)0xff)); - commands.append(COMMAND(num++, "TX Power", commandKnob, funcRFPower, funcRFPower, (quint8)0xff)); - commands.append(COMMAND(num++, "Mic Gain", commandKnob, funcMicGain, funcMicGain, (quint8)0xff)); - commands.append(COMMAND(num++, "Mod Level", commandKnob, funcDATAOffMod, funcDATAOffMod, (quint8)0xff)); - commands.append(COMMAND(num++, "Data Mod", commandKnob, funcDATAOffMod, funcDATAOffMod, (quint8)0xff)); - commands.append(COMMAND(num++, "Squelch", commandKnob, funcSquelch, funcSquelch, (quint8)0xff)); - commands.append(COMMAND(num++, "Monitor", commandKnob, funcMonitorGain, funcMonitorGain, (quint8)0xff)); - commands.append(COMMAND(num++, "Compressor", commandKnob, funcCompressorLevel, funcCompressorLevel, (quint8)0xff)); - commands.append(COMMAND(num++, "Vox Level", commandKnob, funcVoxGain, funcVoxGain, (quint8)0xff)); - commands.append(COMMAND(num++, "Anti-Vox", commandKnob, funcAntiVoxGain, funcAntiVoxGain, (quint8)0xff)); - commands.append(COMMAND(num++, "NB Level", commandKnob, funcNBLevel, funcNBLevel, (quint8)0xff)); - commands.append(COMMAND(num++, "NR Level", commandKnob, funcNRLevel, funcNRLevel, (quint8)0xff)); + commands.append(COMMAND(num++, "AF Gain", commandKnob, funcAfGain, (quint8)0xff)); + commands.append(COMMAND(num++, "RF Gain", commandKnob, funcRfGain, (quint8)0xff)); + commands.append(COMMAND(num++, "TX Power", commandKnob, funcRFPower, (quint8)0xff)); + commands.append(COMMAND(num++, "Mic Gain", commandKnob, funcMicGain, (quint8)0xff)); + commands.append(COMMAND(num++, "Mod Level", commandKnob, funcDATAOffMod, (quint8)0xff)); + commands.append(COMMAND(num++, "Data Mod", commandKnob, funcDATAOffMod, (quint8)0xff)); + commands.append(COMMAND(num++, "Squelch", commandKnob, funcSquelch, (quint8)0xff)); + commands.append(COMMAND(num++, "Monitor", commandKnob, funcMonitorGain, (quint8)0xff)); + commands.append(COMMAND(num++, "Compressor", commandKnob, funcCompressorLevel, (quint8)0xff)); + commands.append(COMMAND(num++, "Vox Level", commandKnob, funcVoxGain, (quint8)0xff)); + commands.append(COMMAND(num++, "Anti-Vox", commandKnob, funcAntiVoxGain, (quint8)0xff)); + commands.append(COMMAND(num++, "NB Level", commandKnob, funcNBLevel, (quint8)0xff)); + commands.append(COMMAND(num++, "NR Level", commandKnob, funcNRLevel, (quint8)0xff)); commands.append(COMMAND(num++, "Span/Step", commandKnob, cmdSeparator, (quint8)0x0)); - commands.append(COMMAND(num++, "IF Shift", commandKnob, funcIFShift, funcIFShift, (quint8)0xff)); - commands.append(COMMAND(num++, "In PBT", commandKnob, funcPBTInner, funcPBTInner, (quint8)0xff)); - commands.append(COMMAND(num++, "Out PBT", commandKnob, funcPBTOuter, funcPBTOuter, (quint8)0xff)); + commands.append(COMMAND(num++, "IF Shift", commandKnob, funcIFShift, (quint8)0xff)); + commands.append(COMMAND(num++, "In PBT", commandKnob, funcPBTInner, (quint8)0xff)); + commands.append(COMMAND(num++, "Out PBT", commandKnob, funcPBTOuter, (quint8)0xff)); commands.append(COMMAND(num++, "Span/Step", commandKnob, cmdSeparator, (quint8)0x0)); - commands.append(COMMAND(num++, "CW Pitch", commandKnob, funcCwPitch, funcCwPitch, (quint8)0xff)); - commands.append(COMMAND(num++, "CW Speed", commandKnob, funcKeySpeed, funcKeySpeed, (quint8)0xff)); + commands.append(COMMAND(num++, "CW Pitch", commandKnob, funcCwPitch, (quint8)0xff)); + commands.append(COMMAND(num++, "CW Speed", commandKnob, funcKeySpeed, (quint8)0xff)); } @@ -1831,7 +1831,7 @@ void usbController::receiveLevel(cmds cmd, unsigned char level) auto dev = &devIt.value(); auto kb = std::find_if(knobList->begin(), knobList->end(), [dev, cmd](const KNOB& k) - { return (k.command && dev->connected && k.path == dev->path && k.page == dev->currentPage && k.command->getCommand == cmd);}); + { return (k.command && dev->connected && k.path == dev->path && k.page == dev->currentPage && k.command->command == cmd);}); if (kb != knobList->end() && kb->num < dev->knobValues.size()) { // qInfo(logUsbControl()) << "Received value:" << level << "for knob" << kb->num; // Set both current and previous knobvalue to the received value @@ -1839,7 +1839,7 @@ void usbController::receiveLevel(cmds cmd, unsigned char level) dev->knobValues[kb->num].previous = level/dev->sensitivity; } auto bt = std::find_if(buttonList->begin(), buttonList->end(), [dev, cmd](const BUTTON& b) - { return (b.onCommand && dev->connected && b.path == dev->path && b.page == dev->currentPage && b.onCommand->getCommand == cmd && b.led != 0 && b.led <= dev->type.leds);}); + { return (b.onCommand && dev->connected && b.path == dev->path && b.page == dev->currentPage && b.onCommand->command == cmd && b.led != 0 && b.led <= dev->type.leds);}); if (bt != buttonList->end()) { // qInfo(logUsbControl()) << "Received value:" << level << "for led" << bt->led; QTimer::singleShot(0, this, [=]() { sendRequest(dev,usbFeatureType::featureLEDControl,bt->led,QString("%1").arg(level)); }); diff --git a/usbcontroller.h b/usbcontroller.h index 312609f..f12a3ed 100644 --- a/usbcontroller.h +++ b/usbcontroller.h @@ -144,8 +144,6 @@ struct COMMAND { index(index), text(text), cmdType(cmdType), command(command), value(value) {} COMMAND(int index, QString text, usbCommandType cmdType, int command, unsigned char suffix) : index(index), text(text), cmdType(cmdType), command(command), suffix(suffix) {} - COMMAND(int index, QString text, usbCommandType cmdType, int command, int getCommand, unsigned char suffix) : - index(index), text(text), cmdType(cmdType), command(command), getCommand(getCommand), suffix(suffix) {} COMMAND(int index, QString text, usbCommandType cmdType, int command, availableBands band) : index(index), text(text), cmdType(cmdType), command(command), band(band) {} COMMAND(int index, QString text, usbCommandType cmdType, int command, rigMode_t mode) : @@ -155,7 +153,6 @@ struct COMMAND { QString text; usbCommandType cmdType = commandButton; int command=funcNone; - int getCommand=funcNone; unsigned char suffix=0x0; int value=0; availableBands band=bandGen; diff --git a/wfmain.cpp b/wfmain.cpp index 2bf2549..df71381 100644 --- a/wfmain.cpp +++ b/wfmain.cpp @@ -64,7 +64,6 @@ wfmain::wfmain(const QString settingsFile, const QString logFile, bool debugMode qRegisterMetaType(); qRegisterMetaType(); qRegisterMetaType(); - qRegisterMetaType(); qRegisterMetaType(); qRegisterMetaType(); qRegisterMetaType(); @@ -467,14 +466,6 @@ void wfmain::rigConnections() //connect(this, SIGNAL(setCWBreakMode(unsigned char)), rig, SLOT(setBreakIn(unsigned char))); //connect(this, SIGNAL(getCWBreakMode()), rig, SLOT(getBreakIn())); - connect(this->rig, &rigCommander::haveKeySpeed, - [=](const unsigned char& wpm) { cw->handleKeySpeed(wpm); }); - connect(this->rig, &rigCommander::haveDashRatio, - [=](const unsigned char& ratio) { cw->handleDashRatio(ratio); }); - connect(this->rig, &rigCommander::haveCwPitch, - [=](const unsigned char& speed) { cw->handlePitch(speed); }); - connect(this->rig, &rigCommander::haveCWBreakMode, - [=](const unsigned char &bm) { cw->handleBreakInMode(bm);}); //connect(rig, SIGNAL(haveBandStackReg(freqt,char,char,bool)), this, SLOT(receiveBandStackReg(freqt,char,char,bool))); //connect(this, SIGNAL(setRitEnable(bool)), rig, SLOT(setRitEnable(bool))); @@ -505,9 +496,9 @@ void wfmain::rigConnections() //connect(rig, SIGNAL(haveMonitor(bool)), this, SLOT(receiveMonitor(bool))); // Repeater, duplex, and split: - connect(rpt, SIGNAL(getDuplexMode()), rig, SLOT(getDuplexMode())); - connect(rpt, SIGNAL(setDuplexMode(duplexMode_t)), rig, SLOT(setDuplexMode(duplexMode_t))); - connect(rig, SIGNAL(haveDuplexMode(duplexMode_t)), rpt, SLOT(receiveDuplexMode(duplexMode_t))); + //connect(rpt, SIGNAL(getDuplexMode()), rig, SLOT(getDuplexMode())); + //connect(rpt, SIGNAL(setDuplexMode(duplexMode_t)), rig, SLOT(setDuplexMode(duplexMode_t))); + //connect(rig, SIGNAL(haveDuplexMode(duplexMode_t)), rpt, SLOT(receiveDuplexMode(duplexMode_t))); //connect(this, SIGNAL(getRptDuplexOffset()), rig, SLOT(getRptDuplexOffset())); connect(rig, SIGNAL(haveRptOffsetFrequency(freqt)), rpt, SLOT(handleRptOffsetFrequency(freqt))); @@ -520,16 +511,24 @@ void wfmain::rigConnections() //connect(this, SIGNAL(clearMemory(quint32)), rig, SLOT(clearMemory(quint32))); //connect(this, SIGNAL(recallMemory(quint32)), rig, SLOT(recallMemory(quint32))); - // These are the current tone frequency or DCS code selected: - connect(rpt, SIGNAL(getTone()), rig, SLOT(getTone())); - connect(rpt, SIGNAL(getTSQL()), rig, SLOT(getTSQL())); - connect(rpt, SIGNAL(getDTCS()), rig, SLOT(getDTCS())); + connect(this->rpt, &repeaterSetup::setDuplexMode, this->rig, + [=](const duplexMode_t &t) { queue->add(priorityImmediate,queueItem(funcSplitStatus,QVariant::fromValue(t),false));}); - connect(this->rpt, &repeaterSetup::setTone, this->rig, - [=](const rptrTone_t &t) { queue->add(priorityImmediate,queueItem(funcToneFreq,QVariant::fromValue(t),false));}); + connect(this->rpt, &repeaterSetup::getTone, this->rig, + [=]() { queue->add(priorityImmediate,funcRepeaterTone);}); connect(this->rpt, &repeaterSetup::setTSQL, this->rig, - [=](const rptrTone_t &t) { queue->add(priorityImmediate,queueItem(funcTSQLFreq,QVariant::fromValue(t),false));}); + [=](const toneInfo& t) { queue->add(priorityImmediate,queueItem(funcTSQLFreq,QVariant::fromValue(t),false));}); + + connect(this->rpt, &repeaterSetup::getTSQL, this->rig, + [=]() { queue->add(priorityImmediate,funcRepeaterTSQL);}); + + connect(this->rpt, &repeaterSetup::setDTCS, this->rig, + [=](const toneInfo& t) { queue->add(priorityImmediate,queueItem(funcRepeaterDTCS,QVariant::fromValue(t),false));}); + + connect(this->rpt, &repeaterSetup::getDTCS, this->rig, + [=]() { queue->add(priorityImmediate,funcRepeaterDTCS);}); + connect(this->rpt, &repeaterSetup::getRptAccessMode, this->rig, [=]() { @@ -551,12 +550,6 @@ void wfmain::rigConnections() queue->add(priorityImmediate,queueItem(funcToneSquelchType,QVariant::fromValue(rd),false)); }); - - connect(rig, SIGNAL(haveTone(quint16)), rpt, SLOT(handleTone(quint16))); - connect(rig, SIGNAL(haveTSQL(quint16)), rpt, SLOT(handleTSQL(quint16))); - connect(rig, SIGNAL(haveDTCS(quint16,bool,bool)), rpt, SLOT(handleDTCS(quint16,bool,bool))); - connect(rig, SIGNAL(haveRptAccessMode(rptAccessTxRx_t)), rpt, SLOT(handleRptAccessMode(rptAccessTxRx_t))); - connect(this->rig, &rigCommander::haveDuplexMode, this->rpt, [=](const duplexMode_t &dm) { if(dm==dmSplitOn) @@ -565,23 +558,27 @@ void wfmain::rigConnections() this->splitModeEnabled = false; }); - //connect(this, SIGNAL(getToneEnabled()), rig, SLOT(getToneEnabled())); - //connect(this, SIGNAL(getTSQLEnabled()), rig, SLOT(getToneSqlEnabled())); - connect(this->rpt, &repeaterSetup::setTransmitFrequency, this->rig, [=](const freqt &transmitFreq) { queue->add(priorityImmediate,queueItem(funcFreqSet,QVariant::fromValue(transmitFreq),false));}); + connect(this->rpt, &repeaterSetup::setTransmitMode, this->rig, [=](const modeInfo &transmitMode) { queue->add(priorityImmediate,queueItem(funcModeSet,QVariant::fromValue(transmitMode),false));}); + connect(this->rpt, &repeaterSetup::selectVFO, this->rig, [=](const vfo_t &v) { queue->add(priorityImmediate,queueItem(funcSelectVFO,QVariant::fromValue(v),false));}); + connect(this->rpt, &repeaterSetup::equalizeVFOsAB, this->rig, [=]() { queue->add(priorityImmediate,funcVFOEqualAB);}); + connect(this->rpt, &repeaterSetup::equalizeVFOsMS, this->rig, [=]() { queue->add(priorityImmediate,funcVFOEqualMS);}); + connect(this->rpt, &repeaterSetup::swapVFOs, this->rig, [=]() { queue->add(priorityImmediate,funcVFOSwapMS);}); + connect(this->rpt, &repeaterSetup::setRptDuplexOffset, this->rig, [=](const freqt &fOffset) { queue->add(priorityImmediate,queueItem(funcSendFreqOffset,QVariant::fromValue(fOffset),false));}); + connect(this->rpt, &repeaterSetup::getRptDuplexOffset, this->rig, [=]() { queue->add(priorityImmediate,funcReadFreqOffset);}); @@ -596,7 +593,6 @@ void wfmain::rigConnections() connect(rig, SIGNAL(haveSpectrumData(QByteArray, double, double)), this, SLOT(receiveSpectrumData(QByteArray, double, double))); connect(rig, SIGNAL(havespectrumMode_t(spectrumMode_t)), this, SLOT(receivespectrumMode_t(spectrumMode_t))); - connect(rig, SIGNAL(haveScopeOutOfRange(bool)), this, SLOT(handleScopeOutOfRange(bool))); connect(this, SIGNAL(setScopeMode(spectrumMode_t)), rig, SLOT(setspectrumMode_t(spectrumMode_t))); connect(this, SIGNAL(getScopeMode()), rig, SLOT(getScopeMode())); @@ -1011,21 +1007,21 @@ void wfmain::setupPlots() freqIndicatorLine->setAntialiased(true); freqIndicatorLine->setPen(QPen(Qt::blue)); - /* - text = new QCPItemText(plot); - text->setAntialiased(true); - text->setColor(QColor(Qt::red)); - text->setText("TEST"); - text->position->setCoords(14.195, rigCaps.spectAmpMax); - text->setFont(QFont(font().family(), 12)); - */ + oorIndicator = new QCPItemText(plot); + oorIndicator->setVisible(false); + oorIndicator->setAntialiased(true); + oorIndicator->setPen(QPen(Qt::red)); + oorIndicator->setBrush(QBrush(Qt::red)); + oorIndicator->setFont(QFont(font().family(), 14)); + oorIndicator->setPositionAlignment(Qt::AlignVCenter | Qt::AlignHCenter); + oorIndicator->position->setType(QCPItemPosition::ptAxisRectRatio); // Positioned relative to the current plot rect + oorIndicator->setText("SCOPE OUT OF RANGE"); ui->plot->addGraph(); // primary ui->plot->addGraph(0, 0); // secondary, peaks, same axis as first. ui->plot->addLayer( "Top Layer", ui->plot->layer("main")); ui->plot->graph(0)->setLayer("Top Layer"); - ui->waterfall->addGraph(); colorMap = new QCPColorMap(wf->xAxis, wf->yAxis); @@ -1053,6 +1049,7 @@ void wfmain::setupPlots() pbtIndicator->topLeft->setCoords(0.5, 0); pbtIndicator->bottomRight->setCoords(0.5, 160); + // Plot user interaction connect(plot, SIGNAL(mouseDoubleClick(QMouseEvent*)), this, SLOT(handlePlotDoubleClick(QMouseEvent*))); connect(wf, SIGNAL(mouseDoubleClick(QMouseEvent*)), this, SLOT(handleWFDoubleClick(QMouseEvent*))); @@ -1135,9 +1132,9 @@ void wfmain::setupMainUI() - spans << "2.5k" << "5.0k" << "10k" << "25k"; - spans << "50k" << "100k" << "250k" << "500k"; - ui->scopeBWCombo->insertItems(0, spans); + //spans << "2.5k" << "5.0k" << "10k" << "25k"; + //spans << "50k" << "100k" << "250k" << "500k"; + //ui->scopeBWCombo->insertItems(0, spans); edges << "1" << "2" << "3" << "4"; ui->scopeEdgeCombo->insertItems(0, edges); @@ -1257,36 +1254,6 @@ void wfmain::setupMainUI() queue->add(priorityImmediate,queueItem(funcPBTInner,QVariant::fromValue(passbandHz))); }); - connect(this->cw, &cwSender::sendCW, this, [=](const QString &cwMessage) { - queue->add(priorityImmediate,queueItem(funcSendCW,QVariant::fromValue(cwMessage))); - }); - - connect(this->cw, &cwSender::stopCW, this, [=]() { - queue->add(priorityImmediate,queueItem(funcSendCW,QVariant::fromValue(0xff))); - }); - - connect(this->cw, &cwSender::setBreakInMode, this, [=](const unsigned char &bmode) { - queue->add(priorityImmediate,queueItem(funcBreakIn,QVariant::fromValue(bmode))); - }); - - connect(this->cw, &cwSender::setKeySpeed, this, [=](const unsigned char& wpm) { - queue->add(priorityImmediate,queueItem(funcKeySpeed,QVariant::fromValue(wpm))); - }); - - connect(this->cw, &cwSender::setDashRatio, this, [=](const unsigned char& ratio) { - queue->add(priorityImmediate,queueItem(funcDashRatio,QVariant::fromValue(ratio))); - }); - - connect(this->cw, &cwSender::setPitch, this, [=](const unsigned char& pitch) { - queue->add(priorityImmediate,queueItem(funcSendCW,QVariant::fromValue(pitch))); - }); - - connect(this->cw, &cwSender::getCWSettings, this, [=]() { - queue->add(priorityImmediate,funcKeySpeed); - queue->add(priorityImmediate,funcBreakIn); - queue->add(priorityImmediate,funcCwPitch); - queue->add(priorityImmediate,funcDashRatio); - }); } void wfmain::prepareSettingsWindow() @@ -1951,7 +1918,7 @@ void wfmain::buttonControl(const COMMAND* cmd) //Potentially add option to select specific step size? } break; - case funcScopeCenterSpan: + case funcScopeMainSpan: if (cmd->value == 100) { if (ui->scopeBWCombo->currentIndex() < ui->scopeBWCombo->count()-1) { @@ -2004,9 +1971,9 @@ void wfmain::buttonControl(const COMMAND* cmd) break; } - // Make sure we get status quickly - if (cmd->getCommand != funcNone) { - queue->add(priorityHigh,(funcs)cmd->getCommand); + // Make sure we get status quickly by sending a get command + if (cmd->command != funcNone) { + queue->add(priorityHigh,(funcs)cmd->command); } } @@ -3441,7 +3408,7 @@ void wfmain::shortcutF12() { // Speak current frequency and mode from the radio showStatusBarText("Sending speech command to radio."); - emit sayAll(); + queue->add(priorityImmediate,queueItem(funcSpeech,QVariant::fromValue(uchar(0U)))); } void wfmain::shortcutControlT() @@ -3811,17 +3778,17 @@ void wfmain:: getInitialRigState() queue->add(priorityImmediate,queueItem(funcScopeDataOutput,QVariant::fromValue(quint8(1)),false)); queue->add(priorityImmediate,queueItem(funcScopeOnOff,QVariant::fromValue(quint8(1)),false)); } - queue->add(priorityHigh,funcFilterWidth,false); - queue->add(priorityHigh,funcScopeRef,false); - queue->add(priorityHigh,funcScopeCenterFixed,false); - queue->add(priorityHigh,funcScopeCenterSpan,false); - queue->add(priorityHigh,funcDuplexStatus,false); } + if (rigCaps.commands.contains(funcFilterWidth)) + queue->add(priorityHigh,funcFilterWidth,false); + + + if (rigCaps.commands.contains(funcSplitStatus)) + queue->add(priorityHigh,funcSplitStatus,false); + if(rigCaps.commands.contains(funcTuningStep)) - { queue->add(priorityImmediate,funcTuningStep,false); - } if(rigCaps.commands.contains(funcRepeaterTone)) { @@ -3830,27 +3797,19 @@ void wfmain:: getInitialRigState() } if(rigCaps.commands.contains(funcRepeaterDTCS)) - { queue->add(priorityImmediate,funcRepeaterDTCS,false); - } if(rigCaps.commands.contains(funcToneSquelchType)) - { queue->add(priorityImmediate,funcToneSquelchType,false); - } if(rigCaps.commands.contains(funcAntenna)) - { queue->add(priorityImmediate,funcAntenna,false); - } + if(rigCaps.commands.contains(funcAttenuator)) - { queue->add(priorityImmediate,funcAttenuator,false); - } + if(rigCaps.commands.contains(funcPreamp)) - { queue->add(priorityImmediate,funcPreamp,false); - } if (rigCaps.commands.contains(funcRitStatus)) { @@ -3859,9 +3818,7 @@ void wfmain:: getInitialRigState() } if(rigCaps.commands.contains(funcIFShift)) - { queue->add(priorityImmediate,funcIFShift,false); - } if(rigCaps.commands.contains(funcPBTInner) && rigCaps.commands.contains(funcPBTOuter)) { @@ -3870,9 +3827,7 @@ void wfmain:: getInitialRigState() } if(rigCaps.commands.contains(funcTunerStatus)) - { queue->add(priorityImmediate,funcTunerStatus,false); - } } @@ -4218,7 +4173,7 @@ void wfmain::receiveRigID(rigCapabilities rigCaps) ui->scopeBWCombo->setHidden(false); for(unsigned int i=0; i < rigCaps.scopeCenterSpans.size(); i++) { - ui->scopeBWCombo->addItem(rigCaps.scopeCenterSpans.at(i).name, (int)rigCaps.scopeCenterSpans.at(i).cstype); + ui->scopeBWCombo->addItem(rigCaps.scopeCenterSpans.at(i).name, QVariant::fromValue(rigCaps.scopeCenterSpans.at(i))); } plot->yAxis->setRange(QCPRange(prefs.plotFloor, prefs.plotCeiling)); colorMap->setDataRange(QCPRange(prefs.plotFloor, prefs.plotCeiling)); @@ -4312,8 +4267,8 @@ void wfmain::initPeriodicCommands() if (rigCaps.commands.contains(funcAntenna)) queue->add(priorityMediumLow,funcAntenna,true); - if (rigCaps.commands.contains(funcDuplexStatus)) - queue->add(priorityMediumLow,funcDuplexStatus,true); + if (rigCaps.commands.contains(funcSplitStatus)) + queue->add(priorityMediumLow,funcSplitStatus,true); if(rigCaps.commands.contains(funcToneSquelchType)) queue->add(priorityMediumLow,funcToneSquelchType,true); @@ -4321,6 +4276,11 @@ void wfmain::initPeriodicCommands() if (rigCaps.commands.contains(funcSMeter)) queue->add(priorityHighest,queueItem(funcSMeter,true)); + if (rigCaps.hasSpectrum) + { + queue->add(priorityMediumHigh,queueItem(funcScopeMainMode,true)); + queue->add(priorityMediumHigh,queueItem(funcScopeMainSpan,true)); + } } void wfmain::receiveFreq(freqt freqStruct) @@ -4384,7 +4344,7 @@ void wfmain::changeTxBtn() -void wfmain::receiveSpectrumData(QByteArray spectrum, double startFreq, double endFreq) +void wfmain::receiveSpectrumData(scopeData spectrum) { if (ui->scopeEnableWFBtn->checkState()== Qt::PartiallyChecked) { @@ -4401,9 +4361,9 @@ void wfmain::receiveSpectrumData(QByteArray spectrum, double startFreq, double e //QElapsedTimer performanceTimer; bool updateRange = false; - if((startFreq != oldLowerFreq) || (endFreq != oldUpperFreq)) + if((spectrum.startFreq != oldLowerFreq) || (spectrum.endFreq != oldUpperFreq)) { - // If the frequency changed and we were drawing peaks, now is the time to clearn them + // If the frequency changed and we were drawing peaks, now is the time to clean them if(underlayMode == underlayPeakHold) { // TODO: create non-button function to do this @@ -4414,49 +4374,39 @@ void wfmain::receiveSpectrumData(QByteArray spectrum, double startFreq, double e preparePlasma(); } // Inform other threads (cluster) that the frequency range has changed. - emit setFrequencyRange(startFreq, endFreq); + emit setFrequencyRange(spectrum.startFreq, spectrum.endFreq); } - oldLowerFreq = startFreq; - oldUpperFreq = endFreq; + oldLowerFreq = spectrum.startFreq; + oldUpperFreq = spectrum.endFreq; - //qInfo(logSystem()) << "start: " << startFreq << " end: " << endFreq; - quint16 specLen = spectrum.length(); - //qInfo(logSystem()) << "Spectrum data received at UI! Length: " << specLen; - //if( (specLen != 475) || (specLen!=689) ) + //qInfo(logSystem()) << "start: " << spectrum.startFreq << " end: " << spectrum.endFreq; + quint16 specLen = spectrum.data.length(); - if( specLen != rigCaps.spectLenMax ) - { - qDebug(logSystem()) << "-------------------------------------------"; - qDebug(logSystem()) << "------ Unusual spectrum received, length: " << specLen; - qDebug(logSystem()) << "------ Expected spectrum length: " << rigCaps.spectLenMax; - qDebug(logSystem()) << "------ This should happen once at most. "; - return; // safe. Using these unusual length things is a problem. - } QVector x(spectWidth), y(spectWidth), y2(spectWidth); // TODO: Keep x around unless the frequency range changes. Should save a little time. for(int i=0; i < spectWidth; i++) { - x[i] = (i * (endFreq-startFreq)/spectWidth) + startFreq; + x[i] = (i * (spectrum.endFreq-spectrum.startFreq)/spectWidth) + spectrum.startFreq; } for(int i=0; i (unsigned char)spectrumPeaks.at(i)) + if((unsigned char)spectrum.data.at(i) > (unsigned char)spectrumPeaks.at(i)) { - spectrumPeaks[i] = spectrum.at(i); + spectrumPeaks[i] = spectrum.data.at(i); } y2[i] = (unsigned char)spectrumPeaks.at(i); } } plasmaMutex.lock(); - spectrumPlasma.push_front(spectrum); + spectrumPlasma.push_front(spectrum.data); if(spectrumPlasma.size() > (int)spectrumPlasmaSize) { spectrumPlasma.pop_back(); @@ -4475,7 +4425,7 @@ void wfmain::receiveSpectrumData(QByteArray spectrum, double startFreq, double e plot->graph(0)->setData(x, y, true); #endif - if((freq.MHzDouble < endFreq) && (freq.MHzDouble > startFreq)) + if((freq.MHzDouble < spectrum.endFreq) && (freq.MHzDouble > spectrum.startFreq)) { freqIndicatorLine->start->setCoords(freq.MHzDouble, 0); freqIndicatorLine->end->setCoords(freq.MHzDouble, rigCaps.spectAmpMax); @@ -4585,12 +4535,12 @@ void wfmain::receiveSpectrumData(QByteArray spectrum, double startFreq, double e if(updateRange) plot->yAxis->setRange(prefs.plotFloor, prefs.plotCeiling); - plot->xAxis->setRange(startFreq, endFreq); + plot->xAxis->setRange(spectrum.startFreq, spectrum.endFreq); plot->replot(); if(specLen == spectWidth) { - wfimage.prepend(spectrum); + wfimage.prepend(spectrum.data); wfimage.pop_back(); QByteArray wfRow; // Waterfall: @@ -4633,8 +4583,14 @@ void wfmain::receiveSpectrumData(QByteArray spectrum, double startFreq, double e oldPlotFloor = plotFloor; oldPlotCeiling = plotCeiling; - - + if (spectrum.oor && !oorIndicator->visible()) { + oorIndicator->setVisible(true); + oorIndicator->position->setCoords(0.5f,0.5f); + //oorIndicator->position->setCoords((oldLowerFreq+oldUpperFreq)/2,ui->topLevelSlider->value() - 20); + qInfo(logSystem()) << "Scope out of range"; + } else if (!spectrum.oor && oorIndicator->visible()) { + oorIndicator->setVisible(false); + } } } @@ -4687,29 +4643,12 @@ void wfmain::computePlasma() void wfmain::receivespectrumMode_t(spectrumMode_t spectMode) { - for (int i = 0; i < ui->spectrumMode_tCombo->count(); i++) - { - if (static_cast(ui->spectrumMode_tCombo->itemData(i).toInt()) == spectMode) - { - ui->spectrumMode_tCombo->blockSignals(true); - ui->spectrumMode_tCombo->setCurrentIndex(i); - ui->spectrumMode_tCombo->blockSignals(false); - } - } + ui->spectrumMode_tCombo->blockSignals(true); + ui->spectrumMode_tCombo->setCurrentIndex(ui->spectrumMode_tCombo->findData(spectMode)); + ui->spectrumMode_tCombo->blockSignals(false); setUISpectrumControlsToMode(spectMode); } -void wfmain::handleScopeOutOfRange(bool outOfRange) -{ - if(outOfRange) - { - ui->scopeOutOfRangeLabel->setText("OUT OF RANGE"); - ui->scopeOutOfRangeLabel->setStyleSheet("QLabel { background-color : red; color : blue; }"); - } else { - ui->scopeOutOfRangeLabel->setText(""); - ui->scopeOutOfRangeLabel->setStyleSheet(""); - } -} void wfmain::handlePlotDoubleClick(QMouseEvent *me) { @@ -5171,6 +5110,8 @@ void wfmain::receiveMode(modeInfo mode) if (!rigCaps.commands.contains(funcSelectedMode)) { queue->add(priorityImmediate,funcDataModeWithFilter); + } else { + receiveDataModeStatus(mode.data,mode.filter); } return; // We have nothing more to process @@ -5350,7 +5291,7 @@ void wfmain::on_fCEbtn_clicked() void wfmain::on_spectrumMode_tCombo_currentIndexChanged(int index) { spectrumMode_t smode = static_cast(ui->spectrumMode_tCombo->itemData(index).toInt()); - emit setScopeMode(smode); + queue->add(priorityImmediate,queueItem(funcScopeMainMode,QVariant::fromValue(smode))); setUISpectrumControlsToMode(smode); } @@ -5384,12 +5325,12 @@ void wfmain::on_fEnterBtn_clicked() void wfmain::on_scopeBWCombo_currentIndexChanged(int index) { - emit setScopeSpan((char)index); + queue->add(priorityImmediate,queueItem(funcScopeMainSpan,ui->scopeBWCombo->itemData(index))); } void wfmain::on_scopeEdgeCombo_currentIndexChanged(int index) { - emit setScopeEdge((char)index+1); + queue->add(priorityImmediate,queueItem(funcScopeMainEdge,QVariant::fromValue(index+1))); } void wfmain::changeMode(rigMode_t mode) @@ -5835,21 +5776,15 @@ void wfmain::receiveIFShift(unsigned char level) void wfmain::on_tuneNowBtn_clicked() { - queue->addUnique(priorityImmediate,queueItem(funcTunerStatus,QVariant::fromValue(2))); + queue->addUnique(priorityImmediate,queueItem(funcTunerStatus,QVariant::fromValue(2U))); showStatusBarText("Starting ATU tuning cycle..."); - queue->addUnique(priorityImmediate,funcTunerStatus); } void wfmain::on_tuneEnableChk_clicked(bool checked) { queue->addUnique(priorityImmediate,queueItem(funcTunerStatus,QVariant::fromValue(checked))); - if(checked) - { - showStatusBarText("Turning on ATU"); - } else { - showStatusBarText("Turning off ATU"); - } + showStatusBarText(QString("Turning %0 ATU").arg(checked?"on":"off")); } void wfmain::on_exitBtn_clicked() @@ -6100,12 +6035,11 @@ void wfmain::on_toFixedBtn_clicked() int edge = QString(item).toInt(&numOk,10); if(numOk) { - emit setScopeFixedEdge(oldLowerFreq, oldUpperFreq, edge); - emit setScopeEdge(edge); ui->scopeEdgeCombo->blockSignals(true); ui->scopeEdgeCombo->setCurrentIndex(edge-1); ui->scopeEdgeCombo->blockSignals(false); - queue->add(priorityImmediate,queueItem(funcScopeCenterFixed,QVariant::fromValue(1))); + queue->add(priorityImmediate,queueItem(funcScopeFixedEdgeFreq,QVariant::fromValue(spectrumBounds(oldLowerFreq, oldUpperFreq, edge)))); + queue->add(priorityImmediate,queueItem(funcScopeMainMode,QVariant::fromValue(spectrumMode_t::spectModeFixed))); } } } @@ -6798,14 +6732,12 @@ void wfmain::on_wfthemeCombo_activated(int index) void wfmain::receivePreamp(unsigned char pre) { - int preindex = ui->preampSelCombo->findData(pre); - ui->preampSelCombo->setCurrentIndex(preindex); + ui->preampSelCombo->setCurrentIndex(ui->preampSelCombo->findData(pre)); } void wfmain::receiveAttenuator(unsigned char att) { - int attindex = ui->attSelCombo->findData(att); - ui->attSelCombo->setCurrentIndex(attindex); + ui->attSelCombo->setCurrentIndex(ui->attSelCombo->findData(att)); } void wfmain::receiveAntennaSel(unsigned char ant, bool rx) @@ -6816,6 +6748,8 @@ void wfmain::receiveAntennaSel(unsigned char ant, bool rx) void wfmain::receiveSpectrumSpan(freqt freqspan, bool isSub) { + + if(!isSub) { switch((int)(freqspan.MHzDouble * 1000000.0)) @@ -8372,7 +8306,8 @@ with a comma between the low and high range.", if(ok) { qDebug(logGui()) << "setting edge to: " << lowFreq << ", " << highFreq << ", edge num: " << ui->scopeEdgeCombo->currentIndex() + 1; - emit setScopeFixedEdge(lowFreq, highFreq, ui->scopeEdgeCombo->currentIndex() + 1); + queue->add(priorityImmediate,queueItem(funcScopeFixedEdgeFreq, + QVariant::fromValue(spectrumBounds(lowFreq, highFreq, ui->scopeEdgeCombo->currentIndex() + 1)))); return; } } @@ -8989,7 +8924,7 @@ void wfmain::receiveValue(cacheItem val){ switch (val.command) { case funcFreqGet: - case funcfreqTR: + case funcFreqTR: case funcSelectedFreq: case funcUnselectedFreq: { @@ -9023,8 +8958,7 @@ void wfmain::receiveValue(cacheItem val){ case funcReadFreqOffset: break; case funcSplitStatus: - break; - case funcDuplexStatus: + rpt->receiveDuplexMode(val.value.value()); break; case funcTuningStep: receiveTuningStep(val.value.value()); @@ -9058,8 +8992,15 @@ void wfmain::receiveValue(cacheItem val){ case funcIFShift: receiveIFShift(val.value.value()); break; + /* + connect(this->rig, &rigCommander::haveDashRatio, + [=](const unsigned char& ratio) { cw->handleDashRatio(ratio); }); + connect(this->rig, &rigCommander::haveCWBreakMode, + [=](const unsigned char &bm) { cw->handleBreakInMode(bm);}); +*/ case funcCwPitch: receiveCwPitch(val.value.value()); + cw->handlePitch(val.value.value()); break; case funcRFPower: receiveTxPower(val.value.value()); @@ -9069,6 +9010,7 @@ void wfmain::receiveValue(cacheItem val){ break; case funcKeySpeed: // Only used by CW window + cw->handleKeySpeed(val.value.value()); break; case funcNotchFilter: break; @@ -9140,9 +9082,12 @@ void wfmain::receiveValue(cacheItem val){ break; case funcRepeaterTone: break; + rpt->handleRptAccessMode(rptAccessTxRx_t((val.value.value())?ratrTONEon:ratrTONEoff)); case funcRepeaterTSQL: + rpt->handleRptAccessMode(rptAccessTxRx_t((val.value.value())?ratrTSQLon:ratrTSQLoff)); break; case funcRepeaterDTCS: + break; case funcRepeaterCSQL: break; case funcCompressor: @@ -9176,6 +9121,9 @@ void wfmain::receiveValue(cacheItem val){ break; case funcIPPlus: break; + case funcBreakIn: + cw->handleBreakInMode(val.value.value()); + break; // 0x17 is CW send and 0x18 is power control (no reply) // 0x19 it automatically added. case funcTransceiverId: @@ -9224,14 +9172,21 @@ void wfmain::receiveValue(cacheItem val){ receiveModInput(val.value.value(), 3); break; case funcDashRatio: + cw->handleDashRatio(val.value.value()); break; // 0x1b register case funcToneFreq: + rpt->handleTone(val.value.value().tone); break; case funcTSQLFreq: + rpt->handleTSQL(val.value.value().tone); break; case funcDTCSCode: + { + toneInfo t = val.value.value(); + rpt->handleDTCS(t.tone,t.rinv,t.tinv); break; + } case funcCSQLCode: break; // 0x1c register @@ -9246,10 +9201,9 @@ void wfmain::receiveValue(cacheItem val){ case funcRITFreq: break; // 0x27 - case funcScopeWaveData: + case funcScopeMainWaveData: { - scopeData d = val.value.value(); - receiveSpectrumData(d.data,d.startFreq,d.endFreq); + receiveSpectrumData(val.value.value()); break; } case funcScopeOnOff: @@ -9264,29 +9218,36 @@ void wfmain::receiveValue(cacheItem val){ case funcScopeSingleDual: // This tells us whether we are receiving single or dual scopes break; - case funcScopeCenterFixed: + case funcScopeMainMode: // fixed or center // [1] 0x14 // [2] 0x00 // [3] 0x00 (center), 0x01 (fixed), 0x02, 0x03 + receivespectrumMode_t(val.value.value()); break; - case funcScopeCenterSpan: + case funcScopeMainSpan: { // read span in center mode // [1] 0x15 - // [2] to [8] is spastatic_cast(payloadIn.at(2)n encoded as a frequency - //emit haveScopeSpan(parseFrequency(payloadIn, 6), static_cast(payloadIn.at(2))); + // [2] to [8] is encoded as a frequency + centerSpanData d = val.value.value(); + if (ui->scopeBWCombo->currentIndex() != d.cstype) + { + ui->scopeBWCombo->blockSignals(true); + ui->scopeBWCombo->setCurrentIndex(d.cstype); + ui->scopeBWCombo->blockSignals(false); + } break; } - case funcScopeEdgeNumber: + case funcScopeMainEdge: // read edge mode center in edge mode // [1] 0x16 // [2] 0x01, 0x02, 0x03: Edge 1,2,3 break; - case funcScopeHold: + case funcScopeMainHold: // Hold status (only 9700?) break; - case funcScopeRef: + case funcScopeMainRef: { // scope reference level // [1] 0x19 @@ -9296,12 +9257,12 @@ void wfmain::receiveValue(cacheItem val){ // [5] 0x00 = +, 0x01 = - break; } - case funcScopeSpeed: + case funcScopeMainSpeed: case funcScopeDuringTX: case funcScopeCenterType: - case funcScopeVBW: - case funcScopeFixedFreq: - case funcScopeRBW: + case funcScopeMainVBW: + case funcScopeFixedEdgeFreq: + case funcScopeMainRBW: break; // 0x28 case funcVoiceTX: @@ -9314,10 +9275,5 @@ void wfmain::receiveValue(cacheItem val){ qWarning(logSystem()) << "Unhandled command received from rigcommander()" << funcString[val.command] << "Contact support!"; break; } - - - } - - diff --git a/wfmain.h b/wfmain.h index 3d8da93..fac3842 100644 --- a/wfmain.h +++ b/wfmain.h @@ -150,8 +150,8 @@ signals: void getDTCS(); void getRptAccessMode(); void setRepeaterAccessMode(rptrAccessData rd); - void setTone(rptrTone_t t); - void setTSQL(rptrTone_t t); + void setTone(toneInfo t); + void setTSQL(toneInfo t); void getToneEnabled(); void getTSQLEnabled(); void setToneEnabled(bool enabled); @@ -351,10 +351,9 @@ private slots: void receiveCommReady(); void receiveFreq(freqt); void receiveMode(modeInfo mode); - void receiveSpectrumData(QByteArray spectrum, double startFreq, double endFreq); + void receiveSpectrumData(scopeData data); void receivespectrumMode_t(spectrumMode_t spectMode); void receiveSpectrumSpan(freqt freqspan, bool isSub); - void handleScopeOutOfRange(bool outOfRange); void receivePTTstatus(bool pttOn); void receiveDataModeStatus(unsigned char data, unsigned char filter); void receiveBandStackReg(freqt f, char mode, char filter, bool dataOn); // freq, mode, (filter,) datamode @@ -861,6 +860,7 @@ private: QCPItemLine * freqIndicatorLine; QCPItemRect* passbandIndicator; QCPItemRect* pbtIndicator; + QCPItemText* oorIndicator; void setAppTheme(bool isCustom); void prepareWf(); void prepareWf(unsigned int wfLength); diff --git a/wfmain.ui b/wfmain.ui index 3eacdd0..60d08f9 100644 --- a/wfmain.ui +++ b/wfmain.ui @@ -18,7 +18,7 @@ - 3 + 0 @@ -117,19 +117,6 @@ - - - - - 5 - 0 - - - - - - - @@ -3902,7 +3889,7 @@ Please use the "Radio Server" page to select server audio 0 0 - 824 + 579 254 @@ -6009,8 +5996,8 @@ Please use the "Radio Server" page to select server audio - + diff --git a/wfviewtypes.h b/wfviewtypes.h index c207d2b..d17703a 100644 --- a/wfviewtypes.h +++ b/wfviewtypes.h @@ -75,11 +75,6 @@ enum vfo_t { vfoSub = 0xD1 }; -struct rptrTone_t { - quint16 tone = 0; - bool useSecondaryVFO = false; -}; - enum duplexMode_t { dmSplitOff=0x00, dmSplitOn=0x01, @@ -210,14 +205,14 @@ cmdLCDWaterfall, cmdLCDSpectrum, cmdLCDNothing, cmdSeparator // funcs and funcString MUST match exactly (and NUMFUNCS must be updated) -#define NUMFUNCS 197 +#define NUMFUNCS 210 enum funcs { funcNone, -funcfreqTR, funcModeTR, funcBandEdgeFreq, funcFreqGet, funcModeGet, funcFreqSet, // \x00 +funcFreqTR, funcModeTR, funcBandEdgeFreq, funcFreqGet, funcModeGet, funcFreqSet, // \x00 funcModeSet, funcVFOSwapAB, funcVFOSwapMS, funcVFOEqualAB, funcVFOEqualMS, funcVFODualWatchOff, // \x06 funcVFODualWatchOn, funcVFODualWatch, funcVFOMainSelect, funcVFOSubSelect, funcVFOASelect, funcVFOBSelect, // \x07 funcVFOBandMS, funcMemoryMode, funcMemoryWrite, funcMemoryToVFO, funcMemoryClear, funcReadFreqOffset, -funcSendFreqOffset, funcScanning, funcSplitStatus, funcDuplexStatus, funcTuningStep, funcAttenuator, +funcSendFreqOffset, funcScanning, funcSplitStatus, funcTuningStep, funcAttenuator, funcAntenna, funcSpeech, funcAfGain, funcRfGain, funcSquelch, funcAPFLevel, funcNRLevel, funcIFShift, funcPBTInner, funcPBTOuter, funcCwPitch, funcRFPower, funcMicGain, funcKeySpeed, funcNotchFilter, funcCompressorLevel, funcBreakInDelay, funcNBLevel, @@ -231,22 +226,23 @@ funcDSPIFFilter, funcNotchWidth, funcSSBBandwidth, funcMainSu funcToneSquelchType, funcIPPlus, funcSendCW, funcPowerControl, funcTransceiverId, funcFilterWidth, funcMemoryContents, funcBandStackReg, funcMemoryKeyer, funcIFFilterWidth, funcQuickDualWatch, funcQuickSplit, funcAutoRepeater, funcTunerStatus, funcTransverter, funcTransverterOffset, funcLockFunction, funcREFAdjust, -funcREFAdjustFine, funcACCAModLevel, funcACCBModLevel, funcUSBModLevel, funcLANModLevel, funcSPDIFModLevel, funcDATAOffMod, -funcDATA1Mod, funcDATA2Mod, funcDATA3Mod, funcCIVTransceive, funcTime, funcDate, -funcUTCOffset, funcCLOCK2, funcCLOCK2UTCOffset, funcCLOCK2Name, funcDashRatio, funcScanSpeed, -funcScanResume, funcRecorderMode, funcRecorderTX, funcRecorderRX, funcRecorderSplit, funcRecorderPTTAuto, -funcRecorderPreRec, funcRXAntConnector, funcAntennaSelectMode, funcNBDepth, funcNBWidth, funcVOXDelay, -funcVOXVoiceDelay, funcAPFType, funcAPFTypeLevel, funcPSKTone, funcRTTYMarkTone, funcDataModeWithFilter, -funcAFMute, funcToneFreq, funcTSQLFreq, funcDTCSCode, funcCSQLCode, funcTransceiverStatus, -funcXFCStatus, funcReadTXFreq, funcCIVOutput, funcReadTXFreqs, funcReadUserTXFreqs, funcUserTXBandEdgeFreq, -funcRITFreq, funcRitStatus, funcRitTXStatus, funcSelectedFreq, funcSelectedMode, funcUnselectedFreq, -funcUnselectedMode, funcScopeWaveData, -funcScopeOnOff, funcScopeDataOutput, funcScopeMainSub, funcScopeSingleDual, funcScopeCenterFixed, funcScopeCenterSpan, -funcScopeEdgeNumber, funcScopeHold, funcScopeRef, funcScopeSpeed, funcScopeDuringTX, funcScopeCenterType, -funcScopeVBW, funcScopeFixedFreq, funcScopeRBW, funcVoiceTX, funcMainSubPrefix, funcAFCSetting, +funcREFAdjustFine, funcACCAModLevel, funcACCBModLevel, funcUSBModLevel, funcLANModLevel, funcSPDIFModLevel, +funcDATAOffMod, funcDATA1Mod, funcDATA2Mod, funcDATA3Mod, funcCIVTransceive, funcTime, +funcDate, funcUTCOffset, funcCLOCK2, funcCLOCK2UTCOffset, funcCLOCK2Name, funcDashRatio, +funcScanSpeed, funcScanResume, funcRecorderMode, funcRecorderTX, funcRecorderRX, funcRecorderSplit, +funcRecorderPTTAuto, funcRecorderPreRec, funcRXAntConnector, funcAntennaSelectMode, funcNBDepth, funcNBWidth, +funcVOXDelay, funcVOXVoiceDelay, funcAPFType, funcAPFTypeLevel, funcPSKTone, funcRTTYMarkTone, +funcDataModeWithFilter, funcAFMute, funcToneFreq, funcTSQLFreq, funcDTCSCode, funcCSQLCode, +funcTransceiverStatus, funcXFCStatus, funcReadTXFreq, funcCIVOutput, funcReadTXFreqs, funcReadUserTXFreqs, +funcUserTXBandEdgeFreq, funcRITFreq, funcRitStatus, funcRitTXStatus, funcSelectedFreq, funcSelectedMode, +funcUnselectedFreq, funcUnselectedMode, funcScopeMainWaveData, funcScopeSubWaveData, funcScopeOnOff, funcScopeDataOutput, +funcScopeMainSub, funcScopeSingleDual, funcScopeMainMode, funcScopeSubMode, funcScopeMainSpan, funcScopeSubSpan, +funcScopeMainEdge, funcScopeSubEdge, funcScopeMainHold, funcScopeSubHold, funcScopeMainRef, funcScopeSubRef, +funcScopeMainSpeed, funcScopeSubSpeed, funcScopeMainVBW, funcScopeSubVBW, funcScopeMainRBW, funcScopeSubRBW, +funcScopeDuringTX, funcScopeCenterType, funcScopeFixedEdgeFreq, funcVoiceTX, funcMainSubPrefix, funcAFCSetting, funcGPSTXMode, funcSatelliteMemory, funcGPSPosition, funcMemoryGroup, funcSelectVFO, funcSeparator, -funcLCDWaterfall, funcLCDSpectrum, funcLCDNothing, funcPageUp, funcPageDown, funcFA, -funcFB +funcLCDWaterfall, funcLCDSpectrum, funcLCDNothing, funcPageUp, funcPageDown, funcVFOFrequency, +funcVFOMode, funcRigctlFunction, funcRigctlLevel, funcRigctlParam, funcFA, funcFB }; @@ -256,7 +252,7 @@ static QString funcString[] { "None", "Mode Set", "VFO Swap A/B", "VFO Swap M/S", "VFO Equal AB", "VFO Equal MS", "VFO Dual Watch Off", "VFO Dual Watch On", "VFO Dual Watch", "VFO Main Select", "VFO Sub Select", "VFO A Select", "VFO B Select", "VFO Main/Sub Band", "Memory Mode", "Memory Write", "Memory to VFO", "Memory Clear", "Read Freq Offset", -"Send Freq Offset", "Scanning", "Split Operation", "Duplex Operation", "Tuning Step", "Attenuator Status", +"Send Freq Offset", "Scanning", "Split/Duplex", "Tuning Step", "Attenuator Status", "Antenna", "Speech", "AF Gain", "RF Gain", "Squelch", "APF Level", "NR Level", "IF Shift", "PBT Inner", "PBT Outer", "CW Pitch", "RF Power", "Mic Gain", "Key Speed", "Notch Filter", "Compressor Level", "Break-In Delay", "NB Level", @@ -270,26 +266,25 @@ static QString funcString[] { "None", "Tone Squelch Type", "IP Plus Status", "Send CW", "Power Control", "Transceiver ID", "Filter Width", "Memory Contents", "Band Stacking Reg", "Memory Keyer", "IF Filter Width", "Quick Dual Watch", "Quick Split", "Auto Repeater Mode", "Tuner/ATU Status", "Transverter Function", "Transverter Offset", "Lock Function", "REF Adjust", -"REF Adjust Fine", "ACC1 Mod Level", "ACC2 Mod Level", "USB Mod Level", "LAN Mod Level", "SPDIF Mod Level", "Data Off Mod Input", -"DATA1 Mod Input", "DATA2 Mod Input", "DATA3 Mod Input", "CIV Transceive", "System Time", "System Date", -"UTC Offset", "CLOCK2 Setting", "CLOCK2 UTC Offset", "CLOCK 2 Name", "Dash Ratio", "Scanning Speed", -"Scanning Resume", "Recorder Mode", "Recorder TX", "Recorder RX", "Recorder Split", "Recorder PTT Auto", -"Recorder Pre Rec", "RX Ant Connector", "Antenna Select Mode", "NB Depth", "NB Width", "VOX Delay", -"VOX Voice Delay", "APF Type", "APF Type Level", "PSK Tone", "RTTY Mark Tone", "Data Mode Filter", -"AF Mute Status", "Tone Frequency", "TSQL Frequency", "DTCS Code/Polarity", "CSQL Code", "Transceiver Status", -"XFC Status", "Read TX Freq", "CI-V Output", "Read TX Freqs", "Read User TX Freqs", "User TX Band Edge Freq", -"RIT Frequency", "RIT Status", "RIT TX Status", "Selected Freq", "Selected Mode", "Unselected Freq", -"Unselected Mode", "Scope Wave Data", -"Scope On/Off", "Scope Data Output", "Scope Main/Sub", "Scope Single/Dual", "Scope Center Fixed", "Scope Center Span", -"Scope Edge Number", "Scope Hold", "Scope Ref", "Scope Speed", "Scope During TX", "Scope Center Type", -"Scope VBW", "Scope Fixed Freq", "Scope RBW", "Voice TX", "Main/Sub Prefix", "AFC Function", +"REF Adjust Fine", "ACC1 Mod Level", "ACC2 Mod Level", "USB Mod Level", "LAN Mod Level", "SPDIF Mod Level", +"Data Off Mod Input", "DATA1 Mod Input", "DATA2 Mod Input", "DATA3 Mod Input", "CIV Transceive", "System Time", +"System Date", "UTC Offset", "CLOCK2 Setting", "CLOCK2 UTC Offset", "CLOCK 2 Name", "Dash Ratio", +"Scanning Speed", "Scanning Resume", "Recorder Mode", "Recorder TX", "Recorder RX", "Recorder Split", +"Recorder PTT Auto", "Recorder Pre Rec", "RX Ant Connector", "Antenna Select Mode", "NB Depth", "NB Width", +"VOX Delay", "VOX Voice Delay", "APF Type", "APF Type Level", "PSK Tone", "RTTY Mark Tone", +"Data Mode Filter", "AF Mute Status", "Tone Frequency", "TSQL Frequency", "DTCS Code/Polavrity", "CSQL Code", +"Transceiver Status", "XFC Status", "Read TX Freq", "CI-V Output", "Read TX Freqs", "Read User TX Freqs", +"User TX Band Edge Freq","RIT Frequency", "RIT Status", "RIT TX Status", "Selected Freq", "Selected Mode", +"Unselected Freq", "Unselected Mode", "Scope Main Wave Data", "Scope Sub Wave Data", "Scope On/Off", "Scope Data Output", +"Scope Main/Sub", "Scope Single/Dual", "Scope Main Mode", "Scope Sub Mode", "Scope Main Span", "Scope Sub Span", +"Scope Main Edge", "Scope Sub Edge", "Scope Main Hold", "Scope Sub Hold", "Scope Main Ref", "Scope Sub Ref", +"Scope Main Speed", "Scope Sub Speed", "Scope Main VBW", "Scope Sub VBW", "Scope Main RBW", "Scope Sub RBW", +"Scope During TX", "Scope Center Type", "Scope Fixed Edge Freq", "Voice TX", "Main/Sub Prefix", "AFC Function", "GPS TX Mode", "Satellite Memory", "GPS Position", "Memory Group", "-Select VFO", "-Seperator", -"-LCD Waterfall", "-LCD Spectrum", "-LCD Nothing", "-Page Up", "-Page Down", "Command Error FA", -"Command OK FB" +"-LCD Waterfall", "-LCD Spectrum", "-LCD Nothing", "-Page Up", "-Page Down", "-VFO Frequency", +"-VFO Mode", "-Rigctl Function", "-Rigctl Level", "-Rigctl Param", "Command Error FA", "Command OK FB" }; - - struct spanType { spanType() {} spanType(int num, QString name, unsigned int freq) : num(num), name(name), freq(freq) {} @@ -321,6 +316,15 @@ struct stepType { quint64 hz; }; +struct spectrumBounds { + spectrumBounds(){}; + spectrumBounds(double start, double end, uchar edge) : start(start), end(end), edge(edge) {}; + double start; + double end; + uchar edge; + +}; + struct errorType { errorType() : alert(false) {}; errorType(bool alert, QString message) : alert(alert), message(message) {}; @@ -408,7 +412,6 @@ Q_DECLARE_METATYPE(rigMode_t) Q_DECLARE_METATYPE(vfo_t) Q_DECLARE_METATYPE(duplexMode_t) Q_DECLARE_METATYPE(rptAccessTxRx_t) -Q_DECLARE_METATYPE(rptrTone_t) Q_DECLARE_METATYPE(rptrAccessData) Q_DECLARE_METATYPE(usbFeatureType) Q_DECLARE_METATYPE(cmds)