1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2026-03-18 14:09:37 -04:00

FT8 demod: FT4 support (1)

This commit is contained in:
f4exb 2026-03-01 22:21:16 +01:00
parent 39374ce0b8
commit 9bb9493afd
13 changed files with 264 additions and 40 deletions

View File

@ -18,6 +18,7 @@
///////////////////////////////////////////////////////////////////////////////////
#include <QMutexLocker>
#include <algorithm>
#include "ft8demodsettings.h"
#include "ft8buffer.h"
@ -46,8 +47,10 @@ void FT8Buffer::feed(int16_t sample)
}
}
void FT8Buffer::getCurrentBuffer(int16_t *bufferCopy)
void FT8Buffer::getCurrentBuffer(int16_t *bufferCopy, int samplesToCopy)
{
QMutexLocker mlock(&m_mutex);
std::copy(&m_buffer[m_sampleIndex], &m_buffer[m_sampleIndex + m_bufferSize], bufferCopy);
const int samples = std::max(1, std::min(samplesToCopy, m_bufferSize));
const int start = m_sampleIndex + m_bufferSize - samples;
std::copy(&m_buffer[start], &m_buffer[start + samples], bufferCopy);
}

View File

@ -31,7 +31,7 @@ public:
~FT8Buffer();
void feed(int16_t sample);
void getCurrentBuffer(int16_t *bufferCopy);
void getCurrentBuffer(int16_t *bufferCopy, int samplesToCopy);
private:
int16_t *m_buffer;

View File

