diff --git a/doc/img/MainWindow_spectrum_gui.png b/doc/img/MainWindow_spectrum_gui.png index ec92eaf15..aa2e13d74 100644 Binary files a/doc/img/MainWindow_spectrum_gui.png and b/doc/img/MainWindow_spectrum_gui.png differ diff --git a/doc/img/MainWindow_spectrum_gui.xcf b/doc/img/MainWindow_spectrum_gui.xcf index 0745ac0c2..8eb84edae 100644 Binary files a/doc/img/MainWindow_spectrum_gui.xcf and b/doc/img/MainWindow_spectrum_gui.xcf differ diff --git a/sdrbase/dsp/spectrumvis.cpp b/sdrbase/dsp/spectrumvis.cpp index 5f0778d7e..bb617f61f 100644 --- a/sdrbase/dsp/spectrumvis.cpp +++ b/sdrbase/dsp/spectrumvis.cpp @@ -39,11 +39,13 @@ MESSAGE_CLASS_DEFINITION(SpectrumVis::MsgConfigureSpectrumVis, Message) MESSAGE_CLASS_DEFINITION(SpectrumVis::MsgConfigureScalingFactor, Message) MESSAGE_CLASS_DEFINITION(SpectrumVis::MsgConfigureWSpectrumOpenClose, Message) MESSAGE_CLASS_DEFINITION(SpectrumVis::MsgConfigureWSpectrum, Message) +MESSAGE_CLASS_DEFINITION(SpectrumVis::MsgStartStop, Message) const Real SpectrumVis::m_mult = (10.0f / log2f(10.0f)); SpectrumVis::SpectrumVis(Real scalef) : BasebandSampleSink(), + m_running(true), m_fft(nullptr), m_fftEngineSequence(0), m_fftBuffer(MAX_FFT_SIZE), @@ -319,8 +321,11 @@ void SpectrumVis::feed(const Complex *begin, unsigned int length) void SpectrumVis::feed(const SampleVector::const_iterator& cbegin, const SampleVector::const_iterator& end, bool positiveOnly) { - // if no visualisation is set, send the samples to /dev/null + if (!m_running) { + return; + } + // if no visualisation is set, send the samples to /dev/null if (!m_glSpectrum && !m_wsSpectrum.socketOpened()) { return; } @@ -621,10 +626,12 @@ void SpectrumVis::feed(const SampleVector::const_iterator& cbegin, const SampleV void SpectrumVis::start() { + m_running = true; } void SpectrumVis::stop() { + m_running = false; } bool SpectrumVis::handleMessage(const Message& message) @@ -663,6 +670,17 @@ bool SpectrumVis::handleMessage(const Message& message) handleConfigureWSSpectrum(conf.getAddress(), conf.getPort()); return true; } + else if (MsgStartStop::match(message)) { + MsgStartStop& cmd = (MsgStartStop&) message; + + if (cmd.getStartStop()) { + start(); + } else { + stop(); + } + + return true; + } else { return false; diff --git a/sdrbase/dsp/spectrumvis.h b/sdrbase/dsp/spectrumvis.h index 311411ef0..ad87a50b8 100644 --- a/sdrbase/dsp/spectrumvis.h +++ b/sdrbase/dsp/spectrumvis.h @@ -63,6 +63,25 @@ public: { } }; + class MsgStartStop : public Message { + MESSAGE_CLASS_DECLARATION + + public: + bool getStartStop() const { return m_startStop; } + + static MsgStartStop* create(bool startStop) { + return new MsgStartStop(startStop); + } + + protected: + bool m_startStop; + + MsgStartStop(bool startStop) : + Message(), + m_startStop(startStop) + { } + }; + enum AvgMode { AvgModeNone, @@ -150,6 +169,7 @@ private: uint16_t m_port; }; + bool m_running; FFTEngine* m_fft; FFTWindow m_window; unsigned int m_fftEngineSequence; diff --git a/sdrgui/gui/glspectrum.cpp b/sdrgui/gui/glspectrum.cpp index c781da183..f3d8be70e 100644 --- a/sdrgui/gui/glspectrum.cpp +++ b/sdrgui/gui/glspectrum.cpp @@ -1988,6 +1988,8 @@ void GLSpectrum::mousePressEvent(QMouseEvent* event) if ((m_waterfallMarkers.size() > 0) && (pWat.x() >= 0) && (pWat.x() <= 1) && (pWat.y() >= 0) && (pWat.y() <= 1)) { m_waterfallMarkers.pop_back(); } + + update(); } else if (event->button() == Qt::LeftButton) { @@ -2076,6 +2078,8 @@ void GLSpectrum::mousePressEvent(QMouseEvent* event) } } } + + update(); } if (m_cursorState == CSSplitter) diff --git a/sdrgui/gui/glspectrumgui.cpp b/sdrgui/gui/glspectrumgui.cpp index 24882b1b7..f42bda634 100644 --- a/sdrgui/gui/glspectrumgui.cpp +++ b/sdrgui/gui/glspectrumgui.cpp @@ -340,6 +340,12 @@ void GLSpectrumGUI::on_clearSpectrum_clicked(bool checked) } } +void GLSpectrumGUI::on_freeze_toggled(bool checked) +{ + SpectrumVis::MsgStartStop *msg = SpectrumVis::MsgStartStop::create(!checked); + m_spectrumVis->getInputMessageQueue()->push(msg); +} + int GLSpectrumGUI::getAveragingMaxScale(GLSpectrumSettings::AveragingMode averagingMode) { if (averagingMode == GLSpectrumSettings::AvgModeMoving) { diff --git a/sdrgui/gui/glspectrumgui.h b/sdrgui/gui/glspectrumgui.h index db04e7dd1..147f3c3ae 100644 --- a/sdrgui/gui/glspectrumgui.h +++ b/sdrgui/gui/glspectrumgui.h @@ -101,6 +101,7 @@ private slots: void on_invert_toggled(bool checked); void on_grid_toggled(bool checked); void on_clearSpectrum_clicked(bool checked); + void on_freeze_toggled(bool checked); void handleInputMessages(); }; diff --git a/sdrgui/gui/glspectrumgui.ui b/sdrgui/gui/glspectrumgui.ui index aa8040c00..65599b789 100644 --- a/sdrgui/gui/glspectrumgui.ui +++ b/sdrgui/gui/glspectrumgui.ui @@ -312,24 +312,26 @@ - - - Qt::Horizontal + + + Play/Pause spectrum display - - - 40 - 20 - + + + :/pause.png + :/play.png:/pause.png - + + true + + - 2 + 3 diff --git a/sdrgui/readme.md b/sdrgui/readme.md index 996007426..a741b7b3a 100644 --- a/sdrgui/readme.md +++ b/sdrgui/readme.md @@ -453,6 +453,72 @@ Use this toggle button to switch between spectrum logarithmic and linear scale d When in linear mode the range control (4.4) has no effect because the actual range is between 0 and the reference level. The reference level in dB (4.3) still applies but is translated to a linear value e.g -40 dB is 1e-4. In linear mode the scale numbers are formatted using scientific notation so that they always occupy the same space. +

4.K. Spectrum live display pause/resume (freeze)

+ +Use this control to pause or resume spectrum live display. You can use this control to freeze the spectrum display. This may be useful to make measurements using the markers (see section 7). + +

4.L. Spectrum server control

+ +⚠ Note: this is a v5 feature only. + +A websockets based server can be used to send spectrum data to clients. An example of such client can be found in the [SDRangelSpectrum](https://github.com/f4exb/sdrangelspectrum) project. + + - Left button: toggles server on/off + - Right button: opens a secondary dialog that lets you choose the server listening (local) address and port. + +The server only sends data. Control including FFT details is done via the REST API. FFT frames are formatted as follows (in bytes): + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OffsetLengthValue
08Center frequency in Hz as 64 bit integer
88Effective FFT time in milliseconds as 64 bit integer
168Unix timestamp in milliseconds as 64 bit integer
244FFT size as 32 bit integer
284FFT bandwidth in Hz as 32 bit integer
324 + Indicators as 32 bit integer LSB to MSB: +
    +
  • bit 0: Linear (1) / log (0) spectrum indicator
  • +
  • bit 1: SSB (1) / DSB (0) spectrum indicator
  • +
  • bit 2: USB (1) / LSB (0) spectrum indicator
  • +
+
36N*4Vector of N = FFT size 32 bit floating point spectrum power values either log (dB) or linear
+

5. Presets and commands

The presets and commands tree view are by default stacked in tabs. The following sections describe the presets section 5A) and commands (section 5B) views successively