FT8 demod: band presets

This commit is contained in:
f4exb 2023-01-22 20:08:32 +01:00
parent 2b5078e000
commit 09d18ce9a3
14 changed files with 895 additions and 103 deletions

View File

@ -3269,10 +3269,11 @@ void FT8::subtract(
// ???
while (fabs(target - actual) > M_PI)
{
if (target < actual)
target += 2 * M_PI;
else
target -= 2 * M_PI;
if (target < actual) {
target += (2 * M_PI) - 1e-3; // plus epsilonn to break possible infinite loop
} else {
target -= (2 * M_PI) + 1e-3; // plus epsilonn to break possible infinite loop
}
}
// adj is to be spread evenly over the off-ramp and on-ramp samples.

View File

@ -32,10 +32,13 @@ if(NOT SERVER_MODE)
${demodft8_SOURCES}
ft8demodgui.cpp
ft8demodgui.ui
ft8demodsettingsdialog.cpp
ft8demodsettingsdialog.ui
)
set(demodft8_HEADERS
${demodft8_HEADERS}
ft8demodgui.h
ft8demodsettingsdialog.h
)
set(TARGET_NAME demodft8)
set(TARGET_LIB "Qt::Widgets")

View File

@ -32,6 +32,10 @@
#include "SWGFT8DemodReport.h"
#include "dsp/dspengine.h"
#include "dsp/dspdevicesourceengine.h"
#include "dsp/dspdevicemimoengine.h"
#include "dsp/devicesamplesource.h"
#include "dsp/devicesamplemimo.h"
#include "dsp/dspcommands.h"
#include "dsp/devicesamplemimo.h"
#include "device/deviceapi.h"
@ -104,6 +108,18 @@ void FT8Demod::setDeviceAPI(DeviceAPI *deviceAPI)
}
}
void FT8Demod::setDeviceCenterFrequency(qint64 centerFrequency, int index)
{
DSPDeviceSourceEngine *deviceSourceEngine = m_deviceAPI->getDeviceSourceEngine();
DSPDeviceMIMOEngine *deviceMIMOEngine = m_deviceAPI->getDeviceMIMOEngine();
if (deviceSourceEngine) {
deviceSourceEngine->getSource()->setCenterFrequency(centerFrequency);
} else if (deviceMIMOEngine) {
deviceMIMOEngine->getMIMO()->setSourceCenterFrequency(centerFrequency, index);
}
}
void FT8Demod::setMessageQueueToGUI(MessageQueue *queue)
{
ChannelAPI::setMessageQueueToGUI(queue);

View File

@ -95,6 +95,7 @@ public:
return m_settings.m_inputFrequencyOffset;
}
void setDeviceCenterFrequency(qint64 centerFrequency, int index);
void setMessageQueueToGUI(MessageQueue* queue) override;
uint32_t getChannelSampleRate() const { return m_running ? m_basebandSink->getChannelSampleRate() : 0; }
double getMagSq() const { return m_running ? m_basebandSink->getMagSq() : 0.0; }

View File

