From 47da4a20238413e503c40b2d14c9df6227b62722 Mon Sep 17 00:00:00 2001 From: f4exb Date: Thu, 8 Feb 2018 16:45:00 +0100 Subject: [PATCH] Perseus support (8) --- CMakeLists.txt | 4 + plugins/samplesource/perseus/CMakeLists.txt | 4 +- plugins/samplesource/perseus/perseusgui.cpp | 352 ++++++++++++++++++++ plugins/samplesource/perseus/perseusgui.h | 91 +++++ plugins/samplesource/perseus/perseusinput.h | 2 + 5 files changed, 451 insertions(+), 2 deletions(-) create mode 100644 plugins/samplesource/perseus/perseusgui.cpp create mode 100644 plugins/samplesource/perseus/perseusgui.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 6c46eea7e..ac8d8a3be 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -188,8 +188,12 @@ endif() # Compiler flags. if (RX_SAMPLE_24BIT) + message(STATUS "Compiling for 24 bit Rx DSP chain") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSDR_RX_SAMPLE_24BIT") +else() + message(STATUS "Compiling for 16 bit Rx DSP chain") endif() + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -fmax-errors=10 -ffast-math -ftree-vectorize ${EXTRA_FLAGS}") ############################################################################## diff --git a/plugins/samplesource/perseus/CMakeLists.txt b/plugins/samplesource/perseus/CMakeLists.txt index b6c415333..65d62d256 100644 --- a/plugins/samplesource/perseus/CMakeLists.txt +++ b/plugins/samplesource/perseus/CMakeLists.txt @@ -3,7 +3,7 @@ project(perseus) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") set(perseus_SOURCES -# perseusgui.cpp + perseusgui.cpp perseusinput.cpp # perseusplugin.cpp perseussettings.cpp @@ -11,7 +11,7 @@ set(perseus_SOURCES ) set(perseus_HEADERS -# perseusgui.h + perseusgui.h perseusinput.h # perseusplugin.h perseussettings.h diff --git a/plugins/samplesource/perseus/perseusgui.cpp b/plugins/samplesource/perseus/perseusgui.cpp new file mode 100644 index 000000000..0e851f29d --- /dev/null +++ b/plugins/samplesource/perseus/perseusgui.cpp @@ -0,0 +1,352 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2018 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 // +// // +// 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 +#include + +#include +#include "device/deviceuiset.h" +#include + +#include "ui_perseusgui.h" +#include "gui/colormapper.h" +#include "gui/glspectrum.h" +#include "dsp/dspengine.h" +#include "dsp/dspcommands.h" +#include "perseusgui.h" + +PerseusGui::PerseusGui(DeviceUISet *deviceUISet, QWidget* parent) : + QWidget(parent), + ui(new Ui::PerseusGui), + m_deviceUISet(deviceUISet), + m_doApplySettings(true), + m_forceSettings(true), + m_settings(), + m_sampleSource(0), + m_lastEngineState((DSPDeviceSourceEngine::State)-1) +{ + m_sampleSource = (PerseusInput*) m_deviceUISet->m_deviceSourceAPI->getSampleSource(); + + ui->setupUi(this); + ui->centerFrequency->setColorMapper(ColorMapper(ColorMapper::GrayGold)); + + connect(&m_updateTimer, SIGNAL(timeout()), this, SLOT(updateHardware())); + connect(&m_statusTimer, SIGNAL(timeout()), this, SLOT(updateStatus())); + m_statusTimer.start(500); + + displaySettings(); + + m_rates = m_sampleSource->getSampleRates(); + displaySampleRates(); + connect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()), Qt::QueuedConnection); + + sendSettings(); +} + +PerseusGui::~PerseusGui() +{ + delete ui; +} + +void PerseusGui::destroy() +{ + delete this; +} + +void PerseusGui::setName(const QString& name) +{ + setObjectName(name); +} + +QString PerseusGui::getName() const +{ + return objectName(); +} + +void PerseusGui::resetToDefaults() +{ + m_settings.resetToDefaults(); + displaySettings(); + sendSettings(); +} + +qint64 PerseusGui::getCenterFrequency() const +{ + return m_settings.m_centerFrequency; +} + +void PerseusGui::setCenterFrequency(qint64 centerFrequency) +{ + m_settings.m_centerFrequency = centerFrequency; + displaySettings(); + sendSettings(); +} + +QByteArray PerseusGui::serialize() const +{ + return m_settings.serialize(); +} + +bool PerseusGui::deserialize(const QByteArray& data) +{ + if(m_settings.deserialize(data)) { + displaySettings(); + m_forceSettings = true; + sendSettings(); + return true; + } else { + resetToDefaults(); + return false; + } +} + +bool PerseusGui::handleMessage(const Message& message) +{ + // Returned messages to update the GUI (usually from web interface) + if (PerseusInput::MsgConfigurePerseus::match(message)) + { + const PerseusInput::MsgConfigurePerseus& cfg = (PerseusInput::MsgConfigurePerseus&) message; + m_settings = cfg.getSettings(); + blockApplySettings(true); + displaySettings(); + blockApplySettings(false); + return true; + } + else if (PerseusInput::MsgStartStop::match(message)) + { + PerseusInput::MsgStartStop& notif = (PerseusInput::MsgStartStop&) message; + blockApplySettings(true); + ui->startStop->setChecked(notif.getStartStop()); + blockApplySettings(false); + + return true; + } + else + { + return false; + } +} + +void PerseusGui::handleInputMessages() +{ + Message* message; + + while ((message = m_inputMessageQueue.pop()) != 0) + { + if (DSPSignalNotification::match(*message)) + { + DSPSignalNotification* notif = (DSPSignalNotification*) message; + m_sampleRate = notif->getSampleRate(); + m_deviceCenterFrequency = notif->getCenterFrequency(); + qDebug("PerseusGui::handleInputMessages: DSPSignalNotification: SampleRate:%d, CenterFrequency:%llu", notif->getSampleRate(), notif->getCenterFrequency()); + updateSampleRateAndFrequency(); + + delete message; + } + else + { + qDebug("PerseusGui::handleInputMessages: message: %s", message->getIdentifier()); + + if (handleMessage(*message)) + { + delete message; + } + } + } +} + +void PerseusGui::updateSampleRateAndFrequency() +{ + m_deviceUISet->getSpectrum()->setSampleRate(m_sampleRate); + m_deviceUISet->getSpectrum()->setCenterFrequency(m_deviceCenterFrequency); + ui->deviceRateText->setText(tr("%1k").arg((float)m_sampleRate / 1000)); +} + +void PerseusGui::displaySettings() +{ + blockApplySettings(true); + ui->transverter->setDeltaFrequency(m_settings.m_transverterDeltaFrequency); + ui->transverter->setDeltaFrequencyActive(m_settings.m_transverterMode); + ui->centerFrequency->setValue(m_settings.m_centerFrequency / 1000); + ui->LOppm->setValue(m_settings.m_LOppmTenths); + ui->LOppmText->setText(QString("%1").arg(QString::number(m_settings.m_LOppmTenths/10.0, 'f', 1))); + ui->sampleRate->setCurrentIndex(m_settings.m_devSampleRateIndex); + ui->decim->setCurrentIndex(m_settings.m_log2Decim); + blockApplySettings(false); +} + +void PerseusGui::displaySampleRates() +{ + unsigned int savedIndex = m_settings.m_devSampleRateIndex; + ui->sampleRate->blockSignals(true); + + if (m_rates.size() > 0) + { + ui->sampleRate->clear(); + + for (unsigned int i = 0; i < m_rates.size(); i++) + { + int sampleRate = m_rates[i]/1000; + ui->sampleRate->addItem(QString("%1").arg(QString("%1").arg(sampleRate, 5, 10, QChar(' ')))); + } + } + + ui->sampleRate->blockSignals(false); + + if (savedIndex < m_rates.size()) + { + ui->sampleRate->setCurrentIndex(savedIndex); + } + else + { + ui->sampleRate->setCurrentIndex((int) m_rates.size()-1); + } +} + +void PerseusGui::sendSettings() +{ + if(!m_updateTimer.isActive()) + m_updateTimer.start(100); +} + +void PerseusGui::on_centerFrequency_changed(quint64 value) +{ + m_settings.m_centerFrequency = value * 1000; + sendSettings(); +} + +void PerseusGui::on_LOppm_valueChanged(int value) +{ + m_settings.m_LOppmTenths = value; + ui->LOppmText->setText(QString("%1").arg(QString::number(m_settings.m_LOppmTenths/10.0, 'f', 1))); + sendSettings(); +} + +void PerseusGui::on_resetLOppm_clicked() +{ + ui->LOppm->setValue(0); +} + +void PerseusGui::on_sampleRate_currentIndexChanged(int index) +{ + m_settings.m_devSampleRateIndex = index; + sendSettings(); +} + +void PerseusGui::on_decim_currentIndexChanged(int index) +{ + if ((index < 0) || (index > 5)) + return; + m_settings.m_log2Decim = index; + sendSettings(); +} + +void PerseusGui::on_startStop_toggled(bool checked) +{ + if (m_doApplySettings) + { + PerseusInput::MsgStartStop *message = PerseusInput::MsgStartStop::create(checked); + m_sampleSource->getInputMessageQueue()->push(message); + } +} + +void PerseusGui::on_record_toggled(bool checked) +{ + if (checked) { + ui->record->setStyleSheet("QToolButton { background-color : red; }"); + } else { + ui->record->setStyleSheet("QToolButton { background:rgb(79,79,79); }"); + } + + PerseusInput::MsgFileRecord* message = PerseusInput::MsgFileRecord::create(checked); + m_sampleSource->getInputMessageQueue()->push(message); +} + +void PerseusGui::on_transverter_clicked() +{ + m_settings.m_transverterMode = ui->transverter->getDeltaFrequencyAcive(); + m_settings.m_transverterDeltaFrequency = ui->transverter->getDeltaFrequency(); + qDebug("PerseusGui::on_transverter_clicked: %lld Hz %s", m_settings.m_transverterDeltaFrequency, m_settings.m_transverterMode ? "on" : "off"); + m_settings.m_centerFrequency = ui->centerFrequency->getValueNew()*1000; + sendSettings(); +} + +void PerseusGui::updateHardware() +{ + qDebug() << "PerseusGui::updateHardware"; + PerseusInput::MsgConfigurePerseus* message = PerseusInput::MsgConfigurePerseus::create(m_settings, m_forceSettings); + m_sampleSource->getInputMessageQueue()->push(message); + m_forceSettings = false; + m_updateTimer.stop(); +} + +void PerseusGui::updateStatus() +{ + int state = m_deviceUISet->m_deviceSourceAPI->state(); + + if(m_lastEngineState != state) + { + switch(state) + { + case DSPDeviceSourceEngine::StNotStarted: + ui->startStop->setStyleSheet("QToolButton { background:rgb(79,79,79); }"); + break; + case DSPDeviceSourceEngine::StIdle: + ui->startStop->setStyleSheet("QToolButton { background-color : blue; }"); + break; + case DSPDeviceSourceEngine::StRunning: + ui->startStop->setStyleSheet("QToolButton { background-color : green; }"); + break; + case DSPDeviceSourceEngine::StError: + ui->startStop->setStyleSheet("QToolButton { background-color : red; }"); + QMessageBox::information(this, tr("Message"), m_deviceUISet->m_deviceSourceAPI->errorMessage()); + break; + default: + break; + } + + m_lastEngineState = state; + } +} + +uint32_t PerseusGui::getDevSampleRate(unsigned int rate_index) +{ + if (rate_index < m_rates.size()) + { + return m_rates[rate_index]; + } + else + { + return m_rates[0]; + } +} + +int PerseusGui::getDevSampleRateIndex(uint32_t sampeRate) +{ + for (unsigned int i=0; i < m_rates.size(); i++) + { + if (sampeRate == m_rates[i]) + { + return i; + } + } + + return -1; +} + + + + diff --git a/plugins/samplesource/perseus/perseusgui.h b/plugins/samplesource/perseus/perseusgui.h new file mode 100644 index 000000000..84ff7fc41 --- /dev/null +++ b/plugins/samplesource/perseus/perseusgui.h @@ -0,0 +1,91 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2018 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 // +// // +// 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_SAMPLESOURCE_PERSEUS_PERSEUSGUI_H_ +#define PLUGINS_SAMPLESOURCE_PERSEUS_PERSEUSGUI_H_ + +#include +#include +#include + +#include "util/messagequeue.h" + +#include "perseusinput.h" + +class DeviceUISet; + +namespace Ui { + class PerseusGui; +} + +class PerseusGui : public QWidget, public PluginInstanceGUI { + Q_OBJECT + +public: + explicit PerseusGui(DeviceUISet *deviceUISet, QWidget* parent = 0); + virtual ~PerseusGui(); + virtual void destroy(); + + void setName(const QString& name); + QString getName() const; + + void resetToDefaults(); + virtual qint64 getCenterFrequency() const; + virtual void setCenterFrequency(qint64 centerFrequency); + QByteArray serialize() const; + bool deserialize(const QByteArray& data); + virtual MessageQueue* getInputMessageQueue() { return &m_inputMessageQueue; } + virtual bool handleMessage(const Message& message); + uint32_t getDevSampleRate(unsigned int index); + int getDevSampleRateIndex(uint32_t sampleRate); + +private: + Ui::PerseusGui* ui; + + DeviceUISet* m_deviceUISet; + bool m_doApplySettings; + bool m_forceSettings; + PerseusSettings m_settings; + QTimer m_updateTimer; + QTimer m_statusTimer; + std::vector m_rates; + PerseusInput* m_sampleSource; + int m_sampleRate; + quint64 m_deviceCenterFrequency; //!< Center frequency in device + int m_lastEngineState; + MessageQueue m_inputMessageQueue; + + void blockApplySettings(bool block) { m_doApplySettings = !block; } + void displaySettings(); + void displaySampleRates(); + void sendSettings(); + void updateSampleRateAndFrequency(); + +private slots: + void on_centerFrequency_changed(quint64 value); + void on_LOppm_valueChanged(int value); + void on_resetLOppm_clicked(); + void on_sampleRate_currentIndexChanged(int index); + void on_decim_currentIndexChanged(int index); + void on_startStop_toggled(bool checked); + void on_record_toggled(bool checked); + void on_transverter_clicked(); + void updateHardware(); + void updateStatus(); + void handleInputMessages(); +}; + +#endif /* PLUGINS_SAMPLESOURCE_PERSEUS_PERSEUSGUI_H_ */ diff --git a/plugins/samplesource/perseus/perseusinput.h b/plugins/samplesource/perseus/perseusinput.h index 9f647eff1..e3357813e 100644 --- a/plugins/samplesource/perseus/perseusinput.h +++ b/plugins/samplesource/perseus/perseusinput.h @@ -119,6 +119,8 @@ public: SWGSDRangel::SWGDeviceState& response, QString& errorMessage); + const std::vector& getSampleRates() const { return m_sampleRates; } + private: DeviceSourceAPI *m_deviceAPI; FileRecord *m_fileSink;