From a96216e2f8517c1c35205a22f4aa0f868b2e7f60 Mon Sep 17 00:00:00 2001 From: Jordan Sherer Date: Fri, 13 Jul 2018 10:32:58 -0400 Subject: [PATCH] Refactored directed code into decoded text so the rest of the app can use it as is. --- decodedtext.cpp | 18 +++++++ decodedtext.h | 23 +++++---- mainwindow.cpp | 121 +++++++++++++++++++++++++++++++++++------------- mainwindow.h | 3 +- varicode.cpp | 4 +- 5 files changed, 126 insertions(+), 43 deletions(-) diff --git a/decodedtext.cpp b/decodedtext.cpp index ea72032..7bb41fa 100644 --- a/decodedtext.cpp +++ b/decodedtext.cpp @@ -4,6 +4,8 @@ #include #include +#include + extern "C" { bool stdmsg_(char const * msg, bool contest_mode, char const * mygrid, fortran_charlen_t, fortran_charlen_t); } @@ -51,6 +53,22 @@ DecodedText::DecodedText (QString const& the_string, bool contest_mode, QString , grid_c_string.constData () , 22, 6); } + + if(!is_standard_){ + tryUnpackDirected(); + } +} + +void DecodedText::tryUnpackDirected(){ + QStringList parts = Varicode::unpackDirectedMessage(message()); + + if(parts.isEmpty()){ + return; + } + + // replace it with the correct unpacked + message_ = QString("%1:%2%3").arg(parts.at(0), parts.at(1), parts.at(2)); + directed_ = parts; } QStringList DecodedText::messageWords () const diff --git a/decodedtext.h b/decodedtext.h index 6aca30e..f41aaec 100644 --- a/decodedtext.h +++ b/decodedtext.h @@ -10,6 +10,7 @@ #define DECODEDTEXT_H #include +#include @@ -31,15 +32,20 @@ class DecodedText public: explicit DecodedText (QString const& message, bool, QString const& my_grid); - QString string() const { return string_; }; - QString message() const { return message_; }; - QStringList messageWords () const; - int indexOf(QString s) const { return string_.indexOf(s); }; - int indexOf(QString s, int i) const { return string_.indexOf(s,i); }; - QString mid(int f, int t) const { return string_.mid(f,t); }; - QString left(int i) const { return string_.left(i); }; + void tryUnpackDirected(); - void clear() { string_.clear(); }; + QStringList directedMessage() const { return directed_; } + bool isDirectedMessage() const { return !directed_.isEmpty(); } + + QString string() const { return string_; } + QString message() const { return message_; } + QStringList messageWords () const; + int indexOf(QString s) const { return string_.indexOf(s); } + int indexOf(QString s, int i) const { return string_.indexOf(s,i); } + QString mid(int f, int t) const { return string_.mid(f,t); } + QString left(int i) const { return string_.left(i); } + + void clear() { string_.clear(); } QString CQersCall() const; @@ -78,6 +84,7 @@ private: column_mode = 19, column_qsoText = 22 }; + QStringList directed_; QString string_; int padding_; bool contest_mode_; diff --git a/mainwindow.cpp b/mainwindow.cpp index 01a186b..d3b7029 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -2030,6 +2030,7 @@ void MainWindow::keyPressEvent (QKeyEvent * e) foxTest(); return; } + break; case Qt::Key_E: if(e->modifiers() & Qt::ShiftModifier) { ui->txFirstCheckBox->setChecked(false); @@ -3150,9 +3151,12 @@ void MainWindow::readFromStdout() //readFromStdout d.firstCall = decodedtext.CQersCall(); if(d.firstCall.isEmpty()){ auto words = decodedtext.messageWords(); - if(words.length() > 1){ + if(words.length() == 2){ d.firstCall = words.at(0); d.secondCall = words.at(1); + } else if(words.length() == 3){ + d.firstCall = words.at(1); + d.secondCall = words.at(2); } } @@ -3161,6 +3165,7 @@ void MainWindow::readFromStdout() //readFromStdout d.utcTimestamp = QDateTime::currentDateTimeUtc(); d.snr = decodedtext.snr(); m_bandActivity[offset].append(d); + while(m_bandActivity[offset].count() > 10){ m_bandActivity[offset].removeFirst(); } @@ -3234,36 +3239,26 @@ void MainWindow::readFromStdout() //readFromStdout // TOD0: jsherer - parse for commands? // KN4CRD K1JT ? - bool shouldParseDirected = false; - if(shouldParseDirected){ - // can this be decoded as a directed message? - if(!decodedtext.isStandardMessage()){ - QStringList parts = Varicode::unpackDirectedMessage(decodedtext.message()); + bool shouldProcessDirected = true; + if(shouldProcessDirected && decodedtext.isDirectedMessage()){ + auto parts = decodedtext.directedMessage(); - if(!parts.isEmpty()){ - if(parts.at(1) == m_config.my_callsign()){ - CommandDetail d; - d.call = parts.at(0); - d.command = parts.at(2); - d.freq = decodedtext.frequencyOffset(); - d.snr = decodedtext.snr(); - d.utcTimestamp = QDateTime::currentDateTimeUtc(); - m_rxCommandQueue.append(d); + CommandDetail d; + d.from = parts.at(0); + d.to = parts.at(1); + d.command = parts.at(2); + d.freq = decodedtext.frequencyOffset(); + d.snr = decodedtext.snr(); + d.utcTimestamp = QDateTime::currentDateTimeUtc(); + m_rxCommandQueue.append(d); - // TODO: jsherer - don't hardcode this here... - if(m_txFrameQueue.isEmpty() && QDateTime::currentDateTimeUtc().secsTo(m_nextBeacon) > 0){ - QString text = QString("%1 %2 %3").arg(d.call.trimmed()).arg(m_config.my_callsign().trimmed()).arg(d.snr); - - setFreq4(d.freq, d.freq); - m_bandActivity[decodedtext.frequencyOffset()].last().text = QString("%1:%2%3").arg(d.call.trimmed()).arg(m_config.my_callsign()).arg(d.command); - m_rxDirectedCache.insert(decodedtext.frequencyOffset()/10*10, new QDateTime(QDateTime::currentDateTimeUtc()), 25); - - ui->extFreeTextMsgEdit->setPlainText(text); - ui->startTxButton->setChecked(true); - } - } - } - } + CallDetail cd; + cd.call = d.from; + cd.grid = ""; + cd.snr = decodedtext.snr(); + cd.freq = decodedtext.frequencyOffset(); + cd.utcTimestamp = d.utcTimestamp; + m_callActivity[cd.call] = cd; } } } @@ -4059,11 +4054,13 @@ void MainWindow::guiUpdate() m_rxDirty = true; } + // once per second displayDialFrequency (); displayActivity(); } + // once per 100ms displayTransmit(); m_iptt0=g_iptt; @@ -5234,7 +5231,7 @@ void MainWindow::clearActivity(){ m_rxDirectedCache.clear(); m_rxFrameBlockNumbers.clear(); m_rxFrameQueue.clear(); - + m_rxCommandQueue.clear(); clearTableWidget(ui->tableWidgetCalls); clearTableWidget(ui->tableWidgetRXAll); @@ -5545,7 +5542,7 @@ void MainWindow::scheduleBeacon(bool first){ timestamp = timestamp.addSecs(delta); // 25% of the time, switch intervals - float prob = (float) qrand() / (RAND_MAX+1); + float prob = (float) qrand() / (RAND_MAX); if(prob < 0.25){ timestamp = timestamp.addSecs(15); } @@ -5580,7 +5577,9 @@ void MainWindow::prepareBeacon(){ QString message = QString("DE %1 %2\nDE %1 %2").arg(m_config.my_callsign()).arg(m_config.my_grid().mid(0, 4)); - ui->extFreeTextMsgEdit->setPlainText(message); + //ui->extFreeTextMsgEdit->setPlainText(message); + + addMessageText(message); ui->startTxButton->setChecked(true); scheduleBeacon(); @@ -7947,6 +7946,64 @@ void MainWindow::displayActivity(){ block = logRxTxMessageText(d.utcTimestamp, d.isFree, d.text, d.freq, false, block); m_rxFrameBlockNumbers[freq] = block; } + +#if 0 + // Directed Activity + // TODO: jsherer - don't hardcode this here... + if(m_txFrameQueue.isEmpty() && QDateTime::currentDateTimeUtc().secsTo(m_nextBeacon) > 0){ + // construct a reply + QString text = QString("%1 %2 %3").arg(d.call.trimmed()).arg(m_config.my_callsign().trimmed()).arg(d.snr); + + setFreq4(d.freq, d.freq); + m_bandActivity[decodedtext.frequencyOffset()].last().text = QString("%1:%2%3").arg(d.call.trimmed()).arg(m_config.my_callsign()).arg(d.command); + m_rxDirectedCache.insert(decodedtext.frequencyOffset()/10*10, new QDateTime(QDateTime::currentDateTimeUtc()), 25); + + ui->extFreeTextMsgEdit->setPlainText(text); + ui->startTxButton->setChecked(true); + } +#endif + + if(m_txFrameQueue.isEmpty()){ + int f; + + while(!m_rxCommandQueue.isEmpty()){ + auto d = m_rxCommandQueue.head(); + m_rxCommandQueue.pop_front(); + + qDebug() << "processing command" << d.from << d.to << d.command; + + // we're only processing queries at this point + if(d.command != "?"){ + continue; + } + + // we're only processing allcall and our callsign at this point + if(d.to != "ALLCALL" && d.to != m_config.my_callsign().trimmed()){ + continue; + } + + // TODO: jsherer - check to make sure we haven't replied to their allcall recently + + + // construct reply + auto reply = QString("%1 %2 %3").arg(d.from).arg(d.to).arg(d.snr); + addMessageText(reply); + + // use the last frequency + f = d.freq; + + // if we're responding via allcall, pick a different frequency. + if(d.to == "ALLCALL"){ + f = findFreeFreqOffset(qMax(0, f-100), qMin(f+100, 2500), 50); + } + } + + // if we have beacon turned on, and it's more than 15 seconds away, automatically reply now + if(QDateTime::currentDateTimeUtc().secsTo(m_nextBeacon) > 15){ + setFreq4(f, f); + ui->startTxButton->setChecked(true); + } + } } void MainWindow::postWSPRDecode (bool is_new, QStringList parts) diff --git a/mainwindow.h b/mainwindow.h index 1a21c2c..afeeb2d 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -643,7 +643,8 @@ private: struct CommandDetail { - QString call; + QString from; + QString to; QString command; int freq; QDateTime utcTimestamp; diff --git a/varicode.cpp b/varicode.cpp index ecedd1b..8ffe194 100644 --- a/varicode.cpp +++ b/varicode.cpp @@ -402,8 +402,8 @@ QStringList Varicode::unpackDirectedMessage(const QString &text){ quint32 packed_to = Varicode::bitsToInt(Varicode::strToBits(bits.mid(31, 28))); quint8 packed_cmd = Varicode::bitsToInt(Varicode::strToBits(bits.mid(59, 5))); - unpacked.append(Varicode::unpackCallsign(packed_from)); - unpacked.append(Varicode::unpackCallsign(packed_to)); + unpacked.append(Varicode::unpackCallsign(packed_from).trimmed()); + unpacked.append(Varicode::unpackCallsign(packed_to).trimmed()); unpacked.append(QString(cmds.at(packed_cmd & 7))); return unpacked;