From 8f33bad363bed4579e073d2554b0f5884f81f25e Mon Sep 17 00:00:00 2001 From: f4exb Date: Thu, 28 Mar 2024 22:12:27 +0100 Subject: [PATCH 1/6] Fix MXVC boost multiprecision issue --- ft8/packing.cpp | 9 +++++++++ ft8/packing.h | 1 + sdrbench/test_ft8protocols.cpp | 9 +-------- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/ft8/packing.cpp b/ft8/packing.cpp index dfa8c427b..aa5eac1aa 100644 --- a/ft8/packing.cpp +++ b/ft8/packing.cpp @@ -934,4 +934,13 @@ bool Packing::packfree(int a77[], const std::string& msg) return true; } +void Packing::pack1(int a77[], int c28_1, int c28_2, int g15, int report) +{ + pa64(a77, 0, 28, c28_1); + pa64(a77, 28+1, 28, c28_2); + a77[28+1+28+1] = report; + pa64(a77, 28+1+28+2, 15, g15); + pa64(a77, 28+1+28+2+15, 3, 1); +} + } // namespace FT8 diff --git a/ft8/packing.h b/ft8/packing.h index 0659d1949..c3caa9775 100644 --- a/ft8/packing.h +++ b/ft8/packing.h @@ -40,6 +40,7 @@ public: static bool packcall_std(int& c28, const std::string& callstr); static bool packgrid(int& g15, const std::string& locstr); static bool packfree(int a77[], const std::string& msg); + static void pack1(int a77[], int c28_1, int c28_2, int g15, int report); private: static int ihashcall(std::string call, int m); diff --git a/sdrbench/test_ft8protocols.cpp b/sdrbench/test_ft8protocols.cpp index 654336a19..075338d98 100644 --- a/sdrbench/test_ft8protocols.cpp +++ b/sdrbench/test_ft8protocols.cpp @@ -34,7 +34,6 @@ void MainBench::testFT8(const QString& wavFile, const QString& argsStr) #include "ft8/ft8.h" #include "ft8/packing.h" -#include "ft8/pack0.h" class TestFT8Protocols { @@ -122,13 +121,7 @@ void TestFT8Protocols::testMsg1(const QStringList& argElements, bool runLDPC) int a77[77]; std::fill(a77, a77 + 77, 0); - - FT8::pa64(a77, 0, 28, c28_1); - FT8::pa64(a77, 28+1, 28, c28_2); - a77[28+1+28+1] = report; - FT8::pa64(a77, 28+1+28+2, 15, g15); - FT8::pa64(a77, 28+1+28+2+15, 3, 1); - + FT8::Packing::pack1(a77, c28_1, c28_2, g15, report); FT8::Packing packing; std::string call1, call2, loc; From eef0084a6e6d60b22c3396ecef3cdde918c4d0c4 Mon Sep 17 00:00:00 2001 From: mxi-box Date: Sat, 30 Mar 2024 12:10:21 +0800 Subject: [PATCH 2/6] Make AudioDeviceInfo singleton, remove the ones in AudioDeviceManager --- .../samplesource/audioinput/audioinputgui.cpp | 3 +- sdrbase/audio/audiodeviceinfo.cpp | 84 +++++++++++-------- sdrbase/audio/audiodeviceinfo.h | 8 +- sdrbase/audio/audiodevicemanager.cpp | 50 +++++------ sdrbase/audio/audiodevicemanager.h | 6 -- sdrbase/audio/audiooutputdevice.cpp | 2 +- sdrgui/gui/audiodialog.cpp | 6 +- sdrgui/gui/audioselectdialog.cpp | 2 +- 8 files changed, 86 insertions(+), 75 deletions(-) diff --git a/plugins/samplesource/audioinput/audioinputgui.cpp b/plugins/samplesource/audioinput/audioinputgui.cpp index ce6141c66..c6b321de5 100644 --- a/plugins/samplesource/audioinput/audioinputgui.cpp +++ b/plugins/samplesource/audioinput/audioinputgui.cpp @@ -186,8 +186,7 @@ void AudioInputGui::updateSampleRateAndFrequency() void AudioInputGui::refreshDeviceList() { ui->device->blockSignals(true); - AudioDeviceManager *audioDeviceManager = DSPEngine::instance()->getAudioDeviceManager(); - const QList& audioList = audioDeviceManager->getInputDevices(); + const QList& audioList = AudioDeviceInfo::availableInputDevices(); ui->device->clear(); for (const auto &itAudio : audioList) diff --git a/sdrbase/audio/audiodeviceinfo.cpp b/sdrbase/audio/audiodeviceinfo.cpp index c40c7f0c7..e766898eb 100644 --- a/sdrbase/audio/audiodeviceinfo.cpp +++ b/sdrbase/audio/audiodeviceinfo.cpp @@ -20,6 +20,10 @@ #include "audiodeviceinfo.h" +bool inputDevicesEnumerated = false, outputDevicesEnumerated = false; +QList inputDevices, outputDevices; +AudioDeviceInfo defaultInputDevice_, defaultOutputDevice_; + QString AudioDeviceInfo::deviceName() const { #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) @@ -67,69 +71,81 @@ QString AudioDeviceInfo::realm() const } #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) -QList AudioDeviceInfo::availableInputDevices() +const QList &AudioDeviceInfo::availableInputDevices() { - QList devInfos = QMediaDevices::audioInputs(); - QList list; - - for (auto devInfo : devInfos) { - list.append(AudioDeviceInfo(devInfo)); + if (!m_inputDevicesEnumerated) { + QList devInfos = QMediaDevices::audioInputs(); + for (auto devInfo : devInfos) { + m_inputDevices.append(AudioDeviceInfo(devInfo)); + } + m_inputDevicesEnumerated = true; } - return list; + return m_inputDevices; } -QList AudioDeviceInfo::availableOutputDevices() +const QList &AudioDeviceInfo::availableOutputDevices() { - QList devInfos = QMediaDevices::audioOutputs(); - QList list; - - for (auto devInfo : devInfos) { - list.append(AudioDeviceInfo(devInfo)); + if (!m_outputDevicesEnumerated) { + QList devInfos = QMediaDevices::audioOutputs(); + for (auto devInfo : devInfos) { + m_outputDevices.append(AudioDeviceInfo(devInfo)); + } + m_outputDevicesEnumerated = true; } - return list; + return m_outputDevices; } #else -QList AudioDeviceInfo::availableInputDevices() +const QList &AudioDeviceInfo::availableInputDevices() { - QList devInfos = QAudioDeviceInfo::availableDevices(QAudio::AudioInput); - QList list; - - for (auto devInfo : devInfos) { - list.append(AudioDeviceInfo(devInfo)); + if (!inputDevicesEnumerated) { + QList devInfos = QAudioDeviceInfo::availableDevices(QAudio::AudioInput); + for (auto devInfo : devInfos) { + inputDevices.append(AudioDeviceInfo(devInfo)); + } + inputDevicesEnumerated = true; } - return list; + return inputDevices; } -QList AudioDeviceInfo::availableOutputDevices() +const QList &AudioDeviceInfo::availableOutputDevices() { - QList devInfos = QAudioDeviceInfo::availableDevices(QAudio::AudioOutput); - QList list; - - for (auto devInfo : devInfos) { - list.append(AudioDeviceInfo(devInfo)); + if (!outputDevicesEnumerated) { + QList devInfos = QAudioDeviceInfo::availableDevices(QAudio::AudioOutput); + for (auto devInfo : devInfos) { + outputDevices.append(AudioDeviceInfo(devInfo)); + } + outputDevicesEnumerated = true; } - return list; + return outputDevices; } #endif -AudioDeviceInfo AudioDeviceInfo::defaultOutputDevice() +const AudioDeviceInfo &AudioDeviceInfo::defaultOutputDevice() { + if (defaultOutputDevice_.m_deviceInfo.isNull()) + { #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) - return AudioDeviceInfo(QMediaDevices::defaultAudioOutput()); + defaultOutputDevice_ = AudioDeviceInfo(QMediaDevices::defaultAudioOutput()); #else - return AudioDeviceInfo(QAudioDeviceInfo::defaultOutputDevice()); + defaultOutputDevice_ = AudioDeviceInfo(QAudioDeviceInfo::defaultOutputDevice()); #endif + } + return defaultOutputDevice_; } -AudioDeviceInfo AudioDeviceInfo::defaultInputDevice() +const AudioDeviceInfo &AudioDeviceInfo::defaultInputDevice() { + if (defaultInputDevice_.m_deviceInfo.isNull()) + { #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) - return AudioDeviceInfo(QMediaDevices::defaultAudioInput()); + defaultInputDevice_ = AudioDeviceInfo(QMediaDevices::defaultAudioInput()); #else - return AudioDeviceInfo(QAudioDeviceInfo::defaultInputDevice()); + defaultInputDevice_ = AudioDeviceInfo(QAudioDeviceInfo::defaultInputDevice()); #endif + } + return defaultInputDevice_; } diff --git a/sdrbase/audio/audiodeviceinfo.h b/sdrbase/audio/audiodeviceinfo.h index 27a377925..5e3608801 100644 --- a/sdrbase/audio/audiodeviceinfo.h +++ b/sdrbase/audio/audiodeviceinfo.h @@ -67,10 +67,10 @@ public: bool isFormatSupported(const QAudioFormat &settings) const; QList supportedSampleRates() const; - static QList availableInputDevices(); - static QList availableOutputDevices(); - static AudioDeviceInfo defaultInputDevice(); - static AudioDeviceInfo defaultOutputDevice(); + static const QList &availableInputDevices(); + static const QList &availableOutputDevices(); + static const AudioDeviceInfo &defaultInputDevice(); + static const AudioDeviceInfo &defaultOutputDevice(); private: diff --git a/sdrbase/audio/audiodevicemanager.cpp b/sdrbase/audio/audiodevicemanager.cpp index bb4ca35ba..949945910 100644 --- a/sdrbase/audio/audiodevicemanager.cpp +++ b/sdrbase/audio/audiodevicemanager.cpp @@ -82,20 +82,22 @@ QDataStream& operator>>(QDataStream& ds, AudioDeviceManager::OutputDeviceInfo& i AudioDeviceManager::AudioDeviceManager() { qDebug("AudioDeviceManager::AudioDeviceManager: scan input devices"); - m_inputDevicesInfo = AudioDeviceInfo::availableInputDevices(); + { + auto &devicesInfo = AudioDeviceInfo::availableInputDevices(); - for (int i = 0; i < m_inputDevicesInfo.size(); i++) { - qDebug("AudioDeviceManager::AudioDeviceManager: input device #%d: %s", i, qPrintable(m_inputDevicesInfo[i].deviceName())); + for (int i = 0; i < devicesInfo.size(); i++) { + qDebug("AudioDeviceManager::AudioDeviceManager: input device #%d: %s", i, qPrintable(devicesInfo[i].deviceName())); + } } - qDebug("AudioDeviceManager::AudioDeviceManager: scan output devices"); - m_outputDevicesInfo = AudioDeviceInfo::availableOutputDevices(); + { + auto &devicesInfo = AudioDeviceInfo::availableOutputDevices(); - for (int i = 0; i < m_outputDevicesInfo.size(); i++) { - qDebug("AudioDeviceManager::AudioDeviceManager: output device #%d: %s", i, qPrintable(m_outputDevicesInfo[i].deviceName())); + for (int i = 0; i < devicesInfo.size(); i++) { + qDebug("AudioDeviceManager::AudioDeviceManager: output device #%d: %s", i, qPrintable(devicesInfo[i].deviceName())); + } } - m_defaultInputStarted = false; m_defaultOutputStarted = false; @@ -142,9 +144,9 @@ bool AudioDeviceManager::getOutputDeviceName(int outputDeviceIndex, QString &dev } else { - if (outputDeviceIndex < m_outputDevicesInfo.size()) + if (outputDeviceIndex < AudioDeviceInfo::availableOutputDevices().size()) { - deviceName = m_outputDevicesInfo[outputDeviceIndex].deviceName(); + deviceName = AudioDeviceInfo::availableOutputDevices()[outputDeviceIndex].deviceName(); return true; } else @@ -163,9 +165,9 @@ bool AudioDeviceManager::getInputDeviceName(int inputDeviceIndex, QString &devic } else { - if (inputDeviceIndex < m_inputDevicesInfo.size()) + if (inputDeviceIndex < AudioDeviceInfo::availableInputDevices().size()) { - deviceName = m_inputDevicesInfo[inputDeviceIndex].deviceName(); + deviceName = AudioDeviceInfo::availableInputDevices()[inputDeviceIndex].deviceName(); return true; } else @@ -177,10 +179,10 @@ bool AudioDeviceManager::getInputDeviceName(int inputDeviceIndex, QString &devic int AudioDeviceManager::getOutputDeviceIndex(const QString &deviceName) const { - for (int i = 0; i < m_outputDevicesInfo.size(); i++) + for (int i = 0; i < AudioDeviceInfo::availableOutputDevices().size(); i++) { - //qDebug("AudioDeviceManager::getOutputDeviceIndex: %d: %s|%s", i, qPrintable(deviceName), qPrintable(m_outputDevicesInfo[i].deviceName())); - if (deviceName == m_outputDevicesInfo[i].deviceName()) { + //qDebug("AudioDeviceManager::getOutputDeviceIndex: %d: %s|%s", i, qPrintable(deviceName), qPrintable(AudioDeviceInfo::availableOutputDevices()[i].deviceName())); + if (deviceName == AudioDeviceInfo::availableOutputDevices()[i].deviceName()) { return i; } } @@ -190,10 +192,10 @@ int AudioDeviceManager::getOutputDeviceIndex(const QString &deviceName) const int AudioDeviceManager::getInputDeviceIndex(const QString &deviceName) const { - for (int i = 0; i < m_inputDevicesInfo.size(); i++) + for (int i = 0; i < AudioDeviceInfo::availableInputDevices().size(); i++) { - //qDebug("AudioDeviceManager::getInputDeviceIndex: %d: %s|%s", i, qPrintable(deviceName), qPrintable(m_inputDevicesInfo[i].deviceName())); - if (deviceName == m_inputDevicesInfo[i].deviceName()) { + //qDebug("AudioDeviceManager::getInputDeviceIndex: %d: %s|%s", i, qPrintable(deviceName), qPrintable(AudioDeviceInfo::availableInputDevices()[i].deviceName())); + if (deviceName == AudioDeviceInfo::availableInputDevices()[i].deviceName()) { return i; } } @@ -295,7 +297,7 @@ void AudioDeviceManager::addAudioSink(AudioFifo* audioFifo, MessageQueue *sample if (outputDeviceIndex < 0) { audioOutputDevice->setDeviceName("System default"); } else { - audioOutputDevice->setDeviceName(m_outputDevicesInfo[outputDeviceIndex].deviceName()); + audioOutputDevice->setDeviceName(AudioDeviceInfo::availableOutputDevices()[outputDeviceIndex].deviceName()); } qDebug("AudioDeviceManager::addAudioSink: new AudioOutputDevice on thread: %p", thread); @@ -382,7 +384,7 @@ void AudioDeviceManager::addAudioSource(AudioFifo* audioFifo, MessageQueue *samp if (inputDeviceIndex < 0) { audioInputDevice->setDeviceName("System default"); } else { - audioInputDevice->setDeviceName(m_outputDevicesInfo[inputDeviceIndex].deviceName()); + audioInputDevice->setDeviceName(AudioDeviceInfo::availableOutputDevices()[inputDeviceIndex].deviceName()); } qDebug("AudioDeviceManager::addAudioSource: new AudioInputDevice on thread: %p", thread); @@ -789,9 +791,9 @@ void AudioDeviceManager::inputInfosCleanup() { QSet deviceNames; deviceNames.insert(m_defaultDeviceName); - QList::const_iterator itd = m_inputDevicesInfo.begin(); + QList::const_iterator itd = AudioDeviceInfo::availableInputDevices().begin(); - for (; itd != m_inputDevicesInfo.end(); ++itd) + for (; itd != AudioDeviceInfo::availableInputDevices().end(); ++itd) { qDebug("AudioDeviceManager::inputInfosCleanup: device: %s", qPrintable(itd->deviceName())); deviceNames.insert(itd->deviceName()); @@ -817,9 +819,9 @@ void AudioDeviceManager::outputInfosCleanup() { QSet deviceNames; deviceNames.insert(m_defaultDeviceName); - QList::const_iterator itd = m_outputDevicesInfo.begin(); + QList::const_iterator itd = AudioDeviceInfo::availableOutputDevices().begin(); - for (; itd != m_outputDevicesInfo.end(); ++itd) + for (; itd != AudioDeviceInfo::availableOutputDevices().end(); ++itd) { qDebug("AudioDeviceManager::outputInfosCleanup: device: %s", qPrintable(itd->deviceName())); deviceNames.insert(itd->deviceName()); diff --git a/sdrbase/audio/audiodevicemanager.h b/sdrbase/audio/audiodevicemanager.h index 0cbbb9e5e..ca78191eb 100644 --- a/sdrbase/audio/audiodevicemanager.h +++ b/sdrbase/audio/audiodevicemanager.h @@ -102,9 +102,6 @@ public: AudioDeviceManager(); ~AudioDeviceManager(); - const QList& getInputDevices() const { return m_inputDevicesInfo; } - const QList& getOutputDevices() const { return m_outputDevicesInfo; } - bool getOutputDeviceName(int outputDeviceIndex, QString &deviceName) const; bool getInputDeviceName(int inputDeviceIndex, QString &deviceName) const; int getOutputDeviceIndex(const QString &deviceName) const; @@ -136,9 +133,6 @@ public: static const QString m_defaultDeviceName; private: - QList m_inputDevicesInfo; - QList m_outputDevicesInfo; - QMap m_audioSinkFifos; //< audio sink FIFO to audio output device index-1 map QMap m_audioFifoToSinkMessageQueues; //!< audio sink FIFO to attached sink message queue QMap > m_outputDeviceSinkMessageQueues; //!< sink message queues attached to device diff --git a/sdrbase/audio/audiooutputdevice.cpp b/sdrbase/audio/audiooutputdevice.cpp index 4a9b98001..b886165fb 100644 --- a/sdrbase/audio/audiooutputdevice.cpp +++ b/sdrbase/audio/audiooutputdevice.cpp @@ -91,7 +91,7 @@ bool AudioOutputDevice::start(int deviceIndex, int sampleRate) } else { - QList devicesInfo = AudioDeviceInfo::availableOutputDevices(); + auto &devicesInfo = AudioDeviceInfo::availableOutputDevices(); if (deviceIndex < devicesInfo.size()) { diff --git a/sdrgui/gui/audiodialog.cpp b/sdrgui/gui/audiodialog.cpp index 7f7a7d378..5183b1bc6 100644 --- a/sdrgui/gui/audiodialog.cpp +++ b/sdrgui/gui/audiodialog.cpp @@ -40,14 +40,14 @@ AudioDialogX::AudioDialogX(AudioDeviceManager* audioDeviceManager, QWidget* pare // out panel AudioDeviceManager::OutputDeviceInfo outDeviceInfo; - AudioDeviceInfo defaultOutputDeviceInfo = AudioDeviceInfo::defaultOutputDevice(); + const AudioDeviceInfo &defaultOutputDeviceInfo = AudioDeviceInfo::defaultOutputDevice(); treeItem = new QTreeWidgetItem(ui->audioOutTree); treeItem->setText(1, AudioDeviceManager::m_defaultDeviceName); bool found = m_audioDeviceManager->getOutputDeviceInfo(AudioDeviceManager::m_defaultDeviceName, outDeviceInfo); treeItem->setText(0, found ? "__" : "_D"); ui->audioOutTree->setCurrentItem(treeItem); - const QList& outputDevices = m_audioDeviceManager->getOutputDevices(); + const QList& outputDevices = AudioDeviceInfo::availableOutputDevices(); for(QList::const_iterator it = outputDevices.begin(); it != outputDevices.end(); ++it) { @@ -75,7 +75,7 @@ AudioDialogX::AudioDialogX(AudioDeviceManager* audioDeviceManager, QWidget* pare treeItem->setText(0, found ? "__" : "_D"); ui->audioInTree->setCurrentItem(treeItem); - const QList& inputDevices = m_audioDeviceManager->getInputDevices(); + const QList& inputDevices = AudioDeviceInfo::availableInputDevices(); for(QList::const_iterator it = inputDevices.begin(); it != inputDevices.end(); ++it) { diff --git a/sdrgui/gui/audioselectdialog.cpp b/sdrgui/gui/audioselectdialog.cpp index 4ce95fdb1..79fbdab43 100644 --- a/sdrgui/gui/audioselectdialog.cpp +++ b/sdrgui/gui/audioselectdialog.cpp @@ -40,7 +40,7 @@ AudioSelectDialog::AudioSelectDialog(const AudioDeviceManager* audioDeviceManage defaultItem->setText(2, tr("%1").arg(sampleRate)); defaultItem->setTextAlignment(2, Qt::AlignRight); - QList devices = input ? m_audioDeviceManager->getInputDevices() : m_audioDeviceManager->getOutputDevices(); + const QList &devices = input ? AudioDeviceInfo::availableInputDevices() : AudioDeviceInfo::availableOutputDevices(); for(QList::const_iterator it = devices.begin(); it != devices.end(); ++it) { From ce3e78322b9b6067ad565cffb704aa7336277f3e Mon Sep 17 00:00:00 2001 From: mxi-box Date: Sat, 30 Mar 2024 12:12:57 +0800 Subject: [PATCH 3/6] Fix default audio boolean mark --- sdrbase/audio/audiodevicemanager.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sdrbase/audio/audiodevicemanager.cpp b/sdrbase/audio/audiodevicemanager.cpp index 949945910..f845ef615 100644 --- a/sdrbase/audio/audiodevicemanager.cpp +++ b/sdrbase/audio/audiodevicemanager.cpp @@ -502,7 +502,7 @@ void AudioDeviceManager::startAudioOutput(int outputDeviceIndex) m_audioOutputInfos[deviceName].udpChannelMode = udpChannelMode; m_audioOutputInfos[deviceName].udpChannelCodec = udpChannelCodec; m_audioOutputInfos[deviceName].udpDecimationFactor = decimationFactor; - m_defaultOutputStarted = (outputDeviceIndex == -1); + m_defaultOutputStarted |= (outputDeviceIndex == -1); } else { @@ -540,7 +540,7 @@ void AudioDeviceManager::startAudioInput(int inputDeviceIndex) m_audioInputs[inputDeviceIndex]->setVolume(volume); m_audioInputInfos[deviceName].volume = volume; - m_defaultInputStarted = (inputDeviceIndex == -1); + m_defaultInputStarted |= (inputDeviceIndex == -1); } else { From 556cc8ad453e510c69788b91264a0d350bc8c3c5 Mon Sep 17 00:00:00 2001 From: mxi-box Date: Sat, 30 Mar 2024 14:24:05 +0800 Subject: [PATCH 4/6] Move AudioDeviceInfo singleton --- plugins/samplesource/fcdpro/fcdproinput.cpp | 2 +- .../samplesource/fcdproplus/fcdproplusinput.cpp | 2 +- sdrbase/audio/audiodeviceinfo.cpp | 16 ++++++++-------- sdrbase/webapi/webapiadapter.cpp | 4 ++-- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/plugins/samplesource/fcdpro/fcdproinput.cpp b/plugins/samplesource/fcdpro/fcdproinput.cpp index c91ba1187..834239319 100644 --- a/plugins/samplesource/fcdpro/fcdproinput.cpp +++ b/plugins/samplesource/fcdpro/fcdproinput.cpp @@ -174,7 +174,7 @@ void FCDProInput::closeDevice() bool FCDProInput::openFCDAudio(const char* cardname) { AudioDeviceManager *audioDeviceManager = DSPEngine::instance()->getAudioDeviceManager(); - const QList& audioList = audioDeviceManager->getInputDevices(); + const QList& audioList = AudioDeviceInfo::availableInputDevices(); for (const auto &itAudio : audioList) { diff --git a/plugins/samplesource/fcdproplus/fcdproplusinput.cpp b/plugins/samplesource/fcdproplus/fcdproplusinput.cpp index f72e0024d..ee3bce44a 100644 --- a/plugins/samplesource/fcdproplus/fcdproplusinput.cpp +++ b/plugins/samplesource/fcdproplus/fcdproplusinput.cpp @@ -176,7 +176,7 @@ void FCDProPlusInput::closeDevice() bool FCDProPlusInput::openFCDAudio(const char* cardname) { AudioDeviceManager *audioDeviceManager = DSPEngine::instance()->getAudioDeviceManager(); - const QList& audioList = audioDeviceManager->getInputDevices(); + const QList& audioList = AudioDeviceInfo::availableInputDevices(); for (const auto &itAudio : audioList) { diff --git a/sdrbase/audio/audiodeviceinfo.cpp b/sdrbase/audio/audiodeviceinfo.cpp index e766898eb..ec457aef7 100644 --- a/sdrbase/audio/audiodeviceinfo.cpp +++ b/sdrbase/audio/audiodeviceinfo.cpp @@ -73,28 +73,28 @@ QString AudioDeviceInfo::realm() const #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) const QList &AudioDeviceInfo::availableInputDevices() { - if (!m_inputDevicesEnumerated) { + if (!inputDevicesEnumerated) { QList devInfos = QMediaDevices::audioInputs(); for (auto devInfo : devInfos) { - m_inputDevices.append(AudioDeviceInfo(devInfo)); + inputDevices.append(AudioDeviceInfo(devInfo)); } - m_inputDevicesEnumerated = true; + inputDevicesEnumerated = true; } - return m_inputDevices; + return inputDevices; } const QList &AudioDeviceInfo::availableOutputDevices() { - if (!m_outputDevicesEnumerated) { + if (!outputDevicesEnumerated) { QList devInfos = QMediaDevices::audioOutputs(); for (auto devInfo : devInfos) { - m_outputDevices.append(AudioDeviceInfo(devInfo)); + outputDevices.append(AudioDeviceInfo(devInfo)); } - m_outputDevicesEnumerated = true; + outputDevicesEnumerated = true; } - return m_outputDevices; + return outputDevices; } #else const QList &AudioDeviceInfo::availableInputDevices() diff --git a/sdrbase/webapi/webapiadapter.cpp b/sdrbase/webapi/webapiadapter.cpp index 3e7d32841..b72a20d40 100644 --- a/sdrbase/webapi/webapiadapter.cpp +++ b/sdrbase/webapi/webapiadapter.cpp @@ -454,8 +454,8 @@ int WebAPIAdapter::instanceAudioGet( { (void) error; DSPEngine *dspEngine = DSPEngine::instance(); - const QList& audioInputDevices = dspEngine->getAudioDeviceManager()->getInputDevices(); - const QList& audioOutputDevices = dspEngine->getAudioDeviceManager()->getOutputDevices(); + const QList& audioInputDevices = AudioDeviceInfo::availableInputDevices(); + const QList& audioOutputDevices = AudioDeviceInfo::availableOutputDevices(); int nbInputDevices = audioInputDevices.size(); int nbOutputDevices = audioOutputDevices.size(); From 2a39ef5d6d39eb9ff201e5cdeea736a054078ba3 Mon Sep 17 00:00:00 2001 From: f4exb Date: Sat, 30 Mar 2024 10:41:28 +0100 Subject: [PATCH 5/6] ChirpChat modulator: added FT protocol --- plugins/channeltx/modchirpchat/CMakeLists.txt | 11 +- .../channeltx/modchirpchat/chirpchatmod.cpp | 79 +------ .../modchirpchat/chirpchatmodencoder.cpp | 42 ++++ .../modchirpchat/chirpchatmodencoder.h | 3 +- .../modchirpchat/chirpchatmodencoderft.cpp | 220 ++++++++++++++++++ .../modchirpchat/chirpchatmodencoderft.h | 48 ++++ .../channeltx/modchirpchat/chirpchatmodgui.ui | 5 + .../modchirpchat/chirpchatmodsettings.h | 3 +- plugins/channeltx/modchirpchat/readme.md | 18 +- sdrbench/test_ft8protocols.cpp | 9 +- 10 files changed, 360 insertions(+), 78 deletions(-) create mode 100644 plugins/channeltx/modchirpchat/chirpchatmodencoderft.cpp create mode 100644 plugins/channeltx/modchirpchat/chirpchatmodencoderft.h diff --git a/plugins/channeltx/modchirpchat/CMakeLists.txt b/plugins/channeltx/modchirpchat/CMakeLists.txt index 19439ad9b..ee264b45b 100644 --- a/plugins/channeltx/modchirpchat/CMakeLists.txt +++ b/plugins/channeltx/modchirpchat/CMakeLists.txt @@ -1,5 +1,10 @@ project(modchirpchat) +if (FT8_SUPPORT) + set(chirpchatmod_FT8_LIB ft8) + set(chirpchatmod_FT8_INCLUDE ${CMAKE_SOURCE_DIR}/ft8) +endif() + set(modchirpchat_SOURCES chirpchatmod.cpp chirpchatmodsettings.cpp @@ -10,6 +15,7 @@ set(modchirpchat_SOURCES chirpchatmodencodertty.cpp chirpchatmodencoderascii.cpp chirpchatmodencoderlora.cpp + chirpchatmodencoderft.cpp chirpchatmodwebapiadapter.cpp ) @@ -23,11 +29,13 @@ set(modchirpchat_HEADERS chirpchatmodencodertty.h chirpchatmodencoderascii.h chirpchatmodencoderlora.h + chirpchatmodencoderft.h chirpchatmodwebapiadapter.h ) include_directories( ${CMAKE_SOURCE_DIR}/swagger/sdrangel/code/qt5/client + ${chirpchatmod_FT8_INCLUDE} ) if(NOT SERVER_MODE) @@ -38,7 +46,7 @@ if(NOT SERVER_MODE) ) set(modchirpchat_HEADERS ${modchirpchat_HEADERS} - chirpchatmodgui.h + chirpchatmodgui.h ) set(TARGET_NAME modchirpchat) @@ -62,6 +70,7 @@ target_link_libraries(${TARGET_NAME} sdrbase ${TARGET_LIB_GUI} swagger + ${chirpchatmod_FT8_LIB} ) install(TARGETS ${TARGET_NAME} DESTINATION ${INSTALL_FOLDER}) diff --git a/plugins/channeltx/modchirpchat/chirpchatmod.cpp b/plugins/channeltx/modchirpchat/chirpchatmod.cpp index fe07de693..cd60864ef 100644 --- a/plugins/channeltx/modchirpchat/chirpchatmod.cpp +++ b/plugins/channeltx/modchirpchat/chirpchatmod.cpp @@ -284,74 +284,19 @@ void ChirpChatMod::applySettings(const ChirpChatModSettings& settings, bool forc { payloadMsg = ChirpChatModBaseband::MsgConfigureChirpChatModPayload::create(); } - else if ((settings.m_messageType == ChirpChatModSettings::MessageBeacon) - && ((settings.m_messageType != m_settings.m_messageType) - || (settings.m_beaconMessage != m_settings.m_beaconMessage) || force)) + else if ((settings.m_messageType != m_settings.m_messageType) + || (settings.m_beaconMessage != m_settings.m_beaconMessage) + || (settings.m_cqMessage != m_settings.m_cqMessage) + || (settings.m_replyMessage != m_settings.m_replyMessage) + || (settings.m_reportMessage != m_settings.m_reportMessage) + || (settings.m_replyReportMessage != m_settings.m_replyReportMessage) + || (settings.m_rrrMessage != m_settings.m_rrrMessage) + || (settings.m_73Message != m_settings.m_73Message) + || (settings.m_qsoTextMessage != m_settings.m_qsoTextMessage) + || (settings.m_textMessage != m_settings.m_textMessage) + || (settings.m_bytesMessage != m_settings.m_bytesMessage) || force) { - m_encoder.encodeString(settings.m_beaconMessage, symbols); - payloadMsg = ChirpChatModBaseband::MsgConfigureChirpChatModPayload::create(symbols); - } - else if ((settings.m_messageType == ChirpChatModSettings::MessageCQ) - && ((settings.m_messageType != m_settings.m_messageType) - || (settings.m_cqMessage != m_settings.m_cqMessage) || force)) - { - m_encoder.encodeString(settings.m_cqMessage, symbols); - payloadMsg = ChirpChatModBaseband::MsgConfigureChirpChatModPayload::create(symbols); - } - else if ((settings.m_messageType == ChirpChatModSettings::MessageReply) - && ((settings.m_messageType != m_settings.m_messageType) - || (settings.m_replyMessage != m_settings.m_replyMessage) || force)) - { - m_encoder.encodeString(settings.m_replyMessage, symbols); - payloadMsg = ChirpChatModBaseband::MsgConfigureChirpChatModPayload::create(symbols); - } - else if ((settings.m_messageType == ChirpChatModSettings::MessageReport) - && ((settings.m_messageType != m_settings.m_messageType) - || (settings.m_reportMessage != m_settings.m_reportMessage) || force)) - { - m_encoder.encodeString(settings.m_reportMessage, symbols); - payloadMsg = ChirpChatModBaseband::MsgConfigureChirpChatModPayload::create(symbols); - } - else if ((settings.m_messageType == ChirpChatModSettings::MessageReplyReport) - && ((settings.m_messageType != m_settings.m_messageType) - || (settings.m_replyReportMessage != m_settings.m_replyReportMessage) || force)) - { - m_encoder.encodeString(settings.m_replyReportMessage, symbols); - payloadMsg = ChirpChatModBaseband::MsgConfigureChirpChatModPayload::create(symbols); - } - else if ((settings.m_messageType == ChirpChatModSettings::MessageRRR) - && ((settings.m_messageType != m_settings.m_messageType) - || (settings.m_rrrMessage != m_settings.m_rrrMessage) || force)) - { - m_encoder.encodeString(settings.m_rrrMessage, symbols); - payloadMsg = ChirpChatModBaseband::MsgConfigureChirpChatModPayload::create(symbols); - } - else if ((settings.m_messageType == ChirpChatModSettings::Message73) - && ((settings.m_messageType != m_settings.m_messageType) - || (settings.m_73Message != m_settings.m_73Message) || force)) - { - m_encoder.encodeString(settings.m_73Message, symbols); - payloadMsg = ChirpChatModBaseband::MsgConfigureChirpChatModPayload::create(symbols); - } - else if ((settings.m_messageType == ChirpChatModSettings::MessageQSOText) - && ((settings.m_messageType != m_settings.m_messageType) - || (settings.m_qsoTextMessage != m_settings.m_qsoTextMessage) || force)) - { - m_encoder.encodeString(settings.m_qsoTextMessage, symbols); - payloadMsg = ChirpChatModBaseband::MsgConfigureChirpChatModPayload::create(symbols); - } - else if ((settings.m_messageType == ChirpChatModSettings::MessageText) - && ((settings.m_messageType != m_settings.m_messageType) - || (settings.m_textMessage != m_settings.m_textMessage) || force)) - { - m_encoder.encodeString(settings.m_textMessage, symbols); - payloadMsg = ChirpChatModBaseband::MsgConfigureChirpChatModPayload::create(symbols); - } - else if ((settings.m_messageType == ChirpChatModSettings::MessageBytes) - && ((settings.m_messageType != m_settings.m_messageType) - || (settings.m_bytesMessage != m_settings.m_bytesMessage) || force)) - { - m_encoder.encodeBytes(settings.m_bytesMessage, symbols); + m_encoder.encode(settings, symbols); payloadMsg = ChirpChatModBaseband::MsgConfigureChirpChatModPayload::create(symbols); } diff --git a/plugins/channeltx/modchirpchat/chirpchatmodencoder.cpp b/plugins/channeltx/modchirpchat/chirpchatmodencoder.cpp index 71b68180c..de9441629 100644 --- a/plugins/channeltx/modchirpchat/chirpchatmodencoder.cpp +++ b/plugins/channeltx/modchirpchat/chirpchatmodencoder.cpp @@ -19,6 +19,7 @@ #include "chirpchatmodencodertty.h" #include "chirpchatmodencoderascii.h" #include "chirpchatmodencoderlora.h" +#include "chirpchatmodencoderft.h" ChirpChatModEncoder::ChirpChatModEncoder() : m_codingScheme(ChirpChatModSettings::CodingTTY), @@ -44,6 +45,47 @@ void ChirpChatModEncoder::setNbSymbolBits(unsigned int spreadFactor, unsigned in m_nbSymbolBits = m_spreadFactor - m_deBits; } +void ChirpChatModEncoder::encode(ChirpChatModSettings settings, std::vector& symbols) +{ + if (settings.m_codingScheme == ChirpChatModSettings::CodingFT) + { + ChirpChatModEncoderFT::encodeMsg( + settings.m_myCall, + settings.m_urCall, + settings.m_myLoc, + settings.m_myRpt, + settings.m_textMessage, + settings.m_messageType, + m_nbSymbolBits, + symbols + ); + } + else + { + if (settings.m_messageType == ChirpChatModSettings::MessageBytes) { + encodeBytes(settings.m_bytesMessage, symbols); + } else if (settings.m_messageType == ChirpChatModSettings::MessageBeacon) { + encodeString(settings.m_beaconMessage, symbols); + } else if (settings.m_messageType == ChirpChatModSettings::MessageCQ) { + encodeString(settings.m_cqMessage, symbols); + } else if (settings.m_messageType == ChirpChatModSettings::MessageReply) { + encodeString(settings.m_replyMessage, symbols); + } else if (settings.m_messageType == ChirpChatModSettings::MessageReport) { + encodeString(settings.m_reportMessage, symbols); + } else if (settings.m_messageType == ChirpChatModSettings::MessageReplyReport) { + encodeString(settings.m_replyReportMessage, symbols); + } else if (settings.m_messageType == ChirpChatModSettings::MessageRRR) { + encodeString(settings.m_rrrMessage, symbols); + } else if (settings.m_messageType == ChirpChatModSettings::Message73) { + encodeString(settings.m_73Message, symbols); + } else if (settings.m_messageType == ChirpChatModSettings::MessageQSOText) { + encodeString(settings.m_qsoTextMessage, symbols); + } else if (settings.m_messageType == ChirpChatModSettings::MessageText) { + encodeString(settings.m_textMessage, symbols); + } + } +} + void ChirpChatModEncoder::encodeString(const QString& str, std::vector& symbols) { switch (m_codingScheme) diff --git a/plugins/channeltx/modchirpchat/chirpchatmodencoder.h b/plugins/channeltx/modchirpchat/chirpchatmodencoder.h index 46c0e4ce3..69c028eba 100644 --- a/plugins/channeltx/modchirpchat/chirpchatmodencoder.h +++ b/plugins/channeltx/modchirpchat/chirpchatmodencoder.h @@ -34,10 +34,11 @@ public: void setLoRaParityBits(unsigned int parityBits) { m_nbParityBits = parityBits; } void setLoRaHasHeader(bool hasHeader) { m_hasHeader = hasHeader; } void setLoRaHasCRC(bool hasCRC) { m_hasCRC = hasCRC; } - void encodeString(const QString& str, std::vector& symbols); void encodeBytes(const QByteArray& bytes, std::vector& symbols); + void encode(ChirpChatModSettings settings, std::vector& symbols); private: + void encodeString(const QString& str, std::vector& symbols); // LoRa functions void encodeBytesLoRa(const QByteArray& bytes, std::vector& symbols); diff --git a/plugins/channeltx/modchirpchat/chirpchatmodencoderft.cpp b/plugins/channeltx/modchirpchat/chirpchatmodencoderft.cpp new file mode 100644 index 000000000..c874fc350 --- /dev/null +++ b/plugins/channeltx/modchirpchat/chirpchatmodencoderft.cpp @@ -0,0 +1,220 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2024 Edouard Griffiths, F4EXB // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#include "chirpchatmodencoderft.h" + +#ifndef HAS_FT8 +void ChirpChatModEncoderFT::encodeMsg( + const QString& myCall, + const QString& urCall, + const QString& myLocator, + const QString& myReport, + const QString& textMessage, + ChirpChatModSettings::MessageType messageType, + unsigned int nbSymbolBits, + std::vector& symbols +) +{ + qDebug("ChirpChatModEncoderFT::encodeMsg: not implemented"); +} +#else + +#include "ft8.h" +#include "packing.h" + + +void ChirpChatModEncoderFT::encodeMsg( + const QString& myCall, + const QString& urCall, + const QString& myLocator, + const QString& myReport, + const QString& textMessage, + ChirpChatModSettings::MessageType messageType, + unsigned int nbSymbolBits, + std::vector& symbols +) +{ + int a174[174]; // FT payload is 174 bits + + if (messageType == ChirpChatModSettings::MessageNone) { + return; // do nothing + } else if (messageType == ChirpChatModSettings::MessageBeacon) { + encodeMsgBeaconOrCQ(myCall, myLocator, "DE", a174); + } else if (messageType == ChirpChatModSettings::MessageCQ) { + encodeMsgBeaconOrCQ(myCall, myLocator, "CQ", a174); + } else if (messageType == ChirpChatModSettings::MessageReply) { + encodeMsgReply(myCall, urCall, myLocator, a174); + } else if (messageType == ChirpChatModSettings::MessageReport) { + encodeMsgReport(myCall, urCall, myReport, 0, a174); + } else if (messageType == ChirpChatModSettings::MessageReplyReport) { + encodeMsgReport(myCall, urCall, myReport, 1, a174); + } else if (messageType == ChirpChatModSettings::MessageRRR) { + encodeMsgReport(myCall, urCall, "RRR", 1, a174); + } else if (messageType == ChirpChatModSettings::Message73) { + encodeMsgReport(myCall, urCall, "73", 1, a174); + } else { + encodeTextMsg(textMessage, a174); + } + + int allBits = ((174 / nbSymbolBits) + (174 % nbSymbolBits == 0 ? 0 : 1))*nbSymbolBits; // ensures zero bits padding + int iBit; + int symbol = 0; + + for (int i = 0; i < allBits; i++) + { + iBit = nbSymbolBits - (i % nbSymbolBits) - 1; // MSB first + + if (i < 174) { + symbol += a174[i] * (1< // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef PLUGINS_CHANNELTX_MODCHIRPCHAT_CHIRPCHATMODENCODEFT_H_ +#define PLUGINS_CHANNELTX_MODCHIRPCHAT_CHIRPCHATMODENCODEFT_H_ + +#include +#include + +#include "chirpchatmodsettings.h" + +class ChirpChatModEncoderFT +{ +public: + static void encodeMsg( + const QString& myCall, + const QString& urCall, + const QString& myLocator, + const QString& myReport, + const QString& textMessage, + ChirpChatModSettings::MessageType messageType, + unsigned int nbSymbolBits, + std::vector& symbols + ); + +private: + static void encodeTextMsg(const QString& text, int a174[]); + static void encodeMsgBeaconOrCQ(const QString& myCall, const QString& myLocator, const QString& shorthand, int a174[]); + static void encodeMsgReply(const QString& myCall, const QString& urCall, const QString& myLocator, int a174[]); + static void encodeMsgReport(const QString& myCall, const QString& urCall, const QString& myReport, int reply, int a174[]); + static void encodeMsgFinish(const QString& myCall, const QString& urCall, const QString& shorthand, int a174[]); +}; + +#endif // PLUGINS_CHANNELTX_MODCHIRPCHAT_CHIRPCHATMODENCODEFT_H_ diff --git a/plugins/channeltx/modchirpchat/chirpchatmodgui.ui b/plugins/channeltx/modchirpchat/chirpchatmodgui.ui index 03915bf8e..79d272da2 100644 --- a/plugins/channeltx/modchirpchat/chirpchatmodgui.ui +++ b/plugins/channeltx/modchirpchat/chirpchatmodgui.ui @@ -551,6 +551,11 @@ TTY + + + FT + + diff --git a/plugins/channeltx/modchirpchat/chirpchatmodsettings.h b/plugins/channeltx/modchirpchat/chirpchatmodsettings.h index 263fddb13..884f5716b 100644 --- a/plugins/channeltx/modchirpchat/chirpchatmodsettings.h +++ b/plugins/channeltx/modchirpchat/chirpchatmodsettings.h @@ -34,7 +34,8 @@ struct ChirpChatModSettings { CodingLoRa, //!< Standard LoRa CodingASCII, //!< plain ASCII (7 bits) - CodingTTY //!< plain TTY (5 bits) + CodingTTY, //!< plain TTY (5 bits) + CodingFT //!< FT8/4 scheme (payload 174 bits LDPC) }; enum MessageType diff --git a/plugins/channeltx/modchirpchat/readme.md b/plugins/channeltx/modchirpchat/readme.md index 1e0687aae..8a631b4e4 100644 --- a/plugins/channeltx/modchirpchat/readme.md +++ b/plugins/channeltx/modchirpchat/readme.md @@ -13,9 +13,7 @@ LoRa is a property of Semtech and the details of the protocol are not made publi This LoRa encoder is designed for experimentation. For production grade applications it is recommended to use dedicated hardware instead. -Modulation characteristics from LoRa have been augmented with more bandwidths and FFT bin collations (DE factor). Plain TTY and ASCII have also been added and there are plans to add some more complex typically amateur radio MFSK based modes like JT65. - -Note: this plugin is officially supported since version 6. +Modulation characteristics from LoRa have been augmented with more bandwidths and FFT bin collations (DE factor). Plain TTY and ASCII have also been added that match character value to symbols directly. The FT protocol used in FT8 and FT4 is introduced packing the 174 bits payload into (SF -DE) bits symbols. There are plans to add some more of these typically amateur radio MFSK based modes like JT65.

