diff --git a/MessageClient.cpp b/MessageClient.cpp index c7106762d..1c6712e31 100644 --- a/MessageClient.cpp +++ b/MessageClient.cpp @@ -350,7 +350,8 @@ void MessageClient::status_update (Frequency f, QString const& mode, QString con , bool tx_enabled, bool transmitting, bool decoding , qint32 rx_df, qint32 tx_df, QString const& de_call , QString const& de_grid, QString const& dx_grid - , bool watchdog_timeout) + , bool watchdog_timeout, QString const& sub_mode + , bool fast_mode) { if (m_->server_port_ && !m_->server_string_.isEmpty ()) { @@ -358,7 +359,8 @@ void MessageClient::status_update (Frequency f, QString const& mode, QString con NetworkMessage::Builder out {&message, NetworkMessage::Status, m_->id_, m_->schema_}; 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; + << de_grid.toUtf8 () << dx_grid.toUtf8 () << watchdog_timeout << sub_mode.toUtf8 () + << fast_mode; m_->send_message (out, message); } } diff --git a/MessageClient.hpp b/MessageClient.hpp index d3db02f2e..d8b3788dd 100644 --- a/MessageClient.hpp +++ b/MessageClient.hpp @@ -50,7 +50,8 @@ public: Q_SLOT void status_update (Frequency, QString const& mode, QString const& dx_call, QString const& report , QString const& tx_mode, bool tx_enabled, bool transmitting, bool decoding , qint32 rx_df, qint32 tx_df, QString const& de_call, QString const& de_grid - , QString const& dx_grid, bool watchdog_timeout); + , QString const& dx_grid, bool watchdog_timeout, QString const& sub_mode + , bool fast_mode); Q_SLOT void decode (bool is_new, QTime time, qint32 snr, float delta_time, quint32 delta_frequency , QString const& mode, QString const& message); Q_SLOT void WSPR_decode (bool is_new, QTime time, qint32 snr, float delta_time, Frequency diff --git a/MessageServer.cpp b/MessageServer.cpp index 6d1c6007a..c33588649 100644 --- a/MessageServer.cpp +++ b/MessageServer.cpp @@ -214,15 +214,19 @@ void MessageServer::impl::parse_message (QHostAddress const& sender, port_type s QByteArray de_grid; QByteArray dx_grid; bool watchdog_timeout {false}; + QByteArray sub_mode; + bool fast_mode {false}; in >> f >> mode >> dx_call >> report >> tx_mode >> tx_enabled >> transmitting >> decoding - >> rx_df >> tx_df >> de_call >> de_grid >> dx_grid >> watchdog_timeout; + >> rx_df >> tx_df >> de_call >> de_grid >> dx_grid >> watchdog_timeout >> sub_mode + >> fast_mode; if (check_status (in) != Fail) { Q_EMIT self_->status_update (id, f, QString::fromUtf8 (mode), QString::fromUtf8 (dx_call) , QString::fromUtf8 (report), QString::fromUtf8 (tx_mode) , tx_enabled, transmitting, decoding, rx_df, tx_df , QString::fromUtf8 (de_call), QString::fromUtf8 (de_grid) - , QString::fromUtf8 (dx_grid), watchdog_timeout); + , QString::fromUtf8 (dx_grid), watchdog_timeout + , QString::fromUtf8 (sub_mode), fast_mode); } } break; diff --git a/MessageServer.hpp b/MessageServer.hpp index a2da57241..ad6cca1d0 100644 --- a/MessageServer.hpp +++ b/MessageServer.hpp @@ -66,7 +66,7 @@ public: , QString const& report, QString const& tx_mode, bool tx_enabled , bool transmitting, bool decoding, qint32 rx_df, qint32 tx_df , QString const& de_call, QString const& de_grid, QString const& dx_grid - , bool watchdog_timeout); + , bool watchdog_timeout, QString const& sub_mode, bool fast_mode); Q_SIGNAL void client_closed (QString const& id); Q_SIGNAL void decode (bool is_new, QString const& id, QTime time, qint32 snr, float delta_time , quint32 delta_frequency, QString const& mode, QString const& message); diff --git a/NetworkMessage.hpp b/NetworkMessage.hpp index bc16a7b92..41fba03f9 100644 --- a/NetworkMessage.hpp +++ b/NetworkMessage.hpp @@ -122,6 +122,8 @@ * DE grid utf8 * DX grid utf8 * Tx Watchdog bool + * Sub-mode utf8 + * Fast mode bool * * WSJT-X sends this status message when various internal state * changes to allow the server to track the relevant state of each @@ -132,7 +134,7 @@ * "Enable Tx" button status changes, * Dial frequency changes, * Changes to the "DX Call" field, - * Operating mode changes, + * Operating mode, sub-mode or fast mode changes, * Transmit mode changed (in dual JT9+JT65 mode), * Changes to the "Rpt" spinner, * After an old decodes replay sequence (see Replay below), diff --git a/UDPExamples/ClientWidget.cpp b/UDPExamples/ClientWidget.cpp index 36a64796b..3ff1a561f 100644 --- a/UDPExamples/ClientWidget.cpp +++ b/UDPExamples/ClientWidget.cpp @@ -124,6 +124,7 @@ ClientWidget::ClientWidget (QAbstractItemModel * decodes_model, QAbstractItemMod , auto_off_button_ {new QPushButton {tr ("&Auto Off")}} , halt_tx_button_ {new QPushButton {tr ("&Halt Tx")}} , mode_label_ {new QLabel} + , fast_mode_ {false} , frequency_label_ {new QLabel} , dx_label_ {new QLabel} , rx_df_label_ {new QLabel} @@ -215,14 +216,17 @@ void ClientWidget::update_status (QString const& id, Frequency f, QString const& , QString const& report, QString const& tx_mode, bool tx_enabled , bool transmitting, bool decoding, qint32 rx_df, qint32 tx_df , QString const& de_call, QString const& /*de_grid*/, QString const& dx_grid - , bool watchdog_timeout) + , bool watchdog_timeout, QString const& sub_mode, bool fast_mode) { if (id == id_) { + fast_mode_ = fast_mode; decodes_proxy_model_.de_call (de_call); decodes_proxy_model_.rx_df (rx_df); - mode_label_->setText (QString {"Mode: %1%2"} + mode_label_->setText (QString {"Mode: %1%2%3%4"} .arg (mode) + .arg (sub_mode) + .arg (fast_mode && !mode.contains (QRegularExpression {R"(ISCAT|MSK144)"}) ? "fast" : "") .arg (tx_mode.isEmpty () || tx_mode == mode ? "" : '(' + tx_mode + ')')); frequency_label_->setText ("QRG: " + Radio::pretty_frequency_MHz_string (f)); dx_label_->setText (dx_call.size () >= 0 ? QString {"DX: %1%2"}.arg (dx_call) diff --git a/UDPExamples/ClientWidget.hpp b/UDPExamples/ClientWidget.hpp index 3fc1bb35c..1e7779c87 100644 --- a/UDPExamples/ClientWidget.hpp +++ b/UDPExamples/ClientWidget.hpp @@ -24,11 +24,13 @@ public: , QString const& id, QString const& version, QString const& revision , QWidget * parent = nullptr); + bool fast_mode () const {return fast_mode_;} + Q_SLOT void update_status (QString const& id, Frequency f, QString const& mode, QString const& dx_call , QString const& report, QString const& tx_mode, bool tx_enabled , bool transmitting, bool decoding, qint32 rx_df, qint32 tx_df , QString const& de_call, QString const& de_grid, QString const& dx_grid - , bool watchdog_timeout); + , bool watchdog_timeout, QString const& sub_mode, bool fast_mode); Q_SLOT void decode_added (bool is_new, QString const& client_id, QTime, qint32 snr , float delta_time, quint32 delta_frequency, QString const& mode , QString const& message); @@ -69,6 +71,7 @@ private: QAbstractButton * auto_off_button_; QAbstractButton * halt_tx_button_; QLabel * mode_label_; + bool fast_mode_; QLabel * frequency_label_; QLabel * dx_label_; QLabel * rx_df_label_; diff --git a/UDPExamples/DecodesModel.cpp b/UDPExamples/DecodesModel.cpp index 59684ba43..eb9aa64cc 100644 --- a/UDPExamples/DecodesModel.cpp +++ b/UDPExamples/DecodesModel.cpp @@ -22,9 +22,10 @@ namespace QFont text_font {"Courier", 10}; QList make_row (QString const& client_id, QTime time, qint32 snr, float delta_time - , quint32 delta_frequency, QString const& mode, QString const& message) + , quint32 delta_frequency, QString const& mode, QString const& message + , bool is_fast) { - auto time_item = new QStandardItem {time.toString ("hh:mm")}; + auto time_item = new QStandardItem {time.toString (is_fast ? "hh:mm:ss" : "hh:mm")}; time_item->setData (time); time_item->setTextAlignment (Qt::AlignRight); @@ -66,7 +67,8 @@ DecodesModel::DecodesModel (QObject * parent) } void DecodesModel::add_decode (bool is_new, QString const& client_id, QTime time, qint32 snr, float delta_time - , quint32 delta_frequency, QString const& mode, QString const& message) + , quint32 delta_frequency, QString const& mode, QString const& message + , bool is_fast) { if (!is_new) { @@ -93,12 +95,13 @@ void DecodesModel::add_decode (bool is_new, QString const& client_id, QTime time } if (target_row >= 0) { - insertRow (target_row + 1, make_row (client_id, time, snr, delta_time, delta_frequency, mode, message)); + insertRow (target_row + 1, make_row (client_id, time, snr, delta_time, delta_frequency, mode + , message, is_fast)); return; } } - appendRow (make_row (client_id, time, snr, delta_time, delta_frequency, mode, message)); + appendRow (make_row (client_id, time, snr, delta_time, delta_frequency, mode, message, is_fast)); } void DecodesModel::clear_decodes (QString const& client_id) diff --git a/UDPExamples/DecodesModel.hpp b/UDPExamples/DecodesModel.hpp index 4425a7e9f..03eaab39f 100644 --- a/UDPExamples/DecodesModel.hpp +++ b/UDPExamples/DecodesModel.hpp @@ -32,7 +32,7 @@ public: explicit DecodesModel (QObject * parent = nullptr); Q_SLOT void add_decode (bool is_new, QString const& client_id, QTime time, qint32 snr, float delta_time - , quint32 delta_frequency, QString const& mode, QString const& message); + , quint32 delta_frequency, QString const& mode, QString const& message, bool is_fast); Q_SLOT void clear_decodes (QString const& client_id); Q_SLOT void do_reply (QModelIndex const& source); diff --git a/UDPExamples/MessageAggregatorMainWindow.cpp b/UDPExamples/MessageAggregatorMainWindow.cpp index 660af08d6..e15fcbf17 100644 --- a/UDPExamples/MessageAggregatorMainWindow.cpp +++ b/UDPExamples/MessageAggregatorMainWindow.cpp @@ -87,7 +87,12 @@ MessageAggregatorMainWindow::MessageAggregatorMainWindow () connect (server_, &MessageServer::client_closed, this, &MessageAggregatorMainWindow::remove_client); connect (server_, &MessageServer::client_closed, decodes_model_, &DecodesModel::clear_decodes); connect (server_, &MessageServer::client_closed, beacons_model_, &BeaconsModel::clear_decodes); - connect (server_, &MessageServer::decode, decodes_model_, &DecodesModel::add_decode); + connect (server_, &MessageServer::decode, [this] (bool is_new, QString const& id, QTime time + , qint32 snr, float delta_time + , quint32 delta_frequency, QString const& mode + , QString const& message) { + decodes_model_->add_decode (is_new, id, time, snr, delta_time, delta_frequency, mode, message + , dock_widgets_[id]->fast_mode ());}); connect (server_, &MessageServer::WSPR_decode, beacons_model_, &BeaconsModel::add_beacon_spot); connect (server_, &MessageServer::clear_decodes, decodes_model_, &DecodesModel::clear_decodes); connect (server_, &MessageServer::clear_decodes, beacons_model_, &BeaconsModel::clear_decodes); diff --git a/UDPExamples/UDPDaemon.cpp b/UDPExamples/UDPDaemon.cpp index e11b28a18..14a531bbf 100644 --- a/UDPExamples/UDPDaemon.cpp +++ b/UDPExamples/UDPDaemon.cpp @@ -46,10 +46,11 @@ public: { } - Q_SLOT void update_status (QString const& id, Frequency f, QString const& /*mode*/, QString const& /*dx_call*/ + Q_SLOT void update_status (QString const& id, Frequency f, QString const& mode, QString const& /*dx_call*/ , QString const& /*report*/, QString const& /*tx_mode*/, bool /*tx_enabled*/ , bool /*transmitting*/, bool /*decoding*/, qint32 /*rx_df*/, qint32 /*tx_df*/ - , QString const& /*de_call*/, QString const& /*de_grid*/, QString const& /*dx_grid*/, bool /* watchdog_timeout */) + , QString const& /*de_call*/, QString const& /*de_grid*/, QString const& /*dx_grid*/ + , bool /* watchdog_timeout */, QString const& sub_mode, bool /*fast_mode*/) { if (id == id_) { @@ -58,6 +59,11 @@ public: std::cout << tr ("%1: Dial frequency changed to %2").arg (id_).arg (f).toStdString () << std::endl; dial_frequency_ = f; } + if (mode + sub_mode != mode_) + { + std::cout << tr ("%1: Mode changed to %2").arg (id_).arg (mode + sub_mode).toStdString () << std::endl; + mode_ = mode + sub_mode; + } } } @@ -90,6 +96,7 @@ public: private: QString id_; Frequency dial_frequency_; + QString mode_; }; class Server diff --git a/mainwindow.cpp b/mainwindow.cpp index 6c5432c04..debdb5bbb 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -1310,6 +1310,7 @@ void MainWindow::fastSink(qint64 frames) processMessage (message,43,false); } } + if (m_mode != "ISCAT") postDecode (true, decodedtext.string ()); writeAllTxt(message); bool stdMsg = decodedtext.report(m_baseCall, Radio::base_callsign(ui->dxCallEntry->text()),m_rptRcvd); @@ -1747,12 +1748,15 @@ void MainWindow::createStatusBar() //createStatusBar void MainWindow::setup_status_bar (bool vhf) { - mode_label.setText ("QRA64" == m_mode ? QString {"QRA64"} : m_mode); - if (m_mode.contains (QRegularExpression {R"(^(JT65|JT9|JT4|ISCAT|QRA64)$)"})) { - if (vhf || "JT4" == m_mode || "ISCAT" == m_mode) { - mode_label.setText (mode_label.text () + " " + QChar {short (m_nSubMode + 65)}); + auto submode = current_submode (); + if (vhf && submode != '\0') + { + mode_label.setText (m_mode + " " + submode); + } + else + { + mode_label.setText (m_mode); } - } if ("ISCAT" == m_mode) { mode_label.setStyleSheet ("QLabel{background-color: #ff9933}"); } else if ("JT9" == m_mode) { @@ -2328,6 +2332,7 @@ void::MainWindow::fast_decode_done() tmax=t; m_bDecoded=true; } + postDecode (true, decodedtext.string ()); writeAllTxt(message); if(m_mode=="JT9" or m_mode=="MSK144") { @@ -3977,7 +3982,6 @@ void MainWindow::on_actionJT4_triggered() WSPR_config(false); switch_mode (Modes::JT4); m_modeTx="JT4"; - statusChanged(); m_TRperiod=60; m_modulator->setPeriod(m_TRperiod); // TODO - not thread safe m_detector->setPeriod(m_TRperiod); // TODO - not thread safe @@ -4005,6 +4009,7 @@ void MainWindow::on_actionJT4_triggered() ui->sbSubmode->setValue(0); ui->sbTR->setValue(0); } + statusChanged(); } void MainWindow::on_actionJT9_triggered() @@ -4021,7 +4026,6 @@ void MainWindow::on_actionJT9_triggered() WSPR_config(false); switch_mode (Modes::JT9); if(m_modeTx!="JT9") on_pbTxMode_clicked(); - statusChanged(); m_nsps=6912; m_FFTSize = m_nsps / 2; Q_EMIT FFTSize (m_FFTSize); @@ -4061,6 +4065,7 @@ void MainWindow::on_actionJT9_triggered() m_detector->setPeriod(m_TRperiod); // TODO - not thread safe ui->label_6->setText("Band Activity"); ui->label_7->setText("Rx Frequency"); + statusChanged(); } void MainWindow::on_actionJT9_JT65_triggered() @@ -4074,7 +4079,6 @@ void MainWindow::on_actionJT9_JT65_triggered() m_modeTx="JT9"; } m_nSubMode=0; //Dual-mode always means JT9 and JT65A - statusChanged(); m_TRperiod=60; m_modulator->setPeriod(m_TRperiod); // TODO - not thread safe m_detector->setPeriod(m_TRperiod); // TODO - not thread safe @@ -4097,6 +4101,7 @@ void MainWindow::on_actionJT9_JT65_triggered() ui->sbTR->setValue(0); ui->label_6->setText("Band Activity"); ui->label_7->setText("Rx Frequency"); + statusChanged(); } void MainWindow::on_actionJT65_triggered() @@ -4118,7 +4123,6 @@ void MainWindow::on_actionJT65_triggered() WSPR_config(false); switch_mode (Modes::JT65); if(m_modeTx!="JT65") on_pbTxMode_clicked(); - statusChanged(); m_TRperiod=60; m_modulator->setPeriod(m_TRperiod); // TODO - not thread safe m_detector->setPeriod(m_TRperiod); // TODO - not thread safe @@ -4148,6 +4152,7 @@ void MainWindow::on_actionJT65_triggered() ui->label_6->setText("Band Activity"); ui->label_7->setText("Rx Frequency"); } + statusChanged(); } void MainWindow::on_actionQRA64_triggered() @@ -4213,6 +4218,7 @@ void MainWindow::on_actionISCAT_triggered() ui->sbSubmode->setMaximum(1); if(m_nSubMode==0) ui->TxFreqSpinBox->setValue(1012); if(m_nSubMode==1) ui->TxFreqSpinBox->setValue(560); + statusChanged (); } void MainWindow::on_actionMSK144_triggered() @@ -4222,7 +4228,6 @@ void MainWindow::on_actionMSK144_triggered() m_modeTx="MSK144"; ui->actionMSK144->setChecked(true); switch_mode (Modes::MSK144); - statusChanged(); m_nsps=6; m_FFTSize = 7 * 512; Q_EMIT FFTSize (m_FFTSize); @@ -4257,6 +4262,7 @@ void MainWindow::on_actionMSK144_triggered() ui->rptSpinBox->setSingleStep(1); ui->sbFtol->setMinimum(22); ui->sbFtol->setMaximum(25); + statusChanged(); } void MainWindow::on_actionWSPR_triggered() @@ -4266,7 +4272,6 @@ void MainWindow::on_actionWSPR_triggered() WSPR_config(true); switch_mode (Modes::WSPR); m_modeTx="WSPR"; //### not needed ?? ### - statusChanged(); m_TRperiod=120; m_modulator->setPeriod(m_TRperiod); // TODO - not thread safe m_detector->setPeriod(m_TRperiod); // TODO - not thread safe @@ -4285,6 +4290,7 @@ void MainWindow::on_actionWSPR_triggered() m_bFast9=false; fast_config(false); ui->TxFreqSpinBox->setValue(ui->WSPRfreqSpinBox->value()); + statusChanged(); } void MainWindow::on_actionEcho_triggered() @@ -4308,7 +4314,6 @@ void MainWindow::on_actionEcho_triggered() m_wideGraph->setModeTx(m_modeTx); ui->TxFreqSpinBox->setValue(1500); ui->TxFreqSpinBox->setEnabled (false); - statusChanged(); if(!m_echoGraph->isVisible()) m_echoGraph->show(); if (!ui->actionAstronomical_data->isChecked ()) { ui->actionAstronomical_data->setChecked (true); @@ -4318,6 +4323,7 @@ void MainWindow::on_actionEcho_triggered() fast_config(false); WSPR_config(true); ui->decodedTextLabel->setText(" UTC N Level Sig DF Width Q"); + statusChanged(); } @@ -5253,15 +5259,30 @@ void MainWindow::on_sbTR_valueChanged(int index) m_fastGraph->setTRperiod(m_TRperiod); } +QChar MainWindow::current_submode () const +{ + QChar submode {0}; + if (m_mode.contains (QRegularExpression {R"(^(JT65|JT9|JT4|ISCAT|QRA64)$)"}) + && (m_config.enable_VHF_features () || "JT4" == m_mode || "ISCAT" == m_mode)) + { + submode = m_nSubMode + 65; + } + return submode; +} + void MainWindow::on_sbSubmode_valueChanged(int n) { m_nSubMode=n; m_wideGraph->setSubMode(m_nSubMode); - mode_label.setText (m_mode); - if ((m_mode != "JT9+JT65" and m_mode != "MSK144" and - !m_mode.startsWith ("WSPR")) || !m_config.enable_VHF_features ()) { - mode_label.setText (mode_label.text () + " " + QChar {short (m_nSubMode + 65)}); - } + auto submode = current_submode (); + if (submode != '\0') + { + mode_label.setText (m_mode + " " + submode); + } + else + { + mode_label.setText (m_mode); + } if(m_mode=="ISCAT") { if(m_nSubMode==0) ui->TxFreqSpinBox->setValue(1012); if(m_nSubMode==1) ui->TxFreqSpinBox->setValue(560); @@ -5280,6 +5301,7 @@ void MainWindow::on_sbSubmode_valueChanged(int n) if(m_bFast9) ui->TxFreqSpinBox->setValue(700); } if(m_transmitting and m_bFast9 and m_nSubMode>=4) transmit(99.0); + statusUpdate (); } void MainWindow::on_cbFast9_clicked(bool b) @@ -5298,6 +5320,7 @@ void MainWindow::on_cbFast9_clicked(bool b) progressBar.setMaximum(m_TRperiod); m_wideGraph->setPeriod(m_TRperiod,m_nsps); fast_config(b); + statusChanged (); } @@ -5412,6 +5435,7 @@ void MainWindow::replayDecodes () { eom_pos = message.size () - 1; } + // TODO - how to skip ISCAT decodes postDecode (false, message.left (eom_pos + 1)); } } @@ -5425,7 +5449,9 @@ void MainWindow::postDecode (bool is_new, QString const& message) auto const& parts = decode.left (22).split (' ', QString::SkipEmptyParts); if (parts.size () >= 5) { - m_messageClient->decode (is_new, QTime::fromString (parts[0], "hhmm"), parts[1].toInt () + m_messageClient->decode (is_new + , QTime::fromString (parts[0], parts[0].size () > 4 ? "hhmmss" : "hhmm") + , parts[1].toInt () , parts[2].toFloat (), parts[3].toUInt (), parts[4][0], decode.mid (22)); } } @@ -5836,13 +5862,15 @@ void MainWindow::on_cbCQTx_toggled(bool b) void MainWindow::statusUpdate () const { if (!ui) return; + auto submode = current_submode (); m_messageClient->status_update (m_freqNominal, m_mode, m_hisCall, QString::number (ui->rptSpinBox->value ()), m_modeTx, ui->autoButton->isChecked (), m_transmitting, m_decoderBusy, ui->RxFreqSpinBox->value (), ui->TxFreqSpinBox->value (), m_config.my_callsign (), m_config.my_grid (), - m_hisGrid, m_tx_watchdog); + m_hisGrid, m_tx_watchdog, + submode != '\0' ? QString {submode} : QString {}, m_bFastMode); } void MainWindow::childEvent (QChildEvent * e) diff --git a/mainwindow.h b/mainwindow.h index c470e5f58..7cecb6d90 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -581,6 +581,8 @@ private: int nWidgets(QString t); void displayWidgets(int n); void vhfWarning(); + QChar current_submode () const; // returns QChar {0} if sub mode is + // not appropriate }; extern int killbyname(const char* progName);