@ -36,6 +36,7 @@
#include "ui_ft8demodgui.h"
#include "ft8demodgui.h"
#include "ft8demod.h"
#include "ft8demodsettingsdialog.h"
FT8DemodGUI* FT8DemodGUI::create(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSampleSink *rxChannel)
{
@ -68,6 +69,7 @@ bool FT8DemodGUI::deserialize(const QByteArray& data)
ui->lowCut->setMinimum(-480);
displaySettings();
applyBandwidths(m_settings.m_filterBank[m_settings.m_filterIndex].m_spanLog2, true); // does applySettings(true)
populateBandPresets();
return true;
}
else
@ -79,6 +81,7 @@ bool FT8DemodGUI::deserialize(const QByteArray& data)
ui->lowCut->setMinimum(-480);
displaySettings();
applyBandwidths(m_settings.m_filterBank[m_settings.m_filterIndex].m_spanLog2, true); // does applySettings(true)
populateBandPresets();
return false;
}
}
@ -211,6 +214,22 @@ void FT8DemodGUI::on_filterIndex_valueChanged(int value)
applyBandwidths(m_settings.m_filterBank[m_settings.m_filterIndex].m_spanLog2, true); // does applySettings(true)
}
void FT8DemodGUI::on_applyBandPreset_clicked()
{
int bandPresetIndex = ui->bandPreset->currentIndex();
int channelShift = m_settings.m_bandPresets[bandPresetIndex].m_channelOffset; // kHz
int baseFrequency = m_settings.m_bandPresets[bandPresetIndex].m_baseFrequency; // kHz
quint64 deviceFrequency = (baseFrequency - channelShift)*1000; // Hz
m_ft8Demod->setDeviceCenterFrequency(deviceFrequency, m_settings.m_streamIndex);
if (channelShift * 1000 != m_settings.m_inputFrequencyOffset)
{
m_settings.m_inputFrequencyOffset = channelShift * 1000; // Hz
displaySettings();
applySettings();
}
}
void FT8DemodGUI::on_clearMessages_clicked()
{
ui->messages->setRowCount(0);
@ -229,18 +248,38 @@ void FT8DemodGUI::on_logMessages_toggled(bool checked)
applySettings();
}
void FT8DemodGUI::on_nbThreads_valueChanged(int value)
void FT8DemodGUI::on_settings_clicked()
{
ui->nbThreadsText->setText(tr("%1").arg(value));
m_settings.m_nbDecoderThreads = value;
applySettings();
}
FT8DemodSettings settings = m_settings;
QStringList settingsKeys;
FT8DemodSettingsDialog dialog(settings, settingsKeys);
void FT8DemodGUI::on_timeBudget_valueChanged(int value)
{
m_settings.m_decoderTimeBudget = value / 10.0f;
ui->timeBudgetText->setText(tr("%1").arg(m_settings.m_decoderTimeBudget, 0, 'f', 1));
applySettings();
if (dialog.exec() == QDialog::Accepted)
{
bool changed = false;
if (settingsKeys.contains("nbDecoderThreads"))
{
m_settings.m_nbDecoderThreads = settings.m_nbDecoderThreads;
changed = true;
}
if (settingsKeys.contains("decoderTimeBudget"))
{
m_settings.m_decoderTimeBudget = settings.m_decoderTimeBudget;
changed = true;
}
if (settingsKeys.contains("bandPresets"))
{
m_settings.m_bandPresets = settings.m_bandPresets;
populateBandPresets();
}
if (changed) {
applySettings();
}
}
}
void FT8DemodGUI::onMenuDialogCalled(const QPoint &p)
@ -377,6 +416,7 @@ FT8DemodGUI::FT8DemodGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, Baseban
// Resize the table using dummy data
resizeMessageTable();
populateBandPresets();
}
FT8DemodGUI::~FT8DemodGUI()
@ -544,10 +584,6 @@ void FT8DemodGUI::displaySettings()
ui->recordWav->setChecked(m_settings.m_recordWav);
ui->logMessages->setChecked(m_settings.m_logMessages);
ui->nbThreads->setValue(m_settings.m_nbDecoderThreads);
ui->nbThreadsText->setText(tr("%1").arg(m_settings.m_nbDecoderThreads));
ui->timeBudget->setValue(m_settings.m_decoderTimeBudget*10);
ui->timeBudgetText->setText(tr("%1").arg(m_settings.m_decoderTimeBudget, 0, 'f', 1));
updateIndexLabel();
@ -598,11 +634,11 @@ void FT8DemodGUI::makeUIConnections()
QObject::connect(ui->spanLog2, &QSlider::valueChanged, this, &FT8DemodGUI::on_spanLog2_valueChanged);
QObject::connect(ui->fftWindow, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &FT8DemodGUI::on_fftWindow_currentIndexChanged);
QObject::connect(ui->filterIndex, &QDial::valueChanged, this, &FT8DemodGUI::on_filterIndex_valueChanged);
QObject::connect(ui->applyBandPreset, &QPushButton::clicked, this, &FT8DemodGUI::on_applyBandPreset_clicked);
QObject::connect(ui->clearMessages, &QPushButton::clicked, this, &FT8DemodGUI::on_clearMessages_clicked);
QObject::connect(ui->recordWav, &ButtonSwitch::toggled, this, &FT8DemodGUI::on_recordWav_toggled);
QObject::connect(ui->logMessages, &ButtonSwitch::toggled, this, &FT8DemodGUI::on_logMessages_toggled);
QObject::connect(ui->nbThreads, &QDial::valueChanged, this, &FT8DemodGUI::on_nbThreads_valueChanged);
QObject::connect(ui->timeBudget, &QDial::valueChanged, this, &FT8DemodGUI::on_timeBudget_valueChanged);
QObject::connect(ui->settings, &QPushButton::clicked, this, &FT8DemodGUI::on_settings_clicked);
}
void FT8DemodGUI::updateAbsoluteCenterFrequency()
@ -687,3 +723,15 @@ void FT8DemodGUI::messagesReceived(const QList<FT8Message>& messages)
ui->messages->scrollToBottom();
}
}
void FT8DemodGUI::populateBandPresets()
{
ui->bandPreset->blockSignals(true);
ui->bandPreset->clear();
for (const auto& bandPreset : m_settings.m_bandPresets) {
ui->bandPreset->addItem(bandPreset.m_name);
}
ui->bandPreset->blockSignals(false);
}

