From c133a848894944954048d377cd867cb1a26435d2 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Mon, 16 Nov 2020 02:32:06 +0000 Subject: [PATCH 01/75] Repair strict standard callsign regexp --- Radio.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Radio.cpp b/Radio.cpp index 56b943739..79b332fbd 100644 --- a/Radio.cpp +++ b/Radio.cpp @@ -22,7 +22,7 @@ namespace Radio QRegularExpression valid_callsign_regexp {R"(\d[[:alpha:]]|[[:alpha:]]\d)"}; // standard callsign - QRegularExpression strict_standard_callsign_re {R"(^([A-Z][0-9]?|[0-9][A-Z])[0-9][A-Z]{0,3}$)"}; + QRegularExpression strict_standard_callsign_re {R"(^([A-Z][0-9]?|[0-9A-Z][A-Z])[0-9][A-Z]{0,3}$)"}; // suffixes that are often used and should not be interpreted as a // DXCC Entity prefix used as a suffix From 46a6b75944f478c8943ba3c2b7f1d0e349fbe049 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Mon, 16 Nov 2020 03:07:35 +0000 Subject: [PATCH 02/75] Repair User Guide file name, asciidoctor macros, web fetch URL --- doc/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt index 9b48ced82..40d8b27fd 100644 --- a/doc/CMakeLists.txt +++ b/doc/CMakeLists.txt @@ -197,7 +197,7 @@ function (document) -a data-uri! -a VERSION_MAJOR=${WSJTX_VERSION_MAJOR} -a VERSION_MINOR=${WSJTX_VERSION_MINOR} - -a VERSION_PATCH=${WSJTX_VERSION_PATCH} + -a VERSION_PATCH=${WSJTX_VERSION_PATCH}${BUILD_TYPE_REVISION} -a VERSION=${wsjtx_VERSION} -D ${CMAKE_CURRENT_BINARY_DIR} -o ${_docbook_file} ${_source_name} From 33c14aa4004d2be6d5537f1a311b40596a5a47ce Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Mon, 16 Nov 2020 13:06:38 +0000 Subject: [PATCH 03/75] Doc updates --- doc/building on MS Windows.txt | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/doc/building on MS Windows.txt b/doc/building on MS Windows.txt index 9e954285c..42ea8d0e5 100644 --- a/doc/building on MS Windows.txt +++ b/doc/building on MS Windows.txt @@ -43,7 +43,7 @@ CMake ----- Download and install a recent version from the official CMake web -site. A default installation is fine. I am currently using v3.18.3, +site. A default installation is fine. I am currently using v3.18.4, versions as old as v3.9 should work. Other tools and libraries without installers @@ -59,8 +59,10 @@ FFTW v3 DFT library ------------------- The MS Windows builds of FFTW3 can be downloaded from -http://www.fftw.org/install/windows.html and unzipped into C:\Tools. -You only need the 64-bit package. +http://www.fftw.org/install/windows.html. The ZIP archives for this +package have no directory structure so create a directory under C:\ +Tools\ called fftw-3.3.5-dll64 and unzip the archive there. You only +need the 64-bit package. libusb library -------------- From b98746ffc921e5ed1721259a6ae6d9213eb768e5 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Mon, 16 Nov 2020 13:14:51 +0000 Subject: [PATCH 04/75] Installation and build documentation updates --- INSTALL | 8 ++++---- doc/user_guide/en/install-linux.adoc | 5 +++-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/INSTALL b/INSTALL index c96e7d3b3..02e0429e3 100644 --- a/INSTALL +++ b/INSTALL @@ -23,10 +23,10 @@ Building from Source ==================== On Linux systems some of the prerequisite libraries are available in -the mainstream distribution repositories. They are Qt v5 and FFTW v3. -For MS Windows see the section "Building from Source on MS Windows" -below. For Apple Mac see the section "Building from Source on Apple -Mac". +the mainstream distribution repositories. They are Qt v5, FFTW v3, and +the Boost C++ libraries. For MS Windows see the section "Building +from Source on MS Windows" below. For Apple Mac see the section +"Building from Source on Apple Mac". Qt v5, preferably v5.9 or later is required to build WSJT-X. diff --git a/doc/user_guide/en/install-linux.adoc b/doc/user_guide/en/install-linux.adoc index bbd53b2b9..ff108ef34 100644 --- a/doc/user_guide/en/install-linux.adoc +++ b/doc/user_guide/en/install-linux.adoc @@ -43,7 +43,8 @@ You may also need to execute the following command in a terminal: .... sudo apt install libgfortran5 libqt5widgets5 libqt5network5 \ libqt5printsupport5 libqt5multimedia5-plugins libqt5serialport5 \ - libqt5sql5-sqlite libfftw3-single3 libgomp1 libusb-1.0-0 + libqt5sql5-sqlite libfftw3-single3 libgomp1 libboost-all-dev \ + libusb-1.0-0 .... Fedora, CentOS, Red Hat, and other rpm-based systems: @@ -75,5 +76,5 @@ You may also need to execute the following command in a terminal: .... sudo dnf install libgfortran fftw-libs-single qt5-qtbase \ qt5-qtmultimedia qt5-qtserialport qt5-qtsvg \ - qt5-qtserialport libgomp libusbx + qt5-qtserialport libgomp boost libusbx .... From dc4f824f431d6ec5eadd73df936219854c3b864e Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Mon, 16 Nov 2020 17:10:33 +0000 Subject: [PATCH 05/75] Only attempt to fetch LoTW users at start up if highlighting enabled --- Configuration.cpp | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/Configuration.cpp b/Configuration.cpp index 98f3841cd..f409e66e5 100644 --- a/Configuration.cpp +++ b/Configuration.cpp @@ -1076,9 +1076,6 @@ Configuration::impl::impl (Configuration * self, QNetworkAccessManager * network }); lotw_users_.set_local_file_path (writeable_data_dir_.absoluteFilePath ("lotw-user-activity.csv")); - // load the dictionary if it exists, fetch and load if it doesn't - lotw_users_.load (ui_->LotW_CSV_URL_line_edit->text ()); - // // validation // @@ -1239,6 +1236,19 @@ Configuration::impl::impl (Configuration * self, QNetworkAccessManager * network audio_output_device_ = next_audio_output_device_; audio_output_channel_ = next_audio_output_channel_; + bool fetch_if_needed {false}; + for (auto const& item : decode_highlighing_model_.items ()) + { + if (DecodeHighlightingModel::Highlight::LotW == item.type_) + { + fetch_if_needed = item.enabled_; + break; + } + } + // load the LoTW users dictionary if it exists, fetch and load if it + // doesn't and we need it + lotw_users_.load (ui_->LotW_CSV_URL_line_edit->text (), fetch_if_needed); + transceiver_thread_ = new QThread {this}; transceiver_thread_->start (); } From 3cd567e4642f1239849644cddb4b6ca2f9cc01cd Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Mon, 16 Nov 2020 17:24:10 +0000 Subject: [PATCH 06/75] Allow decodes window splitter widget to shrink its height further --- widgets/mainwindow.ui | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/widgets/mainwindow.ui b/widgets/mainwindow.ui index 6ffcf9a24..73404806d 100644 --- a/widgets/mainwindow.ui +++ b/widgets/mainwindow.ui @@ -7,7 +7,7 @@ 0 0 805 - 589 + 637 @@ -26,12 +26,6 @@ - - - 0 - 2 - - Qt::Horizontal @@ -590,7 +584,7 @@ - + From f10d6fb712d51a7673315fdb21300778ec97ad26 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Mon, 16 Nov 2020 17:36:50 +0000 Subject: [PATCH 07/75] Fix regression in hiding Rx Frequency window titles & headings --- widgets/mainwindow.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/widgets/mainwindow.cpp b/widgets/mainwindow.cpp index cd260df5b..a40e27d37 100644 --- a/widgets/mainwindow.cpp +++ b/widgets/mainwindow.cpp @@ -2597,8 +2597,10 @@ void MainWindow::hideMenus(bool checked) ui->menuBar->setVisible(!checked); if(m_mode!="FreqCal" and m_mode!="WSPR" and m_mode!="FST4W") { ui->lh_decodes_title_label->setVisible(!checked); + ui->rh_decodes_title_label->setVisible(!checked); } ui->lh_decodes_headings_label->setVisible(!checked); + ui->rh_decodes_headings_label->setVisible(!checked); ui->gridLayout_5->layout()->setSpacing(spacing); ui->horizontalLayout_2->layout()->setSpacing(spacing); ui->horizontalLayout_5->layout()->setSpacing(spacing); From a1808c99f7801f1c85c0af7d4f067d9303b2702a Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Tue, 17 Nov 2020 00:55:24 +0000 Subject: [PATCH 08/75] Fix issue with main window height growing on restart --- widgets/mainwindow.cpp | 6 +- widgets/mainwindow.ui | 1308 +++++++++++++++++++++------------------- 2 files changed, 689 insertions(+), 625 deletions(-) diff --git a/widgets/mainwindow.cpp b/widgets/mainwindow.cpp index a40e27d37..357d99644 100644 --- a/widgets/mainwindow.cpp +++ b/widgets/mainwindow.cpp @@ -5920,7 +5920,11 @@ void MainWindow::displayWidgets(qint64 n) if(i==31) ui->cbRxAll->setVisible(b); if(i==32) ui->cbCQonly->setVisible(b); if(i==33) ui->sbTR_FST4W->setVisible(b); - if(i==34) ui->sbF_Low->setVisible(b); + if (34 == i) // adjust the stacked widget + { + ui->opt_controls_stack->setCurrentIndex (b ? 1 : 0); + ui->sbF_Low->setVisible(b); + } if(i==35) ui->sbF_High->setVisible(b); j=j>>1; } diff --git a/widgets/mainwindow.ui b/widgets/mainwindow.ui index 73404806d..f4f1ed750 100644 --- a/widgets/mainwindow.ui +++ b/widgets/mainwindow.ui @@ -6,8 +6,8 @@ 0 0 - 805 - 637 + 692 + 498 @@ -307,12 +307,6 @@ true - - - 0 - 10 - - 200 @@ -336,6 +330,12 @@ + + + 0 + 0 + + 0 @@ -584,7 +584,7 @@ - + @@ -767,7 +767,7 @@ Yellow when too low 0 - + @@ -859,7 +859,17 @@ Yellow when too low - + + + + Add callsign and locator to database + + + Add + + + + @@ -881,20 +891,17 @@ Yellow when too low - - + + - Callsign of station to be worked + Search for callsign in database - - - - Qt::AlignCenter + &Lookup - + @@ -986,20 +993,10 @@ Yellow when too low - - + + - Search for callsign in database - - - &Lookup - - - - - - - Locator of station to be worked + Callsign of station to be worked @@ -1009,13 +1006,16 @@ Yellow when too low - - + + - Add callsign and locator to database + Locator of station to be worked - Add + + + + Qt::AlignCenter @@ -1110,7 +1110,7 @@ Yellow when too low - + 0 @@ -1124,347 +1124,8 @@ Yellow when too low 0 - - - - - - - - 0 - 0 - - - - - 20 - 0 - - - - - 50 - 20 - - - - Set Tx frequency to Rx Frequency - - - Set Tx frequency to Rx Frequency - - - - - - - - - - Frequency tolerance (Hz) - - - Qt::AlignCenter - - - F Tol - - - 1 - - - 1000 - - - 10 - - - - - - - - 0 - 0 - - - - - 20 - 0 - - - - - 50 - 20 - - - - Set Rx frequency to Tx Frequency - - - Set Rx frequency to Tx Frequency - - - - - - - - - - - - true - - - - 0 - 0 - - - - Toggle Tx mode - - - Tx JT9 @ - - - - - - - Audio Tx frequency - - - Qt::AlignCenter - - - Hz - - - Tx - - - 200 - - - 5000 - - - 1500 - - - - - - - <html><head/><body><p>Submode determines tone spacing; A is narrowest.</p></body></html> - - - Submode determines tone spacing; A is narrowest. - - - Qt::AlignCenter - - - Submode - - - 0 - - - 7 - - - - - - - Qt::AlignCenter - - - - - - F High - - - 100 - - - 5000 - - - 50 - - - 1400 - - - - - - - - - <html><head/><body><p>Check to use short-format messages.</p></body></html> - - - Check to use short-format messages. - - - Sh - - - - - - - <html><head/><body><p>Check to enable JT9 fast modes</p></body></html> - - - Check to enable JT9 fast modes - - - Fast - - - - - - - <html><head/><body><p>Check to enable automatic sequencing of Tx messages based on received messages.</p></body></html> - - - Check to enable automatic sequencing of Tx messages based on received messages. - - - Auto Seq - - - - - - - <html><head/><body><p>Check to call the first decoded responder to my CQ.</p></body></html> - - - Check to call the first decoded responder to my CQ. - - - Call 1st - - - - - - - false - - - Check to generate "@1250 (SEND MSGS)" in Tx6. - - - Tx6 - - - - - - - - - Qt::AlignCenter - - - F Low - - - 100 - - - 5000 - - - 50 - - - 600 - - - - - - - <html><head/><body><p>Double-click on another caller to queue that call for your next QSO.</p></body></html> - - - Double-click on another caller to queue that call for your next QSO. - - - Next Call - - - Qt::AlignCenter - - - - - - - Audio Rx frequency - - - Qt::AlignCenter - - - Hz - - - Rx - - - 200 - - - 5000 - - - 1500 - - - - - - - <html><head/><body><p>Tx/Rx or Frequency calibration sequence length</p></body></html> - - - Tx/Rx or Frequency calibration sequence length - - - Qt::AlignCenter - - - s - - - T/R - - - 5 - - - 1800 - - - 30 - - - - + + @@ -1517,74 +1178,7 @@ Not available to nonstandard callsign holders. - - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - Tx# - - - 1 - - - 4095 - - - - - - - <html><head/><body><p>Check to keep Tx frequency fixed when double-clicking on decoded text.</p></body></html> - - - Check to keep Tx frequency fixed when double-clicking on decoded text. - - - Hold Tx Freq - - - - - - - <html><head/><body><p>Synchronizing threshold. Lower numbers accept weaker sync signals.</p></body></html> - - - Synchronizing threshold. Lower numbers accept weaker sync signals. - - - Qt::AlignCenter - - - Sync - - - -1 - - - 10 - - - 1 - - - - - - - <html><head/><body><p>Check to Tx in even-numbered minutes or sequences, starting at 0; uncheck for odd sequences.</p></body></html> - - - Check to Tx in even-numbered minutes or sequences, starting at 0; uncheck for odd sequences. - - - Tx even/1st - - - - + @@ -1660,32 +1254,498 @@ When not checked you can view the calibration results. - - - - <html><head/><body><p>Signal report: Signal-to-noise ratio in 2500 Hz reference bandwidth (dB).</p></body></html> - - - Signal report: Signal-to-noise ratio in 2500 Hz reference bandwidth (dB). - - - Qt::AlignCenter - - - Report - - - -50 - - - 49 - - - -15 - - + + + + + + <html><head/><body><p>Check to use short-format messages.</p></body></html> + + + Check to use short-format messages. + + + Sh + + + + + + + <html><head/><body><p>Check to enable JT9 fast modes</p></body></html> + + + Check to enable JT9 fast modes + + + Fast + + + + + + + <html><head/><body><p>Check to enable automatic sequencing of Tx messages based on received messages.</p></body></html> + + + Check to enable automatic sequencing of Tx messages based on received messages. + + + Auto Seq + + + + + + + <html><head/><body><p>Check to call the first decoded responder to my CQ.</p></body></html> + + + Check to call the first decoded responder to my CQ. + + + Call 1st + + + + + + + false + + + Check to generate "@1250 (SEND MSGS)" in Tx6. + + + Tx6 + + + + - + + + + + + <html><head/><body><p>Check to Tx in even-numbered minutes or sequences, starting at 0; uncheck for odd sequences.</p></body></html> + + + Check to Tx in even-numbered minutes or sequences, starting at 0; uncheck for odd sequences. + + + Tx even/1st + + + + + + + Audio Tx frequency + + + Qt::AlignCenter + + + Hz + + + Tx + + + 200 + + + 5000 + + + 1500 + + + + + + + + + + 0 + 0 + + + + + 20 + 0 + + + + + 50 + 20 + + + + Set Tx frequency to Rx Frequency + + + Set Tx frequency to Rx Frequency + + + + + + + + + + Frequency tolerance (Hz) + + + Qt::AlignCenter + + + F Tol + + + 1 + + + 1000 + + + 10 + + + + + + + + 0 + 0 + + + + + 20 + 0 + + + + + 50 + 20 + + + + Set Rx frequency to Tx Frequency + + + Set Rx frequency to Tx Frequency + + + + + + + + + + + + Audio Rx frequency + + + Qt::AlignCenter + + + Hz + + + Rx + + + 200 + + + 5000 + + + 1500 + + + + + + + <html><head/><body><p>Signal report: Signal-to-noise ratio in 2500 Hz reference bandwidth (dB).</p></body></html> + + + Signal report: Signal-to-noise ratio in 2500 Hz reference bandwidth (dB). + + + Qt::AlignCenter + + + Report + + + -50 + + + 49 + + + -15 + + + + + + + <html><head/><body><p>Tx/Rx or Frequency calibration sequence length</p></body></html> + + + Tx/Rx or Frequency calibration sequence length + + + Qt::AlignCenter + + + s + + + T/R + + + 5 + + + 1800 + + + 30 + + + + + + + + + + + true + + + + 0 + 0 + + + + Toggle Tx mode + + + Tx JT9 @ + + + + + + + <html><head/><body><p>Check to keep Tx frequency fixed when double-clicking on decoded text.</p></body></html> + + + Check to keep Tx frequency fixed when double-clicking on decoded text. + + + Hold Tx Freq + + + + + + + 0 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + <html><head/><body><p>Double-click on another caller to queue that call for your next QSO.</p></body></html> + + + Double-click on another caller to queue that call for your next QSO. + + + Next Call + + + Qt::AlignCenter + + + + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + Tx# + + + 1 + + + 4095 + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Qt::AlignCenter + + + F Low + + + 100 + + + 5000 + + + 50 + + + 600 + + + + + + + Qt::AlignCenter + + + + + + F High + + + 100 + + + 5000 + + + 50 + + + 1400 + + + + + + + + + + + <html><head/><body><p>Submode determines tone spacing; A is narrowest.</p></body></html> + + + Submode determines tone spacing; A is narrowest. + + + Qt::AlignCenter + + + Submode + + + 0 + + + 7 + + + + + + + <html><head/><body><p>Synchronizing threshold. Lower numbers accept weaker sync signals.</p></body></html> + + + Synchronizing threshold. Lower numbers accept weaker sync signals. + + + Qt::AlignCenter + + + Sync + + + -1 + + + 10 + + + 1 + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + Qt::Vertical @@ -1724,84 +1784,6 @@ When not checked you can view the calibration results. - - - - Send this message in next Tx interval - - - margin-left: 10%; margin-right: 0% - - - - - - Ctrl+2 - - - - - - - <html><head/><body><p>Send this message in next Tx interval</p><p>Double click to toggle the use of the Tx1 message to start a QSO with a station (not allowed for type 1 compound call holders)</p></body></html> - - - Send this message in next Tx interval -Double click to toggle the use of the Tx1 message to start a QSO with a station (not allowed for type 1 compound call holders) - - - margin-left: 10%; margin-right: 0% - - - - - - Ctrl+1 - - - - - - - Switch to this Tx message NOW - - - padding-left: 15%; padding-right: 15%; padding-top: 3%; padding-bottom: 3% - - - Tx &2 - - - Alt+2 - - - - - - - - - - <html><head/><body><p>Switch to this Tx message NOW</p><p>Double click to toggle the use of the Tx1 message to start a QSO with a station (not allowed for type 1 compound call holders)</p></body></html> - - - Switch to this Tx message NOW -Double click to toggle the use of the Tx1 message to start a QSO with a station (not allowed for type 1 compound call holders) - - - Qt::LeftToRight - - - padding-left: 15%; padding-right: 15%; padding-top: 3%; padding-bottom: 3% - - - Tx &1 - - - Alt+1 - - - @@ -1821,59 +1803,24 @@ Double click to toggle the use of the Tx1 message to start a QSO with a station - - - - - + + - <html><head/><body><p>Send this message in next Tx interval</p><p>Double-click to reset to the standard 73 message</p></body></html> - - - Send this message in next Tx interval -Double-click to reset to the standard 73 message - - - margin-left: 10%; margin-right: 0% + Queue up the next Tx message - + Next - - Ctrl+5 + + Qt::AlignCenter - - - - Send this message in next Tx interval - - - margin-left: 10%; margin-right: 0% - + + - - Ctrl+3 - - - - - - - Switch to this Tx message NOW - - - padding-left: 15%; padding-right: 15%; padding-top: 3%; padding-bottom: 3% - - - Tx &3 - - - Alt+3 - @@ -1897,24 +1844,30 @@ RR73 messages should only be used when you are reasonably confident that no mess - - + + - <html><head/><body><p>Switch to this Tx message NOW</p><p>Double-click to toggle between RRR and RR73 messages in Tx4 (not allowed for type2 compound call holders)</p><p>RR73 messages should only be used when you are reasonably confident that no message repetitions will be required</p></body></html> + <html><head/><body><p>Send this message in next Tx interval</p><p>Double click to toggle the use of the Tx1 message to start a QSO with a station (not allowed for type 1 compound call holders)</p></body></html> - Switch to this Tx message NOW -Double-click to toggle between RRR and RR73 messages in Tx4 (not allowed for type2 compound call holders) -RR73 messages should only be used when you are reasonably confident that no message repetitions will be required + Send this message in next Tx interval +Double click to toggle the use of the Tx1 message to start a QSO with a station (not allowed for type 1 compound call holders) - padding-left: 15%; padding-right: 15%; padding-top: 3%; padding-bottom: 3% + margin-left: 10%; margin-right: 0% - Tx &4 + - Alt+4 + Ctrl+1 + + + + + + + @@ -1938,8 +1891,24 @@ Double-click to reset to the standard 73 message - - + + + + Switch to this Tx message NOW + + + padding-left: 15%; padding-right: 15%; padding-top: 3%; padding-bottom: 3% + + + Tx &2 + + + Alt+2 + + + + + @@ -1954,6 +1923,28 @@ Double-click to reset to the standard 73 message + + + + Send this message in next Tx interval + + + margin-left: 10%; margin-right: 0% + + + + + + Ctrl+2 + + + + + + + + + @@ -1964,6 +1955,66 @@ Double-click to reset to the standard 73 message + + + + Switch to this Tx message NOW + + + padding-left: 15%; padding-right: 15%; padding-top: 3%; padding-bottom: 3% + + + Tx &3 + + + Alt+3 + + + + + + + <html><head/><body><p>Switch to this Tx message NOW</p><p>Double-click to toggle between RRR and RR73 messages in Tx4 (not allowed for type2 compound call holders)</p><p>RR73 messages should only be used when you are reasonably confident that no message repetitions will be required</p></body></html> + + + Switch to this Tx message NOW +Double-click to toggle between RRR and RR73 messages in Tx4 (not allowed for type2 compound call holders) +RR73 messages should only be used when you are reasonably confident that no message repetitions will be required + + + padding-left: 15%; padding-right: 15%; padding-top: 3%; padding-bottom: 3% + + + Tx &4 + + + Alt+4 + + + + + + + <html><head/><body><p>Switch to this Tx message NOW</p><p>Double click to toggle the use of the Tx1 message to start a QSO with a station (not allowed for type 1 compound call holders)</p></body></html> + + + Switch to this Tx message NOW +Double click to toggle the use of the Tx1 message to start a QSO with a station (not allowed for type 1 compound call holders) + + + Qt::LeftToRight + + + padding-left: 15%; padding-right: 15%; padding-top: 3%; padding-bottom: 3% + + + Tx &1 + + + Alt+1 + + + @@ -1980,6 +2031,22 @@ Double-click to reset to the standard 73 message + + + + Send this message in next Tx interval + + + margin-left: 10%; margin-right: 0% + + + + + + Ctrl+3 + + + @@ -1996,30 +2063,23 @@ list. The list can be maintained in Settings (F2). - - - - - - - - - - - - - - - - + + - Queue up the next Tx message + <html><head/><body><p>Send this message in next Tx interval</p><p>Double-click to reset to the standard 73 message</p></body></html> + + + Send this message in next Tx interval +Double-click to reset to the standard 73 message + + + margin-left: 10%; margin-right: 0% - Next + - - Qt::AlignCenter + + Ctrl+5 @@ -2797,7 +2857,7 @@ list. The list can be maintained in Settings (F2). 0 0 - 805 + 692 21 From e3bffc3ecef26f10121a05994e6d38d34f299f2e Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Tue, 17 Nov 2020 21:52:28 +0000 Subject: [PATCH 09/75] Read hamlib_settings.json when rig is None to allow PTT only config --- Transceiver/HamlibTransceiver.cpp | 76 +++++++++++++++---------------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/Transceiver/HamlibTransceiver.cpp b/Transceiver/HamlibTransceiver.cpp index 67fc36dc3..13b08ed6f 100644 --- a/Transceiver/HamlibTransceiver.cpp +++ b/Transceiver/HamlibTransceiver.cpp @@ -259,53 +259,53 @@ HamlibTransceiver::HamlibTransceiver (logger_type * logger, // rig_->state.obj = this; - if (!is_dummy_) + // + // user defined Hamlib settings + // + auto settings_file_name = QStandardPaths::locate (QStandardPaths::AppConfigLocation + , "hamlib_settings.json"); + if (!settings_file_name.isEmpty ()) { - // - // user defined Hamlib settings - // - auto settings_file_name = QStandardPaths::locate (QStandardPaths::AppConfigLocation - , "hamlib_settings.json"); - if (!settings_file_name.isEmpty ()) + QFile settings_file {settings_file_name}; + qDebug () << "Using Hamlib settings file:" << settings_file_name; + if (settings_file.open (QFile::ReadOnly)) { - QFile settings_file {settings_file_name}; - qDebug () << "Using Hamlib settings file:" << settings_file_name; - if (settings_file.open (QFile::ReadOnly)) + QJsonParseError status; + auto settings_doc = QJsonDocument::fromJson (settings_file.readAll (), &status); + if (status.error) { - QJsonParseError status; - auto settings_doc = QJsonDocument::fromJson (settings_file.readAll (), &status); - if (status.error) - { - throw error {tr ("Hamlib settings file error: %1 at character offset %2") - .arg (status.errorString ()).arg (status.offset)}; - } - qDebug () << "Hamlib settings JSON:" << settings_doc.toJson (); - if (!settings_doc.isObject ()) - { - throw error {tr ("Hamlib settings file error: top level must be a JSON object")}; - } - auto const& settings = settings_doc.object (); + throw error {tr ("Hamlib settings file error: %1 at character offset %2") + .arg (status.errorString ()).arg (status.offset)}; + } + qDebug () << "Hamlib settings JSON:" << settings_doc.toJson (); + if (!settings_doc.isObject ()) + { + throw error {tr ("Hamlib settings file error: top level must be a JSON object")}; + } + auto const& settings = settings_doc.object (); - // - // configuration settings - // - auto const& config = settings["config"]; - if (!config.isUndefined ()) + // + // configuration settings + // + auto const& config = settings["config"]; + if (!config.isUndefined ()) + { + if (!config.isObject ()) { - if (!config.isObject ()) - { - throw error {tr ("Hamlib settings file error: config must be a JSON object")}; - } - auto const& config_list = config.toObject (); - for (auto item = config_list.constBegin (); item != config_list.constEnd (); ++item) - { - set_conf (item.key ().toLocal8Bit ().constData () - , (*item).toVariant ().toString ().toLocal8Bit ().constData ()); - } + throw error {tr ("Hamlib settings file error: config must be a JSON object")}; + } + auto const& config_list = config.toObject (); + for (auto item = config_list.constBegin (); item != config_list.constEnd (); ++item) + { + set_conf (item.key ().toLocal8Bit ().constData () + , (*item).toVariant ().toString ().toLocal8Bit ().constData ()); } } } + } + if (!is_dummy_) + { switch (rig_->caps->port_type) { case RIG_PORT_SERIAL: From 0fc5639fd525540b752778df915fb8611b5c273d Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Wed, 18 Nov 2020 02:06:30 +0000 Subject: [PATCH 10/75] Repair a regression causing missing Rx decode timestamps in ALL.TXT --- widgets/mainwindow.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/widgets/mainwindow.cpp b/widgets/mainwindow.cpp index 357d99644..44a1af29e 100644 --- a/widgets/mainwindow.cpp +++ b/widgets/mainwindow.cpp @@ -3027,8 +3027,8 @@ void MainWindow::decode() //decode() dec_data.params.nutc=dec_data.params.nutc/100; } if(dec_data.params.nagain==0 && dec_data.params.newdat==1 && (!m_diskData)) { - auto t_start = qt_truncate_date_time_to (QDateTime::currentDateTimeUtc (), m_TRperiod * 1.e3); - auto t = t_start.time (); + m_dateTimeSeqStart = qt_truncate_date_time_to (QDateTime::currentDateTimeUtc (), m_TRperiod * 1.e3); + auto t = m_dateTimeSeqStart.time (); dec_data.params.nutc = t.hour () * 100 + t.minute (); if (m_TRperiod < 60.) { From b834645bf71b6a4bee765ea891717eebaf8d4fe5 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Fri, 20 Nov 2020 13:45:44 +0000 Subject: [PATCH 11/75] Debian 9 backwards compatibility --- CMakeLists.txt | 15 +++++++-------- WSJTXLogging.cpp | 8 +++++--- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 72c38fa13..84bbfbae5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required (VERSION 3.9 FATAL_ERROR) +cmake_minimum_required (VERSION 3.7.2 FATAL_ERROR) if (APPLE) # @@ -46,9 +46,9 @@ endif () project (wsjtx VERSION 2.3.0.0 - DESCRIPTION "WSJT-X: Digital Modes for Weak Signal Communications in Amateur Radio" LANGUAGES C CXX Fortran ) +set (PROJECT_DESCRIPTION "WSJT-X: Digital Modes for Weak Signal Communications in Amateur Radio") # # Local CMake modules and support files @@ -838,7 +838,7 @@ endif () if (WIN32) set (Boost_USE_STATIC_LIBS OFF) endif () -find_package (Boost 1.63 REQUIRED COMPONENTS log_setup log) +find_package (Boost 1.62 REQUIRED COMPONENTS log_setup log) # # OpenMP @@ -1053,7 +1053,7 @@ query_qmake (QT_HOST_DATA QT_DATA_DIR) set (QT_MKSPECS_DIR ${QT_DATA_DIR}/mkspecs) # project definitions -add_definitions (-DQT5 -DCMAKE_BUILD -DBIGSYM=1) +add_definitions (-DQT5 -DCMAKE_BUILD -DBIGSYM=1 -DBOOST_ALL_DYN_LINK) if (CMAKE_HOST_UNIX) add_definitions (-DUNIX) elseif (CMAKE_HOST_WIN32) @@ -1062,7 +1062,6 @@ endif () # build a library of package functionality (without and optionally with OpenMP support) add_library (wsjt_cxx STATIC ${wsjt_CSRCS} ${wsjt_CXXSRCS}) -target_compile_definitions (wsjt_cxx PUBLIC BOOST_LOG_DYN_LINK) target_link_libraries (wsjt_cxx ${LIBM_LIBRARIES} Boost::log_setup ${LIBM_LIBRARIES}) # build an OpenMP variant of the Fortran library routines @@ -1310,7 +1309,7 @@ target_link_libraries (qcp Qt5::Widgets Qt5::PrintSupport) # build a library of package Qt functionality add_library (wsjt_qt STATIC ${wsjt_qt_CXXSRCS} ${wsjt_qt_GENUISRCS} ${GENAXSRCS}) # set wsjtx_udp exports to static variants -target_compile_definitions (wsjt_qt PUBLIC UDP_STATIC_DEFINE BOOST_LOG_DYN_LINK) +target_compile_definitions (wsjt_qt PUBLIC UDP_STATIC_DEFINE) target_link_libraries (wsjt_qt Boost::log qcp Qt5::Widgets Qt5::Network Qt5::Sql) target_include_directories (wsjt_qt BEFORE PRIVATE ${hamlib_INCLUDE_DIRS}) if (WIN32) @@ -1853,11 +1852,11 @@ else () endif () set (CPACK_DEBIAN_PACKAGE_HOMEPAGE "${PROJECT_HOMEPAGE}") -set (CPACK_DEBIAN_PACKAGE_DEPENDS "libgfortran5 (>=8.3) | libgfortran4 (>=7.3) | libgfortran3 (>=6.3), libfftw3-single3 (>=3.3), libgomp1 (>=6), libqt5serialport5 (>=5.7), libqt5multimedia5-plugins (>=5.7), libqt5widgets5 (>=5.7), libqt5network5 (>=5.7), libqt5printsupport5 (>=5.7), libqt5sql5-sqlite (>=5.7), libusb-1.0-0 (>=1.0.21), libboost-log1.65.1 (>=1.62.0) | libboost-log1.65.1 (>=1.65.1) | libboost-log1.67.0 (>=1.67.0) | libboost-log1.71.0 (>=1.71.0)") +set (CPACK_DEBIAN_PACKAGE_DEPENDS "libgfortran5 (>=8.3) | libgfortran4 (>=7.3) | libgfortran3 (>=6.3), libfftw3-single3 (>=3.3), libgomp1 (>=6), libqt5serialport5 (>=5.7), libqt5multimedia5-plugins (>=5.7), libqt5widgets5 (>=5.7), libqt5network5 (>=5.7), libqt5printsupport5 (>=5.7), libqt5sql5-sqlite (>=5.7), libusb-1.0-0 (>=1.0.21), libboost-log1.62.0 (>=1.62.0) | libboost-log1.65.1 (>=1.65.1) | libboost-log1.67.0 (>=1.67.0) | libboost-log1.71.0 (>=1.71.0) | libboost-log1.74.0 (>=1.74.0)") set (CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON) set (CPACK_RPM_PACKAGE_ARCHITECTURE ${CMAKE_SYSTEM_PROCESSOR}) -set (CPACK_RPM_PACKAGE_REQUIRES "qt5-qtbase >= 5.9, qt5-qtserialport >= 5.9, qt5-qtmultimedia >= 5.9, qt5-qtsvg >= 5.9, libusbx >= 1.0.22, libgfortran >= 7, libgomp >= 7, fftw-libs-single >= 3.3") +set (CPACK_RPM_PACKAGE_REQUIRES "qt5-qtbase >= 5.9, qt5-qtserialport >= 5.9, qt5-qtmultimedia >= 5.9, qt5-qtsvg >= 5.9, libusbx >= 1.0.22, libgfortran >= 7, libgomp >= 7, fftw-libs-single >= 3.3, boost-log >= 1.62") set (CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION /usr/share/pixmaps /usr/share/applications /usr/share/man /usr/share/man1) configure_file ("${PROJECT_SOURCE_DIR}/CMakeCPackOptions.cmake.in" diff --git a/WSJTXLogging.cpp b/WSJTXLogging.cpp index 76adf81b0..ffea213c8 100644 --- a/WSJTXLogging.cpp +++ b/WSJTXLogging.cpp @@ -35,7 +35,7 @@ namespace trivial = logging::trivial; namespace keywords = logging::keywords; namespace expr = logging::expressions; namespace sinks = logging::sinks; -namespace ptime = boost::posix_time; +namespace posix_time = boost::posix_time; namespace gregorian = boost::gregorian; namespace container = boost::container; @@ -139,7 +139,9 @@ WSJTXLogging::WSJTXLogging () app_data.absoluteFilePath ("logs/wsjtx_syslog_%Y-%m.log").toStdString () , keywords::time_based_rotation = sinks::file::rotation_at_time_point (gregorian::greg_day (1), 0, 0, 0) , keywords::open_mode = std::ios_base::out | std::ios_base::app +#if BOOST_VERSION / 100 >= 1063 , keywords::enable_final_rotation = false +#endif ); sys_sink->locked_backend ()->set_file_collector @@ -166,8 +168,8 @@ WSJTXLogging::WSJTXLogging () ( expr::stream << "[" << channel - << "][" << expr::format_date_time ("TimeStamp", "%Y-%m-%d %H:%M:%S.%f") - << "][" << expr::format_date_time ("Uptime", "%O:%M:%S.%f") + << "][" << expr::format_date_time ("TimeStamp", "%Y-%m-%d %H:%M:%S.%f") + << "][" << expr::format_date_time ("Uptime", "%O:%M:%S.%f") << "][" << trivial::severity << "] " << expr::message ); From ed465e11f257de07afff2609ece72b02b8f2a1da Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Fri, 20 Nov 2020 21:05:59 +0000 Subject: [PATCH 12/75] More Debian 9 backwards compatibility changes (Qt 5.7) --- main.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/main.cpp b/main.cpp index 021e327b4..9e2403de1 100644 --- a/main.cpp +++ b/main.cpp @@ -76,7 +76,13 @@ namespace switch (static_cast (v.type ())) { case QMetaType::QByteArray: - os << "0x" << v.toByteArray ().toHex (':').toStdString (); + os << "0x" +#if QT_VERSION >= QT_VERSION_CHECK (5, 9, 0) + << v.toByteArray ().toHex (':').toStdString () +#else + << v.toByteArray ().toHex ().toStdString () +#endif + ; break; case QMetaType::QBitArray: From bb52f12f7182eb2d68c76fc88036868a9b5a219e Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Fri, 20 Nov 2020 21:28:12 +0000 Subject: [PATCH 13/75] Updated macOS installer ReadMe.txt --- Darwin/ReadMe.txt | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/Darwin/ReadMe.txt b/Darwin/ReadMe.txt index 3adf32f21..15a13b315 100644 --- a/Darwin/ReadMe.txt +++ b/Darwin/ReadMe.txt @@ -16,7 +16,8 @@ Double-click on the wsjtx-...-Darwin.dmg file you have downloaded from K1JT's we Now open a Terminal window by going to Applications->Utilities and clicking on Terminal. Along with this ReadMe file there is a file: sysctl.conf which must be copied to a -system area by typing this line in the Terminal window and then pressing the Return key. +system area by typing these two lines in the Terminal window and then pressing the Return key +after each line. sudo cp /Volumes/WSJT-X/sysctl.conf /etc @@ -28,7 +29,7 @@ change has been made by typing: sysctl -a | grep sysv.shm -If shmmax is not shown as 14680064 then contact me since WSJT-X will fail to load with +If shmmax is not shown as 104857600 then contact me since WSJT-X will fail to load with an error message: "Unable to create shared memory segment". You can now close the Terminal window. It will not be necessary to repeat this procedure @@ -85,15 +86,8 @@ has to be increased. The sysctl.conf file is used for this purpose. You can use a Mac editor to examine sysctl.conf. (Do not use another editor - the file would be probably be corrupted.) -There are two important parameters that you need to consider. shmmax determines the -amount of shared memory that must be allocated for WSJT-X to operate. This is 14680064 (14MB) -and this is defined in the sysctl.conf file and should not be changed. +It is possible to run two instances of WSJT-X simultaneously. See "Section 16.2 +Frequently asked Questions" in the User Guide. If you wish to run more than two instances +simutaneously, the sysctl.conf file needs to be modified. Please email me with your +requirements and I will provide a replacement sysctl.conf to suit. -It is possible to run more than one instance of WSJT-X simultaneously. See -"Section 16.2 Frequently asked Questions" in the User Guide. The second important parameter -shmall=17920 determines how many instances are permitted. This is calculated as: - (shmall x 4096/14680064) = 5. -The sysctl.conf file is configured to permit up to 5 instances of wsjtx to run simultaneously. -If this limitation is acceptable then you can continue to install the sysctl.conf file without making any -alterations. Otherwise you must edit the file to increase shmall according to this calculation. - From 540d0646514b4d386c6dbbccb88897fea74ca01c Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Thu, 26 Nov 2020 12:31:00 +0000 Subject: [PATCH 14/75] Updated macOS ReadMe.txt with extra instructions for M1 Macs, tnx to John, G4KLA --- Darwin/ReadMe.txt | 36 +++++++++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/Darwin/ReadMe.txt b/Darwin/ReadMe.txt index 15a13b315..283aa1025 100644 --- a/Darwin/ReadMe.txt +++ b/Darwin/ReadMe.txt @@ -1,15 +1,33 @@ Notes on WSJT-X Installation for Mac OS X ----------------------------------------- +Important: If you are using the new Mac with the M1 chip then please read +the section marked: BEGIN M1. Otherwise BEGIN INTEL applies. + If you have already downloaded a previous version of WSJT-X then I suggest you change the name in the Applications folder from WSJT-X to WSJT-X_previous before proceeding. -If you have installed a previous version of WSJT-X before, then there is no -need to change anything on your system so proceed to NEXT. If you upgrade macOS -it is possible that you might need to re-install the sysctl.conf file. +I recommend that you follow the installation instructions especially if you +are moving from v2.2 to v2.3 of WSJT-X or you have upgraded macOS. -BEGIN: +BEGIN M1: + +Double-click on the wsjtx-...-Darwin.dmg file you have downloaded from K1JT's web-site. + +Now open a Terminal window by going to Applications->Utilities and clicking on Terminal. + +There are two system variables that must be set manually since the M1 Macs do not recognise +automatic parameter settings by means of the sysctl.conf file present in the download. +Type these commands - you will be asked for your password which will not be echoed: + + sudo sysctl -w kern.sysv.shmmax=104857600 + sudo sysctl -w kern.sysv.shmall=25600 + +It is important to note that these parameter settings will not survive a reboot. If you +need to reboot your Mac, then these commands must be re-entered. Now proceed to NEXT. + +BEGIN INTEL: Double-click on the wsjtx-...-Darwin.dmg file you have downloaded from K1JT's web-site. @@ -78,16 +96,20 @@ Please email me if you have problems. --- John G4KLA (g4kla@rmnjmn.co.uk) -Addendum: Information about sysctl.conf and multiple instances of wsjt-x. +Addendum: Information about sysctl.conf and multiple instances of WSJT-X. WSJT-X makes use of a block of memory which is shared between different parts of the code. The normal allocation of shared memory on a Mac is insufficient and this has to be increased. The sysctl.conf file is used for this purpose. You can use a Mac editor to examine sysctl.conf. (Do not use another editor - the file -would be probably be corrupted.) +would probably be corrupted.) It is possible to run two instances of WSJT-X simultaneously. See "Section 16.2 Frequently asked Questions" in the User Guide. If you wish to run more than two instances -simutaneously, the sysctl.conf file needs to be modified. Please email me with your +simultaneously, the sysctl.conf file needs to be modified. Please email me with your requirements and I will provide a replacement sysctl.conf to suit. +If two instances of WSJT-X are running, it is likely that you might need additional +audio devices, from two rigs for example. Visit Audio MIDI Setup and create an Aggregate Device +which will allow you to specific more than one interface. I recommend you consult Apple's guide +on combining multiple audio interfaces which is at https://support.apple.com/en-us/HT202000. From b9a6cb867029ffb763686a8d5f4ca3558022cffb Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Thu, 26 Nov 2020 12:32:29 +0000 Subject: [PATCH 15/75] Updated build instructions --- INSTALL | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/INSTALL b/INSTALL index 02e0429e3..121572022 100644 --- a/INSTALL +++ b/INSTALL @@ -43,12 +43,13 @@ the libfftw library development package. Normally installing the library development package pulls in all the FFTW v3 libraries including the single precision variant. -The Hamlib library optionally requires the libusb-1.0-1 library, if -the development version (libusb-1.0-0-dev) is available Hamlib will -configure its custom USB device back end drivers. Most rigs do not -require this so normally you can choose not to install libusb-1.0-dev -but if you have a SoftRock USB or similar SDR that uses a custom USB -interface then it is required. +The Hamlib library requires the readline development package and +optionally requires the libusb-1.0-1 library, if the development +version (libusb-1.0-0-dev) is available Hamlib will configure its +custom USB device back end drivers. Most rigs do not require this so +normally you can choose not to install libusb-1.0-dev but if you have +a SoftRock USB or similar SDR that uses a custom USB interface then it +is required. The Hamlib library is required. Currently WSJT-X needs to be built using a forked version of the Hamlib git master. This fork contains From 56f16cc023ad622d717e63eae71b1a900442eaec Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Thu, 26 Nov 2020 12:33:02 +0000 Subject: [PATCH 16/75] Updated example logging configuration example. --- wsjtx_log_config.ini | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/wsjtx_log_config.ini b/wsjtx_log_config.ini index f4e8ed339..cd97bb2ee 100644 --- a/wsjtx_log_config.ini +++ b/wsjtx_log_config.ini @@ -20,15 +20,15 @@ AutoFlush="false" # Line Formats available: TimeStamp, Uptime, Severity, LineID (counter), ProcessID, ThreadID, Line, File, Function # TimeStamp and Uptime support boost date time format: # http://www.boost.org/doc/libs/1_60_0/doc/html/date_time/date_time_io.html#date_time.format_flags -Format="[%TimeStamp(format=\"%Y-%m-%d %H:%M:%S.%f\")%][%Uptime(format=\"%O:%M:%S.%f\")%][%Severity%] %File%(%Line%) %Function%: %Message%" +Format="[%TimeStamp(format=\"%Y-%m-%d %H:%M:%S.%f\")%][%Uptime(format=\"%O:%M:%S.%f\")%][%Channel%][%Severity%] %File%(%Line%) %Function%: %Message%" # Target directory in which rotated files will be stored. -Target="${AppLocalDataLocation}/old_logs" +Target="${AppLocalDataLocation}/logs" # FileName pattern to use. %N is a counter for files. FileName="${AppLocalDataLocation}/wsjtx_syslog.log" -TargetFileName="${AppLocalDataLocation}/old_logs/wsjtx_syslog_%Y-%m-%d_%H-%M-%S.%N.log" +TargetFileName="${AppLocalDataLocation}/old_logs/wsjtx_syslog_%Y-%m_%2N.log" # RotationSize in bytes, File size, in bytes, upon which file rotation will be performed. # Time based rotation also available via RotationInterval and RotationTimePoint see boost log docs. -RotationSize="1048576" +RotationSize="5242880" # 5 Mbyte # If Append is true then do not start a new log file for each session Append="true" # EnableFinalRotation will rotate on close, make this false if using Append true @@ -36,10 +36,10 @@ EnableFinalRotation="false" # Matching used so that only files matching FileName pattern are deleted. ScanForFiles="Matching" # MaxSize - Total size of files in the target directory in bytes upon which the oldest file will be deleted. -#MaxSize=100485760 +MaxSize="1073741824" # 1 Gbyte total # MinFreeSpace - Minimum free space in the Target directory in bytes. Above this value oldest file is deleted. -#MinFreeSpace=1485760 -MaxFiles="10" +MinFreeSpace="42949672960" # 40 Gbyte +MaxFiles="50" # Specify level of log, options are: trace, debug, info, warning, error, fatal # Since Channel not part of filter all log output will be included. # If only SYSLOG logging desired, change to: Filter="%Severity% >= trace & %Channel% matches \"SYSLOG\"" @@ -58,20 +58,20 @@ Append="true" # http://www.boost.org/doc/libs/1_60_0/doc/html/date_time/date_time_io.html#date_time.format_flags Format="[%TimeStamp(format=\"%Y-%m-%d %H:%M:%S.%f\")%][%Uptime(format=\"%O:%M:%S.%f\")%][%Severity%] %Message%" # Target directory in which rotated files will be stored. -Target="${AppLocalDataLocation}/old_logs" +Target="${AppLocalDataLocation}/logs" # FileName pattern to use. %N is a counter for files. FileName="${AppLocalDataLocation}/wsjtx_datalog.log" TargetFileName="wsjtx_datalog_%5N.log" # RotationSize in bytes, File size, in bytes, upon which file rotation will be performed. # Time based rotation also available via RotationInterval and RotationTimePoint see boost log docs. -RotationSize="1048576" +RotationSize="5242880" EnableFinalRotation="false" # Matching used so that only files matching FileName pattern are deleted. ScanForFiles="Matching" # MaxSize - Total size of files in the target directory in bytes upon which the oldest file will be deleted. -#MaxSize=100485760 +MaxSize="1073741824" # MinFreeSpace - Minimum free space in the Target directory in bytes. Above this value oldest file is deleted. -#MinFreeSpace=1485760 +MinFreeSpace="42949672960" MaxFiles="10" # Specify level of log, options are: trace, debug, info, warning, error, fatal # Specify Channel otherwise all log output will be included. From 95cd992300200a4116a74e9897164fd02fb1f814 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Thu, 26 Nov 2020 12:33:51 +0000 Subject: [PATCH 17/75] Updated instructions for building the Boost C++ libraries --- doc/building-Boost-libs.txt | 39 +++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/doc/building-Boost-libs.txt b/doc/building-Boost-libs.txt index 8f913a90a..f45b3ceec 100644 --- a/doc/building-Boost-libs.txt +++ b/doc/building-Boost-libs.txt @@ -82,12 +82,12 @@ Common steps Download and extract the latest Boost library sources, at the time of writing that was https://dl.bintray.com/boostorg/release/1.74.0/source/boost_1_74_0.7z -. Extract to some convenient location, I use %HOME%\src . +. Extract to some convenient location, I use %USERPROFILE%\src . Download and extract the libbacktrace sources from https://github.com/ianlancetaylor/libbacktrace as follows. -cd %HOME%\src +cd %USERPROFILE%\src mkdir github.com cd github.com mkdir ianlancetaylor @@ -101,8 +101,8 @@ names are unique per architecture and tool-chain. This saves a lot of space as the boost header files are quite big, and there's no need to install multiple copies. -Create a new file %HOME%\src\boost_1_74_0\project-config.jam with the -following three lines to specify how Boost.Build finds the +Create a new file %USERPROFILE%\src\boost_1_74_0\project-config.jam +with the following three lines to specify how Boost.Build finds the libbacktrace library matched to your relevant C++ compliers: import toolset ; @@ -133,13 +133,15 @@ tool-chain bundled with your Qt binary installation. Verify the correct compiler is in the PATH. i.e. it identifies (g++ --version) as i686-posix-dwarf-rev0. -cd %HOME%\src\boost_1_74_0\tools\build +cd %USERPROFILE%\src\boost_1_74_0\tools\build bootstrap.bat mingw .\b2 --prefix=C:\Tools\boost-build\MinGW32 install cd ..\.. C:\Tools\boost-build\MinGW32\bin\b2 -j8 toolset=gcc ^ - --build-dir=%HOME%\build\boost ^ - --build-type=complete --prefix=C:\Tools\boost install + --build-dir=%USERPROFILE%\build\boost ^ + address-model=32 architecture=x86 variant=debug,release ^ + link=shared threading=multi ^ + --with-log --with-stacktrace --prefix=C:\Tools\boost install If all is well you should see the following line about a 1/3 of the way through the initial configuration steps. @@ -156,7 +158,7 @@ warnings can usually be ignored. If successful; you can release some space by cleaning the build tree: C:\Tools\boost-build\MinGW32\bin\b2 toolset=gcc ^ - --build-dir=%HOME%\build\boost ^ + --build-dir=%USERPROFILE%\build\boost ^ --build-type=complete clean 64-bit @@ -179,13 +181,16 @@ compilers and the project-config.jam file you created above. With a v7 gcc-8~64. My example matches my 64-bit Qt v5.15.0 with the bundled MinGW64 v8.1.0. -cd %HOME%\src\boost_1_74_0\tools\build -bootstrap.bat +cd %USERPROFILE%\src\boost_1_74_0\tools\build +bootstrap.bat mingw .\b2 --prefix=C:\Tools\boost-build\MinGW64 install cd ..\.. C:\Tools\boost-build\MinGW64\bin\b2 -j8 toolset=gcc-8~64 ^ - address-model=64 --build-dir=%HOME%\build\boost ^ - --build-type=complete --prefix=C:\Tools\boost install + address-model=64 architecture=x86 variant=debug,release ^ + link=shared threading=multi ^ + --with-log --with-stacktrace ^ + --build-dir=%USERPROFILE%\build\boost ^ + --prefix=C:\Tools\boost install If all is well you should see the following line about a 1/3 of the way through the initial configuration steps. @@ -202,9 +207,8 @@ warnings can usually be ignored. If successful; you can release some space by cleaning the build tree: C:\Tools\boost-build\MinGW32\bin\b2 toolset=gcc-8~64 ^ - address-model=64 --build-dir=%HOME%\build\boost ^ + address-model=64 --build-dir=%USERPROFILE%\build\boost ^ --build-type=complete clean - Run-time Environment -------------------- @@ -226,15 +230,12 @@ configuration tool-chain file: # ... set (BOOSTDIR C:/Tools/boost) -set (QTDIR C:/Qt/5.12.9/mingw73_32) -# set (QTDIR C:/Qt/5.15.0/mingw81_32) +set (QTDIR C:/Qt/5.15.2/mingw81_32) set (FFTWDIR C:/Tools/fftw-3.3.5-dll32) set (HAMLIBDIR C:/test-install/hamlib/mingw32/debug) set (LIBUSBDIR C:/Tools/libusb-1.0.23) -set (PYTHONDIR C:/Python27) -set (ASCIIDOCDIR C:/Tools/asciidoc-master) # where to find required packages -set (CMAKE_PREFIX_PATH ${BOOSTDIR} ${QTDIR} ${FFTWDIR} ${HAMLIBDIR} ${HAMLIBDIR}/bin ${LIBUSBDIR} ${PYTHONDIR} ${ASCIIDOCDIR}) +set (CMAKE_PREFIX_PATH ${BOOSTDIR} ${QTDIR} ${FFTWDIR} ${HAMLIBDIR} ${HAMLIBDIR}/bin ${LIBUSBDIR}) # ... From 3663b3ea3203671a2ed86980aefe5f05202ebe40 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Fri, 27 Nov 2020 01:14:12 +0000 Subject: [PATCH 18/75] MultiGeometryWidget template class abstracts window geometry changes --- widgets/MultiGeometryWidget.hpp | 92 ++++++++++++++++++++++++++++ widgets/mainwindow.cpp | 103 ++++++++++++++++++++++---------- widgets/mainwindow.h | 9 ++- widgets/mainwindow.ui | 36 +---------- 4 files changed, 171 insertions(+), 69 deletions(-) create mode 100644 widgets/MultiGeometryWidget.hpp diff --git a/widgets/MultiGeometryWidget.hpp b/widgets/MultiGeometryWidget.hpp new file mode 100644 index 000000000..a9386189c --- /dev/null +++ b/widgets/MultiGeometryWidget.hpp @@ -0,0 +1,92 @@ +#ifndef MULTI_GEOMETRY_WIDGET_HPP__ +#define MULTI_GEOMETRY_WIDGET_HPP__ + +#include +#include +#include + +#include +#include +#include + +// +// Class MultiGeometryWidget - Decorate a QWidget type with +// switchable geometries +// +// The abstract base class imbues a Qt Widget type with N alternative +// geometries. Sub-classes can initialise the currently selected +// geometry and the initial geometries using geometries. To switch +// geometry call select_geometry(n) which saves the current geometry +// and switches to the n'th saved geometry. +// +template +class MultiGeometryWidget + : public Widget +{ +public: + template + explicit MultiGeometryWidget (Args&&... args) + : Widget {std::forward (args)...} + , current_geometry_ {0} + { + } + + void geometries (std::size_t current + , std::array const& the_geometries = std::array {}) + { + Q_ASSERT (current < the_geometries.size ()); + saved_geometries_ = the_geometries; + current_geometry_ = current; + Widget::restoreGeometry (saved_geometries_[current_geometry_]); + } + + std::array const& geometries () const {return saved_geometries_;} + std::size_t current () {return current_geometry_;} + + // Call this to select a new geometry denoted by the 'n' argument, + // any actual layout changes should be made in the implementation of + // the change_layout operation below. + void select_geometry (std::size_t n) + { + Q_ASSERT (n < N); + auto geometry = Widget::saveGeometry (); + change_layout (n); + saved_geometries_[current_geometry_] = geometry; + current_geometry_ = n; + + // Defer restoration of the window geometry until the layour + // request event has been processed, this is necessary otherwise + // the final geometry may be affected by widgets not shown in the + // new layout. + desired_geometry_ = saved_geometries_[n]; + } + +protected: + virtual ~MultiGeometryWidget () {} + +private: + // Override this operation to implement any layout changes for the + // geometry specified by the argument 'n'. + virtual void change_layout (std::size_t n) = 0; + + bool event (QEvent * e) override + { + auto ret = Widget::event (e); + if (QEvent::LayoutRequest == e->type () + && desired_geometry_.size ()) + { + // Restore the new desired geometry and flag that we have done + // so by clearing the desired_geometry_ member variable. + QByteArray geometry; + std::swap (geometry, desired_geometry_); + Widget::restoreGeometry (geometry); + } + return ret; + } + + std::size_t current_geometry_; + std::array saved_geometries_; + QByteArray desired_geometry_; +}; + +#endif diff --git a/widgets/mainwindow.cpp b/widgets/mainwindow.cpp index 44a1af29e..eafa76545 100644 --- a/widgets/mainwindow.cpp +++ b/widgets/mainwindow.cpp @@ -236,7 +236,7 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple, MultiSettings * multi_settings, QSharedMemory *shdmem, unsigned downSampleFactor, QSplashScreen * splash, QProcessEnvironment const& env, QWidget *parent) : - QMainWindow(parent), + MultiGeometryWidget {parent}, m_env {env}, m_network_manager {this}, m_valid {true}, @@ -1022,10 +1022,7 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple, } ui->pbBestSP->setVisible(m_mode=="FT4"); - if(!ui->cbMenus->isChecked()) { - ui->cbMenus->setChecked(true); - ui->cbMenus->setChecked(false); - } + // this must be the last statement of constructor if (!m_valid) throw std::runtime_error {"Fatal initialization exception"}; } @@ -1094,8 +1091,33 @@ MainWindow::~MainWindow() void MainWindow::writeSettings() { m_settings->beginGroup("MainWindow"); - m_settings->setValue ("geometry", saveGeometry ()); - m_settings->setValue ("geometryNoControls", m_geometryNoControls); + if (ui->actionSWL_Mode->isChecked ()) + { + m_settings->setValue ("SWLView", true); + m_settings->setValue ("ShowMenus", ui->cbMenus->isChecked ()); + m_settings->setValue ("geometry", geometries ()[0]); + m_settings->setValue ("SWLModeGeometry", saveGeometry ()); + m_settings->setValue ("geometryNoControls", geometries ()[2]); + } + else + { + if (ui->cbMenus->isChecked()) + { + m_settings->setValue ("SWLView", ui->actionSWL_Mode->isChecked ()); + m_settings->setValue ("ShowMenus", true); + m_settings->setValue ("geometry", saveGeometry ()); + m_settings->setValue ("SWLModeGeometry", geometries ()[1]); + m_settings->setValue ("geometryNoControls", geometries ()[2]); + } + else + { + m_settings->setValue ("SWLView", ui->actionSWL_Mode->isChecked ()); + m_settings->setValue ("ShowMenus", false); + m_settings->setValue ("geometry", geometries ()[0]); + m_settings->setValue ("SWLModeGeometry", geometries ()[1]); + m_settings->setValue ("geometryNoControls", saveGeometry ()); + } + } m_settings->setValue ("state", saveState ()); m_settings->setValue("MRUdir", m_path); m_settings->setValue("TxFirst",m_txFirst); @@ -1105,7 +1127,6 @@ void MainWindow::writeSettings() m_settings->setValue ("MsgAvgDisplayed", m_msgAvgWidget && m_msgAvgWidget->isVisible ()); m_settings->setValue ("FoxLogDisplayed", m_foxLogWindow && m_foxLogWindow->isVisible ()); m_settings->setValue ("ContestLogDisplayed", m_contestLogWindow && m_contestLogWindow->isVisible ()); - m_settings->setValue("ShowMenus",ui->cbMenus->isChecked()); m_settings->setValue("CallFirst",ui->cbFirst->isChecked()); m_settings->setValue("HoundSort",ui->comboBoxHoundSort->currentIndex()); m_settings->setValue("FoxNlist",ui->sbNlist->value()); @@ -1159,9 +1180,8 @@ void MainWindow::writeSettings() m_settings->setValue("pwrBandTuneMemory",m_pwrBandTuneMemory); m_settings->setValue ("FT8AP", ui->actionEnable_AP_FT8->isChecked ()); m_settings->setValue ("JT65AP", ui->actionEnable_AP_JT65->isChecked ()); - m_settings->setValue("SplitterState",ui->splitter->saveState()); + m_settings->setValue("SplitterState",ui->decodes_splitter->saveState()); m_settings->setValue("Blanker",ui->sbNB->value()); - m_settings->setValue ("SWLView", ui->actionSWL_Mode->isChecked ()); { QList coeffs; // suitable for QSettings @@ -1180,8 +1200,17 @@ void MainWindow::readSettings() ui->cbAutoSeq->setVisible(false); ui->cbFirst->setVisible(false); m_settings->beginGroup("MainWindow"); - restoreGeometry (m_settings->value ("geometry", saveGeometry ()).toByteArray ()); - m_geometryNoControls = m_settings->value ("geometryNoControls",saveGeometry()).toByteArray(); + std::array the_geometries; + the_geometries[0] = m_settings->value ("geometry", saveGeometry ()).toByteArray (); + the_geometries[1] = m_settings->value ("SWLModeGeometry", saveGeometry ()).toByteArray (); + the_geometries[2] = m_settings->value ("geometryNoControls", saveGeometry ()).toByteArray (); + auto SWL_mode = m_settings->value ("SWLView", false).toBool (); + auto show_menus = m_settings->value ("ShowMenus", true).toBool (); + ui->actionSWL_Mode->setChecked (SWL_mode); + ui->cbMenus->setChecked (show_menus); + auto current_view_mode = SWL_mode ? 1 : show_menus ? 0 : 2; + change_layout (current_view_mode); + geometries (current_view_mode, the_geometries); restoreState (m_settings->value ("state", saveState ()).toByteArray ()); ui->dxCallEntry->setText (m_settings->value ("DXcall", QString {}).toString ()); ui->dxGridEntry->setText (m_settings->value ("DXgrid", QString {}).toString ()); @@ -1191,7 +1220,6 @@ void MainWindow::readSettings() auto displayMsgAvg = m_settings->value ("MsgAvgDisplayed", false).toBool (); auto displayFoxLog = m_settings->value ("FoxLogDisplayed", false).toBool (); auto displayContestLog = m_settings->value ("ContestLogDisplayed", false).toBool (); - ui->cbMenus->setChecked(m_settings->value("ShowMenus",true).toBool()); ui->cbFirst->setChecked(m_settings->value("CallFirst",true).toBool()); ui->comboBoxHoundSort->setCurrentIndex(m_settings->value("HoundSort",3).toInt()); ui->sbNlist->setValue(m_settings->value("FoxNlist",12).toInt()); @@ -1265,10 +1293,8 @@ void MainWindow::readSettings() m_pwrBandTuneMemory=m_settings->value("pwrBandTuneMemory").toHash(); ui->actionEnable_AP_FT8->setChecked (m_settings->value ("FT8AP", false).toBool()); ui->actionEnable_AP_JT65->setChecked (m_settings->value ("JT65AP", false).toBool()); - ui->splitter->restoreState(m_settings->value("SplitterState").toByteArray()); + ui->decodes_splitter->restoreState(m_settings->value("SplitterState").toByteArray()); ui->sbNB->setValue(m_settings->value("Blanker",0).toInt()); - ui->actionSWL_Mode->setChecked (m_settings->value ("SWLView", false).toBool ()); - on_actionSWL_Mode_triggered (ui->actionSWL_Mode->isChecked ()); { auto const& coeffs = m_settings->value ("PhaseEqualizationCoefficients" , QList {0., 0., 0., 0., 0.}).toList (); @@ -2568,34 +2594,47 @@ void MainWindow::on_actionCopyright_Notice_triggered() MessageBox::warning_message(this, message); } +// Implement the MultiGeometryWidget::change_layout() operation. +void MainWindow::change_layout (std::size_t n) +{ + switch (n) + { + case 1: // SWL view + ui->menuBar->show (); + ui->lower_panel_widget->hide (); + trim_view (false); // ensure we can switch back + break; + + case 2: // hide menus view + ui->menuBar->hide (); + ui->lower_panel_widget->show (); + trim_view (true); + break; + + default: // normal view + ui->menuBar->setVisible (ui->cbMenus->isChecked ()); + ui->lower_panel_widget->show (); + trim_view (!ui->cbMenus->isChecked ()); + break; + } +} + void MainWindow::on_actionSWL_Mode_triggered (bool checked) { - ui->lower_panel_widget->setVisible (!checked); - if (checked) - { - hideMenus (false); // make sure we can be turned off - } + select_geometry (checked ? 1 : ui->cbMenus->isChecked () ? 0 : 2); } // This allows the window to shrink by removing certain things // and reducing space used by controls -void MainWindow::hideMenus(bool checked) +void MainWindow::trim_view (bool checked) { int spacing = checked ? 1 : 6; if (checked) { statusBar ()->removeWidget (&auto_tx_label); - minimumSize().setHeight(450); - minimumSize().setWidth(700); - restoreGeometry(m_geometryNoControls); - updateGeometry(); } else { - m_geometryNoControls = saveGeometry(); statusBar ()->addWidget(&auto_tx_label); - minimumSize().setHeight(520); - minimumSize().setWidth(770); } - ui->menuBar->setVisible(!checked); - if(m_mode!="FreqCal" and m_mode!="WSPR" and m_mode!="FST4W") { + if (m_mode != "FreqCal" && m_mode != "WSPR" && m_mode != "FST4W") { ui->lh_decodes_title_label->setVisible(!checked); ui->rh_decodes_title_label->setVisible(!checked); } @@ -8437,7 +8476,7 @@ void MainWindow::update_watchdog_label () void MainWindow::on_cbMenus_toggled(bool b) { - hideMenus(!b); + select_geometry (!b ? 2 : ui->actionSWL_Mode->isChecked () ? 1 : 0); } void MainWindow::on_cbCQonly_toggled(bool) diff --git a/widgets/mainwindow.h b/widgets/mainwindow.h index c51a418de..dd53e8837 100644 --- a/widgets/mainwindow.h +++ b/widgets/mainwindow.h @@ -26,6 +26,7 @@ #include #include +#include "MultiGeometryWidget.hpp" #include "NonInheritingProcess.hpp" #include "Audio/AudioDevice.hpp" #include "commons.h" @@ -94,7 +95,8 @@ class MultiSettings; class EqualizationToolsDialog; class DecodedText; -class MainWindow : public QMainWindow +class MainWindow + : public MultiGeometryWidget<3, QMainWindow> { Q_OBJECT; @@ -130,7 +132,8 @@ public slots: void msgAvgDecode2(); void fastPick(int x0, int x1, int y); -protected: +private: + void change_layout (std::size_t) override; void keyPressEvent (QKeyEvent *) override; void closeEvent(QCloseEvent *) override; void childEvent(QChildEvent *) override; @@ -353,7 +356,7 @@ private: void astroUpdate (); void writeAllTxt(QString message); void auto_sequence (DecodedText const& message, unsigned start_tolerance, unsigned stop_tolerance); - void hideMenus(bool b); + void trim_view (bool b); void foxTest(); void setColorHighlighting(); void chkFT4(); diff --git a/widgets/mainwindow.ui b/widgets/mainwindow.ui index f4f1ed750..61affd377 100644 --- a/widgets/mainwindow.ui +++ b/widgets/mainwindow.ui @@ -2,20 +2,6 @@ MainWindow - - - 0 - 0 - 692 - 498 - - - - - 0 - 0 - - WSJT-X by K1JT @@ -25,7 +11,7 @@ - + Qt::Horizontal @@ -148,18 +134,6 @@ - - - 0 - 10 - - - - - 200 - 100 - - QFrame::StyledPanel @@ -307,12 +281,6 @@ true - - - 200 - 100 - - Qt::ScrollBarAlwaysOn @@ -2857,7 +2825,7 @@ Double-click to reset to the standard 73 message 0 0 - 692 + 834 21 From 6a44e68033e1088c0714adf39a050024635e157d Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Fri, 27 Nov 2020 12:36:24 +0000 Subject: [PATCH 19/75] Repair regression that stopped Best S&P transmitting on a match This change also ensures that second or subsequent matches in the same T/R period do not trigger a QSO with a new QSO partner. --- widgets/displaytext.cpp | 1 + widgets/displaytext.h | 3 +-- widgets/mainwindow.cpp | 4 +++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/widgets/displaytext.cpp b/widgets/displaytext.cpp index d498f180e..b083defc0 100644 --- a/widgets/displaytext.cpp +++ b/widgets/displaytext.cpp @@ -15,6 +15,7 @@ #include #include "Configuration.hpp" +#include "Decoder/decodedtext.h" #include "Network/LotWUsers.hpp" #include "models/DecodeHighlightingModel.hpp" #include "logbook/logbook.h" diff --git a/widgets/displaytext.h b/widgets/displaytext.h index 3b577e619..773901cea 100644 --- a/widgets/displaytext.h +++ b/widgets/displaytext.h @@ -8,11 +8,10 @@ #include #include -#include "Decoder/decodedtext.h" - class QAction; class Configuration; class LogBook; +class DecodedText; class DisplayText : public QTextEdit diff --git a/widgets/mainwindow.cpp b/widgets/mainwindow.cpp index eafa76545..701649aa1 100644 --- a/widgets/mainwindow.cpp +++ b/widgets/mainwindow.cpp @@ -3441,19 +3441,21 @@ void MainWindow::readFromStdout() //readFromStdout ui->cbCQonly->isVisible() && ui->cbCQonly->isChecked(), haveFSpread, fSpread); - if(m_bBestSPArmed and m_mode=="FT4") { + if(m_bBestSPArmed && m_mode=="FT4" && CALLING == m_QSOProgress) { QString messagePriority=ui->decodedTextBrowser->CQPriority(); if(messagePriority!="") { if(messagePriority=="New Call on Band" and m_BestCQpriority!="New Call on Band" and m_BestCQpriority!="New Multiplier") { m_BestCQpriority="New Call on Band"; + m_bDoubleClicked = true; processMessage(decodedtext0); } if(messagePriority=="New DXCC" and m_BestCQpriority!="New DXCC" and m_BestCQpriority!="New Multiplier") { m_BestCQpriority="New DXCC"; + m_bDoubleClicked = true; processMessage(decodedtext0); } } From dc7803fe0d12160da489643bc1a6a85144e1a43d Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Sat, 28 Nov 2020 13:47:54 +0000 Subject: [PATCH 20/75] Install some example logging configuration files --- CMakeLists.txt | 7 +++++++ example_log_configurations/README | 5 +++++ .../wsjtx_log_config.ini.console | 14 ++++++++++++++ .../wsjtx_log_config.ini.debugger | 15 +++++++++++++++ .../wsjtx_log_config.ini.simple_verbose | 14 ++++++++++++++ 5 files changed, 55 insertions(+) create mode 100644 example_log_configurations/README create mode 100644 example_log_configurations/wsjtx_log_config.ini.console create mode 100644 example_log_configurations/wsjtx_log_config.ini.debugger create mode 100644 example_log_configurations/wsjtx_log_config.ini.simple_verbose diff --git a/CMakeLists.txt b/CMakeLists.txt index 84bbfbae5..709fc350f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1573,6 +1573,13 @@ install (FILES #COMPONENT runtime ) +install (DIRECTORY + example_log_configurations + DESTINATION ${CMAKE_INSTALL_DOCDIR} + FILES_MATCHING REGEX "^.*[^~]$" + #COMPONENT runtime + ) + # # Mac installer files # diff --git a/example_log_configurations/README b/example_log_configurations/README new file mode 100644 index 000000000..d7ed52f40 --- /dev/null +++ b/example_log_configurations/README @@ -0,0 +1,5 @@ +Example WSJT-X Logging Configuration Files +========================================== + +Here you will find some typical loggin configuration files. Pick a +suitable one and copy it to the WSJT-X log files directory. diff --git a/example_log_configurations/wsjtx_log_config.ini.console b/example_log_configurations/wsjtx_log_config.ini.console new file mode 100644 index 000000000..a1076b788 --- /dev/null +++ b/example_log_configurations/wsjtx_log_config.ini.console @@ -0,0 +1,14 @@ +# +# Example logging confguration file to send records to the console terminal +# + +[Core] +# Set DisableLogging to true to disable all logging. +DisableLogging="false" + +[Sinks.Console] +Destination="Console" +Asynchronous="false" +AutoFlush="true" +Format="[%TimeStamp(format=\"%H:%M:%S.%f\")%][%Channel%:%Severity%] %Message%" +Filter="(%Channel% matches \"SYSLOG\" & %Severity% >= trace) | (%Channel% matches \"RIGCTRL\" & %Severity% >= info)" \ No newline at end of file diff --git a/example_log_configurations/wsjtx_log_config.ini.debugger b/example_log_configurations/wsjtx_log_config.ini.debugger new file mode 100644 index 000000000..71056aee5 --- /dev/null +++ b/example_log_configurations/wsjtx_log_config.ini.debugger @@ -0,0 +1,15 @@ +# +# Example WSJT-X logging configuration for sending records to the +# attached Windows debugger (e.g. gdb) +# + +[Core] +# Set DisableLogging to true to disable all logging. +DisableLogging="false" + +[Sinks.Debugger] +Destination="Debugger" +Asynchronous="false" +AutoFlush="true" +Format="[%TimeStamp(format=\"%H:%M:%S.%f\")%][%Channel%][%Severity%] %File%(%Line%) %Function%: %Message%" +Filter="(%Channel% matches \"SYSLOG\" & %Severity% >= debug) | (%Channel% matches \"RIGCTRL\" & %Severity% >= info)" \ No newline at end of file diff --git a/example_log_configurations/wsjtx_log_config.ini.simple_verbose b/example_log_configurations/wsjtx_log_config.ini.simple_verbose new file mode 100644 index 000000000..26047ebb0 --- /dev/null +++ b/example_log_configurations/wsjtx_log_config.ini.simple_verbose @@ -0,0 +1,14 @@ +[Sinks.SYSLOG] +Destination="TextFile" +Asynchronous="true" +AutoFlush="true" +Format="[%TimeStamp(format=\"%Y-%m-%d %H:%M:%S.%f\")%][%Uptime(format=\"%O:%M:%S.%f\")%][%Channel%][%Severity%] %File%(%Line%) %Function%: %Message%" +RotationTimePoint="11:42:00" +Target="${AppLocalDataLocation}/logs" +FileName="${AppLocalDataLocation}/wsjtx_syslog.log" +TargetFileName="${AppLocalDataLocation}/logs/wsjtx_syslog_%Y-%m_%3N.log" +Append="true" +EnableFinalRotation="false" +ScanForFiles="Matching" +MaxSize=1073741824 +MaxFiles="10" From 462ef827c99dcc5614ecec64c34aec30f7e0dedc Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Sat, 28 Nov 2020 13:48:49 +0000 Subject: [PATCH 21/75] Shorten some diagnostic messages --- Configuration.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Configuration.cpp b/Configuration.cpp index f409e66e5..2b668f902 100644 --- a/Configuration.cpp +++ b/Configuration.cpp @@ -812,7 +812,7 @@ bool Configuration::is_dummy_rig () const bool Configuration::transceiver_online () { - LOG_TRACE ("transceiver_online: " << m_->cached_rig_state_); + LOG_TRACE (m_->cached_rig_state_); return m_->have_rig (); } @@ -823,37 +823,37 @@ int Configuration::transceiver_resolution () const void Configuration::transceiver_offline () { - LOG_TRACE ("transceiver_offline: " << m_->cached_rig_state_); + LOG_TRACE (m_->cached_rig_state_); m_->close_rig (); } void Configuration::transceiver_frequency (Frequency f) { - LOG_TRACE ("transceiver_frequency: " << f << m_->cached_rig_state_); + LOG_TRACE (f << ' ' << m_->cached_rig_state_); m_->transceiver_frequency (f); } void Configuration::transceiver_tx_frequency (Frequency f) { - LOG_TRACE ("transceiver_tx_frequency: " << f << m_->cached_rig_state_); + LOG_TRACE (f << ' ' << m_->cached_rig_state_); m_->transceiver_tx_frequency (f); } void Configuration::transceiver_mode (MODE mode) { - LOG_TRACE ("transceiver_mode: " << mode << " " << m_->cached_rig_state_); + LOG_TRACE (mode << ' ' << m_->cached_rig_state_); m_->transceiver_mode (mode); } void Configuration::transceiver_ptt (bool on) { - LOG_TRACE ("transceiver_ptt: " << on << " " << m_->cached_rig_state_); + LOG_TRACE (on << ' ' << m_->cached_rig_state_); m_->transceiver_ptt (on); } void Configuration::sync_transceiver (bool force_signal, bool enforce_mode_and_split) { - LOG_TRACE ("sync_transceiver: force signal: " << force_signal << " enforce_mode_and_split: " << enforce_mode_and_split << " " << m_->cached_rig_state_); + LOG_TRACE ("force signal: " << force_signal << " enforce_mode_and_split: " << enforce_mode_and_split << ' ' << m_->cached_rig_state_); m_->sync_transceiver (force_signal); if (!enforce_mode_and_split) { @@ -2838,7 +2838,7 @@ void Configuration::impl::sync_transceiver (bool /*force_signal*/) void Configuration::impl::handle_transceiver_update (TransceiverState const& state, unsigned sequence_number) { - LOG_TRACE ("handle_transceiver_update: Transceiver State #: " << sequence_number << " " << state); + LOG_TRACE ("#: " << sequence_number << ' ' << state); // only follow rig on some information, ignore other stuff cached_rig_state_.online (state.online ()); From 3352220715de61478bdfe54a9a092a0c6285fc41 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Sat, 28 Nov 2020 13:49:35 +0000 Subject: [PATCH 22/75] Clean up logging initialization and setup --- Logger.cpp | 1 - WSJTXLogging.cpp | 118 +++++++++++++++++++++++------------------------ WSJTXLogging.hpp | 12 ----- main.cpp | 8 ++-- 4 files changed, 60 insertions(+), 79 deletions(-) diff --git a/Logger.cpp b/Logger.cpp index 6c92ca407..00e5597b1 100644 --- a/Logger.cpp +++ b/Logger.cpp @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include diff --git a/WSJTXLogging.cpp b/WSJTXLogging.cpp index ffea213c8..bb6171609 100644 --- a/WSJTXLogging.cpp +++ b/WSJTXLogging.cpp @@ -10,7 +10,6 @@ #include #include #include -#include #include #include #include @@ -19,6 +18,7 @@ #include #include +#include #include #include #include @@ -60,12 +60,62 @@ namespace //throw; } }; + + // Reroute Qt messages to the system logger + void qt_log_handler (QtMsgType type, QMessageLogContext const& context, QString const& msg) + { + // Convert Qt message types to logger severities + auto severity = trivial::trace; + switch (type) + { + case QtDebugMsg: severity = trivial::debug; break; + case QtInfoMsg: severity = trivial::info; break; + case QtWarningMsg: severity = trivial::warning; break; + case QtCriticalMsg: severity = trivial::error; break; + case QtFatalMsg: severity = trivial::fatal; break; + } + // Map non-default Qt categories to logger channels, Qt logger + // context is mapped to the appropriate logger attributes. + auto log = sys::get (); + std::string file; + std::string function; + if (context.file) + { + file = context.file; + } + if (context.function) + { + function = context.function; + } + if (!context.category || !qstrcmp (context.category, "default")) + { + BOOST_LOG_SEV (log, severity) + << boost::log::add_value ("Line", context.line) + << boost::log::add_value ("File", file) + << boost::log::add_value ("Function", function) + << msg.toStdString (); + } + else + { + BOOST_LOG_CHANNEL_SEV (log, std::string {context.category}, severity) + << boost::log::add_value ("Line", context.line) + << boost::log::add_value ("File", file) + << boost::log::add_value ("Function", function) + << msg.toStdString (); + } + if (QtFatalMsg == type) + { + // bail out + throw std::runtime_error {"Fatal Qt Error"}; + } + } } WSJTXLogging::WSJTXLogging () { + auto core = logging::core::get (); // Catch relevant exceptions from logging. - logging::core::get ()->set_exception_handler + core->set_exception_handler ( logging::make_exception_handler (exception_handler {}) ); @@ -120,7 +170,6 @@ WSJTXLogging::WSJTXLogging () // Default log file location. QDir app_data {QStandardPaths::writableLocation (QStandardPaths::AppLocalDataLocation)}; Logger::init (); // Basic setup of attributes - auto core = logging::core::get (); // // Sink intended for general use that passes everything above @@ -175,70 +224,17 @@ WSJTXLogging::WSJTXLogging () ); core->add_sink (sys_sink); - -#if !defined (NDEBUG) && defined (Q_OS_WIN) - // auto windbg_sink = boost::make_shared> (); - // windbg_sink->set_filter (trivial::severity >= trivial::trace && expr::is_debugger_present ()); - // core->add_sink (windbg_sink); -#endif } + // Indicate start of logging LOG_INFO ("Log Start"); + ::qInstallMessageHandler (&qt_log_handler); } WSJTXLogging::~WSJTXLogging () { LOG_INFO ("Log Finish"); - auto lg = logging::core::get (); - lg->flush (); - lg->remove_all_sinks (); -} - -// Reroute Qt messages to the system logger -void WSJTXLogging::qt_log_handler (QtMsgType type, QMessageLogContext const& context, QString const& msg) -{ - // Convert Qt message types to logger severities - auto severity = trivial::trace; - switch (type) - { - case QtDebugMsg: severity = trivial::debug; break; - case QtInfoMsg: severity = trivial::info; break; - case QtWarningMsg: severity = trivial::warning; break; - case QtCriticalMsg: severity = trivial::error; break; - case QtFatalMsg: severity = trivial::fatal; break; - } - // Map non-default Qt categories to logger channels, Qt logger - // context is mapped to the appropriate logger attributes. - auto log = sys::get (); - std::string file; - std::string function; - if (context.file) - { - file = context.file; - } - if (context.function) - { - function = context.function; - } - if (!context.category || !qstrcmp (context.category, "default")) - { - BOOST_LOG_SEV (log, severity) - << boost::log::add_value ("Line", context.line) - << boost::log::add_value ("File", file) - << boost::log::add_value ("Function", function) - << msg.toStdString (); - } - else - { - BOOST_LOG_CHANNEL_SEV (log, std::string {context.category}, severity) - << boost::log::add_value ("Line", context.line) - << boost::log::add_value ("File", file) - << boost::log::add_value ("Function", function) - << msg.toStdString (); - } - if (QtFatalMsg == type) - { - // bail out - throw std::runtime_error {"Fatal Qt Error"}; - } + auto core = logging::core::get (); + core->flush (); + core->remove_all_sinks (); } diff --git a/WSJTXLogging.hpp b/WSJTXLogging.hpp index d36e9afd2..4ecedbf78 100644 --- a/WSJTXLogging.hpp +++ b/WSJTXLogging.hpp @@ -1,10 +1,6 @@ #ifndef WSJTX_LOGGING_HPP__ #define WSJTX_LOGGING_HPP__ -#include - -class QString; - // // Class WSJTXLogging - wraps application specific logging // @@ -13,14 +9,6 @@ class WSJTXLogging final public: explicit WSJTXLogging (); ~WSJTXLogging (); - - // - // Install this as the Qt message handler (qInstallMessageHandler) - // to integrate Qt messages. This handler can be installed at any - // time, it does not rely on an instance of WSJTXLogging existing, - // so logging occurring before the logging sinks, filters, and - // formatters, etc, are established can take place. - static void qt_log_handler (QtMsgType type, QMessageLogContext const& context, QString const&); }; #endif diff --git a/main.cpp b/main.cpp index 9e2403de1..c6dd0ccbf 100644 --- a/main.cpp +++ b/main.cpp @@ -104,7 +104,6 @@ namespace int main(int argc, char *argv[]) { - ::qInstallMessageHandler (&WSJTXLogging::qt_log_handler); init_random_seed (); // make the Qt type magic happen @@ -211,7 +210,9 @@ int main(int argc, char *argv[]) multiple = true; } - // now we have the application name we can open the settings + // now we have the application name we can open the logging and settings + WSJTXLogging lg; + LOG_INFO (program_title (revision ()) << " - Program startup"); MultiSettings multi_settings {parser.value (cfg_option)}; // find the temporary files path @@ -247,9 +248,6 @@ int main(int argc, char *argv[]) } } - WSJTXLogging lg; - LOG_INFO (program_title (revision ()) << " - Program startup"); - // load UI translations L10nLoader l10n {&a, locale, parser.value (lang_option)}; From 48cb207cd3f46ac5c77862dcb4b047699308f335 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Sun, 29 Nov 2020 13:08:35 +0000 Subject: [PATCH 23/75] Bump RC number --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 709fc350f..1597eddca 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -70,7 +70,7 @@ message (STATUS "******************************************************") include (set_build_type) # RC 0 or omitted is a development build, GA is a General Availability release build -set_build_type (RC 2) +set_build_type (RC 3) set (wsjtx_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}${BUILD_TYPE_REVISION}") # From d186f7b14e995179a7fe24c1efc8dac670f92f1f Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Mon, 30 Nov 2020 02:13:16 +0000 Subject: [PATCH 24/75] Repair regression in message_aggregator decode filtering by client --- UDPExamples/ClientWidget.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/UDPExamples/ClientWidget.cpp b/UDPExamples/ClientWidget.cpp index 3be8c788c..75930b7e5 100644 --- a/UDPExamples/ClientWidget.cpp +++ b/UDPExamples/ClientWidget.cpp @@ -5,7 +5,6 @@ #include #include #include -#include #include "validators/MaidenheadLocatorValidator.hpp" @@ -73,7 +72,7 @@ bool ClientWidget::IdFilterModel::filterAcceptsRow (int source_row , QModelIndex const& source_parent) const { auto source_index_col0 = sourceModel ()->index (source_row, 0, source_parent); - return sourceModel ()->data (source_index_col0).value () == key_; + return sourceModel ()->data (source_index_col0, Qt::UserRole + 1).value () == key_; } void ClientWidget::IdFilterModel::de_call (QString const& call) From 2db2884c399d59170c81c88309dd460395a319d4 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Tue, 1 Dec 2020 15:11:36 +0000 Subject: [PATCH 25/75] Fix regression with selecting a working frequency when changing mode --- models/FrequencyList.cpp | 1 + widgets/mainwindow.cpp | 4 ---- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/models/FrequencyList.cpp b/models/FrequencyList.cpp index 3c4a43012..b14dae6f9 100644 --- a/models/FrequencyList.cpp +++ b/models/FrequencyList.cpp @@ -580,6 +580,7 @@ auto FrequencyList_v2::impl::frequency_list (FrequencyItems frequency_list) -> F return frequency_list; } +// add a frequency returning the new model index QModelIndex FrequencyList_v2::impl::add (Item f) { // Any Frequency that isn't in the list may be added diff --git a/widgets/mainwindow.cpp b/widgets/mainwindow.cpp index 701649aa1..7e7bf0ebf 100644 --- a/widgets/mainwindow.cpp +++ b/widgets/mainwindow.cpp @@ -7609,10 +7609,6 @@ void MainWindow::on_sbTR_valueChanged(int value) progressBar.setMaximum (value); } if(m_mode=="FST4") chk_FST4_freq_range(); - if(m_monitoring) { - on_stopButton_clicked(); - on_monitorButton_clicked(true); - } if(m_transmitting) { on_stopTxButton_clicked(); } From 4492d8e977eab6c558b86f1a20665e6eada12ba7 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Tue, 1 Dec 2020 15:47:07 +0000 Subject: [PATCH 26/75] Add tool-tip for "Best S+P" push-button --- widgets/mainwindow.ui | 3 +++ 1 file changed, 3 insertions(+) diff --git a/widgets/mainwindow.ui b/widgets/mainwindow.ui index 61affd377..948bfc68f 100644 --- a/widgets/mainwindow.ui +++ b/widgets/mainwindow.ui @@ -1185,6 +1185,9 @@ Not available to nonstandard callsign holders. + + Enable auto response to the first decode from a new DXCC or new call on the current band. + QPushButton:checked { color: rgb(0, 0, 0); From 6214cc9835d7cff2400e0d3d556cbdf7582194e5 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Tue, 1 Dec 2020 20:55:10 +0000 Subject: [PATCH 27/75] Use same user defined audio out buffer sizes on all platforms --- Audio/soundout.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Audio/soundout.cpp b/Audio/soundout.cpp index fe7c58fbf..bd71d8560 100644 --- a/Audio/soundout.cpp +++ b/Audio/soundout.cpp @@ -106,9 +106,9 @@ void SoundOutput::restart (QIODevice * source) //qDebug () << "SoundOut default buffer size (bytes):" << m_stream->bufferSize () << "period size:" << m_stream->periodSize (); if (m_framesBuffered) { -#if defined (Q_OS_WIN) + //#if defined (Q_OS_WIN) m_stream->setBufferSize (m_stream->format().bytesForFrames (m_framesBuffered)); -#endif + //#endif } m_stream->setCategory ("production"); m_stream->start (source); From 041c6b68fec60a8a161cabcb364036bfbc9fb786 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Tue, 1 Dec 2020 21:05:01 +0000 Subject: [PATCH 28/75] Reduce non-Windows Tx audio buffer size --- Audio/soundout.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Audio/soundout.cpp b/Audio/soundout.cpp index bd71d8560..d64f3fb2c 100644 --- a/Audio/soundout.cpp +++ b/Audio/soundout.cpp @@ -106,9 +106,11 @@ void SoundOutput::restart (QIODevice * source) //qDebug () << "SoundOut default buffer size (bytes):" << m_stream->bufferSize () << "period size:" << m_stream->periodSize (); if (m_framesBuffered) { - //#if defined (Q_OS_WIN) +#if defined (Q_OS_WIN) m_stream->setBufferSize (m_stream->format().bytesForFrames (m_framesBuffered)); - //#endif +#else + m_stream->setBufferSize (m_stream->format().bytesForFrames (3456)); +#endif } m_stream->setCategory ("production"); m_stream->start (source); From 5f85dfac61119446878db794c82d5ec6f2a36f95 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Tue, 1 Dec 2020 21:24:41 +0000 Subject: [PATCH 29/75] Looking for a Tx audio buffer size that works on macOS. --- Audio/soundout.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Audio/soundout.cpp b/Audio/soundout.cpp index d64f3fb2c..6a99afd34 100644 --- a/Audio/soundout.cpp +++ b/Audio/soundout.cpp @@ -109,10 +109,10 @@ void SoundOutput::restart (QIODevice * source) #if defined (Q_OS_WIN) m_stream->setBufferSize (m_stream->format().bytesForFrames (m_framesBuffered)); #else - m_stream->setBufferSize (m_stream->format().bytesForFrames (3456)); + m_stream->setBufferSize (m_stream->format().bytesForFrames (48000 / 10)); #endif } - m_stream->setCategory ("production"); + m_stream->setCategory ("game"); m_stream->start (source); // qDebug () << "SoundOut selected buffer size (bytes):" << m_stream->bufferSize () << "period size:" << m_stream->periodSize (); } From 917e87cee57e1972474b48a8c03f6050965b3fc6 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Wed, 2 Dec 2020 00:40:37 +0000 Subject: [PATCH 30/75] Handle Qt logging category when redirecting to SYSLOG channel --- WSJTXLogging.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/WSJTXLogging.cpp b/WSJTXLogging.cpp index bb6171609..ffa563b23 100644 --- a/WSJTXLogging.cpp +++ b/WSJTXLogging.cpp @@ -97,11 +97,11 @@ namespace } else { - BOOST_LOG_CHANNEL_SEV (log, std::string {context.category}, severity) + BOOST_LOG_SEV (log, severity) << boost::log::add_value ("Line", context.line) << boost::log::add_value ("File", file) << boost::log::add_value ("Function", function) - << msg.toStdString (); + << context.category << ": " << msg.toStdString (); } if (QtFatalMsg == type) { From 94f0af72e3c2edbb0b1ed7cc9404ca73f276114b Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Wed, 2 Dec 2020 01:53:36 +0000 Subject: [PATCH 31/75] Command line tool prints WSJT-X version to console, tnx Dave, W3DJS --- AppVersion/AppVersion.cpp | 43 +++++++++++++++++++++++++++++++++++++++ CMakeLists.txt | 11 +++++++++- widgets/about.cpp | 2 +- 3 files changed, 54 insertions(+), 2 deletions(-) create mode 100644 AppVersion/AppVersion.cpp diff --git a/AppVersion/AppVersion.cpp b/AppVersion/AppVersion.cpp new file mode 100644 index 000000000..26cac2c10 --- /dev/null +++ b/AppVersion/AppVersion.cpp @@ -0,0 +1,43 @@ +// +// wsjtx_app_version - a console application that outputs WSJT-X +// application version +// +// This application is only provided as a simple console application +// +// + +#include +#include +#include + +#include +#include +#include + +#include "revision_utils.hpp" + +int main (int argc, char * argv[]) +{ + QCoreApplication app {argc, argv}; + try + { + app.setApplicationName ("WSJT-X"); + app.setApplicationVersion (version()); + + QCommandLineParser parser; +// parser.setApplicationDescription ("\n" PROJECT_DESCRIPTION); + parser.addHelpOption (); + parser.addVersionOption (); + parser.process (app); + return EXIT_SUCCESS; + } + catch (std::exception const& e) + { + std::cerr << "Error: " << e.what () << '\n'; + } + catch (...) + { + std::cerr << "Unexpected error\n"; + } + return -1; +} diff --git a/CMakeLists.txt b/CMakeLists.txt index 1597eddca..e9c6db665 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1457,6 +1457,15 @@ generate_version_info (udp_daemon_VERSION_RESOURCES add_executable (udp_daemon UDPExamples/UDPDaemon.cpp ${udp_daemon_VERSION_RESOURCES}) target_link_libraries (udp_daemon wsjtx_udp-static) +generate_version_info (wsjtx_app_version_VERSION_RESOURCES + NAME wsjtx_app_version + BUNDLE ${PROJECT_BUNDLE_NAME} + ICON ${WSJTX_ICON_FILE} + FILE_DESCRIPTION "Display WSJT-X Application Version on console" + ) +add_executable (wsjtx_app_version AppVersion/AppVersion.cpp ${wsjtx_app_version_VERSION_RESOURCES}) +target_link_libraries (wsjtx_app_version wsjt_qt) + generate_version_info (message_aggregator_VERSION_RESOURCES NAME message_aggregator BUNDLE ${PROJECT_BUNDLE_NAME} @@ -1516,7 +1525,7 @@ install (TARGETS wsjtx # DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/wsjtx # ) -install (TARGETS udp_daemon message_aggregator +install (TARGETS udp_daemon message_aggregator wsjtx_app_version RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT runtime BUNDLE DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT runtime ) diff --git a/widgets/about.cpp b/widgets/about.cpp index b8e0fab43..908e6e38d 100644 --- a/widgets/about.cpp +++ b/widgets/about.cpp @@ -23,7 +23,7 @@ CAboutDlg::CAboutDlg(QWidget *parent) : "We gratefully acknowledge contributions from AC6SL, AE4JY,
" "DF2ET, DJ0OT, G3WDG, G4KLA, IV3NWV, IW3RAB, KA1GT, K3WYC,
" "KA6MAL, KA9Q, KB1ZMX, KD6EKQ, KI7MT, KK1D, ND0B, PY2SDR,
" - "VE1SKY, VK3ACF, VK4BDJ, VK7MO, W4TI, W4TV, and W9MDB.

