diff --git a/plugins/channelrx/demoddsd/dsddemod.cpp b/plugins/channelrx/demoddsd/dsddemod.cpp index 4c0e57874..d7f3dfc4e 100644 --- a/plugins/channelrx/demoddsd/dsddemod.cpp +++ b/plugins/channelrx/demoddsd/dsddemod.cpp @@ -54,6 +54,7 @@ DSDDemod::DSDDemod(DeviceSourceAPI *deviceAPI) : m_audioFifo1(48000), m_audioFifo2(48000), m_scope(0), + m_scopeXY(0), m_scopeEnabled(true), m_dsdDecoder(), m_settingsMutex(QMutex::Recursive) @@ -315,6 +316,11 @@ void DSDDemod::feed(const SampleVector::const_iterator& begin, const SampleVecto m_scope->feed(m_scopeSampleBuffer.begin(), m_scopeSampleBuffer.end(), true); // true = real samples for what it's worth } + if ((m_scopeXY != 0) && (m_scopeEnabled)) + { + m_scopeXY->feed(m_scopeSampleBuffer.begin(), m_scopeSampleBuffer.end(), true); // true = real samples for what it's worth + } + m_settingsMutex.unlock(); } diff --git a/plugins/channelrx/demoddsd/dsddemod.h b/plugins/channelrx/demoddsd/dsddemod.h index 046bab152..6a581ce2c 100644 --- a/plugins/channelrx/demoddsd/dsddemod.h +++ b/plugins/channelrx/demoddsd/dsddemod.h @@ -94,6 +94,7 @@ public: ~DSDDemod(); virtual void destroy() { delete this; } void setScopeSink(BasebandSampleSink* sampleSink) { m_scope = sampleSink; } + void setScopeXYSink(BasebandSampleSink* sampleSink) { m_scopeXY = sampleSink; } void configureMyPosition(MessageQueue* messageQueue, float myLatitude, float myLongitude); @@ -193,6 +194,7 @@ private: AudioFifo m_audioFifo1; AudioFifo m_audioFifo2; BasebandSampleSink* m_scope; + BasebandSampleSink* m_scopeXY; bool m_scopeEnabled; DSDDecoder m_dsdDecoder; diff --git a/plugins/channelrx/demoddsd/dsddemodgui.cpp b/plugins/channelrx/demoddsd/dsddemodgui.cpp index ec6966bd4..4a9e52dd0 100644 --- a/plugins/channelrx/demoddsd/dsddemodgui.cpp +++ b/plugins/channelrx/demoddsd/dsddemodgui.cpp @@ -20,13 +20,11 @@ #include #include "device/deviceuiset.h" #include -#include -#include -#include #include "dsp/threadedbasebandsamplesink.h" #include "ui_dsddemodgui.h" #include "dsp/scopevis.h" +#include "dsp/scopevisxy.h" #include "gui/glscope.h" #include "plugin/pluginapi.h" #include "util/simpleserializer.h" @@ -38,6 +36,12 @@ #include "dsddemodbaudrates.h" #include "dsddemod.h" +#include +#include +#include + +#include + DSDDemodGUI* DSDDemodGUI::create(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSampleSink *rxChannel) { DSDDemodGUI* gui = new DSDDemodGUI(pluginAPI, deviceUISet, rxChannel); @@ -270,14 +274,32 @@ DSDDemodGUI::DSDDemodGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, Baseban m_tickCount(0) { ui->setupUi(this); + ui->screenTV->setColor(true); + ui->screenTV->resizeTVScreen(200,200); + ui->screenTV->setRenderImmediate(true); setAttribute(Qt::WA_DeleteOnClose, true); connect(this, SIGNAL(widgetRolled(QWidget*,bool)), this, SLOT(onWidgetRolled(QWidget*,bool))); connect(this, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(onMenuDialogCalled(const QPoint &))); m_scopeVis = new ScopeVis(SDR_RX_SCALEF, ui->glScope); + m_scopeVisXY = new ScopeVisXY(ui->screenTV); + m_scopeVisXY->setScale(2.0); + m_scopeVisXY->setPixelsPerFrame(4001); + m_scopeVisXY->setPlotRGB(qRgb(0, 220, 250)); + m_scopeVisXY->setGridRGB(qRgb(255, 255, 128)); + + for (float x = -0.84; x < 1.0; x += 0.56) + { + for (float y = -0.84; y < 1.0; y += 0.56) + { + m_scopeVisXY->addGraticulePoint(std::complex(x, y)); + } + } + m_dsdDemod = (DSDDemod*) rxChannel; //new DSDDemod(m_deviceUISet->m_deviceSourceAPI); m_dsdDemod->setScopeSink(m_scopeVis); + m_dsdDemod->setScopeXYSink(m_scopeVisXY); m_dsdDemod->setMessageQueueToGUI(getInputMessageQueue()); ui->glScope->setSampleRate(48000); @@ -329,6 +351,7 @@ DSDDemodGUI::~DSDDemodGUI() { m_deviceUISet->removeRxChannelInstance(this); delete m_dsdDemod; // TODO: check this: when the GUI closes it has to delete the demodulator + delete m_scopeVisXY; delete m_scopeVis; delete ui; } diff --git a/plugins/channelrx/demoddsd/dsddemodgui.h b/plugins/channelrx/demoddsd/dsddemodgui.h index c79648b44..a7269dfff 100644 --- a/plugins/channelrx/demoddsd/dsddemodgui.h +++ b/plugins/channelrx/demoddsd/dsddemodgui.h @@ -33,6 +33,7 @@ class PluginAPI; class DeviceUISet; class BasebandSampleSink; class ScopeVis; +class ScopeVisXY; class DSDDemod; namespace Ui { @@ -81,6 +82,7 @@ private: SignalFormat m_signalFormat; ScopeVis* m_scopeVis; + ScopeVisXY* m_scopeVisXY; DSDDemod* m_dsdDemod; bool m_enableCosineFiltering; diff --git a/plugins/channelrx/demoddsd/dsddemodgui.ui b/plugins/channelrx/demoddsd/dsddemodgui.ui index c05e60e6f..244b5228d 100644 --- a/plugins/channelrx/demoddsd/dsddemodgui.ui +++ b/plugins/channelrx/demoddsd/dsddemodgui.ui @@ -62,16 +62,7 @@ 3 - - 2 - - - 2 - - - 2 - - + 2 @@ -954,33 +945,50 @@ Discriminator Scope - - 2 - - - 2 - - - 2 - - + 2 - - - - 632 - 250 - - - - - Monospace - 8 - - - + + + + + + 0 + 0 + + + + + 432 + 200 + + + + + Monospace + 8 + + + + + + + + + 0 + 0 + + + + + 200 + 200 + + + + + @@ -1024,6 +1032,12 @@
gui/valuedialz.h
1 + + TVScreen + QWidget +
gui/tvscreen.h
+ 1 +
diff --git a/sdrgui/CMakeLists.txt b/sdrgui/CMakeLists.txt index a893a5e8a..149fff50a 100644 --- a/sdrgui/CMakeLists.txt +++ b/sdrgui/CMakeLists.txt @@ -48,6 +48,7 @@ set(sdrgui_SOURCES dsp/scopevis.cpp dsp/scopevisng.cpp dsp/scopevismulti.cpp + dsp/scopevisxy.cpp dsp/spectrumvis.cpp dsp/spectrumscopecombovis.cpp dsp/spectrumscopengcombovis.cpp @@ -105,6 +106,7 @@ set(sdrgui_HEADERS dsp/scopevis.h dsp/scopevisng.h dsp/scopevismulti.h + dsp/scopevisxy.h dsp/spectrumvis.h dsp/spectrumscopecombovis.h dsp/spectrumscopengcombovis.h diff --git a/sdrgui/dsp/scopevisxy.cpp b/sdrgui/dsp/scopevisxy.cpp new file mode 100644 index 000000000..2758417e5 --- /dev/null +++ b/sdrgui/dsp/scopevisxy.cpp @@ -0,0 +1,111 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2018 F4EXB // +// written by Edouard Griffiths // +// // +// 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 "scopevisxy.h" +#include "gui/tvscreen.h" +#include + +ScopeVisXY::ScopeVisXY(TVScreen *tvScreen) : + m_tvScreen(tvScreen), + m_scale(1.0), + m_cols(0), + m_rows(0), + m_pixelsPerFrame(480), + m_pixelCount(0), + m_plotRGB(qRgb(0, 255, 0)), + m_gridRGB(qRgb(255, 255 ,255)) +{ + setObjectName("ScopeVisXY"); +} + +ScopeVisXY::~ScopeVisXY() +{} + +void ScopeVisXY::feed(const SampleVector::const_iterator& cbegin, const SampleVector::const_iterator& end, + bool positiveOnly __attribute__((unused))) +{ + SampleVector::const_iterator begin(cbegin); + + while (begin < end) + { + float x = m_scale * (begin->m_real/SDR_RX_SCALEF); + float y = m_scale * (begin->m_imag/SDR_RX_SCALEF); + + int row = m_rows * ((1.0 - y) / 2.0); + int col = m_cols * ((1.0 + x) / 2.0); + + row = row < 0 ? 0 : row >= m_rows ? m_rows-1 : row; + col = col < 0 ? 0 : col >= m_cols ? m_cols-1 : col; + + m_tvScreen->selectRow(row); + m_tvScreen->setDataColor(col, qRed(m_plotRGB), qGreen(m_plotRGB), qBlue(m_plotRGB)); + m_pixelCount++; + + if (m_pixelCount == m_pixelsPerFrame) + { + drawGraticule(); + m_tvScreen->renderImage(0); + usleep(10000); + m_tvScreen->getSize(m_cols, m_rows); + m_tvScreen->resetImage(); + m_pixelCount = 0; + } + + ++begin; + } +} + +void ScopeVisXY::start() +{ +} + +void ScopeVisXY::stop() +{ +} + +bool ScopeVisXY::handleMessage(const Message& message __attribute__((unused))) +{ + return false; +} + +void ScopeVisXY::addGraticulePoint(const std::complex& z) { + m_graticule.push_back(z); +} + +void ScopeVisXY::clearGraticule() { + m_graticule.clear(); +} + +void ScopeVisXY::drawGraticule() +{ + std::vector >::const_iterator grIt = m_graticule.begin(); + + for (; grIt != m_graticule.end(); ++grIt) + { + int y = m_rows * ((1.0 - grIt->imag()) / 2.0); + int x = m_cols * ((1.0 + grIt->real()) / 2.0); + + for (int d = -4; d <= 4; ++d) + { + m_tvScreen->selectRow(y + d); + m_tvScreen->setDataColor(x, qRed(m_gridRGB), qGreen(m_gridRGB), qBlue(m_gridRGB)); + m_tvScreen->selectRow(y); + m_tvScreen->setDataColor(x + d, qRed(m_gridRGB), qGreen(m_gridRGB), qBlue(m_gridRGB)); + } + } +} + diff --git a/sdrgui/dsp/scopevisxy.h b/sdrgui/dsp/scopevisxy.h new file mode 100644 index 000000000..bea51e3c5 --- /dev/null +++ b/sdrgui/dsp/scopevisxy.h @@ -0,0 +1,64 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2018 F4EXB // +// written by Edouard Griffiths // +// // +// 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 SDRGUI_DSP_SCOPEVISXY_H_ +#define SDRGUI_DSP_SCOPEVISXY_H_ + +#include "dsp/basebandsamplesink.h" +#include "util/export.h" +#include "util/message.h" + +#include +#include +#include + +class TVScreen; + +class SDRGUI_API ScopeVisXY : public BasebandSampleSink { +public: + ScopeVisXY(TVScreen *tvScreen); + virtual ~ScopeVisXY(); + + virtual void feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool positiveOnly); + virtual void start(); + virtual void stop(); + virtual bool handleMessage(const Message& message); + + void setScale(float scale) { m_scale = scale; } + void setPixelsPerFrame(int pixelsPerFrame) { m_pixelsPerFrame = pixelsPerFrame; } + void setPlotRGB(const QRgb& plotRGB) { m_plotRGB = plotRGB; } + void setGridRGB(const QRgb& gridRGB) { m_gridRGB = gridRGB; } + + void addGraticulePoint(const std::complex& z); + void clearGraticule(); + +private: + void drawGraticule(); + + TVScreen *m_tvScreen; + float m_scale; + int m_cols; + int m_rows; + int m_pixelsPerFrame; + int m_pixelCount; + QRgb m_plotRGB; + QRgb m_gridRGB; + std::vector > m_graticule; +}; + + +#endif /* SDRGUI_DSP_SCOPEVISXY_H_ */ diff --git a/sdrgui/gui/glshadertvarray.h b/sdrgui/gui/glshadertvarray.h index d7b881140..408a62ef4 100644 --- a/sdrgui/gui/glshadertvarray.h +++ b/sdrgui/gui/glshadertvarray.h @@ -45,6 +45,7 @@ public: void setColor(bool blnColor) { m_blnColor = blnColor; } void InitializeGL(int intCols, int intRows); void ResizeContainer(int intCols, int intRows); + void getSize(int& intCols, int& intRows) const { intCols = m_intCols, intRows = m_intRows; } void Cleanup(); QRgb *GetRowBuffer(int intRow); void RenderPixels(unsigned char *chrData); diff --git a/sdrgui/gui/tvscreen.cpp b/sdrgui/gui/tvscreen.cpp index 729d1bacf..729421a06 100644 --- a/sdrgui/gui/tvscreen.cpp +++ b/sdrgui/gui/tvscreen.cpp @@ -38,6 +38,7 @@ TVScreen::TVScreen(bool blnColor, QWidget* parent) : m_blnConfigChanged = false; m_blnDataChanged = false; m_blnGLContextInitialized = false; + m_blnRenderImmediate = false; //Par défaut m_intAskedCols = TV_COLS; @@ -69,7 +70,10 @@ void TVScreen::renderImage(unsigned char * objData) { m_chrLastData = objData; m_blnDataChanged = true; - //update(); + + if (m_blnRenderImmediate) { + update(); + } } void TVScreen::resetImage() @@ -83,6 +87,11 @@ void TVScreen::resizeTVScreen(int intCols, int intRows) m_intAskedRows = intRows; } +void TVScreen::getSize(int& intCols, int& intRows) const +{ + m_objGLShaderArray.getSize(intCols, intRows); +} + void TVScreen::initializeGL() { m_objMutex.lock(); @@ -209,7 +218,7 @@ bool TVScreen::setDataColor(int intCol, int intRed, int intGreen, int intBlue) { if (m_blnGLContextInitialized) { - return m_objGLShaderArray.SetDataColor(intCol, qRgb(intRed, intGreen, intBlue)); + return m_objGLShaderArray.SetDataColor(intCol, qRgb(intBlue, intGreen, intRed)); // FIXME: blue <> red inversion in shader } else { diff --git a/sdrgui/gui/tvscreen.h b/sdrgui/gui/tvscreen.h index 5676f23bc..da19c653d 100644 --- a/sdrgui/gui/tvscreen.h +++ b/sdrgui/gui/tvscreen.h @@ -46,12 +46,14 @@ public: void setColor(bool blnColor); void resizeTVScreen(int intCols, int intRows); + void getSize(int& intCols, int& intRows) const; void renderImage(unsigned char * objData); QRgb* getRowBuffer(int intRow); void resetImage(); bool selectRow(int intLine); bool setDataColor(int intCol,int intRed, int intGreen, int intBlue); + void setRenderImmediate(bool blnRenderImmediate) { m_blnRenderImmediate = blnRenderImmediate; } void connectTimer(const QTimer& timer); @@ -74,6 +76,7 @@ private: QMutex m_objMutex; bool m_blnDataChanged; bool m_blnConfigChanged; + bool m_blnRenderImmediate; GLShaderTVArray m_objGLShaderArray;