1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2025-09-05 22:57:47 -04:00

TestSink spectrum display

This commit is contained in:
f4exb 2019-10-28 01:26:33 +01:00
parent 077a083336
commit dce1951e94
9 changed files with 132 additions and 13 deletions

View File

@ -25,6 +25,7 @@
#include "plugin/pluginapi.h" #include "plugin/pluginapi.h"
#include "gui/colormapper.h" #include "gui/colormapper.h"
#include "gui/glspectrum.h" #include "gui/glspectrum.h"
#include "dsp/spectrumvis.h"
#include "dsp/dspengine.h" #include "dsp/dspengine.h"
#include "dsp/dspcommands.h" #include "dsp/dspcommands.h"
@ -41,7 +42,6 @@ TestSinkGui::TestSinkGui(DeviceUISet *deviceUISet, QWidget* parent) :
m_doApplySettings(true), m_doApplySettings(true),
m_forceSettings(true), m_forceSettings(true),
m_settings(), m_settings(),
m_deviceSampleSink(0),
m_sampleRate(0), m_sampleRate(0),
m_generation(false), m_generation(false),
m_samplesCount(0), m_samplesCount(0),
@ -49,6 +49,7 @@ TestSinkGui::TestSinkGui(DeviceUISet *deviceUISet, QWidget* parent) :
m_lastEngineState(DeviceAPI::StNotStarted) m_lastEngineState(DeviceAPI::StNotStarted)
{ {
ui->setupUi(this); ui->setupUi(this);
m_sampleSink = (TestSinkOutput*) m_deviceUISet->m_deviceAPI->getSampleSink();
ui->centerFrequency->setColorMapper(ColorMapper(ColorMapper::GrayGold)); ui->centerFrequency->setColorMapper(ColorMapper(ColorMapper::GrayGold));
ui->centerFrequency->setValueRange(7, 0, pow(10,7)); ui->centerFrequency->setValueRange(7, 0, pow(10,7));
@ -56,6 +57,13 @@ TestSinkGui::TestSinkGui(DeviceUISet *deviceUISet, QWidget* parent) :
ui->sampleRate->setColorMapper(ColorMapper(ColorMapper::GrayGreenYellow)); ui->sampleRate->setColorMapper(ColorMapper(ColorMapper::GrayGreenYellow));
ui->sampleRate->setValueRange(7, 32000U, 9000000U); ui->sampleRate->setValueRange(7, 32000U, 9000000U);
m_spectrumVis = new SpectrumVis(SDR_TX_SCALEF, ui->glSpectrum);
m_sampleSink->setSpectrumSink(m_spectrumVis);
ui->glSpectrum->setCenterFrequency(m_settings.m_centerFrequency);
ui->glSpectrum->setSampleRate(m_settings.m_sampleRate*(1<<m_settings.m_log2Interp));
ui->glSpectrum->connectTimer(MainWindow::getInstance()->getMasterTimer());
ui->spectrumGUI->setBuddies(m_spectrumVis->getInputMessageQueue(), m_spectrumVis, ui->glSpectrum);
connect(&(m_deviceUISet->m_deviceAPI->getMasterTimer()), SIGNAL(timeout()), this, SLOT(tick())); connect(&(m_deviceUISet->m_deviceAPI->getMasterTimer()), SIGNAL(timeout()), this, SLOT(tick()));
connect(&m_updateTimer, SIGNAL(timeout()), this, SLOT(updateHardware())); connect(&m_updateTimer, SIGNAL(timeout()), this, SLOT(updateHardware()));
connect(&m_statusTimer, SIGNAL(timeout()), this, SLOT(updateStatus())); connect(&m_statusTimer, SIGNAL(timeout()), this, SLOT(updateStatus()));
@ -63,12 +71,12 @@ TestSinkGui::TestSinkGui(DeviceUISet *deviceUISet, QWidget* parent) :
displaySettings(); displaySettings();
m_deviceSampleSink = (TestSinkOutput*) m_deviceUISet->m_deviceAPI->getSampleSink();
connect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()), Qt::QueuedConnection); connect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()), Qt::QueuedConnection);
} }
TestSinkGui::~TestSinkGui() TestSinkGui::~TestSinkGui()
{ {
delete m_spectrumVis;
delete ui; delete ui;
} }
@ -202,7 +210,7 @@ void TestSinkGui::updateHardware()
{ {
qDebug() << "TestSinkGui::updateHardware"; qDebug() << "TestSinkGui::updateHardware";
TestSinkOutput::MsgConfigureTestSink* message = TestSinkOutput::MsgConfigureTestSink::create(m_settings, m_forceSettings); TestSinkOutput::MsgConfigureTestSink* message = TestSinkOutput::MsgConfigureTestSink::create(m_settings, m_forceSettings);
m_deviceSampleSink->getInputMessageQueue()->push(message); m_sampleSink->getInputMessageQueue()->push(message);
m_forceSettings = false; m_forceSettings = false;
m_updateTimer.stop(); m_updateTimer.stop();
} }
@ -239,12 +247,14 @@ void TestSinkGui::updateStatus()
void TestSinkGui::on_centerFrequency_changed(quint64 value) void TestSinkGui::on_centerFrequency_changed(quint64 value)
{ {
m_settings.m_centerFrequency = value * 1000; m_settings.m_centerFrequency = value * 1000;
ui->glSpectrum->setCenterFrequency(m_settings.m_centerFrequency);
sendSettings(); sendSettings();
} }
void TestSinkGui::on_sampleRate_changed(quint64 value) void TestSinkGui::on_sampleRate_changed(quint64 value)
{ {
m_settings.m_sampleRate = value; m_settings.m_sampleRate = value;
ui->glSpectrum->setSampleRate(m_settings.m_sampleRate*(1<<m_settings.m_log2Interp));
sendSettings(); sendSettings();
} }
@ -255,6 +265,7 @@ void TestSinkGui::on_interp_currentIndexChanged(int index)
} }
m_settings.m_log2Interp = index; m_settings.m_log2Interp = index;
ui->glSpectrum->setSampleRate(m_settings.m_sampleRate*(1<<m_settings.m_log2Interp));
updateSampleRateAndFrequency(); updateSampleRateAndFrequency();
sendSettings(); sendSettings();
} }
@ -264,7 +275,7 @@ void TestSinkGui::on_startStop_toggled(bool checked)
if (m_doApplySettings) if (m_doApplySettings)
{ {
TestSinkOutput::MsgStartStop *message = TestSinkOutput::MsgStartStop::create(checked); TestSinkOutput::MsgStartStop *message = TestSinkOutput::MsgStartStop::create(checked);
m_deviceSampleSink->getInputMessageQueue()->push(message); m_sampleSink->getInputMessageQueue()->push(message);
} }
} }

