mirror of
https://github.com/f4exb/sdrangel.git
synced 2024-12-23 18:15:45 -05:00
1339 lines
43 KiB
C++
1339 lines
43 KiB
C++
///////////////////////////////////////////////////////////////////////////////////
|
|
// Copyright (C) 2017-2021, 2023 Edouard Griffiths, F4EXB <f4exb06@gmail.com> //
|
|
// Copyright (C) 2019 Martin Hauke <mardnh@gmx.de> //
|
|
// Copyright (C) 2020 Kacper Michajłow <kasper93@gmail.com> //
|
|
// Copyright (C) 2022 Jiří Pinkava <jiri.pinkava@rossum.ai> //
|
|
// //
|
|
// 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 SDRBASE_DSP_SCOPEVISNG_H_
|
|
#define SDRBASE_DSP_SCOPEVISNG_H_
|
|
|
|
#include <QDebug>
|
|
#include <QColor>
|
|
#include <QByteArray>
|
|
|
|
#include <algorithm>
|
|
#include <utility>
|
|
#include <cmath>
|
|
|
|
#include <stdint.h>
|
|
#include <vector>
|
|
#include "dsp/dsptypes.h"
|
|
#include "dsp/projector.h"
|
|
#include "dsp/glscopesettings.h"
|
|
#include "export.h"
|
|
#include "util/message.h"
|
|
#include "util/messagequeue.h"
|
|
#include "util/doublebuffer.h"
|
|
|
|
|
|
class GLScopeInterface;
|
|
class SpectrumVis;
|
|
|
|
class SDRBASE_API ScopeVis : public QObject {
|
|
Q_OBJECT
|
|
public:
|
|
// === messages ===
|
|
// ---------------------------------------------
|
|
class SDRBASE_API MsgConfigureScopeVis : public Message {
|
|
MESSAGE_CLASS_DECLARATION
|
|
|
|
public:
|
|
const GLScopeSettings& getSettings() const { return m_settings; }
|
|
bool getForce() const { return m_force; }
|
|
|
|
static MsgConfigureScopeVis* create(const GLScopeSettings& settings, bool force)
|
|
{
|
|
return new MsgConfigureScopeVis(settings, force);
|
|
}
|
|
|
|
private:
|
|
GLScopeSettings m_settings;
|
|
bool m_force;
|
|
|
|
MsgConfigureScopeVis(const GLScopeSettings& settings, bool force) :
|
|
Message(),
|
|
m_settings(settings),
|
|
m_force(force)
|
|
{ }
|
|
};
|
|
|
|
// ---------------------------------------------
|
|
class SDRBASE_API MsgScopeVisAddTrigger : public Message {
|
|
MESSAGE_CLASS_DECLARATION
|
|
|
|
public:
|
|
static MsgScopeVisAddTrigger* create(
|
|
const GLScopeSettings::TriggerData& triggerData)
|
|
{
|
|
return new MsgScopeVisAddTrigger(triggerData);
|
|
}
|
|
|
|
const GLScopeSettings::TriggerData& getTriggerData() const { return m_triggerData; }
|
|
|
|
private:
|
|
GLScopeSettings::TriggerData m_triggerData;
|
|
|
|
MsgScopeVisAddTrigger(const GLScopeSettings::TriggerData& triggerData) :
|
|
m_triggerData(triggerData)
|
|
{}
|
|
};
|
|
|
|
// ---------------------------------------------
|
|
class SDRBASE_API MsgScopeVisChangeTrigger : public Message {
|
|
MESSAGE_CLASS_DECLARATION
|
|
|
|
public:
|
|
static MsgScopeVisChangeTrigger* create(
|
|
const GLScopeSettings::TriggerData& triggerData, uint32_t triggerIndex)
|
|
{
|
|
return new MsgScopeVisChangeTrigger(triggerData, triggerIndex);
|
|
}
|
|
|
|
const GLScopeSettings::TriggerData& getTriggerData() const { return m_triggerData; }
|
|
uint32_t getTriggerIndex() const { return m_triggerIndex; }
|
|
|
|
private:
|
|
GLScopeSettings::TriggerData m_triggerData;
|
|
uint32_t m_triggerIndex;
|
|
|
|
MsgScopeVisChangeTrigger(const GLScopeSettings::TriggerData& triggerData, uint32_t triggerIndex) :
|
|
m_triggerData(triggerData),
|
|
m_triggerIndex(triggerIndex)
|
|
{}
|
|
};
|
|
|
|
// ---------------------------------------------
|
|
class SDRBASE_API MsgScopeVisRemoveTrigger : public Message {
|
|
MESSAGE_CLASS_DECLARATION
|
|
|
|
public:
|
|
static MsgScopeVisRemoveTrigger* create(
|
|
uint32_t triggerIndex)
|
|
{
|
|
return new MsgScopeVisRemoveTrigger(triggerIndex);
|
|
}
|
|
|
|
uint32_t getTriggerIndex() const { return m_triggerIndex; }
|
|
|
|
private:
|
|
uint32_t m_triggerIndex;
|
|
|
|
MsgScopeVisRemoveTrigger(uint32_t triggerIndex) :
|
|
m_triggerIndex(triggerIndex)
|
|
{}
|
|
};
|
|
|
|
// ---------------------------------------------
|
|
class SDRBASE_API MsgScopeVisMoveTrigger : public Message {
|
|
MESSAGE_CLASS_DECLARATION
|
|
|
|
public:
|
|
static MsgScopeVisMoveTrigger* create(
|
|
uint32_t triggerIndex,
|
|
bool moveUpElseDown)
|
|
{
|
|
return new MsgScopeVisMoveTrigger(triggerIndex, moveUpElseDown);
|
|
}
|
|
|
|
uint32_t getTriggerIndex() const { return m_triggerIndex; }
|
|
bool getMoveUp() const { return m_moveUpElseDown; }
|
|
|
|
private:
|
|
uint32_t m_triggerIndex;
|
|
bool m_moveUpElseDown;
|
|
|
|
MsgScopeVisMoveTrigger(uint32_t triggerIndex, bool moveUpElseDown) :
|
|
m_triggerIndex(triggerIndex),
|
|
m_moveUpElseDown(moveUpElseDown)
|
|
{}
|
|
};
|
|
|
|
// ---------------------------------------------
|
|
class SDRBASE_API MsgScopeVisFocusOnTrigger : public Message {
|
|
MESSAGE_CLASS_DECLARATION
|
|
|
|
public:
|
|
static MsgScopeVisFocusOnTrigger* create(
|
|
uint32_t triggerIndex)
|
|
{
|
|
return new MsgScopeVisFocusOnTrigger(triggerIndex);
|
|
}
|
|
|
|
uint32_t getTriggerIndex() const { return m_triggerIndex; }
|
|
|
|
private:
|
|
uint32_t m_triggerIndex;
|
|
|
|
MsgScopeVisFocusOnTrigger(uint32_t triggerIndex) :
|
|
m_triggerIndex(triggerIndex)
|
|
{}
|
|
};
|
|
|
|
// ---------------------------------------------
|
|
class SDRBASE_API MsgScopeVisAddTrace : public Message {
|
|
MESSAGE_CLASS_DECLARATION
|
|
|
|
public:
|
|
static MsgScopeVisAddTrace* create(
|
|
const GLScopeSettings::TraceData& traceData)
|
|
{
|
|
return new MsgScopeVisAddTrace(traceData);
|
|
}
|
|
|
|
const GLScopeSettings::TraceData& getTraceData() const { return m_traceData; }
|
|
|
|
private:
|
|
GLScopeSettings::TraceData m_traceData;
|
|
|
|
MsgScopeVisAddTrace(const GLScopeSettings::TraceData& traceData) :
|
|
m_traceData(traceData)
|
|
{}
|
|
};
|
|
|
|
// ---------------------------------------------
|
|
class SDRBASE_API MsgScopeVisChangeTrace : public Message {
|
|
MESSAGE_CLASS_DECLARATION
|
|
|
|
public:
|
|
static MsgScopeVisChangeTrace* create(
|
|
const GLScopeSettings::TraceData& traceData, uint32_t traceIndex)
|
|
{
|
|
return new MsgScopeVisChangeTrace(traceData, traceIndex);
|
|
}
|
|
|
|
const GLScopeSettings::TraceData& getTraceData() const { return m_traceData; }
|
|
uint32_t getTraceIndex() const { return m_traceIndex; }
|
|
|
|
private:
|
|
GLScopeSettings::TraceData m_traceData;
|
|
uint32_t m_traceIndex;
|
|
|
|
MsgScopeVisChangeTrace(GLScopeSettings::TraceData traceData, uint32_t traceIndex) :
|
|
m_traceData(traceData),
|
|
m_traceIndex(traceIndex)
|
|
{}
|
|
};
|
|
|
|
// ---------------------------------------------
|
|
class SDRBASE_API MsgScopeVisRemoveTrace : public Message {
|
|
MESSAGE_CLASS_DECLARATION
|
|
|
|
public:
|
|
static MsgScopeVisRemoveTrace* create(
|
|
uint32_t traceIndex)
|
|
{
|
|
return new MsgScopeVisRemoveTrace(traceIndex);
|
|
}
|
|
|
|
uint32_t getTraceIndex() const { return m_traceIndex; }
|
|
|
|
private:
|
|
uint32_t m_traceIndex;
|
|
|
|
MsgScopeVisRemoveTrace(uint32_t traceIndex) :
|
|
m_traceIndex(traceIndex)
|
|
{}
|
|
};
|
|
|
|
// ---------------------------------------------
|
|
class SDRBASE_API MsgScopeVisMoveTrace : public Message {
|
|
MESSAGE_CLASS_DECLARATION
|
|
|
|
public:
|
|
static MsgScopeVisMoveTrace* create(
|
|
uint32_t traceIndex,
|
|
bool moveUpElseDown)
|
|
{
|
|
return new MsgScopeVisMoveTrace(traceIndex, moveUpElseDown);
|
|
}
|
|
|
|
uint32_t getTraceIndex() const { return m_traceIndex; }
|
|
bool getMoveUp() const { return m_moveUpElseDown; }
|
|
|
|
private:
|
|
uint32_t m_traceIndex;
|
|
bool m_moveUpElseDown;
|
|
|
|
MsgScopeVisMoveTrace(uint32_t traceIndex, bool moveUpElseDown) :
|
|
m_traceIndex(traceIndex),
|
|
m_moveUpElseDown(moveUpElseDown)
|
|
{}
|
|
};
|
|
|
|
// ---------------------------------------------
|
|
class SDRBASE_API MsgScopeVisFocusOnTrace : public Message {
|
|
MESSAGE_CLASS_DECLARATION
|
|
|
|
public:
|
|
static MsgScopeVisFocusOnTrace* create(
|
|
uint32_t traceIndex)
|
|
{
|
|
return new MsgScopeVisFocusOnTrace(traceIndex);
|
|
}
|
|
|
|
uint32_t getTraceIndex() const { return m_traceIndex; }
|
|
|
|
private:
|
|
uint32_t m_traceIndex;
|
|
|
|
MsgScopeVisFocusOnTrace(uint32_t traceIndex) :
|
|
m_traceIndex(traceIndex)
|
|
{}
|
|
};
|
|
|
|
// ---------------------------------------------
|
|
class SDRBASE_API MsgScopeVisNGOneShot : public Message {
|
|
MESSAGE_CLASS_DECLARATION
|
|
|
|
public:
|
|
static MsgScopeVisNGOneShot* create(
|
|
bool oneShot)
|
|
{
|
|
return new MsgScopeVisNGOneShot(oneShot);
|
|
}
|
|
|
|
bool getOneShot() const { return m_oneShot; }
|
|
|
|
private:
|
|
bool m_oneShot;
|
|
|
|
MsgScopeVisNGOneShot(bool oneShot) :
|
|
m_oneShot(oneShot)
|
|
{}
|
|
};
|
|
|
|
// ---------------------------------------------
|
|
class SDRBASE_API MsgScopeVisNGMemoryTrace : public Message {
|
|
MESSAGE_CLASS_DECLARATION
|
|
|
|
public:
|
|
static MsgScopeVisNGMemoryTrace* create(
|
|
uint32_t memoryIndex)
|
|
{
|
|
return new MsgScopeVisNGMemoryTrace(memoryIndex);
|
|
}
|
|
|
|
uint32_t getMemoryIndex() const { return m_memoryIndex; }
|
|
|
|
private:
|
|
uint32_t m_memoryIndex;
|
|
|
|
MsgScopeVisNGMemoryTrace(uint32_t memoryIndex) :
|
|
m_memoryIndex(memoryIndex)
|
|
{}
|
|
};
|
|
|
|
ScopeVis();
|
|
virtual ~ScopeVis();
|
|
|
|
void setGLScope(GLScopeInterface* glScope);
|
|
void setSpectrumVis(SpectrumVis *spectrumVis) { m_spectrumVis = spectrumVis; }
|
|
void setSSBSpectrum(bool ssbSpectrum) { m_ssbSpectrum = ssbSpectrum; }
|
|
MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } //!< Get the queue for asynchronous inbound communication
|
|
|
|
void setLiveRate(int sampleRate);
|
|
void setNbStreams(uint32_t nbStreams);
|
|
void configure(
|
|
uint32_t traceSize,
|
|
uint32_t timeBase,
|
|
uint32_t timeOfsProMill,
|
|
uint32_t triggerPre,
|
|
bool freeRun
|
|
);
|
|
void configure(
|
|
GLScopeSettings::DisplayMode displayMode,
|
|
uint32_t traceIntensity,
|
|
uint32_t gridIntensity
|
|
);
|
|
void setOneShot(bool oneShot);
|
|
void setMemoryIndex(uint32_t memoryIndex);
|
|
void setTraceChunkSize(uint32_t chunkSize) { m_traceChunkSize = chunkSize; }
|
|
uint32_t getTraceChunkSize() const { return m_traceChunkSize; }
|
|
|
|
QByteArray serializeMemory() const
|
|
{
|
|
SimpleSerializer s(1);
|
|
|
|
s.writeU32(1, m_traceSize);
|
|
s.writeU32(2, m_preTriggerDelay);
|
|
s.writeS32(3, m_sampleRate);
|
|
QByteArray buffer = m_traceDiscreteMemory.serialize();
|
|
s.writeBlob(4, buffer);
|
|
|
|
return s.final();
|
|
}
|
|
|
|
bool deserializeMemory(const QByteArray& data)
|
|
{
|
|
SimpleDeserializer d(data);
|
|
|
|
if(!d.isValid()) {
|
|
return false;
|
|
}
|
|
|
|
if (d.getVersion() == 1)
|
|
{
|
|
uint32_t traceSize, preTriggerDelay;
|
|
int sampleRate;
|
|
QByteArray buf;
|
|
bool traceDiscreteMemorySuccess;
|
|
|
|
d.readU32(1, &traceSize, GLScopeSettings::m_traceChunkDefaultSize);
|
|
d.readU32(2, &preTriggerDelay, 0);
|
|
d.readS32(3, &sampleRate, 0);
|
|
setSampleRate(sampleRate);
|
|
setTraceSize(traceSize, true);
|
|
setPreTriggerDelay(preTriggerDelay, true);
|
|
d.readBlob(4, &buf);
|
|
traceDiscreteMemorySuccess = m_traceDiscreteMemory.deserialize(buf);
|
|
|
|
if (traceDiscreteMemorySuccess && (m_glScope) && (m_currentTraceMemoryIndex > 0)) {
|
|
processMemoryTrace();
|
|
}
|
|
|
|
return traceDiscreteMemorySuccess;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
void getTriggerData(GLScopeSettings::TriggerData& triggerData, uint32_t triggerIndex)
|
|
{
|
|
if (triggerIndex < m_triggerConditions.size()) {
|
|
triggerData = m_triggerConditions[triggerIndex]->m_triggerData;
|
|
}
|
|
}
|
|
|
|
void getTraceData(GLScopeSettings::TraceData& traceData, uint32_t traceIndex)
|
|
{
|
|
if (traceIndex < m_traces.m_tracesData.size()) {
|
|
traceData = m_traces.m_tracesData[traceIndex];
|
|
}
|
|
}
|
|
|
|
const GLScopeSettings::TriggerData& getTriggerData(uint32_t triggerIndex) const { return m_triggerConditions[triggerIndex]->m_triggerData; }
|
|
const std::vector<GLScopeSettings::TraceData>& getTracesData() const { return m_traces.m_tracesData; }
|
|
uint32_t getNbTriggers() const { return m_triggerConditions.size(); }
|
|
uint32_t getNbTraces() const { return m_traces.size(); }
|
|
|
|
void feed(const std::vector<SampleVector::const_iterator>& vbegin, int nbSamples);
|
|
void feed(const std::vector<ComplexVector::const_iterator>& vbegin, int nbSamples);
|
|
//virtual void start();
|
|
//virtual void stop();
|
|
bool handleMessage(const Message& message);
|
|
int getTriggerLocation() const { return m_triggerLocation; }
|
|
bool getFreeRun() const { return m_freeRun; }
|
|
|
|
private:
|
|
/**
|
|
* Trigger stuff
|
|
*/
|
|
enum TriggerState
|
|
{
|
|
TriggerUntriggered, //!< Trigger is not kicked off yet (or trigger list is empty)
|
|
TriggerTriggered, //!< Trigger has been kicked off
|
|
TriggerDelay, //!< Trigger conditions have been kicked off but it is waiting for delay before final kick off
|
|
};
|
|
|
|
struct TriggerCondition
|
|
{
|
|
public:
|
|
Projector m_projector;
|
|
GLScopeSettings::TriggerData m_triggerData; //!< Trigger data
|
|
bool m_prevCondition; //!< Condition (above threshold) at previous sample
|
|
uint32_t m_triggerDelayCount; //!< Counter of samples for delay
|
|
uint32_t m_triggerCounter; //!< Counter of trigger occurrences
|
|
uint32_t m_trues; //!< Count of true conditions for holdoff processing
|
|
uint32_t m_falses; //!< Count of false conditions for holdoff processing
|
|
|
|
|
|
TriggerCondition(const GLScopeSettings::TriggerData& triggerData) :
|
|
m_projector(Projector::ProjectionReal),
|
|
m_triggerData(triggerData),
|
|
m_prevCondition(false),
|
|
m_triggerDelayCount(0),
|
|
m_triggerCounter(0),
|
|
m_trues(0),
|
|
m_falses(0)
|
|
{
|
|
}
|
|
|
|
~TriggerCondition()
|
|
{
|
|
}
|
|
|
|
void initProjector()
|
|
{
|
|
m_projector.settProjectionType(m_triggerData.m_projectionType);
|
|
}
|
|
|
|
void releaseProjector()
|
|
{
|
|
}
|
|
|
|
void setData(const GLScopeSettings::TriggerData& triggerData)
|
|
{
|
|
m_triggerData = triggerData;
|
|
|
|
if (m_projector.getProjectionType() != m_triggerData.m_projectionType)
|
|
{
|
|
m_projector.settProjectionType(m_triggerData.m_projectionType);
|
|
}
|
|
|
|
m_prevCondition = false;
|
|
m_triggerDelayCount = 0;
|
|
m_triggerCounter = 0;
|
|
m_trues = 0;
|
|
m_falses = 0;
|
|
}
|
|
|
|
void operator=(const TriggerCondition& other)
|
|
{
|
|
setData(other.m_triggerData);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Complex trace stuff
|
|
*/
|
|
typedef DoubleBufferSimple<Complex> TraceBuffer;
|
|
|
|
struct TraceBackBuffer
|
|
{
|
|
TraceBuffer m_traceBuffer;
|
|
|
|
TraceBackBuffer() {
|
|
m_endPoint = m_traceBuffer.getCurrent();
|
|
}
|
|
|
|
void resize(uint32_t size) {
|
|
m_traceBuffer.resize(size);
|
|
}
|
|
|
|
void reset() {
|
|
m_traceBuffer.reset();
|
|
}
|
|
|
|
void write(const ComplexVector::const_iterator begin, int nbSamples) {
|
|
m_traceBuffer.write(begin, nbSamples);
|
|
}
|
|
|
|
unsigned int absoluteFill() const {
|
|
return m_traceBuffer.absoluteFill();
|
|
}
|
|
|
|
void current(ComplexVector::iterator& it) {
|
|
m_traceBuffer.getCurrent(it);
|
|
}
|
|
|
|
QByteArray serialize() const
|
|
{
|
|
SimpleSerializer s(1);
|
|
|
|
QByteArray buffer = m_traceBuffer.serialize();
|
|
unsigned int endDelta = m_endPoint - m_traceBuffer.begin();
|
|
s.writeU32(1, endDelta);
|
|
s.writeBlob(2, buffer);
|
|
|
|
return s.final();
|
|
}
|
|
|
|
bool deserialize(const QByteArray& data)
|
|
{
|
|
SimpleDeserializer d(data);
|
|
|
|
if(!d.isValid()) {
|
|
return false;
|
|
}
|
|
|
|
if (d.getVersion() == 1)
|
|
{
|
|
unsigned int tmpUInt;
|
|
QByteArray buf;
|
|
|
|
d.readU32(1, &tmpUInt, 0);
|
|
d.readBlob(2, &buf);
|
|
m_traceBuffer.deserialize(buf);
|
|
m_endPoint = m_traceBuffer.begin() + tmpUInt;
|
|
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
void setEndPoint(const ComplexVector::const_iterator& endPoint) {
|
|
m_endPoint = endPoint;
|
|
}
|
|
|
|
ComplexVector::const_iterator getEndPoint() {
|
|
return m_endPoint;
|
|
}
|
|
|
|
void getEndPoint(ComplexVector::const_iterator& it) {
|
|
it = m_endPoint;
|
|
}
|
|
|
|
private:
|
|
ComplexVector::const_iterator m_endPoint;
|
|
};
|
|
|
|
typedef std::vector<TraceBackBuffer> TraceBackBufferStream;
|
|
|
|
struct ConvertBuffers
|
|
{
|
|
ConvertBuffers(uint32_t nbStreams = 1) :
|
|
m_convertBuffers(nbStreams)
|
|
{}
|
|
|
|
void setNbStreams(uint32_t nbStreams)
|
|
{
|
|
m_convertBuffers.resize(nbStreams);
|
|
resize(m_size);
|
|
}
|
|
|
|
void resize(unsigned int size)
|
|
{
|
|
for (unsigned int s = 0; s < m_convertBuffers.size(); s++) {
|
|
m_convertBuffers[s].resize(size);
|
|
}
|
|
|
|
m_size = size;
|
|
}
|
|
|
|
unsigned int size() const {
|
|
return m_size;
|
|
}
|
|
|
|
std::vector<ComplexVector>& getBuffers() {
|
|
return m_convertBuffers;
|
|
}
|
|
|
|
private:
|
|
unsigned int m_size;
|
|
std::vector<ComplexVector> m_convertBuffers;
|
|
};
|
|
struct TraceBackDiscreteMemory
|
|
{
|
|
/**
|
|
* Give memory size in number of traces
|
|
*/
|
|
TraceBackDiscreteMemory(uint32_t size, uint32_t nbStreams = 1) :
|
|
m_traceBackBuffersStreams(nbStreams),
|
|
m_memSize(size),
|
|
m_currentMemIndex(0),
|
|
m_maxMemIndex(0),
|
|
m_traceSize(0)
|
|
{
|
|
for (unsigned int s = 0; s < m_traceBackBuffersStreams.size(); s++) {
|
|
m_traceBackBuffersStreams[s].resize(m_memSize);
|
|
}
|
|
}
|
|
|
|
void setNbStreams(uint32_t nbStreams)
|
|
{
|
|
m_traceBackBuffersStreams.resize(nbStreams);
|
|
|
|
for (unsigned int s = 0; s < m_traceBackBuffersStreams.size(); s++) {
|
|
m_traceBackBuffersStreams[s].resize(m_memSize);
|
|
}
|
|
|
|
resize(m_traceSize);
|
|
}
|
|
|
|
/**
|
|
* Resize all trace buffers in memory
|
|
*/
|
|
void resize(uint32_t size)
|
|
{
|
|
m_traceSize = size;
|
|
|
|
for (unsigned int s = 0; s < m_traceBackBuffersStreams.size(); s++)
|
|
{
|
|
for (std::vector<TraceBackBuffer>::iterator it = m_traceBackBuffersStreams[s].begin(); it != m_traceBackBuffersStreams[s].end(); ++it) {
|
|
it->resize(2*m_traceSize); // was multiplied by 4
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Move index forward by one position and return reference to the trace at this position
|
|
* Copy a trace length of samples into the new memory slot
|
|
* samplesToReport are the number of samples to report on the next trace
|
|
*/
|
|
void store(int samplesToReport)
|
|
{
|
|
uint32_t nextMemIndex = m_currentMemIndex < (m_memSize-1) ? m_currentMemIndex+1 : 0;
|
|
|
|
for (unsigned int s = 0; s < m_traceBackBuffersStreams.size(); s++)
|
|
{
|
|
m_traceBackBuffersStreams[s][nextMemIndex].reset();
|
|
m_traceBackBuffersStreams[s][nextMemIndex].write(
|
|
m_traceBackBuffersStreams[s][m_currentMemIndex].getEndPoint() - samplesToReport,
|
|
samplesToReport
|
|
);
|
|
}
|
|
|
|
m_currentMemIndex = nextMemIndex;
|
|
|
|
if (m_currentMemIndex > m_maxMemIndex) {
|
|
m_maxMemIndex = m_currentMemIndex;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Return current memory index
|
|
*/
|
|
uint32_t currentIndex() const { return m_currentMemIndex; }
|
|
|
|
/**
|
|
* Return max memory index processed
|
|
*/
|
|
uint32_t maxIndex() const { return m_maxMemIndex; }
|
|
|
|
/**
|
|
* Serializer
|
|
*/
|
|
QByteArray serialize() const
|
|
{
|
|
SimpleSerializer s(1);
|
|
|
|
s.writeU32(1, m_traceBackBuffersStreams.size());
|
|
s.writeU32(2, m_memSize);
|
|
s.writeU32(3, m_currentMemIndex);
|
|
s.writeU32(4, m_traceSize);
|
|
|
|
for (unsigned int is = 0; is < m_traceBackBuffersStreams.size(); is++)
|
|
{
|
|
SimpleSerializer ss(1);
|
|
|
|
for (unsigned int i = 0; i < m_memSize; i++)
|
|
{
|
|
QByteArray buffer = m_traceBackBuffersStreams[is][i].serialize();
|
|
ss.writeBlob(i, buffer);
|
|
}
|
|
|
|
s.writeBlob(5+is, ss.final());
|
|
}
|
|
|
|
return s.final();
|
|
}
|
|
|
|
/**
|
|
* Deserializer
|
|
*/
|
|
bool deserialize(const QByteArray& data)
|
|
{
|
|
SimpleDeserializer d(data);
|
|
|
|
if(!d.isValid()) {
|
|
return false;
|
|
}
|
|
|
|
if (d.getVersion() == 1)
|
|
{
|
|
unsigned int nbStreams;
|
|
d.readU32(1, &nbStreams, 0);
|
|
d.readU32(2, &m_memSize, 0);
|
|
d.readU32(3, &m_currentMemIndex, 0);
|
|
uint32_t traceSize;
|
|
d.readU32(4, &traceSize, 0);
|
|
|
|
for (unsigned int is = 0; is < nbStreams; is++)
|
|
{
|
|
if (is >= m_traceBackBuffersStreams.size()) {
|
|
break;
|
|
}
|
|
|
|
m_traceBackBuffersStreams[is].resize(m_memSize);
|
|
|
|
if (traceSize != m_traceSize) {
|
|
resize(traceSize);
|
|
}
|
|
|
|
QByteArray streamData;
|
|
d.readBlob(5+is, &streamData);
|
|
SimpleDeserializer ds(streamData);
|
|
|
|
for (unsigned int i = 0; i < m_memSize; i++)
|
|
{
|
|
QByteArray buffer;
|
|
ds.readBlob(i, &buffer);
|
|
m_traceBackBuffersStreams[is][i].deserialize(buffer);
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get current point at current memory position (first stream)
|
|
*/
|
|
void getCurrent(ComplexVector::iterator& it) {
|
|
current().current(it);
|
|
}
|
|
|
|
/**
|
|
* Get current points at current memory position
|
|
*/
|
|
void getCurrent(std::vector<ComplexVector::const_iterator>& vit)
|
|
{
|
|
vit.clear();
|
|
|
|
for (unsigned int is = 0; is < m_traceBackBuffersStreams.size(); is++)
|
|
{
|
|
ComplexVector::iterator it;
|
|
current(is).current(it);
|
|
vit.push_back(it);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Set end point at current memory position (first stream)
|
|
*/
|
|
void setCurrentEndPoint(const ComplexVector::iterator& it) {
|
|
current().setEndPoint(it);
|
|
}
|
|
|
|
/**
|
|
* Set end points at current memory position
|
|
*/
|
|
void setCurrentEndPoint(const std::vector<ComplexVector::const_iterator>& vit)
|
|
{
|
|
for (unsigned int is = 0; is < vit.size(); is++)
|
|
{
|
|
if (is >= m_traceBackBuffersStreams.size()) {
|
|
break;
|
|
}
|
|
|
|
current(is).setEndPoint(vit[is]);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get end point at given memory position (first stream)
|
|
*/
|
|
void getEndPointAt(int index, ComplexVector::const_iterator& mend) {
|
|
at(index).getEndPoint(mend);
|
|
}
|
|
|
|
/**
|
|
* Get end points at given memory position
|
|
*/
|
|
void getEndPointAt(int index, std::vector<ComplexVector::const_iterator>& vend)
|
|
{
|
|
vend.clear();
|
|
|
|
for (unsigned int is = 0; is < m_traceBackBuffersStreams.size(); is++)
|
|
{
|
|
ComplexVector::const_iterator mend;
|
|
at(index, is).getEndPoint(mend);
|
|
vend.push_back(mend);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Write trace at current memory position (first stream)
|
|
*/
|
|
void writeCurrent(const ComplexVector::const_iterator& begin, int length) {
|
|
current().write(begin, length);
|
|
}
|
|
|
|
/**
|
|
* Write traces at current memory position
|
|
*/
|
|
void writeCurrent(const std::vector<ComplexVector::const_iterator>& vbegin, int length)
|
|
{
|
|
for (unsigned int i = 0; i < vbegin.size(); i++) {
|
|
current(i).write(vbegin[i], length);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Move buffer iterator by a certain amount (first stream)
|
|
*/
|
|
static void moveIt(const ComplexVector::const_iterator& x, ComplexVector::const_iterator& y, int amount) {
|
|
y = x + amount;
|
|
}
|
|
|
|
/**
|
|
* Move buffers iterators by a certain amount
|
|
*/
|
|
static void moveIt(const std::vector<ComplexVector::const_iterator>& vx, std::vector<ComplexVector::const_iterator>& vy, int amount)
|
|
{
|
|
for (unsigned int i = 0; i < vx.size(); i++)
|
|
{
|
|
if (i >= vy.size()) {
|
|
break;
|
|
}
|
|
|
|
vy[i] = vx[i] + amount;
|
|
}
|
|
}
|
|
|
|
private:
|
|
std::vector<TraceBackBufferStream> m_traceBackBuffersStreams;
|
|
uint32_t m_memSize;
|
|
uint32_t m_currentMemIndex;
|
|
uint32_t m_maxMemIndex;
|
|
uint32_t m_traceSize;
|
|
|
|
TraceBackBuffer& current(uint32_t streamIndex = 0) { //!< Return trace at current memory position
|
|
return m_traceBackBuffersStreams[streamIndex][m_currentMemIndex];
|
|
}
|
|
|
|
TraceBackBuffer& at(int index, uint32_t streamIndex = 0) { //!< Return trace at given memory position
|
|
return m_traceBackBuffersStreams[streamIndex][index];
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Displayable trace stuff
|
|
*/
|
|
struct TraceControl
|
|
{
|
|
Projector m_projector; //!< Projector transform from complex trace to real (displayable) trace
|
|
uint32_t m_traceCount[2]; //!< Count of samples processed (double buffered)
|
|
double m_maxPow; //!< Maximum power over the current trace for MagDB overlay display
|
|
double m_sumPow; //!< Cumulative power over the current trace for MagDB overlay display
|
|
int m_nbPow; //!< Number of power samples over the current trace for MagDB overlay display
|
|
|
|
TraceControl() : m_projector(Projector::ProjectionReal)
|
|
{
|
|
reset();
|
|
}
|
|
|
|
~TraceControl()
|
|
{
|
|
}
|
|
|
|
void initProjector(Projector::ProjectionType projectionType)
|
|
{
|
|
m_projector.settProjectionType(projectionType);
|
|
}
|
|
|
|
void releaseProjector()
|
|
{
|
|
}
|
|
|
|
void reset()
|
|
{
|
|
m_traceCount[0] = 0;
|
|
m_traceCount[1] = 0;
|
|
m_maxPow = 0.0f;
|
|
m_sumPow = 0.0f;
|
|
m_nbPow = 0;
|
|
}
|
|
};
|
|
|
|
struct Traces
|
|
{
|
|
std::vector<TraceControl*> m_tracesControl; //!< Corresponding traces control data
|
|
std::vector<GLScopeSettings::TraceData> m_tracesData; //!< Corresponding traces data
|
|
std::vector<float *> m_traces[2]; //!< Double buffer of traces processed by glScope
|
|
std::vector<Projector::ProjectionType> m_projectionTypes;
|
|
int m_traceSize; //!< Current size of a trace in buffer
|
|
int m_maxTraceSize; //!< Maximum Size of a trace in buffer
|
|
bool evenOddIndex; //!< Even (true) or odd (false) index
|
|
|
|
Traces() :
|
|
m_traceSize(0),
|
|
m_maxTraceSize(0),
|
|
evenOddIndex(true),
|
|
m_x0(0),
|
|
m_x1(0)
|
|
{
|
|
}
|
|
|
|
~Traces()
|
|
{
|
|
for (std::vector<TraceControl*>::iterator it = m_tracesControl.begin(); it != m_tracesControl.end(); ++it) {
|
|
delete *it;
|
|
}
|
|
|
|
if (m_x0) {
|
|
delete[] m_x0;
|
|
}
|
|
|
|
if (m_x1) {
|
|
delete[] m_x1;
|
|
}
|
|
|
|
m_maxTraceSize = 0;
|
|
}
|
|
|
|
bool isVerticalDisplayChange(const GLScopeSettings::TraceData& traceData, uint32_t traceIndex)
|
|
{
|
|
return (m_tracesData[traceIndex].m_projectionType != traceData.m_projectionType)
|
|
|| (m_tracesData[traceIndex].m_amp != traceData.m_amp)
|
|
|| (m_tracesData[traceIndex].m_ofs != traceData.m_ofs
|
|
|| (m_tracesData[traceIndex].m_traceColor != traceData.m_traceColor));
|
|
}
|
|
|
|
void addTrace(const GLScopeSettings::TraceData& traceData, int traceSize)
|
|
{
|
|
if (m_traces[0].size() < GLScopeSettings::m_maxNbTraces)
|
|
{
|
|
qDebug("ScopeVis::Traces::addTrace");
|
|
m_traces[0].push_back(nullptr);
|
|
m_traces[1].push_back(nullptr);
|
|
m_tracesData.push_back(traceData);
|
|
m_projectionTypes.push_back(traceData.m_projectionType);
|
|
m_tracesControl.push_back(new TraceControl());
|
|
TraceControl *traceControl = m_tracesControl.back();
|
|
traceControl->initProjector(traceData.m_projectionType);
|
|
|
|
resize(traceSize);
|
|
}
|
|
}
|
|
|
|
void changeTrace(const GLScopeSettings::TraceData& traceData, uint32_t traceIndex)
|
|
{
|
|
if (traceIndex < m_tracesControl.size())
|
|
{
|
|
TraceControl *traceControl = m_tracesControl[traceIndex];
|
|
traceControl->releaseProjector();
|
|
traceControl->initProjector(traceData.m_projectionType);
|
|
m_tracesData[traceIndex] = traceData;
|
|
m_projectionTypes[traceIndex] = traceData.m_projectionType;
|
|
}
|
|
}
|
|
|
|
void removeTrace(uint32_t traceIndex)
|
|
{
|
|
if (traceIndex < m_tracesControl.size())
|
|
{
|
|
qDebug("ScopeVis::Traces::removeTrace");
|
|
m_traces[0].erase(m_traces[0].begin() + traceIndex);
|
|
m_traces[1].erase(m_traces[1].begin() + traceIndex);
|
|
m_projectionTypes.erase(m_projectionTypes.begin() + traceIndex);
|
|
TraceControl *traceControl = m_tracesControl[traceIndex];
|
|
traceControl->releaseProjector();
|
|
m_tracesControl.erase(m_tracesControl.begin() + traceIndex);
|
|
m_tracesData.erase(m_tracesData.begin() + traceIndex);
|
|
delete traceControl;
|
|
|
|
resize(m_traceSize); // reallocate pointers
|
|
}
|
|
}
|
|
|
|
void moveTrace(uint32_t traceIndex, bool upElseDown)
|
|
{
|
|
if ((!upElseDown) && (traceIndex == 0)) {
|
|
return;
|
|
}
|
|
|
|
int nextControlIndex = (traceIndex + (upElseDown ? 1 : -1)) % (m_tracesControl.size());
|
|
int nextDataIndex = (traceIndex + (upElseDown ? 1 : -1)) % (m_tracesData.size()); // should be the same
|
|
int nextProjectionTypeIndex = (traceIndex + (upElseDown ? 1 : -1)) % (m_projectionTypes.size()); // should be the same
|
|
|
|
Projector::ProjectionType nextType = m_projectionTypes[traceIndex];
|
|
m_projectionTypes[nextProjectionTypeIndex] = m_projectionTypes[traceIndex];
|
|
m_projectionTypes[traceIndex] = nextType;
|
|
|
|
TraceControl *traceControl = m_tracesControl[traceIndex];
|
|
TraceControl *nextTraceControl = m_tracesControl[nextControlIndex];
|
|
|
|
traceControl->releaseProjector();
|
|
nextTraceControl->releaseProjector();
|
|
|
|
m_tracesControl[nextControlIndex] = traceControl;
|
|
m_tracesControl[traceIndex] = nextTraceControl;
|
|
|
|
GLScopeSettings::TraceData nextData = m_tracesData[nextDataIndex];
|
|
m_tracesData[nextDataIndex] = m_tracesData[traceIndex];
|
|
m_tracesData[traceIndex] = nextData;
|
|
|
|
traceControl = m_tracesControl[traceIndex];
|
|
nextTraceControl = m_tracesControl[nextControlIndex];
|
|
|
|
traceControl->initProjector(m_tracesData[traceIndex].m_projectionType);
|
|
nextTraceControl->initProjector(m_tracesData[nextDataIndex].m_projectionType);
|
|
}
|
|
|
|
void resize(int traceSize)
|
|
{
|
|
m_traceSize = traceSize;
|
|
|
|
if (m_traceSize > m_maxTraceSize)
|
|
{
|
|
delete[] m_x0;
|
|
delete[] m_x1;
|
|
m_x0 = new float[2*m_traceSize*GLScopeSettings::m_maxNbTraces];
|
|
m_x1 = new float[2*m_traceSize*GLScopeSettings::m_maxNbTraces];
|
|
|
|
m_maxTraceSize = m_traceSize;
|
|
}
|
|
|
|
std::fill_n(m_x0, 2*m_traceSize*m_traces[0].size(), 0.0f);
|
|
std::fill_n(m_x1, 2*m_traceSize*m_traces[0].size(), 0.0f);
|
|
|
|
for (unsigned int i = 0; i < m_traces[0].size(); i++)
|
|
{
|
|
(m_traces[0])[i] = &m_x0[2*m_traceSize*i];
|
|
(m_traces[1])[i] = &m_x1[2*m_traceSize*i];
|
|
}
|
|
}
|
|
|
|
uint32_t currentBufferIndex() const { return evenOddIndex? 0 : 1; }
|
|
uint32_t size() const { return m_tracesControl.size(); }
|
|
|
|
void switchBuffer()
|
|
{
|
|
evenOddIndex = !evenOddIndex;
|
|
|
|
for (std::vector<TraceControl*>::iterator it = m_tracesControl.begin(); it != m_tracesControl.end(); ++it) {
|
|
(*it)->m_traceCount[currentBufferIndex()] = 0;
|
|
}
|
|
}
|
|
|
|
void resetControls()
|
|
{
|
|
for (auto traceControl : m_tracesControl) {
|
|
traceControl->reset();
|
|
}
|
|
}
|
|
|
|
private:
|
|
float *m_x0;
|
|
float *m_x1;
|
|
};
|
|
|
|
class TriggerComparator
|
|
{
|
|
public:
|
|
TriggerComparator() : m_level(0), m_reset(true) {
|
|
computeLevels();
|
|
}
|
|
|
|
bool triggered(const Complex& s, TriggerCondition& triggerCondition)
|
|
{
|
|
if (triggerCondition.m_triggerData.m_triggerLevel != m_level)
|
|
{
|
|
m_level = triggerCondition.m_triggerData.m_triggerLevel;
|
|
computeLevels();
|
|
}
|
|
|
|
bool condition, trigger;
|
|
|
|
if (triggerCondition.m_projector.getProjectionType() == Projector::ProjectionMagDB) {
|
|
condition = triggerCondition.m_projector.run(s) > m_levelPowerDB;
|
|
} else if (triggerCondition.m_projector.getProjectionType() == Projector::ProjectionMagLin) {
|
|
condition = triggerCondition.m_projector.run(s) > m_levelPowerLin;
|
|
} else if (triggerCondition.m_projector.getProjectionType() == Projector::ProjectionMagSq) {
|
|
condition = triggerCondition.m_projector.run(s) > m_levelPowerLin;
|
|
} else {
|
|
condition = triggerCondition.m_projector.run(s) > m_level;
|
|
}
|
|
|
|
if (condition)
|
|
{
|
|
if (triggerCondition.m_trues < triggerCondition.m_triggerData.m_triggerHoldoff) {
|
|
condition = false;
|
|
triggerCondition.m_trues++;
|
|
}
|
|
else
|
|
{
|
|
triggerCondition.m_falses = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (triggerCondition.m_falses < triggerCondition.m_triggerData.m_triggerHoldoff) {
|
|
condition = true;
|
|
triggerCondition.m_falses++;
|
|
}
|
|
else
|
|
{
|
|
triggerCondition.m_trues = 0;
|
|
}
|
|
}
|
|
|
|
if (m_reset)
|
|
{
|
|
triggerCondition.m_prevCondition = condition;
|
|
m_reset = false;
|
|
return false;
|
|
}
|
|
|
|
if (triggerCondition.m_triggerData.m_triggerBothEdges) {
|
|
trigger = triggerCondition.m_prevCondition ? !condition : condition; // This is a XOR between bools
|
|
} else if (triggerCondition.m_triggerData.m_triggerPositiveEdge) {
|
|
trigger = !triggerCondition.m_prevCondition && condition;
|
|
} else {
|
|
trigger = triggerCondition.m_prevCondition && !condition;
|
|
}
|
|
|
|
// if (trigger) {
|
|
// qDebug("ScopeVis::triggered: %s/%s %f/%f",
|
|
// triggerCondition.m_prevCondition ? "T" : "F",
|
|
// condition ? "T" : "F",
|
|
// triggerCondition.m_projector->run(s),
|
|
// triggerCondition.m_triggerData.m_triggerLevel);
|
|
// }
|
|
|
|
triggerCondition.m_prevCondition = condition;
|
|
return trigger;
|
|
}
|
|
|
|
void reset() {
|
|
m_reset = true;
|
|
}
|
|
|
|
private:
|
|
void computeLevels()
|
|
{
|
|
m_levelPowerLin = m_level + 1.0f;
|
|
m_levelPowerDB = (100.0f * (m_level - 1.0f));
|
|
}
|
|
|
|
Real m_level;
|
|
Real m_levelPowerDB;
|
|
Real m_levelPowerLin;
|
|
bool m_reset;
|
|
};
|
|
|
|
GLScopeInterface* m_glScope;
|
|
SpectrumVis *m_spectrumVis;
|
|
bool m_ssbSpectrum;
|
|
GLScopeSettings m_settings;
|
|
MessageQueue m_inputMessageQueue;
|
|
uint32_t m_preTriggerDelay; //!< Pre-trigger delay in number of samples
|
|
uint32_t m_livePreTriggerDelay; //!< Pre-trigger delay in number of samples in live mode
|
|
std::vector<TriggerCondition*> m_triggerConditions; //!< Chain of triggers
|
|
uint32_t m_currentTriggerIndex; //!< Index of current index in the chain
|
|
uint32_t m_focusedTriggerIndex; //!< Index of the trigger that has focus
|
|
TriggerState m_triggerState; //!< Current trigger state
|
|
Traces m_traces; //!< Displayable traces
|
|
int m_focusedTraceIndex; //!< Index of the trace that has focus
|
|
uint32_t m_nbStreams;
|
|
uint32_t m_traceChunkSize; //!< Trace length unit size in number of samples
|
|
uint32_t m_traceSize; //!< Size of traces in number of samples
|
|
uint32_t m_liveTraceSize; //!< Size of traces in number of samples in live mode
|
|
int m_nbSamples; //!< Number of samples yet to process in one complex trace
|
|
uint32_t m_timeBase; //!< Trace display time divisor
|
|
uint32_t m_timeOfsProMill; //!< Start trace shift in 1/1000 trace size
|
|
bool m_traceStart; //!< Trace is at start point
|
|
int m_triggerLocation; //!< Trigger location from end point
|
|
int m_sampleRate; //!< Actual sample rate being used
|
|
int m_liveSampleRate; //!< Sample rate in live mode
|
|
TraceBackDiscreteMemory m_traceDiscreteMemory; //!< Complex trace memory
|
|
ConvertBuffers m_convertBuffers; //!< Sample to Complex conversions
|
|
bool m_freeRun; //!< True if free running (trigger globally disabled)
|
|
int m_maxTraceDelay; //!< Maximum trace delay
|
|
TriggerComparator m_triggerComparator; //!< Compares sample level to trigger level
|
|
QRecursiveMutex m_mutex;
|
|
Real m_projectorCache[(int) Projector::nbProjectionTypes];
|
|
bool m_triggerOneShot; //!< True when one shot mode is active
|
|
bool m_triggerWaitForReset; //!< In one shot mode suspended until reset by UI
|
|
uint32_t m_currentTraceMemoryIndex; //!< The current index of trace in memory (0: current)
|
|
|
|
|
|
void applySettings(const GLScopeSettings& settings, bool force = false);
|
|
void addTrace(const GLScopeSettings::TraceData& traceData);
|
|
void changeTrace(const GLScopeSettings::TraceData& traceData, uint32_t traceIndex);
|
|
void removeTrace(uint32_t traceIndex);
|
|
void moveTrace(uint32_t traceIndex, bool upElseDown);
|
|
void focusOnTrace(uint32_t traceIndex);
|
|
void addTrigger(const GLScopeSettings::TriggerData& triggerData);
|
|
void changeTrigger(const GLScopeSettings::TriggerData& triggerData, uint32_t triggerIndex);
|
|
void removeTrigger(uint32_t triggerIndex);
|
|
void moveTrigger(uint32_t triggerIndex, bool upElseDown);
|
|
void focusOnTrigger(uint32_t triggerIndex);
|
|
|
|
/**
|
|
* Moves on to the next trigger if any or increments trigger count if in repeat mode
|
|
* - If not final it returns true
|
|
* - If final i.e. signal is actually triggered it returns false
|
|
*/
|
|
bool nextTrigger(); //!< Returns true if not final
|
|
|
|
/**
|
|
* Process a sample trace which length is at most the trace length (m_traceSize)
|
|
*/
|
|
void processTrace(const std::vector<ComplexVector::const_iterator>& vbegin, int length, int& triggerPointToEnd);
|
|
|
|
/**
|
|
* process a trace in memory at current trace index in memory
|
|
*/
|
|
void processMemoryTrace();
|
|
|
|
/**
|
|
* Process traces from complex trace memory buffer.
|
|
* - if finished it returns the number of unprocessed samples left in the buffer
|
|
* - if not finished it returns -1
|
|
*/
|
|
int processTraces(const std::vector<ComplexVector::const_iterator>& vbegin, int length, bool traceBack = false);
|
|
|
|
/**
|
|
* Get maximum trace delay
|
|
*/
|
|
void updateMaxTraceDelay();
|
|
|
|
/**
|
|
* Initialize trace buffers
|
|
*/
|
|
void initTraceBuffers();
|
|
|
|
/**
|
|
* Calculate trigger levels on display
|
|
* - every time a trigger condition focus changes TBD
|
|
* - every time the focused trigger condition changes its projection type or level
|
|
* - every time a trace data changes: projection type, amp, offset
|
|
* - every time a trace data is added or removed
|
|
*/
|
|
void computeDisplayTriggerLevels();
|
|
|
|
/**
|
|
* Update glScope display
|
|
* - Live trace: call glScipe update method
|
|
* - Trace in memory: call process memory trace
|
|
*/
|
|
void updateGLScopeDisplay();
|
|
|
|
/**
|
|
* Set the actual sample rate
|
|
*/
|
|
void setSampleRate(int sampleRate);
|
|
|
|
/**
|
|
* Set the traces size
|
|
*/
|
|
void setTraceSize(uint32_t traceSize, bool emitSignal = false);
|
|
|
|
/**
|
|
* Set the pre trigger delay
|
|
*/
|
|
void setPreTriggerDelay(uint32_t preTriggerDelay, bool emitSignal = false);
|
|
|
|
private slots:
|
|
void handleInputMessages();
|
|
};
|
|
|
|
|
|
|
|
#endif /* SDRBASE_DSP_SCOPEVISNG_H_ */
|