1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2026-06-19 22:28:35 -04:00
Files
sdrangel/sdrbase/dsp/spectrumvis.h
T
Jon Beniston 9171a205d4 Spectrum Changes:
Added optional scrollbar to be able to scroll back through waterfall.
When scrolling is enabled:
        Can adjust power scale for complete waterfall, not just future spectra.
        Waterfall time axis can use local time or UTC.
        Waterfall not lost when resizing window.
Can now zoom when device is stopped.
Added Min averaging type.
Added button to load spectrum from .csv file.
Add button to save spectrum/waterfall to .png or jpg.
Changed show all controls button to a combobox with choices of Min/Std/All (Minimum/Standard/All).
Changed some buttons in spectrum GUI from QPushButton to QToolButton so their size matches the others.
Fix spectrum from displaying a mixture of old and new spectrums (m_currentSpectrum was a pointer to SpectrumVis buffer).
Added M1 and M2 memories to allow display of reference spectra.
Added math operations to allow spectrum to be difference of current spectrum and either memory or a moving average.
Fixed measurement counts, so they are performed once per spectrum, not on displayed spectra.
Added spectrum mask measurement, to check when a spectrum exceeds mask held in M1 or M2.
Optionally display power/frequency under cursor in status line.
Optionally display peak power/frequency in status line.
Fix incorrect nyquist sample replication, when zoom used.
Fix cursor not changing from resize to pointer when moving over spectrum measurements window.
Add spectrum colour setting.
2026-03-25 16:30:13 +00:00

247 lines
8.4 KiB
C++