View File

@ -28,8 +28,9 @@
#include "testsinksettings.h" #include "testsinksettings.h"
class DeviceSampleSink; class TestSinkOutput;
class DeviceUISet; class DeviceUISet;
class SpectrumVis;
namespace Ui { namespace Ui {
class TestSinkGui; class TestSinkGui;
@ -63,7 +64,7 @@ private:
TestSinkSettings m_settings; TestSinkSettings m_settings;
QTimer m_updateTimer; QTimer m_updateTimer;
QTimer m_statusTimer; QTimer m_statusTimer;
DeviceSampleSink* m_deviceSampleSink; TestSinkOutput* m_sampleSink;
int m_sampleRate; int m_sampleRate;
quint64 m_deviceCenterFrequency; //!< Center frequency in device quint64 m_deviceCenterFrequency; //!< Center frequency in device
bool m_generation; bool m_generation;
@ -71,6 +72,7 @@ private:
std::size_t m_tickCount; std::size_t m_tickCount;
int m_lastEngineState; int m_lastEngineState;
MessageQueue m_inputMessageQueue; MessageQueue m_inputMessageQueue;
SpectrumVis* m_spectrumVis;
void blockApplySettings(bool block) { m_doApplySettings = !block; } void blockApplySettings(bool block) { m_doApplySettings = !block; }
void displaySettings(); void displaySettings();

View File

@ -7,7 +7,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>350</width> <width>350</width>
<height>190</height> <height>400</height>
</rect> </rect>
</property> </property>
<property name="sizePolicy"> <property name="sizePolicy">
@ -19,7 +19,7 @@
<property name="minimumSize"> <property name="minimumSize">
<size> <size>
<width>350</width> <width>350</width>
<height>190</height> <height>400</height>
</size> </size>
</property> </property>
<property name="font"> <property name="font">
@ -292,6 +292,35 @@
</item> </item>
</layout> </layout>
</item> </item>
<item>
<layout class="QVBoxLayout" name="spectrumLayout">
<property name="topMargin">
<number>6</number>
</property>
<property name="bottomMargin">
<number>6</number>
</property>
<item>
<widget class="GLSpectrum" name="glSpectrum" native="true">
<property name="minimumSize">
<size>
<width>200</width>
<height>200</height>
</size>
</property>
<property name="font">
<font>
<family>Liberation Mono</family>
<pointsize>8</pointsize>
</font>
</property>
</widget>
</item>
<item>
<widget class="GLSpectrumGUI" name="spectrumGUI" native="true"/>
</item>
</layout>
</item>
<item> <item>
<layout class="QHBoxLayout" name="padLayout"> <layout class="QHBoxLayout" name="padLayout">
<item> <item>
@ -323,6 +352,18 @@
<extends>QToolButton</extends> <extends>QToolButton</extends>
<header>gui/buttonswitch.h</header> <header>gui/buttonswitch.h</header>
</customwidget> </customwidget>
<customwidget>
<class>GLSpectrum</class>
<extends>QWidget</extends>
<header>gui/glspectrum.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>GLSpectrumGUI</class>
<extends>QWidget</extends>
<header>gui/glspectrumgui.h</header>
<container>1</container>
</customwidget>
</customwidgets> </customwidgets>
<resources> <resources>
<include location="../../../sdrgui/resources/res.qrc"/> <include location="../../../sdrgui/resources/res.qrc"/>

View File

@ -25,6 +25,7 @@
#include "util/simpleserializer.h" #include "util/simpleserializer.h"
#include "dsp/dspcommands.h" #include "dsp/dspcommands.h"
#include "dsp/dspengine.h" #include "dsp/dspengine.h"
#include "dsp/basebandsamplesink.h"
#include "device/deviceapi.h" #include "device/deviceapi.h"
@ -39,7 +40,8 @@ TestSinkOutput::TestSinkOutput(DeviceAPI *deviceAPI) :
m_settings(), m_settings(),
m_testSinkThread(nullptr), m_testSinkThread(nullptr),
m_deviceDescription("TestSink"), m_deviceDescription("TestSink"),
m_masterTimer(deviceAPI->getMasterTimer()) m_masterTimer(deviceAPI->getMasterTimer()),
m_spectrumSink(nullptr)
{ {
m_deviceAPI->setNbSinkStreams(1); m_deviceAPI->setNbSinkStreams(1);
} }
@ -65,6 +67,7 @@ bool TestSinkOutput::start()
qDebug() << "TestSinkOutput::start"; qDebug() << "TestSinkOutput::start";
m_testSinkThread = new TestSinkThread(&m_sampleSourceFifo); m_testSinkThread = new TestSinkThread(&m_sampleSourceFifo);
m_testSinkThread->setSpectrumSink(m_spectrumSink);
m_testSinkThread->setSamplerate(m_settings.m_sampleRate); m_testSinkThread->setSamplerate(m_settings.m_sampleRate);
m_testSinkThread->setLog2Interpolation(m_settings.m_log2Interp); m_testSinkThread->setLog2Interpolation(m_settings.m_log2Interp);
m_testSinkThread->connectTimer(m_masterTimer); m_testSinkThread->connectTimer(m_masterTimer);

View File

@ -29,6 +29,7 @@
class TestSinkThread; class TestSinkThread;
class DeviceAPI; class DeviceAPI;
class BasebandSampleSink;
class TestSinkOutput : public DeviceSampleSink { class TestSinkOutput : public DeviceSampleSink {
public: public:
@ -103,6 +104,8 @@ public:
SWGSDRangel::SWGDeviceState& response, SWGSDRangel::SWGDeviceState& response,
QString& errorMessage); QString& errorMessage);
void setSpectrumSink(BasebandSampleSink* spectrumSink) { m_spectrumSink = spectrumSink; }
private: private:
DeviceAPI *m_deviceAPI; DeviceAPI *m_deviceAPI;
QMutex m_mutex; QMutex m_mutex;
@ -111,6 +114,7 @@ private:
TestSinkThread* m_testSinkThread; TestSinkThread* m_testSinkThread;
QString m_deviceDescription; QString m_deviceDescription;
const QTimer& m_masterTimer; const QTimer& m_masterTimer;
BasebandSampleSink* m_spectrumSink;
void applySettings(const TestSinkSettings& settings, bool force = false); void applySettings(const TestSinkSettings& settings, bool force = false);
}; };

