From 565f4d93217a798a3c962437678ad76ccd540801 Mon Sep 17 00:00:00 2001 From: Jordan Sherer Date: Sun, 29 Jul 2018 10:39:58 -0400 Subject: [PATCH] Starting compound call refactoring --- decodedtext.cpp | 37 ++++++++++++++++---------- decodedtext.h | 2 +- mainwindow.cpp | 71 +++++++++++++++++++++++++++++++++++-------------- varicode.cpp | 39 +++++++++++++++++++++------ varicode.h | 8 +++--- 5 files changed, 110 insertions(+), 47 deletions(-) diff --git a/decodedtext.cpp b/decodedtext.cpp index e98e4a7..4a4c9e5 100644 --- a/decodedtext.cpp +++ b/decodedtext.cpp @@ -76,7 +76,7 @@ bool DecodedText::tryUnpack(){ bool unpacked = false; if(!unpacked){ - unpacked = tryUnpackCompound(); + unpacked = tryUnpackBeacon(); } if(!unpacked){ @@ -90,23 +90,32 @@ bool DecodedText::tryUnpack(){ return unpacked; } -bool DecodedText::tryUnpackCompound(){ - QString m = message().trimmed(); +bool DecodedText::tryUnpackBeacon(){ + QString m = message().trimmed(); - // directed calls will always be 12+ chars and contain no spaces. - if(m.length() < 12 || m.contains(' ')){ - return false; - } + // directed calls will always be 12+ chars and contain no spaces. + if(m.length() < 12 || m.contains(' ')){ + return false; + } - QStringList parts = Varicode::unpackCompoundMessage(m, nullptr); + bool isBCN = false; + QStringList parts = Varicode::unpackBeaconMessage(m, &isBCN); - if(parts.isEmpty() || parts.length() < 2){ - return false; - } + if(parts.isEmpty() || parts.length() < 2){ + return false; + } - compound_ = QString("%1/%2").arg(parts.at(0), parts.at(1)); - message_ = QString("%1: ").arg(compound_); - return true; + auto extra = parts.at(2); + + compound_ = QStringList{ parts.at(0), parts.at(1) }.join("/"); + + if(isBCN){ + message_ = QString("%1: BCN %2 ").arg(compound_).arg(extra); + } else { + message_ = QString("%1: ").arg(compound_); + } + + return true; } bool DecodedText::tryUnpackDirected(){ diff --git a/decodedtext.h b/decodedtext.h index f1c8746..33c3d01 100644 --- a/decodedtext.h +++ b/decodedtext.h @@ -34,7 +34,7 @@ public: explicit DecodedText (QString const& ft8callmessage); bool tryUnpack(); - bool tryUnpackCompound(); + bool tryUnpackBeacon(); bool tryUnpackDirected(); bool tryUnpackData(); diff --git a/mainwindow.cpp b/mainwindow.cpp index efa94d9..27ebe8e 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -3454,7 +3454,7 @@ void MainWindow::readFromStdout() //readFromStdout CallDetail cd; cd.call = compoundCall; - cd.grid = ""; + cd.grid = ""; // compound calls via beacons contain grid... cd.snr = decodedtext.snr(); cd.freq = decodedtext.frequencyOffset(); cd.utcTimestamp = QDateTime::currentDateTimeUtc(); @@ -5776,6 +5776,7 @@ QPair MainWindow::buildFT8MessageFrames(QString const& // prepare compound bool compoundSent = false; bool compound = Radio::is_compound_callsign(m_config.my_callsign()); + QString mygrid = m_config.my_grid(); QString mycall = m_config.my_callsign(); QString basecall = Radio::base_callsign(m_config.my_callsign()); QString fix = QString(m_config.my_callsign()).replace(basecall, ""); @@ -5787,15 +5788,27 @@ QPair MainWindow::buildFT8MessageFrames(QString const& // once we find a directed call, data encode the rest of the line. bool hasDirected = false; + // remove our callsign from the start of the line... + if(line.startsWith(mycall + ":")){ + line = lstrip(line.mid(mycall.length() + 1)); + } + if(line.startsWith(basecall + ":")){ + line = lstrip(line.mid(basecall.length() + 1)); + } + while(line.size() > 0){ QString frame; bool useStd = false; + bool useBcn = false; bool useDir = false; bool useDat = false; bool isFree = false; QString stdFrame = parseFT8Message(line, &isFree); + int l = 0; + QString bcnFrame = Varicode::packBeaconMessage(line, mycall, &l); + int n = 0; QString dirCmd; QString dirFrame = Varicode::packDirectedMessage(line, basecall, &dirCmd, &n); @@ -5807,12 +5820,21 @@ QPair MainWindow::buildFT8MessageFrames(QString const& // if this parses to a standard FT8 free text message // but it can be parsed as a directed message, then we - // should send the directed version - if(isFree && !hasDirected && n > 0){ + // should send the directed version. if we've already sent + // a directed message, we won't send any more but instead + // send it as a data message + + if(isFree && !hasDirected && l > 0){ + useBcn = true; + hasDirected = false; + frame = bcnFrame; + } + else if(isFree && !hasDirected && n > 0){ useDir = true; hasDirected = true; frame = dirFrame; - } else if ((isFree || hasDirected) && m > 0) { + } + else if ((isFree || hasDirected) && m > 0) { useDat = true; frame = datFrame; if(!datLineOut.isEmpty()){ @@ -5840,14 +5862,20 @@ QPair MainWindow::buildFT8MessageFrames(QString const& line = line.mid(frame.length()).trimmed(); } + if(useBcn){ + frames.append(frame); + lines.append(QString("%1: ").arg(mycall) + line.left(l) + " "); + line = line.mid(l); + } + if(useDir){ if(compound && !compoundSent){ - QString compoundFrame = Varicode::packCompoundMessage(basecall, fix, prefix, 0); - if(!compoundFrame.isEmpty()){ - frames.append(compoundFrame); - lines.append(QString("%1: ").arg(mycall)); - compoundSent = true; - } + QString compoundMessage = QString("DE %1").arg(mygrid); + QString beaconFrame = Varicode::packBeaconMessage(compoundMessage, mycall, nullptr); + if(!beaconFrame.isEmpty()){ + frames.append(beaconFrame); + lines.append(QString("%1: ").arg(mycall)); + } } frames.append(frame); @@ -5881,7 +5909,7 @@ QPair MainWindow::buildFT8MessageFrames(QString const& #if 1 qDebug() << "parsed frames:"; foreach(auto frame, frames){ - qDebug() << "->" << frame << Varicode::unpackDataMessage(frame) << Varicode::unpackDirectedMessage(frame) << Varicode::unpackCompoundMessage(frame, nullptr); + qDebug() << "->" << frame << Varicode::unpackDataMessage(frame) << Varicode::unpackDirectedMessage(frame) << Varicode::unpackCompoundFrame(frame, nullptr) << Varicode::unpackBeaconMessage(frame, nullptr); } qDebug() << "lines:"; @@ -6108,8 +6136,11 @@ void MainWindow::prepareBacon(){ beacon = QString("DE %1").arg(call).arg(grid); } + // FT8 Style lines.append(beacon); - lines.append(beacon); + + // FT8Call Style + lines.append(QString("%1: BCN %2").arg(call).arg(grid)); #if 0 if(!m_callActivity.isEmpty()){ @@ -8793,6 +8824,9 @@ void MainWindow::displayActivity(bool force){ } } + // Grouped Compound Activity + // TODO: jsherer - group compound callsign and directed commands together. + // Buffered Activity foreach(auto freq, m_messageBuffer.keys()){ auto buffer = m_messageBuffer[freq]; @@ -8866,7 +8900,7 @@ void MainWindow::displayActivity(bool force){ // QUERIED SNR if(d.cmd == "?"){ - reply = QString("%1 SNR %2").arg(Radio::base_callsign(d.from)).arg(Varicode::formatSNR(d.snr)); + reply = QString("%1 SNR %2").arg(d.from).arg(Varicode::formatSNR(d.snr)); } // QUERIED ACK //else if(d.cmd == "#"){ @@ -8874,7 +8908,7 @@ void MainWindow::displayActivity(bool force){ //} // QUERIED PWR else if(d.cmd == "%" && !isAllCall && m_config.my_dBm() >= 0){ - reply = QString("%1 PWR %2").arg(Radio::base_callsign(d.from)).arg(Varicode::formatPWR(m_config.my_dBm())); + reply = QString("%1 PWR %2").arg(d.from).arg(Varicode::formatPWR(m_config.my_dBm())); } // QUERIED QTH else if(d.cmd == "@" && !isAllCall){ @@ -8887,11 +8921,11 @@ void MainWindow::displayActivity(bool force){ qth = grid; } - reply = QString("%1 %2").arg(Radio::base_callsign(d.from)).arg(qth); + reply = QString("%1 %2").arg(d.from).arg(qth); } // QUERIED STATION MESSAGE else if(d.cmd == "&" && !isAllCall){ - reply = QString("%1 %2").arg(Radio::base_callsign(d.from)).arg(m_config.my_station()); + reply = QString("%1 %2").arg(d.from).arg(m_config.my_station()); } // QUERIED STATIONS HEARD else if(d.cmd == "$" && !isAllCall){ @@ -8909,12 +8943,9 @@ void MainWindow::displayActivity(bool force){ if(i >= maxStations){ break; } - if(Radio::base_callsign(call) == Radio::base_callsign(m_config.my_callsign())){ - continue; - } auto d = m_callActivity[call]; - lines.append(QString("%1 SNR %2").arg(Radio::base_callsign(call)).arg(Varicode::formatSNR(d.snr))); + lines.append(QString("%1 SNR %2").arg(d.call).arg(Varicode::formatSNR(d.snr))); i++; } reply = lines.join('\n'); diff --git a/varicode.cpp b/varicode.cpp index 0ad9e99..a024ab9 100644 --- a/varicode.cpp +++ b/varicode.cpp @@ -52,6 +52,7 @@ QMap directed_cmds = { // {"/", 9 }, // unused? (can we even use stroke?) // directed responses + {" BCN", 22 }, // beacon {" ACK", 23 }, // acknowledged {" PWR", 24 }, // power level {" SNR", 25 }, // seen a station at the provided snr @@ -805,11 +806,26 @@ bool Varicode::isCommandBuffered(const QString &cmd){ return directed_cmds.contains(cmd) && buffered_cmds.contains(directed_cmds[cmd]); } -QString Varicode::packBeaconMessage(QString const &callsign, QString const &extra, bool isCQ){ +QString Varicode::packBeaconMessage(QString const &text, const QString &callsign, int *n){ QString frame; + auto parsedText = QRegularExpression(R"(^(?BCN|DE)\s(?[A-Z]{2}[0-9]{2})\b)").match(text); + if(!parsedText.hasMatch()){ + if(n) *n = 0; + return frame; + } + + auto extra = parsedText.captured("grid"); + if(extra.isEmpty()){ + if(n) *n = 0; + return frame; + } + + auto isBCN = parsedText.captured("type") == "BCN"; + auto parsedCall = QRegularExpression(compound_callsign_pattern).match(callsign); if(!parsedCall.hasMatch()){ + if(n) *n = 0; return frame; } @@ -830,26 +846,33 @@ QString Varicode::packBeaconMessage(QString const &callsign, QString const &extr packed_extra = Varicode::packGrid(extra); } - if(isCQ){ + if(isBCN){ packed_extra |= (1<<15); } - return packCompoundMessage(base, fix, isPrefix, packed_extra); + frame = packCompoundFrame(base, fix, isPrefix, packed_extra); + if(frame.isEmpty()){ + if(n) *n = 0; + return frame; + } + + if(n) *n = parsedText.captured(0).length(); + return frame; } -QStringList Varicode::unpackBeaconMessage(const QString &text, bool * isCQ){ +QStringList Varicode::unpackBeaconMessage(const QString &text, bool * isBCN){ quint16 num = 0; - QStringList unpacked = unpackCompoundMessage(text, &num); + QStringList unpacked = unpackCompoundFrame(text, &num); - if(isCQ) *isCQ = (num & (1<<15)); + if(isBCN) *isBCN = (num & (1<<15)); unpacked.append(Varicode::unpackGrid(num & ((1<<15)-1))); return unpacked; } -QString Varicode::packCompoundMessage(const QString &baseCallsign, const QString &fix, bool isPrefix, quint16 num){ +QString Varicode::packCompoundFrame(const QString &baseCallsign, const QString &fix, bool isPrefix, quint16 num){ QString frame; quint8 packed_is_data = 0; @@ -881,7 +904,7 @@ QString Varicode::packCompoundMessage(const QString &baseCallsign, const QString return Varicode::pack64bits(Varicode::bitsToInt(bits)) + Varicode::pack5bits(packed_5 % 32); } -QStringList Varicode::unpackCompoundMessage(const QString &text, quint16 *pNum){ +QStringList Varicode::unpackCompoundFrame(const QString &text, quint16 *pNum){ QStringList unpacked; if(text.length() < 13 || text.contains(" ")){ diff --git a/varicode.h b/varicode.h index ff65f29..1594537 100644 --- a/varicode.h +++ b/varicode.h @@ -83,11 +83,11 @@ public: static bool isCommandAllowed(const QString &cmd); static bool isCommandBuffered(const QString &cmd); - static QString packBeaconMessage(QString const &callsign, QString const &extra, bool isCQ); - static QStringList unpackBeaconMessage(const QString &text, bool *isCQ); + static QString packBeaconMessage(QString const &text, QString const&callsign, int *n); + static QStringList unpackBeaconMessage(const QString &text, bool *isBCN); - static QString packCompoundMessage(const QString &baseCallsign, const QString &fix, bool isPrefix, quint16 num); - static QStringList unpackCompoundMessage(const QString &text, quint16 *pNum); + static QString packCompoundFrame(const QString &baseCallsign, const QString &fix, bool isPrefix, quint16 num); + static QStringList unpackCompoundFrame(const QString &text, quint16 *pNum); static QString packDirectedMessage(QString const& text, QString const& callsign, QString * pCmd, int *n); static QStringList unpackDirectedMessage(QString const& text);