diff --git a/CHANGELOG b/CHANGELOG index 6ba44d8..ae1a20d 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,8 +1,143 @@ # CHANGELOG +- 20210706 + + Local af gain now has anti-log audio pot taper. + + Only start audio when stream is ready + +- 20210705 + + Added transceiver adjustment window show code, for the debug button only + currently. + + Added window title text change to show radio model. Needs to be checked + cross-platform. On Linux Mint, displays: "IC-7300 -- wfview" + + Applying setup.volume within audio handler if the audio handled is an + output. Added this to the init function. + + waterfall theme is now saved. + + Added local af gain and wf length to the preferences. + +- 20210702 + fixed small error where the tx latency was not copied in the UI + +- 20210626 + Merge branch 'sequence' of gitlab.com:eliggett/wfview into sequence + + Duplicate of existing command. + + Remove unnecessary escape sequence + + Fix for fix of missing __PRETTY_FUNCTION__ + + Add __PRETTY_FUNCTION__ for compilers that don't have it. + +- 20210625 + Mode changes from the combo box now use the que. There are still other + methods to change mode which will transition shortly. + + Faster PTT + + Added PTT to the queue. + + Added unique priority insertion methods. + + Changed how commands with parameter data are added. + + Initial queued "set" command commit. Only the frequency set command is + used so far, and only for the "Frequency" tab and the tuning knob. + +- 20210624 + Quick hack for WFM forcing FIL1 always + +- 20210621 + Added polling button + + Moving to std::deque (double-ended que). + +- 20210620 + + IC-R8600 span is now received into the UI correctly. + + New unified outgoing command queue. Tested on IC-9700 and IC-718 (to + remote wfview server). CPU usage seems higher but please check your + system. + + Timing seems to be acceptable but could probably use some tweaks. + S-meter polling is 25ms for fast radios, and slower rates for slower + radios. Half-duplex serial radios receive 3x slower polling to make room + for replies. + + For Freq, Mode, etc "regular" constant polling (new feature): + + IC-9700 polling is 5 per second, IC-718 is 1-2 per second. + + Just helps keep the UI in sync with changes taking place at the rig. The + polling is slow enough that it doesn't impact anything. But quick enough + that it catches discrepencies pretty quickly. + +- 20210619 + + Added a few more slider things + + whatsnew: improved IC-R8600 + +- 20210618 + + Additional support for the IC-R8600, including wider scope spans. + + Minor change to remove some old debug code that snuck in. + + If no rig caps, then don't mess with the window! + + Added full duplex comms parameter to rigCaps. We assume half-duplex + until we receive a reply to rigID. + + Fixed accidental s-meter timing parameter change. + +- 20210617 + + Radios without spectrum do not show spectrum, and, the window properly + resizes for those controls. Also, a new key command, control-shift-d has + been added to run debug functions from any tab in the program. + +- 20210615 + + Additional code to hide/show spectrum and correcting an issue with the + rig name not populating for non-spectrum radios. + + Dynamic show/hide spectrum for rigs without this feature. + + Additional data corruption checking. + +- 20210614 + + Changed collision detection code so that we can more easily see what + message was missed. + + Added collision detection for serial commands. Collisions are aparently + frequent for true 1-wire CI-V radios. + + We now calculate polling rates immediately upon receiveCommReady for + serial connections. For network connections, we assume sane values and + modify once we receive the baud rate from the server. + + Add Neon (ARM) support to resampler + + Revert to using resampler directory rather than opus-tools submodule + +- 20210612 + + Add tooltip showing percentage of TX power when slider is moved + - 20210611 + adding a second path/way for the qcustomplot link if the first fails + Update udpserver.cpp Use global watchdog rather than per-connection diff --git a/WHATSNEW b/WHATSNEW index 898e8c1..86c24b5 100644 --- a/WHATSNEW +++ b/WHATSNEW @@ -1,7 +1,7 @@ The following highlights are in this dot-release: - added IC7700 + added IC7700, 718, 7100. (more testing needed) fixes and improvements to audio ability to choose between rtaudio and qtmultimedia (default) as compile time option fixes and lots of improvements at the usb-server end @@ -12,3 +12,5 @@ The following highlights are in this dot-release: wf display disappears when there is no wf capable rig IC R8600 support improved for older rigs added a polling timing box to keep stuff keeping smooth + Local af gain now has anti-log audio pot taper. + diff --git a/aboutbox.cpp b/aboutbox.cpp new file mode 100644 index 0000000..9f95cda --- /dev/null +++ b/aboutbox.cpp @@ -0,0 +1,111 @@ +#include "aboutbox.h" +#include "ui_aboutbox.h" + +aboutbox::aboutbox(QWidget *parent) : + QWidget(parent), + ui(new Ui::aboutbox) +{ + ui->setupUi(this); + setWindowTitle("About wfview"); + setWindowIcon(QIcon(":resources/wfview.png")); + + ui->logoBtn->setIcon(QIcon(":resources/wfview.png")); + ui->logoBtn->setStyleSheet("Text-align:left"); + + ui->topText->setText("wfview version 1.1a"); + + QString head = QString(""); + QString copyright = QString("Copyright 2017-2021 Elliott H. Liggett, W6EL. All rights reserved. wfview source code is licensed under the GNU GPLv3."); + QString nacode = QString("

Networking, audio, rigctl server, and much more written by Phil Taylor, M0VSE"); + QString doctest = QString("

Testing, documentation, bug fixes, and development mentorship from
Roeland Jansen, PA3MET, and Jim Nijkamp, PA8E."); + + + QString ssCredit = QString("

Stylesheet qdarkstyle used under MIT license, stored in /usr/share/wfview/stylesheets/."); + + QString website = QString("

Please visit https://wfview.org/ for the latest information."); + QString docs = QString("

Be sure to check the User Manual and the Forum if you have any questions."); + QString support = QString("

For support, please visit the official wfview support forum."); + QString gitcodelink = QString("").arg(GITSHORT); + + QString contact = QString("
email W6EL: kilocharlie8@gmail.com"); + + QString buildInfo = QString("

Build " + gitcodelink + QString(GITSHORT) + "
on " + QString(__DATE__) + " at " + __TIME__ + " by " + UNAME + "@" + HOST); + QString end = QString(""); + + // Short credit strings: + QString rsCredit = QString("

Speex Resample library Copyright 2003-2008 Jean-Marc Valin"); +#if defined(RTAUDIO) + QString rtaudiocredit = QString("

RT Audio, from Gary P. Scavone"); +#endif + +#if defined(PORTAUDIO) + QString portaudiocredit = QString("

Port Audio, from The Port Audio Community"); +#endif + + QString qcpcredit = QString("

The waterfall and spectrum plot graphics use QCustomPlot, from Emanuel Eichhammer"); + QString qtcredit = QString("

This copy of wfview was built against Qt version %1").arg(QT_VERSION_STR); + + // Acknowledgement: + QString wfviewcommunityack = QString("

The developers of wfview wish to thank the many contributions from the wfview community at-large, including ideas, bug reports, and fixes."); + QString kappanhangack = QString("

Special thanks to Norbert Varga, and the nonoo/kappanhang team for their initial work on the OEM protocol."); + + QString sxcreditcopyright = QString("Speex copyright notice:\ +Copyright (C) 2003 Jean-Marc Valin\n\ +Redistribution and use in source and binary forms, with or without\n\ +modification, are permitted provided that the following conditions\n\ +are met:\n\ +- Redistributions of source code must retain the above copyright\n\ +notice, this list of conditions and the following disclaimer.\n\ +- Redistributions in binary form must reproduce the above copyright\n\ +notice, this list of conditions and the following disclaimer in the\n\ +documentation and/or other materials provided with the distribution.\n\ +- Neither the name of the Xiph.org Foundation nor the names of its\n\ +contributors may be used to endorse or promote products derived from\n\ +this software without specific prior written permission.\n\ +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n\ +``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n\ +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n\ +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR\n\ +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n\ +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n\ +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n\ +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\n\ +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\n\ +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n\ +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."); + + + // String it all together: + + QString aboutText = head + copyright + "\n" + nacode + "\n" + doctest + wfviewcommunityack; + aboutText.append(website + "\n"+ docs + support + contact +"\n"); + aboutText.append("\n" + ssCredit + "\n" + rsCredit + "\n"); + +#if defined(RTAUDIO) + aboutText.append(rtaudiocredit); +#endif + +#if defined(PORTAUDIO) + aboutText.append(portaudiocredit); +#endif + + aboutText.append(kappanhangack + qcpcredit + qtcredit); + aboutText.append("