View File

@ -16,6 +16,7 @@
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////
#include "util/simpleserializer.h" #include "util/simpleserializer.h"
#include "settings/serializable.h"
#include "testsinksettings.h" #include "testsinksettings.h"
TestSinkSettings::TestSinkSettings() TestSinkSettings::TestSinkSettings()
@ -28,14 +29,20 @@ void TestSinkSettings::resetToDefaults()
m_centerFrequency = 435000*1000; m_centerFrequency = 435000*1000;
m_sampleRate = 48000; m_sampleRate = 48000;
m_log2Interp = 0; m_log2Interp = 0;
m_spectrumGUI = nullptr;
} }
QByteArray TestSinkSettings::serialize() const QByteArray TestSinkSettings::serialize() const
{ {
SimpleSerializer s(1); SimpleSerializer s(1);
s.writeU64(1, m_sampleRate); s.writeU64(1, m_centerFrequency);
s.writeU32(2, m_log2Interp); s.writeU64(2, m_sampleRate);
s.writeU32(3, m_log2Interp);
if (m_spectrumGUI) {
s.writeBlob(4, m_spectrumGUI->serialize());
}
return s.final(); return s.final();
} }
@ -52,8 +59,18 @@ bool TestSinkSettings::deserialize(const QByteArray& data)
if (d.getVersion() == 1) if (d.getVersion() == 1)
{ {
d.readU64(1, &m_sampleRate, 48000); QByteArray bytetmp;
d.readU32(2, &m_log2Interp, 0);
d.readU64(1, &m_sampleRate, 435000*1000);
d.readU64(2, &m_sampleRate, 48000);
d.readU32(3, &m_log2Interp, 0);
if (m_spectrumGUI)
{
d.readBlob(4, &bytetmp);
m_spectrumGUI->deserialize(bytetmp);
}
return true; return true;
} }
else else