View File

@ -103,6 +103,7 @@ private:
void resizeMessageTable();
void messagesReceived(const QList<FT8Message>& messages);
void populateBandPresets();
enum MessageCol {
MESSAGE_COL_UTC,
@ -126,11 +127,11 @@ private slots:
void on_spanLog2_valueChanged(int value);
void on_fftWindow_currentIndexChanged(int index);
void on_filterIndex_valueChanged(int value);
void on_applyBandPreset_clicked();
void on_clearMessages_clicked();
void on_recordWav_toggled(bool checked);
void on_logMessages_toggled(bool checked);
void on_nbThreads_valueChanged(int value);
void on_timeBudget_valueChanged(int value);
void on_settings_clicked();
void onWidgetRolled(QWidget* widget, bool rollDown);
void onMenuDialogCalled(const QPoint& p);
void handleInputMessages();

View File

@ -780,93 +780,22 @@
<item>
<layout class="QHBoxLayout" name="ft8Settings">
<item>
<widget class="QLabel" name="nbThreadsLabel">
<property name="text">
<string>Th</string>
</property>
</widget>
</item>
<item>
<widget class="QDial" name="nbThreads">
<widget class="QPushButton" name="settings">
<property name="maximumSize">
<size>
<width>24</width>
<height>24</height>
<width>32</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip">
<string>Number of decoder threads</string>
<string>Open settings dialog</string>
</property>
<property name="minimum">
<number>2</number>
</property>
<property name="maximum">
<number>12</number>
</property>
<property name="singleStep">
<number>1</number>
</property>
<property name="pageStep">
<number>1</number>
</property>
<property name="value">
<number>6</number>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="nbThreadsText">
<property name="text">
<string>6</string>
<string/>
</property>
</widget>
</item>
<item>
<widget class="Line" name="line_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="timeBudgetLabel">
<property name="text">
<string>TB</string>
</property>
</widget>
</item>
<item>
<widget class="QDial" name="timeBudget">
<property name="maximumSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
<property name="toolTip">
<string>Decoder time budget (seconds)</string>
</property>
<property name="minimum">
<number>5</number>
</property>
<property name="maximum">
<number>50</number>
</property>
<property name="singleStep">
<number>1</number>
</property>
<property name="pageStep">
<number>1</number>
</property>
<property name="value">
<number>25</number>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="timeBudgetText">
<property name="text">
<string>2.5</string>
<property name="icon">
<iconset resource="../../../sdrgui/resources/res.qrc">
<normaloff>:/tool.png</normaloff>:/tool.png</iconset>
</property>
</widget>
</item>
@ -904,7 +833,7 @@
</widget>
</item>
<item>
<widget class="QLabel" name="label">
<widget class="QLabel" name="separatorLabel">
<property name="text">
<string>/</string>
</property>
@ -918,6 +847,9 @@
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Total number of decodes displayed</string>
</property>
<property name="text">
<string>0</string>
</property>
@ -926,6 +858,43 @@
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="bandPresetLabel">
<property name="text">
<string>Band</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="bandPreset">
<property name="minimumSize">
<size>
<width>80</width>
<height>0</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="applyBandPreset">
<property name="maximumSize">
<size>
<width>32</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip">
<string>Apply selected band presets</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../../../sdrgui/resources/res.qrc">
<normaloff>:/arrow_left.png</normaloff>:/arrow_left.png</iconset>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">

View File

@ -60,11 +60,54 @@ void FT8DemodSettings::resetToDefaults()
m_workspaceIndex = 0;
m_hidden = false;
m_filterIndex = 0;
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.2m", 222065, 0});
m_bandPresets.push_back(FT8DemodBandPreset{"70cm", 432065, 0});
}
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.2m", 222065, 0});
m_bandPresets.push_back(FT8DemodBandPreset{"70cm", 432065, 0});
}
QByteArray FT8DemodSettings::serialize() const
{
SimpleSerializer s(1);
QByteArray bytetmp;
QDataStream *stream = new QDataStream(&bytetmp, QIODevice::WriteOnly);
*stream << m_bandPresets;
delete stream;
s.writeBlob(2, bytetmp);
s.writeS32(1, m_inputFrequencyOffset);
s.writeS32(3, m_volume * 10.0);
@ -123,6 +166,10 @@ bool FT8DemodSettings::deserialize(const QByteArray& data)
uint32_t utmp;
QString strtmp;
d.readBlob(2, &bytetmp);
QDataStream readStream(&bytetmp, QIODevice::ReadOnly);
readStream >> m_bandPresets;
d.readS32(1, &m_inputFrequencyOffset, 0);
d.readS32(3, &tmp, 30);
m_volume = tmp / 10.0;
@ -188,3 +235,19 @@ bool FT8DemodSettings::deserialize(const QByteArray& data)
return false;
}
}
QDataStream& operator<<(QDataStream& out, const FT8DemodBandPreset& bandPreset)
{
out << bandPreset.m_name;
out << bandPreset.m_baseFrequency;
out << bandPreset.m_channelOffset;
return out;
}
QDataStream& operator>>(QDataStream& in, FT8DemodBandPreset& bandPreset)
{
in >> bandPreset.m_name;
in >> bandPreset.m_baseFrequency;
in >> bandPreset.m_channelOffset;
return in;
}

