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:
parent
39374ce0b8
commit
9bb9493afd
@ -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);
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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">
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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[];
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user