Interface

@@ -106,6 +104,7 @@ To populate messages you can specify your callsign (10.5), the other party calls - **LoRa**: LoRa compatible - **ASCII**: 7 bit plain ASCII without FEC and CRC. Requires exactly 7 bit effective samples thus SF-DE = 7 where SF is the spreading factor (5) and DE the distance enhancement factor (6) - **TTY**: 5 bit Baudot (Teletype) without FEC and CRC. Requires exactly 5 bit effective samples thus SF-DE = 5 where SF is the spreading factor (5) and DE the distance enhancement factor (6) + - **FT**: FT8/FT4 coding is applied using data in (10.5) to (10.8) to encode the 174 bit message payload with CRC and FEC as per FT8/FT4 protocol using a type 1 (standard) type of message. Note that the report (10.8) must comply with the FT rule (coded "-35" to "+99" with a leading 0 for the number) and would usually represent the integer part of the S/N ratio in the ChirpChat demodulator receiver. Calls should not be prefixed nor suffixed and the first 4 characters of the locator must represent a valid 4 character grid square. Plain text messages (13 characters) are also supported with the 0.0 type of message using the text entered in the message box (11). These 174 bits are packed into (SF - DE) bits symbols padded with zero bits if necessary. For the details of the FT protocol see: https://wsjt.sourceforge.io/FT4_FT8_QEX.pdf