"); + aboutText.append("
" + sxcreditcopyright + "
"); + aboutText.append("

"); + + aboutText.append(end); + ui->midTextBox->setText(aboutText); + ui->bottomText->setText(buildInfo); + ui->midTextBox->setFocus(); +} + +aboutbox::~aboutbox() +{ + delete ui; +} + +void aboutbox::on_logoBtn_clicked() +{ + QDesktopServices::openUrl(QUrl("https://www.wfview.org/")); +} diff --git a/aboutbox.h b/aboutbox.h new file mode 100644 index 0000000..eac5de0 --- /dev/null +++ b/aboutbox.h @@ -0,0 +1,26 @@ +#ifndef ABOUTBOX_H +#define ABOUTBOX_H + +#include +#include + +namespace Ui { +class aboutbox; +} + +class aboutbox : public QWidget +{ + Q_OBJECT + +public: + explicit aboutbox(QWidget *parent = 0); + ~aboutbox(); + +private slots: + void on_logoBtn_clicked(); + +private: + Ui::aboutbox *ui; +}; + +#endif // ABOUTBOX_H diff --git a/aboutbox.ui b/aboutbox.ui new file mode 100644 index 0000000..1594e10 --- /dev/null +++ b/aboutbox.ui @@ -0,0 +1,74 @@ + + + aboutbox + + + + 0 + 0 + 700 + 567 + + + + Form + + + + + + + 0 + 128 + + + + + 0 + 0 + + + + + + + + 128 + 128 + + + + true + + + + + + + wfview version + + + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Noto Sans'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Detailed text here</p></body></html> + + + + + + + Build String + + + + + + + + diff --git a/audiohandler.cpp b/audiohandler.cpp index 32960e5..9b99d0a 100644 --- a/audiohandler.cpp +++ b/audiohandler.cpp @@ -76,7 +76,10 @@ bool audioHandler::init(audioSetup setupIn) tempBuf.sent = 0; - + if(!setup.isinput) + { + this->setVolume(setup.localAFgain); + } #if defined(RTAUDIO) #if !defined(Q_OS_MACX) @@ -285,7 +288,9 @@ void audioHandler::start() void audioHandler::setVolume(unsigned char volume) { - this->volume = (qreal)volume/255.0; + //this->volume = (qreal)volume/255.0; + this->volume = audiopot[volume]; + qInfo(logAudio()) << (setup.isinput ? "Input" : "Output") << "setVolume: " << volume << "(" << this->volume << ")"; } diff --git a/audiohandler.h b/audiohandler.h index 45a6f3e..4e7a3f2 100644 --- a/audiohandler.h +++ b/audiohandler.h @@ -33,7 +33,7 @@ typedef signed short MY_TYPE; #include #include "resampler/speex_resampler.h" #include "ring/ring.h" - +#include "audiotaper.h" #include @@ -67,6 +67,7 @@ struct audioSetup { QAudioDeviceInfo port; #endif quint8 resampleQuality; + unsigned char localAFgain; }; // For QtMultimedia, use a native QIODevice diff --git a/audiotaper.h b/audiotaper.h new file mode 100644 index 0000000..e1d5752 --- /dev/null +++ b/audiotaper.h @@ -0,0 +1,273 @@ +#ifndef AUDIOTAPER_H +#define AUDIOTAPER_H +#include + +const qreal audiopot[256] = +{ + 0.00000, + 0.00101, + 0.00202, + 0.00305, + 0.00409, + 0.00513, + 0.00619, + 0.00725, + 0.00832, + 0.00941, + 0.01050, + 0.01160, + 0.01272, + 0.01384, + 0.01497, + 0.01612, + 0.01727, + 0.01843, + 0.01961, + 0.02080, + 0.02199, + 0.02320, + 0.02442, + 0.02565, + 0.02689, + 0.02814, + 0.02940, + 0.03068, + 0.03196, + 0.03326, + 0.03457, + 0.03589, + 0.03723, + 0.03857, + 0.03993, + 0.04130, + 0.04268, + 0.04408, + 0.04548, + 0.04690, + 0.04834, + 0.04978, + 0.05124, + 0.05272, + 0.05420, + 0.05570, + 0.05721, + 0.05874, + 0.06028, + 0.06184, + 0.06341, + 0.06499, + 0.06659, + 0.06820, + 0.06982, + 0.07146, + 0.07312, + 0.07479, + 0.07648, + 0.07818, + 0.07990, + 0.08163, + 0.08338, + 0.08514, + 0.08692, + 0.08872, + 0.09053, + 0.09236, + 0.09421, + 0.09607, + 0.09795, + 0.09984, + 0.10176, + 0.10369, + 0.10564, + 0.10760, + 0.10959, + 0.11159, + 0.11361, + 0.11565, + 0.11770, + 0.11978, + 0.12187, + 0.12399, + 0.12612, + 0.12827, + 0.13044, + 0.13263, + 0.13484, + 0.13707, + 0.13933, + 0.14160, + 0.14389, + 0.14620, + 0.14854, + 0.15089, + 0.15327, + 0.15567, + 0.15809, + 0.16053, + 0.16299, + 0.16548, + 0.16799, + 0.17052, + 0.17307, + 0.17565, + 0.17825, + 0.18088, + 0.18353, + 0.18620, + 0.18889, + 0.19162, + 0.19436, + 0.19713, + 0.19993, + 0.20275, + 0.20560, + 0.20847, + 0.21137, + 0.21429, + 0.21725, + 0.22022, + 0.22323, + 0.22626, + 0.22932, + 0.23241, + 0.23553, + 0.23867, + 0.24184, + 0.24504, + 0.24828, + 0.25153, + 0.25482, + 0.25814, + 0.26149, + 0.26487, + 0.26828, + 0.27172, + 0.27520, + 0.27870, + 0.28224, + 0.28580, + 0.28941, + 0.29304, + 0.29670, + 0.30040, + 0.30414, + 0.30790, + 0.31170, + 0.31554, + 0.31941, + 0.32331, + 0.32725, + 0.33123, + 0.33524, + 0.33929, + 0.34338, + 0.34750, + 0.35166, + 0.35586, + 0.36009, + 0.36437, + 0.36868, + 0.37303, + 0.37742, + 0.38185, + 0.38633, + 0.39084, + 0.39539, + 0.39999, + 0.40462, + 0.40930, + 0.41402, + 0.41878, + 0.42359, + 0.42844, + 0.43333, + 0.43827, + 0.44326, + 0.44828, + 0.45336, + 0.45848, + 0.46364, + 0.46886, + 0.47412, + 0.47943, + 0.48478, + 0.49019, + 0.49564, + 0.50115, + 0.50670, + 0.51230, + 0.51796, + 0.52366, + 0.52942, + 0.53523, + 0.54110, + 0.54701, + 0.55298, + 0.55900, + 0.56508, + 0.57122, + 0.57741, + 0.58365, + 0.58995, + 0.59631, + 0.60273, + 0.60920, + 0.61574, + 0.62233, + 0.62898, + 0.63570, + 0.64247, + 0.64931, + 0.65620, + 0.66316, + 0.67019, + 0.67727, + 0.68442, + 0.69164, + 0.69892, + 0.70627, + 0.71368, + 0.72116, + 0.72871, + 0.73633, + 0.74402, + 0.75178, + 0.75960, + 0.76750, + 0.77547, + 0.78351, + 0.79163, + 0.79981, + 0.80808, + 0.81641, + 0.82483, + 0.83332, + 0.84188, + 0.85053, + 0.85925, + 0.86805, + 0.87693, + 0.88590, + 0.89494, + 0.90407, + 0.91327, + 0.92257, + 0.93194, + 0.94140, + 0.95095, + 0.96058, + 0.97030, + 0.98011, + 0.99001, + 1.00000 +}; + + + + + + + + + +#endif // AUDIOTAPER_H diff --git a/freqmemory.h b/freqmemory.h index b803f4a..96d3c6b 100644 --- a/freqmemory.h +++ b/freqmemory.h @@ -37,6 +37,7 @@ enum mode_kind { struct mode_info { mode_kind mk; unsigned char reg; + unsigned char filter; QString name; }; diff --git a/logcategories.h b/logcategories.h index a76de51..2bd780b 100644 --- a/logcategories.h +++ b/logcategories.h @@ -12,4 +12,9 @@ Q_DECLARE_LOGGING_CATEGORY(logUdp) Q_DECLARE_LOGGING_CATEGORY(logUdpServer) Q_DECLARE_LOGGING_CATEGORY(logRigCtlD) + +#if defined(Q_OS_WIN) && !defined(__PRETTY_FUNCTION__) +#define __PRETTY_FUNCTION__ __FUNCSIG__ +#endif + #endif // LOGCATEGORIES_H diff --git a/pttyhandler.cpp b/pttyhandler.cpp index 414ead2..b671aa0 100644 --- a/pttyhandler.cpp +++ b/pttyhandler.cpp @@ -117,7 +117,7 @@ void pttyHandler::receiveDataFromRigToPtty(const QByteArray& data) { int fePos=data.lastIndexOf((char)0xfe); - if (fePos>0) + if (fePos > 0 && data.length() > fePos+2) fePos=fePos-1; else { @@ -125,7 +125,14 @@ void pttyHandler::receiveDataFromRigToPtty(const QByteArray& data) printHex(data,false,true); } - if (isConnected && (unsigned char)data[fePos+2] != 0xE1 && (unsigned char)data[fePos+3] != 0xE1) + if (disableTransceive && ((unsigned char)data[fePos + 2] == 0x00 || (unsigned char)data[fePos + 3] == 0x00)) + { + // Ignore data that is sent to/from transceive address as client has requested transceive disabled. + qDebug(logSerial()) << "Transceive command filtered"; + return; + } + + if (isConnected && (unsigned char)data[fePos + 2] != 0xE1 && (unsigned char)data[fePos + 3] != 0xE1) { // send to the pseudo port as well // index 2 is dest, 0xE1 is wfview, 0xE0 is assumed to be the other device. @@ -133,7 +140,7 @@ void pttyHandler::receiveDataFromRigToPtty(const QByteArray& data) // 0xE1 = wfview // 0xE0 = pseudo-term host // 0x00 = broadcast to all - //qInfo(logSerial()) << "Sending data from radio to pseudo-terminal"; + //qInfo(logSerial()) << "Sending data from radio to pseudo-terminal"; sendDataOut(data); } } @@ -221,12 +228,16 @@ void pttyHandler::receiveDataIn(int fd) { reply[3] = inPortData[2]; sendDataOut(inPortData); // Echo command back sendDataOut(reply); + if (!disableTransceive) { + qInfo(logSerial()) << "pty requested CI-V Transceive disable"; + disableTransceive = true; + } } else if (inPortData.length() > lastFE + 2 && ((quint8)inPortData[lastFE + 1] == civId || (quint8)inPortData[lastFE + 2] == civId)) { emit haveDataFromPort(inPortData); - //qInfo(logSerial()) << "Data from pseudo term:"; - //printHex(inPortData, false, true); + qDebug(logSerial()) << "Data from pseudo term:"; + printHex(inPortData, false, true); } if (rolledBack) diff --git a/pttyhandler.h b/pttyhandler.h index ac96684..da52ef8 100644 --- a/pttyhandler.h +++ b/pttyhandler.h @@ -65,7 +65,7 @@ private: bool isConnected=false; // port opened mutable QMutex mutex; void printHex(const QByteArray& pdata, bool printVert, bool printHoriz); - + bool disableTransceive = false; QSocketNotifier *ptReader = nullptr; quint8 civId=0; }; diff --git a/rigcommander.cpp b/rigcommander.cpp index 9e8efca..6eac210 100644 --- a/rigcommander.cpp +++ b/rigcommander.cpp @@ -133,7 +133,8 @@ void rigCommander::commSetup(unsigned char rigCivAddr, udpPreferences prefs, aud connect(ptty, SIGNAL(haveSerialPortError(QString, QString)), this, SLOT(handleSerialPortError(QString, QString))); connect(this, SIGNAL(getMoreDebug()), ptty, SLOT(debugThis())); - emit haveAfGain(255); + + emit haveAfGain(rxSetup.localAFgain); } // data from the comm port to the program: @@ -665,6 +666,28 @@ void rigCommander::setRitValue(int ritValue) prepDataAndSend(payload); } +void rigCommander::setMode(mode_info m) +{ + QByteArray payload; + + if(rigCaps.model==model706) + { + m.filter = '\x01'; + } + if(m.mk == modeWFM) + { + m.filter = '\x01'; + } + + payload.setRawData("\x06", 1); + payload.append(m.reg); + payload.append(m.filter); + + prepDataAndSend(payload); + rigState.mode = m.reg; + rigState.filter = m.filter; +} + void rigCommander::setMode(unsigned char mode, unsigned char modeFilter) { QByteArray payload; @@ -683,7 +706,12 @@ void rigCommander::setMode(unsigned char mode, unsigned char modeFilter) { payload.append("\x01"); // "normal" on IC-706 } else { - payload.append(modeFilter); + if(mode == 0x06) + { + payload.append(0x01); + } else { + payload.append(modeFilter); + } } prepDataAndSend(payload); diff --git a/rigcommander.h b/rigcommander.h index ef01a54..d073484 100644 --- a/rigcommander.h +++ b/rigcommander.h @@ -119,6 +119,7 @@ public slots: void setFrequency(freqt freq); void getFrequency(); void setMode(unsigned char mode, unsigned char modeFilter); + void setMode(mode_info); void getMode(); void setDataMode(bool dataOn, unsigned char filter); void getDataMode(); diff --git a/transceiveradjustments.cpp b/transceiveradjustments.cpp new file mode 100644 index 0000000..5779f5f --- /dev/null +++ b/transceiveradjustments.cpp @@ -0,0 +1,16 @@ +#include "transceiveradjustments.h" +#include "ui_transceiveradjustments.h" + +transceiverAdjustments::transceiverAdjustments(QWidget *parent) : + QWidget(parent), + ui(new Ui::transceiverAdjustments) +{ + ui->setupUi(this); + // request level updates + +} + +transceiverAdjustments::~transceiverAdjustments() +{ + delete ui; +} diff --git a/transceiveradjustments.h b/transceiveradjustments.h new file mode 100644 index 0000000..2eee158 --- /dev/null +++ b/transceiveradjustments.h @@ -0,0 +1,22 @@ +#ifndef TRANSCEIVERADJUSTMENTS_H +#define TRANSCEIVERADJUSTMENTS_H + +#include + +namespace Ui { +class transceiverAdjustments; +} + +class transceiverAdjustments : public QWidget +{ + Q_OBJECT + +public: + explicit transceiverAdjustments(QWidget *parent = 0); + ~transceiverAdjustments(); + +private: + Ui::transceiverAdjustments *ui; +}; + +#endif // TRANSCEIVERADJUSTMENTS_H diff --git a/transceiveradjustments.ui b/transceiveradjustments.ui new file mode 100644 index 0000000..9e8bb32 --- /dev/null +++ b/transceiveradjustments.ui @@ -0,0 +1,329 @@ + + + transceiverAdjustments + + + + 0 + 0 + 680 + 339 + + + + Form + + + + + + 10 + + + 10 + + + 10 + + + 10 + + + + + Transmitter + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Qt::Vertical + + + + + + + Comp + + + + + + + + + + + Qt::Vertical + + + + + + + + 0 + 23 + + + + Bass + + + + + + + + + + + Qt::Vertical + + + + + + + + 0 + 23 + + + + Trebble + + + + + + + + + + + Qt::Vertical + + + + + + + + 0 + 23 + + + + TBD + + + + + + + + + + + + Receiver + + + + + + + + Qt::Vertical + + + + + + + + 0 + 23 + + + + Bass + + + + + + + + + + + Qt::Vertical + + + + + + + + 0 + 23 + + + + Trebble + + + + + + + + + + + Qt::Vertical + + + + + + + IF Shift + + + + + + + + + + + Qt::Vertical + + + + + + + NR + + + + + + + + + + + Qt::Vertical + + + + + + + NB + + + + + + + + + + + Qt::Vertical + + + + + + + Notch + + + + + + + + + Bandwidth + + + + + + Low + + + + + + + + + + High + + + + + + + + + + Filter + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + + + + + diff --git a/udphandler.cpp b/udphandler.cpp index a2c8e49..c320e7d 100644 --- a/udphandler.cpp +++ b/udphandler.cpp @@ -195,7 +195,7 @@ void udpHandler::dataReceived() if (txSetup.codec == 0) { txString = "(no tx)"; } - emit haveNetworkStatus(QString("
%1 rx latency: %2 ms / rtt: %3 ms / loss: %4/%5
").arg(txString).arg(tempLatency).arg(latency, 3).arg(totallost, 3).arg(totalsent, 3)); + emit haveNetworkStatus(QString("
%1 rx latency: %2 / rtt: %3 ms / loss: %4/%5
").arg(txString).arg(tempLatency).arg(latency, 3).arg(totallost, 3).arg(totalsent, 3)); } break; } @@ -1133,6 +1133,10 @@ void udpBase::dataReceived(QByteArray r) { rxBufferMutex.lock(); if (rxSeqBuf.isEmpty()) { + if (rxSeqBuf.size() > 400) + { + rxSeqBuf.erase(rxSeqBuf.begin()); + } rxSeqBuf.insert(in->seq, QTime::currentTime()); } else @@ -1153,6 +1157,10 @@ void udpBase::dataReceived(QByteArray r) { // Add incoming packet to the received buffer and if it is in the missing buffer, remove it. rxSeqBuf.insert(in->seq, QTime::currentTime()); + if (rxSeqBuf.size() > 400) + { + rxSeqBuf.erase(rxSeqBuf.begin()); + } } else { // This is probably one of our missing packets! @@ -1208,7 +1216,15 @@ void udpBase::sendRetransmitRequest() { // We haven't seen this missing packet before qDebug(logUdp()) << this->metaObject()->className() << ": Adding to missing buffer (len=" << rxMissing.size() << "): " << j; + if (rxMissing.size() > 25) + { + rxMissing.erase(rxMissing.begin()); + } rxMissing.insert(j, 0); + if (rxSeqBuf.size() > 400) + { + rxSeqBuf.erase(rxSeqBuf.begin()); + } rxSeqBuf.insert(j, QTime::currentTime()); // Add this missing packet to the rxbuffer as we now long about it. packetsLost++; } @@ -1351,11 +1367,17 @@ void udpBase::sendTrackedPacket(QByteArray d) congestion = 0; } txSeqBuf.insert(sendSeq,s); + if (txSeqBuf.size() > 400) + { + txSeqBuf.erase(txSeqBuf.begin()); + } txBufferMutex.unlock(); } else { qInfo(logUdp()) << this->metaObject()->className() << ": txBuffer mutex is locked"; } - purgeOldEntries(); // Delete entries older than PURGE_SECONDS seconds (currently 5) + // Stop using purgeOldEntries() as it is likely slower than just removing the earliest packet. + //qInfo(logUdp()) << this->metaObject()->className() << "RX:" << rxSeqBuf.size() << "TX:" <(); qRegisterMetaType(); qRegisterMetaType(); + qRegisterMetaType(); qRegisterMetaType(); qRegisterMetaType (); @@ -267,6 +270,7 @@ void wfmain::rigConnections() connect(this, SIGNAL(setScopeFixedEdge(double,double,unsigned char)), rig, SLOT(setSpectrumBounds(double,double,unsigned char))); connect(this, SIGNAL(setMode(unsigned char, unsigned char)), rig, SLOT(setMode(unsigned char, unsigned char))); + connect(this, SIGNAL(setMode(mode_info)), rig, SLOT(setMode(mode_info))); // Levels (read and write) // Levels: Query: @@ -880,6 +884,12 @@ void wfmain::setUIToPrefs() ui->drawPeakChk->setChecked(prefs.drawPeaks); on_drawPeakChk_clicked(prefs.drawPeaks); drawPeaks = prefs.drawPeaks; + + ui->wfLengthSlider->setValue(prefs.wflength); + prepareWf(prefs.wflength); + + ui->wfthemeCombo->setCurrentIndex(ui->wfthemeCombo->findData(prefs.wftheme)); + colorMap->setGradient(static_cast(prefs.wftheme)); } void wfmain::setAudioDevicesUI() @@ -1217,6 +1227,9 @@ void wfmain::setDefPrefs() defPrefs.enableRigCtlD = false; defPrefs.rigCtlPort = 4533; defPrefs.virtualSerialPort = QString("none"); + defPrefs.localAFgain = 255; + defPrefs.wflength = 160; + defPrefs.wftheme = static_cast(QCPColorGradient::gpJet); udpDefPrefs.ipAddress = QString(""); udpDefPrefs.controlLANPort = 50001; @@ -1238,7 +1251,9 @@ void wfmain::loadSettings() prefs.useFullScreen = settings->value("UseFullScreen", defPrefs.useFullScreen).toBool(); prefs.useDarkMode = settings->value("UseDarkMode", defPrefs.useDarkMode).toBool(); prefs.useSystemTheme = settings->value("UseSystemTheme", defPrefs.useSystemTheme).toBool(); + prefs.wftheme = settings->value("WFTheme", defPrefs.wftheme).toInt(); prefs.drawPeaks = settings->value("DrawPeaks", defPrefs.drawPeaks).toBool(); + prefs.wflength = (unsigned int) settings->value("WFLength", defPrefs.wflength).toInt(); prefs.stylesheetPath = settings->value("StylesheetPath", defPrefs.stylesheetPath).toString(); ui->splitter->restoreState(settings->value("splitter").toByteArray()); @@ -1322,7 +1337,8 @@ void wfmain::loadSettings() ui->vspCombo->setCurrentIndex(ui->vspCombo->count()-1); } - + prefs.localAFgain = (unsigned char) settings->value("localAFgain", defPrefs.localAFgain).toUInt(); + rxSetup.localAFgain = prefs.localAFgain; settings->endGroup(); // Misc. user settings (enable PTT, draw peaks, etc) @@ -1378,7 +1394,7 @@ void wfmain::loadSettings() txSetup.latency = settings->value("AudioTXLatency", "150").toInt(); ui->txLatencySlider->setEnabled(ui->lanEnableBtn->isChecked()); - ui->txLatencySlider->setValue(rxSetup.latency); + ui->txLatencySlider->setValue(txSetup.latency); ui->txLatencySlider->setTracking(false); // Stop it sending value on every change. ui->audioSampleRateCombo->blockSignals(true); @@ -1527,10 +1543,12 @@ void wfmain::saveSettings() settings->setValue("UseSystemTheme", prefs.useSystemTheme); settings->setValue("UseDarkMode", prefs.useDarkMode); settings->setValue("DrawPeaks", prefs.drawPeaks); + settings->setValue("WFTheme", prefs.wftheme); settings->setValue("StylesheetPath", prefs.stylesheetPath); settings->setValue("splitter", ui->splitter->saveState()); settings->setValue("windowGeometry", saveGeometry()); settings->setValue("windowState", saveState()); + settings->setValue("WFLength", prefs.wflength); settings->endGroup(); // Radio and Comms: C-IV addr, port to use @@ -1539,6 +1557,7 @@ void wfmain::saveSettings() settings->setValue("SerialPortRadio", prefs.serialPortRadio); settings->setValue("SerialPortBaud", prefs.serialPortBaud); settings->setValue("VirtualSerialPort", prefs.virtualSerialPort); + settings->setValue("localAFgain", prefs.localAFgain); settings->endGroup(); // Misc. user settings (enable PTT, draw peaks, etc) @@ -1967,7 +1986,8 @@ void wfmain::shortcutMinus() f.MHzDouble = f.Hz / (double)1E6; setUIFreq(); - emit setFrequency(f); + //emit setFrequency(f); + issueCmd(cmdSetFreq, f); issueDelayedCommandUnique(cmdGetFreq); } @@ -1980,7 +2000,8 @@ void wfmain::shortcutPlus() f.MHzDouble = f.Hz / (double)1E6; setUIFreq(); - emit setFrequency(f); + //emit setFrequency(f); + issueCmd(cmdSetFreq, f); issueDelayedCommandUnique(cmdGetFreq); } @@ -2019,7 +2040,8 @@ void wfmain::shortcutShiftMinus() f.MHzDouble = f.Hz / (double)1E6; setUIFreq(); - emit setFrequency(f); + //emit setFrequency(f); + issueCmd(cmdSetFreq, f); issueDelayedCommandUnique(cmdGetFreq); } @@ -2032,7 +2054,8 @@ void wfmain::shortcutShiftPlus() f.MHzDouble = f.Hz / (double)1E6; setUIFreq(); - emit setFrequency(f); + //emit setFrequency(f); + issueCmd(cmdSetFreq, f); issueDelayedCommandUnique(cmdGetFreq); } @@ -2045,7 +2068,8 @@ void wfmain::shortcutControlMinus() f.MHzDouble = f.Hz / (double)1E6; setUIFreq(); - emit setFrequency(f); + //emit setFrequency(f); + issueCmd(cmdSetFreq, f); issueDelayedCommandUnique(cmdGetFreq); } @@ -2058,7 +2082,8 @@ void wfmain::shortcutControlPlus() f.MHzDouble = f.Hz / (double)1E6; setUIFreq(); - emit setFrequency(f); + //emit setFrequency(f); + issueCmd(cmdSetFreq, f); issueDelayedCommandUnique(cmdGetFreq); } @@ -2071,7 +2096,8 @@ void wfmain::shortcutPageUp() f.MHzDouble = f.Hz / (double)1E6; setUIFreq(); - emit setFrequency(f); + //emit setFrequency(f); + issueCmd(cmdSetFreq, f); issueDelayedCommandUnique(cmdGetFreq); } @@ -2084,7 +2110,8 @@ void wfmain::shortcutPageDown() f.MHzDouble = f.Hz / (double)1E6; setUIFreq(); - emit setFrequency(f); + //emit setFrequency(f); + issueCmd(cmdSetFreq, f); issueDelayedCommandUnique(cmdGetFreq); } @@ -2311,6 +2338,90 @@ void wfmain::setPlotTheme(QCustomPlot *plot, bool isDark) } } +void wfmain::doCmd(commandtype cmddata) +{ + cmds cmd = cmddata.cmd; + std::shared_ptr data = cmddata.data; + + // This switch is for commands with parameters. + // the "default" for non-parameter commands is to call doCmd(cmd). + switch (cmd) + { + case cmdSetFreq: + { + freqt f = (*std::static_pointer_cast(data)); + emit setFrequency(f); + break; + } + case cmdSetMode: + { + mode_info m = (*std::static_pointer_cast(data)); + emit setMode(m); + break; + } + case cmdSetTxPower: + { + unsigned char txpower = (*std::static_pointer_cast(data)); + emit setTxPower(txpower); + break; + } + case cmdSetMicGain: + { + unsigned char micgain = (*std::static_pointer_cast(data)); + emit setTxPower(micgain); + break; + } + case cmdSetRxRfGain: + { + unsigned char rfgain = (*std::static_pointer_cast(data)); + emit setRfGain(rfgain); + break; + } + case cmdSetModLevel: + { + unsigned char modlevel = (*std::static_pointer_cast(data)); + rigInput currentIn; + if(usingDataMode) + { + currentIn = currentModDataSrc; + } else { + currentIn = currentModSrc; + } + emit setModLevel(currentIn, modlevel); + break; + } + case cmdSetAfGain: + { + unsigned char afgain = (*std::static_pointer_cast(data)); + emit setAfGain(afgain); + break; + } + case cmdSetSql: + { + unsigned char sqlLevel = (*std::static_pointer_cast(data)); + emit setSql(sqlLevel); + break; + } + case cmdSetPTT: + { + bool pttrequest = (*std::static_pointer_cast(data)); + emit setPTT(pttrequest); + break; + } + case cmdSetATU: + { + bool atuOn = (*std::static_pointer_cast(data)); + emit setATU(atuOn); + break; + } + default: + doCmd(cmd); + break; + } + +} + + void wfmain::doCmd(cmds cmd) { // Use this function to take action upon a command. @@ -2420,6 +2531,9 @@ void wfmain::doCmd(cmds cmd) case cmdGetATUStatus: emit getATUStatus(); break; + case cmdStartATU: + emit startATU(); + break; case cmdGetAttenuator: emit getAttenuator(); break; @@ -2484,6 +2598,7 @@ void wfmain::doCmd(cmds cmd) } break; default: + qInfo(logSystem()) << __PRETTY_FUNCTION__ << "WARNING: Command fell through of type: " << (unsigned int)cmd; break; } } @@ -2498,9 +2613,9 @@ void wfmain::sendRadioCommandLoop() // if ther's a command waiting, run it. if(!delayedCmdQue.empty()) { - cmds cmd = delayedCmdQue.front(); + commandtype cmddata = delayedCmdQue.front(); delayedCmdQue.pop_front(); - doCmd(cmd); + doCmd(cmddata); } else if(!(loopTickCounter % 10)) { // pick from useful queries to make now and then @@ -2528,14 +2643,20 @@ void wfmain::sendRadioCommandLoop() void wfmain::issueDelayedCommand(cmds cmd) { // Append to end of command queue - delayedCmdQue.push_back(cmd); + commandtype cmddata; + cmddata.cmd = cmd; + cmddata.data = NULL; + delayedCmdQue.push_back(cmddata); } void wfmain::issueDelayedCommandPriority(cmds cmd) { // Places the new command at the top of the queue // Use only when needed. - delayedCmdQue.push_front(cmd); + commandtype cmddata; + cmddata.cmd = cmd; + cmddata.data = NULL; + delayedCmdQue.push_front(cmddata); } void wfmain::issueDelayedCommandUnique(cmds cmd) @@ -2543,11 +2664,133 @@ void wfmain::issueDelayedCommandUnique(cmds cmd) // Use this function to insert commands where // multiple (redundant) commands don't make sense. - if( std::find(delayedCmdQue.begin(), delayedCmdQue.end(), cmd ) == delayedCmdQue.end()) + commandtype cmddata; + cmddata.cmd = cmd; + cmddata.data = NULL; + + // The following is both expensive and not that great, + // since it does not check if the arguments are the same. + bool found = false; + for(unsigned int i=0; i < delayedCmdQue.size(); i++) { - delayedCmdQue.push_front(cmd); + if(delayedCmdQue.at(i).cmd == cmd) + { + found = true; + break; + } } + if(!found) + { + delayedCmdQue.push_front(cmddata); + } + +// if( std::find(delayedCmdQue.begin(), delayedCmdQue.end(), cmddata ) == delayedCmdQue.end()) +// { +// delayedCmdQue.push_front(cmddata); +// } + +} + +void wfmain::issueCmd(cmds cmd, mode_info m) +{ + commandtype cmddata; + cmddata.cmd = cmd; + cmddata.data = std::shared_ptr(new mode_info(m)); + delayedCmdQue.push_back(cmddata); +} + +void wfmain::issueCmd(cmds cmd, freqt f) +{ + commandtype cmddata; + cmddata.cmd = cmd; + cmddata.data = std::shared_ptr(new freqt(f)); + //*static_cast(cmddata.data.get()) = f; + delayedCmdQue.push_back(cmddata); +} + +void wfmain::issueCmd(cmds cmd, int i) +{ + commandtype cmddata; + cmddata.cmd = cmd; + cmddata.data = std::shared_ptr(new int(i)); + delayedCmdQue.push_back(cmddata); +} + +void wfmain::issueCmd(cmds cmd, char c) +{ + commandtype cmddata; + cmddata.cmd = cmd; + cmddata.data = std::shared_ptr(new char(c)); + delayedCmdQue.push_back(cmddata); +} + +void wfmain::issueCmd(cmds cmd, bool b) +{ + commandtype cmddata; + cmddata.cmd = cmd; + cmddata.data = std::shared_ptr(new bool(b)); + delayedCmdQue.push_back(cmddata); +} + +void wfmain::issueCmd(cmds cmd, unsigned char c) +{ + commandtype cmddata; + cmddata.cmd = cmd; + cmddata.data = std::shared_ptr(new unsigned char(c)); + delayedCmdQue.push_back(cmddata); +} + +void wfmain::issueCmdUniquePriority(cmds cmd, bool b) +{ + commandtype cmddata; + cmddata.cmd = cmd; + cmddata.data = std::shared_ptr(new bool(b)); + delayedCmdQue.push_front(cmddata); + removeSimilarCommand(cmd); +} + +void wfmain::issueCmdUniquePriority(cmds cmd, unsigned char c) +{ + commandtype cmddata; + cmddata.cmd = cmd; + cmddata.data = std::shared_ptr(new unsigned char(c)); + delayedCmdQue.push_front(cmddata); + removeSimilarCommand(cmd); +} + +void wfmain::issueCmdUniquePriority(cmds cmd, char c) +{ + commandtype cmddata; + cmddata.cmd = cmd; + cmddata.data = std::shared_ptr(new char(c)); + delayedCmdQue.push_front(cmddata); + removeSimilarCommand(cmd); +} + +void wfmain::issueCmdUniquePriority(cmds cmd, freqt f) +{ + commandtype cmddata; + cmddata.cmd = cmd; + cmddata.data = std::shared_ptr(new freqt(f)); + delayedCmdQue.push_front(cmddata); + removeSimilarCommand(cmd); +} + +void wfmain::removeSimilarCommand(cmds cmd) +{ + // pop anything out that is of the same kind of command: + // pop anything out that is of the same kind of command: + // Start at 1 since we put one in at zero that we want to keep. + for(unsigned int i=1; i < delayedCmdQue.size(); i++) + { + if(delayedCmdQue.at(i).cmd == cmd) + { + //delayedCmdQue[i].cmd = cmdNone; + delayedCmdQue.erase(delayedCmdQue.begin()+i); + // i -= 1; + } + } } void wfmain::receiveRigID(rigCapabilities rigCaps) @@ -2570,6 +2813,7 @@ void wfmain::receiveRigID(rigCapabilities rigCaps) this->rigCaps = rigCaps; rigName->setText(rigCaps.modelName); + setWindowTitle(rigCaps.modelName); this->spectWidth = rigCaps.spectLenMax; // used once haveRigCaps is true. haveRigCaps = true; // Added so that server receives rig capabilities. @@ -2691,14 +2935,17 @@ void wfmain::receiveRigID(rigCapabilities rigCaps) } ui->scopeBWCombo->blockSignals(false); - setBandButtons(); ui->tuneEnableChk->setEnabled(rigCaps.hasATU); ui->tuneNowBtn->setEnabled(rigCaps.hasATU); ui->connectBtn->setText("Disconnect"); // We must be connected now. - prepareWf(); + prepareWf(ui->wfLengthSlider->value()); + if(usingLAN) + { + ui->afGainSlider->setValue(prefs.localAFgain); + } // Adding these here because clearly at this point we have valid // rig comms. In the future, we should establish comms and then // do all the initial grabs. For now, this hack of adding them here and there: @@ -2915,7 +3162,8 @@ void wfmain::handlePlotDoubleClick(QMouseEvent *me) freq.Hz = roundFrequency(freq.Hz, tsWfScrollHz); - emit setFrequency(freq); + //emit setFrequency(freq); + issueCmd(cmdSetFreq, freq); issueDelayedCommand(cmdGetFreq); showStatusBarText(QString("Going to %1 MHz").arg(x)); } @@ -2936,7 +3184,8 @@ void wfmain::handleWFDoubleClick(QMouseEvent *me) freq.Hz = roundFrequency(freq.Hz, tsWfScrollHz); - emit setFrequency(freq); + //emit setFrequency(freq); + issueCmd(cmdSetFreq, freq); issueDelayedCommand(cmdGetFreq); showStatusBarText(QString("Going to %1 MHz").arg(x)); } @@ -2989,7 +3238,8 @@ void wfmain::handleWFScroll(QWheelEvent *we) f.MHzDouble = f.Hz / (double)1E6; freq = f; - emit setFrequency(f); + //emit setFrequency(f); + issueCmdUniquePriority(cmdSetFreq, f); ui->freqLabel->setText(QString("%1").arg(f.MHzDouble, 0, 'f')); issueDelayedCommandUnique(cmdGetFreq); } @@ -3120,7 +3370,9 @@ void wfmain::on_goFreqBtn_clicked() if(ok) { f.Hz = freq*1E6; - emit setFrequency(f); + //emit setFrequency(f); + issueCmd(cmdSetFreq, f); + //issueCmdSetFreq(f); issueDelayedCommand(cmdGetFreq); } } else { @@ -3128,7 +3380,9 @@ void wfmain::on_goFreqBtn_clicked() if(ok) { f.Hz = KHz*1E3; - emit setFrequency(f); + //issueCmdSetFreq(f); + //emit setFrequency(f); + issueCmd(cmdSetFreq, f); issueDelayedCommand(cmdGetFreq); } } @@ -3288,17 +3542,35 @@ void wfmain::on_modeSelectCombo_activated(int index) // The "acticvated" signal means the user initiated a mode change. // This function is not called if code initated the change. + mode_info mode; unsigned char newMode = static_cast(ui->modeSelectCombo->itemData(index).toUInt()); currentModeIndex = newMode; + mode.reg = newMode; + int filterSelection = ui->modeFilterCombo->currentData().toInt(); if(filterSelection == 99) { // oops, we forgot to reset the combo box + return; } else { //qInfo(logSystem()) << __func__ << " at index " << index << " has newMode: " << newMode; currentMode = (mode_kind)newMode; - emit setMode(newMode, filterSelection); + mode.filter = filterSelection; + mode.name = ui->modeSelectCombo->currentText(); // for debug + + for(unsigned int i=0; i < rigCaps.modes.size(); i++) + { + if(rigCaps.modes.at(i).reg == newMode) + { + mode.mk = rigCaps.modes.at(i).mk; + break; + } + } + + issueCmd(cmdSetMode, mode); + currentModeInfo = mode; + //emit setMode(newMode, filterSelection); } } @@ -3383,9 +3655,8 @@ void wfmain::on_freqDial_valueChanged(int value) ui->freqLabel->setText(QString("%1").arg(f.MHzDouble, 0, 'f')); - emit setFrequency(f); - } - else { + issueCmdUniquePriority(cmdSetFreq, f); + } else { ui->freqDial->blockSignals(true); ui->freqDial->setValue(oldFreqDialVal); ui->freqDial->blockSignals(false); @@ -3398,7 +3669,8 @@ void wfmain::receiveBandStackReg(freqt freq, char mode, char filter, bool dataOn // read the band stack and apply by sending out commands qInfo(logSystem()) << __func__ << "BSR received into main: Freq: " << freq.Hz << ", mode: " << (unsigned int)mode << ", filter: " << (unsigned int)filter << ", data mode: " << dataOn; - emit setFrequency(freq); + //emit setFrequency(freq); + issueCmd(cmdSetFreq, freq); setModeVal = (unsigned char) mode; setFilterVal = (unsigned char) filter; @@ -3464,9 +3736,10 @@ void wfmain::on_band4mbtn_clicked() } else { f.Hz = (70.200) * 1E6; } - emit setFrequency(f); - issueDelayedCommandUnique(cmdGetFreq); - ui->tabWidget->setCurrentIndex(0); + issueCmd(cmdSetFreq, f); + //emit setFrequency(f); + issueDelayedCommandUnique(cmdGetFreq); + ui->tabWidget->setCurrentIndex(0); } void wfmain::on_band6mbtn_clicked() @@ -3530,7 +3803,8 @@ void wfmain::on_band60mbtn_clicked() // clutter the UI with 60M channel buttons... freqt f; f.Hz = (5.3305) * 1E6; - emit setFrequency(f); + issueCmd(cmdSetFreq, f); + //emit setFrequency(f); issueDelayedCommandUnique(cmdGetFreq); ui->tabWidget->setCurrentIndex(0); } @@ -3551,7 +3825,8 @@ void wfmain::on_band630mbtn_clicked() { freqt f; f.Hz = 475 * 1E3; - emit setFrequency(f); + //emit setFrequency(f); + issueCmd(cmdSetFreq, f); issueDelayedCommandUnique(cmdGetFreq); ui->tabWidget->setCurrentIndex(0); } @@ -3560,7 +3835,8 @@ void wfmain::on_band2200mbtn_clicked() { freqt f; f.Hz = 136 * 1E3; - emit setFrequency(f); + //emit setFrequency(f); + issueCmd(cmdSetFreq, f); issueDelayedCommandUnique(cmdGetFreq); ui->tabWidget->setCurrentIndex(0); } @@ -3575,58 +3851,9 @@ void wfmain::on_bandGenbtn_clicked() void wfmain::on_aboutBtn_clicked() { - QMessageBox msgBox(this); - msgBox.setWindowTitle("Abou wfview"); - msgBox.setTextFormat(Qt::RichText); - msgBox.setWindowIcon(QIcon(":resources/wfview.png")); - // TODO: change style of link color based on current CSS sheet. + abtBox->show(); - QString head = QString(""); - QString copyright = QString("Copyright 2017-2021 Elliott H. Liggett, W6EL. All rights reserved."); - QString nacode = QString("

