diff --git a/cwsender.ui b/cwsender.ui index 900684f..f328e0f 100644 --- a/cwsender.ui +++ b/cwsender.ui @@ -6,7 +6,7 @@ 0 0 - 636 + 886 451 @@ -18,7 +18,7 @@ - + Macros @@ -161,41 +161,6 @@ - - - - - 0 - 0 - - - - Type here to send text as CW - - - true - - - - - - QComboBox::InsertAtTop - - - - - - - Send - - - Return - - - true - - - @@ -212,17 +177,7 @@ - - - - Stop sending CW - - - Stop - - - - + QLayout::SetMinimumSize @@ -334,6 +289,90 @@ + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Send + + + Return + + + true + + + + + + + Stop sending CW + + + Stop + + + + + + + + 0 + 0 + + + + Type here to send text as CW + + + true + + + + + + QComboBox::InsertAtTop + + + + + + + diff --git a/prefs.h b/prefs.h index 3f855d0..86c19f8 100644 --- a/prefs.h +++ b/prefs.h @@ -45,6 +45,7 @@ struct preferences { bool enablePTT; bool niceTS; bool automaticSidebandSwitching = true; + bool enableUSBControllers; // LAN: bool enableLAN; diff --git a/qledlabel.cpp b/qledlabel.cpp index d4fb314..e12e444 100644 --- a/qledlabel.cpp +++ b/qledlabel.cpp @@ -4,6 +4,7 @@ static const int SIZE = 16; static const QString greenSS = QString("color: white;border-radius: %1;background-color: qlineargradient(spread:pad, x1:0.145, y1:0.16, x2:1, y2:1, stop:0 rgba(20, 252, 7, 255), stop:1 rgba(25, 134, 5, 255));").arg(SIZE / 2); static const QString redSS = QString("color: white;border-radius: %1;background-color: qlineargradient(spread:pad, x1:0.145, y1:0.16, x2:0.92, y2:0.988636, stop:0 rgba(255, 12, 12, 255), stop:0.869347 rgba(103, 0, 0, 255));").arg(SIZE / 2); +static const QString rgSplitSS = QString("color: white;border-radius: %1;background-color: qlineargradient(spread:pad, x1:0.4, y1:0.5, x2:0.6, y2:0.5, stop:0 rgba(255, 0, 0, 255), stop:1.0 rgba(0, 255, 0, 255));").arg(SIZE / 2); static const QString orangeSS = QString("color: white;border-radius: %1;background-color: qlineargradient(spread:pad, x1:0.232, y1:0.272, x2:0.98, y2:0.959773, stop:0 rgba(255, 113, 4, 255), stop:1 rgba(91, 41, 7, 255))").arg(SIZE / 2); static const QString blueSS = QString("color: white;border-radius: %1;background-color: qlineargradient(spread:pad, x1:0.04, y1:0.0565909, x2:0.799, y2:0.795, stop:0 rgba(203, 220, 255, 255), stop:0.41206 rgba(0, 115, 255, 255), stop:1 rgba(0, 49, 109, 255));").arg(SIZE / 2); static const QString blankSS = QString("color: white;border-radius: %1;background-color: qlineargradient(spread:pad, x1:0.04, y1:0.0565909, x2:0.799, y2:0.795, stop:0 rgba(203, 220, 255, 0), stop:0.41206 rgba(0, 115, 255, 0), stop:1 rgba(0, 49, 109, 0));").arg(SIZE / 2); @@ -36,6 +37,9 @@ void QLedLabel::setState(State state) case StateBlank: setStyleSheet(blankSS); break; + case StateSplitErrorOk: + setStyleSheet(rgSplitSS); + break; default: setStyleSheet(blueSS); break; diff --git a/qledlabel.h b/qledlabel.h index d4117c9..ab041bd 100644 --- a/qledlabel.h +++ b/qledlabel.h @@ -14,6 +14,7 @@ public: StateOkBlue, StateWarning, StateError, + StateSplitErrorOk, StateBlank }; diff --git a/repeaterattributes.h b/repeaterattributes.h index b0389a2..4019b5f 100644 --- a/repeaterattributes.h +++ b/repeaterattributes.h @@ -2,31 +2,7 @@ #define REPEATERATTRIBUTES_H #include -enum duplexMode { - dmSplitOff=0x00, - dmSplitOn=0x01, - dmSimplex=0x10, - dmDupMinus=0x11, - dmDupPlus=0x12, - dmDupRPS=0x13, - dmDupAutoOn=0x26, - dmDupAutoOff=0x36 -}; +// TODO: Remove this file as it does nothing. -// Here, T=tone, D=DCS, N=none -// And the naming convention order is Transmit Receive -enum rptAccessTxRx { - ratrNN=0x00, - ratrTN=0x01, // "TONE" (T only) - ratrNT=0x02, // "TSQL" (R only) - ratrDD=0x03, // "DTCS" (TR) - ratrDN=0x06, // "DTCS(T)" - ratrTD=0x07, // "TONE(T) / TSQL(R)" - ratrDT=0x08, // "DTCS(T) / TSQL(R)" - ratrTT=0x09 // "TONE(T) / TSQL(R)" -}; - -Q_DECLARE_METATYPE(enum duplexMode) -Q_DECLARE_METATYPE(enum rptAccessTxRx) #endif // REPEATERATTRIBUTES_H diff --git a/repeatersetup.cpp b/repeatersetup.cpp index 58c148d..155cc79 100644 --- a/repeatersetup.cpp +++ b/repeatersetup.cpp @@ -7,22 +7,13 @@ repeaterSetup::repeaterSetup(QWidget *parent) : { ui->setupUi(this); + ui->autoTrackLiveBtn->setEnabled(false); // until we set split enabled. + // populate the CTCSS combo box: populateTones(); // populate the DCS combo box: populateDTCS(); - -#ifdef QT_DEBUG - ui->debugBtn->setVisible(true); - ui->rptReadRigBtn->setVisible(true); - ui->rptOffsetBtn->setVisible(true); -#else - ui->debugBtn->setVisible(false); - ui->rptReadRigBtn->setVisible(false); - ui->rptOffsetBtn->setVisible(false); -#endif - } repeaterSetup::~repeaterSetup() @@ -50,7 +41,6 @@ void repeaterSetup::setRig(rigCapabilities inRig) ui->toneTone->setDisabled(true); ui->toneTSQL->setDisabled(true); } - if(rig.hasDTCS) { ui->rptDTCSCombo->setDisabled(false); @@ -63,6 +53,54 @@ void repeaterSetup::setRig(rigCapabilities inRig) ui->rptDTCSInvertRx->setDisabled(true); ui->rptDTCSInvertTx->setDisabled(true); } + if(rig.hasVFOAB) + { + ui->selABtn->setDisabled(false); + ui->selBBtn->setDisabled(false); + ui->aEqBBtn->setDisabled(false); + ui->swapABBtn->setDisabled(false); + } else { + ui->selABtn->setDisabled(true); + ui->selBBtn->setDisabled(true); + ui->aEqBBtn->setDisabled(true); + ui->swapABBtn->setDisabled(true); + } + if(rig.hasVFOMS) + { + ui->selMainBtn->setDisabled(false); + ui->selSubBtn->setDisabled(false); + ui->mEqSBtn->setDisabled(false); + ui->swapMSBtn->setDisabled(false); + } else { + ui->selMainBtn->setDisabled(true); + ui->selSubBtn->setDisabled(true); + ui->mEqSBtn->setDisabled(true); + ui->swapMSBtn->setDisabled(true); + } + if(rig.hasVFOMS && rig.hasVFOAB) + { + // Rigs that have both AB and MS + // do not have a swap AB command. + ui->swapABBtn->setDisabled(true); + } + if(rig.hasSpecifyMainSubCmd) + { + ui->setRptrSubVFOBtn->setEnabled(true); + ui->setToneSubVFOBtn->setEnabled(true); + ui->setSplitRptrToneChk->setEnabled(true); + } else { + ui->setRptrSubVFOBtn->setDisabled(true); + ui->setToneSubVFOBtn->setDisabled(true); + ui->setSplitRptrToneChk->setDisabled(true); + } + ui->rptAutoBtn->setEnabled(rig.hasRepeaterModes); + ui->rptDupMinusBtn->setEnabled(rig.hasRepeaterModes); + ui->rptDupPlusBtn->setEnabled(rig.hasRepeaterModes); + ui->rptSimplexBtn->setEnabled(rig.hasRepeaterModes); + ui->rptrOffsetEdit->setEnabled(rig.hasRepeaterModes); + ui->rptrOffsetSetBtn->setEnabled(rig.hasRepeaterModes); + ui->setToneSubVFOBtn->setEnabled(rig.hasSpecifyMainSubCmd); + ui->setRptrSubVFOBtn->setEnabled(rig.hasSpecifyMainSubCmd); } void repeaterSetup::populateTones() @@ -241,29 +279,30 @@ void repeaterSetup::receiveDuplexMode(duplexMode dm) switch(dm) { case dmSplitOff: - ui->splitEnableChk->setChecked(false); - ui->autoTrackLiveBtn->setChecked(false); + ui->splitOffBtn->setChecked(true); + ui->autoTrackLiveBtn->setDisabled(true); break; case dmSplitOn: ui->splitEnableChk->setChecked(true); ui->rptSimplexBtn->setChecked(false); ui->rptDupPlusBtn->setChecked(false); + ui->autoTrackLiveBtn->setEnabled(true); ui->rptDupMinusBtn->setChecked(false); break; case dmSimplex: ui->rptSimplexBtn->setChecked(true); - ui->splitEnableChk->setChecked(false); - ui->autoTrackLiveBtn->setChecked(false); + //ui->splitEnableChk->setChecked(false); + ui->autoTrackLiveBtn->setDisabled(true); break; case dmDupPlus: ui->rptDupPlusBtn->setChecked(true); - ui->splitEnableChk->setChecked(false); - ui->autoTrackLiveBtn->setChecked(false); + //ui->splitEnableChk->setChecked(false); + ui->autoTrackLiveBtn->setDisabled(true); break; case dmDupMinus: ui->rptDupMinusBtn->setChecked(true); - ui->splitEnableChk->setChecked(false); - ui->autoTrackLiveBtn->setChecked(false); + //ui->splitEnableChk->setChecked(false); + ui->autoTrackLiveBtn->setDisabled(true); break; default: qDebug() << "Did not understand duplex/split/repeater value of " << (unsigned char)dm; @@ -321,7 +360,8 @@ void repeaterSetup::handleUpdateCurrentMainFrequency(freqt mainfreq) if(amTransmitting) return; - if(ui->autoTrackLiveBtn->isChecked() && !ui->splitOffsetEdit->text().isEmpty()) + // Track if autoTrack enabled, split enabled, and there's a split defined. + if(ui->autoTrackLiveBtn->isChecked() && (currentdm == dmSplitOn) && !ui->splitOffsetEdit->text().isEmpty()) { if(currentMainFrequency.Hz != mainfreq.Hz) { @@ -333,6 +373,11 @@ void repeaterSetup::handleUpdateCurrentMainFrequency(freqt mainfreq) on_splitMinusBtn_clicked(); } } + if(ui->setSplitRptrToneChk->isChecked()) + { + // TODO, not really needed if the op + // just sets the tone when needed, as it will do both bands. + } } this->currentMainFrequency = mainfreq; } @@ -351,6 +396,12 @@ void repeaterSetup::handleUpdateCurrentMainMode(mode_info m) } } +void repeaterSetup::handleRptOffsetFrequency(freqt f) +{ + QString offsetstr = QString::number(f.Hz / double(1E6), 'f', 4); + ui->rptrOffsetEdit->setText(offsetstr); +} + void repeaterSetup::handleTransmitStatus(bool amTransmitting) { this->amTransmitting = amTransmitting; @@ -358,15 +409,45 @@ void repeaterSetup::handleTransmitStatus(bool amTransmitting) void repeaterSetup::showEvent(QShowEvent *event) { + emit getDuplexMode(); emit getSplitModeEnabled(); + if(rig.hasRepeaterModes) + emit getRptDuplexOffset(); + (void)event; } +void repeaterSetup::on_splitEnableChk_clicked() +{ + emit setDuplexMode(dmSplitOn); + ui->autoTrackLiveBtn->setEnabled(true); + + if(ui->autoTrackLiveBtn->isChecked() && !ui->splitOffsetEdit->text().isEmpty()) + { + if(usedPlusSplit) + { + on_splitPlusButton_clicked(); + } else { + on_splitMinusBtn_clicked(); + } + } +} + +void repeaterSetup::on_splitOffBtn_clicked() +{ + emit setDuplexMode(dmSplitOff); + ui->autoTrackLiveBtn->setDisabled(true); +} + void repeaterSetup::on_rptSimplexBtn_clicked() { // Simplex - emit setDuplexMode(dmDupAutoOff); - emit setDuplexMode(dmSimplex); + emit setDuplexMode(dmSplitOff); + if(rig.hasRepeaterModes) + { + emit setDuplexMode(dmDupAutoOff); + emit setDuplexMode(dmSimplex); + } } void repeaterSetup::on_rptDupPlusBtn_clicked() @@ -399,11 +480,25 @@ void repeaterSetup::on_rptToneCombo_activated(int tindex) { quint16 tone=0; tone = (quint16)ui->rptToneCombo->itemData(tindex).toUInt(); + rptrTone_t rt; + rt.tone = tone; + bool updateSub = ui->setSplitRptrToneChk->isEnabled() && ui->setSplitRptrToneChk->isChecked(); if(ui->toneTone->isChecked()) { - emit setTone(tone); + emit setTone(rt); + if(updateSub) + { + rt.useSecondaryVFO = true; + emit setTone(rt); + } + } else if (ui->toneTSQL->isChecked()) { - emit setTSQL(tone); + emit setTSQL(rt); + if(updateSub) + { + rt.useSecondaryVFO = true; + emit setTone(rt); + } } } @@ -419,38 +514,75 @@ void repeaterSetup::on_rptDTCSCombo_activated(int index) void repeaterSetup::on_toneNone_clicked() { rptAccessTxRx rm; + rptrAccessData_t rd; rm = ratrNN; - emit setRptAccessMode(rm); + rd.accessMode = rm; + emit setRptAccessMode(rd); + bool updateSub = ui->setSplitRptrToneChk->isEnabled() && ui->setSplitRptrToneChk->isChecked(); + + if(updateSub) + { + rd.useSecondaryVFO = true; + emit setRptAccessMode(rd); + } } void repeaterSetup::on_toneTone_clicked() { rptAccessTxRx rm; + rptrAccessData_t rd; rm = ratrTN; - emit setRptAccessMode(rm); - emit setTone((quint16)ui->rptToneCombo->currentData().toUInt()); + rd.accessMode = rm; + rptrTone_t rt; + rt.tone = (quint16)ui->rptToneCombo->currentData().toUInt(); + emit setRptAccessMode(rd); + emit setTone(rt); + + bool updateSub = ui->setSplitRptrToneChk->isEnabled() && ui->setSplitRptrToneChk->isChecked(); + + if(updateSub) + { + rd.useSecondaryVFO = true; + rt.useSecondaryVFO = true; + emit setRptAccessMode(rd); + emit setTone(rt); + } } void repeaterSetup::on_toneTSQL_clicked() { rptAccessTxRx rm; + rptrAccessData_t rd; rm = ratrTT; - emit setRptAccessMode(rm); - emit setTSQL((quint16)ui->rptToneCombo->currentData().toUInt()); + rptrTone_t rt; + rt.tone = (quint16)ui->rptToneCombo->currentData().toUInt(); + rd.accessMode = rm; + emit setRptAccessMode(rd); + emit setTSQL(rt); + bool updateSub = ui->setSplitRptrToneChk->isEnabled() && ui->setSplitRptrToneChk->isChecked(); + + if(updateSub) + { + rd.useSecondaryVFO = true; + rt.useSecondaryVFO = true; + emit setRptAccessMode(rd); + emit setTone(rt); + } } void repeaterSetup::on_toneDTCS_clicked() { - rptAccessTxRx rm; + rptrAccessData_t rd; quint16 dcode=0; - rm = ratrDD; - emit setRptAccessMode(rm); + 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); + // TODO: DTCS with subband } void repeaterSetup::on_debugBtn_clicked() @@ -462,27 +594,13 @@ void repeaterSetup::on_debugBtn_clicked() emit getRptAccessMode(); } -void repeaterSetup::on_splitOffsetSetBtn_clicked() -{ - freqt txFreq; - bool ok = true; - txFreq.Hz = ui->splitTransmitFreqEdit->text().toDouble(&ok) * 1E6; - emit setTransmitFrequency(txFreq); -} - -void repeaterSetup::on_splitEnableChk_clicked(bool enabled) -{ - if(enabled) - { - emit setDuplexMode(dmSplitOn); - } else { - emit setDuplexMode(dmSplitOff); - } - if(ui->autoTrackLiveBtn->isChecked()) - { - ui->autoTrackLiveBtn->setChecked(false); - } -} +//void repeaterSetup::on_splitOffsetSetBtn_clicked() +//{ +// freqt txFreq; +// bool ok = true; +// txFreq.Hz = ui->splitTransmitFreqEdit->text().toDouble(&ok) * 1E6; +// emit setTransmitFrequency(txFreq); +//} quint64 repeaterSetup::getFreqHzFromKHzString(QString khz) { @@ -528,10 +646,16 @@ quint64 repeaterSetup::getFreqHzFromMHzString(QString MHz) // We want the right 4xx 3 characters. QString KHz = MHz.right(MHz.length() - decimalPtIndex - 1); MHz.chop(MHz.length() - decimalPtIndex); - + if(KHz.length() != 6) + { + QString zeros = QString("000000"); + zeros.chop(KHz.length()); + KHz.append(zeros); + } + //qInfo() << "KHz string: " << KHz; fhz = MHz.toUInt(&ok) * 1E6; if(!ok) goto handleError; - fhz += KHz.toUInt(&ok) * 1E3; if(!ok) goto handleError; - + fhz += KHz.toUInt(&ok) * 1; if(!ok) goto handleError; + //qInfo() << "Fhz: " << fhz; } else { // Frequency was already MHz (unlikely but what can we do?) fhz = MHz.toUInt(&ok) * 1E6; if(!ok) goto handleError; @@ -562,7 +686,6 @@ void repeaterSetup::on_splitPlusButton_clicked() } } - void repeaterSetup::on_splitMinusBtn_clicked() { quint64 hzOffset = getFreqHzFromKHzString(ui->splitOffsetEdit->text()); @@ -594,3 +717,97 @@ void repeaterSetup::on_splitTxFreqSetBtn_clicked() emit setTransmitMode(modeTransmitVFO); } } + +void repeaterSetup::on_splitTransmitFreqEdit_returnPressed() +{ + this->on_splitTxFreqSetBtn_clicked(); +} + +void repeaterSetup::on_selABtn_clicked() +{ + vfo_t v = vfoA; + emit selectVFO(v); +} + +void repeaterSetup::on_selBBtn_clicked() +{ + vfo_t v = vfoB; + emit selectVFO(v); +} + +void repeaterSetup::on_aEqBBtn_clicked() +{ + emit equalizeVFOsAB(); +} + +void repeaterSetup::on_swapABBtn_clicked() +{ + emit swapVFOs(); +} + +void repeaterSetup::on_selMainBtn_clicked() +{ + vfo_t v = vfoMain; + emit selectVFO(v); +} + +void repeaterSetup::on_selSubBtn_clicked() +{ + vfo_t v = vfoSub; + emit selectVFO(v); +} + +void repeaterSetup::on_mEqSBtn_clicked() +{ + emit equalizeVFOsMS(); +} + +void repeaterSetup::on_swapMSBtn_clicked() +{ + emit swapVFOs(); +} + +void repeaterSetup::on_setToneSubVFOBtn_clicked() +{ + // Perhaps not needed + // Set the secondary VFO to the selected tone + // TODO: DTCS + rptrTone_t rt; + rt.tone = (quint16)ui->rptToneCombo->currentData().toUInt(); + rt.useSecondaryVFO = true; + emit setTone(rt); +} + +void repeaterSetup::on_setRptrSubVFOBtn_clicked() +{ + // Perhaps not needed + // Set the secondary VFO to the selected repeater mode + rptrAccessData_t rd; + rd.useSecondaryVFO = true; + + if(ui->toneTone->isChecked()) + rd.accessMode=ratrTN; + if(ui->toneNone->isChecked()) + rd.accessMode=ratrNN; + if(ui->toneTSQL->isChecked()) + rd.accessMode=ratrTT; + if(ui->toneDTCS->isChecked()) + rd.accessMode=ratrDD; + + emit setRptAccessMode(rd); +} + +void repeaterSetup::on_rptrOffsetSetBtn_clicked() +{ + freqt f; + f.Hz = getFreqHzFromMHzString(ui->rptrOffsetEdit->text()); + if(f.Hz != 0) + { + emit setRptDuplexOffset(f); + } +} + +void repeaterSetup::on_rptrOffsetEdit_returnPressed() +{ + this->on_rptrOffsetSetBtn_clicked(); +} diff --git a/repeatersetup.h b/repeatersetup.h index 73c71c7..47f3ec1 100644 --- a/repeatersetup.h +++ b/repeatersetup.h @@ -23,14 +23,16 @@ public: signals: void getDuplexMode(); void setDuplexMode(duplexMode dm); - void setTone(quint16 tone); - void setTSQL(quint16 tsql); + void setTone(rptrTone_t tone); + void setTSQL(rptrTone_t tsql); void setDTCS(quint16 dcode, bool tinv, bool rinv); void getTone(); void getTSQL(); void getDTCS(); - void setRptAccessMode(rptAccessTxRx tmode); + void setRptAccessMode(rptrAccessData_t rd); void getRptAccessMode(); + void setRptDuplexOffset(freqt f); + void getRptDuplexOffset(); // Split: void getSplitModeEnabled(); void getTransmitFrequency(); @@ -38,6 +40,11 @@ signals: // void setSplitModeEnabled(bool splitEnabled); void setTransmitFrequency(freqt transmitFreq); void setTransmitMode(mode_info m); + // VFO: + void selectVFO(vfo_t v); // A,B,M,S + void equalizeVFOsAB(); + void equalizeVFOsMS(); + void swapVFOs(); public slots: void receiveDuplexMode(duplexMode dm); @@ -50,6 +57,7 @@ public slots: void handleUpdateCurrentMainFrequency(freqt mainfreq); void handleUpdateCurrentMainMode(mode_info m); void handleTransmitStatus(bool amTransmitting); + void handleRptOffsetFrequency(freqt f); private slots: void showEvent(QShowEvent *event); @@ -65,13 +73,41 @@ private slots: void on_toneTone_clicked(); void on_toneTSQL_clicked(); void on_toneDTCS_clicked(); - void on_splitOffsetSetBtn_clicked(); - void on_splitEnableChk_clicked(bool enabled); void on_splitPlusButton_clicked(); void on_splitMinusBtn_clicked(); void on_splitTxFreqSetBtn_clicked(); + void on_selABtn_clicked(); + + void on_selBBtn_clicked(); + + void on_aEqBBtn_clicked(); + + void on_swapABBtn_clicked(); + + void on_selMainBtn_clicked(); + + void on_selSubBtn_clicked(); + + void on_mEqSBtn_clicked(); + + void on_swapMSBtn_clicked(); + + void on_setToneSubVFOBtn_clicked(); + + void on_setRptrSubVFOBtn_clicked(); + + void on_rptrOffsetSetBtn_clicked(); + + void on_splitOffBtn_clicked(); + + void on_splitEnableChk_clicked(); + + void on_rptrOffsetEdit_returnPressed(); + + void on_splitTransmitFreqEdit_returnPressed(); + private: Ui::repeaterSetup *ui; freqt currentMainFrequency; diff --git a/repeatersetup.ui b/repeatersetup.ui index e49f2f2..da02a26 100644 --- a/repeatersetup.ui +++ b/repeatersetup.ui @@ -6,62 +6,27 @@ 0 0 - 922 - 217 + 1071 + 231 + + + 1071 + 230 + + + + + 1071 + 231 + + Repeater Setup - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - 0 - - - - - Read Current Settings - - - - - - - Debug - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - @@ -72,6 +37,12 @@ + + + 180 + 16777215 + + Repeater Duplex @@ -116,11 +87,38 @@ + + + + + + <html><head/><body><p>Set the repeater offset for radios using Repeater modes. Only available on radios that have repeater modes. Radios using Split should instead use the provided Split Mode section with a custom Offset. </p></body></html> + + + Set Offset (MHz): + + + + + + + + + Rpt Offset (MHz) + + + + + + 400 + 16777215 + + Split Mode @@ -128,16 +126,52 @@ - + + + Turn on Split + - Split Enable + Split On + + + rptDuplexBtns + + + + + + + Turn off Split + + + Split Off + + + rptDuplexBtns + + + + + + + + + + + <html><head/><body><p>Click here to automatically set the sub VFO (transmit VFO) tone. Only available on some radios. Other radios may take care of this for you.</p></body></html> + + + Set Rpt Tone + + <html><head/><body><p>Click here to continually set the transmit VFO to match the receive VFO with the offset accounted for. </p></body></html> + - Auto Track Live + AutoTrack @@ -166,10 +200,22 @@ 16777215 + + Enter the desired split offset in KHz. + + + + 55 + 16777215 + + + + <html><head/><body><p>Set the transmit frequency to the receive frequency PLUS the offset. Sets the radio sub VFO and also populates the wfview text box (as a convenience). </p></body></html> + Split+ @@ -177,18 +223,20 @@ + + + 55 + 16777215 + + + + <html><head/><body><p>Set the transmit frequency to the receive frequency PLUS the offset. Sets the radio sub VFO and also populates the wfview text box (as a convenience). </p></body></html> + Split- - - - - RPT - - - @@ -218,6 +266,15 @@ + + + 116 + 16777215 + + + + <html><head/><body><p>Set the transmit frequency manually. Not needed if the Split+ or Split- button was used. </p></body></html> + Set @@ -228,8 +285,109 @@ + + + + + 220 + 16777215 + + + + VFO + + + + + + Swap VFO A with VFO B. Some radios do not support this. + + + Swap AB + + + + + + + Select the Sub VFO + + + Sel Sub + + + + + + + Select the Main VFO + + + Sel Main + + + + + + + Select VFO B + + + Sel B + + + + + + + Select VFO A + + + Sel A + + + + + + + Set VFO B to VFO A + + + A=B + + + + + + + Set the SUB VFO to match the Main VFO + + + M=>S + + + + + + + Swap the Main VFO and Sub VFO + + + Swap MS + + + + + + + + + 200 + 16777215 + + Repeater Tone Type @@ -274,11 +432,27 @@ + + + + Set the Tone Mode for the Sub VFO. Not available on all radios. + + + Set Sub VFO + + + + + + 200 + 16777215 + + Tone Selection @@ -329,6 +503,16 @@ + + + + Set the Sub VFO to the selected Tone. Not available on all radios and not available for DTCS. + + + Set Sub VFO + + + @@ -340,7 +524,7 @@ - + diff --git a/resources/shuttlexpress.png b/resources/shuttlexpress.png index bc64bdd..934f2d4 100644 Binary files a/resources/shuttlexpress.png and b/resources/shuttlexpress.png differ diff --git a/rigcommander.cpp b/rigcommander.cpp index eedd21b..d2aa849 100644 --- a/rigcommander.cpp +++ b/rigcommander.cpp @@ -657,6 +657,44 @@ void rigCommander::setFrequency(unsigned char vfo, freqt freq) prepDataAndSend(cmdPayload); } +void rigCommander::selectVFO(vfo_t vfo) +{ + // Note, some radios use main/sub, + // some use A/B, + // and some appear to use both... + QByteArray payload; + + char vfoBytes[1]; + vfoBytes[0] = (unsigned char)vfo; + + payload.setRawData("\x07", 1); + payload.append(vfoBytes, 1); + prepDataAndSend(payload); +} + +void rigCommander::equalizeVFOsAB() +{ + QByteArray payload; + payload.setRawData("\x07\xA0", 2); + prepDataAndSend(payload); +} + +void rigCommander::equalizeVFOsMS() +{ + QByteArray payload; + payload.setRawData("\x07\xB1", 2); + prepDataAndSend(payload); +} + +void rigCommander::exchangeVFOs() +{ + // NB: This command exchanges A-B or M-S + // depending upon the radio. + QByteArray payload; + payload.setRawData("\x07\xB0", 2); + prepDataAndSend(payload); +} + QByteArray rigCommander::makeFreqPayload(freqt freq) { QByteArray result; @@ -1005,28 +1043,54 @@ void rigCommander::getTransmitFrequency() void rigCommander::setTone(quint16 tone) { + rptrTone_t t; + t.tone = tone; + setTone(t); +} + +void rigCommander::setTone(rptrTone_t t) +{ + quint16 tone = t.tone; + QByteArray fenc = encodeTone(tone); QByteArray payload; payload.setRawData("\x1B\x00", 2); payload.append(fenc); - //qInfo() << __func__ << "TONE encoded payload: "; - printHex(payload); + if(t.useSecondaryVFO) + { + qDebug(logRig()) << "Sending TONE to secondary VFO"; + payload.prepend("\x29\x01"); + printHex(payload); + } prepDataAndSend(payload); } -void rigCommander::setTSQL(quint16 tsql) +void rigCommander::setTSQL(quint16 t) { + rptrTone_t tn; + tn.tone = t; + setTSQL(tn); +} + +void rigCommander::setTSQL(rptrTone_t t) +{ + quint16 tsql = t.tone; + QByteArray fenc = encodeTone(tsql); QByteArray payload; payload.setRawData("\x1B\x01", 2); payload.append(fenc); - //qInfo() << __func__ << "TSQL encoded payload: "; - printHex(payload); + if(t.useSecondaryVFO) + { + qDebug(logRig()) << "Sending TSQL to secondary VFO"; + payload.prepend("\x29\x01"); + printHex(payload); + } prepDataAndSend(payload); } @@ -1134,10 +1198,42 @@ void rigCommander::getRptAccessMode() } void rigCommander::setRptAccessMode(rptAccessTxRx ratr) +{ + rptrAccessData_t rd; + rd.accessMode = ratr; + setRptAccessMode(rd); +} + +void rigCommander::setRptAccessMode(rptrAccessData_t rd) { QByteArray payload; payload.setRawData("\x16\x5D", 2); - payload.append((unsigned char)ratr); + payload.append((unsigned char)rd.accessMode); + if(rd.useSecondaryVFO) + { + payload.prepend("\x29\x01"); + } + prepDataAndSend(payload); +} + +void rigCommander::setRptDuplexOffset(freqt f) +{ + QByteArray payload; + payload.setRawData("\x0D", 1); + // get f, chop to 10 MHz + QByteArray freqPayload = makeFreqPayload(f); + payload.append(freqPayload.mid(1, 3)); + //qInfo(logRig()) << "Here is potential repeater offset setting, not sending to radio:"; + printHexNow(payload, logRig()); + QString g = getHex(payload); + //qInfo(logRig()).noquote().nospace() << g; + prepDataAndSend(payload); +} + +void rigCommander::getRptDuplexOffset() +{ + QByteArray payload; + payload.setRawData("\x0C", 1); prepDataAndSend(payload); } @@ -1475,6 +1571,10 @@ void rigCommander::parseCommand() //qInfo(logRig()) << "Have mode data"; this->parseMode(); break; + case '\x0C': + //qDebug(logRig) << "Have 0x0C reply"; + emit haveRptOffsetFrequency(parseFrequencyRptOffset(payloadIn)); + break; case '\x0F': emit haveDuplexMode((duplexMode)(unsigned char)payloadIn[1]); state.set(DUPLEX, (duplexMode)(unsigned char)payloadIn[1], false); @@ -3357,7 +3457,8 @@ void rigCommander::determineRigCaps() rigCaps.bands.insert(rigCaps.bands.end(), { bandDef4m, bandDef630m, bandDef2200m, bandDefGen }); rigCaps.modes = commonModes; rigCaps.transceiveCommand = QByteArrayLiteral("\x1a\x05\x00\x71"); - + rigCaps.hasVFOMS = false; + rigCaps.hasVFOAB = true; break; case modelR8600: rigCaps.modelName = QString("IC-R8600"); @@ -3395,6 +3496,8 @@ void rigCommander::determineRigCaps() createMode(modeDCR, 0x21, "DCR")}); rigCaps.scopeCenterSpans.insert(rigCaps.scopeCenterSpans.end(), {createScopeCenter(cs1M, "±1M"), createScopeCenter(cs2p5M, "±2.5M")}); rigCaps.transceiveCommand = QByteArrayLiteral("\x1a\x05\x00\x92"); + rigCaps.hasVFOMS = true; // not documented very well + rigCaps.hasVFOAB = true; // so we just do both... break; case model9700: rigCaps.modelName = QString("IC-9700"); @@ -3413,6 +3516,7 @@ void rigCommander::determineRigCaps() rigCaps.hasDV = true; rigCaps.hasCTCSS = true; rigCaps.hasDTCS = true; + rigCaps.hasRepeaterModes = true; rigCaps.hasTBPF = true; rigCaps.attenuators.push_back('\x10'); rigCaps.preamps.push_back('\x01'); @@ -3425,6 +3529,8 @@ void rigCommander::determineRigCaps() rigCaps.modes.insert(rigCaps.modes.end(), {createMode(modeDV, 0x17, "DV"), createMode(modeDD, 0x22, "DD")}); rigCaps.transceiveCommand = QByteArrayLiteral("\x1a\x05\x01\x27"); + rigCaps.hasVFOMS = true; + rigCaps.hasVFOAB = true; break; case model910h: rigCaps.modelName = QString("IC-910H"); @@ -3438,6 +3544,7 @@ void rigCommander::determineRigCaps() rigCaps.hasDV = false; rigCaps.hasCTCSS = true; rigCaps.hasDTCS = true; + rigCaps.hasRepeaterModes = true; rigCaps.hasATU = false; rigCaps.attenuators.insert(rigCaps.attenuators.end(),{ '\x10' , '\x20', '\x30'}); rigCaps.preamps.push_back('\x01'); @@ -3448,6 +3555,8 @@ void rigCommander::determineRigCaps() rigCaps.bsr[band2m] = 0x01; rigCaps.modes = commonModes; rigCaps.transceiveCommand = QByteArrayLiteral("\x1a\x05\x00\x58"); + rigCaps.hasVFOMS = false; + rigCaps.hasVFOAB = true; break; case model7600: rigCaps.modelName = QString("IC-7600"); @@ -3474,6 +3583,8 @@ void rigCommander::determineRigCaps() rigCaps.modes.insert(rigCaps.modes.end(), { createMode(modePSK, 0x12, "PSK"), createMode(modePSK_R, 0x13, "PSK-R") }); rigCaps.transceiveCommand = QByteArrayLiteral("\x1a\x05\x00\x97"); + rigCaps.hasVFOMS = true; + rigCaps.hasVFOAB = false; break; case model7610: rigCaps.modelName = QString("IC-7610"); @@ -3507,6 +3618,9 @@ void rigCommander::determineRigCaps() createMode(modePSK_R, 0x13, "PSK-R") }); rigCaps.hasRXAntenna = true; rigCaps.transceiveCommand = QByteArrayLiteral("\x1a\x05\x01\x12"); + rigCaps.hasSpecifyMainSubCmd = true; + rigCaps.hasVFOMS = true; + rigCaps.hasVFOAB = false; break; case model7850: rigCaps.modelName = QString("IC-785x"); @@ -3539,6 +3653,9 @@ void rigCommander::determineRigCaps() createMode(modePSK_R, 0x13, "PSK-R")}); rigCaps.hasRXAntenna = true; rigCaps.transceiveCommand = QByteArrayLiteral("\x1a\x05\x01\x55"); + rigCaps.hasSpecifyMainSubCmd = true; + rigCaps.hasVFOMS = true; + rigCaps.hasVFOAB = false; break; case model705: rigCaps.modelName = QString("IC-705"); @@ -3557,6 +3674,7 @@ void rigCommander::determineRigCaps() rigCaps.hasATU = true; rigCaps.hasCTCSS = true; rigCaps.hasDTCS = true; + rigCaps.hasRepeaterModes = true; rigCaps.hasTBPF = true; rigCaps.attenuators.insert(rigCaps.attenuators.end(),{ '\x10' , '\x20'}); rigCaps.preamps.push_back('\x01'); @@ -3573,6 +3691,8 @@ void rigCommander::determineRigCaps() rigCaps.modes.insert(rigCaps.modes.end(), {createMode(modeWFM, 0x06, "WFM"), createMode(modeDV, 0x17, "DV")}); rigCaps.transceiveCommand = QByteArrayLiteral("\x1a\x05\x01\x31"); + rigCaps.hasVFOMS = false; + rigCaps.hasVFOAB = true; break; case model7000: rigCaps.modelName = QString("IC-7000"); @@ -3597,6 +3717,8 @@ void rigCommander::determineRigCaps() rigCaps.bsr[bandGen] = 0x13; rigCaps.modes = commonModes; rigCaps.transceiveCommand = QByteArrayLiteral("\x1a\x05\x00\x92"); + rigCaps.hasVFOMS = false; + rigCaps.hasVFOAB = true; break; case model7410: rigCaps.modelName = QString("IC-7410"); @@ -3620,6 +3742,8 @@ void rigCommander::determineRigCaps() rigCaps.bsr[bandGen] = 0x11; rigCaps.modes = commonModes; rigCaps.transceiveCommand = QByteArrayLiteral("\x1a\x05\x00\x40"); + rigCaps.hasVFOMS = false; + rigCaps.hasVFOAB = true; break; case model7100: rigCaps.modelName = QString("IC-7100"); @@ -3634,6 +3758,7 @@ void rigCommander::determineRigCaps() rigCaps.hasATU = true; rigCaps.hasCTCSS = true; rigCaps.hasDTCS = true; + rigCaps.hasRepeaterModes = true; rigCaps.hasTBPF = true; rigCaps.attenuators.push_back('\x12'); rigCaps.preamps.push_back('\x01'); @@ -3648,6 +3773,8 @@ void rigCommander::determineRigCaps() rigCaps.modes.insert(rigCaps.modes.end(), {createMode(modeWFM, 0x06, "WFM"), createMode(modeDV, 0x17, "DV")}); rigCaps.transceiveCommand = QByteArrayLiteral("\x1a\x05\x00\x95"); + rigCaps.hasVFOMS = false; + rigCaps.hasVFOAB = true; break; case model7200: rigCaps.modelName = QString("IC-7200"); @@ -3670,6 +3797,8 @@ void rigCommander::determineRigCaps() rigCaps.bsr[bandGen] = 0x11; rigCaps.modes = commonModes; rigCaps.transceiveCommand = QByteArrayLiteral("\x1a\x03\x48"); + rigCaps.hasVFOMS = false; + rigCaps.hasVFOAB = true; break; case model7700: rigCaps.modelName = QString("IC-7700"); @@ -3696,6 +3825,8 @@ void rigCommander::determineRigCaps() rigCaps.modes.insert(rigCaps.modes.end(), {createMode(modePSK, 0x12, "PSK"), createMode(modePSK_R, 0x13, "PSK-R")}); rigCaps.transceiveCommand = QByteArrayLiteral("\x1a\x05\x00\x95"); + rigCaps.hasVFOMS = false; + rigCaps.hasVFOAB = true; break; case model703: rigCaps.modelName = QString("IC-703"); @@ -3738,6 +3869,8 @@ void rigCommander::determineRigCaps() rigCaps.modes = commonModes; rigCaps.modes.insert(rigCaps.modes.end(), createMode(modeWFM, 0x06, "WFM")); rigCaps.transceiveCommand = QByteArrayLiteral("\x1a\x05\x00\x00"); + rigCaps.hasVFOMS = false; + rigCaps.hasVFOAB = true; break; case model718: rigCaps.modelName = QString("IC-718"); @@ -3764,7 +3897,9 @@ void rigCommander::determineRigCaps() createMode(modeRTTY, 0x04, "RTTY"), createMode(modeRTTY_R, 0x08, "RTTY-R") }; rigCaps.transceiveCommand = QByteArrayLiteral("\x1a\x05\x00\x00"); - break; + rigCaps.hasVFOMS = false; + rigCaps.hasVFOAB = true; + break; case model736: rigCaps.modelName = QString("IC-736"); rigCaps.rigctlModel = 3020; @@ -3785,6 +3920,8 @@ void rigCommander::determineRigCaps() createMode(modeAM, 0x02, "AM"), createMode(modeFM, 0x05, "FM"), createMode(modeCW, 0x03, "CW"), createMode(modeCW_R, 0x07, "CW-R"), }; + rigCaps.hasVFOMS = false; + rigCaps.hasVFOAB = true; break; case model737: rigCaps.modelName = QString("IC-737"); @@ -3806,6 +3943,8 @@ void rigCommander::determineRigCaps() createMode(modeAM, 0x02, "AM"), createMode(modeFM, 0x05, "FM"), createMode(modeCW, 0x03, "CW"), createMode(modeCW_R, 0x07, "CW-R"), }; + rigCaps.hasVFOMS = false; + rigCaps.hasVFOAB = true; break; case model738: rigCaps.modelName = QString("IC-738"); @@ -3827,6 +3966,8 @@ void rigCommander::determineRigCaps() createMode(modeAM, 0x02, "AM"), createMode(modeFM, 0x05, "FM"), createMode(modeCW, 0x03, "CW"), createMode(modeCW_R, 0x07, "CW-R"), }; + rigCaps.hasVFOMS = false; + rigCaps.hasVFOAB = true; break; case model746: rigCaps.modelName = QString("IC-746"); @@ -3842,6 +3983,7 @@ void rigCommander::determineRigCaps() rigCaps.hasIFShift = true; rigCaps.hasCTCSS = true; rigCaps.hasDTCS = true; + rigCaps.hasRepeaterModes = true; rigCaps.hasAntennaSel = true; rigCaps.preamps.push_back('\x01'); rigCaps.preamps.push_back('\x02'); @@ -3854,6 +3996,8 @@ void rigCommander::determineRigCaps() rigCaps.bands.push_back(bandDefGen); rigCaps.modes = commonModes; rigCaps.transceiveCommand = QByteArrayLiteral("\x1a\x05\x00\x00"); + rigCaps.hasVFOMS = true; + rigCaps.hasVFOAB = true; break; case model756: rigCaps.modelName = QString("IC-756"); @@ -3875,6 +4019,8 @@ void rigCommander::determineRigCaps() rigCaps.bsr[bandGen] = 0x11; rigCaps.modes = commonModes; rigCaps.transceiveCommand = QByteArrayLiteral("\x1a\x05\x00\x00"); + rigCaps.hasVFOMS = true; + rigCaps.hasVFOAB = false; break; case model756pro: rigCaps.modelName = QString("IC-756 Pro"); @@ -3896,6 +4042,8 @@ void rigCommander::determineRigCaps() rigCaps.bsr[bandGen] = 0x11; rigCaps.modes = commonModes; rigCaps.transceiveCommand = QByteArrayLiteral("\x1a\x05\x00\x00"); + rigCaps.hasVFOMS = true; + rigCaps.hasVFOAB = false; break; case model756proii: rigCaps.modelName = QString("IC-756 Pro II"); @@ -3917,6 +4065,8 @@ void rigCommander::determineRigCaps() rigCaps.bsr[bandGen] = 0x11; rigCaps.modes = commonModes; rigCaps.transceiveCommand = QByteArrayLiteral("\x1a\x05\x00\x00"); + rigCaps.hasVFOMS = true; + rigCaps.hasVFOAB = false; break; case model756proiii: rigCaps.modelName = QString("IC-756 Pro III"); @@ -3938,6 +4088,8 @@ void rigCommander::determineRigCaps() rigCaps.bsr[bandGen] = 0x11; rigCaps.modes = commonModes; rigCaps.transceiveCommand = QByteArrayLiteral("\x1a\x05\x00\x00"); + rigCaps.hasVFOMS = true; + rigCaps.hasVFOAB = false; break; case model9100: rigCaps.modelName = QString("IC-9100"); @@ -3952,6 +4104,7 @@ void rigCommander::determineRigCaps() rigCaps.hasATU = true; rigCaps.hasDV = true; rigCaps.hasTBPF = true; + rigCaps.hasRepeaterModes = true; rigCaps.preamps.push_back('\x01'); rigCaps.preamps.push_back('\x02'); rigCaps.attenuators.insert(rigCaps.attenuators.end(),{ '\x20' }); @@ -3966,6 +4119,8 @@ void rigCommander::determineRigCaps() rigCaps.bsr[bandGen] = 0x14; rigCaps.modes = commonModes; rigCaps.modes.insert(rigCaps.modes.end(), {createMode(modeDV, 0x17, "DV")}); + rigCaps.hasVFOMS = true; + rigCaps.hasVFOAB = true; break; default: rigCaps.modelName = QString("IC-0x%1").arg(rigCaps.modelID, 2, 16); @@ -3988,6 +4143,8 @@ void rigCommander::determineRigCaps() rigCaps.bands.insert(rigCaps.bands.end(), {bandDef23cm, bandDef4m, bandDef630m, bandDef2200m, bandDefGen}); rigCaps.modes = commonModes; rigCaps.transceiveCommand = QByteArrayLiteral("\x1a\x05\x00\x00"); + rigCaps.hasVFOMS = true; + rigCaps.hasVFOAB = true; qInfo(logRig()) << "Found unknown rig: 0x" << QString("%1").arg(rigCaps.modelID, 2, 16); break; } @@ -4303,6 +4460,29 @@ void rigCommander::parseFrequency() emit haveFrequency(freq); } +freqt rigCommander::parseFrequencyRptOffset(QByteArray data) +{ + // VHF 600 KHz: + // DATA: 0c 00 60 00 fd + // INDEX: 00 01 02 03 04 + + // UHF 5 MHz: + // DATA: 0c 00 00 05 fd + // INDEX: 00 01 02 03 04 + + freqt f; + f.Hz = 0; + + f.Hz += (data[3] & 0x0f) * 1E6; // 1 MHz + f.Hz += ((data[3] & 0xf0) >> 4) * 1E6 * 10; // 10 MHz + f.Hz += (data[2] & 0x0f) * 10E3; // 10 KHz + f.Hz += ((data[2] & 0xf0) >> 4) * 100E3; // 100 KHz + f.Hz += (data[1] & 0x0f) * 100; // 100 Hz + f.Hz += ((data[1] & 0xf0) >> 4) * 1000; // 1 KHz + + return f; +} + freqt rigCommander::parseFrequency(QByteArray data, unsigned char lastPosition) { // process payloadIn, which is stripped. diff --git a/rigcommander.h b/rigcommander.h index 5dba56a..bf07110 100644 --- a/rigcommander.h +++ b/rigcommander.h @@ -71,6 +71,10 @@ public slots: // Frequency, Mode, BSR: void setFrequency(unsigned char vfo, freqt freq); void getFrequency(); + void selectVFO(vfo_t vfo); + void equalizeVFOsAB(); + void equalizeVFOsMS(); + void exchangeVFOs(); void setMode(unsigned char mode, unsigned char modeFilter); void setMode(mode_info); void getMode(); @@ -134,14 +138,19 @@ public slots: void setDuplexMode(duplexMode dm); void getDuplexMode(); void getTransmitFrequency(); - void setTone(quint16 tone); - void setTSQL(quint16 tsql); + void setTone(rptrTone_t t); + void setTSQL(rptrTone_t t); + void setTone(quint16 t); + void setTSQL(quint16 t); void getTSQL(); void getTone(); void setDTCS(quint16 dcscode, bool tinv, bool rinv); void getDTCS(); void setRptAccessMode(rptAccessTxRx ratr); + void setRptAccessMode(rptrAccessData_t ratr); void getRptAccessMode(); + void setRptDuplexOffset(freqt f); + void getRptDuplexOffset(); // Get Levels: void getLevels(); // all supported levels @@ -305,6 +314,7 @@ signals: void haveTone(quint16 tone); void haveTSQL(quint16 tsql); void haveDTCS(quint16 dcscode, bool tinv, bool rinv); + void haveRptOffsetFrequency(freqt f); // Levels: void haveRfGain(unsigned char level); @@ -374,6 +384,8 @@ private: QByteArray bcdEncodeInt(unsigned int); void parseFrequency(); freqt parseFrequency(QByteArray data, unsigned char lastPosition); // supply index where Mhz is found + freqt parseFrequencyRptOffset(QByteArray data); + QByteArray makeFreqPayloadRptOffset(freqt freq); QByteArray makeFreqPayload(double frequency); QByteArray makeFreqPayload(freqt freq); QByteArray encodeTone(quint16 tone, bool tinv, bool rinv); diff --git a/rigidentities.h b/rigidentities.h index 3ea80ea..dbd6e3f 100644 --- a/rigidentities.h +++ b/rigidentities.h @@ -134,6 +134,7 @@ struct rigCapabilities { bool hasCTCSS; bool hasDTCS; + bool hasRepeaterModes = false; bool hasTransmit; bool hasPTTCommand; @@ -147,6 +148,10 @@ struct rigCapabilities { bool hasRXAntenna; + bool hasSpecifyMainSubCmd = false; // 0x29 + bool hasVFOMS = false; + bool hasVFOAB = true; // 0x07 [00||01] + std::vector attenuators; std::vector preamps; std::vector antennas; diff --git a/udpbase.h b/udpbase.h index e5c67cf..24ce4be 100644 --- a/udpbase.h +++ b/udpbase.h @@ -35,6 +35,7 @@ struct udpPreferences { QString password; QString clientName; quint8 waterfallFormat; + bool halfDuplex; }; struct networkAudioLevels { diff --git a/usbcontroller.cpp b/usbcontroller.cpp index 7989bc1..95c75dc 100644 --- a/usbcontroller.cpp +++ b/usbcontroller.cpp @@ -246,7 +246,7 @@ void usbController::run() void usbController::runTimer() { int res=1; - int changeVFO=0; + while (res > 0) { QByteArray data(HIDDATALENGTH, 0x0); res = hid_read(handle, (unsigned char*)data.data(), HIDDATALENGTH); @@ -307,14 +307,12 @@ void usbController::runTimer() { - // Step through all buttons and emit ones that have been pressed. for (unsigned char i = 0; i < 16; i++) { - + for (BUTTON* but = buttonList->begin(); but != buttonList->end(); but++) { if (but->dev == usbDevice && but->num == i) { - if ((tempButtons >> i & 1) && !(buttons >> i & 1) && but->onCommand->index > 0) { qInfo(logUsbControl()) << "On Button event:" << but->onCommand->text; @@ -343,9 +341,9 @@ void usbController::runTimer() // Buttons - BUTTON* butptt; - BUTTON* butf1; - BUTTON* butf2; + BUTTON* butptt = Q_NULLPTR; + BUTTON* butf1 = Q_NULLPTR; + BUTTON* butf2 = Q_NULLPTR;; for (BUTTON* but = buttonList->begin(); but != buttonList->end(); but++) { if (but->dev == usbDevice) { @@ -370,7 +368,7 @@ void usbController::runTimer() lastData = data; } - if (((unsigned char)data[5] == 0x06) && ((unsigned char)lastData[5] != 0x06)) + if (butptt != Q_NULLPTR && ((unsigned char)data[5] == 0x06) && ((unsigned char)lastData[5] != 0x06)) { // TRANSMIT key down only (no other keys down) qDebug(logUsbControl()) << "PTT key down"; @@ -378,7 +376,7 @@ void usbController::runTimer() emit button(butptt->onCommand); } - else if (((unsigned char)data[5] != 0x06) && ((unsigned char)lastData[5] == 0x06)) + else if (butptt != Q_NULLPTR && ((unsigned char)data[5] != 0x06) && ((unsigned char)lastData[5] == 0x06)) { // TRANSMIT key up only (no other keys down) //emit button(false, 6); @@ -386,7 +384,7 @@ void usbController::runTimer() qInfo(logUsbControl()) << "Off Button event:" << butptt->offCommand->text; emit button(butptt->offCommand); } - else if (((unsigned char)data[5] == 0x03) && ((unsigned char)lastData[5] != 0x03)) + else if (butf2 != Q_NULLPTR && ((unsigned char)data[5] == 0x03) && ((unsigned char)lastData[5] != 0x03)) { // F-2 key up only (no other keys down) //emit button(true, 7); @@ -394,7 +392,7 @@ void usbController::runTimer() qInfo(logUsbControl()) << "On Button event:" << butf2->onCommand->text; emit button(butf2->onCommand); } - else if (((unsigned char)data[5] != 0x03) && ((unsigned char)lastData[5] == 0x03)) + else if (butf2 != Q_NULLPTR && ((unsigned char)data[5] != 0x03) && ((unsigned char)lastData[5] == 0x03)) { // F-2 key down only (no other keys down) //emit button(false, 7); @@ -402,7 +400,7 @@ void usbController::runTimer() qInfo(logUsbControl()) << "Off Button event:" << butf2->offCommand->text; emit button(butf2->offCommand); } - else if (((unsigned char)data[5] == 0x05) && ((unsigned char)lastData[5] != 0x05)) + else if (butf1 != Q_NULLPTR && ((unsigned char)data[5] == 0x05) && ((unsigned char)lastData[5] != 0x05)) { // F-1 key up only (no other keys down) //emit button(true, 5); @@ -410,7 +408,7 @@ void usbController::runTimer() qInfo(logUsbControl()) << "On Button event:" << butf1->onCommand->text; emit button(butf1->onCommand); } - else if (((unsigned char)data[5] != 0x05) && ((unsigned char)lastData[5] == 0x05)) + else if (butf1 != Q_NULLPTR && ((unsigned char)data[5] != 0x05) && ((unsigned char)lastData[5] == 0x05)) { // F-1 key down only (no other keys down) //emit button(false, 5); @@ -421,33 +419,20 @@ void usbController::runTimer() if ((unsigned char)data[5] == 0x07) { - // TODO: change of frequency should be multiplied by data[1] or data[4] - // data[1] max value depend on rotation speed I was able to detect was 150 decimal - // data[4] can have 3 values 0 1 or 2 it depends on rotation speed - if ((unsigned char)data[4] > 0x00) { - changeVFO = data[4] * data[1]; - } else { - changeVFO = data[1]; - } if ((unsigned char)data[3] == 0x01) { - //qDebug(logUsbControl()) << "Frequency UP"; - //emit jogPlus(); - jogCounter = jogCounter + changeVFO; + jogCounter = jogCounter + data[1]; } else if ((unsigned char)data[3] == 0x02) { - //qDebug(logUsbControl()) << "Frequency DOWN"; - //emit jogMinus(); - jogCounter = jogCounter - changeVFO; - jogCounter--; + jogCounter = jogCounter - data[1]; } } lastData = data; } - if (lastusbController.msecsTo(QTime::currentTime()) >= 200 || lastusbController > QTime::currentTime()) + if (lastusbController.msecsTo(QTime::currentTime()) >= 100 || lastusbController > QTime::currentTime()) { if (usbDevice == shuttleXpress || usbDevice == shuttlePro2) { diff --git a/usbcontroller.h b/usbcontroller.h index 80f0c68..04af2cf 100644 --- a/usbcontroller.h +++ b/usbcontroller.h @@ -37,25 +37,22 @@ using namespace std; #define HIDDATALENGTH 64 #define MAX_STR 255 -enum commandType {normalCommand,bandswitch,modeswitch}; - struct COMMAND { COMMAND() {} COMMAND(int index, QString text, int command, char suffix) : - index(index), text(text), command(command), suffix(suffix), type(normalCommand){} - COMMAND(int index, QString text, int command, bandType band) : - index(index), text(text), command(command), band(band), type(bandswitch) {} + index(index), text(text), command(command), suffix(suffix) {} + COMMAND(int index, QString text, int command, availableBands band) : + index(index), text(text), command(command), band(band) {} COMMAND(int index, QString text, int command, mode_kind mode) : - index(index), text(text), command(command), mode(mode), type(modeswitch) {} + index(index), text(text), command(command), mode(mode) {} - int index; + int index=0; QString text; - int command; - unsigned char suffix; - bandType band; - mode_kind mode; - commandType type; + int command=0; + unsigned char suffix=0x0; + availableBands band=bandGen; + mode_kind mode=modeLSB; }; struct BUTTON { diff --git a/wfmain.cpp b/wfmain.cpp index 4570338..cef43f0 100644 --- a/wfmain.cpp +++ b/wfmain.cpp @@ -57,10 +57,13 @@ wfmain::wfmain(const QString settingsFile, const QString logFile, bool debugMode qRegisterMetaType(); qRegisterMetaType(); qRegisterMetaType(); + qRegisterMetaType(); qRegisterMetaType(); qRegisterMetaType(); qRegisterMetaType(); qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType(); qRegisterMetaType(); qRegisterMetaType(); qRegisterMetaType(); @@ -164,13 +167,12 @@ wfmain::wfmain(const QString settingsFile, const QString logFile, bool debugMode amTransmitting = false; -#if defined(USB_CONTROLLER) - // Setup USB Controller - setupUsbControllerDevice(); - emit sendUsbControllerCommands(&usbCommands); - emit sendUsbControllerButtons(&usbButtons); -#else +#if !defined(USB_CONTROLLER) + ui->enableUsbChk->setVisible(false); ui->usbControllerBtn->setVisible(false); + ui->usbButtonsResetBtn->setVisible(false); + ui->usbCommandsResetBtn->setVisible(false); + ui->usbResetLbl->setVisible(false); #endif connect(ui->txPowerSlider, &QSlider::sliderMoved, @@ -343,6 +345,11 @@ void wfmain::rigConnections() connect(this, SIGNAL(setPTT(bool)), rig, SLOT(setPTT(bool))); connect(this, SIGNAL(getPTT()), rig, SLOT(getPTT())); + connect(this, SIGNAL(selectVFO(vfo_t)), rig, SLOT(selectVFO(vfo_t))); + connect(this, SIGNAL(sendVFOSwap()), rig, SLOT(exchangeVFOs())); + connect(this, SIGNAL(sendVFOEqualAB()), rig, SLOT(equalizeVFOsAB())); + connect(this, SIGNAL(sendVFOEqualMS()), rig, SLOT(equalizeVFOsMS())); + connect(this, SIGNAL(sendCW(QString)), rig, SLOT(sendCW(QString))); connect(this, SIGNAL(stopCW()), rig, SLOT(sendStopCW())); connect(this, SIGNAL(setKeySpeed(unsigned char)), rig, SLOT(setKeySpeed(unsigned char))); @@ -376,28 +383,65 @@ void wfmain::rigConnections() connect(rig, SIGNAL(havePassband(quint16)), this, SLOT(receivePassband(quint16))); connect(rig, SIGNAL(haveCwPitch(unsigned char)), this, SLOT(receiveCwPitch(unsigned char))); + // Repeater, duplex, and split: connect(rpt, SIGNAL(getDuplexMode()), rig, SLOT(getDuplexMode())); connect(rpt, SIGNAL(setDuplexMode(duplexMode)), rig, SLOT(setDuplexMode(duplexMode))); connect(rig, SIGNAL(haveDuplexMode(duplexMode)), rpt, SLOT(receiveDuplexMode(duplexMode))); + connect(this, SIGNAL(getRptDuplexOffset()), rig, SLOT(getRptDuplexOffset())); + connect(rig, SIGNAL(haveRptOffsetFrequency(freqt)), rpt, SLOT(handleRptOffsetFrequency(freqt))); connect(rpt, SIGNAL(getTone()), rig, SLOT(getTone())); connect(rpt, SIGNAL(getTSQL()), rig, SLOT(getTSQL())); connect(rpt, SIGNAL(getDTCS()), rig, SLOT(getDTCS())); - connect(rpt, SIGNAL(setTone(quint16)), rig, SLOT(setTone(quint16))); - connect(rpt, SIGNAL(setTSQL(quint16)), rig, SLOT(setTSQL(quint16))); + + connect(this->rpt, &repeaterSetup::setTone, + [=](const rptrTone_t &t) { issueCmd(cmdSetTone, t);}); + + connect(this->rpt, &repeaterSetup::setTSQL, + [=](const rptrTone_t &t) { issueCmd(cmdSetTSQL, t);}); + connect(rpt, SIGNAL(setDTCS(quint16,bool,bool)), rig, SLOT(setDTCS(quint16,bool,bool))); connect(rpt, SIGNAL(getRptAccessMode()), rig, SLOT(getRptAccessMode())); - connect(rpt, SIGNAL(setRptAccessMode(rptAccessTxRx)), rig, SLOT(setRptAccessMode(rptAccessTxRx))); + + //connect(rpt, SIGNAL(setRptAccessMode(rptAccessTxRx)), rig, SLOT(setRptAccessMode(rptAccessTxRx))); + + connect(this->rpt, &repeaterSetup::setRptAccessMode, + [=](const rptrAccessData_t &rd) { issueCmd(cmdSetRptAccessMode, rd);}); + connect(this, SIGNAL(setRepeaterAccessMode(rptrAccessData_t)), rig, SLOT(setRptAccessMode(rptrAccessData_t))); + connect(this, SIGNAL(setTone(rptrTone_t)), rig, SLOT(setTone(rptrTone_t))); + 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)), rpt, SLOT(handleRptAccessMode(rptAccessTxRx))); + + connect(this->rig, &rigCommander::haveDuplexMode, + [=](const duplexMode &dm) { + if(dm==dmSplitOn) + this->splitModeEnabled = true; + else + this->splitModeEnabled = false; + }); + connect(this->rpt, &repeaterSetup::setTransmitFrequency, [=](const freqt &transmitFreq) { issueCmd(cmdSetFreq, transmitFreq);}); - connect(this->rpt, &repeaterSetup::setTransmitMode, [=](const mode_info &transmitMode) { issueCmd(cmdSetMode, transmitMode);}); + connect(this->rpt, &repeaterSetup::selectVFO, + [=](const vfo_t &v) { issueCmd(cmdSelVFO, v);}); + connect(this->rpt, &repeaterSetup::equalizeVFOsAB, + [=]() { issueDelayedCommand(cmdVFOEqualAB);}); + connect(this->rpt, &repeaterSetup::equalizeVFOsMS, + [=]() { issueDelayedCommand(cmdVFOEqualMS);}); + connect(this->rpt, &repeaterSetup::swapVFOs, + [=]() { issueDelayedCommand(cmdVFOSwap);}); + connect(this->rpt, &repeaterSetup::setRptDuplexOffset, + [=](const freqt &fOffset) { issueCmd(cmdSetRptDuplexOffset, fOffset);}); + connect(this->rpt, &repeaterSetup::getRptDuplexOffset, + [=]() { issueDelayedCommand(cmdGetRptDuplexOffset);}); + connect(this, SIGNAL(setRptDuplexOffset(freqt)), rig, SLOT(setRptDuplexOffset(freqt))); connect(this, SIGNAL(getDuplexMode()), rig, SLOT(getDuplexMode())); + connect(this, SIGNAL(getPassband()), rig, SLOT(getPassband())); connect(this, SIGNAL(setPassband(quint16)), rig, SLOT(setPassband(quint16))); connect(this, SIGNAL(getCwPitch()), rig, SLOT(getCwPitch())); @@ -406,8 +450,6 @@ void wfmain::rigConnections() connect(this, SIGNAL(getTone()), rig, SLOT(getTone())); connect(this, SIGNAL(getTSQL()), rig, SLOT(getTSQL())); connect(this, SIGNAL(getRptAccessMode()), rig, SLOT(getRptAccessMode())); - //connect(this, SIGNAL(setDuplexMode(duplexMode)), rig, SLOT(setDuplexMode(duplexMode))); - //connect(rig, SIGNAL(haveDuplexMode(duplexMode)), this, SLOT(receiveDuplexMode(duplexMode))); connect(this, SIGNAL(getModInput(bool)), rig, SLOT(getModInput(bool))); connect(rig, SIGNAL(haveModInput(rigInput,bool)), this, SLOT(receiveModInput(rigInput, bool))); @@ -1010,6 +1052,7 @@ void wfmain::setupMainUI() pttLed = new QLedLabel(this); ui->statusBar->addPermanentWidget(pttLed); pttLed->setState(QLedLabel::State::StateOk); + pttLed->setToolTip("Receiving"); connectedLed = new QLedLabel(this); ui->statusBar->addPermanentWidget(connectedLed); @@ -1652,20 +1695,108 @@ void wfmain::doShuttle(bool up, unsigned char level) void wfmain::buttonControl(const COMMAND* cmd) { - - if (cmd->type==normalCommand) { - //qDebug() << "Other command"; - issueCmdUniquePriority((cmds)cmd->command, cmd->suffix); - } - else if (cmd->type == bandswitch) - { - //qDebug() << "Bandswitch"; - //issueCmd((cmds)cmd->command, cmd->band); // Needs fixing! - } - else if (cmd->type == modeswitch) - { - //qDebug() << "Bandswitch"; + switch (cmd->command) { + case cmdGetBandStackReg: + issueCmd((cmds)cmd->command, cmd->band); + break; + case cmdSetBandUp: + for (size_t i = 0; i < rigCaps.bands.size(); i++) { + if (rigCaps.bands[i].band == lastRequestedBand) + { + if (i>0) { + issueCmd(cmdGetBandStackReg, rigCaps.bands[i - 1].band); + } + else { + issueCmd(cmdGetBandStackReg, rigCaps.bands[rigCaps.bands.size() - 1].band); + } + } + } + break; + case cmdSetBandDown: + for (size_t i = 0; i < rigCaps.bands.size(); i++) { + if (rigCaps.bands[i].band == lastRequestedBand) + { + if (i + 1 < rigCaps.bands.size()) { + issueCmd(cmdGetBandStackReg, rigCaps.bands[i + 1].band); + } + else { + issueCmd(cmdGetBandStackReg, rigCaps.bands[0].band); + } + } + } + break; + case cmdSetMode: changeMode(cmd->mode); + break; + case cmdSetModeUp: + for (size_t i = 0; i < rigCaps.modes.size(); i++) { + if (rigCaps.modes[i].mk == currentModeInfo.mk) + { + if (i + 1 < rigCaps.modes.size()) { + changeMode(rigCaps.modes[i + 1].mk); + } + else { + changeMode(rigCaps.modes[0].mk); + } + } + } + break; + case cmdSetModeDown: + for (size_t i = 0; i < rigCaps.modes.size(); i++) { + if (rigCaps.modes[i].mk == currentModeInfo.mk) + { + if (i>0) { + changeMode(rigCaps.modes[i - 1].mk); + } + else { + changeMode(rigCaps.modes[rigCaps.modes.size()-1].mk); + } + } + } + break; + case cmdSetStepUp: + if (ui->tuningStepCombo->currentIndex() < ui->tuningStepCombo->count()-1) + { + ui->tuningStepCombo->setCurrentIndex(ui->tuningStepCombo->currentIndex() + 1); + } + else + { + ui->tuningStepCombo->setCurrentIndex(0); + } + break; + case cmdSetStepDown: + if (ui->tuningStepCombo->currentIndex() > 0) + { + ui->tuningStepCombo->setCurrentIndex(ui->tuningStepCombo->currentIndex() - 1); + } + else + { + ui->tuningStepCombo->setCurrentIndex(ui->tuningStepCombo->count() - 1); + } + break; + case cmdSetSpanUp: + if (ui->scopeBWCombo->currentIndex() < ui->scopeBWCombo->count()-1) + { + ui->scopeBWCombo->setCurrentIndex(ui->scopeBWCombo->currentIndex() + 1); + } + else + { + ui->scopeBWCombo->setCurrentIndex(0); + } + break; + case cmdSetSpanDown: + if (ui->scopeBWCombo->currentIndex() > 0) + { + ui->scopeBWCombo->setCurrentIndex(ui->scopeBWCombo->currentIndex() - 1); + } + else + { + ui->scopeBWCombo->setCurrentIndex(ui->scopeBWCombo->count() - 1); + } + break; + default: + issueCmdUniquePriority((cmds)cmd->command, cmd->suffix); + break; } } @@ -1685,12 +1816,11 @@ void wfmain::changeFrequency(int value) { if (freqLock) return; freqt f; - f.Hz = roundFrequencyWithStep(freq.Hz, value, tsKnobHz); - + f.Hz = roundFrequencyWithStep(freq.Hz, value, tsWfScrollHz); f.MHzDouble = f.Hz / (double)1E6; - setUIFreq(); + freq = f; issueCmdUniquePriority(cmdSetFreq, f); - issueDelayedCommandUnique(cmdGetFreq); + ui->freqLabel->setText(QString("%1").arg(f.MHzDouble, 0, 'f')); } void wfmain::setDefPrefs() @@ -1726,6 +1856,7 @@ void wfmain::setDefPrefs() defPrefs.tcpPort = 0; defPrefs.waterfallFormat = 0; defPrefs.audioSystem = qtAudio; + defPrefs.enableUSBControllers = false; udpDefPrefs.ipAddress = QString(""); udpDefPrefs.controlLANPort = 50001; @@ -1746,7 +1877,7 @@ void wfmain::loadSettings() settings->beginGroup("Program"); QString priorVersionString = settings->value("version", "unset").toString(); float priorVersionFloat = priorVersionString.toFloat(); - if(currentVersionString != priorVersionString) + if (currentVersionString != priorVersionString) { qWarning(logSystem()) << "Settings previously saved under version " << priorVersionString << ", you should review your settings and press SaveSettings."; } @@ -2045,6 +2176,8 @@ void wfmain::loadSettings() udpPrefs.clientName = settings->value("ClientName", udpDefPrefs.clientName).toString(); + udpPrefs.halfDuplex = settings->value("HalfDuplex", udpDefPrefs.halfDuplex).toBool(); + settings->endGroup(); settings->beginGroup("Server"); @@ -2264,79 +2397,30 @@ void wfmain::loadSettings() settings->endGroup(); #if defined (USB_CONTROLLER) - /* Load USB buttons*/ settings->beginGroup("USB"); + /* Load USB buttons*/ + prefs.enableUSBControllers = settings->value("EnableUSBControllers", defPrefs.enableUSBControllers).toBool(); + ui->enableUsbChk->blockSignals(true); + ui->enableUsbChk->setChecked(prefs.enableUSBControllers); + ui->enableUsbChk->blockSignals(false); + ui->usbControllerBtn->setEnabled(prefs.enableUSBControllers); + ui->usbButtonsResetBtn->setEnabled(prefs.enableUSBControllers); + ui->usbCommandsResetBtn->setEnabled(prefs.enableUSBControllers); + ui->usbResetLbl->setVisible(prefs.enableUSBControllers); + + if (prefs.enableUSBControllers) { + // Setup USB Controller + setupUsbControllerDevice(); + emit sendUsbControllerCommands(&usbCommands); + emit sendUsbControllerButtons(&usbButtons); + } + int numCommands = settings->beginReadArray("Commands"); - if (numCommands == 0) { + // This is the last time the commands were changed (v1.58) + if (numCommands == 0 || priorVersionFloat < 1.58) { settings->endArray(); // We have no buttons so create defaults - usbCommands.clear(); - usbCommands.append(COMMAND(0, "None", cmdNone, 0x0)); - usbCommands.append(COMMAND(1, "PTT On", cmdSetPTT, 0x1)); - usbCommands.append(COMMAND(2, "PTT Off", cmdSetPTT, 0x0)); - usbCommands.append(COMMAND(3, "PTT Toggle", cmdPTTToggle, 0x0)); - usbCommands.append(COMMAND(4, "Tune", cmdNone, 0x0)); - usbCommands.append(COMMAND(5, "Step+", cmdNone, 0x0)); - usbCommands.append(COMMAND(6, "Step-", cmdNone, 0x0)); - usbCommands.append(COMMAND(7, "Mode+", cmdNone, 0x0)); - usbCommands.append(COMMAND(8, "Mode-", cmdNone, 0x0)); - usbCommands.append(COMMAND(9, "Band+", cmdNone, 0x0)); - usbCommands.append(COMMAND(10, "Band-", cmdNone, 0x0)); - usbCommands.append(COMMAND(11, "NR", cmdNone, 0x0)); - usbCommands.append(COMMAND(12, "NB", cmdNone, 0x0)); - usbCommands.append(COMMAND(13, "AGC", cmdNone, 0x0)); - usbCommands.append(COMMAND(14, "NB", cmdNone, 0x0)); - usbCommands.append(COMMAND(15, "23cm", cmdGetBandStackReg, band23cm)); - usbCommands.append(COMMAND(16, "70cm", cmdGetBandStackReg, band70cm)); - usbCommands.append(COMMAND(17, "2m", cmdGetBandStackReg, band2m)); - usbCommands.append(COMMAND(18, "AIR", cmdGetBandStackReg, bandAir)); - usbCommands.append(COMMAND(19, "WFM", cmdGetBandStackReg, bandWFM)); - usbCommands.append(COMMAND(20, "4m", cmdGetBandStackReg, band4m)); - usbCommands.append(COMMAND(21, "6m", cmdGetBandStackReg, band6m)); - usbCommands.append(COMMAND(22, "10m", cmdGetBandStackReg, band10m)); - usbCommands.append(COMMAND(23, "12m", cmdGetBandStackReg, band12m)); - usbCommands.append(COMMAND(24, "15m", cmdGetBandStackReg, band15m)); - usbCommands.append(COMMAND(25, "17m", cmdGetBandStackReg, band17m)); - usbCommands.append(COMMAND(26, "20m", cmdGetBandStackReg, band20m)); - usbCommands.append(COMMAND(27, "30m", cmdGetBandStackReg, band30m)); - usbCommands.append(COMMAND(28, "40m", cmdGetBandStackReg, band40m)); - usbCommands.append(COMMAND(29, "60m", cmdGetBandStackReg, band60m)); - usbCommands.append(COMMAND(30, "80m", cmdGetBandStackReg, band80m)); - usbCommands.append(COMMAND(31, "160m", cmdGetBandStackReg, band160m)); - usbCommands.append(COMMAND(32, "630m", cmdGetBandStackReg, band630m)); - usbCommands.append(COMMAND(33, "2200m", cmdGetBandStackReg, band2200m)); - usbCommands.append(COMMAND(34, "GEN", cmdGetBandStackReg, bandGen)); - usbCommands.append(COMMAND(35, "Mode LSB", cmdSetMode, modeLSB)); - usbCommands.append(COMMAND(36, "Mode USB", cmdSetMode, modeUSB)); - usbCommands.append(COMMAND(37, "Mode CW", cmdSetMode, modeCW)); - usbCommands.append(COMMAND(38, "Mode FM", cmdSetMode, modeFM)); - - - /* - modeLSB = 0x00, - modeUSB = 0x01, - modeAM = 0x02, - modeCW = 0x03, - modeRTTY = 0x04, - modeFM = 0x05, - modeCW_R = 0x07, - modeRTTY_R = 0x08, - modeLSB_D = 0x80, - modeUSB_D = 0x81, - modeDV = 0x17, - modeDD = 0x27, - modeWFM, - modeS_AMD, - modeS_AML, - modeS_AMU, - modeP25, - modedPMR, - modeNXDN_VN, - modeNXDN_N, - modeDCR, - modePSK, - modePSK_R - */ + resetUsbCommands(); } else { for (int nc = 0; nc < numCommands; nc++) @@ -2346,66 +2430,20 @@ void wfmain::loadSettings() comm.index = settings->value("Num", 0).toInt(); comm.text = settings->value("Text", "").toString(); comm.command = settings->value("Command", 0).toInt(); - //comm.band = (bandType)settings->value("Band", 0).toInt(); // Needs fixing! + comm.band = (availableBands)settings->value("Band", 0).toInt(); + comm.mode = (mode_kind)settings->value("Mode", 0).toInt(); + comm.suffix = (unsigned char)settings->value("Suffix", 0).toInt(); usbCommands.append(comm); } settings->endArray(); } int numButtons = settings->beginReadArray("Buttons"); - if (numButtons == 0) { + // This is the last time the buttons were changed, (v1.58) + if (numButtons == 0 || priorVersionFloat < 1.58) { settings->endArray(); // We have no buttons so create defaults - usbButtons.clear(); - - // ShuttleXpress - usbButtons.append(BUTTON(1, 0, QRect(60, 66, 40, 30), Qt::red, &usbCommands[0], &usbCommands[0])); - usbButtons.append(BUTTON(1, 1, QRect(114, 50, 40, 30), Qt::red, &usbCommands[0], &usbCommands[0])); - usbButtons.append(BUTTON(1, 2, QRect(169, 47, 40, 30), Qt::red, &usbCommands[0], &usbCommands[0])); - usbButtons.append(BUTTON(1, 3, QRect(225, 59, 40, 30), Qt::red, &usbCommands[0], &usbCommands[0])); - usbButtons.append(BUTTON(1, 4, QRect(41, 132, 40, 30), Qt::red, &usbCommands[0], &usbCommands[0])); - - // ShuttlePro2 - usbButtons.append(BUTTON(2, 0, QRect(60, 66, 40, 30), Qt::red, &usbCommands[0], &usbCommands[0])); - usbButtons.append(BUTTON(2, 1, QRect(114, 50, 40, 30), Qt::red, &usbCommands[0], &usbCommands[0])); - usbButtons.append(BUTTON(2, 2, QRect(169, 47, 40, 30), Qt::red, &usbCommands[0], &usbCommands[0])); - usbButtons.append(BUTTON(2, 3, QRect(225, 59, 40, 30), Qt::red, &usbCommands[0], &usbCommands[0])); - usbButtons.append(BUTTON(2, 4, QRect(41, 132, 40, 30), Qt::red, &usbCommands[0], &usbCommands[0])); - usbButtons.append(BUTTON(2, 5, QRect(91, 105, 40, 30), Qt::red, &usbCommands[0], &usbCommands[0])); - usbButtons.append(BUTTON(2, 6, QRect(144, 93, 40, 30), Qt::red, &usbCommands[0], &usbCommands[0])); - usbButtons.append(BUTTON(2, 7, QRect(204, 99, 40, 30), Qt::red, &usbCommands[0], &usbCommands[0])); - usbButtons.append(BUTTON(2, 8, QRect(253, 124, 40, 30), Qt::red, &usbCommands[0], &usbCommands[0])); - usbButtons.append(BUTTON(2, 9, QRect(50, 270, 70, 55), Qt::red, &usbCommands[0], &usbCommands[0])); - usbButtons.append(BUTTON(2, 10, QRect(210, 270, 70, 55), Qt::red, &usbCommands[0], &usbCommands[0])); - usbButtons.append(BUTTON(2, 11, QRect(50, 335, 70, 55), Qt::red, &usbCommands[0], &usbCommands[0])); - usbButtons.append(BUTTON(2, 12, QRect(210, 335, 70, 55), Qt::red, &usbCommands[0], &usbCommands[0])); - usbButtons.append(BUTTON(2, 13, QRect(30, 195, 25, 80), Qt::red, &usbCommands[0], &usbCommands[0])); - usbButtons.append(BUTTON(2, 14, QRect(280, 195, 25, 80), Qt::red, &usbCommands[0], &usbCommands[0])); - - // RC28 - usbButtons.append(BUTTON(3, 0, QRect(52, 445, 238, 64), Qt::red, &usbCommands[0], &usbCommands[0])); - usbButtons.append(BUTTON(3, 1, QRect(52, 373, 98, 46), Qt::red, &usbCommands[0], &usbCommands[0])); - usbButtons.append(BUTTON(3, 2, QRect(193, 373, 98, 46), Qt::red, &usbCommands[0], &usbCommands[0])); - - // Xbox Gamepad - usbButtons.append(BUTTON(4, "UP", QRect(256, 229, 50, 50), Qt::red, &usbCommands[0], &usbCommands[0])); - usbButtons.append(BUTTON(4, "DOWN", QRect(256, 316, 50, 50), Qt::red, &usbCommands[0], &usbCommands[0])); - usbButtons.append(BUTTON(4, "LEFT", QRect(203, 273, 50, 50), Qt::red, &usbCommands[0], &usbCommands[0])); - usbButtons.append(BUTTON(4, "RIGHT", QRect(303, 273, 50, 50), Qt::red, &usbCommands[0], &usbCommands[0])); - usbButtons.append(BUTTON(4, "SELECT", QRect(302, 160, 40, 40), Qt::red, &usbCommands[0], &usbCommands[0])); - usbButtons.append(BUTTON(4, "START", QRect(412, 163, 40, 40), Qt::red, &usbCommands[0], &usbCommands[0])); - usbButtons.append(BUTTON(4, "Y", QRect(534, 104, 53, 53), Qt::red, &usbCommands[0], &usbCommands[0])); - usbButtons.append(BUTTON(4, "X", QRect(485, 152, 53, 53), Qt::red, &usbCommands[0], &usbCommands[0])); - usbButtons.append(BUTTON(4, "B", QRect(590, 152, 53, 53), Qt::red, &usbCommands[0], &usbCommands[0])); - usbButtons.append(BUTTON(4, "A", QRect(534, 202, 53, 53), Qt::red, &usbCommands[0], &usbCommands[0])); - usbButtons.append(BUTTON(4, "L1", QRect(123, 40, 70, 45), Qt::red, &usbCommands[0], &usbCommands[0])); - usbButtons.append(BUTTON(4, "R1", QRect(562, 40, 70, 45), Qt::red, &usbCommands[0], &usbCommands[0])); - usbButtons.append(BUTTON(4, "LEFTX", QRect(143, 119, 83, 35), Qt::red, &usbCommands[0], &usbCommands[0])); - usbButtons.append(BUTTON(4, "LEFTY", QRect(162, 132, 50, 57), Qt::red, &usbCommands[0], &usbCommands[0])); - usbButtons.append(BUTTON(4, "RIGHTX", QRect(430, 298, 83, 35), Qt::red, &usbCommands[0], &usbCommands[0])); - usbButtons.append(BUTTON(4, "RIGHTY", QRect(453, 233, 50, 57), Qt::red, &usbCommands[0], &usbCommands[0])); - //usbButtons.append(BUTTON(4, 14, QRect(280, 195, 25, 80), Qt::red, &usbCommands[0], &usbCommands[0])); - + resetUsbButtons(); } else { usbButtons.clear(); @@ -2705,6 +2743,7 @@ void wfmain::saveSettings() settings->setValue("ResampleQuality", rxSetup.resampleQuality); settings->setValue("ClientName", udpPrefs.clientName); settings->setValue("WaterfallFormat", prefs.waterfallFormat); + settings->setValue("HalfDuplex", udpPrefs.halfDuplex); settings->endGroup(); @@ -2837,6 +2876,7 @@ void wfmain::saveSettings() #if defined(USB_CONTROLLER) settings->beginGroup("USB"); // Store USB Controller + settings->setValue("EnableUSBControllers", prefs.enableUSBControllers); settings->beginWriteArray("Buttons"); for (int nb = 0; nb < usbButtons.count(); nb++) @@ -2858,6 +2898,21 @@ void wfmain::saveSettings() settings->endArray(); + settings->beginWriteArray("Commands"); + for (int nc = 0; nc < usbCommands.count(); nc++) + { + settings->setArrayIndex(nc); + + settings->setValue("Num", usbCommands[nc].index); + settings->setValue("Text", usbCommands[nc].text); + settings->setValue("Command", usbCommands[nc].command); + settings->setValue("Band", usbCommands[nc].band); + settings->setValue("Mode", usbCommands[nc].mode); + settings->setValue("Suffix", usbCommands[nc].suffix); + } + + settings->endArray(); + settings->endGroup(); #endif @@ -3608,6 +3663,12 @@ void wfmain::doCmd(commandtype cmddata) emit setMode(m); break; } + case cmdSelVFO: + { + vfo_t v = (*std::static_pointer_cast(data)); + emit selectVFO(v); + break; + } case cmdSetTxPower: { unsigned char txpower = (*std::static_pointer_cast(data)); @@ -3669,6 +3730,30 @@ void wfmain::doCmd(commandtype cmddata) emit setTPBFOuter(outerLevel); break; } + case cmdSetTone: + { + rptrTone_t t = (*std::static_pointer_cast(data)); + emit setTone(t); + break; + } + case cmdSetTSQL: + { + rptrTone_t t = (*std::static_pointer_cast(data)); + emit setTSQL(t); + break; + } + case cmdSetRptAccessMode: + { + rptrAccessData_t rd = (*std::static_pointer_cast(data)); + emit setRepeaterAccessMode(rd); + break; + } + case cmdSetRptDuplexOffset: + { + freqt f = (*std::static_pointer_cast(data)); + emit setRptDuplexOffset(f); + break; + } case cmdSetPTT: { bool pttrequest = (*std::static_pointer_cast(data)); @@ -3751,6 +3836,7 @@ void wfmain::doCmd(commandtype cmddata) case cmdGetBandStackReg: { char band = (*std::static_pointer_cast(data)); + lastRequestedBand = (availableBands)band; bandStkBand = rigCaps.bsr[(availableBands)band]; // 23cm Needs fixing bandStkRegCode = ui->bandStkPopdown->currentIndex() + 1; emit getBandStackReg(bandStkBand, bandStkRegCode); @@ -3797,6 +3883,15 @@ void wfmain::doCmd(cmds cmd) case cmdGetMode: emit getMode(); break; + case cmdVFOSwap: + emit sendVFOSwap(); + break; + case cmdVFOEqualAB: + emit sendVFOEqualAB(); + break; + case cmdVFOEqualMS: + emit sendVFOEqualMS(); + break; case cmdGetDataMode: if(rigCaps.hasDataModes) emit getDataMode(); @@ -3830,6 +3925,9 @@ void wfmain::doCmd(cmds cmd) case cmdGetDuplexMode: emit getDuplexMode(); break; + case cmdGetRptDuplexOffset: + emit getRptDuplexOffset(); + break; case cmdGetPassband: emit getPassband(); break; @@ -4060,9 +4158,15 @@ void wfmain::issueDelayedCommandUnique(cmds cmd) cmddata.cmd = cmd; cmddata.data = NULL; + delayedCmdQue.push_front(cmddata); + delayedCmdQue.erase(std::remove_if(delayedCmdQue.begin() + 1, delayedCmdQue.end(), [cmd](const commandtype& c) { return (c.cmd == cmd); }), delayedCmdQue.end()); + // The following is both expensive and not that great, - // since it does not check if the arguments are the same. - bool found = false; + // since it does not check if the arguments are the same. +/* bool found = false; + + + for(unsigned int i=0; i < delayedCmdQue.size(); i++) { if(delayedCmdQue.at(i).cmd == cmd) @@ -4081,7 +4185,9 @@ void wfmain::issueDelayedCommandUnique(cmds cmd) // { // delayedCmdQue.push_front(cmddata); // } +*/ +// delayedCmdQue.push_front(cmddata); } void wfmain::issueCmd(cmds cmd, mode_info m) @@ -4100,6 +4206,30 @@ void wfmain::issueCmd(cmds cmd, freqt f) delayedCmdQue.push_back(cmddata); } +void wfmain::issueCmd(cmds cmd, vfo_t v) +{ + commandtype cmddata; + cmddata.cmd = cmd; + cmddata.data = std::shared_ptr(new vfo_t(v)); + delayedCmdQue.push_back(cmddata); +} + +void wfmain::issueCmd(cmds cmd, rptrTone_t v) +{ + commandtype cmddata; + cmddata.cmd = cmd; + cmddata.data = std::shared_ptr(new rptrTone_t(v)); + delayedCmdQue.push_back(cmddata); +} + +void wfmain::issueCmd(cmds cmd, rptrAccessData_t rd) +{ + commandtype cmddata; + cmddata.cmd = cmd; + cmddata.data = std::shared_ptr(new rptrAccessData_t(rd)); + delayedCmdQue.push_back(cmddata); +} + void wfmain::issueCmd(cmds cmd, timekind t) { qDebug(logSystem()) << "Issuing timekind command with data: " << t.hours << " hours, " << t.minutes << " minutes, " << t.isMinus << " isMinus"; @@ -4180,7 +4310,9 @@ void wfmain::issueCmdUniquePriority(cmds cmd, bool b) cmddata.cmd = cmd; cmddata.data = std::shared_ptr(new bool(b)); delayedCmdQue.push_front(cmddata); - removeSimilarCommand(cmd); + delayedCmdQue.erase(std::remove_if(delayedCmdQue.begin() + 1, delayedCmdQue.end(), [cmd](const commandtype& c) { return (c.cmd == cmd); }), delayedCmdQue.end()); + + //removeSimilarCommand(cmd); } void wfmain::issueCmdUniquePriority(cmds cmd, unsigned char c) @@ -4189,7 +4321,9 @@ void wfmain::issueCmdUniquePriority(cmds cmd, unsigned char c) cmddata.cmd = cmd; cmddata.data = std::shared_ptr(new unsigned char(c)); delayedCmdQue.push_front(cmddata); - removeSimilarCommand(cmd); + delayedCmdQue.erase(std::remove_if(delayedCmdQue.begin() + 1, delayedCmdQue.end(), [cmd](const commandtype& c) { return (c.cmd == cmd); }), delayedCmdQue.end()); + + //removeSimilarCommand(cmd); } void wfmain::issueCmdUniquePriority(cmds cmd, char c) @@ -4198,7 +4332,8 @@ void wfmain::issueCmdUniquePriority(cmds cmd, char c) cmddata.cmd = cmd; cmddata.data = std::shared_ptr(new char(c)); delayedCmdQue.push_front(cmddata); - removeSimilarCommand(cmd); + delayedCmdQue.erase(std::remove_if(delayedCmdQue.begin() + 1, delayedCmdQue.end(), [cmd](const commandtype& c) { return (c.cmd == cmd); }), delayedCmdQue.end()); + //removeSimilarCommand(cmd); } void wfmain::issueCmdUniquePriority(cmds cmd, freqt f) @@ -4207,7 +4342,8 @@ void wfmain::issueCmdUniquePriority(cmds cmd, freqt f) cmddata.cmd = cmd; cmddata.data = std::shared_ptr(new freqt(f)); delayedCmdQue.push_front(cmddata); - removeSimilarCommand(cmd); + delayedCmdQue.erase(std::remove_if(delayedCmdQue.begin() + 1, delayedCmdQue.end(), [cmd](const commandtype& c) { return (c.cmd == cmd); }), delayedCmdQue.end()); + //removeSimilarCommand(cmd); } void wfmain::issueCmdUniquePriority(cmds cmd, quint16 c) @@ -4216,7 +4352,8 @@ void wfmain::issueCmdUniquePriority(cmds cmd, quint16 c) cmddata.cmd = cmd; cmddata.data = std::shared_ptr(new quint16(c)); delayedCmdQue.push_front(cmddata); - removeSimilarCommand(cmd); + delayedCmdQue.erase(std::remove_if(delayedCmdQue.begin() + 1, delayedCmdQue.end(), [cmd](const commandtype& c) { return (c.cmd == cmd); }), delayedCmdQue.end()); + //removeSimilarCommand(cmd); } void wfmain::issueCmdUniquePriority(cmds cmd, qint16 c) @@ -4225,7 +4362,8 @@ void wfmain::issueCmdUniquePriority(cmds cmd, qint16 c) cmddata.cmd = cmd; cmddata.data = std::shared_ptr(new qint16(c)); delayedCmdQue.push_front(cmddata); - removeSimilarCommand(cmd); + delayedCmdQue.erase(std::remove_if(delayedCmdQue.begin() + 1, delayedCmdQue.end(), [cmd](const commandtype& c) { return (c.cmd == cmd); }), delayedCmdQue.end()); + //removeSimilarCommand(cmd); } void wfmain::removeSimilarCommand(cmds cmd) @@ -4506,16 +4644,14 @@ void wfmain::initPeriodicCommands() if (rigCaps.hasRXAntenna) { insertSlowPeriodicCommand(cmdGetAntenna, 128); } - insertSlowPeriodicCommand(cmdGetDuplexMode, 128); + insertSlowPeriodicCommand(cmdGetDuplexMode, 128); // split and repeater + if(rigCaps.hasRepeaterModes) + { + insertSlowPeriodicCommand(cmdGetRptDuplexOffset, 128); + } rapidPollCmdQueueEnabled = false; rapidPollCmdQueue.clear(); - if (rigCaps.hasSpectrum) { - // Get passband - insertPeriodicRapidCmd(cmdGetPassband); - insertPeriodicRapidCmd(cmdGetTPBFInner); - insertPeriodicRapidCmd(cmdGetTPBFOuter); - } rapidPollCmdQueueEnabled = true; } @@ -4555,6 +4691,12 @@ void wfmain::insertPeriodicCommandUnique(cmds cmd) void wfmain::removePeriodicRapidCmd(cmds cmd) { + + qDebug() << "Removing" << cmd << "From periodic queue, len" << slowPollCmdQueue.size(); + periodicCmdQueue.erase(std::remove_if(periodicCmdQueue.begin(), periodicCmdQueue.end(), [cmd](const cmds& c) { return (c == cmd); }), periodicCmdQueue.end()); + qDebug() << "Removed" << cmd << "From periodic queue, len" << slowPollCmdQueue.size(); + + /* while(true) { auto it = std::find(this->rapidPollCmdQueue.begin(), this->rapidPollCmdQueue.end(), cmd); @@ -4565,11 +4707,17 @@ void wfmain::removePeriodicRapidCmd(cmds cmd) break; } } + */ } void wfmain::removePeriodicCommand(cmds cmd) { - while(true) + + qDebug() << "Removing" << cmd << "From periodic queue, len" << slowPollCmdQueue.size(); + periodicCmdQueue.erase(std::remove_if(periodicCmdQueue.begin(), periodicCmdQueue.end(), [cmd](const cmds& c) { return (c == cmd); }), periodicCmdQueue.end()); + qDebug() << "Removed" << cmd << "From periodic queue, len" << slowPollCmdQueue.size(); + +/* while (true) { auto it = std::find(this->periodicCmdQueue.begin(), this->periodicCmdQueue.end(), cmd); if(it != periodicCmdQueue.end()) @@ -4579,6 +4727,7 @@ void wfmain::removePeriodicCommand(cmds cmd) break; } } + */ } @@ -4587,12 +4736,21 @@ void wfmain::insertSlowPeriodicCommand(cmds cmd, unsigned char priority=100) // TODO: meaningful priority // These commands are run every 20 "ticks" of the primary radio command loop // Basically 20 times less often than the standard periodic command + qDebug() << "Inserting" << cmd << "To slow queue, priority" << priority << "len" << slowPollCmdQueue.size(); if(priority < 10) { slowPollCmdQueue.push_front(cmd); } else { slowPollCmdQueue.push_back(cmd); } + qDebug() << "Inserted" << cmd << "To slow queue, priority" << priority << "len" << slowPollCmdQueue.size(); +} + +void wfmain::removeSlowPeriodicCommand(cmds cmd) +{ + qDebug() << "Removing" << cmd << "From slow queue, len" << slowPollCmdQueue.size(); + slowPollCmdQueue.erase(std::remove_if(slowPollCmdQueue.begin(), slowPollCmdQueue.end(), [cmd](const cmds& c) { return (c == cmd); }), slowPollCmdQueue.end()); + qDebug() << "Removed" << cmd << "From slow queue, len" << slowPollCmdQueue.size(); } void wfmain::receiveFreq(freqt freqStruct) @@ -4613,15 +4771,24 @@ void wfmain::receiveFreq(freqt freqStruct) void wfmain::receivePTTstatus(bool pttOn) { // This is the only place where amTransmitting and the transmit button text should be changed: - //qInfo(logSystem()) << "PTT status: " << pttOn; if (pttOn && !amTransmitting) { - pttLed->setState(QLedLabel::State::StateError); + pttLed->setState(QLedLabel::State::StateError); + pttLed->setToolTip("Transmitting"); + if(splitModeEnabled) + { + pttLed->setState(QLedLabel::State::StateSplitErrorOk); + pttLed->setToolTip("TX Split"); + } else { + pttLed->setState(QLedLabel::State::StateError); + pttLed->setToolTip("Transmitting"); + } } else if (!pttOn && amTransmitting) { pttLed->setState(QLedLabel::State::StateOk); + pttLed->setToolTip("Receiving"); } amTransmitting = pttOn; rpt->handleTransmitStatus(pttOn); @@ -4949,6 +5116,9 @@ void wfmain::handlePlotDoubleClick(QMouseEvent *me) qint16 newFreq = pbFreq + 128; issueCmdUniquePriority(cmdSetTPBFInner, (unsigned char)newFreq); issueCmdUniquePriority(cmdSetTPBFOuter, (unsigned char)newFreq); + issueDelayedCommandUnique(cmdGetTPBFInner); + issueDelayedCommandUnique(cmdGetTPBFOuter); + } } } @@ -5117,31 +5287,36 @@ void wfmain::handlePlotMouseMove(QMouseEvent* me) } else if (passbandAction == passbandResizing) { - // We are currently resizing the passband. - double pb = 0.0; - double origin = 0.0; - switch (currentModeInfo.mk) - { - case modeCW: - case modeCW_R: - origin = 0.0; - break; - case modeLSB: - origin = -passbandCenterFrequency; - break; - default: - origin = passbandCenterFrequency; - break; - } + static double lastFreq = movedFrequency; + if (lastFreq - movedFrequency > 0.000049 || movedFrequency - lastFreq > 0.000049) { - if (plot->xAxis->pixelToCoord(cursor) >= freq.MHzDouble + origin) { - pb = plot->xAxis->pixelToCoord(cursor) - passbandIndicator->topLeft->coords().x(); - } - else { - pb = passbandIndicator->bottomRight->coords().x() - plot->xAxis->pixelToCoord(cursor); - } + // We are currently resizing the passband. + double pb = 0.0; + double origin = 0.0; + switch (currentModeInfo.mk) + { + case modeCW: + case modeCW_R: + origin = 0.0; + break; + case modeLSB: + origin = -passbandCenterFrequency; + break; + default: + origin = passbandCenterFrequency; + break; + } - issueCmdUniquePriority(cmdSetPassband, (quint16)(pb * 1000000)); + if (plot->xAxis->pixelToCoord(cursor) >= freq.MHzDouble + origin) { + pb = plot->xAxis->pixelToCoord(cursor) - passbandIndicator->topLeft->coords().x(); + } + else { + pb = passbandIndicator->bottomRight->coords().x() - plot->xAxis->pixelToCoord(cursor); + } + issueCmdUniquePriority(cmdSetPassband, (quint16)(pb * 1000000)); + issueDelayedCommandUnique(cmdGetPassband); + lastFreq = movedFrequency; + } } else if (passbandAction == pbtMoving) { @@ -5161,25 +5336,36 @@ void wfmain::handlePlotMouseMove(QMouseEvent* me) qDebug() << QString("Moving passband by %1 Hz (Inner %2) (Outer %3) Mode:%4").arg((qint16)(movedFrequency * 1000000)) .arg(newInFreq).arg(newOutFreq).arg(currentModeInfo.mk); - issueCmd(cmdSetTPBFInner, (unsigned char)newInFreq); - issueCmd(cmdSetTPBFOuter, (unsigned char)newOutFreq); - + issueCmdUniquePriority(cmdSetTPBFInner, (unsigned char)newInFreq); + issueCmdUniquePriority(cmdSetTPBFOuter, (unsigned char)newOutFreq); + issueDelayedCommandUnique(cmdGetTPBFInner); + issueDelayedCommandUnique(cmdGetTPBFOuter); } lastFreq = movedFrequency; } } else if (passbandAction == pbtInnerMove) { - double pbFreq = ((double)(TPBFInner + movedFrequency) / passbandWidth) * 127.0; - qint16 newFreq = pbFreq + 128; - if (newFreq >= 0 && newFreq <= 255) { - issueCmdUniquePriority(cmdSetTPBFInner, (unsigned char)newFreq); + static double lastFreq = movedFrequency; + if (lastFreq - movedFrequency > 0.000049 || movedFrequency - lastFreq > 0.000049) { + double pbFreq = ((double)(TPBFInner + movedFrequency) / passbandWidth) * 127.0; + qint16 newFreq = pbFreq + 128; + if (newFreq >= 0 && newFreq <= 255) { + issueCmdUniquePriority(cmdSetTPBFInner, (unsigned char)newFreq); + issueDelayedCommandUnique(cmdGetTPBFInner); + } + lastFreq = movedFrequency; } } else if (passbandAction == pbtOuterMove) { - double pbFreq = ((double)(TPBFOuter + movedFrequency) / passbandWidth) * 127.0; - qint16 newFreq = pbFreq + 128; - if (newFreq >= 0 && newFreq <= 255) { - issueCmdUniquePriority(cmdSetTPBFOuter, (unsigned char)newFreq); + static double lastFreq = movedFrequency; + if (lastFreq - movedFrequency > 0.000049 || movedFrequency - lastFreq > 0.000049) { + double pbFreq = ((double)(TPBFOuter + movedFrequency) / passbandWidth) * 127.0; + qint16 newFreq = pbFreq + 128; + if (newFreq >= 0 && newFreq <= 255) { + issueCmdUniquePriority(cmdSetTPBFOuter, (unsigned char)newFreq); + issueDelayedCommandUnique(cmdGetTPBFOuter); + } + lastFreq = movedFrequency; } } else if (passbandAction == passbandStatic && me->buttons() == Qt::LeftButton && textItem == nullptr && prefs.clickDragTuningEnable) @@ -5213,7 +5399,7 @@ void wfmain::handleWFScroll(QWheelEvent *we) // We will click the dial once for every 120 received. //QPoint delta = we->angleDelta(); - if(freqLock) + if (freqLock) return; freqt f; @@ -5222,17 +5408,18 @@ void wfmain::handleWFScroll(QWheelEvent *we) int clicks = we->angleDelta().y() / 120; - if(!clicks) + if (!clicks) return; unsigned int stepsHz = tsWfScrollHz; - Qt::KeyboardModifiers key= we->modifiers(); + Qt::KeyboardModifiers key = we->modifiers(); - if ((key == Qt::ShiftModifier) && (stepsHz !=1)) + if ((key == Qt::ShiftModifier) && (stepsHz != 1)) { stepsHz /= 10; - } else if (key == Qt::ControlModifier) + } + else if (key == Qt::ControlModifier) { stepsHz *= 10; } @@ -5273,109 +5460,105 @@ void wfmain::receiveMode(unsigned char mode, unsigned char filter) if(mode < 0x23) { - for(int i=0; i < ui->modeSelectCombo->count(); i++) + // Update mode information if mode/filter has changed + if (currentModeInfo.mk != (mode_kind)mode || currentModeInfo.filter != filter) { - if(ui->modeSelectCombo->itemData(i).toInt() == mode) - { - ui->modeSelectCombo->blockSignals(true); - ui->modeSelectCombo->setCurrentIndex(i); - ui->modeSelectCombo->blockSignals(false); - found = true; - } - } - currentModeIndex = mode; - currentModeInfo.mk = (mode_kind)mode; - cw->handleCurrentModeUpdate((mode_kind)mode); - currentModeInfo.filter = filter; - switch (currentModeInfo.mk) { - case modeFM: - if (currentModeInfo.filter == 1) - passbandWidth = 0.015; - else if (currentModeInfo.filter == 2) - passbandWidth = 0.010; - else - passbandWidth = 0.007; - passbandCenterFrequency = 0.0; - break; - case modeLSB: - case modeUSB: - removePeriodicCommand(cmdGetCwPitch); - removePeriodicCommand(cmdGetPskTone); - removePeriodicCommand(cmdGetRttyMark); - passbandCenterFrequency = 0.0015; - break; - case modeCW: - case modeCW_R: - insertPeriodicCommandUnique(cmdGetCwPitch); - removePeriodicCommand(cmdGetPskTone); - removePeriodicCommand(cmdGetRttyMark); - break; - default: - removePeriodicCommand(cmdGetCwPitch); - removePeriodicCommand(cmdGetPskTone); - removePeriodicCommand(cmdGetRttyMark); - passbandCenterFrequency = 0.0; - break; + removePeriodicRapidCmd(cmdGetCwPitch); + removeSlowPeriodicCommand(cmdGetPassband); + removeSlowPeriodicCommand(cmdGetTPBFInner); + removeSlowPeriodicCommand(cmdGetTPBFOuter); + + quint16 maxPassbandHz = 0; + switch ((mode_kind)mode) { + case modeFM: + if (filter == 1) + passbandWidth = 0.015; + else if (filter == 2) + passbandWidth = 0.010; + else + passbandWidth = 0.007; + passbandCenterFrequency = 0.0; + maxPassbandHz = 10E3; + break; + case modeCW: + case modeCW_R: + insertPeriodicRapidCmdUnique(cmdGetCwPitch); + issueDelayedCommandUnique(cmdGetCwPitch); + maxPassbandHz = 3600; + break; + case modeAM: + passbandCenterFrequency = 0.0; + maxPassbandHz = 10E3; + break; + case modeLSB: + case modeUSB: + passbandCenterFrequency = 0.0015; + maxPassbandHz = 3600; + break; + default: + passbandCenterFrequency = 0.0; + maxPassbandHz = 3600; + break; + } + + for (int i = 0; i < ui->modeSelectCombo->count(); i++) + { + if (ui->modeSelectCombo->itemData(i).toInt() == mode) + { + ui->modeSelectCombo->blockSignals(true); + ui->modeSelectCombo->setCurrentIndex(i); + ui->modeSelectCombo->blockSignals(false); + found = true; + } + } + + if ((filter) && (filter < 4)) { + ui->modeFilterCombo->blockSignals(true); + ui->modeFilterCombo->setCurrentIndex(filter - 1); + ui->modeFilterCombo->blockSignals(false); + } + + currentModeIndex = mode; + currentModeInfo.mk = (mode_kind)mode; + currentMode = (mode_kind)mode; + currentModeInfo.filter = filter; + currentModeInfo.reg = mode; + rpt->handleUpdateCurrentMainMode(currentModeInfo); + cw->handleCurrentModeUpdate(currentMode); + if (!found) + { + qWarning(logSystem()) << __func__ << "Received mode " << mode << " but could not match to any index within the modeSelectCombo. "; + return; + } + + if (maxPassbandHz != 0) + { + trxadj->setMaxPassband(maxPassbandHz); + } + + if (currentModeInfo.mk != modeFM) + { + insertSlowPeriodicCommand(cmdGetPassband, 128); + insertSlowPeriodicCommand(cmdGetTPBFInner, 128); + insertSlowPeriodicCommand(cmdGetTPBFOuter, 128); + issueDelayedCommandUnique(cmdGetPassband); + issueDelayedCommandUnique(cmdGetTPBFInner); + issueDelayedCommandUnique(cmdGetTPBFOuter); + } + + // Note: we need to know if the DATA mode is active to reach mode-D + // some kind of queued query: + if (rigCaps.hasDataModes && rigCaps.hasTransmit) + { + issueDelayedCommand(cmdGetDataMode); + } + } } else { qCritical(logSystem()) << __func__ << "Invalid mode " << mode << " received. "; } - - if(!found) - { - qWarning(logSystem()) << __func__ << "Received mode " << mode << " but could not match to any index within the modeSelectCombo. "; - return; - } - - currentModeIndex = mode; - currentModeInfo.mk = (mode_kind)mode; - currentMode = (mode_kind)mode; - currentModeInfo.filter = filter; - currentModeInfo.reg = mode; - rpt->handleUpdateCurrentMainMode(currentModeInfo); - - if( (filter) && (filter < 4)){ - ui->modeFilterCombo->blockSignals(true); - ui->modeFilterCombo->setCurrentIndex(filter-1); - ui->modeFilterCombo->blockSignals(false); - } - - quint16 maxPassbandHz = 0; - switch(currentMode) - { - case modeUSB: - case modeLSB: - case modeCW: - case modeCW_R: - case modePSK: - case modePSK_R: - maxPassbandHz = 3600; - break; - case modeRTTY: - case modeRTTY_R: - maxPassbandHz = 2700; - break; - case modeAM: - maxPassbandHz = 10E3; - break; - case modeFM: - maxPassbandHz = 10E3; - break; - default: - break; - } - if(maxPassbandHz != 0) - { - trxadj->setMaxPassband(maxPassbandHz); - } - // Note: we need to know if the DATA mode is active to reach mode-D - // some kind of queued query: - if (rigCaps.hasDataModes && rigCaps.hasTransmit) - { - issueDelayedCommand(cmdGetDataMode); - } } void wfmain::receiveDataModeStatus(bool dataEnabled) @@ -5658,7 +5841,9 @@ void wfmain::on_modeSelectCombo_activated(int index) } issueCmd(cmdSetMode, mode); - currentModeInfo = mode; + issueDelayedCommand(cmdGetMode); + + //currentModeInfo = mode; } } @@ -6200,6 +6385,11 @@ void wfmain::on_passwordTxt_textChanged(QString text) udpPrefs.password = text; } +void wfmain::on_audioDuplexCombo_currentIndexChanged(int value) +{ + udpPrefs.halfDuplex = (bool)value; +} + void wfmain::on_audioOutputCombo_currentIndexChanged(int value) { @@ -6353,6 +6543,7 @@ void wfmain::on_modeFilterCombo_activated(int index) m.mk = (mode_kind)newMode; m.reg = newMode; issueCmd(cmdSetMode, m); + //emit setMode(newMode, (unsigned char)filterSelection); } } @@ -6855,7 +7046,15 @@ void wfmain::on_serialDeviceListCombo_textActivated(const QString &arg1) void wfmain::on_rptSetupBtn_clicked() { + if(rpt->isMinimized()) + { + rpt->raise(); + rpt->activateWindow(); + return; + } rpt->show(); + rpt->raise(); + rpt->activateWindow(); } void wfmain::on_attSelCombo_activated(int index) @@ -7627,7 +7826,8 @@ void wfmain::on_underlayAverageBuffer_toggled(bool checked) void wfmain::on_debugBtn_clicked() { qInfo(logSystem()) << "Debug button pressed."; - cw->show(); + qDebug(logSystem()) << "Query for repeater duplex offset 0x0C headed out"; + issueDelayedCommand(cmdGetRptDuplexOffset); } // ---------- color helper functions: ---------- // @@ -8712,6 +8912,29 @@ void wfmain::on_clickDragTuningEnableChk_clicked(bool checked) prefs.clickDragTuningEnable = checked; } +void wfmain::on_enableUsbChk_clicked(bool checked) +{ + prefs.enableUSBControllers = checked; + ui->usbControllerBtn->setEnabled(checked); + ui->usbButtonsResetBtn->setEnabled(checked); + ui->usbCommandsResetBtn->setEnabled(checked); + ui->usbResetLbl->setVisible(checked); + +#if defined (USB_CONTROLLER) + if (usbControllerThread != Q_NULLPTR) { + usbControllerThread->quit(); + usbControllerThread->wait(); + usbControllerThread = Q_NULLPTR; + } + if (checked) { + // Setup USB Controller + setupUsbControllerDevice(); + emit sendUsbControllerCommands(&usbCommands); + emit sendUsbControllerButtons(&usbButtons); + } +#endif +} + void wfmain::on_usbControllerBtn_clicked() { if (shut != Q_NULLPTR) { @@ -8725,6 +8948,34 @@ void wfmain::on_usbControllerBtn_clicked() } } + +void wfmain::on_usbButtonsResetBtn_clicked() +{ + int ret = QMessageBox::warning(this, tr("wfview"), + tr("Are you sure you wish to reset the USB buttons?"), + QMessageBox::Ok | QMessageBox::Cancel, + QMessageBox::Cancel); + if (ret == QMessageBox::Ok) { + qInfo(logUsbControl()) << "Resetting USB buttons to default values"; + resetUsbButtons(); + on_enableUsbChk_clicked(true); // Force disconnect/reconnect of USB controller. + } +} + +void wfmain::on_usbCommandsResetBtn_clicked() +{ + int ret = QMessageBox::warning(this, tr("wfview"), + tr("Are you sure you wish to reset the USB commands?"), + QMessageBox::Ok | QMessageBox::Cancel, + QMessageBox::Cancel); + if (ret == QMessageBox::Ok) { + qInfo(logUsbControl()) << "Resetting USB commands to default values"; + resetUsbCommands(); + on_enableUsbChk_clicked(true); // Force disconnect/reconnect of USB controller. + } + +} + void wfmain::on_autoPollBtn_clicked(bool checked) { ui->pollTimeMsSpin->setEnabled(!checked); @@ -8810,3 +9061,117 @@ void wfmain::on_cwButton_clicked() cw->raise(); cw->activateWindow(); } + +void wfmain::resetUsbButtons() +{ + usbButtons.clear(); + + // ShuttleXpress + usbButtons.append(BUTTON(1, 4, QRect(25, 199, 89, 169), Qt::red, &usbCommands[0], &usbCommands[0])); + usbButtons.append(BUTTON(1, 5, QRect(101, 72, 83, 88), Qt::red, &usbCommands[0], &usbCommands[0])); + usbButtons.append(BUTTON(1, 6, QRect(238, 26, 134, 69), Qt::red, &usbCommands[0], &usbCommands[0])); + usbButtons.append(BUTTON(1, 7, QRect(452, 72, 77, 86), Qt::red, &usbCommands[0], &usbCommands[0])); + usbButtons.append(BUTTON(1, 8, QRect(504, 199, 89, 169), Qt::red, &usbCommands[0], &usbCommands[0])); + + // ShuttlePro2 + usbButtons.append(BUTTON(2, 0, QRect(60, 66, 40, 30), Qt::red, &usbCommands[0], &usbCommands[0])); + usbButtons.append(BUTTON(2, 1, QRect(114, 50, 40, 30), Qt::red, &usbCommands[0], &usbCommands[0])); + usbButtons.append(BUTTON(2, 2, QRect(169, 47, 40, 30), Qt::red, &usbCommands[0], &usbCommands[0])); + usbButtons.append(BUTTON(2, 3, QRect(225, 59, 40, 30), Qt::red, &usbCommands[0], &usbCommands[0])); + usbButtons.append(BUTTON(2, 4, QRect(41, 132, 40, 30), Qt::red, &usbCommands[0], &usbCommands[0])); + usbButtons.append(BUTTON(2, 5, QRect(91, 105, 40, 30), Qt::red, &usbCommands[0], &usbCommands[0])); + usbButtons.append(BUTTON(2, 6, QRect(144, 93, 40, 30), Qt::red, &usbCommands[0], &usbCommands[0])); + usbButtons.append(BUTTON(2, 7, QRect(204, 99, 40, 30), Qt::red, &usbCommands[0], &usbCommands[0])); + usbButtons.append(BUTTON(2, 8, QRect(253, 124, 40, 30), Qt::red, &usbCommands[0], &usbCommands[0])); + usbButtons.append(BUTTON(2, 9, QRect(50, 270, 70, 55), Qt::red, &usbCommands[0], &usbCommands[0])); + usbButtons.append(BUTTON(2, 10, QRect(210, 270, 70, 55), Qt::red, &usbCommands[0], &usbCommands[0])); + usbButtons.append(BUTTON(2, 11, QRect(50, 335, 70, 55), Qt::red, &usbCommands[0], &usbCommands[0])); + usbButtons.append(BUTTON(2, 12, QRect(210, 335, 70, 55), Qt::red, &usbCommands[0], &usbCommands[0])); + usbButtons.append(BUTTON(2, 13, QRect(30, 195, 25, 80), Qt::red, &usbCommands[0], &usbCommands[0])); + usbButtons.append(BUTTON(2, 14, QRect(280, 195, 25, 80), Qt::red, &usbCommands[0], &usbCommands[0])); + + // RC28 + usbButtons.append(BUTTON(3, 0, QRect(52, 445, 238, 64), Qt::red, &usbCommands[0], &usbCommands[0])); + usbButtons.append(BUTTON(3, 1, QRect(52, 373, 98, 46), Qt::red, &usbCommands[0], &usbCommands[0])); + usbButtons.append(BUTTON(3, 2, QRect(193, 373, 98, 46), Qt::red, &usbCommands[0], &usbCommands[0])); + + // Xbox Gamepad + usbButtons.append(BUTTON(4, "UP", QRect(256, 229, 50, 50), Qt::red, &usbCommands[0], &usbCommands[0])); + usbButtons.append(BUTTON(4, "DOWN", QRect(256, 316, 50, 50), Qt::red, &usbCommands[0], &usbCommands[0])); + usbButtons.append(BUTTON(4, "LEFT", QRect(203, 273, 50, 50), Qt::red, &usbCommands[0], &usbCommands[0])); + usbButtons.append(BUTTON(4, "RIGHT", QRect(303, 273, 50, 50), Qt::red, &usbCommands[0], &usbCommands[0])); + usbButtons.append(BUTTON(4, "SELECT", QRect(302, 160, 40, 40), Qt::red, &usbCommands[0], &usbCommands[0])); + usbButtons.append(BUTTON(4, "START", QRect(412, 163, 40, 40), Qt::red, &usbCommands[0], &usbCommands[0])); + usbButtons.append(BUTTON(4, "Y", QRect(534, 104, 53, 53), Qt::red, &usbCommands[0], &usbCommands[0])); + usbButtons.append(BUTTON(4, "X", QRect(485, 152, 53, 53), Qt::red, &usbCommands[0], &usbCommands[0])); + usbButtons.append(BUTTON(4, "B", QRect(590, 152, 53, 53), Qt::red, &usbCommands[0], &usbCommands[0])); + usbButtons.append(BUTTON(4, "A", QRect(534, 202, 53, 53), Qt::red, &usbCommands[0], &usbCommands[0])); + usbButtons.append(BUTTON(4, "L1", QRect(123, 40, 70, 45), Qt::red, &usbCommands[0], &usbCommands[0])); + usbButtons.append(BUTTON(4, "R1", QRect(562, 40, 70, 45), Qt::red, &usbCommands[0], &usbCommands[0])); + usbButtons.append(BUTTON(4, "LEFTX", QRect(143, 119, 83, 35), Qt::red, &usbCommands[0], &usbCommands[0])); + usbButtons.append(BUTTON(4, "LEFTY", QRect(162, 132, 50, 57), Qt::red, &usbCommands[0], &usbCommands[0])); + usbButtons.append(BUTTON(4, "RIGHTX", QRect(430, 298, 83, 35), Qt::red, &usbCommands[0], &usbCommands[0])); + usbButtons.append(BUTTON(4, "RIGHTY", QRect(453, 233, 50, 57), Qt::red, &usbCommands[0], &usbCommands[0])); + emit sendUsbControllerButtons(&usbButtons); + + +} + +void wfmain::resetUsbCommands() +{ + usbCommands.clear(); + usbCommands.append(COMMAND(0, "None", cmdNone, 0x0)); + usbCommands.append(COMMAND(1, "PTT On", cmdSetPTT, 0x1)); + usbCommands.append(COMMAND(2, "PTT Off", cmdSetPTT, 0x0)); + usbCommands.append(COMMAND(3, "PTT Toggle", cmdPTTToggle, 0x0)); + usbCommands.append(COMMAND(4, "Tune", cmdStartATU, 0x0)); + usbCommands.append(COMMAND(5, "Step+", cmdSetStepUp, 0x0)); + usbCommands.append(COMMAND(6, "Step-", cmdSetStepDown, 0x0)); + usbCommands.append(COMMAND(7, "Span+", cmdSetSpanUp, 0x0)); + usbCommands.append(COMMAND(8, "Span-", cmdSetSpanDown, 0x0)); + usbCommands.append(COMMAND(9, "Mode+", cmdSetModeUp, 0x0)); + usbCommands.append(COMMAND(10, "Mode-", cmdSetModeDown, 0x0)); + usbCommands.append(COMMAND(11, "Mode LSB", cmdSetMode, modeLSB)); + usbCommands.append(COMMAND(12, "Mode USB", cmdSetMode, modeUSB)); + usbCommands.append(COMMAND(13, "Mode LSBD", cmdSetMode, modeLSB_D)); + usbCommands.append(COMMAND(14, "Mode USBD", cmdSetMode, modeUSB_D)); + usbCommands.append(COMMAND(15, "Mode CW", cmdSetMode, modeCW)); + usbCommands.append(COMMAND(16, "Mode CWR", cmdSetMode, modeCW_R)); + usbCommands.append(COMMAND(17, "Mode FM", cmdSetMode, modeFM)); + usbCommands.append(COMMAND(18, "Mode AM", cmdSetMode, modeAM)); + usbCommands.append(COMMAND(19, "Mode RTTY", cmdSetMode, modeRTTY)); + usbCommands.append(COMMAND(20, "Mode RTTYR", cmdSetMode, modeRTTY_R)); + usbCommands.append(COMMAND(21, "Mode PSK", cmdSetMode, modePSK)); + usbCommands.append(COMMAND(22, "Mode PSKR", cmdSetMode, modePSK_R)); + usbCommands.append(COMMAND(23, "Mode DV", cmdSetMode, modeDV)); + usbCommands.append(COMMAND(24, "Mode DD", cmdSetMode, modeDD)); + usbCommands.append(COMMAND(25, "Band+", cmdSetBandUp, 0x0)); + usbCommands.append(COMMAND(26, "Band-", cmdSetBandDown, 0x0)); + usbCommands.append(COMMAND(27, "23cm", cmdGetBandStackReg, band23cm)); + usbCommands.append(COMMAND(28, "70cm", cmdGetBandStackReg, band70cm)); + usbCommands.append(COMMAND(29, "2m", cmdGetBandStackReg, band2m)); + usbCommands.append(COMMAND(30, "AIR", cmdGetBandStackReg, bandAir)); + usbCommands.append(COMMAND(31, "WFM", cmdGetBandStackReg, bandWFM)); + usbCommands.append(COMMAND(32, "4m", cmdGetBandStackReg, band4m)); + usbCommands.append(COMMAND(33, "6m", cmdGetBandStackReg, band6m)); + usbCommands.append(COMMAND(34, "10m", cmdGetBandStackReg, band10m)); + usbCommands.append(COMMAND(35, "12m", cmdGetBandStackReg, band12m)); + usbCommands.append(COMMAND(36, "15m", cmdGetBandStackReg, band15m)); + usbCommands.append(COMMAND(37, "17m", cmdGetBandStackReg, band17m)); + usbCommands.append(COMMAND(38, "20m", cmdGetBandStackReg, band20m)); + usbCommands.append(COMMAND(39, "30m", cmdGetBandStackReg, band30m)); + usbCommands.append(COMMAND(40, "40m", cmdGetBandStackReg, band40m)); + usbCommands.append(COMMAND(41, "60m", cmdGetBandStackReg, band60m)); + usbCommands.append(COMMAND(42, "80m", cmdGetBandStackReg, band80m)); + usbCommands.append(COMMAND(43, "160m", cmdGetBandStackReg, band160m)); + usbCommands.append(COMMAND(44, "630m", cmdGetBandStackReg, band630m)); + usbCommands.append(COMMAND(45, "2200m", cmdGetBandStackReg, band2200m)); + usbCommands.append(COMMAND(46, "GEN", cmdGetBandStackReg, bandGen)); + usbCommands.append(COMMAND(47, "NR On", cmdNone, 0x0)); + usbCommands.append(COMMAND(48, "NR Off", cmdNone, 0x0)); + usbCommands.append(COMMAND(49, "NB On", cmdNone, 0x0)); + usbCommands.append(COMMAND(50, "NB Off", cmdNone, 0x0)); + usbCommands.append(COMMAND(51, "Split On", cmdNone, 0x01)); + usbCommands.append(COMMAND(52, "Split Off", cmdNone, 0x0)); + emit sendUsbControllerCommands(&usbCommands); +} \ No newline at end of file diff --git a/wfmain.h b/wfmain.h index 00c1063..21e151b 100644 --- a/wfmain.h +++ b/wfmain.h @@ -94,6 +94,10 @@ signals: void getMode(); void setMode(unsigned char modeIndex, unsigned char modeFilter); void setMode(mode_info); + void selectVFO(vfo_t vfo); + void sendVFOSwap(); + void sendVFOEqualAB(); + void sendVFOEqualMS(); void setDataMode(bool dataOn, unsigned char filter); void getDataMode(); void getModInput(bool dataOn); @@ -111,6 +115,11 @@ signals: void getTSQL(); void getDTCS(); void getRptAccessMode(); + void setRepeaterAccessMode(rptrAccessData_t rd); + void setTone(rptrTone_t t); + void setTSQL(rptrTone_t t); + void setRptDuplexOffset(freqt f); + void getRptDuplexOffset(); // Level get: void getLevels(); // get all levels @@ -383,6 +392,11 @@ private slots: void on_fEnterBtn_clicked(); void on_usbControllerBtn_clicked(); + void on_usbButtonsResetBtn_clicked(); + void on_usbCommandsResetBtn_clicked(); + + void on_enableUsbChk_clicked(bool checked); + void on_scopeBWCombo_currentIndexChanged(int index); void on_scopeEdgeCombo_currentIndexChanged(int index); @@ -451,6 +465,8 @@ private slots: void on_passwordTxt_textChanged(QString text); + void on_audioDuplexCombo_currentIndexChanged(int value); + void on_audioOutputCombo_currentIndexChanged(int value); void on_audioInputCombo_currentIndexChanged(int value); @@ -909,6 +925,9 @@ private: void issueCmd(cmds cmd, freqt f); void issueCmd(cmds cmd, mode_info m); + void issueCmd(cmds cmd, vfo_t v); + void issueCmd(cmds cmd, rptrTone_t t); + void issueCmd(cmds cmd, rptrAccessData_t rd); void issueCmd(cmds cmd, timekind t); void issueCmd(cmds cmd, datekind d); void issueCmd(cmds cmd, int i); @@ -1024,6 +1043,7 @@ private: void insertSlowPeriodicCommand(cmds cmd, unsigned char priority); + void removeSlowPeriodicCommand(cmds cmd); void calculateTimingParameters(); void changePollTiming(int timing_ms, bool setUI=false); @@ -1036,6 +1056,9 @@ private: void updateUsbButtons(); + void resetUsbButtons(); + void resetUsbCommands(); + int oldFreqDialVal; rigCapabilities rigCaps; @@ -1045,7 +1068,8 @@ private: mode_info currentModeInfo; bool haveRigCaps; - bool amTransmitting; + bool amTransmitting = false; + bool splitModeEnabled = false; bool usingDataMode = false; unsigned char micGain=0; @@ -1101,6 +1125,8 @@ private: double pbtDefault = 0.0; quint16 cwPitch = 600; + availableBands lastRequestedBand=bandGen; + SERVERCONFIG serverConfig; void serverAddUserLine(const QString& user, const QString& pass, const int& type); @@ -1139,6 +1165,7 @@ Q_DECLARE_METATYPE(enum rigInput) Q_DECLARE_METATYPE(enum meterKind) Q_DECLARE_METATYPE(enum spectrumMode) Q_DECLARE_METATYPE(enum mode_kind) +Q_DECLARE_METATYPE(enum vfo_t) Q_DECLARE_METATYPE(QList) Q_DECLARE_METATYPE(QList) Q_DECLARE_METATYPE(rigstate*) @@ -1148,6 +1175,10 @@ Q_DECLARE_METATYPE(QVector *) Q_DECLARE_METATYPE(const COMMAND*) Q_DECLARE_METATYPE(codecType) Q_DECLARE_METATYPE(errorType) +Q_DECLARE_METATYPE(enum duplexMode) +Q_DECLARE_METATYPE(enum rptAccessTxRx) +Q_DECLARE_METATYPE(struct rptrTone_t) +Q_DECLARE_METATYPE(struct rptrAccessData_t) //void (*wfmain::logthistext)(QString text) = NULL; diff --git a/wfmain.ui b/wfmain.ui index cb896a4..3958d51 100644 --- a/wfmain.ui +++ b/wfmain.ui @@ -6,7 +6,7 @@ 0 0 - 1082 + 1012 660 @@ -18,7 +18,7 @@ - 0 + 3 @@ -1057,7 +1057,7 @@ Show the repeater tone and offset window - Repeater + Rpt/Split @@ -1808,7 +1808,6 @@ DejaVu Sans Mono 14 - 75 true @@ -2233,7 +2232,7 @@ - 1 + 4 @@ -2775,61 +2774,26 @@ - + - Audio Output + Duplex - - - - 120 - 16777215 - - - - Audio Output Selector - + + + + Full Duplex + + + + + Half Duplex + + - - - - Audio Input - - - - - - - - 120 - 16777215 - - - - Audio Input Selector - - - - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 15 - 20 - - - - @@ -2871,6 +2835,63 @@ + + + + + + Audio Output + + + + + + + + 200 + 16777215 + + + + Audio Output Selector + + + + + + + Audio Input + + + + + + + + 200 + 16777215 + + + + Audio Input Selector + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + @@ -3409,8 +3430,8 @@ 0 0 - 858 - 287 + 790 + 302 @@ -4929,6 +4950,74 @@ + + + + + + Enable USB Controllers + + + + + + + + + + Setup USB Controller + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Reset Buttons + + + + + + + Reset Commands + + + + + + + Only reset buttons/commands if you have issues. + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + @@ -5233,13 +5322,6 @@ - - - - Setup USB Controller - - - @@ -5359,7 +5441,6 @@ - 50 false @@ -5378,8 +5459,8 @@ 0 0 - 1082 - 21 + 1012 + 22 @@ -5406,8 +5487,8 @@ + - diff --git a/wfview.pro b/wfview.pro index 976c4da..28d89fb 100644 --- a/wfview.pro +++ b/wfview.pro @@ -10,7 +10,7 @@ QT += core gui serialport network multimedia xml #DEFINES += USESQL #Uncomment The following line to enable USB controllers (Shuttle/RC-28 etc.) -#DEFINES += USB_CONTROLLER +DEFINES += USB_CONTROLLER greaterThan(QT_MAJOR_VERSION, 4): QT += widgets printsupport @@ -175,16 +175,17 @@ CONFIG(debug, release|debug) { } } -!win32:LIBS += -L./ -l$$QCPLIB -lopus -win32:LIBS += -l$$QCPLIB -lopus - contains(DEFINES,USB_CONTROLLER){ linux:LIBS += -L./ -l$$QCPLIB -lhidapi-libusb macx:LIBS += -lhidapi + macx:LIBS += -L../hidapi/windows/x64/release -lhidapi win32:INCLUDEPATH += ../hidapi/hidapi - win32:SOURCES += ../hidapi/windows/hid.c } +!win32:LIBS += -L./ -l$$QCPLIB -lopus +win32:LIBS += -l$$QCPLIB -lopus + + #macx:SOURCES += ../qcustomplot/qcustomplot.cpp #macx:HEADERS += ../qcustomplot/qcustomplot.h diff --git a/wfview.vcxproj.user b/wfview.vcxproj.user index e6fe3c4..55b6057 100644 --- a/wfview.vcxproj.user +++ b/wfview.vcxproj.user @@ -45,10 +45,10 @@ 2022-08-21T18:58:23.4329764Z - 2023-01-12T19:02:11.7122024Z + 2023-01-29T11:49:00.1257696Z - 2023-01-12T19:02:11.0783744Z + 2023-01-29T11:48:59.4191765Z 2022-08-22T10:47:49.1255783Z @@ -60,9 +60,9 @@ 2022-08-20T19:06:43.4553894Z - 2023-01-12T19:02:13.6556090Z + 2023-01-29T11:49:01.5629425Z - 2023-01-12T19:02:12.4064183Z + 2023-01-29T11:49:00.7644018Z \ No newline at end of file diff --git a/wfviewtypes.h b/wfviewtypes.h index 131989d..9c5dd24 100644 --- a/wfviewtypes.h +++ b/wfviewtypes.h @@ -65,6 +65,47 @@ enum selVFO_t { inactiveVFO = 1 }; +enum vfo_t { + vfoA=0, + vfoB=1, + vfoMain = 0xD0, + vfoSub = 0xD1 +}; + +struct rptrTone_t { + quint16 tone = 0; + bool useSecondaryVFO = false; +}; + +enum duplexMode { + dmSplitOff=0x00, + dmSplitOn=0x01, + dmSimplex=0x10, + dmDupMinus=0x11, + dmDupPlus=0x12, + dmDupRPS=0x13, + dmDupAutoOn=0x26, + dmDupAutoOff=0x36 +}; + +// Here, T=tone, D=DCS, N=none +// And the naming convention order is Transmit Receive +enum rptAccessTxRx { + ratrNN=0x00, + ratrTN=0x01, // "TONE" (T only) + ratrNT=0x02, // "TSQL" (R only) + ratrDD=0x03, // "DTCS" (TR) + ratrDN=0x06, // "DTCS(T)" + ratrTD=0x07, // "TONE(T) / TSQL(R)" + ratrDT=0x08, // "DTCS(T) / TSQL(R)" + ratrTT=0x09 // "TONE(T) / TSQL(R)" +}; + +struct rptrAccessData_t { + rptAccessTxRx accessMode = ratrNN; + bool useSecondaryVFO = false; +}; + struct mode_info { mode_kind mk; unsigned char reg; @@ -102,18 +143,22 @@ enum cmds { cmdGetDataMode, cmdSetModeFilter, cmdSetDataModeOn, cmdSetDataModeOff, cmdGetRitEnabled, cmdGetRitValue, cmdSpecOn, cmdSpecOff, cmdDispEnable, cmdDispDisable, cmdGetRxGain, cmdSetRxRfGain, cmdGetAfGain, cmdSetAfGain, cmdGetSql, cmdSetSql, cmdGetIFShift, cmdSetIFShift, cmdGetTPBFInner, cmdSetTPBFInner, - cmdGetTPBFOuter, cmdSetTPBFOuter, cmdGetATUStatus, cmdGetPassband, cmdSetPassband, + cmdGetTPBFOuter, cmdSetTPBFOuter, cmdGetPassband, cmdSetPassband, cmdGetCwPitch, cmdGetPskTone, cmdGetRttyMark, cmdSetCwPitch, cmdSetPskTone, cmdSetRttyMark, - cmdSetATU, cmdStartATU, cmdGetSpectrumMode, - cmdGetSpectrumSpan, cmdScopeCenterMode, cmdScopeFixedMode, cmdGetPTT, cmdSetPTT,cmdPTTToggle, + cmdSetATU, cmdStartATU, cmdGetATUStatus, + cmdGetSpectrumMode, cmdGetSpectrumSpan, cmdScopeCenterMode, cmdScopeFixedMode, + cmdGetPTT, cmdSetPTT,cmdPTTToggle, cmdGetTxPower, cmdSetTxPower, cmdGetMicGain, cmdSetMicGain, cmdSetModLevel, cmdGetSpectrumRefLevel, cmdGetDuplexMode, cmdGetModInput, cmdGetModDataInput, cmdGetCurrentModLevel, cmdStartRegularPolling, cmdStopRegularPolling, cmdQueNormalSpeed, cmdGetVdMeter, cmdGetIdMeter, cmdGetSMeter, cmdGetCenterMeter, cmdGetPowerMeter, cmdGetSWRMeter, cmdGetALCMeter, cmdGetCompMeter, cmdGetTxRxMeter, - cmdGetTone, cmdGetTSQL, cmdGetDTCS, cmdGetRptAccessMode, cmdGetPreamp, cmdGetAttenuator, cmdGetAntenna, + cmdGetTone, cmdGetTSQL, cmdGetDTCS, cmdGetRptAccessMode, cmdSetTone, cmdSetTSQL, cmdSetRptAccessMode, cmdSetRptDuplexOffset, cmdGetRptDuplexOffset, + cmdSelVFO, cmdVFOSwap, cmdVFOEqualAB, cmdVFOEqualMS, + cmdGetPreamp, cmdGetAttenuator, cmdGetAntenna, cmdGetBandStackReg, cmdGetKeySpeed, cmdSetKeySpeed, cmdGetBreakMode, cmdSetBreakMode, cmdSendCW, cmdStopCW, - cmdSetTime, cmdSetDate, cmdSetUTCOffset + cmdSetTime, cmdSetDate, cmdSetUTCOffset, + cmdSetBandUp, cmdSetBandDown, cmdSetModeUp, cmdSetModeDown, cmdSetStepUp, cmdSetStepDown, cmdSetSpanUp, cmdSetSpanDown // Only used for USB Controller at the moment. }; struct commandtype {