View File

@ -20,6 +20,7 @@
#include <QByteArray>
#include <QString>
#include <QList>
#include "dsp/fftwindow.h"
@ -40,6 +41,13 @@ struct FT8DemodFilterSettings
{}
};
struct FT8DemodBandPreset
{
QString m_name;
int m_baseFrequency;
int m_channelOffset;
};
struct FT8DemodSettings
{
qint32 m_inputFrequencyOffset;
@ -65,6 +73,7 @@ struct FT8DemodSettings
// FFTWindow::Function m_fftWindow;
std::vector<FT8DemodFilterSettings> m_filterBank;
unsigned int m_filterIndex;
QList<FT8DemodBandPreset> m_bandPresets;
Serializable *m_channelMarker;
Serializable *m_spectrumGUI;
@ -77,11 +86,14 @@ struct FT8DemodSettings
void setRollupState(Serializable *rollupState) { m_rollupState = rollupState; }
QByteArray serialize() const;
bool deserialize(const QByteArray& data);
void resetBandPresets();
static const int m_ft8SampleRate;
static const int m_minPowerThresholdDB;
static const float m_mminPowerThresholdDBf;
};
QDataStream& operator<<(QDataStream& out, const FT8DemodBandPreset& bandPreset);
QDataStream& operator>>(QDataStream& in, FT8DemodBandPreset& bandPreset);
#endif /* PLUGINS_CHANNELRX_DEMODFT8_FT8DEMODSETTINGS_H_ */

View File