View File

@ -20,15 +20,19 @@
#include <QByteArray> #include <QByteArray>
class Serializable;
struct TestSinkSettings { struct TestSinkSettings {
quint64 m_centerFrequency; quint64 m_centerFrequency;
quint64 m_sampleRate; quint64 m_sampleRate;
quint32 m_log2Interp; quint32 m_log2Interp;
Serializable *m_spectrumGUI;
TestSinkSettings(); TestSinkSettings();
void resetToDefaults(); void resetToDefaults();
QByteArray serialize() const; QByteArray serialize() const;
bool deserialize(const QByteArray& data); bool deserialize(const QByteArray& data);
void setSpectrumGUI(Serializable *spectrumGUI) { m_spectrumGUI = spectrumGUI; }
}; };
#endif /* PLUGINS_SAMPLESINK_TESTSINK_TESTSINKSETTINGS_H_ */ #endif /* PLUGINS_SAMPLESINK_TESTSINK_TESTSINKSETTINGS_H_ */

View File

@ -22,6 +22,7 @@
#include <QDebug> #include <QDebug>
#include "dsp/samplesourcefifo.h" #include "dsp/samplesourcefifo.h"
#include "dsp/basebandsamplesink.h"
#include "testsinkthread.h" #include "testsinkthread.h"
TestSinkThread::TestSinkThread(SampleSourceFifo* sampleFifo, QObject* parent) : TestSinkThread::TestSinkThread(SampleSourceFifo* sampleFifo, QObject* parent) :
@ -177,6 +178,7 @@ void TestSinkThread::tick()
if (m_log2Interpolation == 0) if (m_log2Interpolation == 0)
{ {
m_interpolators.interpolate1(&beginRead, m_buf, 2*chunkSize); m_interpolators.interpolate1(&beginRead, m_buf, 2*chunkSize);
feedSpectrum(m_buf, 2*chunkSize);
//m_ofstream->write(reinterpret_cast<char*>(&(*beginRead)), m_samplesChunkSize*sizeof(Sample)); //m_ofstream->write(reinterpret_cast<char*>(&(*beginRead)), m_samplesChunkSize*sizeof(Sample));
} }
else else
@ -206,7 +208,29 @@ void TestSinkThread::tick()
break; break;
} }
feedSpectrum(m_buf, 2*chunkSize*(1<<m_log2Interpolation));
//m_ofstream->write(reinterpret_cast<char*>(m_buf), m_samplesChunkSize*(1<<m_log2Interpolation)*2*sizeof(int16_t)); //m_ofstream->write(reinterpret_cast<char*>(m_buf), m_samplesChunkSize*(1<<m_log2Interpolation)*2*sizeof(int16_t));
} }
} }
} }
void TestSinkThread::feedSpectrum(int16_t *buf, unsigned int bufSize)
{
if (!m_spectrumSink) {
return;
}
m_samplesVector.allocate(bufSize/2);
Sample16 *s16Buf = (Sample16*) buf;
std::transform(
s16Buf,
s16Buf + (bufSize/2),
m_samplesVector.m_vector.begin(),
[](Sample16 s) -> Sample {
return Sample{s.m_real, s.m_imag};
}
);
m_spectrumSink->feed(m_samplesVector.m_vector.begin(), m_samplesVector.m_vector.begin() + (bufSize/2), false);
}