" + "VE1SKY, VK3ACF, VK4BDJ, VK7MO, W3DJS, W4TI, W4TV, and W9MDB.

" "WSJT-X is licensed under the terms of Version 3
" "of the GNU General Public License (GPL)

" "" From 50d0543c0384437a164816f929e033b104b72049 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Thu, 3 Dec 2020 01:49:21 +0000 Subject: [PATCH 32/75] Test version with environment variable to set Tx audio buffer size WSJT_TX_AUDIO_BUFFER_FRAMES takes the following values: -1 - use Qt/system default 0 - use 200 mS (WSJT-X default) +ve integer - value is number of frames at 48 kHz -1 is likely to be a good choice on Windows and may macOS. 0 has proven to be good on Windows. On Linux 0 may be OK but we need to try other values. The value is only a hint, the actual value used along with the period size (the size of each chunk of samples requested by the system) is printed in an info level diagnostic message at the start of each transmission. --- Audio/soundout.cpp | 9 +++------ widgets/mainwindow.cpp | 10 +++++++--- widgets/mainwindow.h | 1 + 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/Audio/soundout.cpp b/Audio/soundout.cpp index 6a99afd34..54b765e22 100644 --- a/Audio/soundout.cpp +++ b/Audio/soundout.cpp @@ -7,6 +7,7 @@ #include #include +#include "Logger.hpp" #include "Audio/AudioDevice.hpp" #include "moc_soundout.cpp" @@ -104,17 +105,13 @@ void SoundOutput::restart (QIODevice * source) // Windows implementation seems to forget the buffer size after a // stop. //qDebug () << "SoundOut default buffer size (bytes):" << m_stream->bufferSize () << "period size:" << m_stream->periodSize (); - if (m_framesBuffered) + if (m_framesBuffered > 0) { -#if defined (Q_OS_WIN) m_stream->setBufferSize (m_stream->format().bytesForFrames (m_framesBuffered)); -#else - m_stream->setBufferSize (m_stream->format().bytesForFrames (48000 / 10)); -#endif } m_stream->setCategory ("game"); m_stream->start (source); - // qDebug () << "SoundOut selected buffer size (bytes):" << m_stream->bufferSize () << "period size:" << m_stream->periodSize (); + LOG_INFO ("Selected buffer size (bytes): " << m_stream->bufferSize () << " period size: " << m_stream->periodSize ()); } void SoundOutput::suspend () diff --git a/widgets/mainwindow.cpp b/widgets/mainwindow.cpp index 7e7bf0ebf..aaec4e558 100644 --- a/widgets/mainwindow.cpp +++ b/widgets/mainwindow.cpp @@ -212,7 +212,7 @@ namespace auto quint32_max = std::numeric_limits::max (); constexpr int N_WIDGETS {36}; constexpr int rx_chunk_size {3456}; // audio samples at 12000 Hz - constexpr int tx_audio_buffer_size {48000 / 5}; // audio frames at 48000 Hz + constexpr int default_tx_audio_buffer_frames {48000 / 5}; // audio frames at 48000 Hz bool message_is_73 (int type, QStringList const& msg_parts) { @@ -265,6 +265,7 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple, m_soundInput {new SoundInput}, m_modulator {new Modulator {TX_SAMPLE_RATE, NTMAX}}, m_soundOutput {new SoundOutput}, + m_tx_audio_buffer_frames {0}, m_msErase {0}, m_secBandChanged {0}, m_freqNominal {0}, @@ -455,6 +456,9 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple, m_modulator->moveToThread (&m_audioThread); m_soundInput->moveToThread (&m_audioThread); m_detector->moveToThread (&m_audioThread); + bool ok; + auto buffer_size = env.value ("WSJT_TX_AUDIO_BUFFER_FRAMES", "0").toInt (&ok); + m_tx_audio_buffer_frames = ok && buffer_size ? buffer_size : default_tx_audio_buffer_frames; // hook up sound output stream slots & signals and disposal connect (this, &MainWindow::initializeAudioOutputStream, m_soundOutput, &SoundOutput::setFormat); @@ -942,7 +946,7 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple, { Q_EMIT initializeAudioOutputStream (m_config.audio_output_device () , AudioDevice::Mono == m_config.audio_output_channel () ? 1 : 2 - , tx_audio_buffer_size); + , m_tx_audio_buffer_frames); } Q_EMIT transmitFrequency (ui->TxFreqSpinBox->value () - m_XIT); @@ -1855,7 +1859,7 @@ void MainWindow::on_actionSettings_triggered() //Setup Dialog if(m_config.restart_audio_output () && !m_config.audio_output_device ().isNull ()) { Q_EMIT initializeAudioOutputStream (m_config.audio_output_device () , AudioDevice::Mono == m_config.audio_output_channel () ? 1 : 2 - , tx_audio_buffer_size); + , m_tx_audio_buffer_frames); } displayDialFrequency (); diff --git a/widgets/mainwindow.h b/widgets/mainwindow.h index dd53e8837..878e9c6c3 100644 --- a/widgets/mainwindow.h +++ b/widgets/mainwindow.h @@ -404,6 +404,7 @@ private: SoundInput * m_soundInput; Modulator * m_modulator; SoundOutput * m_soundOutput; + int m_tx_audio_buffer_frames; QThread m_audioThread; qint64 m_msErase; From 88f18e7528d071bd7b2ef986b5ae4849e7e3b4e3 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Thu, 3 Dec 2020 11:55:21 +0000 Subject: [PATCH 33/75] Updated Catalan UI translation, tnx Xavi, EA3W. --- translations/wsjtx_ca.ts | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/translations/wsjtx_ca.ts b/translations/wsjtx_ca.ts index e8e99b115..dc578b791 100644 --- a/translations/wsjtx_ca.ts +++ b/translations/wsjtx_ca.ts @@ -634,7 +634,8 @@ Format: Not found audio device missing - + falta un dispositiu d'àudio + No trobat @@ -2712,12 +2713,12 @@ Si no està marcat, pots veure els resultats de la calibració. F High - + F Alt F Low - + F Baixa @@ -2964,12 +2965,12 @@ La llista es pot mantenir a la configuració (F2). SWL Mode - + Mode SWL Hide lower panel controls to maximize deocde windows - + Amaga els controls del panell inferior per a maximitzar les finestres de descodificació Calling CQ @@ -3868,7 +3869,7 @@ La llista es pot mantenir a la configuració (F2). Excessive dropped samples - %1 (%2 sec) audio frames dropped in period starting %3 - + Mostres caigudes excessives - %1 (%2 sec) fotogrames d'àudio caiguts en el període inicial %3 @@ -3893,7 +3894,7 @@ La llista es pot mantenir a la configuració (F2). Enumerating audio devices - + Enumeració de dispositius d’àudio From 0b2a9c19534e66577699a16f4ff66db9c3770aee Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Thu, 3 Dec 2020 11:56:01 +0000 Subject: [PATCH 34/75] =?UTF-8?q?Updated=20Spanish=20UI=20translation,=20t?= =?UTF-8?q?nx=20C=C3=A9dric,=20EA4AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- translations/wsjtx_es.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/translations/wsjtx_es.ts b/translations/wsjtx_es.ts index 38da0087a..cd58e874c 100644 --- a/translations/wsjtx_es.ts +++ b/translations/wsjtx_es.ts @@ -2904,13 +2904,13 @@ Amarillo cuando esta muy bajo. Check to Tx in even-numbered minutes or sequences, starting at 0; uncheck for odd sequences. Marca a TX en minutos o secuencias de números pares, a partir de 0; desmarca las secuencias impares. - Marcar para transmitir en secuencias o minutos pares, comenzando por 0; desmarca para transmitir en las secuencias o minutos impares. + Marcar para transmitir en secuencias o minutos pares, comenzando por 0; desmarca para transmitir en las secuencias o minutos impares. Tx even/1st Alternar periodo TX Par/Impar - TX segundo par + Tx primer par/1ro From 5b10479cb447a233e4aada9d4fa97cb8338e4f28 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Thu, 3 Dec 2020 11:56:50 +0000 Subject: [PATCH 35/75] Updated Chinese and Hong Kong UI translations, tnx Sze-to, VR2UPU --- translations/wsjtx_zh.ts | 150 ++++++++++++++++++++++++------------ translations/wsjtx_zh_HK.ts | 72 ++++++++++++++--- 2 files changed, 161 insertions(+), 61 deletions(-) diff --git a/translations/wsjtx_zh.ts b/translations/wsjtx_zh.ts index cc7652ad6..f163e86be 100644 --- a/translations/wsjtx_zh.ts +++ b/translations/wsjtx_zh.ts @@ -388,7 +388,7 @@ path: "%1% - 目錄: "%1% + 目录: "%1% @@ -504,7 +504,12 @@ Format: 您必须输入有效的 ARRL RTTY Roundup 交换数据 - + + Pending DNS lookup, please try again later + 等待域名系统查找,请稍后再试 + + + Reset Decode Highlighting 重置解码突出显示 @@ -519,7 +524,17 @@ Format: WSJT-X 解码文本字体选择 - + + UDP server DNS lookup failed + UDP服务器域名系统查找失败 + + + + MAC-ambiguous multicast groups addresses not supported + 不支持媒体访问控制不明确的多播组地址 + + + Load Working Frequencies 载入工作频率 @@ -2670,12 +2685,12 @@ Not available to nonstandard callsign holders. <html><head/><body><p>Submode determines tone spacing; A is narrowest.</p></body></html> - <html><head/><body><p>子模式確定音調間距; A 最窄.</p></body></html> + <html><head/><body><p>子模式确定音调间距离; A 最窄.</p></body></html> Submode determines tone spacing; A is narrowest. - 子模式確定音調間距; A 最窄. + 子模式确定音调间距离; A 最窄. @@ -3664,12 +3679,12 @@ list. The list can be maintained in Settings (F2). 降低系统负载 - + Excessive dropped samples - %1 (%2 sec) audio frames dropped in period starting %3 样品丢失过多 - %1 (%2 sec) 音频帧在周期开始时丢失 %3 - + Error Scanning ADIF Log 扫描 ADIF 日志错误 @@ -3870,7 +3885,7 @@ list. The list can be maintained in Settings (F2). "fmt.all" 文件将重命名为 "fmt.bak" - + If you make fair use of any part of WSJT-X under terms of the GNU General Public License, you must display the following copyright notice prominently in your derivative work: "The algorithms, source code, look-and-feel of WSJT-X and related programs, and protocol specifications for the modes FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 are Copyright (C) 2001-2020 by one or more of the following authors: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q; and other members of the WSJT Development Group." @@ -3879,7 +3894,7 @@ list. The list can be maintained in Settings (F2). "WSJT-X 的算法, 源代码, 外观和感觉及相关程序,和协议规格模式 FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 的版权 (C) 2001-2019 由以下一个或多个作者: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q; 和 WSJT 开发组的其他成员." - + No data read from disk. Wrong file format? 没有从磁盘读取数据. 文件格式出错误? @@ -3899,42 +3914,7 @@ list. The list can be maintained in Settings (F2). 键盘快捷键 - - Special Mouse Commands - 特殊鼠标组合 - - - - No more files to open. - 没有要打开的文件. - - - - Spotting to PSK Reporter unavailable - 无法发送至PSK Reporter - - - - Please choose another Tx frequency. WSJT-X will not knowingly transmit another mode in the WSPR sub-band on 30m. - 请选择其他发射频率. WSJT-X 不会故意传输另一个模式在 WSPR 30米子波段上. - - - - WSPR Guard Band - WSPR保护波段 - - - - Please choose another dial frequency. WSJT-X will not operate in Fox mode in the standard FT8 sub-bands. - 请选择其它频率. WSJT-X 不会运行狐狸模式在标准 FT8 波段. - - - - Fox Mode warning - 狐狸模式警告 - - - + <table cellspacing=1> <tr><td><b>Esc </b></td><td>Stop Tx, abort QSO, clear next-call queue</td></tr> <tr><td><b>F1 </b></td><td>Online User's Guide (Alt: transmit Tx6)</td></tr> @@ -4028,7 +4008,12 @@ list. The list can be maintained in Settings (F2). </table> - + + Special Mouse Commands + 特殊鼠标组合 + + + <table cellpadding=5> <tr> <th align="right">Click on</th> @@ -4092,6 +4077,36 @@ list. The list can be maintained in Settings (F2). </tr> </table> + + + No more files to open. + 没有要打开的文件. + + + + Spotting to PSK Reporter unavailable + 发送到 Pskreporter 不可用 + + + + Please choose another Tx frequency. WSJT-X will not knowingly transmit another mode in the WSPR sub-band on 30m. + 请选择另一个发射频率. WSJT-X 不会故意在 30m 的 WSPR 子频段中传输另一种模式. + + + + WSPR Guard Band + WSPR 守护波段 + + + + Please choose another dial frequency. WSJT-X will not operate in Fox mode in the standard FT8 sub-bands. + 请选择另一个频率. WSJT-X在标准的FT8子带中不会以狐狸模式工作. + + + + Fox Mode warning + 狐狸模式警告 + Last Tx: %1 @@ -5409,6 +5424,11 @@ quiet period when decoding is done. Data bits 数据位元 + + + Data Bits + 数据位元 + D&efault @@ -5434,6 +5454,11 @@ quiet period when decoding is done. Stop bits 停止位元 + + + Stop Bits + 停止位元 + @@ -5615,7 +5640,7 @@ or bandwidth is selected). None - + @@ -5748,7 +5773,32 @@ transmitting periods. 向外发射输出. - + + <html><head/><body><p>Enter the service port number of the UDP server that WSJT-X should send updates to. If this is zero no updates will be sent.</p></body></html> + <html><head/><body><p>输入WSJT-X应该向其发送更新的UDP服务器的服务端口号. 如果该值为零则不会发送任何更新.</p></body></html> + + + + Outgoing interfaces: + 传出接口: + + + + <html><head/><body><p>When sending updates to a multicast group address it is necessary to specify which network interface(s) to send them to. If the loop-back interface is multicast capable then at least that one will be selected.</p><p>For most users the loop-back interface is all that is needed, that will allow multiple other applications on the same machine to interoperate with WSJT-X. If applications running on other hosts are to receive status updates then a suitable network interface should be used.</p><p>On some Linux systems it may be necessary to enable multicast on the loop-back network interface.</p></body></html> + <html><head/><body><p>向多播组地址发送更新时需要指定将更新发送到哪个网络接口. 如果环回接口支持多播那么将至少选择该接口.</p><p>对于大多数用户来说环回接口是他们所需要的, 这将允许同一台机器上的多个其他应用程序与WSJT-X进行互操作. 如果运行在其他主机上的应用程序要接收状态更新则应使用合适的网络接口.</p><p>在某些Linux系统上可能需要在环回网络接口上启用多播.</p></body></html> + + + + <html><head/><body><p>Sets the number or router hops that multicast datagrams are allowed to make. Almost everyone should set this to 1 to keep outgoing multicast traffic withn the local subnet.</p></body></html> + <html><head/><body><p>设置允许多点传送数据报的资料元或路由器资料元. 几乎每个人都应该将该值设置为 1 以保持出站多点传送流量在本地子网中.</p></body></html> + + + + Multicast TTL: + 多点传送 TTL: + + + Days since last upload 自上次上传以来的天数 @@ -5808,7 +5858,7 @@ both here. 启用甚高频和子模式功能 - + Ou&tput: 输出(&t): @@ -6525,7 +6575,7 @@ Right click for insert and delete options. <html><head/><body><p>Generate Tx audio with four times the normal tone spacing. Intended for special LF/MF transmitters that use a divide-by-4 before generating RF.</p></body></html> - <html><head/><body><p>具有正常音調間距四倍的發射音頻. 適用於在產生射頻之前使用除以 4 的特殊 LF/MF 發射器.</p></body></html> + <html><head/><body><p>具有正常音调间距四倍的发射音频. 适用于在产生射频之前使用除以 4 的特殊 LF/MF 发射器.</p></body></html> diff --git a/translations/wsjtx_zh_HK.ts b/translations/wsjtx_zh_HK.ts index 7bfff1f4e..851f485b9 100644 --- a/translations/wsjtx_zh_HK.ts +++ b/translations/wsjtx_zh_HK.ts @@ -504,7 +504,12 @@ Format: 您必須輸入有效的 ARRL RTTY Roundup 交換數據 - + + Pending DNS lookup, please try again later + 等待 DNS 查找, 請稍後再試 + + + Reset Decode Highlighting 重置解碼突出顯示 @@ -519,7 +524,17 @@ Format: WSJT-X 解碼文本字體選擇 - + + UDP server DNS lookup failed + UDP 伺服器 DNS 尋找失敗 + + + + MAC-ambiguous multicast groups addresses not supported + MAC 模棱兩可的多播組位址不受支援 + + + Load Working Frequencies 載入工作頻率 @@ -1956,7 +1971,7 @@ Error: %2 - %3 Satellite - 卫星 + 衛星 @@ -2434,7 +2449,7 @@ Yellow when too low If orange or red there has been a rig control failure, click to reset and read the dial frequency. S implies split mode. - 如果橙色或红色出现表示无线电设备控制故障, 请单击以重置并读取频率. S 表示异频模式. + 如果橙色或紅色出現表示無線電設備控制故障, 請按下以重置並讀取頻率. S 表示異頻模式. @@ -3879,7 +3894,7 @@ list. The list can be maintained in Settings (F2). "WSJT-X 的演演演算法, 原始碼, 外觀和感覺及相關程式, 和協定規格模式 FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 的版權 (C) 2001-2019 由以下一個或多個作者: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q; 和 WSJT 開發組的其他成員." - + No data read from disk. Wrong file format? 沒有從磁盤讀取數據. 檔案格式錯誤? @@ -3899,7 +3914,7 @@ list. The list can be maintained in Settings (F2). 鍵盤快捷鍵 - + <table cellspacing=1> <tr><td><b>Esc </b></td><td>Stop Tx, abort QSO, clear next-call queue</td></tr> <tr><td><b>F1 </b></td><td>Online User's Guide (Alt: transmit Tx6)</td></tr> @@ -3993,7 +4008,7 @@ list. The list can be maintained in Settings (F2). </table> - + Special Mouse Commands 特殊滑鼠組合 @@ -5410,6 +5425,11 @@ quiet period when decoding is done. Data bits 數據位元 + + + Data Bits + 數據位元 + D&efault @@ -5435,6 +5455,11 @@ quiet period when decoding is done. Stop bits 停止位元 + + + Stop Bits + 停止位元 + @@ -5465,7 +5490,7 @@ quiet period when decoding is done. &None - 無(&N) + @@ -5749,7 +5774,32 @@ transmitting periods. 向外發射輸出. - + + <html><head/><body><p>Enter the service port number of the UDP server that WSJT-X should send updates to. If this is zero no updates will be sent.</p></body></html> + <html><head/><body><p>輸入 WSJT-X 應向其發送更新的 UDP 伺服器的服務埠號. 如果這是零將不發送任何更新.</p></body></html> + + + + Outgoing interfaces: + 傳出介面: + + + + <html><head/><body><p>When sending updates to a multicast group address it is necessary to specify which network interface(s) to send them to. If the loop-back interface is multicast capable then at least that one will be selected.</p><p>For most users the loop-back interface is all that is needed, that will allow multiple other applications on the same machine to interoperate with WSJT-X. If applications running on other hosts are to receive status updates then a suitable network interface should be used.</p><p>On some Linux systems it may be necessary to enable multicast on the loop-back network interface.</p></body></html> + <html><head/><body><p>向組播組地址發送更新時需要指定要將其發送到哪個網路介面. 如果環回介面支援組播則至少將選擇該介面.</p><p>對於大多數用戶來說迴圈回式介面是所有需要的, 將允許同一台電腦上的多個其他應用程式與 WSJT-X 進行互通. 如果在其他主機上運行的應用程式要接收狀態更新則應使用合適的網路介面.</p><p>在某些 Linux 系統上可能需要在環回網路介面上啟用組播.</p></body></html> + + + + <html><head/><body><p>Sets the number or router hops that multicast datagrams are allowed to make. Almost everyone should set this to 1 to keep outgoing multicast traffic withn the local subnet.</p></body></html> + <html><head/><body><p>設置允許組播數據報進行的數位或路由器躍點. 幾乎每個人都應該將此設置為 1 以保持傳出的組播流量與本地子網.</p></body></html> + + + + Multicast TTL: + 組播 TTL TTL: + + + Days since last upload 自上次上傳以來的天數 @@ -5809,7 +5859,7 @@ both here. 啟用甚高頻和子模式功能 - + Ou&tput: 輸出(&t): @@ -6001,7 +6051,7 @@ and DX Grid fields when a 73 or free text message is sent. Log automatically (contesting only) - 日誌自記錄 (僅限競赛) + 日誌自動記錄 (僅限競赛) From 3134dd8a606c0586ca02361ef60693a75e022efc Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Thu, 3 Dec 2020 12:20:14 +0000 Subject: [PATCH 36/75] Removed incorrect pointer declaration, tnx to Rud, K5RUD --- lib/wsprd/wsprd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/wsprd/wsprd.c b/lib/wsprd/wsprd.c index 2e3b385da..522b7097f 100644 --- a/lib/wsprd/wsprd.c +++ b/lib/wsprd/wsprd.c @@ -71,7 +71,7 @@ unsigned long readc2file(char *ptr_to_infile, float *idat, float *qdat, float *buffer; double dfreq; int i,ntrmin; - char *c2file[15]; + char c2file[15]; size_t nr; FILE* fp; From ac6a6d0cd7e8f4f11c6d95d98a5bcd29fa2923e5 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Thu, 3 Dec 2020 13:12:12 +0000 Subject: [PATCH 37/75] Fail wsprd if data directory specified not accessible Also fixed trivial memory leak on error exit. --- lib/wsprd/wsprd.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/lib/wsprd/wsprd.c b/lib/wsprd/wsprd.c index 522b7097f..8ef66fd19 100644 --- a/lib/wsprd/wsprd.c +++ b/lib/wsprd/wsprd.c @@ -875,10 +875,12 @@ int main(int argc, char *argv[]) } } - if( stackdecoder ) { - stack=calloc(stacksize,sizeof(struct snode)); + if( access(data_dir, R_OK | W_OK)) { + fprintf(stderr, "Error: inaccessible data directory: '%s'\n", data_dir); + usage(); + return EXIT_FAILURE; } - + if( optind+1 > argc) { usage(); return 1; @@ -886,6 +888,10 @@ int main(int argc, char *argv[]) ptr_to_infile=argv[optind]; } + if( stackdecoder ) { + stack=calloc(stacksize,sizeof(struct snode)); + } + // setup metric table for(i=0; i<256; i++) { mettab[0][i]=round( 10*(metric_tables[2][i]-bias) ); From ad8c33bee78dda1c706676b0a7a92ee93c7dc6d2 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Thu, 3 Dec 2020 14:31:46 +0000 Subject: [PATCH 38/75] Try not setting low-latency audio category --- Audio/soundout.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Audio/soundout.cpp b/Audio/soundout.cpp index 54b765e22..7f38447ac 100644 --- a/Audio/soundout.cpp +++ b/Audio/soundout.cpp @@ -109,7 +109,7 @@ void SoundOutput::restart (QIODevice * source) { m_stream->setBufferSize (m_stream->format().bytesForFrames (m_framesBuffered)); } - m_stream->setCategory ("game"); + m_stream->setCategory ("production"); m_stream->start (source); LOG_INFO ("Selected buffer size (bytes): " << m_stream->bufferSize () << " period size: " << m_stream->periodSize ()); } From 93cf8a1b58c8aa812b9af4b11bdac576d1a60683 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Thu, 3 Dec 2020 19:19:47 +0000 Subject: [PATCH 39/75] Updated WSJT-X Danish UI translation, tnx Michael, 5P1KZX --- translations/wsjtx_da.ts | 71 ++++++++++++++++++++++++++++++++++------ 1 file changed, 61 insertions(+), 10 deletions(-) diff --git a/translations/wsjtx_da.ts b/translations/wsjtx_da.ts index 3acc2f102..bb7744752 100644 --- a/translations/wsjtx_da.ts +++ b/translations/wsjtx_da.ts @@ -20,8 +20,8 @@ Are you sure you want to delete the %n selected QSO(s) from the log? - Er du sikker på at du vil slette de %n valgte QSO(er) fra loggen? - + Sikker på du vil slette de %n valgte QSO(er) fra loggen? + Er du sikker på du vil slette de %n valgte QSO(s) fra loggen? @@ -626,7 +626,7 @@ Format: Not found audio device missing - + Audio device mangler @@ -2711,12 +2711,12 @@ Når den ikke er markeret, kan du se kalibreringsresultaterne. F High - + F Høj F Low - + F Lav @@ -2964,12 +2964,12 @@ listen. Makro listen kan også ændfres i Inderstillinger (F2). SWL Mode - + SWL Mode Hide lower panel controls to maximize deocde windows - + Skjul nederste del af Control Panel for at maksimere dekoder vinduet Calling CQ @@ -3864,7 +3864,8 @@ listen. Makro listen kan også ændfres i Inderstillinger (F2). Excessive dropped samples - %1 (%2 sec) audio frames dropped in period starting %3 - + For store tabte prøver -% 1 (% 2 sek) lydrammer faldt i perioden startende med% 3 + For stort tab i - %1 (%2 sec) audio frames stoppet i periode startende %3 @@ -3889,7 +3890,7 @@ listen. Makro listen kan også ændfres i Inderstillinger (F2). Enumerating audio devices - + Opsumering af audio enheder @@ -4147,7 +4148,57 @@ listen. Makro listen kan også ændfres i Inderstillinger (F2). <tr><td><b>Alt+Z </b></td><td>Clear hung decoder status</td></tr> </table> Keyboard shortcuts help window contents - + Hjælpetekst til Tastetur genveje + <tabelcelleafstand = 1> + <tr><td> <b> Esc </b></td> <td> Stop Tx, afbryd QSO, ryd kø ved næste kald </td> </tr> + <tr><td> <b> F1 </b></td> <td> Online brugervejledning (Alt: transmitter Tx6) </td> </tr> + <tr><td> <b> Shift + F1 </b></td> <td> Meddelelse om ophavsret </td> </tr> + <tr><td> <b> Ctrl + F1 </b></td> <td> Om WSJT-X </td> </tr> + <tr><td> <b> F2 </b></td> <td> Åbn indstillingsvinduet (Alt: send Tx2) </td> </tr> + <tr><td> <b> F3 </b></td> <td> Vis tastaturgenveje (Alt: transmitter Tx3) </td> </tr> + <tr><td> <b> F4 </b></td> <td> Ryd DX Call, DX Grid, Tx meddelelser 1-4 (Alt: send Tx4) </td> </tr> + <tr><td> <b> Alt + F4 </b></td> <td> Afslutningsprogram </td> </tr> + <tr><td> <b> F5 </b></td> <td> Vis specielle musekommandoer (Alt: transmitter Tx5) </td> </tr> +<tr><td> <b> F6 </b></td> <td> Åbn næste fil i biblioteket (Alt: skift "Call 1st") </td> </tr> + <tr><td> <b> Shift + F6 </b></td> <td> Dekod alle resterende filer i biblioteket </td> </tr> + <tr><td> <b> F7 </b></td> <td> Vis vindue for gennemsnitsmeddelelse </td> </tr> + <tr><td> <b> F11 </b></td> <td> Flyt Rx-frekvensen ned 1 Hz </td> </tr> + <tr><td> <b> Ctrl + F11 </b></td> <td> Flyt identiske Rx- og Tx-frekvenser ned 1 Hz </td> </tr> + <tr><td> <b> Shift + F11 </b></td> <td> Flyt Tx-frekvensen 60 Hz ned (FT8) eller 90 Hz (FT4) </td> </tr> + <tr><td> <b> Ctrl + Shift + F11 </b></td> <td> Flyt kaldefrekvensen 2000 Hz ned </td> </tr> + <tr><td> <b> F12 </b></td> <td> Flyt Rx-frekvensen 1 Hz op </td> </tr> + <tr><td> <b> Ctrl + F12 </b></td> <td> Flyt identiske Rx- og Tx-frekvenser 1 Hz op </td> </tr> +<tr><td> <b> Ctrl + F11 </b></td> <td> Flyt identiske Rx- og Tx-frekvenser ned 1 Hz </td> </tr> + <tr><td> <b> Shift + F11 </b></td> <td> Flyt Tx-frekvensen ned 60 Hz (FT8) eller 90 Hz (FT4) </td> </tr> + <tr><td> <b> Ctrl + Shift + F11 </b></td> <td> Flyt kaldefrekvensen ned 2000 Hz </td> </tr> + <tr><td> <b> F12 </b></td> <td> Flyt Rx-frekvensen op 1 Hz </td> </tr> + <tr><td> <b> Ctrl + F12 </b></td> <td> Flyt identiske Rx- og Tx-frekvenser 1 Hz op </td> </tr> + <tr><td> <b> Shift + F12 </b></td> <td> Flyt Tx-frekvensen 60 Hz op (FT8) eller 90 Hz (FT4) </td> </tr> + <tr><td> <b> Ctrl + Shift + F12 </b></td> <td> Flyt kaldefrekvensen 2000 Hz op</td> </tr> + <tr><td> <b> Alt + 1-6 </b></td> <td> Indstil NU transmission til dette nummer på fane 1 </td> </tr> + <tr><td> <b> Ctl + 1-6 </b></td> <td> Indstil næste transmission til dette nummer på fane 1 </td> </tr> + <tr><td> <b> Alt + B </b></td> <td> Skift status "Bedste S + P" </td> </tr> + <tr><td> <b> Alt + C </b></td> <td> Skift afkrydsningsfelt "Kald 1st" </td> </tr> + <tr><td> <b> Alt + D </b></td> <td> Dekod igen ved QSO-frekvens </td> </tr> + <tr><td> <b> Shift + D </b></td> <td> Fuld Dekodning (begge vinduer) </td> </tr> +<tr><td> <b> Ctrl + E </b></td> <td> Aktiver TX lige / 1. </td> </tr> + <tr><td> <b> Shift + E </b></td> <td> Deaktiver TX lige / 1. </td> </tr> + <tr><td> <b> Alt + E </b></td><td>Sætning</td> </tr> + <tr><td> <b> Ctrl + F </b></td> <td> Rediger fri tekstmeddelelsesfelt </td> </tr> + <tr><td> <b> Alt + G </b></td> <td> Generer standardmeddelelser </td> </tr> + <tr><td> <b> Alt + H </b></td> <td> Stop Tx </td> </tr> + <tr><td> <b> Ctrl + L </b></td> <td> Opslag af kaldesignal i database, generer standardbeskeder </td> </tr> + <tr><td> <b> Alt + M </b></td><td> Skærm</td> </tr> + <tr><td> <b> Alt + N </b></td> <td> Aktivér Tx </td> </tr> + <tr><td> <b> Ctrl + O </b></td> <td> Åbn en .wav-fil </td> </tr> + <tr><td> <b> Alt + O </b></td> <td> Skift operatør </td> </tr> + <tr><td> <b> Alt + Q </b></td> <td> Log QSO </td> </tr> + <tr><td> <b> Ctrl + R </b></td> <td> Indstil Tx4-besked til RRR (ikke i FT4) </td> </tr> + <tr><td> <b> Alt + R </b></td> <td> Indstil Tx4-besked til RR73 </td> </tr> + <tr><td> <b> Alt + S </b></td> <td> Stop overvågning </td> </tr> + <tr><td> <b> Alt + T </b></td> <td> Skift Tune status </td> </tr> + <tr><td> <b> Alt + Z </b></td> <td> Ryd fyldt buffer dekoderstatus </td> </tr> +</tabel> <table cellspacing=1> From 9fed3534d8f69304bb7ebb36eb05ef2c2c82a910 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Thu, 3 Dec 2020 23:39:44 +0000 Subject: [PATCH 40/75] Updated Japanese UI translation, tnx Oba san, JA7UDE --- translations/wsjtx_ja.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/translations/wsjtx_ja.ts b/translations/wsjtx_ja.ts index 0cf5f52bb..2813f3c91 100644 --- a/translations/wsjtx_ja.ts +++ b/translations/wsjtx_ja.ts @@ -625,7 +625,7 @@ Format: Not found audio device missing - + 見つかりません @@ -2703,12 +2703,12 @@ When not checked you can view the calibration results. F High - + F 高 F Low - + F 低 @@ -2962,12 +2962,12 @@ ENTERを押してテキストを登録リストに追加. SWL Mode - + SWLモード Hide lower panel controls to maximize deocde windows - + 下部制御パネルを非表示にしてデコードウィンドウを最大化 Calling CQ @@ -3825,7 +3825,7 @@ ENTERを押してテキストを登録リストに追加. Excessive dropped samples - %1 (%2 sec) audio frames dropped in period starting %3 - + サンプル大量欠落 - %3から始まる%1個(%2秒)のオーディオフレームが欠落 @@ -3850,7 +3850,7 @@ ENTERを押してテキストを登録リストに追加. Enumerating audio devices - + オーディオデバイスを列挙 From f3a2c653aa20d59a0a6dbe6df57f4ac459e3724c Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Fri, 4 Dec 2020 18:59:41 +0000 Subject: [PATCH 41/75] Revert to default o/s or Qt Tx audio buffer sizes --- widgets/mainwindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/widgets/mainwindow.cpp b/widgets/mainwindow.cpp index aaec4e558..8ce3e29cb 100644 --- a/widgets/mainwindow.cpp +++ b/widgets/mainwindow.cpp @@ -212,7 +212,7 @@ namespace auto quint32_max = std::numeric_limits::max (); constexpr int N_WIDGETS {36}; constexpr int rx_chunk_size {3456}; // audio samples at 12000 Hz - constexpr int default_tx_audio_buffer_frames {48000 / 5}; // audio frames at 48000 Hz + constexpr int default_tx_audio_buffer_frames {-1}; // lets Qt decide bool message_is_73 (int type, QStringList const& msg_parts) { From 538d0eedd5d148167ebf9e6f9e9472fa4f9bc808 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Fri, 4 Dec 2020 19:01:05 +0000 Subject: [PATCH 42/75] Change to wide character logging and handle wide character file paths --- Logger.cpp | 18 +++++++++--------- Logger.hpp | 4 ++-- WSJTXLogging.cpp | 12 ++++++------ 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/Logger.cpp b/Logger.cpp index 00e5597b1..e92c7aa2a 100644 --- a/Logger.cpp +++ b/Logger.cpp @@ -21,10 +21,10 @@ #include #include #include - -#include +#include #include +namespace fs = boost::filesystem; namespace logging = boost::log; namespace srcs = logging::sources; namespace sinks = logging::sinks; @@ -128,7 +128,7 @@ namespace Logger CommonInitialization ci; } - void init_from_config (std::istream& stream) + void init_from_config (std::wistream& stream) { CommonInitialization ci; try @@ -152,24 +152,24 @@ namespace Logger logging::core::get ()->set_logging_enabled (false); } - void add_datafile_log (std::string const& log_file_name) + void add_datafile_log (std::wstring const& log_file_name) { // Create a text file sink - boost::shared_ptr backend + boost::shared_ptr backend ( - new sinks::text_ostream_backend() + new sinks::wtext_ostream_backend() ); - backend->add_stream (boost::shared_ptr (new std::ofstream (log_file_name))); + backend->add_stream (boost::shared_ptr (new fs::wofstream (log_file_name))); // Flush after each log record backend->auto_flush (true); // Create a sink for the backend - typedef sinks::synchronous_sink sink_t; + typedef sinks::synchronous_sink sink_t; boost::shared_ptr sink (new sink_t (backend)); // The log output formatter - sink->set_formatter (expr::format ("[%1%][%2%] %3%") + sink->set_formatter (expr::format (L"[%1%][%2%] %3%") % expr::attr ("TimeStamp") % logging::trivial::severity % expr::message diff --git a/Logger.hpp b/Logger.hpp index 6e29789e4..5d497943f 100644 --- a/Logger.hpp +++ b/Logger.hpp @@ -21,14 +21,14 @@ namespace Logger void init (); // define logger(s) and sinks from a configuration stream - void init_from_config (std::istream& config_stream); + void init_from_config (std::wistream& config_stream); // disable logging - useful for unit testing etc. void disable (); // add a new file sink for LOG_DATA_* for Severity >= INFO // this file sink will be used alongside any configured above - void add_data_file_log (std::string const& log_file_name); + void add_data_file_log (std::wstring const& log_file_name); } #define LOG_LOG_LOCATION(LOGGER, LEVEL, ARG) \ diff --git a/WSJTXLogging.cpp b/WSJTXLogging.cpp index ffa563b23..e0ba871bd 100644 --- a/WSJTXLogging.cpp +++ b/WSJTXLogging.cpp @@ -93,7 +93,7 @@ namespace << boost::log::add_value ("Line", context.line) << boost::log::add_value ("File", file) << boost::log::add_value ("Function", function) - << msg.toStdString (); + << msg.toStdWString (); } else { @@ -101,7 +101,7 @@ namespace << boost::log::add_value ("Line", context.line) << boost::log::add_value ("File", file) << boost::log::add_value ("Function", function) - << context.category << ": " << msg.toStdString (); + << context.category << ": " << msg.toStdWString (); } if (QtFatalMsg == type) { @@ -155,8 +155,8 @@ WSJTXLogging::WSJTXLogging () pos = match.capturedEnd (0); } new_config += config.mid (pos); - std::stringbuf buffer {new_config.toStdString (), std::ios_base::in}; - std::istream stream {&buffer}; + std::wstringbuf buffer {new_config.toStdWString (), std::ios_base::in}; + std::wistream stream {&buffer}; Logger::init_from_config (stream); LOG_INFO ("Read logging configuration file: " << log_config.fileName ()); } @@ -180,7 +180,7 @@ WSJTXLogging::WSJTXLogging () ( keywords::auto_flush = false #if BOOST_VERSION / 100 >= 1070 - , keywords::file_name = app_data.absoluteFilePath ("wsjtx_syslog.log").toStdString () + , keywords::file_name = app_data.absoluteFilePath ("wsjtx_syslog.log").toStdWString () , keywords::target_file_name = #else , keywords::file_name = @@ -200,7 +200,7 @@ WSJTXLogging::WSJTXLogging () keywords::max_size = 40 * 1024 * 1024 , keywords::min_free_space = 1024 * 1024 * 1024 , keywords::max_files = 12 - , keywords::target = app_data.absoluteFilePath ("logs").toStdString () + , keywords::target = app_data.absoluteFilePath ("logs").toStdWString () ) ); sys_sink->locked_backend ()->scan_for_files (); From e5686cb21f2e57b766bd1da53284e7ae171501bb Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Mon, 7 Dec 2020 10:40:52 +0000 Subject: [PATCH 43/75] Minor documentation clarification --- Darwin/ReadMe.txt | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Darwin/ReadMe.txt b/Darwin/ReadMe.txt index 283aa1025..78c092ca4 100644 --- a/Darwin/ReadMe.txt +++ b/Darwin/ReadMe.txt @@ -34,10 +34,9 @@ Double-click on the wsjtx-...-Darwin.dmg file you have downloaded from K1JT's we Now open a Terminal window by going to Applications->Utilities and clicking on Terminal. Along with this ReadMe file there is a file: sysctl.conf which must be copied to a -system area by typing these two lines in the Terminal window and then pressing the Return key -after each line. +system area by typing this line in the Terminal window and then pressing the Return key. - sudo cp /Volumes/WSJT-X/sysctl.conf /etc + sudo cp /Volumes/WSJT-X/sysctl.conf /etc you will be asked for your normal password because authorisation is needed to copy this file. (Your password will not be echoed but press the Return key when completed.) @@ -45,7 +44,7 @@ Now re-boot your Mac. This is necessary to install the changes. After the reboot you should re-open the Terminal window as before and you can check that the change has been made by typing: - sysctl -a | grep sysv.shm + sysctl -a | grep sysv.shm If shmmax is not shown as 104857600 then contact me since WSJT-X will fail to load with an error message: "Unable to create shared memory segment". From cefc8e26452375c2188976f1ee6c079721cd38ab Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Mon, 7 Dec 2020 10:41:33 +0000 Subject: [PATCH 44/75] Use the system localized short date format for Log QSO dialog dates This brings these fields into line with other QSO start and end date/time fields elsewhere in the user interface. Note that time entry and edit fields use a fixed hh:mm:ss 24-hour clock format consistent with UTC usage and of suitable accuracy for logging QSOs. --- widgets/logqso.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/widgets/logqso.cpp b/widgets/logqso.cpp index 7a74b86cf..f49274494 100644 --- a/widgets/logqso.cpp +++ b/widgets/logqso.cpp @@ -1,5 +1,6 @@ #include "logqso.h" +#include #include #include #include @@ -61,6 +62,9 @@ LogQSO::LogQSO(QString const& programTitle, QSettings * settings ui->comboBoxPropMode->addItem (prop_mode.name_, prop_mode.id_); } loadSettings (); + auto date_time_format = QLocale {}.dateFormat (QLocale::ShortFormat) + " hh:mm:ss"; + ui->start_date_time->setDisplayFormat (date_time_format); + ui->end_date_time->setDisplayFormat (date_time_format); ui->grid->setValidator (new MaidenheadLocatorValidator {this}); } From 60792182ad9c9771139c128a8114f4ba1edabf56 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Mon, 7 Dec 2020 20:34:56 +0000 Subject: [PATCH 45/75] Environment variables to set audio buffer sizes and fix Windows Rx timing The two environment variables: WSJT_RX_AUDIO_BUFFER_FRAMES WSJT_TX_AUDIO_BUFFER_FRAMES each can be defined to an integer number which will be used as the suggested audio buffer size for Rx and Tx respectively. Not setting the variable or setting it to zero or less will cause the default buffer size to be used, which should be a good choice for most, if not all, systems. --- Audio/soundin.cpp | 11 +++++------ Audio/soundout.cpp | 2 +- widgets/mainwindow.cpp | 11 +++++++---- widgets/mainwindow.h | 1 + 4 files changed, 14 insertions(+), 11 deletions(-) diff --git a/Audio/soundin.cpp b/Audio/soundin.cpp index 581f1a92f..53a29799c 100644 --- a/Audio/soundin.cpp +++ b/Audio/soundin.cpp @@ -88,17 +88,16 @@ void SoundInput::start(QAudioDeviceInfo const& device, int framesPerBuffer, Audi //qDebug () << "SoundIn default buffer size (bytes):" << m_stream->bufferSize () << "period size:" << m_stream->periodSize (); // the Windows MME version of QAudioInput uses 1/5 of the buffer // size for period size other platforms seem to optimize themselves -#if defined (Q_OS_WIN) - m_stream->setBufferSize (m_stream->format ().bytesForFrames (framesPerBuffer * 5)); -#else - Q_UNUSED (framesPerBuffer); -#endif + if (framesPerBuffer > 0) + { + m_stream->setBufferSize (m_stream->format ().bytesForFrames (framesPerBuffer)); + } if (m_sink->initialize (QIODevice::WriteOnly, channel)) { m_stream->start (sink); checkStream (); cummulative_lost_usec_ = -1; - //qDebug () << "SoundIn selected buffer size (bytes):" << m_stream->bufferSize () << "peirod size:" << m_stream->periodSize (); + LOG_DEBUG ("Selected buffer size (bytes): " << m_stream->bufferSize () << " period size: " << m_stream->periodSize ()); } else { diff --git a/Audio/soundout.cpp b/Audio/soundout.cpp index 7f38447ac..f3ec3dce3 100644 --- a/Audio/soundout.cpp +++ b/Audio/soundout.cpp @@ -111,7 +111,7 @@ void SoundOutput::restart (QIODevice * source) } m_stream->setCategory ("production"); m_stream->start (source); - LOG_INFO ("Selected buffer size (bytes): " << m_stream->bufferSize () << " period size: " << m_stream->periodSize ()); + LOG_DEBUG ("Selected buffer size (bytes): " << m_stream->bufferSize () << " period size: " << m_stream->periodSize ()); } void SoundOutput::suspend () diff --git a/widgets/mainwindow.cpp b/widgets/mainwindow.cpp index 8ce3e29cb..a24065d60 100644 --- a/widgets/mainwindow.cpp +++ b/widgets/mainwindow.cpp @@ -211,7 +211,7 @@ namespace QRegularExpression grid_regexp {"\\A(?![Rr]{2}73)[A-Ra-r]{2}[0-9]{2}([A-Xa-x]{2}){0,1}\\z"}; auto quint32_max = std::numeric_limits::max (); constexpr int N_WIDGETS {36}; - constexpr int rx_chunk_size {3456}; // audio samples at 12000 Hz + constexpr int default_rx_audio_buffer_frames {-1}; // lets Qt decide constexpr int default_tx_audio_buffer_frames {-1}; // lets Qt decide bool message_is_73 (int type, QStringList const& msg_parts) @@ -265,6 +265,7 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple, m_soundInput {new SoundInput}, m_modulator {new Modulator {TX_SAMPLE_RATE, NTMAX}}, m_soundOutput {new SoundOutput}, + m_rx_audio_buffer_frames {0}, m_tx_audio_buffer_frames {0}, m_msErase {0}, m_secBandChanged {0}, @@ -457,7 +458,9 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple, m_soundInput->moveToThread (&m_audioThread); m_detector->moveToThread (&m_audioThread); bool ok; - auto buffer_size = env.value ("WSJT_TX_AUDIO_BUFFER_FRAMES", "0").toInt (&ok); + auto buffer_size = env.value ("WSJT_RX_AUDIO_BUFFER_FRAMES", "0").toInt (&ok); + m_rx_audio_buffer_frames = ok && buffer_size ? buffer_size : default_rx_audio_buffer_frames; + buffer_size = env.value ("WSJT_TX_AUDIO_BUFFER_FRAMES", "0").toInt (&ok); m_tx_audio_buffer_frames = ok && buffer_size ? buffer_size : default_tx_audio_buffer_frames; // hook up sound output stream slots & signals and disposal @@ -939,7 +942,7 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple, if (!m_config.audio_input_device ().isNull ()) { Q_EMIT startAudioInputStream (m_config.audio_input_device () - , rx_chunk_size * m_downSampleFactor + , m_rx_audio_buffer_frames , m_detector, m_downSampleFactor, m_config.audio_input_channel ()); } if (!m_config.audio_output_device ().isNull ()) @@ -1851,7 +1854,7 @@ void MainWindow::on_actionSettings_triggered() //Setup Dialog if(m_config.restart_audio_input () && !m_config.audio_input_device ().isNull ()) { Q_EMIT startAudioInputStream (m_config.audio_input_device () - , rx_chunk_size * m_downSampleFactor + , m_rx_audio_buffer_frames , m_detector, m_downSampleFactor , m_config.audio_input_channel ()); } diff --git a/widgets/mainwindow.h b/widgets/mainwindow.h index 878e9c6c3..7dfbf8a7e 100644 --- a/widgets/mainwindow.h +++ b/widgets/mainwindow.h @@ -404,6 +404,7 @@ private: SoundInput * m_soundInput; Modulator * m_modulator; SoundOutput * m_soundOutput; + int m_rx_audio_buffer_frames; int m_tx_audio_buffer_frames; QThread m_audioThread; From ad04f4fbd2ba3d1f754add93f68ae277f2fdef86 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Tue, 8 Dec 2020 23:14:46 +0000 Subject: [PATCH 46/75] Extra example log configuration file for rig control diagnostics --- .../wsjtx_log_config.ini.rig_control | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 example_log_configurations/wsjtx_log_config.ini.rig_control diff --git a/example_log_configurations/wsjtx_log_config.ini.rig_control b/example_log_configurations/wsjtx_log_config.ini.rig_control new file mode 100644 index 000000000..0bcb82066 --- /dev/null +++ b/example_log_configurations/wsjtx_log_config.ini.rig_control @@ -0,0 +1,25 @@ +[Sinks.SYSLOG] +Destination=TextFile +Asynchronous=true +AutoFlush=false +FileName="${AppLocalDataLocation}/wsjtx_syslog.log" +TargetFileName="${AppLocalDataLocation}/logs/wsjtx_syslog_%Y-%m.log" +RotationTimePoint="01 00:00:00" +Append=true +EnableFinalRotation=false +MaxSize=41943040 +MinFreeSpace=1073741824 +MaxFiles=12 +Target="${AppLocalDataLocation}/logs" +ScanForFiles="Matching" +Format="[%Channel%][%TimeStamp(format=\"%Y-%m-%d %H:%M:%S.%f\")%][%Uptime(format=\"%O:%M:%S.%f\")%][%Severity%] %Message%" +Filter="%Severity% >= info" + +[Sinks.RIGCTRL] +Destination=TextFile +Asynchronous=true +AutoFlush=true +FileName="${DesktopLocation}/WSJT-X_RigControl.log" +Append=true +Format="[%TimeStamp(format=\"%Y-%m-%d %H:%M:%S.%f\")%][%Uptime(format=\"%O:%M:%S.%f\")%][%Channel%:%Severity%] %Message%" +Filter="%Channel% matches \"RIGCTRL\" | %Severity% >= info" From b8c8477664c74871ff8f6b96871450211d38f84a Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Sat, 19 Dec 2020 16:32:37 +0000 Subject: [PATCH 47/75] Fix a close down crash due to destruction ordering Static QString variables are unwise as QApplication translators may get destroyed before them. --- widgets/widegraph.cpp | 37 ++++++++++++++++--------------------- widgets/widegraph.h | 2 ++ 2 files changed, 18 insertions(+), 21 deletions(-) diff --git a/widgets/widegraph.cpp b/widgets/widegraph.cpp index a369f6296..fa3f1320e 100644 --- a/widgets/widegraph.cpp +++ b/widgets/widegraph.cpp @@ -13,12 +13,6 @@ #include "SettingsGroup.hpp" #include "moc_widegraph.cpp" -namespace -{ - auto user_defined = QObject::tr ("User Defined"); - float swide[MAX_SCREENSIZE]; -} - WideGraph::WideGraph(QSettings * settings, QWidget *parent) : QDialog(parent), ui(new Ui::WideGraph), @@ -26,7 +20,8 @@ WideGraph::WideGraph(QSettings * settings, QWidget *parent) : m_palettes_path {":/Palettes"}, m_tr0 {0.0}, m_n {0}, - m_bHaveTransmitted {false} + m_bHaveTransmitted {false}, + m_user_defined {tr ("User Defined")} { ui->setupUi(this); @@ -103,8 +98,8 @@ WideGraph::WideGraph(QSettings * settings, QWidget *parent) : if(t==m_waterfallPalette) ui->paletteComboBox->setCurrentIndex(index); index++; } - ui->paletteComboBox->addItem (user_defined); - if (user_defined == m_waterfallPalette) ui->paletteComboBox->setCurrentIndex(index); + ui->paletteComboBox->addItem (m_user_defined); + if (m_user_defined == m_waterfallPalette) ui->paletteComboBox->setCurrentIndex(index); readPalette (); } @@ -147,7 +142,7 @@ void WideGraph::saveSettings() //saveS void WideGraph::drawRed(int ia, int ib) { - ui->widePlot->drawRed(ia,ib,swide); + ui->widePlot->drawRed(ia,ib,m_swide); } void WideGraph::dataSink2(float s[], float df3, int ihsym, int ndiskdata) //dataSink2 @@ -181,8 +176,8 @@ void WideGraph::dataSink2(float s[], float df3, int ihsym, int ndiskdata) //dat ss += sp; smax=qMax(smax,sp); } -// swide[j]=nbpp*smax; - swide[j]=nbpp*ss; +// m_swide[j]=nbpp*smax; + m_swide[j]=nbpp*ss; } // Time according to this computer @@ -192,7 +187,7 @@ void WideGraph::dataSink2(float s[], float df3, int ihsym, int ndiskdata) //dat float flagValue=1.0e30; if(m_bHaveTransmitted) flagValue=2.0e30; for(int i=0; iwidePlot->draw(swide,true,false); + ui->widePlot->draw(m_swide,true,false); } } @@ -238,7 +233,7 @@ void WideGraph::keyPressEvent(QKeyEvent *e) //F1 void WideGraph::setRxFreq(int n) //setRxFreq { ui->widePlot->setRxFreq(n); - ui->widePlot->draw(swide,false,false); + ui->widePlot->draw(m_swide,false,false); } int WideGraph::rxFreq() //rxFreq @@ -384,7 +379,7 @@ void WideGraph::readPalette () //readPalette { try { - if (user_defined == m_waterfallPalette) + if (m_user_defined == m_waterfallPalette) { ui->widePlot->setColours (WFPalette {m_userPalette}.interpolate ()); } @@ -437,7 +432,7 @@ void WideGraph::on_adjust_palette_push_button_clicked (bool) //Adjust Palette { if (m_userPalette.design ()) { - m_waterfallPalette = user_defined; + m_waterfallPalette = m_user_defined; ui->paletteComboBox->setCurrentText (m_waterfallPalette); readPalette (); } @@ -479,8 +474,8 @@ void WideGraph::on_gain2dSlider_valueChanged(int value) //Gain2 { ui->widePlot->setPlot2dGain(value); if(ui->widePlot->scaleOK ()) { - ui->widePlot->draw(swide,false,false); - if(m_mode=="QRA64") ui->widePlot->draw(swide,false,true); + ui->widePlot->draw(m_swide,false,false); + if(m_mode=="QRA64") ui->widePlot->draw(m_swide,false,true); } } @@ -488,8 +483,8 @@ void WideGraph::on_zero2dSlider_valueChanged(int value) //Zero2 { ui->widePlot->setPlot2dZero(value); if(ui->widePlot->scaleOK ()) { - ui->widePlot->draw(swide,false,false); - if(m_mode=="QRA64") ui->widePlot->draw(swide,false,true); + ui->widePlot->draw(m_swide,false,false); + if(m_mode=="QRA64") ui->widePlot->draw(m_swide,false,true); } } diff --git a/widgets/widegraph.h b/widgets/widegraph.h index f5f70c281..421fc8213 100644 --- a/widgets/widegraph.h +++ b/widgets/widegraph.h @@ -117,6 +117,8 @@ private: QString m_mode; QString m_modeTx; QString m_waterfallPalette; + float m_swide[MAX_SCREENSIZE]; + QString m_user_defined; }; #endif // WIDEGRAPH_H From dd631699da4a6eef8d7cf5ecc0969bc1d1e8051e Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Mon, 21 Dec 2020 01:31:57 +0000 Subject: [PATCH 48/75] Add the Tx message to the UDP Status(1) message Thanks to Morgan (sri no other attribution given) for the initial contribution this change is based on. --- Network/MessageClient.cpp | 8 +++++--- Network/MessageClient.hpp | 3 ++- Network/NetworkMessage.hpp | 4 +++- UDPExamples/ClientWidget.cpp | 8 +++++--- UDPExamples/ClientWidget.hpp | 3 ++- UDPExamples/MessageServer.cpp | 7 +++++-- UDPExamples/MessageServer.hpp | 2 +- UDPExamples/UDPDaemon.cpp | 2 +- widgets/mainwindow.cpp | 12 ++++++++++-- 9 files changed, 34 insertions(+), 15 deletions(-) diff --git a/Network/MessageClient.cpp b/Network/MessageClient.cpp index 45d47f9b6..4374e8dc1 100644 --- a/Network/MessageClient.cpp +++ b/Network/MessageClient.cpp @@ -569,7 +569,8 @@ void MessageClient::status_update (Frequency f, QString const& mode, QString con , bool watchdog_timeout, QString const& sub_mode , bool fast_mode, quint8 special_op_mode , quint32 frequency_tolerance, quint32 tr_period - , QString const& configuration_name) + , QString const& configuration_name + , QString const& tx_message) { if (m_->server_port_ && !m_->server_.isNull ()) { @@ -578,8 +579,9 @@ void MessageClient::status_update (Frequency f, QString const& mode, QString con out << f << mode.toUtf8 () << dx_call.toUtf8 () << report.toUtf8 () << tx_mode.toUtf8 () << tx_enabled << transmitting << decoding << rx_df << tx_df << de_call.toUtf8 () << de_grid.toUtf8 () << dx_grid.toUtf8 () << watchdog_timeout << sub_mode.toUtf8 () - << fast_mode << special_op_mode << frequency_tolerance << tr_period << configuration_name.toUtf8 (); - TRACE_UDP ("frequency:" << f << "mode:" << mode << "DX:" << dx_call << "report:" << report << "Tx mode:" << tx_mode << "tx_enabled:" << tx_enabled << "Tx:" << transmitting << "decoding:" << decoding << "Rx df:" << rx_df << "Tx df:" << tx_df << "DE:" << de_call << "DE grid:" << de_grid << "DX grid:" << dx_grid << "w/d t/o:" << watchdog_timeout << "sub_mode:" << sub_mode << "fast mode:" << fast_mode << "spec op mode:" << special_op_mode << "frequency tolerance:" << frequency_tolerance << "T/R period:" << tr_period << "configuration name:" << configuration_name); + << fast_mode << special_op_mode << frequency_tolerance << tr_period << configuration_name.toUtf8 () + << tx_message.toUtf8 (); + TRACE_UDP ("frequency:" << f << "mode:" << mode << "DX:" << dx_call << "report:" << report << "Tx mode:" << tx_mode << "tx_enabled:" << tx_enabled << "Tx:" << transmitting << "decoding:" << decoding << "Rx df:" << rx_df << "Tx df:" << tx_df << "DE:" << de_call << "DE grid:" << de_grid << "DX grid:" << dx_grid << "w/d t/o:" << watchdog_timeout << "sub_mode:" << sub_mode << "fast mode:" << fast_mode << "spec op mode:" << special_op_mode << "frequency tolerance:" << frequency_tolerance << "T/R period:" << tr_period << "configuration name:" << configuration_name << "Tx message:" << tx_message); m_->send_message (out, message); } } diff --git a/Network/MessageClient.hpp b/Network/MessageClient.hpp index cc348be2d..3f21a598a 100644 --- a/Network/MessageClient.hpp +++ b/Network/MessageClient.hpp @@ -63,7 +63,8 @@ public: , quint32 rx_df, quint32 tx_df, QString const& de_call, QString const& de_grid , QString const& dx_grid, bool watchdog_timeout, QString const& sub_mode , bool fast_mode, quint8 special_op_mode, quint32 frequency_tolerance - , quint32 tr_period, QString const& configuration_name); + , quint32 tr_period, QString const& configuration_name + , QString const& tx_message); Q_SLOT void decode (bool is_new, QTime time, qint32 snr, float delta_time, quint32 delta_frequency , QString const& mode, QString const& message, bool low_confidence , bool off_air); diff --git a/Network/NetworkMessage.hpp b/Network/NetworkMessage.hpp index f892eda06..61aaf7038 100644 --- a/Network/NetworkMessage.hpp +++ b/Network/NetworkMessage.hpp @@ -160,6 +160,7 @@ * Frequency Tolerance quint32 * T/R Period quint32 * Configuration Name utf8 + * Tx Message utf8 * * WSJT-X sends this status message when various internal state * changes to allow the server to track the relevant state of each @@ -183,7 +184,8 @@ * when the Tx watchdog is set or reset, * when the frequency tolerance is changed, * when the T/R period is changed, - * when the configuration name changes. + * when the configuration name changes, + * when the message being transmitted changes. * * The Special operation mode is an enumeration that indicates the * setting selected in the WSJT-X "Settings->Advanced->Special diff --git a/UDPExamples/ClientWidget.cpp b/UDPExamples/ClientWidget.cpp index 75930b7e5..b82836f04 100644 --- a/UDPExamples/ClientWidget.cpp +++ b/UDPExamples/ClientWidget.cpp @@ -147,6 +147,7 @@ ClientWidget::ClientWidget (QAbstractItemModel * decodes_model, QAbstractItemMod , mode_line_edit_ {new QLineEdit {this}} , frequency_tolerance_spin_box_ {new QSpinBox {this}} , tx_mode_label_ {new QLabel {this}} + , tx_message_label_ {new QLabel {this}} , submode_line_edit_ {new QLineEdit {this}} , fast_mode_check_box_ {new QCheckBox {this}} , tr_period_spin_box_ {new QSpinBox {this}} @@ -302,6 +303,7 @@ ClientWidget::ClientWidget (QAbstractItemModel * decodes_model, QAbstractItemMod // set up status area status_bar_->addPermanentWidget (de_label_); status_bar_->addPermanentWidget (tx_mode_label_); + status_bar_->addPermanentWidget (tx_message_label_); status_bar_->addPermanentWidget (frequency_label_); status_bar_->addPermanentWidget (tx_df_label_); status_bar_->addPermanentWidget (report_label_); @@ -400,7 +402,7 @@ void ClientWidget::update_status (ClientKey const& key, Frequency f, QString con , QString const& de_call, QString const& de_grid, QString const& dx_grid , bool watchdog_timeout, QString const& submode, bool fast_mode , quint8 special_op_mode, quint32 frequency_tolerance, quint32 tr_period - , QString const& configuration_name) + , QString const& configuration_name, QString const& tx_message) { if (key == key_) { @@ -427,8 +429,8 @@ void ClientWidget::update_status (ClientKey const& key, Frequency f, QString con update_spin_box (frequency_tolerance_spin_box_, frequency_tolerance , quint32_max == frequency_tolerance ? QString {"n/a"} : QString {}); update_line_edit (submode_line_edit_, submode, false); - tx_mode_label_->setText (QString {"Tx Mode: %1"} - .arg (tx_mode.isEmpty () || tx_mode == mode ? "" : '(' + tx_mode + ')')); + tx_mode_label_->setText (tx_mode.isEmpty () || tx_mode == mode ? "" : "Tx Mode: (" + tx_mode + ')'); + tx_message_label_->setText (tx_message.isEmpty () ? "" : "Tx Msg: " + tx_message.trimmed ()); frequency_label_->setText ("QRG: " + Radio::pretty_frequency_MHz_string (f)); update_line_edit (dx_call_line_edit_, dx_call); update_line_edit (dx_grid_line_edit_, dx_grid); diff --git a/UDPExamples/ClientWidget.hpp b/UDPExamples/ClientWidget.hpp index ee91d084a..fb0ef47f4 100644 --- a/UDPExamples/ClientWidget.hpp +++ b/UDPExamples/ClientWidget.hpp @@ -52,7 +52,7 @@ public: , QString const& de_call, QString const& de_grid, QString const& dx_grid , bool watchdog_timeout, QString const& sub_mode, bool fast_mode , quint8 special_op_mode, quint32 frequency_tolerance, quint32 tr_period - , QString const& configuration_name); + , QString const& configuration_name, QString const& tx_message); Q_SLOT void decode_added (bool is_new, ClientKey const& key, QTime, qint32 snr , float delta_time, quint32 delta_frequency, QString const& mode , QString const& message, bool low_confidence, bool off_air); @@ -122,6 +122,7 @@ private: QLineEdit * mode_line_edit_; QSpinBox * frequency_tolerance_spin_box_; QLabel * tx_mode_label_; + QLabel * tx_message_label_; QLineEdit * submode_line_edit_; QCheckBox * fast_mode_check_box_; QSpinBox * tr_period_spin_box_; diff --git a/UDPExamples/MessageServer.cpp b/UDPExamples/MessageServer.cpp index 8aadd08a6..74090395b 100644 --- a/UDPExamples/MessageServer.cpp +++ b/UDPExamples/MessageServer.cpp @@ -243,9 +243,11 @@ void MessageServer::impl::parse_message (QHostAddress const& sender, port_type s quint32 frequency_tolerance {quint32_max}; quint32 tr_period {quint32_max}; QByteArray configuration_name; + QByteArray tx_message; in >> f >> mode >> dx_call >> report >> tx_mode >> tx_enabled >> transmitting >> decoding >> rx_df >> tx_df >> de_call >> de_grid >> dx_grid >> watchdog_timeout >> sub_mode - >> fast_mode >> special_op_mode >> frequency_tolerance >> tr_period >> configuration_name; + >> fast_mode >> special_op_mode >> frequency_tolerance >> tr_period >> configuration_name + >> tx_message; if (check_status (in) != Fail) { Q_EMIT self_->status_update (client_key, f, QString::fromUtf8 (mode) @@ -256,7 +258,8 @@ void MessageServer::impl::parse_message (QHostAddress const& sender, port_type s , QString::fromUtf8 (dx_grid), watchdog_timeout , QString::fromUtf8 (sub_mode), fast_mode , special_op_mode, frequency_tolerance, tr_period - , QString::fromUtf8 (configuration_name)); + , QString::fromUtf8 (configuration_name) + , QString::fromUtf8 (tx_message)); } } break; diff --git a/UDPExamples/MessageServer.hpp b/UDPExamples/MessageServer.hpp index 7cf5653a0..c18cc95fd 100644 --- a/UDPExamples/MessageServer.hpp +++ b/UDPExamples/MessageServer.hpp @@ -97,7 +97,7 @@ public: , QString const& de_call, QString const& de_grid, QString const& dx_grid , bool watchdog_timeout, QString const& sub_mode, bool fast_mode , quint8 special_op_mode, quint32 frequency_tolerance, quint32 tr_period - , QString const& configuration_name); + , QString const& configuration_name, QString const& tx_message); Q_SIGNAL void client_closed (ClientKey const&); Q_SIGNAL void decode (bool is_new, ClientKey const&, QTime time, qint32 snr, float delta_time , quint32 delta_frequency, QString const& mode, QString const& message diff --git a/UDPExamples/UDPDaemon.cpp b/UDPExamples/UDPDaemon.cpp index 2d028f074..1d3a7abef 100644 --- a/UDPExamples/UDPDaemon.cpp +++ b/UDPExamples/UDPDaemon.cpp @@ -59,7 +59,7 @@ public: , QString const& /*de_call*/, QString const& /*de_grid*/, QString const& /*dx_grid*/ , bool /* watchdog_timeout */, QString const& sub_mode, bool /*fast_mode*/ , quint8 /*special_op_mode*/, quint32 /*frequency_tolerance*/, quint32 /*tr_period*/ - , QString const& /*configuration_name*/) + , QString const& /*configuration_name*/, QString const& /*tx_message*/) { if (key == key_) { diff --git a/widgets/mainwindow.cpp b/widgets/mainwindow.cpp index a24065d60..f7517079d 100644 --- a/widgets/mainwindow.cpp +++ b/widgets/mainwindow.cpp @@ -4135,7 +4135,14 @@ void MainWindow::guiUpdate() } } - m_currentMessage = QString::fromLatin1(msgsent); + { + auto temp = m_currentMessage; + m_currentMessage = QString::fromLatin1(msgsent); + if (m_currentMessage != temp) // check if tx message changed + { + statusUpdate (); + } + } m_bCallingCQ = CALLING == m_QSOProgress || m_currentMessage.contains (QRegularExpression {"^(CQ|QRZ) "}); if(m_mode=="FT8" or m_mode=="FT4") { @@ -8398,7 +8405,8 @@ void MainWindow::statusUpdate () const m_hisGrid, m_tx_watchdog, submode != QChar::Null ? QString {submode} : QString {}, m_bFastMode, static_cast (m_config.special_op_id ()), - ftol, tr_period, m_multi_settings->configuration_name ()); + ftol, tr_period, m_multi_settings->configuration_name (), + m_currentMessage); } void MainWindow::childEvent (QChildEvent * e) From a38ec853a43532be17ab7dfff821c10a7de96516 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Wed, 30 Dec 2020 21:45:57 +0000 Subject: [PATCH 49/75] Don't pick up reports to other stations as ours --- widgets/mainwindow.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/widgets/mainwindow.cpp b/widgets/mainwindow.cpp index f7517079d..39cb8b479 100644 --- a/widgets/mainwindow.cpp +++ b/widgets/mainwindow.cpp @@ -3571,7 +3571,16 @@ void MainWindow::readFromStdout() //readFromStdout decodedtext.deCallAndGrid(/*out*/deCall,grid); { auto t = Radio::base_callsign (ui->dxCallEntry->text ()); - if ((t == deCall || ui->dxCallEntry->text () == deCall || !t.size ()) && rpt.size ()) m_rptRcvd = rpt; + auto const& dx_call = decodedtext.call (); + if (rpt.size () // report in message + && (m_baseCall == Radio::base_callsign (dx_call) // for us + || "DE" == dx_call) // probably for us + && (t == deCall // DX station base call is QSO partner + || ui->dxCallEntry->text () == deCall // DX station full call is QSO partner + || !t.size ())) // not in QSO + { + m_rptRcvd = rpt; + } } // extract details and send to PSKreporter int nsec=QDateTime::currentMSecsSinceEpoch()/1000-m_secBandChanged; From e4a7591a835d672a052655fb0ba48951799b54f7 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Sat, 2 Jan 2021 18:02:09 +0000 Subject: [PATCH 50/75] Make the colour highlighting scheme immune to style sheet overrides --- widgets/colorhighlighting.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/widgets/colorhighlighting.cpp b/widgets/colorhighlighting.cpp index 6ad0bd4da..e7e9deddb 100644 --- a/widgets/colorhighlighting.cpp +++ b/widgets/colorhighlighting.cpp @@ -1,7 +1,7 @@ #include "colorhighlighting.h" #include -#include +#include #include "SettingsGroup.hpp" #include "models/DecodeHighlightingModel.hpp" @@ -113,16 +113,16 @@ void ColorHighlighting::set_items (DecodeHighlightingModel const& highlighting_m default: continue; } - auto palette = example->parentWidget ()->palette (); + auto style_sheet = example->parentWidget ()->styleSheet (); if (Qt::NoBrush != item.background_.style ()) { - palette.setColor (QPalette::Window, item.background_.color ()); + style_sheet += QString {"; background-color: #%1"}.arg (item.background_.color ().rgb (), 8, 16, QLatin1Char {'0'}); } if (Qt::NoBrush != item.foreground_.style ()) { - palette.setColor (QPalette::WindowText, item.foreground_.color ()); + style_sheet += QString {"; color: #%1"}.arg (item.foreground_.color ().rgb (), 8, 16, QLatin1Char {'0'}); } - example->setPalette (palette); + example->setStyleSheet (style_sheet); example->setEnabled (item.enabled_); label->setText (DecodeHighlightingModel::highlight_name (item.type_)); label->setEnabled (item.enabled_); From b0b16033a8c4a4735f634d99d8e90bda355c807e Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Sat, 2 Jan 2021 21:12:45 +0000 Subject: [PATCH 51/75] Updated Danish UI translation, tnx Michael, 5P1KZX --- translations/wsjtx_da.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/translations/wsjtx_da.ts b/translations/wsjtx_da.ts index bb7744752..ecb74c401 100644 --- a/translations/wsjtx_da.ts +++ b/translations/wsjtx_da.ts @@ -247,7 +247,7 @@ <html><head/><body><p>Right-click here for available actions.</p></body></html> - <html><head/><body> <p> Højreklik her for tilgængelige muligheder. </p> </body> </html> + <html><head/><body><p> Højreklik her for tilgængelige muligheder.</p></body></html> @@ -318,7 +318,7 @@ New Call - Ny kaldesignal + Nyt kaldesignal @@ -2197,7 +2197,7 @@ Fejl(%2): %3 &Decode - &Dekod + &Dekode @@ -2492,7 +2492,7 @@ Gul er for lavt Fast - Fast + Hurtig @@ -5578,7 +5578,7 @@ Fejl(%2): %3 Monitor returns to last used frequency - Montor til seneste brugte frekvens + Monitor til seneste brugte frekvens @@ -5673,7 +5673,7 @@ den stille periode, når dekodningen er udført. Serial Port Parameters - Seriek Port Parametre + Seriel Port Parametre @@ -5774,7 +5774,7 @@ den stille periode, når dekodningen er udført. Default - Deafult + Default From 11b7aa9429751e28713f9218de23e21b5820ea64 Mon Sep 17 00:00:00 2001 From: Steven Franke Date: Sun, 13 Dec 2020 15:33:12 -0600 Subject: [PATCH 52/75] Implements decoding of FST4W messages as (240,50) crc-less codewords. By cascading the full 24-bit crc generator matrix with the (240,74) LDPC code generator, create a (240,50) generator that is used to decode with approximately 1 dB better sensitivity than the (240,64) with 14-bit CRC approach that is normally used. This approach treats the CRC bits as additional parity bits and provides no means for identifying incorrect codewords. All codewords on the list generated by the OSD algorithm have CRCs that match the CRC of the message payload. Codewords are validated by unpacking the message and comparing the unpacked message with the list of stored callsign/grid pairs stored in the fst4w_calls.txt file. --- CMakeLists.txt | 1 + lib/fst4/decode240_74.f90 | 3 +- lib/fst4/fastosd240_74.f90 | 291 +++++++++++++++++++++++++++++++++++++ lib/fst4/ldpcsim240_74.f90 | 2 +- lib/fst4_decode.f90 | 232 +++++++++++++++++++---------- 5 files changed, 452 insertions(+), 77 deletions(-) create mode 100644 lib/fst4/fastosd240_74.f90 diff --git a/CMakeLists.txt b/CMakeLists.txt index e9c6db665..1adbcd0ee 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -562,6 +562,7 @@ set (wsjt_FSRCS lib/fst4/ldpcsim240_74.f90 lib/fst4/osd240_101.f90 lib/fst4/osd240_74.f90 + lib/fst4/fastosd240_74.f90 lib/fst4/get_crc24.f90 lib/fst4/fst4_baseline.f90 ) diff --git a/lib/fst4/decode240_74.f90 b/lib/fst4/decode240_74.f90 index be18f6e09..20a83362f 100644 --- a/lib/fst4/decode240_74.f90 +++ b/lib/fst4/decode240_74.f90 @@ -135,7 +135,8 @@ subroutine decode240_74(llr,Keff,maxosd,norder,apmask,message74,cw,ntype,nharder do i=1,nosd zn=zsave(:,i) - call osd240_74(zn,Keff,apmask,norder,message74,cw,nharderror,dminosd) +! call osd240_74(zn,Keff,apmask,norder,message74,cw,nharderror,dminosd) + call fastosd240_74(zn,Keff,apmask,norder,message74,cw,nharderror,dminosd) if(nharderror.gt.0) then hdec=0 where(llr .ge. 0) hdec=1 diff --git a/lib/fst4/fastosd240_74.f90 b/lib/fst4/fastosd240_74.f90 new file mode 100644 index 000000000..03ae4071c --- /dev/null +++ b/lib/fst4/fastosd240_74.f90 @@ -0,0 +1,291 @@ +subroutine fastosd240_74(llr,k,apmask,ndeep,message74,cw,nhardmin,dmin) +! +! An ordered-statistics decoder for the (240,74) code. +! Message payload is 50 bits. Any or all of a 24-bit CRC can be +! used for detecting incorrect codewords. The remaining CRC bits are +! cascaded with the LDPC code for the purpose of improving the +! distance spectrum of the code. +! +! If p1 (0.le.p1.le.24) is the number of CRC24 bits that are +! to be used for bad codeword detection, then the argument k should +! be set to 77+p1. +! +! Valid values for k are in the range [50,74]. +! + character*24 c24 + integer, parameter:: N=240 + integer*1 apmask(N),apmaskr(N) + integer*1, allocatable, save :: gen(:,:) + integer*1, allocatable :: genmrb(:,:),g2(:,:) + integer*1, allocatable :: temp(:),temprow(:),m0(:),me(:),mi(:) + integer indices(N),indices2(N),nxor(N) + integer*1 cw(N),ce(N),c0(N),hdec(N) + integer*1, allocatable :: decoded(:) + integer*1 message74(74) + integer*1, allocatable :: sp(:) + integer indx(N),ksave + real llr(N),rx(N),absrx(N) + + logical first + data first/.true./,ksave/64/ + save first,ksave + + allocate( genmrb(k,N), g2(N,k) ) + allocate( temp(k), temprow(n), m0(k), me(k), mi(k) ) + allocate( decoded(k) ) + + if( first .or. k.ne.ksave) then ! fill the generator matrix +! +! Create generator matrix for partial CRC cascaded with LDPC code. +! +! Let p2=74-k and p1+p2=24. +! +! The last p2 bits of the CRC24 are cascaded with the LDPC code. +! +! The first p1=k-50 CRC24 bits will be used for error detection. +! + if( allocated(gen) ) deallocate(gen) + allocate( gen(k,N) ) + gen=0 + do i=1,k + message74=0 + message74(i)=1 + if(i.le.50) then + call get_crc24(message74,74,ncrc24) + write(c24,'(b24.24)') ncrc24 + read(c24,'(24i1)') message74(51:74) + message74(51:k)=0 + endif + call encode240_74(message74,cw) + gen(i,:)=cw + enddo + + first=.false. + ksave=k + endif + +! Use best k elements from the sorted list for the first basis. For the 2nd basis replace +! the nswap lowest quality symbols with the best nswap elements from the parity symbols. + nswap=20 + + do ibasis=1,2 + rx=llr + apmaskr=apmask + +! Hard decisions on the received word. + hdec=0 + where(rx .ge. 0) hdec=1 + +! Use magnitude of received symbols as a measure of reliability. + absrx=abs(llr) + call indexx(absrx,N,indx) + +! Re-order the columns of the generator matrix in order of decreasing reliability. + do i=1,N + genmrb(1:k,i)=gen(1:k,indx(N+1-i)) + indices(i)=indx(N+1-i) + enddo + + if(ibasis.eq.2) then + do i=k-nswap+1,k + temp(1:k)=genmrb(1:k,i) + genmrb(1:k,i)=genmrb(1:k,i+nswap) + genmrb(1:k,i+nswap)=temp(1:k) + itmp=indices(i) + indices(i)=indices(i+nswap) + indices(i+nswap)=itmp + enddo + endif + +! Do gaussian elimination to create a generator matrix with the most reliable +! received bits in positions 1:k in order of decreasing reliability (more or less). + + icol=1 + indices2=0 + nskipped=0 + do id=1,k + iflag=0 + do while(iflag.eq.0) + if(genmrb(id,icol).ne.1) then + do j=id+1,k + if(genmrb(j,icol).eq.1) then + temprow=genmrb(id,:) + genmrb(id,:)=genmrb(j,:) + genmrb(j,:)=temprow + iflag=1 + endif + enddo + if(iflag.eq.0) then ! skip this column + nskipped=nskipped+1 + indices2(k+nskipped)=icol ! put icol where skipped columns go + icol=icol+1 ! look at the next column + endif + else + iflag=1 + endif + enddo + indices2(id)=icol + do j=1,k + if(id.ne.j .and. genmrb(j,icol).eq.1) then + genmrb(j,:)=ieor(genmrb(id,:),genmrb(j,:)) + endif + enddo + icol=icol+1 + enddo + do i=k+nskipped+1,240 + indices2(i)=i + enddo + genmrb(1:k,:)=genmrb(1:k,indices2) + indices=indices(indices2) + +!************************************ + g2=transpose(genmrb) + +! The hard decisions for the k MRB bits define the order 0 message, m0. +! Encode m0 using the modified generator matrix to find the "order 0" codeword. +! Flip various combinations of bits in m0 and re-encode to generate a list of +! codewords. Return the member of the list that has the smallest Euclidean +! distance to the received word. + + hdec=hdec(indices) ! hard decisions from received symbols + m0=hdec(1:k) ! zero'th order message + absrx=abs(llr) + absrx=absrx(indices) + rx=rx(indices) + apmaskr=apmaskr(indices) + + call mrbencode74(m0,c0,g2,N,k) + nxor=ieor(c0,hdec) + nhardmin=sum(nxor) + dmin=sum(nxor*absrx) + np=32 + if(ibasis.eq.1) allocate(sp(np)) + + cw=c0 + ntotal=0 + nrejected=0 + + if(ndeep.eq.0) goto 998 ! norder=0 + if(ndeep.gt.4) ndeep=4 + if( ndeep.eq. 1) then + nord=1 + xlambda=0.0 + nsyncmax=np + elseif(ndeep.eq.2) then + nord=2 + xlambda=0.0 + nsyncmax=np + elseif(ndeep.eq.3) then + nord=3 + xlambda=4.0 + nsyncmax=11 + elseif(ndeep.eq.4) then + nord=4 + xlambda=3.5 + nsyndmax=11 + endif + + s1=sum(absrx(1:k)) + s2=sum(absrx(k+1:N)) + rho=s1/(s1+xlambda*s2) + rhodmin=rho*dmin + nerr64=-1 + do iorder=1,nord +!beta=0.0 +!if(iorder.ge.3) beta=0.4 +!spnc_order=sum(absrx(k-iorder+1:k))+beta*(N-k) +!if(dmin.lt.spnc_order) cycle + mi(1:k-iorder)=0 + mi(k-iorder+1:k)=1 + iflag=k-iorder+1 + do while(iflag .ge.0) + ntotal=ntotal+1 + me=ieor(m0,mi) + d1=sum(mi(1:k)*absrx(1:k)) + if(d1.gt.rhodmin) exit + call partial_syndrome(me,sp,np,g2,N,K) + nwhsp=sum(ieor(sp(1:np),hdec(k:k+np-1))) + if(nwhsp.le.nsyndmax) then + call mrbencode74(me,ce,g2,N,k) + nxor=ieor(ce,hdec) + dd=sum(nxor*absrx(1:N)) + if( dd .lt. dmin ) then + dmin=dd + rhodmin=rho*dmin + cw=ce + nhardmin=sum(nxor) + nwhspmin=nwhsp + nerr64=sum(nxor(1:K)) + endif + endif +! Get the next test error pattern, iflag will go negative +! when the last pattern with weight iorder has been generated. + call nextpat74(mi,k,iorder,iflag) + enddo + enddo + +998 continue +! Re-order the codeword to [message bits][parity bits] format. + cw(indices)=cw + hdec(indices)=hdec + message74=cw(1:74) + call get_crc24(message74,74,nbadcrc) + if(nbadcrc.eq.0) exit + nhardmin=-nhardmin + enddo ! basis loop + return +end subroutine fastosd240_74 + +subroutine mrbencode74(me,codeword,g2,N,K) + integer*1 me(K),codeword(N),g2(N,K) +! fast encoding for low-weight test patterns + codeword=0 + do i=1,K + if( me(i) .eq. 1 ) then + codeword=ieor(codeword,g2(1:N,i)) + endif + enddo + return +end subroutine mrbencode74 + +subroutine partial_syndrome(me,sp,np,g2,N,K) + integer*1 me(K),sp(np),g2(N,K) +! compute partial syndrome + sp=0 + do i=1,K + if( me(i) .eq. 1 ) then + sp=ieor(sp,g2(K:K+np-1,i)) + endif + enddo + return +end subroutine partial_syndrome + +subroutine nextpat74(mi,k,iorder,iflag) + integer*1 mi(k),ms(k) +! generate the next test error pattern + ind=-1 + do i=1,k-1 + if( mi(i).eq.0 .and. mi(i+1).eq.1) ind=i + enddo + if( ind .lt. 0 ) then ! no more patterns of this order + iflag=ind + return + endif + ms=0 + ms(1:ind-1)=mi(1:ind-1) + ms(ind)=1 + ms(ind+1)=0 + if( ind+1 .lt. k ) then + nz=iorder-sum(ms) + ms(k-nz+1:k)=1 + endif + mi=ms + do i=1,k ! iflag will point to the lowest-index 1 in mi + if(mi(i).eq.1) then + iflag=i + exit + endif + enddo + return +end subroutine nextpat74 + diff --git a/lib/fst4/ldpcsim240_74.f90 b/lib/fst4/ldpcsim240_74.f90 index b488aa6b6..78e8e6b5f 100644 --- a/lib/fst4/ldpcsim240_74.f90 +++ b/lib/fst4/ldpcsim240_74.f90 @@ -101,7 +101,7 @@ write(*,'(24i1)') msgbits(51:74) llr=2.0*rxdata/(ss*ss) apmask=0 dmin=0.0 - maxosd=0 + maxosd=2 call decode240_74(llr, Keff, maxosd, norder, apmask, message74, cw, ntype, nharderror, dmin) if(nharderror.ge.0) then n2err=0 diff --git a/lib/fst4_decode.f90 b/lib/fst4_decode.f90 index ba49fb54d..ccf6d9662 100644 --- a/lib/fst4_decode.f90 +++ b/lib/fst4_decode.f90 @@ -33,15 +33,17 @@ contains ndepth,ntrperiod,nexp_decode,ntol,emedelay,lagain,lapcqonly,mycall, & hiscall,iwspr) + use prog_args use timer_module, only: timer use packjt77 use, intrinsic :: iso_c_binding include 'fst4/fst4_params.f90' - parameter (MAXCAND=100) + parameter (MAXCAND=100,MAXWCALLS=100) class(fst4_decoder), intent(inout) :: this procedure(fst4_decode_callback) :: callback character*37 decodes(100) character*37 msg,msgsent + character*20 wcalls(MAXWCALLS), wpart character*77 c77 character*12 mycall,hiscall character*12 mycall0,hiscall0 @@ -66,7 +68,8 @@ contains integer mcq(29),mrrr(19),m73(19),mrr73(19) logical badsync,unpk77_success,single_decode - logical first,nohiscall,lwspr,ex + logical first,nohiscall,lwspr,ex,wcalls_exists,donocrcdecode + logical new_callsign integer*2 iwave(30*60*12000) @@ -80,6 +83,7 @@ contains 0,1,0,1,0,1,1,0,1,1,1,1,1,0,0,0,1,0,1/ data first/.true./,hmod/1/ save first,apbits,nappasses,naptypes,mycall0,hiscall0 + save wcalls,nwcalls this%callback => callback dxcall13=hiscall ! initialize for use in packjt77 @@ -88,6 +92,24 @@ contains if(iwspr.ne.0.and.iwspr.ne.1) return if(first) then +! read the fst4_calls.txt file + write(*,*) 'data_dir is:',trim(data_dir) + inquire(file=trim(data_dir)//'/fst4w_calls.txt',exist=wcalls_exists) + if( wcalls_exists ) then + open(42,file=trim(data_dir)//'/fst4w_calls.txt',status='unknown') + write(*,*) 'fst4w_calls.txt exists' + do i=1,MAXWCALLS + wcalls(i)='' + read(42,fmt='(a)',end=2867) wcalls(i) + wcalls(i)=adjustl(wcalls(i)) + if(len(trim(wcalls(i))).eq.0) exit + write(*,*) 'record ',i,':',wcalls(i),':',len(trim(wcalls(i))) + enddo +2867 nwcalls=i-1 + write(*,*) 'nwcalls ',nwcalls + close(42) + endif + mcq=2*mod(mcq+rvec(1:29),2)-1 mrrr=2*mod(mrrr+rvec(59:77),2)-1 m73=2*mod(m73+rvec(59:77),2)-1 @@ -216,12 +238,15 @@ contains if(ndepth.eq.3) then nblock=4 jittermax=2 + donocrcdecode=.true. elseif(ndepth.eq.2) then - nblock=3 - jittermax=0 + nblock=4 + jittermax=2 + donocrcdecode=.false. elseif(ndepth.eq.1) then - nblock=1 + nblock=4 jittermax=0 + donocrcdecode=.false. endif ndropmax=1 @@ -244,7 +269,7 @@ contains if(iwspr.eq.1) then !FST4W !300 Hz wide noise-fit window - nfa=max(100,nint(nfqso+1.5*baud-150)) + nfa=max(100,nint(nfqso+1.5*baud-150)) nfb=min(4800,nint(nfqso+1.5*baud+150)) fa=max(100,nint(nfqso+1.5*baud-ntol)) ! signal search window fb=min(4800,nint(nfqso+1.5*baud+ntol)) @@ -252,18 +277,19 @@ contains fa=max(100,nint(nfa+1.5*baud)) fb=min(4800,nint(nfb+1.5*baud)) ! extend noise fit 100 Hz outside of search window - nfa=max(100,nfa-100) + nfa=max(100,nfa-100) nfb=min(4800,nfb+100) else fa=max(100,nint(nfa+1.5*baud)) fb=min(4800,nint(nfb+1.5*baud)) ! extend noise fit 100 Hz outside of search window - nfa=max(100,nfa-100) + nfa=max(100,nfa-100) nfb=min(4800,nfb+100) endif - + ndecodes=0 decodes=' ' + new_callsign=.false. do inb=0,inb1,inb2 if(nb.lt.0) npct=inb call blanker(iwave,nfft1,ndropmax,npct,c_bigfft) @@ -275,16 +301,16 @@ contains nsyncoh=8 minsync=1.20 if(ntrperiod.eq.15) minsync=1.15 - + ! Get first approximation of candidate frequencies call get_candidates_fst4(c_bigfft,nfft1,nsps,hmod,fs,fa,fb,nfa,nfb, & - minsync,ncand,candidates0) + minsync,ncand,candidates0) isbest=0 fc2=0. do icand=1,ncand fc0=candidates0(icand,1) if(iwspr.eq.0 .and. nb.lt.0 .and. npct.ne.0 .and. & - abs(fc0-(nfqso+1.5*baud)).gt.ntol) cycle + abs(fc0-(nfqso+1.5*baud)).gt.ntol) cycle detmet=candidates0(icand,2) ! Downconvert and downsample a slice of the spectrum centered on the @@ -330,7 +356,7 @@ contains endif enddo ncand=ic - + ! If FST4 and Single Decode is not checked, then find candidates within ! 20 Hz of nfqso and put them at the top of the list if(iwspr.eq.0 .and. .not.single_decode) then @@ -373,7 +399,7 @@ contains bitmetrics=0 call timer('bitmetrc',0) call get_fst4_bitmetrics(cframe,nss,nblock,nhicoh,bitmetrics, & - s4,nsync_qual,badsync) + s4,nsync_qual,badsync) call timer('bitmetrc',1) if(badsync) cycle @@ -405,7 +431,7 @@ contains iaptype=0 endif - if(itry.gt.nblock) then ! do ap passes + if(itry.gt.nblock .and. iwspr.eq.0) then ! do ap passes llr=llrs(:,nblock) ! Use largest blocksize as the basis for AP passes iaptype=naptypes(nQSOProgress,itry-nblock) if(lapcqonly) iaptype=1 @@ -428,7 +454,7 @@ contains apmask(1:58)=1 llr(1:58)=apmag*apbits(1:58) endif - + if(iaptype.eq.4 .or. iaptype.eq.5 .or. iaptype .eq.6) then apmask=0 apmask(1:77)=1 @@ -438,7 +464,7 @@ contains if(iaptype.eq.6) llr(59:77)=apmag*mrr73(1:19) endif endif - + dmin=0.0 nharderrors=-1 unpk77_success=.false. @@ -448,83 +474,133 @@ contains norder=3 call timer('d240_101',0) call decode240_101(llr,Keff,maxosd,norder,apmask,message101, & - cw,ntype,nharderrors,dmin) + cw,ntype,nharderrors,dmin) call timer('d240_101',1) - elseif(iwspr.eq.1) then - maxosd=2 - call timer('d240_74 ',0) - Keff=64 - norder=4 - call decode240_74(llr,Keff,maxosd,norder,apmask,message74,cw, & - ntype,nharderrors,dmin) - call timer('d240_74 ',1) - endif - - if(nharderrors .ge.0) then if(count(cw.eq.1).eq.0) then nharderrors=-nharderrors cycle endif - if(iwspr.eq.0) then - write(c77,'(77i1)') mod(message101(1:77)+rvec,2) + write(c77,'(77i1)') mod(message101(1:77)+rvec,2) + call unpack77(c77,1,msg,unpk77_success) + elseif(iwspr.eq.1) then + iaptype=0 + if( donocrcdecode ) then + maxosd=1 + call timer('d240_74 ',0) + Keff=50 + norder=4 + call decode240_74(llr,Keff,maxosd,norder,apmask,message74,cw, & + ntype,nharderrors,dmin) + call timer('d240_74 ',1) + if(count(cw.eq.1).eq.0) then + nharderrors=-nharderrors + cycle + endif + write(c77,'(50i1)') message74(1:50) + c77(51:77)='000000000000000000000110000' call unpack77(c77,1,msg,unpk77_success) - else + if(unpk77_success) then + unpk77_success=.false. + do i=1,nwcalls + if(index(msg,trim(wcalls(i))).gt.0) then + unpk77_success=.true. + iaptype=8 + endif + enddo + endif + endif + if(.not. unpk77_success) then + maxosd=2 + call timer('d240_74 ',0) + Keff=64 + norder=3 + call decode240_74(llr,Keff,maxosd,norder,apmask,message74,cw, & + ntype,nharderrors,dmin) + call timer('d240_74 ',1) + if(nharderrors.lt.0) cycle + if(count(cw.eq.1).eq.0) then + nharderrors=-nharderrors + cycle + endif write(c77,'(50i1)') message74(1:50) c77(51:77)='000000000000000000000110000' call unpack77(c77,1,msg,unpk77_success) endif - if(unpk77_success) then - idupe=0 - do i=1,ndecodes - if(decodes(i).eq.msg) idupe=1 + + if(unpk77_success.and.Keff.eq.64) then + + i1=index(msg,' ') + i2=i1+index(msg(i1+1:),' ') + wpart=trim(msg(1:i2)) + + ifound=0 + do i=1,nwcalls + if(index(wcalls(i),wpart).ne.0) ifound=1 enddo - if(idupe.eq.1) goto 800 - ndecodes=ndecodes+1 - decodes(ndecodes)=msg - - if(iwspr.eq.0) then - call get_fst4_tones_from_bits(message101,itone,0) - else - call get_fst4_tones_from_bits(message74,itone,1) - endif - inquire(file='plotspec',exist=ex) - fmid=-999.0 - call timer('dopsprd ',0) - if(ex) then - call dopspread(itone,iwave,nsps,nmax,ndown,hmod, & - isbest,fc_synced,fmid,w50) - endif - call timer('dopsprd ',1) - xsig=0 - do i=1,NN - xsig=xsig+s4(itone(i),i) - enddo - base=candidates(icand,5) - arg=600.0*(xsig/base)-1.0 - if(arg.gt.0.0) then - xsnr=10*log10(arg)-35.5-12.5*log10(nsps/8200.0) - if(ntrperiod.eq. 15) xsnr=xsnr+2 - if(ntrperiod.eq. 30) xsnr=xsnr+1 - if(ntrperiod.eq. 900) xsnr=xsnr+1 - if(ntrperiod.eq.1800) xsnr=xsnr+2 - else - xsnr=-99.9 + + if(ifound.eq.0) then ! This is a new callsign + new_callsign=.true. + if(nwcalls.lt.MAXWCALLS) then + nwcalls=nwcalls+1 + wcalls(nwcalls)=wpart + else + wcalls(1:nwcalls-1)=wcalls(2:nwcalls) + wcalls(nwcalls)=wpart + endif endif + endif + endif + + if(nharderrors .ge.0 .and. unpk77_success) then + idupe=0 + do i=1,ndecodes + if(decodes(i).eq.msg) idupe=1 + enddo + if(idupe.eq.1) goto 800 + ndecodes=ndecodes+1 + decodes(ndecodes)=msg + + if(iwspr.eq.0) then + call get_fst4_tones_from_bits(message101,itone,0) else - cycle + call get_fst4_tones_from_bits(message74,itone,1) + endif + inquire(file='plotspec',exist=ex) + fmid=-999.0 + call timer('dopsprd ',0) + if(ex) then + call dopspread(itone,iwave,nsps,nmax,ndown,hmod, & + isbest,fc_synced,fmid,w50) + endif + call timer('dopsprd ',1) + xsig=0 + do i=1,NN + xsig=xsig+s4(itone(i),i) + enddo + base=candidates(icand,5) + arg=600.0*(xsig/base)-1.0 + if(arg.gt.0.0) then + xsnr=10*log10(arg)-35.5-12.5*log10(nsps/8200.0) + if(ntrperiod.eq. 15) xsnr=xsnr+2 + if(ntrperiod.eq. 30) xsnr=xsnr+1 + if(ntrperiod.eq. 900) xsnr=xsnr+1 + if(ntrperiod.eq.1800) xsnr=xsnr+2 + else + xsnr=-99.9 endif nsnr=nint(xsnr) - qual=0. + qual=0.0 + if(iaptype.eq.8) qual=1. fsig=fc_synced - 1.5*baud if(ex) then write(21,3021) nutc,icand,itry,nsyncoh,iaptype, & - ijitter,ntype,nsync_qual,nharderrors,dmin, & - sync,xsnr,xdt,fsig,w50,trim(msg) + ijitter,ntype,nsync_qual,nharderrors,dmin, & + sync,xsnr,xdt,fsig,w50,trim(msg) 3021 format(i6.6,6i3,2i4,f6.1,f7.2,f6.1,f6.2,f7.1,f7.3,1x,a) flush(21) endif call this%callback(nutc,smax1,nsnr,xdt,fsig,msg, & - iaptype,qual,ntrperiod,lwspr,fmid,w50) + iaptype,qual,ntrperiod,lwspr,fmid,w50) if(iwspr.eq.0 .and. nb.lt.0) go to 900 goto 800 endif @@ -532,9 +608,15 @@ contains enddo ! istart jitter 800 enddo !candidate list enddo ! noise blanker loop - + if(new_callsign) then ! re-write the fst4w_calls.txt file + open(42,file=trim(data_dir)//'/fst4w_calls.txt',status='unknown') + do i=1,nwcalls + write(42,'(a20)') trim(wcalls(i)) + enddo + close(42) + endif 900 return - end subroutine decode + end subroutine decode subroutine sync_fst4(cd0,i0,f0,hmod,ncoh,np,nss,ntr,fs,sync) @@ -902,6 +984,6 @@ contains enddo return - end subroutine dopspread + end subroutine dopspread end module fst4_decode From 65ff3ce05e554f474813666bd15a8e08a600c9d7 Mon Sep 17 00:00:00 2001 From: Steven Franke Date: Sun, 13 Dec 2020 15:47:38 -0600 Subject: [PATCH 53/75] Remove some debug prints. --- lib/fst4_decode.f90 | 4 ---- 1 file changed, 4 deletions(-) diff --git a/lib/fst4_decode.f90 b/lib/fst4_decode.f90 index ccf6d9662..c1ef0ed26 100644 --- a/lib/fst4_decode.f90 +++ b/lib/fst4_decode.f90 @@ -93,20 +93,16 @@ contains if(first) then ! read the fst4_calls.txt file - write(*,*) 'data_dir is:',trim(data_dir) inquire(file=trim(data_dir)//'/fst4w_calls.txt',exist=wcalls_exists) if( wcalls_exists ) then open(42,file=trim(data_dir)//'/fst4w_calls.txt',status='unknown') - write(*,*) 'fst4w_calls.txt exists' do i=1,MAXWCALLS wcalls(i)='' read(42,fmt='(a)',end=2867) wcalls(i) wcalls(i)=adjustl(wcalls(i)) if(len(trim(wcalls(i))).eq.0) exit - write(*,*) 'record ',i,':',wcalls(i),':',len(trim(wcalls(i))) enddo 2867 nwcalls=i-1 - write(*,*) 'nwcalls ',nwcalls close(42) endif From fc3e24f696c882c8ece26fef2b85413835613f76 Mon Sep 17 00:00:00 2001 From: Steven Franke Date: Mon, 14 Dec 2020 10:19:48 -0600 Subject: [PATCH 54/75] More work on K=50 decoding. --- lib/fst4_decode.f90 | 117 +++++++++++++++++++++++--------------------- 1 file changed, 61 insertions(+), 56 deletions(-) diff --git a/lib/fst4_decode.f90 b/lib/fst4_decode.f90 index c1ef0ed26..34f32bf9c 100644 --- a/lib/fst4_decode.f90 +++ b/lib/fst4_decode.f90 @@ -68,8 +68,9 @@ contains integer mcq(29),mrrr(19),m73(19),mrr73(19) logical badsync,unpk77_success,single_decode - logical first,nohiscall,lwspr,ex,wcalls_exists,donocrcdecode - logical new_callsign + logical first,nohiscall,lwspr + logical new_callsign,plotspec_exists,wcalls_exists,do_nocrc_decode + logical decdata_exists integer*2 iwave(30*60*12000) @@ -234,15 +235,15 @@ contains if(ndepth.eq.3) then nblock=4 jittermax=2 - donocrcdecode=.true. + do_nocrc_decode=.true. elseif(ndepth.eq.2) then nblock=4 jittermax=2 - donocrcdecode=.false. + do_nocrc_decode=.false. elseif(ndepth.eq.1) then nblock=4 jittermax=0 - donocrcdecode=.false. + do_nocrc_decode=.false. endif ndropmax=1 @@ -479,52 +480,24 @@ contains write(c77,'(77i1)') mod(message101(1:77)+rvec,2) call unpack77(c77,1,msg,unpk77_success) elseif(iwspr.eq.1) then - iaptype=0 - if( donocrcdecode ) then - maxosd=1 - call timer('d240_74 ',0) - Keff=50 - norder=4 - call decode240_74(llr,Keff,maxosd,norder,apmask,message74,cw, & - ntype,nharderrors,dmin) - call timer('d240_74 ',1) - if(count(cw.eq.1).eq.0) then - nharderrors=-nharderrors - cycle - endif - write(c77,'(50i1)') message74(1:50) - c77(51:77)='000000000000000000000110000' - call unpack77(c77,1,msg,unpk77_success) - if(unpk77_success) then - unpk77_success=.false. - do i=1,nwcalls - if(index(msg,trim(wcalls(i))).gt.0) then - unpk77_success=.true. - iaptype=8 - endif - enddo - endif +! First try decoding with Keff=64 + maxosd=2 + call timer('d240_74 ',0) + Keff=64 + norder=3 + call decode240_74(llr,Keff,maxosd,norder,apmask,message74,cw, & + ntype,nharderrors,dmin) + call timer('d240_74 ',1) + if(nharderrors.lt.0) goto 3465 + if(count(cw.eq.1).eq.0) then + nharderrors=-nharderrors + cycle endif - if(.not. unpk77_success) then - maxosd=2 - call timer('d240_74 ',0) - Keff=64 - norder=3 - call decode240_74(llr,Keff,maxosd,norder,apmask,message74,cw, & - ntype,nharderrors,dmin) - call timer('d240_74 ',1) - if(nharderrors.lt.0) cycle - if(count(cw.eq.1).eq.0) then - nharderrors=-nharderrors - cycle - endif - write(c77,'(50i1)') message74(1:50) - c77(51:77)='000000000000000000000110000' - call unpack77(c77,1,msg,unpk77_success) - endif - - if(unpk77_success.and.Keff.eq.64) then - + write(c77,'(50i1)') message74(1:50) + c77(51:77)='000000000000000000000110000' + call unpack77(c77,1,msg,unpk77_success) + if(unpk77_success) then +! If decode was obtained with Keff=64, save call/grid in fst4w_calls.txt if not there already. i1=index(msg,' ') i2=i1+index(msg(i1+1:),' ') wpart=trim(msg(1:i2)) @@ -545,6 +518,36 @@ contains endif endif endif +3465 continue + +! If no decode then try Keff=50 + iaptype=0 + if( .not. unpk77_success .and. do_nocrc_decode ) then + maxosd=1 + call timer('d240_74 ',0) + Keff=50 + norder=4 + call decode240_74(llr,Keff,maxosd,norder,apmask,message74,cw, & + ntype,nharderrors,dmin) + call timer('d240_74 ',1) + if(count(cw.eq.1).eq.0) then + nharderrors=-nharderrors + cycle + endif + write(c77,'(50i1)') message74(1:50) + c77(51:77)='000000000000000000000110000' + call unpack77(c77,1,msg,unpk77_success) +! No CRC in this mode, so only accept the decode if call/grid have been seen before + if(unpk77_success) then + unpk77_success=.false. + do i=1,nwcalls + if(index(msg,trim(wcalls(i))).gt.0) then + unpk77_success=.true. + endif + enddo + endif + endif + endif if(nharderrors .ge.0 .and. unpk77_success) then @@ -561,10 +564,10 @@ contains else call get_fst4_tones_from_bits(message74,itone,1) endif - inquire(file='plotspec',exist=ex) + inquire(file='plotspec',exist=plotspec_exists) fmid=-999.0 call timer('dopsprd ',0) - if(ex) then + if(plotspec_exists) then call dopspread(itone,iwave,nsps,nmax,ndown,hmod, & isbest,fc_synced,fmid,w50) endif @@ -586,13 +589,13 @@ contains endif nsnr=nint(xsnr) qual=0.0 - if(iaptype.eq.8) qual=1. fsig=fc_synced - 1.5*baud - if(ex) then + inquire(file='decdata',exist=decdata_exists) + if(decdata_exists) then write(21,3021) nutc,icand,itry,nsyncoh,iaptype, & - ijitter,ntype,nsync_qual,nharderrors,dmin, & + ijitter,ntype,Keff,nsync_qual,nharderrors,dmin, & sync,xsnr,xdt,fsig,w50,trim(msg) -3021 format(i6.6,6i3,2i4,f6.1,f7.2,f6.1,f6.2,f7.1,f7.3,1x,a) +3021 format(i6.6,6i3,3i4,f6.1,f9.2,f6.1,f6.2,f7.1,f7.3,1x,a) flush(21) endif call this%callback(nutc,smax1,nsnr,xdt,fsig,msg, & @@ -604,6 +607,7 @@ contains enddo ! istart jitter 800 enddo !candidate list enddo ! noise blanker loop + if(new_callsign) then ! re-write the fst4w_calls.txt file open(42,file=trim(data_dir)//'/fst4w_calls.txt',status='unknown') do i=1,nwcalls @@ -611,6 +615,7 @@ contains enddo close(42) endif + 900 return end subroutine decode From 812bd29e543a33cfced0a1c7482d1363cd478d92 Mon Sep 17 00:00:00 2001 From: Steven Franke Date: Mon, 14 Dec 2020 16:25:37 -0600 Subject: [PATCH 55/75] FST4W: Use K=66 for first OSD decode attempt and for updating fst4w_calls.txt. Use K=50 for 2nd attempt. --- lib/fst4_decode.f90 | 49 ++++++++++++++++++++++++--------------------- 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/lib/fst4_decode.f90 b/lib/fst4_decode.f90 index 34f32bf9c..d4cb47a8b 100644 --- a/lib/fst4_decode.f90 +++ b/lib/fst4_decode.f90 @@ -69,7 +69,7 @@ contains logical badsync,unpk77_success,single_decode logical first,nohiscall,lwspr - logical new_callsign,plotspec_exists,wcalls_exists,do_nocrc_decode + logical new_callsign,plotspec_exists,wcalls_exists,do_k50_decode logical decdata_exists integer*2 iwave(30*60*12000) @@ -232,18 +232,19 @@ contains allocate( cframe(0:160*nss-1) ) jittermax=2 + do_k50_decode=.false. if(ndepth.eq.3) then nblock=4 jittermax=2 - do_nocrc_decode=.true. + do_k50_decode=.true. elseif(ndepth.eq.2) then nblock=4 jittermax=2 - do_nocrc_decode=.false. + do_k50_decode=.false. elseif(ndepth.eq.1) then nblock=4 jittermax=0 - do_nocrc_decode=.false. + do_k50_decode=.false. endif ndropmax=1 @@ -480,10 +481,10 @@ contains write(c77,'(77i1)') mod(message101(1:77)+rvec,2) call unpack77(c77,1,msg,unpk77_success) elseif(iwspr.eq.1) then -! First try decoding with Keff=64 +! Try decoding with Keff=66 maxosd=2 call timer('d240_74 ',0) - Keff=64 + Keff=66 norder=3 call decode240_74(llr,Keff,maxosd,norder,apmask,message74,cw, & ntype,nharderrors,dmin) @@ -496,25 +497,27 @@ contains write(c77,'(50i1)') message74(1:50) c77(51:77)='000000000000000000000110000' call unpack77(c77,1,msg,unpk77_success) - if(unpk77_success) then -! If decode was obtained with Keff=64, save call/grid in fst4w_calls.txt if not there already. + if(unpk77_success .and. do_k50_decode) then +! If decode was obtained with Keff=66, save call/grid in fst4w_calls.txt if not there already. i1=index(msg,' ') i2=i1+index(msg(i1+1:),' ') wpart=trim(msg(1:i2)) +! Only save callsigns/grids from type 1 messages + if(index(wpart,'/').eq.0 .and. index(wpart,'<').eq.0) then + ifound=0 + do i=1,nwcalls + if(index(wcalls(i),wpart).ne.0) ifound=1 + enddo - ifound=0 - do i=1,nwcalls - if(index(wcalls(i),wpart).ne.0) ifound=1 - enddo - - if(ifound.eq.0) then ! This is a new callsign - new_callsign=.true. - if(nwcalls.lt.MAXWCALLS) then - nwcalls=nwcalls+1 - wcalls(nwcalls)=wpart - else - wcalls(1:nwcalls-1)=wcalls(2:nwcalls) - wcalls(nwcalls)=wpart + if(ifound.eq.0) then ! This is a new callsign + new_callsign=.true. + if(nwcalls.lt.MAXWCALLS) then + nwcalls=nwcalls+1 + wcalls(nwcalls)=wpart + else + wcalls(1:nwcalls-1)=wcalls(2:nwcalls) + wcalls(nwcalls)=wpart + endif endif endif endif @@ -522,7 +525,7 @@ contains ! If no decode then try Keff=50 iaptype=0 - if( .not. unpk77_success .and. do_nocrc_decode ) then + if( .not. unpk77_success .and. do_k50_decode ) then maxosd=1 call timer('d240_74 ',0) Keff=50 @@ -608,7 +611,7 @@ contains 800 enddo !candidate list enddo ! noise blanker loop - if(new_callsign) then ! re-write the fst4w_calls.txt file + if(new_callsign .and. do_k50_decode) then ! re-write the fst4w_calls.txt file open(42,file=trim(data_dir)//'/fst4w_calls.txt',status='unknown') do i=1,nwcalls write(42,'(a20)') trim(wcalls(i)) From 89cbd177dfd7419eb98e41b53dc3b4a4458d3842 Mon Sep 17 00:00:00 2001 From: Steven Franke Date: Tue, 15 Dec 2020 09:46:16 -0600 Subject: [PATCH 56/75] If file decdata is present in the data directory, then write detailed decoder data to file fst4_decodes.dat in the same directory. --- lib/fst4_decode.f90 | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/fst4_decode.f90 b/lib/fst4_decode.f90 index d4cb47a8b..d95f6d04d 100644 --- a/lib/fst4_decode.f90 +++ b/lib/fst4_decode.f90 @@ -593,13 +593,14 @@ contains nsnr=nint(xsnr) qual=0.0 fsig=fc_synced - 1.5*baud - inquire(file='decdata',exist=decdata_exists) + inquire(file=trim(data_dir)//'/decdata',exist=decdata_exists) if(decdata_exists) then + open(21,file=trim(data_dir)//'/fst4_decodes.dat',status='unknown') write(21,3021) nutc,icand,itry,nsyncoh,iaptype, & ijitter,ntype,Keff,nsync_qual,nharderrors,dmin, & sync,xsnr,xdt,fsig,w50,trim(msg) 3021 format(i6.6,6i3,3i4,f6.1,f9.2,f6.1,f6.2,f7.1,f7.3,1x,a) - flush(21) + close(21) endif call this%callback(nutc,smax1,nsnr,xdt,fsig,msg, & iaptype,qual,ntrperiod,lwspr,fmid,w50) From 66ddeff25e5d146110873bf1694c06ec4ba05ab3 Mon Sep 17 00:00:00 2001 From: Steven Franke Date: Tue, 15 Dec 2020 09:52:50 -0600 Subject: [PATCH 57/75] Do not save c2 files in FST4W mode. --- widgets/mainwindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/widgets/mainwindow.cpp b/widgets/mainwindow.cpp index 39cb8b479..eeb193e39 100644 --- a/widgets/mainwindow.cpp +++ b/widgets/mainwindow.cpp @@ -1600,7 +1600,7 @@ void MainWindow::dataSink(qint64 frames) m_saveWAVWatcher.setFuture (QtConcurrent::run (std::bind (&MainWindow::save_wave_file, this, m_fnameWE, &dec_data.d2[0], samples, m_config.my_callsign(), m_config.my_grid(), m_mode, m_nSubMode, m_freqNominal, m_hisCall, m_hisGrid))); - if (m_mode=="WSPR" or m_mode=="FST4W") { + if (m_mode=="WSPR") { QString c2name_string {m_fnameWE + ".c2"}; int len1=c2name_string.length(); char c2name[80]; From 8079d35561fc8cca332737520dcddeee9c1715f2 Mon Sep 17 00:00:00 2001 From: Steven Franke Date: Tue, 15 Dec 2020 10:32:57 -0600 Subject: [PATCH 58/75] Append decoder data to file fst4_decodes.dat instead of overwriting. --- lib/fst4_decode.f90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/fst4_decode.f90 b/lib/fst4_decode.f90 index d95f6d04d..3407e41f2 100644 --- a/lib/fst4_decode.f90 +++ b/lib/fst4_decode.f90 @@ -595,7 +595,7 @@ contains fsig=fc_synced - 1.5*baud inquire(file=trim(data_dir)//'/decdata',exist=decdata_exists) if(decdata_exists) then - open(21,file=trim(data_dir)//'/fst4_decodes.dat',status='unknown') + open(21,file=trim(data_dir)//'/fst4_decodes.dat',status='unknown',position='append') write(21,3021) nutc,icand,itry,nsyncoh,iaptype, & ijitter,ntype,Keff,nsync_qual,nharderrors,dmin, & sync,xsnr,xdt,fsig,w50,trim(msg) From b087328fc16b91c27d4664c212a23126c7a30e49 Mon Sep 17 00:00:00 2001 From: Steven Franke Date: Tue, 15 Dec 2020 14:31:46 -0600 Subject: [PATCH 59/75] Don't waste time on excess BP iterations when doing K=50. Decode a little deeper. --- lib/fst4/decode240_74.f90 | 5 +++++ lib/fst4/fastosd240_74.f90 | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/fst4/decode240_74.f90 b/lib/fst4/decode240_74.f90 index 20a83362f..f5aac2e10 100644 --- a/lib/fst4/decode240_74.f90 +++ b/lib/fst4/decode240_74.f90 @@ -25,6 +25,8 @@ subroutine decode240_74(llr,Keff,maxosd,norder,apmask,message74,cw,ntype,nharder include "ldpc_240_74_parity.f90" maxiterations=30 + if(Keff.eq.50) maxiterations=1 + nosd=0 if(maxosd.gt.3) maxosd=3 if(maxosd.eq.0) then ! osd with channel llrs @@ -36,6 +38,8 @@ subroutine decode240_74(llr,Keff,maxosd,norder,apmask,message74,cw,ntype,nharder nosd=0 endif + if(maxosd.eq.0) goto 73 + toc=0 tov=0 tanhtoc=0 @@ -133,6 +137,7 @@ subroutine decode240_74(llr,Keff,maxosd,norder,apmask,message74,cw,ntype,nharder enddo ! bp iterations +73 continue do i=1,nosd zn=zsave(:,i) ! call osd240_74(zn,Keff,apmask,norder,message74,cw,nharderror,dminosd) diff --git a/lib/fst4/fastosd240_74.f90 b/lib/fst4/fastosd240_74.f90 index 03ae4071c..f4bb61d60 100644 --- a/lib/fst4/fastosd240_74.f90 +++ b/lib/fst4/fastosd240_74.f90 @@ -181,8 +181,8 @@ subroutine fastosd240_74(llr,k,apmask,ndeep,message74,cw,nhardmin,dmin) nsyncmax=11 elseif(ndeep.eq.4) then nord=4 - xlambda=3.5 - nsyndmax=11 + xlambda=3.4 + nsyndmax=12 endif s1=sum(absrx(1:k)) From 701d517e6e0fb1b8c84c7a0f0598bd03f54aa7cb Mon Sep 17 00:00:00 2001 From: Steven Franke Date: Tue, 22 Dec 2020 12:33:24 -0600 Subject: [PATCH 60/75] For fst4sim, use Lorentzian fading spectrum when fspread is negative. --- lib/fst4/fst4sim.f90 | 3 ++- lib/fst4/lorentzian_fading.f90 | 43 ++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 lib/fst4/lorentzian_fading.f90 diff --git a/lib/fst4/fst4sim.f90 b/lib/fst4/fst4sim.f90 index 5b8f33bc3..e42bbbb02 100644 --- a/lib/fst4/fst4sim.f90 +++ b/lib/fst4/fst4sim.f90 @@ -118,7 +118,8 @@ program fst4sim do ifile=1,nfiles c=c0 - if(fspread.ne.0.0 .or. delay.ne.0.0) call watterson(c,nwave,NZ,fs,delay,fspread) + if(fspread.gt.0.0 .or. delay.ne.0.0) call watterson(c,nwave,NZ,fs,delay,fspread) + if(fspread.lt.0.0) call lorentzian_fading(c,nwave,fs,-fspread) c=sig*c wave=real(c) if(snrdb.lt.90) then diff --git a/lib/fst4/lorentzian_fading.f90 b/lib/fst4/lorentzian_fading.f90 new file mode 100644 index 000000000..c1bd5c325 --- /dev/null +++ b/lib/fst4/lorentzian_fading.f90 @@ -0,0 +1,43 @@ +subroutine lorentzian_fading(c,npts,fs,fspread) +! +! npts is the total length of the simulated data vector +! + complex c(0:npts-1) + complex cspread(0:npts-1) + complex z + + twopi=8.0*atan(1.0) + df=fs/npts + nh=npts/2 + cspread(0)=1.0 + cspread(nh)=0. + b=6.0 + do i=1,nh + f=i*df + x=b*f/fspread + z=0. + a=0. + if(x.lt.3.0) then + a=sqrt(1.111/(1.0+x*x)-0.1) + phi1=twopi*rran() + z=a*cmplx(cos(phi1),sin(phi1)) + endif + cspread(i)=z + z=0. + if(x.lt.3.0) then + phi2=twopi*rran() + z=a*cmplx(cos(phi2),sin(phi2)) + endif + cspread(npts-i)=z + enddo + + call four2a(cspread,npts,1,1,1) + + s=sum(abs(cspread)**2) + avep=s/npts + fac=sqrt(1.0/avep) + cspread=fac*cspread + c=cspread*c + + return +end subroutine lorentzian_fading From 34d32c78407503a38dd67dcb444457bdcea34662 Mon Sep 17 00:00:00 2001 From: Steven Franke Date: Tue, 22 Dec 2020 12:34:12 -0600 Subject: [PATCH 61/75] Forgot to commit CMakeLists.txt change. --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1adbcd0ee..8c7b65593 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -459,6 +459,7 @@ set (wsjt_FSRCS lib/jtmsg.f90 lib/libration.f90 lib/lorentzian.f90 + lib/fst4/lorentzian_fading.f90 lib/lpf1.f90 lib/mixlpf.f90 lib/makepings.f90 From fb7b751e6d9d274ca800d7645d3926c632283b5a Mon Sep 17 00:00:00 2001 From: Steven Franke Date: Tue, 22 Dec 2020 13:12:58 -0600 Subject: [PATCH 62/75] Remove hmod from command line parameters for fst4sim. --- lib/fst4/fst4sim.f90 | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/lib/fst4/fst4sim.f90 b/lib/fst4/fst4sim.f90 index e42bbbb02..83ac5baed 100644 --- a/lib/fst4/fst4sim.f90 +++ b/lib/fst4/fst4sim.f90 @@ -19,10 +19,10 @@ program fst4sim ! Get command-line argument(s) nargs=iargc() - if(nargs.ne.10) then - print*,'Need 10 arguments, got ',nargs - print*,'Usage: fst4sim "message" TRsec f0 DT h fdop del nfiles snr W' - print*,'Examples: fst4sim "K1JT K9AN EN50" 60 1500 0.0 1 0.1 1.0 10 -15 F' + if(nargs.ne.9) then + print*,'Need 9 arguments, got ',nargs + print*,'Usage: fst4sim "message" TRsec f0 DT fdop del nfiles snr W' + print*,'Examples: fst4sim "K1JT K9AN EN50" 60 1500 0.0 0.1 1.0 10 -15 F' print*,'W (T or F) argument is hint to encoder to use WSPR message when there is abiguity' go to 999 endif @@ -34,16 +34,14 @@ program fst4sim call getarg(4,arg) read(arg,*) xdt !Time offset from nominal (s) call getarg(5,arg) - read(arg,*) hmod !Modulation index, h - call getarg(6,arg) read(arg,*) fspread !Watterson frequency spread (Hz) - call getarg(7,arg) + call getarg(6,arg) read(arg,*) delay !Watterson delay (ms) - call getarg(8,arg) + call getarg(7,arg) read(arg,*) nfiles !Number of files - call getarg(9,arg) + call getarg(8,arg) read(arg,*) snrdb !SNR_2500 - call getarg(10,arg) + call getarg(9,arg) read(arg,*) wspr_hint !0:break ties as 77-bit 1:break ties as 50-bit nfiles=abs(nfiles) @@ -89,8 +87,8 @@ program fst4sim call genfst4(msg37,0,msgsent37,msgbits,itone,iwspr) write(*,*) write(*,'(a9,a37,a3,L2,a7,i2)') 'Message: ',msgsent37,'W:',wspr_hint,' iwspr:',iwspr - write(*,1000) f00,xdt,hmod,txt,snrdb -1000 format('f0:',f9.3,' DT:',f6.2,' hmod:',i6,' TxT:',f6.1,' SNR:',f6.1) + write(*,1000) f00,xdt,txt,snrdb +1000 format('f0:',f9.3,' DT:',f6.2,' TxT:',f6.1,' SNR:',f6.1) write(*,*) if(i3.eq.1) then write(*,*) ' mycall hiscall hisgrid' @@ -106,7 +104,8 @@ program fst4sim ! call sgran() - fsample=12000.0 + fsample=12000.0 + hmod=1 icmplx=1 f0=f00+1.5*hmod*baud call gen_fst4wave(itone,NN,nsps,nwave,fsample,hmod,f0,icmplx,c0,wave) From 4081be94e1d7b629116d343cd3a02a2a59346c72 Mon Sep 17 00:00:00 2001 From: Steven Franke Date: Wed, 23 Dec 2020 11:45:13 -0600 Subject: [PATCH 63/75] Avoid a possible of bounds error. Compute some more decode diagnostic data. --- lib/fst4_decode.f90 | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/lib/fst4_decode.f90 b/lib/fst4_decode.f90 index 3407e41f2..a1b39f744 100644 --- a/lib/fst4_decode.f90 +++ b/lib/fst4_decode.f90 @@ -59,7 +59,7 @@ contains integer itone(NN) integer hmod integer ipct(0:7) - integer*1 apmask(240),cw(240) + integer*1 apmask(240),cw(240),hdec(240) integer*1 message101(101),message74(74),message77(77) integer*1 rvec(77) integer apbits(240) @@ -392,8 +392,9 @@ contains if(ijitter.eq.1) ioffset=1 if(ijitter.eq.2) ioffset=-1 is0=isbest+ioffset - if(is0.lt.0) cycle - cframe=c2(is0:is0+160*nss-1) + iend=is0+160*nss-1 + if( is0.lt.0 .or. iend.gt.(nfft2-1) ) cycle + cframe=c2(is0:iend) bitmetrics=0 call timer('bitmetrc',0) call get_fst4_bitmetrics(cframe,nss,nblock,nhicoh,bitmetrics, & @@ -408,10 +409,10 @@ contains llrs(181:240,il)=bitmetrics(245:304, il) enddo - apmag=maxval(abs(llrs(:,1)))*1.1 + apmag=maxval(abs(llrs(:,4)))*1.1 ntmax=nblock+nappasses(nQSOProgress) if(lapcqonly) ntmax=nblock+1 - if(ndepth.eq.1) ntmax=nblock + if(ndepth.eq.1) ntmax=nblock ! no ap for ndepth=1 apmask=0 if(iwspr.eq.1) then ! 50-bit msgs, no ap decoding @@ -595,11 +596,15 @@ contains fsig=fc_synced - 1.5*baud inquire(file=trim(data_dir)//'/decdata',exist=decdata_exists) if(decdata_exists) then + hdec=0 + where(llrs(:,1).ge.0.0) hdec=1 + nhp=count(hdec.ne.cw) ! # hard errors wrt N=1 soft symbols + hd=sum(ieor(hdec,cw)*abs(llrs(:,1))) ! weighted distance wrt N=1 symbols open(21,file=trim(data_dir)//'/fst4_decodes.dat',status='unknown',position='append') write(21,3021) nutc,icand,itry,nsyncoh,iaptype, & - ijitter,ntype,Keff,nsync_qual,nharderrors,dmin, & + ijitter,ntype,Keff,nsync_qual,nharderrors,dmin,nhp,hd, & sync,xsnr,xdt,fsig,w50,trim(msg) -3021 format(i6.6,6i3,3i4,f6.1,f9.2,f6.1,f6.2,f7.1,f7.3,1x,a) +3021 format(i6.6,6i3,3i4,f6.1,i4,f6.1,f9.2,f6.1,f6.2,f7.1,f7.3,1x,a) close(21) endif call this%callback(nutc,smax1,nsnr,xdt,fsig,msg, & From b51bda480674828267fe96390784d47a53ef49bb Mon Sep 17 00:00:00 2001 From: Steven Franke Date: Fri, 25 Dec 2020 12:22:25 -0600 Subject: [PATCH 64/75] FT8: Fix jt9 crash when nagain is invoked. --- lib/ft8/get_spectrum_baseline.f90 | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/lib/ft8/get_spectrum_baseline.f90 b/lib/ft8/get_spectrum_baseline.f90 index 9cf4e637c..f815eba14 100644 --- a/lib/ft8/get_spectrum_baseline.f90 +++ b/lib/ft8/get_spectrum_baseline.f90 @@ -35,8 +35,19 @@ subroutine get_spectrum_baseline(dd,nfa,nfb,sbase) savg=savg + s(1:NH1,j) !Average spectrum enddo - if(nfa.lt.100) nfa=100 - if(nfb.gt.4910) nfb=4910 + nwin=nfb-nfa + if(nfa.lt.100) then + nfa=100 + if(nwin.lt.100) then ! nagain + nfb=nfa+nwin + endif + endif + if(nfb.gt.4910) then + nfb=4910 + if(nwin.lt.100) then + nfa=nfb-nwin + endif + endif call baseline(savg,nfa,nfb,sbase) return From 41297e87614ebfcee84bfb20ed0b70f5a4984fba Mon Sep 17 00:00:00 2001 From: Steven Franke Date: Fri, 25 Dec 2020 12:31:02 -0600 Subject: [PATCH 65/75] FT8: Commit the rest of the fix for the nagain crash. --- lib/ft8_decode.f90 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/ft8_decode.f90 b/lib/ft8_decode.f90 index 26b12d6c9..a7a467a31 100644 --- a/lib/ft8_decode.f90 +++ b/lib/ft8_decode.f90 @@ -132,8 +132,8 @@ contains ifa=nfa ifb=nfb if(nagain) then - ifa=nfqso-10 - ifb=nfqso+10 + ifa=nfqso-20 + ifb=nfqso+20 endif ! For now: From a657ce29a7aa4e261281fd18252c282a42027a76 Mon Sep 17 00:00:00 2001 From: Steven Franke Date: Sat, 26 Dec 2020 09:46:19 -0600 Subject: [PATCH 66/75] FT8: Make nagain work. --- lib/ft8_decode.f90 | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/ft8_decode.f90 b/lib/ft8_decode.f90 index a7a467a31..73d0f8c2a 100644 --- a/lib/ft8_decode.f90 +++ b/lib/ft8_decode.f90 @@ -118,7 +118,7 @@ contains dd1=dd go to 900 endif - if(nzhsym.eq.50 .and. ndec_early.ge.1) then + if(nzhsym.eq.50 .and. ndec_early.ge.1 .and. .not.nagain) then n=47*3456 dd(1:n)=dd1(1:n) dd(n+1:)=iwave(n+1:) @@ -131,7 +131,8 @@ contains endif ifa=nfa ifb=nfb - if(nagain) then + if(nzhsym.eq.50 .and. nagain) then + dd=iwave ifa=nfqso-20 ifb=nfqso+20 endif From a38b48d13de10a8014987e5016a06197e0fd0e31 Mon Sep 17 00:00:00 2001 From: Steven Franke Date: Mon, 28 Dec 2020 09:27:48 -0600 Subject: [PATCH 67/75] Minor format change for nutc in fst4_decodes.dat. --- lib/fst4_decode.f90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/fst4_decode.f90 b/lib/fst4_decode.f90 index a1b39f744..0e306abe2 100644 --- a/lib/fst4_decode.f90 +++ b/lib/fst4_decode.f90 @@ -604,7 +604,7 @@ contains write(21,3021) nutc,icand,itry,nsyncoh,iaptype, & ijitter,ntype,Keff,nsync_qual,nharderrors,dmin,nhp,hd, & sync,xsnr,xdt,fsig,w50,trim(msg) -3021 format(i6.6,6i3,3i4,f6.1,i4,f6.1,f9.2,f6.1,f6.2,f7.1,f7.3,1x,a) +3021 format(i6,6i3,3i4,f6.1,i4,f6.1,f9.2,f6.1,f6.2,f7.1,f7.3,1x,a) close(21) endif call this%callback(nutc,smax1,nsnr,xdt,fsig,msg, & From 0fef0cc6e6544744e51f4360e76c0839ca438ae5 Mon Sep 17 00:00:00 2001 From: Steven Franke Date: Mon, 28 Dec 2020 09:39:08 -0600 Subject: [PATCH 68/75] Minor formatting change in fst4_decodes.dat. --- lib/fst4_decode.f90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/fst4_decode.f90 b/lib/fst4_decode.f90 index 0e306abe2..d3ecd371b 100644 --- a/lib/fst4_decode.f90 +++ b/lib/fst4_decode.f90 @@ -604,7 +604,7 @@ contains write(21,3021) nutc,icand,itry,nsyncoh,iaptype, & ijitter,ntype,Keff,nsync_qual,nharderrors,dmin,nhp,hd, & sync,xsnr,xdt,fsig,w50,trim(msg) -3021 format(i6,6i3,3i4,f6.1,i4,f6.1,f9.2,f6.1,f6.2,f7.1,f7.3,1x,a) +3021 format(i6.6,i4,5i3,3i4,f6.1,i4,f6.1,f9.2,f6.1,f6.2,f7.1,f7.3,1x,a) close(21) endif call this%callback(nutc,smax1,nsnr,xdt,fsig,msg, & From 41f587c240216afccd9ee5c4aa483678ee70fff5 Mon Sep 17 00:00:00 2001 From: Steven Franke Date: Sat, 2 Jan 2021 10:09:44 -0600 Subject: [PATCH 69/75] Fix a conflict between noise baseline percentile level and noise blanker percentage. Both were using the npct variable. Add an option for an FST4 pass when in FST4W mode. --- lib/fst4_decode.f90 | 681 +++++++++++++++++++++++--------------------- 1 file changed, 354 insertions(+), 327 deletions(-) diff --git a/lib/fst4_decode.f90 b/lib/fst4_decode.f90 index d3ecd371b..9a1aa0f16 100644 --- a/lib/fst4_decode.f90 +++ b/lib/fst4_decode.f90 @@ -43,6 +43,7 @@ contains procedure(fst4_decode_callback) :: callback character*37 decodes(100) character*37 msg,msgsent + character*8 s_nfa_nfb character*20 wcalls(MAXWCALLS), wpart character*77 c77 character*12 mycall,hiscall @@ -58,7 +59,6 @@ contains logical lagain,lapcqonly integer itone(NN) integer hmod - integer ipct(0:7) integer*1 apmask(240),cw(240),hdec(240) integer*1 message101(101),message74(74),message77(77) integer*1 rvec(77) @@ -74,7 +74,6 @@ contains integer*2 iwave(30*60*12000) - data ipct/0,8,14,4,12,2,10,6/ data mcq/0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0/ data mrrr/0,1,1,1,1,1,1,0,1,0,0,1,0,0,1,0,0,0,1/ data m73/0,1,1,1,1,1,1,0,1,0,0,1,0,1,0,0,0,0,1/ @@ -247,6 +246,7 @@ contains do_k50_decode=.false. endif +! Noise blanker setup ndropmax=1 single_decode=iand(nexp_decode,32).ne.0 npct=0 @@ -262,278 +262,260 @@ contains inb2=1 !Try NB = 0, 1, 2,... 20% else inb1=0 !Fixed NB value, 0 to 25% - ipct(0)=npct endif - if(iwspr.eq.1) then !FST4W - !300 Hz wide noise-fit window - nfa=max(100,nint(nfqso+1.5*baud-150)) - nfb=min(4800,nint(nfqso+1.5*baud+150)) - fa=max(100,nint(nfqso+1.5*baud-ntol)) ! signal search window - fb=min(4800,nint(nfqso+1.5*baud+ntol)) - else if(single_decode) then - fa=max(100,nint(nfa+1.5*baud)) - fb=min(4800,nint(nfb+1.5*baud)) - ! extend noise fit 100 Hz outside of search window - nfa=max(100,nfa-100) - nfb=min(4800,nfb+100) - else - fa=max(100,nint(nfa+1.5*baud)) - fb=min(4800,nint(nfb+1.5*baud)) - ! extend noise fit 100 Hz outside of search window - nfa=max(100,nfa-100) - nfb=min(4800,nfb+100) +! If environment variable FST4W_ALSO_FST4 exists then, when in FST4W mode, +! do a second pass for FST4 decodes. The value of FST4W_ALSO_FST4 +! is of the form xxxxyyyy where nfa=xxxx and nfb=yyyy are the +! search limits for the FST4 decoding pass, e.g. +! FST4W_ALSO_FST4=08001700 will set FST4 search window to [800Hz,1700Hz] +! + nmode=1 + call get_environment_variable("FST4W_ALSO_FST4",s_nfa_nfb,nlength) + if(iwspr.eq.1 .and. nlength.eq.8) then + read(s_nfa_nfb,"(i4.4,i4.4)") nfa_mode2,nfb_mode2 + nmode=2 endif - ndecodes=0 - decodes=' ' - new_callsign=.false. - do inb=0,inb1,inb2 - if(nb.lt.0) npct=inb - call blanker(iwave,nfft1,ndropmax,npct,c_bigfft) + do imode=1,nmode + if(imode.eq.1) iwspr=1 + if(imode.eq.2) then ! this is FST4 after a FST4W pass + iwspr=0 + nfa=nfa_mode2 + nfb=nfb_mode2 + endif + +! nfa,nfb: define the noise-baseline analysis window +! fa, fb: define the signal search window +! We usually make nfafb so that noise baseline analysis +! window extends outside of the [fa,fb] window where we think the signals are. +! + if(iwspr.eq.1) then !FST4W + nfa=max(100,nfqso-ntol-100) + nfb=min(4800,nfqso+ntol+100) + fa=max(100,nint(nfqso+1.5*baud-ntol)) ! signal search window + fb=min(4800,nint(nfqso+1.5*baud+ntol)) + else if(iwspr.eq.0) then + if(imode.eq.1 .and. single_decode) then + fa=max(100,nint(nfa+1.5*baud)) + fb=min(4800,nint(nfb+1.5*baud)) + ! extend noise fit 100 Hz outside of search window + nfa=max(100,nfa-100) + nfb=min(4800,nfb+100) + else + fa=max(100,nint(nfa+1.5*baud)) + fb=min(4800,nint(nfb+1.5*baud)) + ! extend noise fit 100 Hz outside of search window + nfa=max(100,nfa-100) + nfb=min(4800,nfb+100) + endif + endif + + ndecodes=0 + decodes=' ' + new_callsign=.false. + do inb=0,inb1,inb2 + if(nb.lt.0) npct=inb ! we are looping over blanker settings + call blanker(iwave,nfft1,ndropmax,npct,c_bigfft) ! The big fft is done once and is used for calculating the smoothed spectrum ! and also for downconverting/downsampling each candidate. - call four2a(c_bigfft,nfft1,1,-1,0) !r2c - nhicoh=1 - nsyncoh=8 - minsync=1.20 - if(ntrperiod.eq.15) minsync=1.15 + call four2a(c_bigfft,nfft1,1,-1,0) !r2c + nhicoh=1 + nsyncoh=8 + minsync=1.20 + if(ntrperiod.eq.15) minsync=1.15 ! Get first approximation of candidate frequencies - call get_candidates_fst4(c_bigfft,nfft1,nsps,hmod,fs,fa,fb,nfa,nfb, & - minsync,ncand,candidates0) - isbest=0 - fc2=0. - do icand=1,ncand - fc0=candidates0(icand,1) - if(iwspr.eq.0 .and. nb.lt.0 .and. npct.ne.0 .and. & - abs(fc0-(nfqso+1.5*baud)).gt.ntol) cycle - detmet=candidates0(icand,2) + call get_candidates_fst4(c_bigfft,nfft1,nsps,hmod,fs,fa,fb,nfa,nfb, & + minsync,ncand,candidates0) + isbest=0 + fc2=0. + do icand=1,ncand + fc0=candidates0(icand,1) + if(iwspr.eq.0 .and. nb.lt.0 .and. npct.ne.0 .and. & + abs(fc0-(nfqso+1.5*baud)).gt.ntol) cycle ! blanker loop only near nfqso + detmet=candidates0(icand,2) ! Downconvert and downsample a slice of the spectrum centered on the ! rough estimate of the candidates frequency. ! Output array c2 is complex baseband sampled at 12000/ndown Sa/sec. ! The size of the downsampled c2 array is nfft2=nfft1/ndown + call timer('dwnsmpl ',0) + call fst4_downsample(c_bigfft,nfft1,ndown,fc0,sigbw,c2) + call timer('dwnsmpl ',1) - call timer('dwnsmpl ',0) - call fst4_downsample(c_bigfft,nfft1,ndown,fc0,sigbw,c2) - call timer('dwnsmpl ',1) + call timer('sync240 ',0) + call fst4_sync_search(c2,nfft2,hmod,fs2,nss,ntrperiod,nsyncoh,emedelay,sbest,fcbest,isbest) + call timer('sync240 ',1) - call timer('sync240 ',0) - call fst4_sync_search(c2,nfft2,hmod,fs2,nss,ntrperiod,nsyncoh,emedelay,sbest,fcbest,isbest) - call timer('sync240 ',1) - - fc_synced = fc0 + fcbest - dt_synced = (isbest-fs2)*dt2 !nominal dt is 1 second so frame starts at sample fs2 - candidates0(icand,3)=fc_synced - candidates0(icand,4)=isbest - enddo + fc_synced = fc0 + fcbest + dt_synced = (isbest-fs2)*dt2 !nominal dt is 1 second so frame starts at sample fs2 + candidates0(icand,3)=fc_synced + candidates0(icand,4)=isbest + enddo ! remove duplicate candidates - do icand=1,ncand - fc=candidates0(icand,3) - isbest=nint(candidates0(icand,4)) - do ic2=icand+1,ncand - fc2=candidates0(ic2,3) - isbest2=nint(candidates0(ic2,4)) - if(fc2.gt.0.0) then - if(abs(fc2-fc).lt.0.10*baud) then ! same frequency - if(abs(isbest2-isbest).le.2) then - candidates0(ic2,3)=-1 - endif - endif - endif - enddo - enddo - ic=0 - do icand=1,ncand - if(candidates0(icand,3).gt.0) then - ic=ic+1 - candidates0(ic,:)=candidates0(icand,:) - endif - enddo - ncand=ic - -! If FST4 and Single Decode is not checked, then find candidates within -! 20 Hz of nfqso and put them at the top of the list - if(iwspr.eq.0 .and. .not.single_decode) then - nclose=count(abs(candidates0(:,3)-(nfqso+1.5*baud)).le.20) - k=0 - do i=1,ncand - if(abs(candidates0(i,3)-(nfqso+1.5*baud)).le.20) then - k=k+1 - candidates(k,:)=candidates0(i,:) - endif - enddo - do i=1,ncand - if(abs(candidates0(i,3)-(nfqso+1.5*baud)).gt.20) then - k=k+1 - candidates(k,:)=candidates0(i,:) - endif - enddo - else - candidates=candidates0 - endif - - xsnr=0. - do icand=1,ncand - sync=candidates(icand,2) - fc_synced=candidates(icand,3) - isbest=nint(candidates(icand,4)) - xdt=(isbest-nspsec)/fs2 - if(ntrperiod.eq.15) xdt=(isbest-real(nspsec)/2.0)/fs2 - call timer('dwnsmpl ',0) - call fst4_downsample(c_bigfft,nfft1,ndown,fc_synced,sigbw,c2) - call timer('dwnsmpl ',1) - - do ijitter=0,jittermax - if(ijitter.eq.0) ioffset=0 - if(ijitter.eq.1) ioffset=1 - if(ijitter.eq.2) ioffset=-1 - is0=isbest+ioffset - iend=is0+160*nss-1 - if( is0.lt.0 .or. iend.gt.(nfft2-1) ) cycle - cframe=c2(is0:iend) - bitmetrics=0 - call timer('bitmetrc',0) - call get_fst4_bitmetrics(cframe,nss,nblock,nhicoh,bitmetrics, & - s4,nsync_qual,badsync) - call timer('bitmetrc',1) - if(badsync) cycle - - do il=1,4 - llrs( 1: 60,il)=bitmetrics( 17: 76, il) - llrs( 61:120,il)=bitmetrics( 93:152, il) - llrs(121:180,il)=bitmetrics(169:228, il) - llrs(181:240,il)=bitmetrics(245:304, il) - enddo - - apmag=maxval(abs(llrs(:,4)))*1.1 - ntmax=nblock+nappasses(nQSOProgress) - if(lapcqonly) ntmax=nblock+1 - if(ndepth.eq.1) ntmax=nblock ! no ap for ndepth=1 - apmask=0 - - if(iwspr.eq.1) then ! 50-bit msgs, no ap decoding - nblock=4 - ntmax=nblock - endif - - do itry=1,ntmax - if(itry.eq.1) llr=llrs(:,1) - if(itry.eq.2.and.itry.le.nblock) llr=llrs(:,2) - if(itry.eq.3.and.itry.le.nblock) llr=llrs(:,3) - if(itry.eq.4.and.itry.le.nblock) llr=llrs(:,4) - if(itry.le.nblock) then - apmask=0 - iaptype=0 - endif - - if(itry.gt.nblock .and. iwspr.eq.0) then ! do ap passes - llr=llrs(:,nblock) ! Use largest blocksize as the basis for AP passes - iaptype=naptypes(nQSOProgress,itry-nblock) - if(lapcqonly) iaptype=1 - if(iaptype.ge.2 .and. apbits(1).gt.1) cycle ! No, or nonstandard, mycall - if(iaptype.ge.3 .and. apbits(30).gt.1) cycle ! No, or nonstandard, dxcall - if(iaptype.eq.1) then ! CQ - apmask=0 - apmask(1:29)=1 - llr(1:29)=apmag*mcq(1:29) - endif - - if(iaptype.eq.2) then ! MyCall ??? ??? - apmask=0 - apmask(1:29)=1 - llr(1:29)=apmag*apbits(1:29) - endif - - if(iaptype.eq.3) then ! MyCall DxCall ??? - apmask=0 - apmask(1:58)=1 - llr(1:58)=apmag*apbits(1:58) - endif - - if(iaptype.eq.4 .or. iaptype.eq.5 .or. iaptype .eq.6) then - apmask=0 - apmask(1:77)=1 - llr(1:58)=apmag*apbits(1:58) - if(iaptype.eq.4) llr(59:77)=apmag*mrrr(1:19) - if(iaptype.eq.5) llr(59:77)=apmag*m73(1:19) - if(iaptype.eq.6) llr(59:77)=apmag*mrr73(1:19) - endif - endif - - dmin=0.0 - nharderrors=-1 - unpk77_success=.false. - if(iwspr.eq.0) then - maxosd=2 - Keff=91 - norder=3 - call timer('d240_101',0) - call decode240_101(llr,Keff,maxosd,norder,apmask,message101, & - cw,ntype,nharderrors,dmin) - call timer('d240_101',1) - if(count(cw.eq.1).eq.0) then - nharderrors=-nharderrors - cycle - endif - write(c77,'(77i1)') mod(message101(1:77)+rvec,2) - call unpack77(c77,1,msg,unpk77_success) - elseif(iwspr.eq.1) then -! Try decoding with Keff=66 - maxosd=2 - call timer('d240_74 ',0) - Keff=66 - norder=3 - call decode240_74(llr,Keff,maxosd,norder,apmask,message74,cw, & - ntype,nharderrors,dmin) - call timer('d240_74 ',1) - if(nharderrors.lt.0) goto 3465 - if(count(cw.eq.1).eq.0) then - nharderrors=-nharderrors - cycle - endif - write(c77,'(50i1)') message74(1:50) - c77(51:77)='000000000000000000000110000' - call unpack77(c77,1,msg,unpk77_success) - if(unpk77_success .and. do_k50_decode) then -! If decode was obtained with Keff=66, save call/grid in fst4w_calls.txt if not there already. - i1=index(msg,' ') - i2=i1+index(msg(i1+1:),' ') - wpart=trim(msg(1:i2)) -! Only save callsigns/grids from type 1 messages - if(index(wpart,'/').eq.0 .and. index(wpart,'<').eq.0) then - ifound=0 - do i=1,nwcalls - if(index(wcalls(i),wpart).ne.0) ifound=1 - enddo - - if(ifound.eq.0) then ! This is a new callsign - new_callsign=.true. - if(nwcalls.lt.MAXWCALLS) then - nwcalls=nwcalls+1 - wcalls(nwcalls)=wpart - else - wcalls(1:nwcalls-1)=wcalls(2:nwcalls) - wcalls(nwcalls)=wpart - endif - endif + do icand=1,ncand + fc=candidates0(icand,3) + isbest=nint(candidates0(icand,4)) + do ic2=icand+1,ncand + fc2=candidates0(ic2,3) + isbest2=nint(candidates0(ic2,4)) + if(fc2.gt.0.0) then + if(abs(fc2-fc).lt.0.10*baud) then ! same frequency + if(abs(isbest2-isbest).le.2) then + candidates0(ic2,3)=-1 endif endif -3465 continue + endif + enddo + enddo + ic=0 + do icand=1,ncand + if(candidates0(icand,3).gt.0) then + ic=ic+1 + candidates0(ic,:)=candidates0(icand,:) + endif + enddo + ncand=ic -! If no decode then try Keff=50 - iaptype=0 - if( .not. unpk77_success .and. do_k50_decode ) then - maxosd=1 +! If FST4 mode and Single Decode is not checked, then find candidates +! within 20 Hz of nfqso and put them at the top of the list + if(iwspr.eq.0 .and. .not.single_decode) then + nclose=count(abs(candidates0(:,3)-(nfqso+1.5*baud)).le.20) + k=0 + do i=1,ncand + if(abs(candidates0(i,3)-(nfqso+1.5*baud)).le.20) then + k=k+1 + candidates(k,:)=candidates0(i,:) + endif + enddo + do i=1,ncand + if(abs(candidates0(i,3)-(nfqso+1.5*baud)).gt.20) then + k=k+1 + candidates(k,:)=candidates0(i,:) + endif + enddo + else + candidates=candidates0 + endif + + xsnr=0. + do icand=1,ncand + sync=candidates(icand,2) + fc_synced=candidates(icand,3) + isbest=nint(candidates(icand,4)) + xdt=(isbest-nspsec)/fs2 + if(ntrperiod.eq.15) xdt=(isbest-real(nspsec)/2.0)/fs2 + call timer('dwnsmpl ',0) + call fst4_downsample(c_bigfft,nfft1,ndown,fc_synced,sigbw,c2) + call timer('dwnsmpl ',1) + + do ijitter=0,jittermax + if(ijitter.eq.0) ioffset=0 + if(ijitter.eq.1) ioffset=1 + if(ijitter.eq.2) ioffset=-1 + is0=isbest+ioffset + iend=is0+160*nss-1 + if( is0.lt.0 .or. iend.gt.(nfft2-1) ) cycle + cframe=c2(is0:iend) + bitmetrics=0 + call timer('bitmetrc',0) + call get_fst4_bitmetrics(cframe,nss,nblock,nhicoh,bitmetrics, & + s4,nsync_qual,badsync) + call timer('bitmetrc',1) + if(badsync) cycle + + do il=1,4 + llrs( 1: 60,il)=bitmetrics( 17: 76, il) + llrs( 61:120,il)=bitmetrics( 93:152, il) + llrs(121:180,il)=bitmetrics(169:228, il) + llrs(181:240,il)=bitmetrics(245:304, il) + enddo + + apmag=maxval(abs(llrs(:,4)))*1.1 + ntmax=nblock+nappasses(nQSOProgress) + if(lapcqonly) ntmax=nblock+1 + if(ndepth.eq.1) ntmax=nblock ! no ap for ndepth=1 + apmask=0 + + if(iwspr.eq.1) then ! 50-bit msgs, no ap decoding + nblock=4 + ntmax=nblock + endif + + do itry=1,ntmax + if(itry.eq.1) llr=llrs(:,1) + if(itry.eq.2.and.itry.le.nblock) llr=llrs(:,2) + if(itry.eq.3.and.itry.le.nblock) llr=llrs(:,3) + if(itry.eq.4.and.itry.le.nblock) llr=llrs(:,4) + if(itry.le.nblock) then + apmask=0 + iaptype=0 + endif + + if(itry.gt.nblock .and. iwspr.eq.0) then ! do ap passes + llr=llrs(:,nblock) ! Use largest blocksize as the basis for AP passes + iaptype=naptypes(nQSOProgress,itry-nblock) + if(lapcqonly) iaptype=1 + if(iaptype.ge.2 .and. apbits(1).gt.1) cycle ! No, or nonstandard, mycall + if(iaptype.ge.3 .and. apbits(30).gt.1) cycle ! No, or nonstandard, dxcall + if(iaptype.eq.1) then ! CQ + apmask=0 + apmask(1:29)=1 + llr(1:29)=apmag*mcq(1:29) + endif + + if(iaptype.eq.2) then ! MyCall ??? ??? + apmask=0 + apmask(1:29)=1 + llr(1:29)=apmag*apbits(1:29) + endif + + if(iaptype.eq.3) then ! MyCall DxCall ??? + apmask=0 + apmask(1:58)=1 + llr(1:58)=apmag*apbits(1:58) + endif + + if(iaptype.eq.4 .or. iaptype.eq.5 .or. iaptype .eq.6) then + apmask=0 + apmask(1:77)=1 + llr(1:58)=apmag*apbits(1:58) + if(iaptype.eq.4) llr(59:77)=apmag*mrrr(1:19) + if(iaptype.eq.5) llr(59:77)=apmag*m73(1:19) + if(iaptype.eq.6) llr(59:77)=apmag*mrr73(1:19) + endif + endif + + dmin=0.0 + nharderrors=-1 + unpk77_success=.false. + if(iwspr.eq.0) then + maxosd=2 + Keff=91 + norder=3 + call timer('d240_101',0) + call decode240_101(llr,Keff,maxosd,norder,apmask,message101, & + cw,ntype,nharderrors,dmin) + call timer('d240_101',1) + if(count(cw.eq.1).eq.0) then + nharderrors=-nharderrors + cycle + endif + write(c77,'(77i1)') mod(message101(1:77)+rvec,2) + call unpack77(c77,1,msg,unpk77_success) + elseif(iwspr.eq.1) then +! Try decoding with Keff=66 + maxosd=2 call timer('d240_74 ',0) - Keff=50 - norder=4 + Keff=66 + norder=3 call decode240_74(llr,Keff,maxosd,norder,apmask,message74,cw, & ntype,nharderrors,dmin) call timer('d240_74 ',1) + if(nharderrors.lt.0) goto 3465 if(count(cw.eq.1).eq.0) then nharderrors=-nharderrors cycle @@ -541,89 +523,134 @@ contains write(c77,'(50i1)') message74(1:50) c77(51:77)='000000000000000000000110000' call unpack77(c77,1,msg,unpk77_success) -! No CRC in this mode, so only accept the decode if call/grid have been seen before - if(unpk77_success) then - unpk77_success=.false. - do i=1,nwcalls - if(index(msg,trim(wcalls(i))).gt.0) then - unpk77_success=.true. + if(unpk77_success .and. do_k50_decode) then +! If decode was obtained with Keff=66, save call/grid in fst4w_calls.txt if not there already. + i1=index(msg,' ') + i2=i1+index(msg(i1+1:),' ') + wpart=trim(msg(1:i2)) +! Only save callsigns/grids from type 1 messages + if(index(wpart,'/').eq.0 .and. index(wpart,'<').eq.0) then + ifound=0 + do i=1,nwcalls + if(index(wcalls(i),wpart).ne.0) ifound=1 + enddo + + if(ifound.eq.0) then ! This is a new callsign + new_callsign=.true. + if(nwcalls.lt.MAXWCALLS) then + nwcalls=nwcalls+1 + wcalls(nwcalls)=wpart + else + wcalls(1:nwcalls-1)=wcalls(2:nwcalls) + wcalls(nwcalls)=wpart + endif endif - enddo + endif endif +3465 continue + +! If no decode then try Keff=50 + iaptype=0 + if( .not. unpk77_success .and. do_k50_decode ) then + maxosd=1 + call timer('d240_74 ',0) + Keff=50 + norder=4 + call decode240_74(llr,Keff,maxosd,norder,apmask,message74,cw, & + ntype,nharderrors,dmin) + call timer('d240_74 ',1) + if(count(cw.eq.1).eq.0) then + nharderrors=-nharderrors + cycle + endif + write(c77,'(50i1)') message74(1:50) + c77(51:77)='000000000000000000000110000' + call unpack77(c77,1,msg,unpk77_success) +! No CRC in this mode, so only accept the decode if call/grid have been seen before + if(unpk77_success) then + unpk77_success=.false. + do i=1,nwcalls + if(index(msg,trim(wcalls(i))).gt.0) then + unpk77_success=.true. + endif + enddo + endif + endif + endif - endif + if(nharderrors .ge.0 .and. unpk77_success) then + idupe=0 + do i=1,ndecodes + if(decodes(i).eq.msg) idupe=1 + enddo + if(idupe.eq.1) goto 800 + ndecodes=ndecodes+1 + decodes(ndecodes)=msg - if(nharderrors .ge.0 .and. unpk77_success) then - idupe=0 - do i=1,ndecodes - if(decodes(i).eq.msg) idupe=1 - enddo - if(idupe.eq.1) goto 800 - ndecodes=ndecodes+1 - decodes(ndecodes)=msg + if(iwspr.eq.0) then + call get_fst4_tones_from_bits(message101,itone,0) + else + call get_fst4_tones_from_bits(message74,itone,1) + endif + inquire(file='plotspec',exist=plotspec_exists) + fmid=-999.0 + call timer('dopsprd ',0) + if(plotspec_exists) then + call dopspread(itone,iwave,nsps,nmax,ndown,hmod, & + isbest,fc_synced,fmid,w50) + endif + call timer('dopsprd ',1) + xsig=0 + do i=1,NN + xsig=xsig+s4(itone(i),i) + enddo + base=candidates(icand,5) + arg=600.0*(xsig/base)-1.0 + if(arg.gt.0.0) then + xsnr=10*log10(arg)-35.5-12.5*log10(nsps/8200.0) + if(ntrperiod.eq. 15) xsnr=xsnr+2 + if(ntrperiod.eq. 30) xsnr=xsnr+1 + if(ntrperiod.eq. 900) xsnr=xsnr+1 + if(ntrperiod.eq.1800) xsnr=xsnr+2 + else + xsnr=-99.9 + endif + nsnr=nint(xsnr) + qual=0.0 + fsig=fc_synced - 1.5*baud + inquire(file=trim(data_dir)//'/decdata',exist=decdata_exists) + if(decdata_exists) then + hdec=0 + where(llrs(:,1).ge.0.0) hdec=1 + nhp=count(hdec.ne.cw) ! # hard errors wrt N=1 soft symbols + hd=sum(ieor(hdec,cw)*abs(llrs(:,1))) ! weighted distance wrt N=1 symbols + open(21,file=trim(data_dir)//'/fst4_decodes.dat',status='unknown',position='append') + write(21,3021) nutc,icand,itry,nsyncoh,iaptype, & + ijitter,npct,ntype,Keff,nsync_qual,nharderrors,dmin,nhp,hd, & + sync,xsnr,xdt,fsig,w50,trim(msg) +3021 format(i6.6,i4,6i3,3i4,f6.1,i4,f6.1,f9.2,f6.1,f6.2,f7.1,f7.3,1x,a) + close(21) + endif + call this%callback(nutc,smax1,nsnr,xdt,fsig,msg, & + iaptype,qual,ntrperiod,lwspr,fmid,w50) + if(iwspr.eq.0 .and. nb.lt.0 .and. imode.eq.1) go to 900 + goto 800 + endif + enddo ! metrics + enddo ! istart jitter +800 enddo !candidate list + enddo ! noise blanker loop - if(iwspr.eq.0) then - call get_fst4_tones_from_bits(message101,itone,0) - else - call get_fst4_tones_from_bits(message74,itone,1) - endif - inquire(file='plotspec',exist=plotspec_exists) - fmid=-999.0 - call timer('dopsprd ',0) - if(plotspec_exists) then - call dopspread(itone,iwave,nsps,nmax,ndown,hmod, & - isbest,fc_synced,fmid,w50) - endif - call timer('dopsprd ',1) - xsig=0 - do i=1,NN - xsig=xsig+s4(itone(i),i) - enddo - base=candidates(icand,5) - arg=600.0*(xsig/base)-1.0 - if(arg.gt.0.0) then - xsnr=10*log10(arg)-35.5-12.5*log10(nsps/8200.0) - if(ntrperiod.eq. 15) xsnr=xsnr+2 - if(ntrperiod.eq. 30) xsnr=xsnr+1 - if(ntrperiod.eq. 900) xsnr=xsnr+1 - if(ntrperiod.eq.1800) xsnr=xsnr+2 - else - xsnr=-99.9 - endif - nsnr=nint(xsnr) - qual=0.0 - fsig=fc_synced - 1.5*baud - inquire(file=trim(data_dir)//'/decdata',exist=decdata_exists) - if(decdata_exists) then - hdec=0 - where(llrs(:,1).ge.0.0) hdec=1 - nhp=count(hdec.ne.cw) ! # hard errors wrt N=1 soft symbols - hd=sum(ieor(hdec,cw)*abs(llrs(:,1))) ! weighted distance wrt N=1 symbols - open(21,file=trim(data_dir)//'/fst4_decodes.dat',status='unknown',position='append') - write(21,3021) nutc,icand,itry,nsyncoh,iaptype, & - ijitter,ntype,Keff,nsync_qual,nharderrors,dmin,nhp,hd, & - sync,xsnr,xdt,fsig,w50,trim(msg) -3021 format(i6.6,i4,5i3,3i4,f6.1,i4,f6.1,f9.2,f6.1,f6.2,f7.1,f7.3,1x,a) - close(21) - endif - call this%callback(nutc,smax1,nsnr,xdt,fsig,msg, & - iaptype,qual,ntrperiod,lwspr,fmid,w50) - if(iwspr.eq.0 .and. nb.lt.0) go to 900 - goto 800 - endif - enddo ! metrics - enddo ! istart jitter -800 enddo !candidate list - enddo ! noise blanker loop + if(new_callsign .and. do_k50_decode) then ! re-write the fst4w_calls.txt file + open(42,file=trim(data_dir)//'/fst4w_calls.txt',status='unknown') + do i=1,nwcalls + write(42,'(a20)') trim(wcalls(i)) + enddo + close(42) + endif - if(new_callsign .and. do_k50_decode) then ! re-write the fst4w_calls.txt file - open(42,file=trim(data_dir)//'/fst4w_calls.txt',status='unknown') - do i=1,nwcalls - write(42,'(a20)') trim(wcalls(i)) - enddo - close(42) - endif + enddo ! mode loop 900 return end subroutine decode @@ -818,8 +845,8 @@ contains do i=ina,inb !Compute CCF of s() and 4 tones s2(i)=s(i-hmod*3) + s(i-hmod) +s(i+hmod) +s(i+hmod*3) enddo - npct=30 - call fst4_baseline(s2,nnw,ina+hmod*3,inb-hmod*3,npct,sbase) + npctile=30 + call fst4_baseline(s2,nnw,ina+hmod*3,inb-hmod*3,npctile,sbase) if(any(sbase(ina:inb).le.0.0)) return s2(ina:inb)=s2(ina:inb)/sbase(ina:inb) !Normalize wrt noise level From 46222c61eddb6b98e35c11d2252e59527359262f Mon Sep 17 00:00:00 2001 From: Steven Franke Date: Sat, 2 Jan 2021 10:25:29 -0600 Subject: [PATCH 70/75] Add rudimentary sanity checks to the values parsed from FST4W_ALSO_FST4. --- lib/fst4_decode.f90 | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/fst4_decode.f90 b/lib/fst4_decode.f90 index 9a1aa0f16..9b066e61f 100644 --- a/lib/fst4_decode.f90 +++ b/lib/fst4_decode.f90 @@ -275,6 +275,7 @@ contains if(iwspr.eq.1 .and. nlength.eq.8) then read(s_nfa_nfb,"(i4.4,i4.4)") nfa_mode2,nfb_mode2 nmode=2 + if(nfa_mode2.lt.100 .or. nfb_mode2.gt.4910 .or. nfb_mode2.le.nfa_mode2) nmode=1 endif do imode=1,nmode From 0013b151200e4f09417bcfa3ef7e27df21412d7a Mon Sep 17 00:00:00 2001 From: Steven Franke Date: Sat, 2 Jan 2021 11:37:16 -0600 Subject: [PATCH 71/75] Remove some debug code. --- lib/fst4_decode.f90 | 638 +++++++++++++++++++++----------------------- 1 file changed, 307 insertions(+), 331 deletions(-) diff --git a/lib/fst4_decode.f90 b/lib/fst4_decode.f90 index 9b066e61f..5fb591ffa 100644 --- a/lib/fst4_decode.f90 +++ b/lib/fst4_decode.f90 @@ -43,7 +43,6 @@ contains procedure(fst4_decode_callback) :: callback character*37 decodes(100) character*37 msg,msgsent - character*8 s_nfa_nfb character*20 wcalls(MAXWCALLS), wpart character*77 c77 character*12 mycall,hiscall @@ -264,259 +263,281 @@ contains inb1=0 !Fixed NB value, 0 to 25% endif -! If environment variable FST4W_ALSO_FST4 exists then, when in FST4W mode, -! do a second pass for FST4 decodes. The value of FST4W_ALSO_FST4 -! is of the form xxxxyyyy where nfa=xxxx and nfb=yyyy are the -! search limits for the FST4 decoding pass, e.g. -! FST4W_ALSO_FST4=08001700 will set FST4 search window to [800Hz,1700Hz] -! - nmode=1 - call get_environment_variable("FST4W_ALSO_FST4",s_nfa_nfb,nlength) - if(iwspr.eq.1 .and. nlength.eq.8) then - read(s_nfa_nfb,"(i4.4,i4.4)") nfa_mode2,nfb_mode2 - nmode=2 - if(nfa_mode2.lt.100 .or. nfb_mode2.gt.4910 .or. nfb_mode2.le.nfa_mode2) nmode=1 - endif - - do imode=1,nmode - if(imode.eq.1) iwspr=1 - if(imode.eq.2) then ! this is FST4 after a FST4W pass - iwspr=0 - nfa=nfa_mode2 - nfb=nfb_mode2 - endif ! nfa,nfb: define the noise-baseline analysis window ! fa, fb: define the signal search window ! We usually make nfafb so that noise baseline analysis ! window extends outside of the [fa,fb] window where we think the signals are. ! - if(iwspr.eq.1) then !FST4W - nfa=max(100,nfqso-ntol-100) - nfb=min(4800,nfqso+ntol+100) - fa=max(100,nint(nfqso+1.5*baud-ntol)) ! signal search window - fb=min(4800,nint(nfqso+1.5*baud+ntol)) - else if(iwspr.eq.0) then - if(imode.eq.1 .and. single_decode) then - fa=max(100,nint(nfa+1.5*baud)) - fb=min(4800,nint(nfb+1.5*baud)) - ! extend noise fit 100 Hz outside of search window - nfa=max(100,nfa-100) - nfb=min(4800,nfb+100) - else - fa=max(100,nint(nfa+1.5*baud)) - fb=min(4800,nint(nfb+1.5*baud)) - ! extend noise fit 100 Hz outside of search window - nfa=max(100,nfa-100) - nfb=min(4800,nfb+100) - endif + if(iwspr.eq.1) then !FST4W + nfa=max(100,nfqso-ntol-100) + nfb=min(4800,nfqso+ntol+100) + fa=max(100,nint(nfqso+1.5*baud-ntol)) ! signal search window + fb=min(4800,nint(nfqso+1.5*baud+ntol)) + else if(iwspr.eq.0) then + if(single_decode) then + fa=max(100,nint(nfa+1.5*baud)) + fb=min(4800,nint(nfb+1.5*baud)) + ! extend noise fit 100 Hz outside of search window + nfa=max(100,nfa-100) + nfb=min(4800,nfb+100) + else + fa=max(100,nint(nfa+1.5*baud)) + fb=min(4800,nint(nfb+1.5*baud)) + ! extend noise fit 100 Hz outside of search window + nfa=max(100,nfa-100) + nfb=min(4800,nfb+100) endif + endif - ndecodes=0 - decodes=' ' - new_callsign=.false. - do inb=0,inb1,inb2 - if(nb.lt.0) npct=inb ! we are looping over blanker settings - call blanker(iwave,nfft1,ndropmax,npct,c_bigfft) + ndecodes=0 + decodes=' ' + new_callsign=.false. + do inb=0,inb1,inb2 + if(nb.lt.0) npct=inb ! we are looping over blanker settings + call blanker(iwave,nfft1,ndropmax,npct,c_bigfft) ! The big fft is done once and is used for calculating the smoothed spectrum ! and also for downconverting/downsampling each candidate. - call four2a(c_bigfft,nfft1,1,-1,0) !r2c - nhicoh=1 - nsyncoh=8 - minsync=1.20 - if(ntrperiod.eq.15) minsync=1.15 + call four2a(c_bigfft,nfft1,1,-1,0) !r2c + nhicoh=1 + nsyncoh=8 + minsync=1.20 + if(ntrperiod.eq.15) minsync=1.15 ! Get first approximation of candidate frequencies - call get_candidates_fst4(c_bigfft,nfft1,nsps,hmod,fs,fa,fb,nfa,nfb, & - minsync,ncand,candidates0) - isbest=0 - fc2=0. - do icand=1,ncand - fc0=candidates0(icand,1) - if(iwspr.eq.0 .and. nb.lt.0 .and. npct.ne.0 .and. & - abs(fc0-(nfqso+1.5*baud)).gt.ntol) cycle ! blanker loop only near nfqso - detmet=candidates0(icand,2) + call get_candidates_fst4(c_bigfft,nfft1,nsps,hmod,fs,fa,fb,nfa,nfb, & + minsync,ncand,candidates0) + isbest=0 + fc2=0. + do icand=1,ncand + fc0=candidates0(icand,1) + if(iwspr.eq.0 .and. nb.lt.0 .and. npct.ne.0 .and. & + abs(fc0-(nfqso+1.5*baud)).gt.ntol) cycle ! blanker loop only near nfqso + detmet=candidates0(icand,2) ! Downconvert and downsample a slice of the spectrum centered on the ! rough estimate of the candidates frequency. ! Output array c2 is complex baseband sampled at 12000/ndown Sa/sec. ! The size of the downsampled c2 array is nfft2=nfft1/ndown - call timer('dwnsmpl ',0) - call fst4_downsample(c_bigfft,nfft1,ndown,fc0,sigbw,c2) - call timer('dwnsmpl ',1) + call timer('dwnsmpl ',0) + call fst4_downsample(c_bigfft,nfft1,ndown,fc0,sigbw,c2) + call timer('dwnsmpl ',1) - call timer('sync240 ',0) - call fst4_sync_search(c2,nfft2,hmod,fs2,nss,ntrperiod,nsyncoh,emedelay,sbest,fcbest,isbest) - call timer('sync240 ',1) + call timer('sync240 ',0) + call fst4_sync_search(c2,nfft2,hmod,fs2,nss,ntrperiod,nsyncoh,emedelay,sbest,fcbest,isbest) + call timer('sync240 ',1) - fc_synced = fc0 + fcbest - dt_synced = (isbest-fs2)*dt2 !nominal dt is 1 second so frame starts at sample fs2 - candidates0(icand,3)=fc_synced - candidates0(icand,4)=isbest - enddo + fc_synced = fc0 + fcbest + dt_synced = (isbest-fs2)*dt2 !nominal dt is 1 second so frame starts at sample fs2 + candidates0(icand,3)=fc_synced + candidates0(icand,4)=isbest + enddo ! remove duplicate candidates - do icand=1,ncand - fc=candidates0(icand,3) - isbest=nint(candidates0(icand,4)) - do ic2=icand+1,ncand - fc2=candidates0(ic2,3) - isbest2=nint(candidates0(ic2,4)) - if(fc2.gt.0.0) then - if(abs(fc2-fc).lt.0.10*baud) then ! same frequency - if(abs(isbest2-isbest).le.2) then - candidates0(ic2,3)=-1 - endif + do icand=1,ncand + fc=candidates0(icand,3) + isbest=nint(candidates0(icand,4)) + do ic2=icand+1,ncand + fc2=candidates0(ic2,3) + isbest2=nint(candidates0(ic2,4)) + if(fc2.gt.0.0) then + if(abs(fc2-fc).lt.0.10*baud) then ! same frequency + if(abs(isbest2-isbest).le.2) then + candidates0(ic2,3)=-1 endif endif - enddo - enddo - ic=0 - do icand=1,ncand - if(candidates0(icand,3).gt.0) then - ic=ic+1 - candidates0(ic,:)=candidates0(icand,:) endif enddo - ncand=ic - -! If FST4 mode and Single Decode is not checked, then find candidates -! within 20 Hz of nfqso and put them at the top of the list - if(iwspr.eq.0 .and. .not.single_decode) then - nclose=count(abs(candidates0(:,3)-(nfqso+1.5*baud)).le.20) - k=0 - do i=1,ncand - if(abs(candidates0(i,3)-(nfqso+1.5*baud)).le.20) then - k=k+1 - candidates(k,:)=candidates0(i,:) - endif - enddo - do i=1,ncand - if(abs(candidates0(i,3)-(nfqso+1.5*baud)).gt.20) then - k=k+1 - candidates(k,:)=candidates0(i,:) - endif - enddo - else - candidates=candidates0 + enddo + ic=0 + do icand=1,ncand + if(candidates0(icand,3).gt.0) then + ic=ic+1 + candidates0(ic,:)=candidates0(icand,:) endif + enddo + ncand=ic - xsnr=0. - do icand=1,ncand - sync=candidates(icand,2) - fc_synced=candidates(icand,3) - isbest=nint(candidates(icand,4)) - xdt=(isbest-nspsec)/fs2 - if(ntrperiod.eq.15) xdt=(isbest-real(nspsec)/2.0)/fs2 - call timer('dwnsmpl ',0) - call fst4_downsample(c_bigfft,nfft1,ndown,fc_synced,sigbw,c2) - call timer('dwnsmpl ',1) +! If FST4 mode and Single Decode is not checked, then find candidates +! within 20 Hz of nfqso and put them at the top of the list + if(iwspr.eq.0 .and. .not.single_decode) then + nclose=count(abs(candidates0(:,3)-(nfqso+1.5*baud)).le.20) + k=0 + do i=1,ncand + if(abs(candidates0(i,3)-(nfqso+1.5*baud)).le.20) then + k=k+1 + candidates(k,:)=candidates0(i,:) + endif + enddo + do i=1,ncand + if(abs(candidates0(i,3)-(nfqso+1.5*baud)).gt.20) then + k=k+1 + candidates(k,:)=candidates0(i,:) + endif + enddo + else + candidates=candidates0 + endif - do ijitter=0,jittermax - if(ijitter.eq.0) ioffset=0 - if(ijitter.eq.1) ioffset=1 - if(ijitter.eq.2) ioffset=-1 - is0=isbest+ioffset - iend=is0+160*nss-1 - if( is0.lt.0 .or. iend.gt.(nfft2-1) ) cycle - cframe=c2(is0:iend) - bitmetrics=0 - call timer('bitmetrc',0) - call get_fst4_bitmetrics(cframe,nss,nblock,nhicoh,bitmetrics, & - s4,nsync_qual,badsync) - call timer('bitmetrc',1) - if(badsync) cycle + xsnr=0. + do icand=1,ncand + sync=candidates(icand,2) + fc_synced=candidates(icand,3) + isbest=nint(candidates(icand,4)) + xdt=(isbest-nspsec)/fs2 + if(ntrperiod.eq.15) xdt=(isbest-real(nspsec)/2.0)/fs2 + call timer('dwnsmpl ',0) + call fst4_downsample(c_bigfft,nfft1,ndown,fc_synced,sigbw,c2) + call timer('dwnsmpl ',1) - do il=1,4 - llrs( 1: 60,il)=bitmetrics( 17: 76, il) - llrs( 61:120,il)=bitmetrics( 93:152, il) - llrs(121:180,il)=bitmetrics(169:228, il) - llrs(181:240,il)=bitmetrics(245:304, il) - enddo + do ijitter=0,jittermax + if(ijitter.eq.0) ioffset=0 + if(ijitter.eq.1) ioffset=1 + if(ijitter.eq.2) ioffset=-1 + is0=isbest+ioffset + iend=is0+160*nss-1 + if( is0.lt.0 .or. iend.gt.(nfft2-1) ) cycle + cframe=c2(is0:iend) + bitmetrics=0 + call timer('bitmetrc',0) + call get_fst4_bitmetrics(cframe,nss,nblock,nhicoh,bitmetrics, & + s4,nsync_qual,badsync) + call timer('bitmetrc',1) + if(badsync) cycle - apmag=maxval(abs(llrs(:,4)))*1.1 - ntmax=nblock+nappasses(nQSOProgress) - if(lapcqonly) ntmax=nblock+1 - if(ndepth.eq.1) ntmax=nblock ! no ap for ndepth=1 - apmask=0 + do il=1,4 + llrs( 1: 60,il)=bitmetrics( 17: 76, il) + llrs( 61:120,il)=bitmetrics( 93:152, il) + llrs(121:180,il)=bitmetrics(169:228, il) + llrs(181:240,il)=bitmetrics(245:304, il) + enddo - if(iwspr.eq.1) then ! 50-bit msgs, no ap decoding - nblock=4 - ntmax=nblock + apmag=maxval(abs(llrs(:,4)))*1.1 + ntmax=nblock+nappasses(nQSOProgress) + if(lapcqonly) ntmax=nblock+1 + if(ndepth.eq.1) ntmax=nblock ! no ap for ndepth=1 + apmask=0 + + if(iwspr.eq.1) then ! 50-bit msgs, no ap decoding + nblock=4 + ntmax=nblock + endif + + do itry=1,ntmax + if(itry.eq.1) llr=llrs(:,1) + if(itry.eq.2.and.itry.le.nblock) llr=llrs(:,2) + if(itry.eq.3.and.itry.le.nblock) llr=llrs(:,3) + if(itry.eq.4.and.itry.le.nblock) llr=llrs(:,4) + if(itry.le.nblock) then + apmask=0 + iaptype=0 endif - do itry=1,ntmax - if(itry.eq.1) llr=llrs(:,1) - if(itry.eq.2.and.itry.le.nblock) llr=llrs(:,2) - if(itry.eq.3.and.itry.le.nblock) llr=llrs(:,3) - if(itry.eq.4.and.itry.le.nblock) llr=llrs(:,4) - if(itry.le.nblock) then + if(itry.gt.nblock .and. iwspr.eq.0) then ! do ap passes + llr=llrs(:,nblock) ! Use largest blocksize as the basis for AP passes + iaptype=naptypes(nQSOProgress,itry-nblock) + if(lapcqonly) iaptype=1 + if(iaptype.ge.2 .and. apbits(1).gt.1) cycle ! No, or nonstandard, mycall + if(iaptype.ge.3 .and. apbits(30).gt.1) cycle ! No, or nonstandard, dxcall + if(iaptype.eq.1) then ! CQ apmask=0 - iaptype=0 + apmask(1:29)=1 + llr(1:29)=apmag*mcq(1:29) endif - if(itry.gt.nblock .and. iwspr.eq.0) then ! do ap passes - llr=llrs(:,nblock) ! Use largest blocksize as the basis for AP passes - iaptype=naptypes(nQSOProgress,itry-nblock) - if(lapcqonly) iaptype=1 - if(iaptype.ge.2 .and. apbits(1).gt.1) cycle ! No, or nonstandard, mycall - if(iaptype.ge.3 .and. apbits(30).gt.1) cycle ! No, or nonstandard, dxcall - if(iaptype.eq.1) then ! CQ - apmask=0 - apmask(1:29)=1 - llr(1:29)=apmag*mcq(1:29) - endif - - if(iaptype.eq.2) then ! MyCall ??? ??? - apmask=0 - apmask(1:29)=1 - llr(1:29)=apmag*apbits(1:29) - endif - - if(iaptype.eq.3) then ! MyCall DxCall ??? - apmask=0 - apmask(1:58)=1 - llr(1:58)=apmag*apbits(1:58) - endif - - if(iaptype.eq.4 .or. iaptype.eq.5 .or. iaptype .eq.6) then - apmask=0 - apmask(1:77)=1 - llr(1:58)=apmag*apbits(1:58) - if(iaptype.eq.4) llr(59:77)=apmag*mrrr(1:19) - if(iaptype.eq.5) llr(59:77)=apmag*m73(1:19) - if(iaptype.eq.6) llr(59:77)=apmag*mrr73(1:19) - endif + if(iaptype.eq.2) then ! MyCall ??? ??? + apmask=0 + apmask(1:29)=1 + llr(1:29)=apmag*apbits(1:29) endif - dmin=0.0 - nharderrors=-1 - unpk77_success=.false. - if(iwspr.eq.0) then - maxosd=2 - Keff=91 - norder=3 - call timer('d240_101',0) - call decode240_101(llr,Keff,maxosd,norder,apmask,message101, & - cw,ntype,nharderrors,dmin) - call timer('d240_101',1) - if(count(cw.eq.1).eq.0) then - nharderrors=-nharderrors - cycle - endif - write(c77,'(77i1)') mod(message101(1:77)+rvec,2) - call unpack77(c77,1,msg,unpk77_success) - elseif(iwspr.eq.1) then + if(iaptype.eq.3) then ! MyCall DxCall ??? + apmask=0 + apmask(1:58)=1 + llr(1:58)=apmag*apbits(1:58) + endif + + if(iaptype.eq.4 .or. iaptype.eq.5 .or. iaptype .eq.6) then + apmask=0 + apmask(1:77)=1 + llr(1:58)=apmag*apbits(1:58) + if(iaptype.eq.4) llr(59:77)=apmag*mrrr(1:19) + if(iaptype.eq.5) llr(59:77)=apmag*m73(1:19) + if(iaptype.eq.6) llr(59:77)=apmag*mrr73(1:19) + endif + endif + + dmin=0.0 + nharderrors=-1 + unpk77_success=.false. + if(iwspr.eq.0) then + maxosd=2 + Keff=91 + norder=3 + call timer('d240_101',0) + call decode240_101(llr,Keff,maxosd,norder,apmask,message101, & + cw,ntype,nharderrors,dmin) + call timer('d240_101',1) + if(count(cw.eq.1).eq.0) then + nharderrors=-nharderrors + cycle + endif + write(c77,'(77i1)') mod(message101(1:77)+rvec,2) + call unpack77(c77,1,msg,unpk77_success) + elseif(iwspr.eq.1) then ! Try decoding with Keff=66 - maxosd=2 + maxosd=2 + call timer('d240_74 ',0) + Keff=66 + norder=3 + call decode240_74(llr,Keff,maxosd,norder,apmask,message74,cw, & + ntype,nharderrors,dmin) + call timer('d240_74 ',1) + if(nharderrors.lt.0) goto 3465 + if(count(cw.eq.1).eq.0) then + nharderrors=-nharderrors + cycle + endif + write(c77,'(50i1)') message74(1:50) + c77(51:77)='000000000000000000000110000' + call unpack77(c77,1,msg,unpk77_success) + if(unpk77_success .and. do_k50_decode) then +! If decode was obtained with Keff=66, save call/grid in fst4w_calls.txt if not there already. + i1=index(msg,' ') + i2=i1+index(msg(i1+1:),' ') + wpart=trim(msg(1:i2)) +! Only save callsigns/grids from type 1 messages + if(index(wpart,'/').eq.0 .and. index(wpart,'<').eq.0) then + ifound=0 + do i=1,nwcalls + if(index(wcalls(i),wpart).ne.0) ifound=1 + enddo + + if(ifound.eq.0) then ! This is a new callsign + new_callsign=.true. + if(nwcalls.lt.MAXWCALLS) then + nwcalls=nwcalls+1 + wcalls(nwcalls)=wpart + else + wcalls(1:nwcalls-1)=wcalls(2:nwcalls) + wcalls(nwcalls)=wpart + endif + endif + endif + endif +3465 continue + +! If no decode then try Keff=50 + iaptype=0 + if( .not. unpk77_success .and. do_k50_decode ) then + maxosd=1 call timer('d240_74 ',0) - Keff=66 - norder=3 + Keff=50 + norder=4 call decode240_74(llr,Keff,maxosd,norder,apmask,message74,cw, & ntype,nharderrors,dmin) call timer('d240_74 ',1) - if(nharderrors.lt.0) goto 3465 if(count(cw.eq.1).eq.0) then nharderrors=-nharderrors cycle @@ -524,134 +545,89 @@ contains write(c77,'(50i1)') message74(1:50) c77(51:77)='000000000000000000000110000' call unpack77(c77,1,msg,unpk77_success) - if(unpk77_success .and. do_k50_decode) then -! If decode was obtained with Keff=66, save call/grid in fst4w_calls.txt if not there already. - i1=index(msg,' ') - i2=i1+index(msg(i1+1:),' ') - wpart=trim(msg(1:i2)) -! Only save callsigns/grids from type 1 messages - if(index(wpart,'/').eq.0 .and. index(wpart,'<').eq.0) then - ifound=0 - do i=1,nwcalls - if(index(wcalls(i),wpart).ne.0) ifound=1 - enddo - - if(ifound.eq.0) then ! This is a new callsign - new_callsign=.true. - if(nwcalls.lt.MAXWCALLS) then - nwcalls=nwcalls+1 - wcalls(nwcalls)=wpart - else - wcalls(1:nwcalls-1)=wcalls(2:nwcalls) - wcalls(nwcalls)=wpart - endif - endif - endif - endif -3465 continue - -! If no decode then try Keff=50 - iaptype=0 - if( .not. unpk77_success .and. do_k50_decode ) then - maxosd=1 - call timer('d240_74 ',0) - Keff=50 - norder=4 - call decode240_74(llr,Keff,maxosd,norder,apmask,message74,cw, & - ntype,nharderrors,dmin) - call timer('d240_74 ',1) - if(count(cw.eq.1).eq.0) then - nharderrors=-nharderrors - cycle - endif - write(c77,'(50i1)') message74(1:50) - c77(51:77)='000000000000000000000110000' - call unpack77(c77,1,msg,unpk77_success) ! No CRC in this mode, so only accept the decode if call/grid have been seen before - if(unpk77_success) then - unpk77_success=.false. - do i=1,nwcalls - if(index(msg,trim(wcalls(i))).gt.0) then - unpk77_success=.true. - endif - enddo - endif + if(unpk77_success) then + unpk77_success=.false. + do i=1,nwcalls + if(index(msg,trim(wcalls(i))).gt.0) then + unpk77_success=.true. + endif + enddo endif - endif - if(nharderrors .ge.0 .and. unpk77_success) then - idupe=0 - do i=1,ndecodes - if(decodes(i).eq.msg) idupe=1 - enddo - if(idupe.eq.1) goto 800 - ndecodes=ndecodes+1 - decodes(ndecodes)=msg + endif - if(iwspr.eq.0) then - call get_fst4_tones_from_bits(message101,itone,0) - else - call get_fst4_tones_from_bits(message74,itone,1) - endif - inquire(file='plotspec',exist=plotspec_exists) - fmid=-999.0 - call timer('dopsprd ',0) - if(plotspec_exists) then - call dopspread(itone,iwave,nsps,nmax,ndown,hmod, & - isbest,fc_synced,fmid,w50) - endif - call timer('dopsprd ',1) - xsig=0 - do i=1,NN - xsig=xsig+s4(itone(i),i) - enddo - base=candidates(icand,5) - arg=600.0*(xsig/base)-1.0 - if(arg.gt.0.0) then - xsnr=10*log10(arg)-35.5-12.5*log10(nsps/8200.0) - if(ntrperiod.eq. 15) xsnr=xsnr+2 - if(ntrperiod.eq. 30) xsnr=xsnr+1 - if(ntrperiod.eq. 900) xsnr=xsnr+1 - if(ntrperiod.eq.1800) xsnr=xsnr+2 - else - xsnr=-99.9 - endif - nsnr=nint(xsnr) - qual=0.0 - fsig=fc_synced - 1.5*baud - inquire(file=trim(data_dir)//'/decdata',exist=decdata_exists) - if(decdata_exists) then - hdec=0 - where(llrs(:,1).ge.0.0) hdec=1 - nhp=count(hdec.ne.cw) ! # hard errors wrt N=1 soft symbols - hd=sum(ieor(hdec,cw)*abs(llrs(:,1))) ! weighted distance wrt N=1 symbols - open(21,file=trim(data_dir)//'/fst4_decodes.dat',status='unknown',position='append') - write(21,3021) nutc,icand,itry,nsyncoh,iaptype, & - ijitter,npct,ntype,Keff,nsync_qual,nharderrors,dmin,nhp,hd, & - sync,xsnr,xdt,fsig,w50,trim(msg) -3021 format(i6.6,i4,6i3,3i4,f6.1,i4,f6.1,f9.2,f6.1,f6.2,f7.1,f7.3,1x,a) - close(21) - endif - call this%callback(nutc,smax1,nsnr,xdt,fsig,msg, & - iaptype,qual,ntrperiod,lwspr,fmid,w50) - if(iwspr.eq.0 .and. nb.lt.0 .and. imode.eq.1) go to 900 - goto 800 + if(nharderrors .ge.0 .and. unpk77_success) then + idupe=0 + do i=1,ndecodes + if(decodes(i).eq.msg) idupe=1 + enddo + if(idupe.eq.1) goto 800 + ndecodes=ndecodes+1 + decodes(ndecodes)=msg + + if(iwspr.eq.0) then + call get_fst4_tones_from_bits(message101,itone,0) + else + call get_fst4_tones_from_bits(message74,itone,1) endif - enddo ! metrics - enddo ! istart jitter -800 enddo !candidate list - enddo ! noise blanker loop + inquire(file='plotspec',exist=plotspec_exists) + fmid=-999.0 + call timer('dopsprd ',0) + if(plotspec_exists) then + call dopspread(itone,iwave,nsps,nmax,ndown,hmod, & + isbest,fc_synced,fmid,w50) + endif + call timer('dopsprd ',1) + xsig=0 + do i=1,NN + xsig=xsig+s4(itone(i),i) + enddo + base=candidates(icand,5) + arg=600.0*(xsig/base)-1.0 + if(arg.gt.0.0) then + xsnr=10*log10(arg)-35.5-12.5*log10(nsps/8200.0) + if(ntrperiod.eq. 15) xsnr=xsnr+2 + if(ntrperiod.eq. 30) xsnr=xsnr+1 + if(ntrperiod.eq. 900) xsnr=xsnr+1 + if(ntrperiod.eq.1800) xsnr=xsnr+2 + else + xsnr=-99.9 + endif + nsnr=nint(xsnr) + qual=0.0 + fsig=fc_synced - 1.5*baud + inquire(file=trim(data_dir)//'/decdata',exist=decdata_exists) + if(decdata_exists) then + hdec=0 + where(llrs(:,1).ge.0.0) hdec=1 + nhp=count(hdec.ne.cw) ! # hard errors wrt N=1 soft symbols + hd=sum(ieor(hdec,cw)*abs(llrs(:,1))) ! weighted distance wrt N=1 symbols + open(21,file=trim(data_dir)//'/fst4_decodes.dat',status='unknown',position='append') + write(21,3021) nutc,icand,itry,nsyncoh,iaptype, & + ijitter,npct,ntype,Keff,nsync_qual,nharderrors,dmin,nhp,hd, & + sync,xsnr,xdt,fsig,w50,trim(msg) +3021 format(i6.6,i4,6i3,3i4,f6.1,i4,f6.1,f9.2,f6.1,f6.2,f7.1,f7.3,1x,a) + close(21) + endif + call this%callback(nutc,smax1,nsnr,xdt,fsig,msg, & + iaptype,qual,ntrperiod,lwspr,fmid,w50) + if(iwspr.eq.0 .and. nb.lt.0) go to 900 + goto 800 + endif + enddo ! metrics + enddo ! istart jitter +800 enddo !candidate list + enddo ! noise blanker loop - if(new_callsign .and. do_k50_decode) then ! re-write the fst4w_calls.txt file - open(42,file=trim(data_dir)//'/fst4w_calls.txt',status='unknown') - do i=1,nwcalls - write(42,'(a20)') trim(wcalls(i)) - enddo - close(42) - endif - - enddo ! mode loop + if(new_callsign .and. do_k50_decode) then ! re-write the fst4w_calls.txt file + open(42,file=trim(data_dir)//'/fst4w_calls.txt',status='unknown') + do i=1,nwcalls + write(42,'(a20)') trim(wcalls(i)) + enddo + close(42) + endif 900 return end subroutine decode From 607a346cf15f6a4fe291719b5fc12e03c59b0e2b Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Mon, 4 Jan 2021 15:35:32 +0000 Subject: [PATCH 72/75] Add new function needed for FST4W decoder updates --- lib/gran.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/gran.c b/lib/gran.c index 24b986503..ac41c7fe4 100644 --- a/lib/gran.c +++ b/lib/gran.c @@ -26,3 +26,9 @@ float gran_() iset++; return v2*fac; } + +/* Generates evenly distributed numbers between 0 and 1. */ +float rran_() +{ + return (float)rand()/(float)RAND_MAX; +} From fd8c993b7be8a6965ec1c2d4ee3317aab49d7b81 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Mon, 4 Jan 2021 21:55:15 +0000 Subject: [PATCH 73/75] Update copyright years --- CMakeLists.txt | 2 +- NEWS | 2 +- Release_Notes.txt | 7 ++++++- translations/wsjtx_ca.ts | 4 ++-- translations/wsjtx_da.ts | 4 ++-- translations/wsjtx_en.ts | 2 +- translations/wsjtx_en_GB.ts | 2 +- translations/wsjtx_es.ts | 6 +++--- translations/wsjtx_it.ts | 4 ++-- translations/wsjtx_ja.ts | 2 +- translations/wsjtx_zh.ts | 4 ++-- translations/wsjtx_zh_HK.ts | 4 ++-- widgets/about.cpp | 2 +- widgets/mainwindow.cpp | 2 +- 14 files changed, 26 insertions(+), 21 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8c7b65593..3108a6d84 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -79,7 +79,7 @@ set (wsjtx_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_ set (PROJECT_BUNDLE_NAME "WSJT-X") set (PROJECT_VENDOR "Joe Taylor, K1JT") set (PROJECT_CONTACT "Joe Taylor ") -set (PROJECT_COPYRIGHT "Copyright (C) 2001-2020 by Joe Taylor, K1JT") +set (PROJECT_COPYRIGHT "Copyright (C) 2001-2021 by Joe Taylor, K1JT") set (PROJECT_HOMEPAGE https://www.physics.princeton.edu/pulsar/K1JT/wsjtx.html) set (PROJECT_MANUAL wsjtx-main) set (PROJECT_MANUAL_DIRECTORY_URL https://www.physics.princeton.edu/pulsar/K1JT/wsjtx-doc/) diff --git a/NEWS b/NEWS index 3c78bb4c2..91fb9cd92 100644 --- a/NEWS +++ b/NEWS @@ -10,7 +10,7 @@ \$$ \$$ \$$$$$$ \$$$$$$ \$$ \$$ \$$ -Copyright 2001 - 2020 by Joe Taylor, K1JT. +Copyright 2001 - 2021 by Joe Taylor, K1JT. Release: WSJT-X 2.3.0-rc1 diff --git a/Release_Notes.txt b/Release_Notes.txt index 793cb905a..e0e8e3c22 100644 --- a/Release_Notes.txt +++ b/Release_Notes.txt @@ -10,7 +10,12 @@ -Copyright 2001 - 2020 by Joe Taylor, K1JT. +Copyright 2001 - 2021 by Joe Taylor, K1JT. + + + Release: WSJT-X 2.3.0-rc3 + Jan 6, 2021 + ------------------------- Release: WSJT-X 2.3.0-rc2 diff --git a/translations/wsjtx_ca.ts b/translations/wsjtx_ca.ts index dc578b791..2b7fbabbd 100644 --- a/translations/wsjtx_ca.ts +++ b/translations/wsjtx_ca.ts @@ -4080,9 +4080,9 @@ La llista es pot mantenir a la configuració (F2). If you make fair use of any part of WSJT-X under terms of the GNU General Public License, you must display the following copyright notice prominently in your derivative work: -"The algorithms, source code, look-and-feel of WSJT-X and related programs, and protocol specifications for the modes FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 are Copyright (C) 2001-2020 by one or more of the following authors: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q; and other members of the WSJT Development Group." +"The algorithms, source code, look-and-feel of WSJT-X and related programs, and protocol specifications for the modes FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 are Copyright (C) 2001-2021 by one or more of the following authors: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q; and other members of the WSJT Development Group." Si fas un ús raonable de qualsevol part de WSJT-X segons els termes de la Llicència Pública General de GNU, has de mostrar de manera destacada el següent avís de copyright en el teu treball derivat: -"Els algoritmes, codi font, aspecte de WSJT-X i programes relacionats i les especificacions de protocol per als modes FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 són Copyright (C) 2001-2020 per un o més dels següents autors: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q i altres membres del grup de desenvolupament de WSJT. " +"Els algoritmes, codi font, aspecte de WSJT-X i programes relacionats i les especificacions de protocol per als modes FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 són Copyright (C) 2001-2021 per un o més dels següents autors: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q i altres membres del grup de desenvolupament de WSJT. " diff --git a/translations/wsjtx_da.ts b/translations/wsjtx_da.ts index ecb74c401..3bff69ce9 100644 --- a/translations/wsjtx_da.ts +++ b/translations/wsjtx_da.ts @@ -4076,9 +4076,9 @@ listen. Makro listen kan også ændfres i Inderstillinger (F2). If you make fair use of any part of WSJT-X under terms of the GNU General Public License, you must display the following copyright notice prominently in your derivative work: -"The algorithms, source code, look-and-feel of WSJT-X and related programs, and protocol specifications for the modes FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 are Copyright (C) 2001-2020 by one or more of the following authors: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q; and other members of the WSJT Development Group." +"The algorithms, source code, look-and-feel of WSJT-X and related programs, and protocol specifications for the modes FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 are Copyright (C) 2001-2021 by one or more of the following authors: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q; and other members of the WSJT Development Group." Hvis du gør brug af nogen del af WSJT-X under betingelserne i GNU General Public License, skal du vise følgende copyright-meddelelse fremtrædende i din egen udgave: -"Algoritmerne, kildekoden, udseendet og funktionen af ​​WSJT-X og relaterede programmer og protokolspecifikationer for Mode FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 er Copyright (C) 2001-2020 af en eller flere af følgende forfattere: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q; og andre medlemmer af WSJT Development Group. " +"Algoritmerne, kildekoden, udseendet og funktionen af ​​WSJT-X og relaterede programmer og protokolspecifikationer for Mode FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 er Copyright (C) 2001-2021 af en eller flere af følgende forfattere: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q; og andre medlemmer af WSJT Development Group. " diff --git a/translations/wsjtx_en.ts b/translations/wsjtx_en.ts index ed8512833..a2bc82d3a 100644 --- a/translations/wsjtx_en.ts +++ b/translations/wsjtx_en.ts @@ -3831,7 +3831,7 @@ list. The list can be maintained in Settings (F2). If you make fair use of any part of WSJT-X under terms of the GNU General Public License, you must display the following copyright notice prominently in your derivative work: -"The algorithms, source code, look-and-feel of WSJT-X and related programs, and protocol specifications for the modes FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 are Copyright (C) 2001-2020 by one or more of the following authors: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q; and other members of the WSJT Development Group." +"The algorithms, source code, look-and-feel of WSJT-X and related programs, and protocol specifications for the modes FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 are Copyright (C) 2001-2021 by one or more of the following authors: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q; and other members of the WSJT Development Group." diff --git a/translations/wsjtx_en_GB.ts b/translations/wsjtx_en_GB.ts index d51b44d29..08dc1f470 100644 --- a/translations/wsjtx_en_GB.ts +++ b/translations/wsjtx_en_GB.ts @@ -3831,7 +3831,7 @@ list. The list can be maintained in Settings (F2). If you make fair use of any part of WSJT-X under terms of the GNU General Public License, you must display the following copyright notice prominently in your derivative work: -"The algorithms, source code, look-and-feel of WSJT-X and related programs, and protocol specifications for the modes FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 are Copyright (C) 2001-2020 by one or more of the following authors: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q; and other members of the WSJT Development Group." +"The algorithms, source code, look-and-feel of WSJT-X and related programs, and protocol specifications for the modes FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 are Copyright (C) 2001-2021 by one or more of the following authors: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q; and other members of the WSJT Development Group." diff --git a/translations/wsjtx_es.ts b/translations/wsjtx_es.ts index cd58e874c..72c269de4 100644 --- a/translations/wsjtx_es.ts +++ b/translations/wsjtx_es.ts @@ -4411,13 +4411,13 @@ Error al cargar datos de usuarios de LotW If you make fair use of any part of WSJT-X under terms of the GNU General Public License, you must display the following copyright notice prominently in your derivative work: -"The algorithms, source code, look-and-feel of WSJT-X and related programs, and protocol specifications for the modes FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 are Copyright (C) 2001-2020 by one or more of the following authors: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q; and other members of the WSJT Development Group." +"The algorithms, source code, look-and-feel of WSJT-X and related programs, and protocol specifications for the modes FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 are Copyright (C) 2001-2021 by one or more of the following authors: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q; and other members of the WSJT Development Group." Si haces un uso justo de cualquier parte de WSJT-X bajo los términos de la Licencia Pública General de GNU, debes mostrar el siguiente aviso de copyright de manera destacada en tú trabajo derivado: -"Los algoritmos, el código fuente, la apariencia de WSJT-X y los programas relacionados, y las especificaciones del protocolo para los modos FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 son Copyright (C) 2001-2020 por uno o más de los siguientes autores: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q y otros miembros del Grupo de Desarrollo WSJT ". +"Los algoritmos, el código fuente, la apariencia de WSJT-X y los programas relacionados, y las especificaciones del protocolo para los modos FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 son Copyright (C) 2001-2021 por uno o más de los siguientes autores: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q y otros miembros del Grupo de Desarrollo WSJT ". Si haces un uso justo de cualquier parte de WSJT-X bajo los términos de la Licencia Pública General de GNU, debes mostrar el siguiente aviso de derechos de autor (copyright) de manera destacada en tu trabajo derivado: -"Los algoritmos, el código fuente, la apariencia y comportamiento del WSJT-X y los programas relacionados, y las especificaciones del protocolo para los modos FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 son Copyright (C) 2001-2020 por uno o más de los siguientes autores: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q y otros miembros del Grupo de Desarrollo WSJT ". +"Los algoritmos, el código fuente, la apariencia y comportamiento del WSJT-X y los programas relacionados, y las especificaciones del protocolo para los modos FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 son Copyright (C) 2001-2021 por uno o más de los siguientes autores: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q y otros miembros del Grupo de Desarrollo WSJT ". diff --git a/translations/wsjtx_it.ts b/translations/wsjtx_it.ts index 3e7b28528..778e1c3b4 100644 --- a/translations/wsjtx_it.ts +++ b/translations/wsjtx_it.ts @@ -4063,10 +4063,10 @@ elenco. L'elenco può essere gestito in Impostazioni (F2). If you make fair use of any part of WSJT-X under terms of the GNU General Public License, you must display the following copyright notice prominently in your derivative work: -"The algorithms, source code, look-and-feel of WSJT-X and related programs, and protocol specifications for the modes FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 are Copyright (C) 2001-2020 by one or more of the following authors: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q; and other members of the WSJT Development Group." +"The algorithms, source code, look-and-feel of WSJT-X and related programs, and protocol specifications for the modes FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 are Copyright (C) 2001-2021 by one or more of the following authors: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q; and other members of the WSJT Development Group." Se si utilizza in modo equo qualsiasi parte di WSJT-X in base ai termini della GNU General Public License, è necessario visualizzare in modo evidente la seguente nota sul copyright nell'opera derivata: -"Gli algoritmi, il codice sorgente, l'aspetto di WSJT-X e dei relativi programmi e le specifiche del protocollo per le modalità FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 sono Copyright (C) 2001-2020 di uno o più dei seguenti autori: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q e altri membri del WSJT Development Group. " +"Gli algoritmi, il codice sorgente, l'aspetto di WSJT-X e dei relativi programmi e le specifiche del protocollo per le modalità FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 sono Copyright (C) 2001-2021 di uno o più dei seguenti autori: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q e altri membri del WSJT Development Group. " diff --git a/translations/wsjtx_ja.ts b/translations/wsjtx_ja.ts index 2813f3c91..d8927464f 100644 --- a/translations/wsjtx_ja.ts +++ b/translations/wsjtx_ja.ts @@ -4032,7 +4032,7 @@ ENTERを押してテキストを登録リストに追加. If you make fair use of any part of WSJT-X under terms of the GNU General Public License, you must display the following copyright notice prominently in your derivative work: -"The algorithms, source code, look-and-feel of WSJT-X and related programs, and protocol specifications for the modes FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 are Copyright (C) 2001-2020 by one or more of the following authors: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q; and other members of the WSJT Development Group." +"The algorithms, source code, look-and-feel of WSJT-X and related programs, and protocol specifications for the modes FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 are Copyright (C) 2001-2021 by one or more of the following authors: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q; and other members of the WSJT Development Group." diff --git a/translations/wsjtx_zh.ts b/translations/wsjtx_zh.ts index f163e86be..90e083071 100644 --- a/translations/wsjtx_zh.ts +++ b/translations/wsjtx_zh.ts @@ -3888,10 +3888,10 @@ list. The list can be maintained in Settings (F2). If you make fair use of any part of WSJT-X under terms of the GNU General Public License, you must display the following copyright notice prominently in your derivative work: -"The algorithms, source code, look-and-feel of WSJT-X and related programs, and protocol specifications for the modes FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 are Copyright (C) 2001-2020 by one or more of the following authors: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q; and other members of the WSJT Development Group." +"The algorithms, source code, look-and-feel of WSJT-X and related programs, and protocol specifications for the modes FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 are Copyright (C) 2001-2021 by one or more of the following authors: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q; and other members of the WSJT Development Group." 如果您根据 GNU 通用公共许可证条款合理使用 WSJT-X 的任何部分, 则必须在衍生作品中醒目地显示以下版权声明: -"WSJT-X 的算法, 源代码, 外观和感觉及相关程序,和协议规格模式 FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 的版权 (C) 2001-2019 由以下一个或多个作者: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q; 和 WSJT 开发组的其他成员." +"WSJT-X 的算法, 源代码, 外观和感觉及相关程序,和协议规格模式 FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 的版权 (C) 2001-2021 由以下一个或多个作者: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q; 和 WSJT 开发组的其他成员." diff --git a/translations/wsjtx_zh_HK.ts b/translations/wsjtx_zh_HK.ts index 851f485b9..a4507e9a2 100644 --- a/translations/wsjtx_zh_HK.ts +++ b/translations/wsjtx_zh_HK.ts @@ -3888,10 +3888,10 @@ list. The list can be maintained in Settings (F2). If you make fair use of any part of WSJT-X under terms of the GNU General Public License, you must display the following copyright notice prominently in your derivative work: -"The algorithms, source code, look-and-feel of WSJT-X and related programs, and protocol specifications for the modes FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 are Copyright (C) 2001-2020 by one or more of the following authors: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q; and other members of the WSJT Development Group." +"The algorithms, source code, look-and-feel of WSJT-X and related programs, and protocol specifications for the modes FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 are Copyright (C) 2001-2021 by one or more of the following authors: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q; and other members of the WSJT Development Group." 如果您根據 GNU 通用公共授權條款合理使用 WSJT-X 的任何部分, 則必須在衍生作品中醒目地顯示以下版權聲明: -"WSJT-X 的演演演算法, 原始碼, 外觀和感覺及相關程式, 和協定規格模式 FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 的版權 (C) 2001-2019 由以下一個或多個作者: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q; 和 WSJT 開發組的其他成員." +"WSJT-X 的演演演算法, 原始碼, 外觀和感覺及相關程式, 和協定規格模式 FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 的版權 (C) 2001-2021 由以下一個或多個作者: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q; 和 WSJT 開發組的其他成員." diff --git a/widgets/about.cpp b/widgets/about.cpp index 908e6e38d..7989f5c9b 100644 --- a/widgets/about.cpp +++ b/widgets/about.cpp @@ -18,7 +18,7 @@ CAboutDlg::CAboutDlg(QWidget *parent) : + " " + revision ()}.simplified () + "
" "WSJT-X implements a number of digital modes designed for
" "weak-signal Amateur Radio communication.

" - "© 2001-2020 by Joe Taylor, K1JT, Bill Somerville, G4WJS,
" + "© 2001-2021 by Joe Taylor, K1JT, Bill Somerville, G4WJS,
" "and Steve Franke, K9AN.

" "We gratefully acknowledge contributions from AC6SL, AE4JY,
" "DF2ET, DJ0OT, G3WDG, G4KLA, IV3NWV, IW3RAB, KA1GT, K3WYC,
" diff --git a/widgets/mainwindow.cpp b/widgets/mainwindow.cpp index eeb193e39..ece0fdea9 100644 --- a/widgets/mainwindow.cpp +++ b/widgets/mainwindow.cpp @@ -2594,7 +2594,7 @@ void MainWindow::on_actionCopyright_Notice_triggered() "\"The algorithms, source code, look-and-feel of WSJT-X and related " "programs, and protocol specifications for the modes FSK441, FT8, JT4, " "JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 are Copyright (C) " - "2001-2020 by one or more of the following authors: Joseph Taylor, " + "2001-2021 by one or more of the following authors: Joseph Taylor, " "K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, " "IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; " "Philip Karn, KA9Q; and other members of the WSJT Development Group.\""); From 43659196bc08957625da15536e37ac4ef33e6369 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Mon, 4 Jan 2021 22:40:25 +0000 Subject: [PATCH 74/75] Release notes for v2.3.0 RC3 --- NEWS | 119 ++++++++++++++++++++++++++++++++++++++++++++++ Release_Notes.txt | 83 ++++++++++++++++++++++++++++++++ 2 files changed, 202 insertions(+) diff --git a/NEWS b/NEWS index 91fb9cd92..76fe7c528 100644 --- a/NEWS +++ b/NEWS @@ -13,6 +13,125 @@ Copyright 2001 - 2021 by Joe Taylor, K1JT. + Release: WSJT-X 2.3.0-rc3 + Jan 6, 2021 + ------------------------- + +WSJT-X 2.3.0 Release Candidate 3 adds an improved FST4W decoder and +fixes several defects and regressions discovered since the second +release candidate. + + - FST4W: Improve FST4W decoder sensitivity on fading channels and + decrease false decode rate. + + FST4W uses 50-bit messages and a 24-bit CRC. The 74-bit + message+CRC is encoded into a 240-bit codeword. Received messages + are decoded by two different decoders: (i) a “belief propagation” + (BP) decoder and (ii) an ordered statistics decoder (OSD). The + ordered statistics decoder has a knob that allows any or all CRC + bits to be treated as additional parity bits rather than as part of + the message+CRC field. Thus, the OSD decoder can decode the + received message as a (240,50+Nc) code, where Nc is any integer + between 0 and 24. In the RC1 and RC2 releases the OSD decoding + attempt treated the code as a (240,64) code (14-bit CRC). This + release uses 2 OSD decoding attempts that treat the received word + as (i) a (240,66) code with 16-bit CRC and code rate 0.308 and (ii) + a (240,50) code with no CRC and code rate 0.208. Codewords returned + by the (240,50) CRC-less decoding attempt are unpacked and the + decode is printed only if it contains a callsign/grid pair that + have been previously decoded by the belief propagation decoder + (which treats the code as a (240,74) code with 24-bit CRC) or the + ordered statistics decoder configured for (240,66) (16-bit + CRC). The callsign/grid memory is stored in file “fst4w_calls.txt” + which resides in the data directory. + + - FT8: Fixed a crash triggered by double clicking on the waterfall to + invoke a decode of a signal in the preceding T/R interval. + + - FST4W: Do not save .c2 files. + + - FST4W: Correct a bug that could cause incorrect operation when + using negative noise blanker (NB) percentage to trigger looping + over a range of NB percentages. + + - fst4sim: Added simulation of Lorentzian fading spectrum, invoked by + negative fspread values. + + - Color highlighting scheme window fixed in dark mode. + + - Reports sent by QSO partners to other stations no longer logged in + error. + + - UDP Status(1) message now includes the current Tx message. + + - Example diagnostic logging configuration files included. + + - Use system localization for date fields in Log QSO dialog. + + - Improvements to audio input and output buffer sizes. + + - wsprd: Fails gracefully if data directory does not exist. + + - wsjtx_app_version: new utility to print application version string. + + - Regression causing incorrect working frequency selection when + changing modes repaired. + + - Regression with QSO initiation with "Best S&P" repaired. + + - Updated installation instructions for macOS covering M1 hardware. + + - Improved compatibility is Debian 9 required distribution packages. + + - Repair regression with missing time-stamps in the ALL.TXT journal. + + - Allow hamlib_settings.json to work with PTT only configurations so + that optional PTT sharing on RTS or DTR can be enabled. + + - Several improvements to main window sizing and layout. + + - Repair regression with OpenSSL libraries being required when LoTW + highlighting is not enabled. + + - Repair a defect that caused 2 by 1 callsigns to be incorrectly + parsed as non-standard. + + - Several updates to international UI translations. + + + + Release: WSJT-X 2.3.0-rc2 + Nov 16, 2020 + ------------------------- + +WSJT-X 2.3.0 Release Candidate 2 fixes issues found in RC1 and +includes some new functionality that missed the RC1 cut off deadline. + + - Dropped audio samples message box removed, warnings and errors for + these are now sent to the WSJT-X system log. + + - FST4W spots to WSPRNet.org will be augmented such that the server + can distinguish the mode being spotted. Spots to WSPRNet.org will + no longer be restricted to WSPR sub-bands. + + - A new internal system and data logging facility used to provide + trace, debug, information, warning, error, and fatal error + messages. The verbosity and filtering of messages is user definable + via a configuration file. Without a configuration file a basic log + is written with information, warning and error messages only. Log + files are automatically rotated to limit disk usage. + + - Due to some users using inappropriate multicast IP addresses for + their interoperating severs the default behaviour now is to only + send multicast UDP datagrams to the loop-back network interface. + Users who require WSJT-X UDP Message Protocol datagrams to reach + other hosts will now have to configure WSJT-X to send on an + appropriate network interface, and use an appropriately scoped + multicast group address for their server applications. If you are + not sure then 224.0.0.1 (or ff02::1 if IPv6 is desired) is a safe + choice. + + Release: WSJT-X 2.3.0-rc1 Sept 28, 2020 ------------------------- diff --git a/Release_Notes.txt b/Release_Notes.txt index e0e8e3c22..b091f6973 100644 --- a/Release_Notes.txt +++ b/Release_Notes.txt @@ -17,6 +17,88 @@ Copyright 2001 - 2021 by Joe Taylor, K1JT. Jan 6, 2021 ------------------------- +WSJT-X 2.3.0 Release Candidate 3 adds an improved FST4W decoder and +fixes several defects and regressions discovered since the second +release candidate. + + - FST4W: Improve FST4W decoder sensitivity on fading channels and + decrease false decode rate. + + FST4W uses 50-bit messages and a 24-bit CRC. The 74-bit + message+CRC is encoded into a 240-bit codeword. Received messages + are decoded by two different decoders: (i) a “belief propagation” + (BP) decoder and (ii) an ordered statistics decoder (OSD). The + ordered statistics decoder has a knob that allows any or all CRC + bits to be treated as additional parity bits rather than as part of + the message+CRC field. Thus, the OSD decoder can decode the + received message as a (240,50+Nc) code, where Nc is any integer + between 0 and 24. In the RC1 and RC2 releases the OSD decoding + attempt treated the code as a (240,64) code (14-bit CRC). This + release uses 2 OSD decoding attempts that treat the received word + as (i) a (240,66) code with 16-bit CRC and code rate 0.308 and (ii) + a (240,50) code with no CRC and code rate 0.208. Codewords returned + by the (240,50) CRC-less decoding attempt are unpacked and the + decode is printed only if it contains a callsign/grid pair that + have been previously decoded by the belief propagation decoder + (which treats the code as a (240,74) code with 24-bit CRC) or the + ordered statistics decoder configured for (240,66) (16-bit + CRC). The callsign/grid memory is stored in file “fst4w_calls.txt” + which resides in the data directory. + + - FT8: Fixed a crash triggered by double clicking on the waterfall to + invoke a decode of a signal in the preceding T/R interval. + + - FST4W: Do not save .c2 files. + + - FST4W: Correct a bug that could cause incorrect operation when + using negative noise blanker (NB) percentage to trigger looping + over a range of NB percentages. + + - fst4sim: Added simulation of Lorentzian fading spectrum, invoked by + negative fspread values. + + - Color highlighting scheme window fixed in dark mode. + + - Reports sent by QSO partners to other stations no longer logged in + error. + + - UDP Status(1) message now includes the current Tx message. + + - Example diagnostic logging configuration files included. + + - Use system localization for date fields in Log QSO dialog. + + - Improvements to audio input and output buffer sizes. + + - wsprd: Fails gracefully if data directory does not exist. + + - wsjtx_app_version: new utility to print application version string. + + - Regression causing incorrect working frequency selection when + changing modes repaired. + + - Regression with QSO initiation with "Best S&P" repaired. + + - Updated installation instructions for macOS covering M1 hardware. + + - Improved compatibility is Debian 9 required distribution packages. + + - Repair regression with missing time-stamps in the ALL.TXT journal. + + - Allow hamlib_settings.json to work with PTT only configurations so + that optional PTT sharing on RTS or DTR can be enabled. + + - Several improvements to main window sizing and layout. + + - Repair regression with OpenSSL libraries being required when LoTW + highlighting is not enabled. + + - Repair a defect that caused 2 by 1 callsigns to be incorrectly + parsed as non-standard. + + - Several updates to international UI translations. + + Release: WSJT-X 2.3.0-rc2 Nov 16, 2020 @@ -50,6 +132,7 @@ includes some new functionality that missed the RC1 cut off deadline. choice. + Release: WSJT-X 2.3.0-rc1 Sept 28, 2020 ------------------------- From c9fb6510a0d1ccbe4cb6e5b58e4c33bb937f5d05 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Mon, 4 Jan 2021 22:50:02 +0000 Subject: [PATCH 75/75] Update expiry and nag message --- widgets/mainwindow.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/widgets/mainwindow.cpp b/widgets/mainwindow.cpp index ece0fdea9..bec116e6e 100644 --- a/widgets/mainwindow.cpp +++ b/widgets/mainwindow.cpp @@ -1039,9 +1039,9 @@ void MainWindow::not_GA_warning_message () MessageBox::critical_message (this, "This is a pre-release version of WSJT-X 2.3.0 made\n" "available for testing purposes. By design it will\n" - "be nonfunctional after 0000 UTC on Jan 19, 2021."); + "be nonfunctional after 0000 UTC on Jan 26, 2021."); auto now = QDateTime::currentDateTimeUtc (); - if (now >= QDateTime {{2021, 1, 19}, {0, 0}, Qt::UTC}) { + if (now >= QDateTime {{2021, 1, 26}, {0, 0}, Qt::UTC}) { Q_EMIT finished (); } }