Add fast mode support to UDP messages and update example apllications

Sub mode and  fast mode flag are  added to the UDP  Status message and
Status messages  after appropriate UI changes.  MSK144 decodes produce
UDP Decode messages. Fast JT9 messages are treated similarly.

Currently ISCAT decodes are not posted  as UDP Decode messages as they
do not fit well with the model.

git-svn-id: svn+ssh://svn.code.sf.net/p/wsjt/wsjt/branches/wsjtx@7389 ab8295b8-cf94-4d9e-aec4-7959e3be5d79
This commit is contained in:
Bill Somerville 2016-12-16 19:36:21 +00:00
parent f7935361b3
commit 336eb0c858
13 changed files with 99 additions and 38 deletions

View File

@ -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);
}
}

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -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),

View File

@ -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)

View File

@ -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_;

View File

@ -22,9 +22,10 @@ namespace
QFont text_font {"Courier", 10};
QList<QStandardItem *> 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)

View File

@ -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);

View File

@ -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);

View File

@ -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

View File

@ -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)

View File

@ -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);