///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2012 maintech GmbH, Otto-Hahn-Str. 15, 97204 Hoechberg, Germany //
// written by Christian Daniel //
// Copyright (C) 2015-2022 Edouard Griffiths, F4EXB <f4exb06@gmail.com> //
// Copyright (C) 2022 Jiří Pinkava <jiri.pinkava@rossum.ai> //
// Copyright (C) 2026 Jon Beniston, M7RCE <jon@beniston.com> //
// //
// 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 INCLUDE_SPECTRUMVIS_H
#define INCLUDE_SPECTRUMVIS_H
#include <QObject>
#include <QRecursiveMutex>
#include "dsp/basebandsamplesink.h"
#include "dsp/fftengine.h"
#include "dsp/fftwindow.h"
#include "dsp/spectrumsettings.h"
#include "export.h"
#include "util/message.h"
#include "util/messagequeue.h"
#include "util/movingaverage2d.h"
#include "util/fixedaverage2d.h"
#include "util/max2d.h"
#include "util/min2d.h"
#include "websockets/wsspectrum.h"
class GLSpectrumInterface;
namespace SWGSDRangel {
class SWGGLSpectrum;
class SWGSpectrumServer;
class SWGSuccessResponse;
};
class SDRBASE_API SpectrumVis : public QObject, public BasebandSampleSink {
Q_OBJECT
public:
class SDRBASE_API MsgConfigureSpectrumVis : public Message {
MESSAGE_CLASS_DECLARATION
public:
const SpectrumSettings& getSettings() const { return m_settings; }
bool getForce() const { return m_force; }
static MsgConfigureSpectrumVis* create(const SpectrumSettings& settings, bool force) {
return new MsgConfigureSpectrumVis(settings, force);
}
private:
SpectrumSettings m_settings;
bool m_force;
MsgConfigureSpectrumVis(const SpectrumSettings& settings, bool force) :
Message(),
m_settings(settings),
m_force(force)
{ }
};
class SDRBASE_API 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)
{ }
};
class SDRBASE_API MsgConfigureWSpectrumOpenClose : public Message
{
MESSAGE_CLASS_DECLARATION
public:
Real getOpenClose() const { return m_openClose; }
static MsgConfigureWSpectrumOpenClose* create(bool openClose) {
return new MsgConfigureWSpectrumOpenClose(openClose);
}
private:
bool m_openClose;
MsgConfigureWSpectrumOpenClose(bool openClose) :
Message(),
m_openClose(openClose)
{}
};
SpectrumVis(Real scalef);
virtual ~SpectrumVis();
void setGLSpectrum(GLSpectrumInterface* glSpectrum) { m_glSpectrum = glSpectrum; }
void setWorkspaceIndex(int index) { m_workspaceIndex = index; }
int getWorkspaceIndex() const { return m_workspaceIndex; }
void setScalef(Real scalef);
void configureWSSpectrum(const QString& address, uint16_t port);
const SpectrumSettings& getSettings() const { return m_settings; }
Real getSpecMax() const { return m_specMax; }
void setMathMemory(const QList<Real> &values);
void getMathMovingAverageCopy(QList<Real>& copy);
virtual void feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool positiveOnly);
void feed(const ComplexVector::const_iterator& begin, const ComplexVector::const_iterator& end, bool positiveOnly);
void feedTriggered(const SampleVector::const_iterator& triggerPoint, const SampleVector::const_iterator& end, bool positiveOnly);
virtual void start();
virtual void stop();
virtual void pushMessage(Message *msg);
virtual QString getSinkName();
MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; }
void setMessageQueueToGUI(MessageQueue *queue) { m_guiMessageQueue = queue; }
MessageQueue *getMessageQueueToGUI() { return m_guiMessageQueue; }
int webapiSpectrumSettingsGet(SWGSDRangel::SWGGLSpectrum& response, QString& errorMessage) const;
int webapiSpectrumSettingsPutPatch(
bool force,
const QStringList& spectrumSettingsKeys,
SWGSDRangel::SWGGLSpectrum& response, // query + response
QString& errorMessage);
int webapiSpectrumServerGet(SWGSDRangel::SWGSpectrumServer& response, QString& errorMessage) const;
int webapiSpectrumServerPost(SWGSDRangel::SWGSuccessResponse& response, QString& errorMessage);
int webapiSpectrumServerDelete(SWGSDRangel::SWGSuccessResponse& response, QString& errorMessage);
private:
class MsgConfigureScalingFactor : public Message
{
MESSAGE_CLASS_DECLARATION
public:
MsgConfigureScalingFactor(Real scalef) :
Message(),
m_scalef(scalef)
{}
Real getScalef() const { return m_scalef; }
private:
Real m_scalef;
};
class MsgConfigureWSpectrum : public Message
{
MESSAGE_CLASS_DECLARATION
public:
MsgConfigureWSpectrum(const QString& address, uint16_t port) :
Message(),
m_address(address),
m_port(port)
{}
const QString& getAddress() const { return m_address; }
uint16_t getPort() const { return m_port; }
private:
QString m_address;
uint16_t m_port;
};
bool m_running;
FFTEngine* m_fft;
FFTWindow m_window;
unsigned int m_fftEngineSequence;
int m_workspaceIndex;
std::vector<Complex> m_fftBuffer;
std::vector<Real> m_powerSpectrum; //!< displayable power spectrum
std::vector<Real> m_mathMemory;
SpectrumSettings m_settings;
int m_overlapSize;
int m_refillSize;
int m_fftBufferFill;
bool m_needMoreSamples;
Real m_scalef;
GLSpectrumInterface* m_glSpectrum;
WSSpectrum m_wsSpectrum;
MovingAverage2D<double> m_movingAverage;
FixedAverage2D<double> m_fixedAverage;
Max2D<Real> m_max;
Min2D<Real> m_min;
Real m_specMax;
MovingAverage2D<double> m_mathMovingAverage;
uint64_t m_centerFrequency;
int m_sampleRate;
Real m_powFFTMul; //!< 1/fftSize^2
static const Real m_mult; //!< 10/log2(10)
MessageQueue m_inputMessageQueue;
MessageQueue *m_guiMessageQueue; //!< Input message queue to the GUI
QRecursiveMutex m_mutex;
void processFFT(bool positiveOnly);
void setRunning(bool running) { m_running = running; }
void applySettings(const SpectrumSettings& settings, bool force = false);
bool handleMessage(const Message& message);
void handleConfigureDSP(uint64_t centerFrequency, int sampleRate);
void handleScalef(Real scalef);
void handleWSOpenClose(bool openClose);
void handleConfigureWSSpectrum(const QString& address, uint16_t port);
float log2fapprox(float x) const;
void mathLinear(std::vector<Real> &spectrum);
void mathDB(std::vector<Real> &spectrum);
static void webapiFormatSpectrumSettings(SWGSDRangel::SWGGLSpectrum& response, const SpectrumSettings& settings);
static void webapiUpdateSpectrumSettings(
SpectrumSettings& settings,
const QStringList& spectrumSettingsKeys,
SWGSDRangel::SWGGLSpectrum& response);
private slots:
void handleInputMessages();
};
#endif // INCLUDE_SPECTRUMVIS_H