@ -0,0 +1,290 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2017 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 <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#include <QScrollBar>
#include <QLineEdit>
#include "ft8demodsettings.h"
#include "ft8demodsettingsdialog.h"
FT8DemodSettingsDialog::FT8DemodSettingsDialog(FT8DemodSettings& settings, QStringList& settingsKeys, QWidget* parent ) :
QDialog(parent),
ui(new Ui::FT8DemodSettingsDialog),
m_settings(settings),
m_settingsKeys(settingsKeys)
{
ui->setupUi(this);
ui->decoderNbThreads->setValue(m_settings.m_nbDecoderThreads);
ui->decoderTimeBudget->setValue(m_settings.m_decoderTimeBudget);
resizeBandsTable();
populateBandsTable();
connect(ui->bands, &QTableWidget::cellChanged, this, &FT8DemodSettingsDialog::textCellChanged);
}
FT8DemodSettingsDialog::~FT8DemodSettingsDialog()
{
}
void FT8DemodSettingsDialog::resizeBandsTable()
{
// Fill table with a row of dummy data that will size the columns nicely
// Trailing spaces are for sort arrow
int row = ui->bands->rowCount();
ui->bands->setRowCount(row + 1);
ui->bands->setItem(row, BAND_NAME, new QTableWidgetItem("123456789012345"));
ui->bands->setItem(row, BAND_BASE_FREQUENCY, new QTableWidgetItem("10000000"));
ui->bands->setItem(row, BAND_OFFSET_FREQUENCY, new QTableWidgetItem("-1000"));
ui->bands->resizeColumnsToContents();
ui->bands->removeRow(row);
}
void FT8DemodSettingsDialog::populateBandsTable()
{
// Add to messages table
int row = ui->bands->rowCount();
for (const auto& band : m_settings.m_bandPresets)
{
ui->bands->setRowCount(row + 1);
QTableWidgetItem *nameItem = new QTableWidgetItem();
QTableWidgetItem *baseFrequencyItem = new QTableWidgetItem();
QTableWidgetItem *offsetFrequencyItem = new QTableWidgetItem();
ui->bands->setItem(row, BAND_NAME, nameItem);
ui->bands->setItem(row, BAND_BASE_FREQUENCY, baseFrequencyItem);
ui->bands->setItem(row, BAND_OFFSET_FREQUENCY, offsetFrequencyItem);
nameItem->setText(band.m_name);
QLineEdit *editBaseFrequency = new QLineEdit(ui->bands);
editBaseFrequency->setValidator(new QIntValidator());
editBaseFrequency->setText(tr("%1").arg(band.m_baseFrequency));
editBaseFrequency->setAlignment(Qt::AlignRight);
editBaseFrequency->setProperty("row", row);
ui->bands->setCellWidget(row, BAND_BASE_FREQUENCY, editBaseFrequency);
QLineEdit *editOffsetFrequency = new QLineEdit(ui->bands);
editOffsetFrequency->setValidator(new QIntValidator());
editOffsetFrequency->setText(tr("%1").arg(band.m_channelOffset));
editOffsetFrequency->setAlignment(Qt::AlignRight);
editOffsetFrequency->setProperty("row", row);
ui->bands->setCellWidget(row, BAND_OFFSET_FREQUENCY, editOffsetFrequency);
connect(editBaseFrequency, &QLineEdit::editingFinished, this, &FT8DemodSettingsDialog::baseFrequencyCellChanged);
connect(editOffsetFrequency, &QLineEdit::editingFinished, this, &FT8DemodSettingsDialog::offsetFrequencyCellChanged);
row++;
}
}
void FT8DemodSettingsDialog::accept()
{
QDialog::accept();
}
void FT8DemodSettingsDialog::reject()
{
m_settingsKeys.clear();
QDialog::reject();
}
void FT8DemodSettingsDialog::on_decoderNbThreads_valueChanged(int value)
{
m_settings.m_nbDecoderThreads = value;
if (!m_settingsKeys.contains("nbDecoderThreads")) {
m_settingsKeys.append("nbDecoderThreads");
}
}
void FT8DemodSettingsDialog::on_decoderTimeBudget_valueChanged(double value)
{
m_settings.m_decoderTimeBudget = value;
if (!m_settingsKeys.contains("decoderTimeBudget")) {
m_settingsKeys.append("decoderTimeBudget");
}
}
void FT8DemodSettingsDialog::on_addBand_clicked()
{
int currentRow = ui->bands->currentRow();
const QTableWidgetItem *currentNameItem = ui->bands->item(currentRow, BAND_NAME);
FT8DemodBandPreset newPreset({"", 0, 0});
if (currentNameItem) {
newPreset.m_name = currentNameItem->text();
}
QLineEdit *currentEditBaseFrequency = qobject_cast<QLineEdit*>(ui->bands->cellWidget(currentRow, BAND_BASE_FREQUENCY));
if (currentEditBaseFrequency) {
newPreset.m_baseFrequency = currentEditBaseFrequency->text().toInt();
}
QLineEdit *currentEditOffsetFrequency = qobject_cast<QLineEdit*>(ui->bands->cellWidget(currentRow, BAND_OFFSET_FREQUENCY));
if (currentEditOffsetFrequency) {
newPreset.m_channelOffset = currentEditOffsetFrequency->text().toInt();
}
m_settings.m_bandPresets.push_back(newPreset);
ui->bands->blockSignals(true);
ui->bands->setRowCount(0);
populateBandsTable();
ui->bands->blockSignals(false);
if (!m_settingsKeys.contains("bandPresets")) {
m_settingsKeys.append("bandPresets");
}
}
void FT8DemodSettingsDialog::on_deleteBand_clicked()
{
int currentRow = ui->bands->currentRow();
if (currentRow < 0) {
return;
}
m_settings.m_bandPresets.removeAt(currentRow);
ui->bands->removeRow(currentRow);
if (!m_settingsKeys.contains("bandPresets")) {
m_settingsKeys.append("bandPresets");
}
}
void FT8DemodSettingsDialog::on_moveBandUp_clicked()
{
int currentRow = ui->bands->currentRow();
if (currentRow < 1) {
return;
}
ui->bands->blockSignals(true);
QList<QTableWidgetItem*> sourceItems = takeRow(currentRow);
QList<QTableWidgetItem*> destItems = takeRow(currentRow-1);
setRow(currentRow, destItems);
setRow(currentRow-1, sourceItems);
ui->bands->blockSignals(false);
const auto sourceBandPreset = m_settings.m_bandPresets[currentRow];
const auto destBandPreset = m_settings.m_bandPresets[currentRow-1];
m_settings.m_bandPresets[currentRow] = destBandPreset;
m_settings.m_bandPresets[currentRow-1] = sourceBandPreset;
if (!m_settingsKeys.contains("bandPresets")) {
m_settingsKeys.append("bandPresets");
}
}
void FT8DemodSettingsDialog::on_moveBandDown_clicked()
{
int currentRow = ui->bands->currentRow();
if (currentRow > ui->bands->rowCount()-2) {
return;
}
ui->bands->blockSignals(true);
QList<QTableWidgetItem*> sourceItems = takeRow(currentRow);
QList<QTableWidgetItem*> destItems = takeRow(currentRow+1);
setRow(currentRow, destItems);
setRow(currentRow+1, sourceItems);
ui->bands->blockSignals(false);
const auto sourceBandPreset = m_settings.m_bandPresets[currentRow];
const auto destBandPreset = m_settings.m_bandPresets[currentRow+1];
m_settings.m_bandPresets[currentRow] = destBandPreset;
m_settings.m_bandPresets[currentRow+1] = sourceBandPreset;
if (!m_settingsKeys.contains("bandPresets")) {
m_settingsKeys.append("bandPresets");
}
}
void FT8DemodSettingsDialog::on_restoreBandPresets_clicked()
{
m_settings.resetBandPresets();
ui->bands->blockSignals(true);
ui->bands->setRowCount(0);
populateBandsTable();
ui->bands->blockSignals(false);
if (!m_settingsKeys.contains("bandPresets")) {
m_settingsKeys.append("bandPresets");
}
}
void FT8DemodSettingsDialog::textCellChanged(int row, int col)
{
if (col == BAND_NAME) {
m_settings.m_bandPresets[row].m_name = ui->bands->item(row, col)->text();
}
if (!m_settingsKeys.contains("bandPresets")) {
m_settingsKeys.append("bandPresets");
}
}
void FT8DemodSettingsDialog::baseFrequencyCellChanged()
{
QLineEdit *editBaseFrequency = qobject_cast<QLineEdit*>(sender());
if (editBaseFrequency)
{
int row = editBaseFrequency->property("row").toInt();
m_settings.m_bandPresets[row].m_baseFrequency = editBaseFrequency->text().toInt();
}
if (!m_settingsKeys.contains("bandPresets")) {
m_settingsKeys.append("bandPresets");
}
}
void FT8DemodSettingsDialog::offsetFrequencyCellChanged()
{
QLineEdit *editOffsetFrequency = qobject_cast<QLineEdit*>(sender());
if (editOffsetFrequency)
{
int row = editOffsetFrequency->property("row").toInt();
m_settings.m_bandPresets[row].m_channelOffset = editOffsetFrequency->text().toInt();
}
if (!m_settingsKeys.contains("bandPresets")) {
m_settingsKeys.append("bandPresets");
}
}
QList<QTableWidgetItem*> FT8DemodSettingsDialog::takeRow(int row)
{
QList<QTableWidgetItem*> rowItems;
for (int col = 0; col < ui->bands->columnCount(); ++col) {
rowItems << ui->bands->takeItem(row, col);
}
return rowItems;
}
void FT8DemodSettingsDialog::setRow(int row, const QList<QTableWidgetItem*>& rowItems)
{
for (int col = 0; col < ui->bands->columnCount(); ++col) {
ui->bands->setItem(row, col, rowItems.at(col));
}
}