Networking and audio code written by Phil Taylor, M0VSE"); - QString doctest = QString("

Testing, documentation, bug fixes, and development mentorship from
Roeland Jansen, PA3MET, and Jim Nijkamp, PA8E."); - QString ssCredit = QString("

Stylesheet qdarkstyle used under MIT license, stored in /usr/share/wfview/stylesheets/."); - QString rsCredit = QString("

Speex Resample library Copyright 2003-2008 Jean-Marc Valin"); - QString website = QString("

Please visit https://wfview.org/ for the latest information."); - QString docs = QString("

Be sure to check the User Manual and the Forum if you have any questions."); - QString gitcodelink = QString("").arg(GITSHORT); - - QString contact = QString("
email the author: kilocharlie8@gmail.com or W6EL on the air!"); - - QString buildInfo = QString("

Build " + gitcodelink + QString(GITSHORT) + "
on " + QString(__DATE__) + " at " + __TIME__ + " by " + UNAME + "@" + HOST); - QString end = QString(""); - - QString aboutText = head + copyright + "\n" + nacode + "\n" + doctest + "\n" + ssCredit + "\n" + rsCredit + "\n"; - aboutText.append(website + "\n"+ docs + contact +"\n" + buildInfo + end); - - msgBox.setText(aboutText); - msgBox.exec(); - - volatile QString sxcreditcopyright = QString("Speex copyright notice:\ -Copyright (C) 2003 Jean-Marc Valin\n\ -Redistribution and use in source and binary forms, with or without\ -modification, are permitted provided that the following conditions\ -are met:\n\ -- Redistributions of source code must retain the above copyright\ -notice, this list of conditions and the following disclaimer.\n\ -- Redistributions in binary form must reproduce the above copyright\ -notice, this list of conditions and the following disclaimer in the\ -documentation and/or other materials provided with the distribution.\n\ -- Neither the name of the Xiph.org Foundation nor the names of its\ -contributors may be used to endorse or promote products derived from\ -this software without specific prior written permission.\n\ -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\ -``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\ -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\ -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR\ -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\ -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\ -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\ -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\ -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\ -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\ -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."); } @@ -3688,13 +3915,17 @@ void wfmain::on_fRclBtn_clicked() void wfmain::on_rfGainSlider_valueChanged(int value) { - emit setRfGain((unsigned char) value); + issueCmdUniquePriority(cmdSetRxRfGain, (unsigned char) value); } void wfmain::on_afGainSlider_valueChanged(int value) { - // qInfo(logSystem()) << "Setting AF gain to " << value; - emit setAfGain((unsigned char)value); + issueCmdUniquePriority(cmdSetAfGain, (unsigned char)value); + if(usingLAN) + { + rxSetup.localAFgain = (unsigned char)(value); + prefs.localAFgain = (unsigned char)(value); + } } void wfmain::receiveRfGain(unsigned char level) @@ -3720,14 +3951,14 @@ void wfmain::receiveSql(unsigned char level) void wfmain::on_tuneNowBtn_clicked() { - emit startATU(); + issueDelayedCommand(cmdStartATU); showStatusBarText("Starting ATU tuning cycle..."); issueDelayedCommand(cmdGetATUStatus); } void wfmain::on_tuneEnableChk_clicked(bool checked) { - emit setATU(checked); + issueCmd(cmdSetATU, checked); if(checked) { showStatusBarText("Turning on ATU"); @@ -3754,7 +3985,7 @@ void wfmain::on_pttOnBtn_clicked() // Are we already PTT? Not a big deal, just send again anyway. showStatusBarText("Sending PTT ON command. Use Control-R to receive."); - emit setPTT(true); + issueCmdUniquePriority(cmdSetPTT, true); // send PTT // Start 3 minute timer pttTimer->start(); @@ -3765,7 +3996,7 @@ void wfmain::on_pttOffBtn_clicked() { // Send the PTT OFF command (more than once?) showStatusBarText("Sending PTT OFF command"); - emit setPTT(false); + issueCmdUniquePriority(cmdSetPTT, false); // Stop the 3 min timer pttTimer->stop(); @@ -3776,7 +4007,7 @@ void wfmain::handlePttLimit() { // transmission time exceeded! showStatusBarText("Transmit timeout at 3 minutes. Sending PTT OFF command now."); - emit setPTT(false); + issueCmdUniquePriority(cmdSetPTT, false); issueDelayedCommand(cmdGetPTT); } @@ -3976,7 +4207,8 @@ void wfmain::on_udpServerSetupBtn_clicked() } void wfmain::on_sqlSlider_valueChanged(int value) { - emit setSql((unsigned char)value); + issueCmd(cmdSetSql, (unsigned char)value); + //emit setSql((unsigned char)value); } void wfmain::on_modeFilterCombo_activated(int index) @@ -4029,18 +4261,18 @@ void wfmain::on_transmitBtn_clicked() // Are we already PTT? Not a big deal, just send again anyway. showStatusBarText("Sending PTT ON command. Use Control-R to receive."); - emit setPTT(true); + issueCmdUniquePriority(cmdSetPTT, true); // send PTT // Start 3 minute timer pttTimer->start(); - issueDelayedCommandPriority(cmdGetPTT); + issueDelayedCommand(cmdGetPTT); //changeTxBtn(); } else { // Currently transmitting - emit setPTT(false); + issueCmdUniquePriority(cmdSetPTT, false); pttTimer->stop(); - issueDelayedCommandPriority(cmdGetPTT); + issueDelayedCommand(cmdGetPTT); } } @@ -4068,7 +4300,7 @@ void wfmain::statusFromSliderRaw(QString name, int rawValue) void wfmain::statusFromSliderPercent(QString name, int rawValue) { - showStatusBarText(name + QString(": %1\%").arg((int)(100*rawValue/255.0))); + showStatusBarText(name + QString(": %1%").arg((int)(100*rawValue/255.0))); } void wfmain::receiveTxPower(unsigned char power) @@ -4267,7 +4499,8 @@ void wfmain::receiveAntiVoxGain(unsigned char antiVoxGain) void wfmain::on_txPowerSlider_valueChanged(int value) { - emit setTxPower(value); + issueCmdUniquePriority(cmdSetTxPower, (unsigned char)value); + //emit setTxPower(value); } void wfmain::on_micGainSlider_valueChanged(int value) @@ -4326,7 +4559,6 @@ void wfmain::on_modInputDataCombo_activated(int index) (void)index; } - void wfmain::changeModLabelAndSlider(rigInput source) { changeModLabel(source, true); @@ -4337,7 +4569,6 @@ void wfmain::changeModLabel(rigInput input) changeModLabel(input, false); } - void wfmain::changeModLabel(rigInput input, bool updateLevel) { QString inputName; @@ -4384,16 +4615,7 @@ void wfmain::changeModLabel(rigInput input, bool updateLevel) void wfmain::processChangingCurrentModLevel(unsigned char level) { // slider moved, so find the current mod and issue the level set command. - rigInput currentIn; - if(usingDataMode) - { - currentIn = currentModDataSrc; - } else { - currentIn = currentModSrc; - } - //qInfo(logSystem()) << __func__ << ": setting current level: " << level; - - emit setModLevel(currentIn, level); + issueCmd(cmdSetModLevel, level); } void wfmain::on_tuneLockChk_clicked(bool checked) @@ -4465,6 +4687,7 @@ void wfmain::on_antennaSelCombo_activated(int index) void wfmain::on_wfthemeCombo_activated(int index) { colorMap->setGradient(static_cast(ui->wfthemeCombo->itemData(index).toInt())); + prefs.wftheme = ui->wfthemeCombo->itemData(index).toInt(); } void wfmain::receivePreamp(unsigned char pre) @@ -4797,6 +5020,7 @@ void wfmain::on_baudRateCombo_activated(int index) void wfmain::on_wfLengthSlider_valueChanged(int value) { + prefs.wflength = (unsigned int)(value); prepareWf(value); } @@ -4818,6 +5042,6 @@ void wfmain::on_pollingBtn_clicked() void wfmain::on_debugBtn_clicked() { qInfo(logSystem()) << "Debug button pressed."; - emit getFrequency(); + trxadj->show(); } diff --git a/wfmain.h b/wfmain.h index fcd3b58..a993a28 100644 --- a/wfmain.h +++ b/wfmain.h @@ -22,16 +22,19 @@ #include "calibrationwindow.h" #include "repeatersetup.h" #include "satellitesetup.h" +#include "transceiveradjustments.h" #include "udpserversetup.h" #include "udpserver.h" #include "qledlabel.h" #include "rigctld.h" +#include "aboutbox.h" #include #include #include "shuttle.h" #include +#include namespace Ui { class wfmain; @@ -60,6 +63,7 @@ signals: void setFrequency(freqt freq); void getMode(); void setMode(unsigned char modeIndex, unsigned char modeFilter); + void setMode(mode_info); void setDataMode(bool dataOn, unsigned char filter); void getDataMode(); void getModInput(bool dataOn); @@ -591,19 +595,41 @@ private: unsigned char setModeVal=0; unsigned char setFilterVal=0; - enum cmds {cmdNone, cmdGetRigID, cmdGetRigCIV, cmdGetFreq, cmdGetMode, cmdGetDataMode, cmdSetModeFilter, + enum cmds {cmdNone, cmdGetRigID, cmdGetRigCIV, cmdGetFreq, cmdSetFreq, cmdGetMode, cmdSetMode, cmdGetDataMode, cmdSetModeFilter, cmdSetDataModeOn, cmdSetDataModeOff, cmdGetRitEnabled, cmdGetRitValue, - cmdSpecOn, cmdSpecOff, cmdDispEnable, cmdDispDisable, cmdGetRxGain, cmdGetAfGain, - cmdGetSql, cmdGetATUStatus, cmdGetSpectrumMode, cmdGetSpectrumSpan, cmdScopeCenterMode, cmdScopeFixedMode, cmdGetPTT, - cmdGetTxPower, cmdGetMicGain, cmdGetSpectrumRefLevel, cmdGetDuplexMode, cmdGetModInput, cmdGetModDataInput, + cmdSpecOn, cmdSpecOff, cmdDispEnable, cmdDispDisable, cmdGetRxGain, cmdSetRxRfGain, cmdGetAfGain, cmdSetAfGain, + cmdGetSql, cmdSetSql, cmdGetATUStatus, cmdSetATU, cmdStartATU, cmdGetSpectrumMode, cmdGetSpectrumSpan, cmdScopeCenterMode, cmdScopeFixedMode, cmdGetPTT, cmdSetPTT, + cmdGetTxPower, cmdSetTxPower, cmdGetMicGain, cmdSetMicGain, cmdSetModLevel, cmdGetSpectrumRefLevel, cmdGetDuplexMode, cmdGetModInput, cmdGetModDataInput, cmdGetCurrentModLevel, cmdStartRegularPolling, cmdStopRegularPolling, cmdQueNormalSpeed, cmdGetVdMeter, cmdGetIdMeter, cmdGetSMeter, cmdGetPowerMeter, cmdGetALCMeter, cmdGetCompMeter, cmdGetTxRxMeter, cmdGetTone, cmdGetTSQL, cmdGetDTCS, cmdGetRptAccessMode, cmdGetPreamp, cmdGetAttenuator, cmdGetAntenna}; - std::deque delayedCmdQue; - std::deque periodicCmdQueue; - std::deque slowPollCmdQueue; + struct commandtype { + cmds cmd; + std::shared_ptr data; + }; + + std::deque delayedCmdQue; // rapid que for commands to the radio + std::deque periodicCmdQueue; // rapid que for metering + std::deque slowPollCmdQueue; // slow, regular checking for UI sync void doCmd(cmds cmd); + void doCmd(commandtype cmddata); + + void issueCmd(cmds cmd, freqt f); + void issueCmd(cmds cmd, mode_info m); + void issueCmd(cmds cmd, int i); + void issueCmd(cmds cmd, unsigned char c); + void issueCmd(cmds cmd, char c); + void issueCmd(cmds cmd, bool b); + + // These commands pop_front and remove similar commands: + void issueCmdUniquePriority(cmds cmd, bool b); + void issueCmdUniquePriority(cmds cmd, unsigned char c); + void issueCmdUniquePriority(cmds cmd, char c); + void issueCmdUniquePriority(cmds cmd, freqt f); + + void removeSimilarCommand(cmds cmd); + int pCmdNum = 0; int delayedCmdIntervalLAN_ms = 100; int delayedCmdIntervalSerial_ms = 100; @@ -653,6 +679,10 @@ private: quint16 rigCtlPort; colors colorScheme; QString virtualSerialPort; + unsigned char localAFgain; + unsigned int wflength; + int wftheme; + // plot scheme } prefs; preferences defPrefs; @@ -708,6 +738,7 @@ private: rigInput currentModSrc = inputUnknown; rigInput currentModDataSrc = inputUnknown; mode_kind currentMode = modeUSB; + mode_info currentModeInfo; bool haveRigCaps; bool amTransmitting; @@ -723,7 +754,10 @@ private: calibrationWindow *cal; repeaterSetup *rpt; satelliteSetup *sat; + transceiverAdjustments *trxadj; udpServerSetup *srv; + aboutbox *abtBox; + udpServer* udp = Q_NULLPTR; rigCtlD* rigCtl = Q_NULLPTR; @@ -763,6 +797,7 @@ private: Q_DECLARE_METATYPE(struct rigCapabilities) Q_DECLARE_METATYPE(struct freqt) +Q_DECLARE_METATYPE(struct mode_info) Q_DECLARE_METATYPE(struct udpPreferences) Q_DECLARE_METATYPE(struct rigStateStruct) Q_DECLARE_METATYPE(struct audioPacket) diff --git a/wfview.pro b/wfview.pro index 45250b8..bb53289 100644 --- a/wfview.pro +++ b/wfview.pro @@ -134,6 +134,8 @@ SOURCES += main.cpp\ rigctld.cpp \ ring/ring.cpp \ shuttle.cpp + transceiveradjustments.cpp \ + aboutbox.cpp HEADERS += wfmain.h \ commhandler.h \ @@ -160,13 +162,17 @@ HEADERS += wfmain.h \ ulaw.h \ ring/ring.h \ shuttle.h - + transceiveradjustments.h \ + audiotaper.h \ + aboutbox.h FORMS += wfmain.ui \ calibrationwindow.ui \ satellitesetup.ui \ udpserversetup.ui \ - repeatersetup.ui + repeatersetup.ui \ + transceiveradjustments.ui \ + aboutbox.ui