View File

@ -30,10 +30,12 @@
#include "dsp/inthalfbandfilter.h" #include "dsp/inthalfbandfilter.h"
#include "dsp/interpolators.h" #include "dsp/interpolators.h"
#include "util/incrementalvector.h"
#define TESTSINK_THROTTLE_MS 50 #define TESTSINK_THROTTLE_MS 50
class SampleSourceFifo; class SampleSourceFifo;
class BasebandSampleSink;
class TestSinkThread : public QThread { class TestSinkThread : public QThread {
Q_OBJECT Q_OBJECT
@ -50,10 +52,18 @@ public:
bool isRunning() const { return m_running; } bool isRunning() const { return m_running; }
std::size_t getSamplesCount() const { return m_samplesCount; } std::size_t getSamplesCount() const { return m_samplesCount; }
void setSamplesCount(int samplesCount) { m_samplesCount = samplesCount; } void setSamplesCount(int samplesCount) { m_samplesCount = samplesCount; }
void setSpectrumSink(BasebandSampleSink *spectrumSink) { m_spectrumSink = spectrumSink; }
void connectTimer(const QTimer& timer); void connectTimer(const QTimer& timer);
private: private:
#pragma pack(push, 1)
struct Sample16
{
int16_t m_real;
int16_t m_imag;
};
#pragma pack(pop)
QMutex m_startWaitMutex; QMutex m_startWaitMutex;
QWaitCondition m_startWaiter; QWaitCondition m_startWaiter;
volatile bool m_running; volatile bool m_running;
@ -72,8 +82,11 @@ private:
Interpolators<qint16, SDR_TX_SAMP_SZ, 16> m_interpolators; Interpolators<qint16, SDR_TX_SAMP_SZ, 16> m_interpolators;
int16_t *m_buf; int16_t *m_buf;
BasebandSampleSink* m_spectrumSink;
IncrementalVector<Sample> m_samplesVector;
void run(); void run();
void feedSpectrum(int16_t *buf, unsigned int bufSize);
private slots: private slots:
void tick(); void tick();