View File

@ -0,0 +1,65 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2017 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 <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#ifndef PLUGINS_CHANNELRX_DEMODFT8_FT8DEMODSETTINGSDIALOG_H_
#define PLUGINS_CHANNELRX_DEMODFT8_FT8DEMODSETTINGSDIALOG_H_
#include "ui_ft8demodsettingsdialog.h"
class FT8DemodSettings;
class QStringList;
class QTableWidgetItem;
class FT8DemodSettingsDialog : public QDialog {
Q_OBJECT
public:
FT8DemodSettingsDialog(FT8DemodSettings& settings, QStringList& settingsKeys, QWidget* parent = nullptr);
~FT8DemodSettingsDialog();
private:
Ui::FT8DemodSettingsDialog* ui;
FT8DemodSettings& m_settings;
QStringList& m_settingsKeys;
enum BandCol {
BAND_NAME,
BAND_BASE_FREQUENCY,
BAND_OFFSET_FREQUENCY,
};
void resizeBandsTable();
void populateBandsTable();
QList<QTableWidgetItem*> takeRow(int row);
void setRow(int row, const QList<QTableWidgetItem*>& rowItems);
private slots:
void accept();
void reject();
void on_decoderNbThreads_valueChanged(int value);
void on_decoderTimeBudget_valueChanged(double value);
void on_addBand_clicked();
void on_deleteBand_clicked();
void on_moveBandUp_clicked();
void on_moveBandDown_clicked();
void on_restoreBandPresets_clicked();
void textCellChanged(int row, int col);
void baseFrequencyCellChanged();
void offsetFrequencyCellChanged();
};
#endif // PLUGINS_CHANNELRX_DEMODFT8_FT8DEMODSETTINGSDIALOG_H_