10.2: Number of FEC parity bits (LoRa)

@@ -157,6 +156,19 @@ This lets you choose which pre-formatted message to send: - **Text**: plain text - **Bytes**: binary message in the form of a string of bytes. Use the hex window (12) to specify the message +In FT mode standard FT type messages are generated regardless of placeholders based on MyCall, YourCall, MyLoc, Report and Msg data (entered while in "Text" format). Locators are 4 character grids i.e. only the 4 first characters are taken. Reports must be valid FT reports from -35 to 99 coded as < sign>< zero padded value> (e.g -12, -04, +00, +04, +12) : + + - **Beacon**: DE < MyCall > < MyLoc > + - **CQ**: CQ < MyCall> < MyLoc > + - **Reply**: < YourCall > < MyCall > < MyLoc > + - **Report**: < YourCall > < MyCall > < Report > + - **R-Report**: < YourCall > < MyCall > R< Report > + - **RRR**: < YourCall > < MyCall > RRR + - **73**: < YourCall > < MyCall > 73 + - **QSO text**: < Msg > + - **Text**: < Msg > + - **Bytes**: < Msg > +

10.10: Revert to standard messages

Reformat all predefined messages in standard messages with placeholders. The Generate button (13) replaces the placeholders with the given QSO elements (10.5 to 10.8) diff --git a/sdrbench/test_ft8protocols.cpp b/sdrbench/test_ft8protocols.cpp index 075338d98..1754deec0 100644 --- a/sdrbench/test_ft8protocols.cpp +++ b/sdrbench/test_ft8protocols.cpp @@ -98,16 +98,16 @@ void TestFT8Protocols::testMsg1(const QStringList& argElements, bool runLDPC) std::string locstr; - int report; + int reply; if (argElements[3].startsWith("R+") || argElements[3].startsWith("R-")) { - report = 1; + reply = 1; locstr = argElements[3].mid(1).toStdString(); } else { - report = 0; + reply = 0; locstr = argElements[3].toStdString(); } @@ -121,14 +121,13 @@ void TestFT8Protocols::testMsg1(const QStringList& argElements, bool runLDPC) int a77[77]; std::fill(a77, a77 + 77, 0); - FT8::Packing::pack1(a77, c28_1, c28_2, g15, report); + FT8::Packing::pack1(a77, c28_1, c28_2, g15, reply); FT8::Packing packing; std::string call1, call2, loc; std::string msg = packing.unpack_1(a77, call1, call2, loc); qInfo("TestFT8Protocols::testMsg1: msg: %s, call1: %s, call2: %s, loc: %s", msg.c_str(), call1.c_str(), call2.c_str(), loc.c_str()); - if (runLDPC) { if (testLDPC(a77)) { From 1dddbd4424a835c6742a0f4925b208623b4d3f28 Mon Sep 17 00:00:00 2001 From: mxi-box Date: Sat, 30 Mar 2024 19:03:31 +0800 Subject: [PATCH 6/6] Packet Plugin: packetmod supports multi Via; packetdemod fix H bit --- plugins/channeltx/modpacket/packetmodsource.cpp | 6 ++++-- sdrbase/util/ax25.cpp | 15 +++++++++++---- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/plugins/channeltx/modpacket/packetmodsource.cpp b/plugins/channeltx/modpacket/packetmodsource.cpp index 63ae3b7fe..b08f44c7c 100644 --- a/plugins/channeltx/modpacket/packetmodsource.cpp +++ b/plugins/channeltx/modpacket/packetmodsource.cpp @@ -574,6 +574,7 @@ void PacketModSource::addTXPacket(QString callsign, QString to, QString via, QSt uint16_t crcValue; int len; int packet_length; + QStringList viaList = via.split(',', Qt::SkipEmptyParts); // Create AX.25 packet p = packet; @@ -584,9 +585,10 @@ void PacketModSource::addTXPacket(QString callsign, QString to, QString via, QSt // Dest p = ax25_address(p, to, 0xe0); // From - p = ax25_address(p, callsign, 0x60); + p = ax25_address(p, callsign, 0x60 | (viaList.empty() ? 0x01 : 0x00)); // Via - p = ax25_address(p, via, 0x61); + for (int i = 0; i < viaList.size(); i++) + p = ax25_address(p, std::move(viaList[i]), 0x60 | (i == viaList.size()-1 ? 0x01 : 0x00)); // Control *p++ = m_settings.m_ax25Control; // PID diff --git a/sdrbase/util/ax25.cpp b/sdrbase/util/ax25.cpp index 5e569bb3e..0e674f781 100644 --- a/sdrbase/util/ax25.cpp +++ b/sdrbase/util/ax25.cpp @@ -61,6 +61,7 @@ bool AX25Packet::decode(QByteArray packet) // List of repeater addresses for via field m_via = QString(""); i = 13; + int incomingViaStrIdx = -1; while ((packet[i] & 1) == 0) { i++; @@ -72,11 +73,17 @@ bool AX25Packet::decode(QByteArray packet) ssid = (repeaterSSID >> 1) & 0xf; QString repeater = QString(repeaterAddress).trimmed(); QString ssidString = (ssid != 0) ? QString("%2-%3").arg(repeater).arg(ssid) : QString(repeater); - if (m_via == "") - m_via = ssidString; - else - m_via = QString("%1,%2").arg(m_via).arg(ssidString); + + if (!m_via.isEmpty()) + m_via.append(','); + m_via.append(ssidString); + + if (packet[i] & 0x80) + incomingViaStrIdx = m_via.length(); } + if (incomingViaStrIdx >= 0) + m_via.insert(incomingViaStrIdx, "*"); + i++; // Control can be 1 or 2 bytes - how to know if 2? // I, U and S frames