@ -18,6 +18,7 @@
#include <QDebug>
#include <QThread>
#include <algorithm>
#include "dsp/dspcommands.h"
#include "dsp/spectrumvis.h"
@ -33,6 +34,7 @@ FT8DemodBaseband::FT8DemodBaseband() :
m_channelizer(&m_sink),
m_messageQueueToGUI(nullptr),
m_spectrumVis(nullptr),
m_lastProcessPeriodIndex(-1),
m_deviceCenterFrequency(0)
{
qDebug("FT8DemodBaseband::FT8DemodBaseband");
@ -103,6 +105,7 @@ void FT8DemodBaseband::reset()
QMutexLocker mutexLocker(&m_mutex);
m_sampleFifo.reset();
m_channelSampleRate = 0;
m_lastProcessPeriodIndex = -1;
}
void FT8DemodBaseband::setMessageQueueToGUI(MessageQueue *messageQueue)
@ -289,6 +292,14 @@ void FT8DemodBaseband::applySettings(const QStringList& settingsKeys, const FT8D
m_ft8DemodWorker->setVerifyOSD(settings.m_verifyOSD);
}
if ((settingsKeys.contains("decoderMode") && (settings.m_decoderMode != m_settings.m_decoderMode)) || force)
{
m_ft8DemodWorker->setDecoderMode(settings.m_decoderMode);
m_pskReporterWorker->setTxMode(FT8DemodSettings::getDecoderModeString(settings.m_decoderMode));
m_ft8DemodWorker->invalidateSequence();
m_lastProcessPeriodIndex = -1;
}
m_sink.applySettings(settingsKeys, settings, force);
if (force) {
@ -313,20 +324,22 @@ void FT8DemodBaseband::setBasebandSampleRate(int sampleRate)
void FT8DemodBaseband::tick()
{
QDateTime nowUTC = QDateTime::currentDateTimeUtc();
const int periodMs = FT8DemodSettings::getDecoderFrameDurationMs(m_settings.m_decoderMode);
const int activeWindowMs = std::max(periodMs - 1000, 1);
const qint64 nowMs = nowUTC.toMSecsSinceEpoch();
const qint64 periodIndex = nowMs / periodMs;
const int periodOffsetMs = nowMs % periodMs;
if (nowUTC.time().second() % 15 < 14)
if (periodOffsetMs < activeWindowMs)
{
if (m_tickCount++ == 0)
if (m_lastProcessPeriodIndex != periodIndex)
{
QDateTime periodTs = nowUTC.addSecs(-15);
// qDebug("FT8DemodBaseband::tick: %s", qPrintable(nowUTC.toString("yyyy-MM-dd HH:mm:ss")));
m_ft8Buffer.getCurrentBuffer(m_ft8WorkerBuffer);
const qint64 previousPeriodStartMs = (periodIndex - 1) * periodMs;
QDateTime periodTs = QDateTime::fromMSecsSinceEpoch(previousPeriodStartMs, Qt::UTC);
const int frameSamples = FT8DemodSettings::getDecoderFrameSamples(m_settings.m_decoderMode);
m_ft8Buffer.getCurrentBuffer(m_ft8WorkerBuffer, frameSamples);
emit bufferReady(m_ft8WorkerBuffer, periodTs);
periodTs = nowUTC;
m_lastProcessPeriodIndex = periodIndex;
}
}
else
{
m_tickCount = 0;
}
}

View File

@ -103,7 +103,7 @@ private:
MessageQueue *m_messageQueueToGUI;
SpectrumVis *m_spectrumVis;
FT8Buffer m_ft8Buffer;
int m_tickCount;
qint64 m_lastProcessPeriodIndex;
QThread *m_workerThread;
FT8DemodWorker *m_ft8DemodWorker;
QThread *m_pskReporterThread;

View File

@ -50,6 +50,7 @@ void FT8DemodSettings::resetToDefaults()
m_agc = false;
m_recordWav = false;
m_logMessages = false;
m_decoderMode = DecoderModeFT8;
m_nbDecoderThreads = 3;
m_decoderTimeBudget = 0.5;
m_useOSD = false;
@ -78,22 +79,78 @@ void FT8DemodSettings::resetToDefaults()
void FT8DemodSettings::resetBandPresets()
{
m_bandPresets.clear();
m_bandPresets.push_back(FT8DemodBandPreset{ "160m", 1840, 0});
m_bandPresets.push_back(FT8DemodBandPreset{ "80m", 3573, 0});
m_bandPresets.push_back(FT8DemodBandPreset{ "60m", 5357, 0});
m_bandPresets.push_back(FT8DemodBandPreset{ "40m", 7074, 0});
m_bandPresets.push_back(FT8DemodBandPreset{ "30m", 10136, 0});
m_bandPresets.push_back(FT8DemodBandPreset{ "20m", 14074, 0});
m_bandPresets.push_back(FT8DemodBandPreset{ "17m", 18100, 0});
m_bandPresets.push_back(FT8DemodBandPreset{ "15m", 21074, 0});
m_bandPresets.push_back(FT8DemodBandPreset{ "12m", 24915, 0});
m_bandPresets.push_back(FT8DemodBandPreset{ "10m", 28074, 0});
m_bandPresets.push_back(FT8DemodBandPreset{ "6m", 50313, 0});
m_bandPresets.push_back(FT8DemodBandPreset{ "4m", 70100, 0});
m_bandPresets.push_back(FT8DemodBandPreset{ "2m", 144120, 0});
m_bandPresets.push_back(FT8DemodBandPreset{"1.25m", 222065, 0});
m_bandPresets.push_back(FT8DemodBandPreset{ "70cm", 432065, 0});
resetBandPresets(m_decoderMode);
}
void FT8DemodSettings::resetBandPresets(int decoderMode)
{
m_bandPresets = getBandPresetsForMode(decoderMode);
}
QList<FT8DemodBandPreset> FT8DemodSettings::getBandPresetsForMode(int decoderMode)
{
QList<FT8DemodBandPreset> bandPresets;
if (decoderMode == DecoderModeFT4)
{
bandPresets.push_back(FT8DemodBandPreset{ "160m", 1840, 0});
bandPresets.push_back(FT8DemodBandPreset{ "80m", 3575, 0});
bandPresets.push_back(FT8DemodBandPreset{ "60m", 5357, 0});
bandPresets.push_back(FT8DemodBandPreset{ "40m", 7047, 500});
bandPresets.push_back(FT8DemodBandPreset{ "30m", 10140, 0});
bandPresets.push_back(FT8DemodBandPreset{ "20m", 14080, 0});
bandPresets.push_back(FT8DemodBandPreset{ "17m", 18104, 0});
bandPresets.push_back(FT8DemodBandPreset{ "15m", 21140, 0});
bandPresets.push_back(FT8DemodBandPreset{ "12m", 24919, 0});
bandPresets.push_back(FT8DemodBandPreset{ "10m", 28180, 0});
bandPresets.push_back(FT8DemodBandPreset{ "6m", 50318, 0});
bandPresets.push_back(FT8DemodBandPreset{ "4m", 70154, 0});
bandPresets.push_back(FT8DemodBandPreset{ "2m", 144170, 0});
bandPresets.push_back(FT8DemodBandPreset{"1.25m", 222065, 0});
bandPresets.push_back(FT8DemodBandPreset{ "70cm", 432065, 0});
}
else
{
bandPresets.push_back(FT8DemodBandPreset{ "160m", 1840, 0});
bandPresets.push_back(FT8DemodBandPreset{ "80m", 3573, 0});
bandPresets.push_back(FT8DemodBandPreset{ "60m", 5357, 0});
bandPresets.push_back(FT8DemodBandPreset{ "40m", 7074, 0});
bandPresets.push_back(FT8DemodBandPreset{ "30m", 10136, 0});
bandPresets.push_back(FT8DemodBandPreset{ "20m", 14074, 0});
bandPresets.push_back(FT8DemodBandPreset{ "17m", 18100, 0});
bandPresets.push_back(FT8DemodBandPreset{ "15m", 21074, 0});
bandPresets.push_back(FT8DemodBandPreset{ "12m", 24915, 0});
bandPresets.push_back(FT8DemodBandPreset{ "10m", 28074, 0});
bandPresets.push_back(FT8DemodBandPreset{ "6m", 50313, 0});
bandPresets.push_back(FT8DemodBandPreset{ "4m", 70100, 0});
bandPresets.push_back(FT8DemodBandPreset{ "2m", 144174, 0});
bandPresets.push_back(FT8DemodBandPreset{"1.25m", 222065, 0});
bandPresets.push_back(FT8DemodBandPreset{ "70cm", 432174, 0});
}
return bandPresets;
}
bool FT8DemodSettings::areBandPresetsEqual(const QList<FT8DemodBandPreset>& left, const QList<FT8DemodBandPreset>& right)
{
if (left.size() != right.size()) {
return false;
}
for (int i = 0; i < left.size(); i++)
{
if (left[i].m_name != right[i].m_name) {
return false;
}
if (left[i].m_baseFrequency != right[i].m_baseFrequency) {
return false;
}
if (left[i].m_channelOffset != right[i].m_channelOffset) {
return false;
}
}
return true;
}
QByteArray FT8DemodSettings::serialize() const
@ -117,6 +174,7 @@ QByteArray FT8DemodSettings::serialize() const
s.writeU32(5, m_rgbColor);
s.writeBool(6, m_recordWav);
s.writeBool(7, m_logMessages);
s.writeS32(10, m_decoderMode);
s.writeS32(8, m_nbDecoderThreads);
s.writeFloat(9, m_decoderTimeBudget);
s.writeBool(11, m_agc);
@ -190,6 +248,8 @@ bool FT8DemodSettings::deserialize(const QByteArray& data)
d.readU32(5, &m_rgbColor);
d.readBool(6, &m_recordWav, false);
d.readBool(7, &m_logMessages, false);
d.readS32(10, &m_decoderMode, DecoderModeFT8);
m_decoderMode = (m_decoderMode >= DecoderModeFT8) && (m_decoderMode <= DecoderModeFT4) ? m_decoderMode : DecoderModeFT8;
d.readS32(8, &m_nbDecoderThreads, 3);
d.readFloat(9, &m_decoderTimeBudget, 0.5);
d.readBool(11, &m_agc, false);
@ -269,6 +329,9 @@ void FT8DemodSettings::applySettings(const QStringList& settingsKeys, const FT8D
if (settingsKeys.contains("logMessages")) {
m_logMessages = settings.m_logMessages;
}
if (settingsKeys.contains("decoderMode")) {
m_decoderMode = settings.m_decoderMode;
}
if (settingsKeys.contains("nbDecoderThreads")) {
m_nbDecoderThreads = settings.m_nbDecoderThreads;
}
@ -359,6 +422,9 @@ QString FT8DemodSettings::getDebugString(const QStringList& settingsKeys, bool f
if (settingsKeys.contains("logMessages") || force) {
ostr << " m_logMessages: " << m_logMessages;
}
if (settingsKeys.contains("decoderMode") || force) {
ostr << " m_decoderMode: " << getDecoderModeString(m_decoderMode).toStdString();
}
if (settingsKeys.contains("nbDecoderThreads") || force) {
ostr << " m_nbDecoderThreads: " << m_nbDecoderThreads;
}
@ -458,3 +524,18 @@ QString FT8DemodSettings::getDefaultReporterSoftware() const
{
return QCoreApplication::applicationName() + " " + QCoreApplication::applicationVersion();
}
QString FT8DemodSettings::getDecoderModeString(int decoderMode)
{
return decoderMode == DecoderModeFT4 ? "FT4" : "FT8";
}
int FT8DemodSettings::getDecoderFrameDurationMs(int decoderMode)
{
return decoderMode == DecoderModeFT4 ? 7500 : 15000;
}
int FT8DemodSettings::getDecoderFrameSamples(int decoderMode)
{
return (m_ft8SampleRate * getDecoderFrameDurationMs(decoderMode)) / 1000;
}

View File

@ -54,6 +54,11 @@ struct FT8DemodBandPreset
class FT8DemodSettings
{
public:
enum DecoderMode {
DecoderModeFT8,
DecoderModeFT4
};
enum MessageCol {
MESSAGE_COL_UTC,
MESSAGE_COL_TYPE,
@ -76,6 +81,7 @@ public:
bool m_agc;
bool m_recordWav;
bool m_logMessages;
int m_decoderMode;
int m_nbDecoderThreads;
float m_decoderTimeBudget;
bool m_useOSD;
@ -114,11 +120,17 @@ public:
QByteArray serialize() const;
bool deserialize(const QByteArray& data);
void resetBandPresets();
void resetBandPresets(int decoderMode);
QString getDefaultReporterCallsign() const;
QString getDefaultReporterLocator() const;
QString getDefaultReporterSoftware() const;
void applySettings(const QStringList& settingsKeys, const FT8DemodSettings& settings);
QString getDebugString(const QStringList& settingsKeys, bool force=false) const;
static QString getDecoderModeString(int decoderMode);
static int getDecoderFrameDurationMs(int decoderMode);
static int getDecoderFrameSamples(int decoderMode);
static QList<FT8DemodBandPreset> getBandPresetsForMode(int decoderMode);
static bool areBandPresetsEqual(const QList<FT8DemodBandPreset>& left, const QList<FT8DemodBandPreset>& right);
static const int m_ft8SampleRate;
static const int m_minPowerThresholdDB;

View File

@ -27,6 +27,7 @@ FT8DemodSettingsDialog::FT8DemodSettingsDialog(FT8DemodSettings& settings, QStri
m_settingsKeys(settingsKeys)
{
ui->setupUi(this);
ui->decoderMode->setCurrentIndex(m_settings.m_decoderMode);
ui->decoderNbThreads->setValue(m_settings.m_nbDecoderThreads);
ui->decoderTimeBudget->setValue(m_settings.m_decoderTimeBudget);
ui->osdEnable->setChecked(m_settings.m_useOSD);
@ -110,6 +111,33 @@ void FT8DemodSettingsDialog::reject()
QDialog::reject();
}
void FT8DemodSettingsDialog::on_decoderMode_currentIndexChanged(int index)
{
const int previousDecoderMode = m_settings.m_decoderMode;
const QList<FT8DemodBandPreset> previousDefaults = FT8DemodSettings::getBandPresetsForMode(previousDecoderMode);
const bool hadDefaultBandPresets = FT8DemodSettings::areBandPresetsEqual(m_settings.m_bandPresets, previousDefaults);
m_settings.m_decoderMode = (index >= FT8DemodSettings::DecoderModeFT8) && (index <= FT8DemodSettings::DecoderModeFT4) ?
index : FT8DemodSettings::DecoderModeFT8;
if (hadDefaultBandPresets)
{
m_settings.resetBandPresets(m_settings.m_decoderMode);
ui->bands->blockSignals(true);
ui->bands->setRowCount(0);
populateBandsTable();
ui->bands->blockSignals(false);
if (!m_settingsKeys.contains("bandPresets")) {
m_settingsKeys.append("bandPresets");
}
}
if (!m_settingsKeys.contains("decoderMode")) {
m_settingsKeys.append("decoderMode");
}
}
void FT8DemodSettingsDialog::on_decoderNbThreads_valueChanged(int value)
{
m_settings.m_nbDecoderThreads = value;

View File

@ -54,6 +54,7 @@ private:
void setRow(int row, const QList<QTableWidgetItem*>& rowItems);
private slots:
void on_decoderMode_currentIndexChanged(int index);
void accept();
void reject();
void on_decoderNbThreads_valueChanged(int value);

View File

@ -27,6 +27,47 @@
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<layout class="QHBoxLayout" name="modeGroup">
<item>
<widget class="QLabel" name="decoderModeLabel">
<property name="text">
<string>Mode</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="decoderMode">
<property name="toolTip">
<string>Decoder mode. FT4 timing and reporting are wired, decoding support is pending.</string>
</property>
<item>
<property name="text">
<string>FT8</string>
</property>
</item>
<item>
<property name="text">
<string>FT4</string>
</property>
</item>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="threadsGroup">
<item>
<widget class="QLabel" name="decoderNbThreadsLabel">

View File

@ -145,12 +145,14 @@ FT8DemodWorker::FT8DemodWorker() :
m_enablePskReporter(false),
m_nbDecoderThreads(6),
m_decoderTimeBudget(0.5),
m_decoderMode(FT8DemodSettings::DecoderModeFT8),
m_useOSD(false),
m_osdDepth(0),
m_osdLDPCThreshold(70),
m_verifyOSD(false),
m_lowFreq(200),
m_highFreq(3000),
m_unsupportedModeWarningPending(true),
m_invalidSequence(true),
m_baseFrequency(0),
m_guiReportingMessageQueue(nullptr),
@ -180,11 +182,21 @@ FT8DemodWorker::FT8DemodWorker() :
FT8DemodWorker::~FT8DemodWorker()
{}
void FT8DemodWorker::setDecoderMode(int decoderMode)
{
m_decoderMode = decoderMode;
m_unsupportedModeWarningPending = true;
}
void FT8DemodWorker::processBuffer(int16_t *buffer, QDateTime periodTS)
{
qDebug("FT8DemodWorker::processBuffer: %6.3f %s %d:%f [%d:%d]",
const int frameSampleCount = FT8DemodSettings::getDecoderFrameSamples(m_decoderMode);
const QString decoderMode = FT8DemodSettings::getDecoderModeString(m_decoderMode);
qDebug("FT8DemodWorker::processBuffer: %6.3f %s mode:%s %d:%f [%d:%d]",
m_baseFrequency / 1000000.0,
qPrintable(periodTS.toString("yyyy-MM-dd HH:mm:ss")),
qPrintable(decoderMode),
m_nbDecoderThreads,
m_decoderTimeBudget,
m_lowFreq,
@ -198,6 +210,32 @@ void FT8DemodWorker::processBuffer(int16_t *buffer, QDateTime periodTS)
return;
}
if (m_decoderMode != FT8DemodSettings::DecoderModeFT8)
{
if (m_unsupportedModeWarningPending)
{
qWarning("FT8DemodWorker::processBuffer: %s decoding is not implemented yet", qPrintable(decoderMode));
m_unsupportedModeWarningPending = false;
}
if (m_recordSamples)
{
WavFileRecord *wavFileRecord = new WavFileRecord(FT8DemodSettings::m_ft8SampleRate);
QFileInfo wfi(QDir(m_samplesPath), periodTS.toString("yyyyMMdd_HHmmss"));
QString wpath = wfi.absoluteFilePath();
qDebug("FT8DemodWorker::processBuffer: WAV file: %s.wav", qPrintable(wpath));
wavFileRecord->setFileName(wpath);
wavFileRecord->setFileBaseIsFileName(true);
wavFileRecord->setMono(true);
wavFileRecord->startRecording();
wavFileRecord->writeMono(buffer, frameSampleCount);
wavFileRecord->stopRecording();
delete wavFileRecord;
}
return;
}
QString channelReference = "d0c0"; // default
if (m_channel) {
@ -211,11 +249,11 @@ void FT8DemodWorker::processBuffer(int16_t *buffer, QDateTime periodTS)
m_ft8Decoder.getParams().use_osd = m_useOSD ? 1 : 0;
m_ft8Decoder.getParams().osd_depth = m_osdDepth;
m_ft8Decoder.getParams().osd_ldpc_thresh = m_osdLDPCThreshold;
std::vector<float> samples(15*FT8DemodSettings::m_ft8SampleRate);
std::vector<float> samples(frameSampleCount);
std::transform(
buffer,
buffer + (15*FT8DemodSettings::m_ft8SampleRate),
buffer + frameSampleCount,
samples.begin(),
[](const int16_t& s) -> float { return s / 32768.0f; }
);
@ -275,9 +313,10 @@ void FT8DemodWorker::processBuffer(int16_t *buffer, QDateTime periodTS)
continue;
}
QString logMessage = QString("%1 %2 Rx FT8 %3 %4 %5 %6 %7 %8")
QString logMessage = QString("%1 %2 Rx %3 %4 %5 %6 %7 %8 %9")
.arg(periodTS.toString("yyyyMMdd_HHmmss"))
.arg(baseFrequencyMHz, 9, 'f', 3)
.arg(decoderMode)
.arg(ft8Message.snr, 6)
.arg(ft8Message.dt, 4, 'f', 1)
.arg(ft8Message.df, 4, 'f', 0)
@ -301,8 +340,9 @@ void FT8DemodWorker::processBuffer(int16_t *buffer, QDateTime periodTS)
if ((ft8Message.loc.size() == 4) && (ft8Message.loc != "RR73") && Maidenhead::fromMaidenhead(ft8Message.loc, latitude, longitude))
{
QString text = QString("%1\nMode: FT8\nFrequency: %2 Hz\nLocator: %3\nSNR: %4\nLast heard: %5")
QString text = QString("%1\nMode: %2\nFrequency: %3 Hz\nLocator: %4\nSNR: %5\nLast heard: %6")
.arg(ft8Message.call2)
.arg(decoderMode)
.arg(baseFrequencyMHz*1000000 + ft8Message.df)
.arg(ft8Message.loc)
.arg(ft8Message.snr)
@ -361,7 +401,7 @@ void FT8DemodWorker::processBuffer(int16_t *buffer, QDateTime periodTS)
wavFileRecord->setFileBaseIsFileName(true);
wavFileRecord->setMono(true);
wavFileRecord->startRecording();
wavFileRecord->writeMono(buffer, 15*FT8DemodSettings::m_ft8SampleRate);
wavFileRecord->writeMono(buffer, frameSampleCount);
wavFileRecord->stopRecording();
delete wavFileRecord;
}

View File

@ -44,6 +44,7 @@ public:
void setEnablePskReporter(bool enablePskReporter) { m_enablePskReporter = enablePskReporter; }
void setNbDecoderThreads(int nbDecoderThreads) { m_nbDecoderThreads = nbDecoderThreads; }
void setDecoderTimeBudget(float decoderTimeBudget) { m_decoderTimeBudget = decoderTimeBudget; }
void setDecoderMode(int decoderMode);
void setUseOSD(bool useOSD) { m_useOSD = useOSD; }
void setOSDDepth(int osdDepth) { m_osdDepth = osdDepth; }
void setOSDLDPCThreshold(int osdLDPCThreshold) { m_osdLDPCThreshold = osdLDPCThreshold; }
@ -97,12 +98,14 @@ private:
bool m_enablePskReporter;
int m_nbDecoderThreads;
float m_decoderTimeBudget;
int m_decoderMode;
bool m_useOSD;
int m_osdDepth;
int m_osdLDPCThreshold;
bool m_verifyOSD;
int m_lowFreq;
int m_highFreq;
bool m_unsupportedModeWarningPending;
bool m_invalidSequence;
qint64 m_baseFrequency;
FT8::FT8Decoder m_ft8Decoder;

View File

@ -23,7 +23,6 @@
const char PskReporterWorker::hostname[] = "report.pskreporter.info";
const char PskReporterWorker::service[] = "4739";
const char PskReporterWorker::test_service[] = "14739";
const char PskReporterWorker::txMode[] = "FT8";
const unsigned char PskReporterWorker::rxDescriptor[] = {
0x00, 0x03, // Template Set ID
0x00, 0x24, // Length
@ -69,6 +68,7 @@ const unsigned char PskReporterWorker::txDescriptor[] = {
}; // "PSKREPORTER_TX"
PskReporterWorker::PskReporterWorker() :
m_txMode("FT8"),
m_udpSocket(new QUdpSocket(this))
{
connect(&m_reportQueue, &MessageQueue::messageEnqueued,
@ -126,10 +126,11 @@ void PskReporterWorker::processFT8Messages(const QList<FT8Message>& ft8Messages,
txPtr +=1;
// Station Mode
const size_t modeLen = strlen(txMode);
const QByteArray txMode = m_txMode.toUtf8();
const size_t modeLen = txMode.size();
*(uint8_t *)&txInfoData[txPtr] = (uint8_t)modeLen;
txPtr += 1;
memcpy(&txInfoData[txPtr], txMode, modeLen);
memcpy(&txInfoData[txPtr], txMode.constData(), modeLen);
txPtr += modeLen;
// Station locator

View File

@ -39,6 +39,7 @@ public:
void setMyCallsign(const QString& callsign) { m_myCallsign = callsign; }
void setMyLocator(const QString& locator) { m_myLocator = locator; }
void setDecoderInfo(const QString& decoderInfo) { m_decoderInfo = decoderInfo; }
void setTxMode(const QString& txMode) { m_txMode = txMode; }
void setTestMode(bool isTestMode) { m_isTestMode = isTestMode; }
private:
@ -52,6 +53,7 @@ private:
QString m_myCallsign;
QString m_myLocator;
QString m_decoderInfo;
QString m_txMode;
bool m_isTestMode = false;
MessageQueue m_reportQueue;
QQueue<FT8Message> m_ft8MessageQueue;
@ -66,7 +68,6 @@ private:
static const char hostname[];
static const char service[];
static const char test_service[];
static const char txMode[];
static const unsigned char rxDescriptor[];
static const unsigned char txDescriptor[];