View File

@ -0,0 +1,322 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>FT8DemodSettingsDialog</class>
<widget class="QDialog" name="FT8DemodSettingsDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>349</width>
<height>316</height>
</rect>
</property>
<property name="font">
<font>
<family>Liberation Sans</family>
<pointsize>9</pointsize>
</font>
</property>
<property name="windowTitle">
<string>FT8 demod settings</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QGroupBox" name="decoderGroup">
<property name="title">
<string>Decoder</string>
</property>
<layout class="QFormLayout" name="formLayout_2">
<property name="verticalSpacing">
<number>2</number>
</property>
<item row="0" column="1">
<layout class="QHBoxLayout" name="threadsGroup">
<item>
<widget class="QLabel" name="decoderNbThreadsLabel">
<property name="text">
<string>Number of threads</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="decoderNbThreads">
<property name="toolTip">
<string>Number of decoding threads </string>
</property>
<property name="minimum">
<number>2</number>
</property>
<property name="maximum">
<number>12</number>
</property>
<property name="value">
<number>3</number>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="decoderTimeBudgetLabel">
<property name="text">
<string>Time budget (s)</string>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="decoderTimeBudget">
<property name="toolTip">
<string>Time limit for the decoder (s)</string>
</property>
<property name="decimals">
<number>1</number>
</property>
<property name="minimum">
<double>0.500000000000000</double>
</property>
<property name="maximum">
<double>5.000000000000000</double>
</property>
<property name="singleStep">
<double>0.100000000000000</double>
</property>
<property name="value">
<double>0.500000000000000</double>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="bandsGroup">
<property name="title">
<string>Band presets</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="spacing">
<number>2</number>
</property>
<item>
<widget class="QTableWidget" name="bands">
<property name="toolTip">
<string>Predefined frequencies </string>
</property>
<attribute name="verticalHeaderVisible">
<bool>false</bool>
</attribute>
<attribute name="verticalHeaderMinimumSectionSize">
<number>15</number>
</attribute>
<attribute name="verticalHeaderDefaultSectionSize">
<number>15</number>
</attribute>
<column>
<property name="text">
<string>Name</string>
</property>
<property name="toolTip">
<string>Band displayed name</string>
</property>
</column>
<column>
<property name="text">
<string>F (kHz)</string>
</property>
<property name="toolTip">
<string>Base frequency (kHz)</string>
</property>
</column>
<column>
<property name="text">
<string>off (kHz)</string>
</property>
<property name="toolTip">
<string>Channel offset frequency (kHz)</string>
</property>
</column>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="bandsControlLayout">
<item>
<widget class="QPushButton" name="addBand">
<property name="maximumSize">
<size>
<width>32</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip">
<string>Add band</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../../../sdrgui/resources/res.qrc">
<normaloff>:/create.png</normaloff>:/create.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="deleteBand">
<property name="maximumSize">
<size>
<width>32</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip">
<string>Remove selected band</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../../../sdrgui/resources/res.qrc">
<normaloff>:/bin.png</normaloff>:/bin.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="moveBandUp">
<property name="maximumSize">
<size>
<width>32</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip">
<string>Move up selected band</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../../../sdrgui/resources/res.qrc">
<normaloff>:/arrow_up.png</normaloff>:/arrow_up.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="moveBandDown">
<property name="maximumSize">
<size>
<width>32</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip">
<string>Move down selected band</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../../../sdrgui/resources/res.qrc">
<normaloff>:/arrow_down.png</normaloff>:/arrow_down.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="restoreBandPresets">
<property name="maximumSize">
<size>
<width>32</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip">
<string>Restore default band presets</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../../../sdrgui/resources/res.qrc">
<normaloff>:/recycle.png</normaloff>:/recycle.png</iconset>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<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>
</layout>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources>
<include location="../../../sdrgui/resources/res.qrc"/>
</resources>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>FT8DemodSettingsDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>FT8DemodSettingsDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -213,7 +213,7 @@ void FT8DemodWorker::processBuffer(int16_t *buffer, QDateTime periodTS)
}
QString logMessage = QString("%1 %2 Rx FT8 %3 %4 %5 %6 %7 %8")
.arg(ft8Message.ts.toString("yyyyMMdd_HHmmss"))
.arg(periodTS.toString("yyyyMMdd_HHmmss"))
.arg(baseFrequencyMHz, 9, 'f', 3)
.arg(ft8Message.snr, 6)
.arg(ft8Message.dt, 4, 'f', 1)

View File

@ -31,6 +31,7 @@
class DeviceSampleMIMO;
class BasebandSampleSink;
class BasebandSampleSource;
class MIMOChannel;
class SDRBASE_API DSPDeviceMIMOEngine : public QThread {