From 95b7d8106a9898dfa2d2752699c56787b54dbb30 Mon Sep 17 00:00:00 2001 From: Chipster Date: Wed, 4 Nov 2026 12:31:36 -0600 Subject: [PATCH] Add a qso-info MQTT topic for modems with their own screen A modem with its own screen, such as the DVMEGA CAST, shows who is talking from QSO information frames (0x91). Since the display moved out of MMDVM-Host nothing sends them, so the screen stays blank. A message on the new qso-info topic is written to the modem as a QSO information frame, its body as given (mode byte first), so a display program can drive that screen. The frame is queued with the serial data, so it is written from the modem's own thread. --- MMDVM-Host.cpp | 10 ++++++++++ MMDVM-Host.h | 1 + Modem.cpp | 25 +++++++++++++++++++++++++ Modem.h | 1 + 4 files changed, 37 insertions(+) diff --git a/MMDVM-Host.cpp b/MMDVM-Host.cpp index e23a4b11..f0684129 100644 --- a/MMDVM-Host.cpp +++ b/MMDVM-Host.cpp @@ -340,6 +340,7 @@ int CMMDVMHost::run() std::vector> subscriptions; subscriptions.push_back(std::make_pair("display-in", CMMDVMHost::onDisplay)); + subscriptions.push_back(std::make_pair("qso-info", CMMDVMHost::onQSOInfo)); if (m_conf.getRemoteControlEnabled()) subscriptions.push_back(std::make_pair("command", CMMDVMHost::onCommand)); @@ -3221,3 +3222,12 @@ void CMMDVMHost::onDisplay(const unsigned char* message, unsigned int length) host->writeSerial(message, length); } + +void CMMDVMHost::onQSOInfo(const unsigned char* message, unsigned int length) +{ + assert(host != nullptr); + assert(message != nullptr); + + if (host->m_modem != nullptr) + host->m_modem->writeQSOInfo(message, length); +} diff --git a/MMDVM-Host.h b/MMDVM-Host.h index b7bbb87c..b4382f91 100644 --- a/MMDVM-Host.h +++ b/MMDVM-Host.h @@ -213,6 +213,7 @@ class CMMDVMHost void writeJSONMessage(const std::string& message); static void onDisplay(const unsigned char* message, unsigned int length); + static void onQSOInfo(const unsigned char* message, unsigned int length); static void onCommand(const unsigned char* command, unsigned int length); }; diff --git a/Modem.cpp b/Modem.cpp index 68510da5..63fb87d3 100644 --- a/Modem.cpp +++ b/Modem.cpp @@ -1943,6 +1943,31 @@ bool CModem::writeSerialData(const unsigned char* data, unsigned int length) return true; } +// A QSO information frame built by the caller (mode byte first), for a +// modem with its own screen such as the DVMega CAST. Queued with the +// serial data so it is written from the modem's own thread. +bool CModem::writeQSOInfo(const unsigned char* data, unsigned int length) +{ + assert(data != nullptr); + + if (length == 0U || length > 250U) + return false; + + unsigned char buffer[255U]; + + buffer[0U] = MMDVM_FRAME_START; + buffer[1U] = length + 3U; + buffer[2U] = MMDVM_QSO_INFO; + + ::memcpy(buffer + 3U, data, length); + + unsigned char len = length + 3U; + m_txSerialData.addData(&len, 1U); + m_txSerialData.addData(buffer, len); + + return true; +} + bool CModem::hasTX() const { return m_tx; diff --git a/Modem.h b/Modem.h index 251b850e..0b882a84 100644 --- a/Modem.h +++ b/Modem.h @@ -192,6 +192,7 @@ class CModem { unsigned int readTransparentData(unsigned char* data); bool writeSerialData(const unsigned char* data, unsigned int length); + bool writeQSOInfo(const unsigned char* data, unsigned int length); unsigned int readSerialData(unsigned char* data); unsigned char getMode() const;