diff --git a/mainwindow.cpp b/mainwindow.cpp index 9b6d6fb..094dee6 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -3208,9 +3208,12 @@ void MainWindow::readFromStdout() //readFromStdout decodedtext.bits() == Varicode::FT8CallLast ); + qDebug() << "frame valid?" << bValidFrame; + qDebug() << "decoded text" << decodedtext.message(); + //Left (Band activity) window if(!bAvgMsg && bValidFrame) { - if(m_mode=="FT8" and m_config.bFox()) { + if(m_mode=="FT8"){ // Parse General Activity #if 1 bool shouldParseGeneralActivity = true; @@ -3300,6 +3303,7 @@ void MainWindow::readFromStdout() //readFromStdout d.snr = decodedtext.snr(); d.utcTimestamp = QDateTime::currentDateTimeUtc(); d.bits = decodedtext.bits(); + d.extra = parts.length() > 2 ? parts.mid(3).join(" ") : ""; // if the command is a buffered command OR we have from or to in a separate message (compound) if(Varicode::isCommandBuffered(d.cmd) || d.from == "<....>" || d.to == "<....>"){ @@ -4302,25 +4306,25 @@ void MainWindow::guiUpdate() m_sec0=nsec; // once per period - if(m_sec0 % m_TRperiod == 0 || (m_sec0 % (m_TRperiod/2)) == 0){ - // force rx dirty at least twice per period - m_rxDirty = true; - m_rxDisplayDirty = true; + bool forceDirty = false; + if(m_sec0 % (m_TRperiod/3) == 0){ + // force rx dirty three times per period + forceDirty = true; } - // once pre second... + // once per second... // update the dial frequency once per second.. displayDialFrequency(); // process all received activity... - processActivity(); + processActivity(forceDirty); // process outgoing tx queue... processTxQueue(); // once processed, lets update the display... - displayActivity(); + displayActivity(forceDirty); } // once per 100ms @@ -5530,24 +5534,27 @@ void MainWindow::clearActivity(){ update_dynamic_property(ui->extFreeTextMsgEdit, "transmitting", false); } -int MainWindow::logRxTxMessageText(QDateTime date, QString text, int freq, bool tx, int block){ +void MainWindow::displayTextForFreq(QString text, int freq, QDateTime date, bool bold, bool newLine, bool clearLine){ + int block = m_rxFrameBlockNumbers.contains(freq) ? m_rxFrameBlockNumbers[freq] : -1; + if(clearLine && block != -1){ + auto c = ui->textEditRX->textCursor(); + QTextBlock b = c.document()->findBlockByNumber(block); + c.setPosition(b.position()); + c.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor); + c.deleteChar(); + c.deleteChar(); + block = -1; + } + if(newLine){ + block = -1; + } + m_rxFrameBlockNumbers[freq] = writeMessageTextToUI(date, text, freq, bold, block); +} + +int MainWindow::writeMessageTextToUI(QDateTime date, QString text, int freq, bool bold, int block){ auto c = ui->textEditRX->textCursor(); -#if ALIAS_COMPOUND_CALLS - // fixup compound callsigns cache / aliases... - // ensure our callsign is cached... - QString myCall = m_config.my_callsign(); - QString baseCall = Radio::base_callsign(myCall); - if(myCall != baseCall && !m_compoundCallCache.contains(baseCall)){ - m_compoundCallCache[baseCall] = myCall; - } - // then, replace the cached calls that we see... - foreach(auto call, m_compoundCallCache.keys()){ - QRegularExpression re(QString(R"((?findBlockByNumber(block); @@ -5556,22 +5563,25 @@ int MainWindow::logRxTxMessageText(QDateTime date, QString text, int freq, bool found = true; } else { c.movePosition(QTextCursor::End); - c.insertBlock(); + if(c.block().length() > 1){ + c.insertBlock(); + } } - if(found && !tx){ + if(found && !bold){ c.clearSelection(); c.insertText(text); } else { text = text.toHtmlEscaped(); - if(tx){ + if(bold){ text = QString("%1").arg(text); - m_rxFrameBlockNumbers.clear(); } c.insertHtml(QString("%1 - (%2) - %3").arg(date.time().toString()).arg(freq).arg(text)); } c.movePosition(QTextCursor::End); + + ui->textEditRX->ensureCursorVisible(); ui->textEditRX->verticalScrollBar()->setValue(ui->textEditRX->verticalScrollBar()->maximum()); @@ -5648,7 +5658,8 @@ void MainWindow::createMessageTransmitQueue(QString const& text){ lines.append(dt.message()); } - logRxTxMessageText(QDateTime::currentDateTimeUtc(), lines.join(""), freq, true); + //logMessageText(QDateTime::currentDateTimeUtc(), lines.join(""), freq, true); + displayTextForFreq(lines.join(""), freq, QDateTime::currentDateTimeUtc(), true, true, false); // keep track of the last message text sent m_lastTxMessage = text; @@ -7203,9 +7214,12 @@ void MainWindow::on_tableWidgetRXAll_cellDoubleClicked(int row, int col){ activityText.append(d.text); } if(!activityText.isEmpty()){ - int block = logRxTxMessageText(firstActivity, activityText, offset, false); - m_rxFrameBlockNumbers[offset/10*10] = block; - m_rxRecentCache.insert(offset/10*10, new QDateTime(QDateTime::currentDateTimeUtc()), 25); + //int block = logMessageText(firstActivity, activityText, offset, false); + + displayTextForFreq(activityText, offset, firstActivity, false, true, false); + + // TODO: jsherer - evaluate recency cache... + // m_rxRecentCache.insert(offset/10*10, new QDateTime(QDateTime::currentDateTimeUtc()), 25); } #if 0 @@ -8216,6 +8230,10 @@ bool MainWindow::isDirectedOffset(int offset){ ); } +void MainWindow::markOffsetDirected(int offset){ + m_rxDirectedCache.insert(offset/10*10, new QDateTime(QDateTime::currentDateTimeUtc()), 25); +} + bool MainWindow::isMyCallIncluded(const QString &text){ QString myCall = Radio::base_callsign(m_config.my_callsign()); @@ -8271,6 +8289,12 @@ void MainWindow::processRxActivity() { bool shouldDisplay = abs(freq - currentFreq()) <= 10; + // if this is a (recent) directed offset, bump the cache, and display... + // this will allow a directed free text command followed by non-buffered data frames. + if(isDirectedOffset(freq)){ + markOffsetDirected(freq); + shouldDisplay = true; + } // TODO: jsherer - develop a better way to determine if we can display this band activity... #if 0 @@ -8285,6 +8309,8 @@ void MainWindow::processRxActivity() { } #endif + + if(!shouldDisplay){ continue; } @@ -8297,12 +8323,15 @@ void MainWindow::processRxActivity() { } // log it to the display! - int block = m_rxFrameBlockNumbers.contains(freq) ? m_rxFrameBlockNumbers[freq] : -1; - m_rxFrameBlockNumbers[freq] = logRxTxMessageText(d.utcTimestamp, d.text, d.freq, false, block); - if (isLast) { - m_rxFrameBlockNumbers.remove(freq); - } - m_rxRecentCache.insert(freq, new QDateTime(QDateTime::currentDateTimeUtc()), 25); + // int block = m_rxFrameBlockNumbers.contains(freq) ? m_rxFrameBlockNumbers[freq] : -1; + // m_rxFrameBlockNumbers[freq] = logMessageText(d.utcTimestamp, d.text, d.freq, false, block); + // if (isLast) { + // m_rxFrameBlockNumbers.remove(freq); + // } + // m_rxRecentCache.insert(freq, new QDateTime(QDateTime::currentDateTimeUtc()), 25); + + displayTextForFreq(d.text, d.freq, d.utcTimestamp, false, false, false); + } } @@ -8401,7 +8430,7 @@ void MainWindow::processBufferedActivity() { bool valid = false; - bool shouldUseLargeChecksum = false; + bool shouldUseLargeChecksum = true; if(shouldUseLargeChecksum && buffer.cmd.cmd == "#"){ checksum = message.right(6); message = message.left(message.length() - 7); @@ -8413,6 +8442,7 @@ void MainWindow::processBufferedActivity() { } if (valid) { + buffer.cmd.bits = Varicode::FT8CallLast; buffer.cmd.text = message; buffer.cmd.isBuffered = true; m_rxCommandQueue.append(buffer.cmd); @@ -8444,7 +8474,7 @@ void MainWindow::processCommandActivity() { int f = currentFreq(); #endif - // TODO: jsherer - should we, if we have _any_ directed messages, pause the beacon?? + // TODO: jsherer - should we, if we have _any_ directed messages, pause the beacon or maybe just bump it? // pauseBacon(); while (!m_rxCommandQueue.isEmpty()) { @@ -8469,26 +8499,15 @@ void MainWindow::processCommandActivity() { continue; } -#if 0 - // TODO: jsherer - check to make sure we haven't replied to their allcall recently (in the past beacon interval) - if (isAllCall && m_txAllcallCommandCache.contains(Radio::base_callsign(d.from)) && m_txAllcallCommandCache[Radio::base_callsign(d.from)]->secsTo(QDateTime::currentDateTimeUtc()) / 60 < m_config.beacon()) { - continue; - } -#endif + // if this is an allcall, check to make sure we haven't replied to their allcall recently (in the past beacon interval) + // that way we never get spammed by allcalls at a high frequency than what we would beacon + if (isAllCall){ + if(m_txAllcallCommandCache.contains(d.from) && m_txAllcallCommandCache[d.from]->secsTo(QDateTime::currentDateTimeUtc()) / 60 < m_config.beacon()) { + continue; + } -#if 0 - if(d.isCompound){ - // this is a command with a compound call... we need to log it to the rx activity! - ActivityDetail ad; - ad.bits = d.bits; - ad.freq = d.freq; - ad.isDirected = true; - ad.snr = d.snr; - ad.text = QString("%1: %2%3 %4 %5 ").arg(d.from).arg(d.to).arg(d.cmd).arg(d.grid).arg(d.text); - ad.utcTimestamp = d.utcTimestamp; - m_bandActivity[d.freq].append(ad); + m_txAllcallCommandCache.insert(d.from, new QDateTime(QDateTime::currentDateTimeUtc()), 25); } -#endif // log call activity... CallDetail cd; @@ -8500,6 +8519,37 @@ void MainWindow::processCommandActivity() { cd.utcTimestamp = d.utcTimestamp; logCallActivity(cd, true); + // display the command activity + ActivityDetail ad; + ad.isLowConfidence = false; + ad.isFree = true; + ad.isDirected = true; + ad.bits = d.bits; + ad.freq = d.freq; + ad.snr = d.snr; + ad.text = QString("%1: %2%3 ").arg(d.from).arg(d.to).arg(d.cmd); + if(!d.grid.isEmpty()){ + ad.text += d.grid; + } + if(!d.extra.isEmpty()){ + ad.text += d.extra; + } + if(!d.text.isEmpty()){ + ad.text += d.text; + } + bool isLast = ad.bits == Varicode::FT8CallLast; + if (isLast) { + // can also use \u0004 \u2666 \u2404 + ad.text += QString(" \u2301 "); + } + ad.utcTimestamp = d.utcTimestamp; + + // log it to the display! + displayTextForFreq(ad.text, ad.freq, ad.utcTimestamp, false, true, true); + + // and mark the offset as a directed offset so future free text is displayed + markOffsetDirected(ad.freq); + // construct a reply, if needed QString reply; @@ -8588,7 +8638,7 @@ void MainWindow::processCommandActivity() { return; } - enqueueMessage(PriorityNormal, QString("%1 ACK").arg(d.from), d.freq, nullptr); + enqueueMessage(PriorityHigh, QString("%1 ACK").arg(d.from), d.freq, nullptr); }); msgBox->show(); @@ -8604,22 +8654,6 @@ void MainWindow::processCommandActivity() { // queue the reply here to be sent when a free interval is available enqueueMessage(PriorityNormal, reply, d.freq, nullptr); - -#if 0 - addMessageText(reply); - - // use the last frequency - f = d.freq; - - // if we're responding via allcall, pick a different frequency and mark it in the cache. - if (isAllCallIncluded(d.to)) { - f = findFreeFreqOffset(qMax(0, f - 100), qMin(f + 100, 2500), 50); - m_txAllcallCommandCache.insert(Radio::base_callsign(d.from), new QDateTime(QDateTime::currentDateTimeUtc()), 25); - } - - processed = true; -#endif - } } @@ -8694,7 +8728,10 @@ void MainWindow::processTxQueue(){ addMessageText(message.message, true); // check to see if we have autoreply enabled...(or if this is a beacon and the beacon button is enabled) - if(ui->autoReplyButton->isChecked() || (ui->beaconButton->isChecked() && message.message.contains("BEACON"))){ + if(message.priority >= PriorityHigh || + (ui->autoReplyButton->isChecked()) || + (ui->beaconButton->isChecked() && message.message.contains("BEACON")) + ){ // then try to set the frequency... setFreqForRestore(f, true); diff --git a/mainwindow.h b/mainwindow.h index 7cce6ce..d5647ec 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -131,7 +131,8 @@ public slots: void logCallActivity(CallDetail d, bool spot=true); QString lookupCallInCompoundCache(QString const &call); void clearActivity(); - int logRxTxMessageText(QDateTime date, QString text, int freq, bool tx, int block=-1); + void displayTextForFreq(QString text, int freq, QDateTime date, bool bold, bool newLine, bool clearLine); + int writeMessageTextToUI(QDateTime date, QString text, int freq, bool bold, int block=-1); void addMessageText(QString text, bool clear=false); void enqueueMessage(int priority, QString message, int freq, Callback c); void resetMessage(); @@ -661,6 +662,7 @@ private: int bits; QString grid; QString text; + QString extra; }; struct ActivityDetail @@ -819,6 +821,7 @@ private: QString callsignSelected(); bool isRecentOffset(int offset); bool isDirectedOffset(int offset); + void markOffsetDirected(int offset); void processActivity(bool force=false); void processRxActivity(); void processCompoundActivity();