mirror of
				https://github.com/f4exb/sdrangel.git
				synced 2025-10-31 04:50:29 -04:00 
			
		
		
		
	
		
			
				
	
	
		
			1168 lines
		
	
	
		
			39 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			1168 lines
		
	
	
		
			39 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| ///////////////////////////////////////////////////////////////////////////////////
 | |
| // Copyright (C) 2017 F4EXB                                                      //
 | |
| // written by Edouard Griffiths                                                  //
 | |
| //                                                                               //
 | |
| // ScopeVis class specialized for multiple sources handling                      //
 | |
| //                                                                               //
 | |
| // 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 <http://www.gnu.org/licenses/>.          //
 | |
| ///////////////////////////////////////////////////////////////////////////////////
 | |
| 
 | |
| #ifndef SDRBASE_DSP_SCOPEVISMULTI_H_
 | |
| #define SDRBASE_DSP_SCOPEVISMULTI_H_
 | |
| 
 | |
| #include <QObject>
 | |
| #include <QDebug>
 | |
| #include <QColor>
 | |
| #include <algorithm>
 | |
| #include <utility>
 | |
| 
 | |
| #include <stdint.h>
 | |
| #include <vector>
 | |
| #include <boost/circular_buffer.hpp>
 | |
| #include "dsp/dsptypes.h"
 | |
| #include "util/export.h"
 | |
| #include "util/message.h"
 | |
| #include "util/messagequeue.h"
 | |
| #include "util/doublebuffer.h"
 | |
| 
 | |
| class GLScopeMulti;
 | |
| 
 | |
| class SDRANGEL_API ScopeVisMulti : public QObject {
 | |
|     Q_OBJECT
 | |
| public:
 | |
|     enum ProjectionType
 | |
|     {
 | |
|         ProjectionReal = 0, //!< Extract real part
 | |
|         ProjectionImag,     //!< Extract imaginary part
 | |
|         ProjectionMagLin,   //!< Calculate linear magnitude or modulus
 | |
|         ProjectionMagDB,    //!< Calculate logarithmic (dB) of squared magnitude
 | |
|         ProjectionPhase,    //!< Calculate phase
 | |
|         ProjectionDPhase,   //!< Calculate phase derivative i.e. instantaneous frequency scaled to sample rate
 | |
|         nbProjectionTypes   //!< Gives the number of projections in the enum
 | |
|     };
 | |
| 
 | |
|     struct TraceData
 | |
|     {
 | |
|         ProjectionType m_projectionType; //!< Complex to real projection type
 | |
|         uint32_t m_inputIndex;           //!< Input or feed index this trace is associated with
 | |
|         float m_amp;                     //!< Amplification factor
 | |
|         uint32_t m_ampIndex;             //!< Index in list of amplification factors
 | |
|         float m_ofs;                     //!< Offset factor
 | |
|         int m_ofsCoarse;                 //!< Coarse offset slider value
 | |
|         int m_ofsFine;                   //!< Fine offset slider value
 | |
|         int m_traceDelay;                //!< Trace delay in number of samples
 | |
|         int m_traceDelayCoarse;          //!< Coarse delay slider value
 | |
|         int m_traceDelayFine;            //!< Fine delay slider value
 | |
|         float m_triggerDisplayLevel;     //!< Displayable trigger display level in -1:+1 scale. Off scale if not displayable.
 | |
|         QColor m_traceColor;             //!< Trace display color
 | |
|         float m_traceColorR;             //!< Trace display color - red shortcut
 | |
|         float m_traceColorG;             //!< Trace display color - green shortcut
 | |
|         float m_traceColorB;             //!< Trace display color - blue shortcut
 | |
|         bool m_hasTextOverlay;           //!< True if a text overlay has to be displayed
 | |
|         QString m_textOverlay;           //!< Text overlay to display
 | |
|         bool m_viewTrace;                //!< Trace visibility
 | |
| 
 | |
|         TraceData() :
 | |
|             m_projectionType(ProjectionReal),
 | |
|             m_inputIndex(0),
 | |
|             m_amp(1.0f),
 | |
|             m_ampIndex(0),
 | |
|             m_ofs(0.0f),
 | |
|             m_ofsCoarse(0),
 | |
|             m_ofsFine(0),
 | |
|             m_traceDelay(0),
 | |
|             m_traceDelayCoarse(0),
 | |
|             m_traceDelayFine(0),
 | |
|             m_triggerDisplayLevel(2.0),  // OVer scale by default (2.0)
 | |
|             m_traceColor(255,255,64),
 | |
|             m_hasTextOverlay(false),
 | |
|             m_viewTrace(true)
 | |
|         {
 | |
|             setColor(m_traceColor);
 | |
|         }
 | |
| 
 | |
|         void setColor(QColor color)
 | |
|         {
 | |
|             m_traceColor = color;
 | |
|             qreal r,g,b,a;
 | |
|             m_traceColor.getRgbF(&r, &g, &b, &a);
 | |
|             m_traceColorR = r;
 | |
|             m_traceColorG = g;
 | |
|             m_traceColorB = b;
 | |
|         }
 | |
|     };
 | |
| 
 | |
| 
 | |
|     struct TriggerData
 | |
|     {
 | |
|         ProjectionType m_projectionType; //!< Complex to real projection type
 | |
|         uint32_t m_inputIndex;           //!< Input or feed index this trigger is associated with
 | |
|         Real m_triggerLevel;             //!< Level in real units
 | |
|         int  m_triggerLevelCoarse;
 | |
|         int  m_triggerLevelFine;
 | |
|         bool m_triggerPositiveEdge;      //!< Trigger on the positive edge (else negative)
 | |
|         bool m_triggerBothEdges;         //!< Trigger on both edges (else only one)
 | |
|         uint32_t m_triggerDelay;         //!< Delay before the trigger is kicked off in number of samples (trigger delay)
 | |
|         double m_triggerDelayMult;       //!< Trigger delay as a multiplier of trace length
 | |
|         int m_triggerDelayCoarse;
 | |
|         int m_triggerDelayFine;
 | |
|         uint32_t m_triggerRepeat;        //!< Number of trigger conditions before the final decisive trigger
 | |
|         QColor m_triggerColor;           //!< Trigger line display color
 | |
|         float m_triggerColorR;           //!< Trigger line display color - red shortcut
 | |
|         float m_triggerColorG;           //!< Trigger line display color - green shortcut
 | |
|         float m_triggerColorB;           //!< Trigger line display color - blue shortcut
 | |
| 
 | |
|         TriggerData() :
 | |
|             m_projectionType(ProjectionReal),
 | |
|             m_inputIndex(0),
 | |
|             m_triggerLevel(0.0f),
 | |
|             m_triggerLevelCoarse(0),
 | |
|             m_triggerLevelFine(0),
 | |
|             m_triggerPositiveEdge(true),
 | |
|             m_triggerBothEdges(false),
 | |
|             m_triggerDelay(0),
 | |
|             m_triggerDelayMult(0.0),
 | |
|             m_triggerDelayCoarse(0),
 | |
|             m_triggerDelayFine(0),
 | |
|             m_triggerRepeat(0),
 | |
|             m_triggerColor(0,255,0)
 | |
|         {
 | |
|             setColor(m_triggerColor);
 | |
|         }
 | |
| 
 | |
|         void setColor(QColor color)
 | |
|         {
 | |
|             m_triggerColor = color;
 | |
|             qreal r,g,b,a;
 | |
|             m_triggerColor.getRgbF(&r, &g, &b, &a);
 | |
|             m_triggerColorR = r;
 | |
|             m_triggerColorG = g;
 | |
|             m_triggerColorB = b;
 | |
|         }
 | |
|     };
 | |
| 
 | |
|     static const uint32_t m_traceChunkSize = 4800;
 | |
|     static const uint32_t m_maxNbTriggers = 10;
 | |
|     static const uint32_t m_maxNbTraces = 10;
 | |
|     static const uint32_t m_nbTraceMemories = 16;
 | |
|     static const uint32_t m_maxNbTraceSources = 4;
 | |
| 
 | |
|     ScopeVisMulti(GLScopeMulti* glScope = 0);
 | |
|     ~ScopeVisMulti();
 | |
| 
 | |
|     void setSampleRate(int sampleRate);
 | |
|     void configure(uint32_t nbSources, uint32_t traceSize, uint32_t timeBase, uint32_t timeOfsProMill, uint32_t triggerPre, bool freeRun);
 | |
|     void addTrace(const TraceData& traceData);
 | |
|     void changeTrace(const 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 TriggerData& triggerData);
 | |
|     void changeTrigger(const TriggerData& triggerData, uint32_t triggerIndex);
 | |
|     void removeTrigger(uint32_t triggerIndex);
 | |
|     void moveTrigger(uint32_t triggerIndex, bool upElseDown);
 | |
|     void focusOnTrigger(uint32_t triggerIndex);
 | |
|     void setOneShot(bool oneShot);
 | |
|     void setMemoryIndex(uint32_t memoryIndex);
 | |
| 
 | |
|     void getTriggerData(TriggerData& triggerData, uint32_t triggerIndex)
 | |
|     {
 | |
|         if (triggerIndex < m_triggerConditions.size())
 | |
|         {
 | |
|             triggerData = m_triggerConditions[triggerIndex].m_triggerData;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     void getTraceData(TraceData& traceData, uint32_t traceIndex)
 | |
|     {
 | |
|         if (traceIndex < m_traces.m_tracesData.size())
 | |
|         {
 | |
|             traceData = m_traces.m_tracesData[traceIndex];
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     const TriggerData& getTriggerData(uint32_t triggerIndex) const { return m_triggerConditions[triggerIndex].m_triggerData; }
 | |
|     const std::vector<TraceData>& getTracesData() const { return m_traces.m_tracesData; }
 | |
|     uint32_t getNbTriggers() const { return m_triggerConditions.size(); }
 | |
| 
 | |
|     void feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, uint32_t sourceIndex);
 | |
| 
 | |
| protected:
 | |
|     MessageQueue m_inputMessageQueue; //!< Queue for asynchronous inbound communication
 | |
|     MessageQueue m_outputMessageQueue; //!< Queue for asynchronous outbound communication
 | |
| 
 | |
|     bool handleMessage(const Message& message);
 | |
| 
 | |
| protected slots:
 | |
|     void handleInputMessages();
 | |
| 
 | |
| private:
 | |
|     // === messages ===
 | |
|     // ---------------------------------------------
 | |
|     class MsgConfigureScopeVisNG : public Message {
 | |
|         MESSAGE_CLASS_DECLARATION
 | |
| 
 | |
|     public:
 | |
|         static MsgConfigureScopeVisNG* create(
 | |
|             uint32_t nbSources,
 | |
|             uint32_t traceSize,
 | |
|             uint32_t timeBase,
 | |
|             uint32_t timeOfsProMill,
 | |
|             uint32_t triggerPre,
 | |
|             bool freeRun)
 | |
|         {
 | |
|             return new MsgConfigureScopeVisNG(nbSources, traceSize, timeBase, timeOfsProMill, triggerPre, freeRun);
 | |
|         }
 | |
| 
 | |
|         uint32_t getNbSources() const { return m_nbSources; }
 | |
|         uint32_t getTraceSize() const { return m_traceSize; }
 | |
|         uint32_t getTimeBase() const { return m_timeBase; }
 | |
|         uint32_t getTimeOfsProMill() const { return m_timeOfsProMill; }
 | |
|         uint32_t getTriggerPre() const { return m_triggerPre; }
 | |
|         bool getFreeRun() const { return m_freeRun; }
 | |
| 
 | |
|     private:
 | |
|         uint32_t m_nbSources;
 | |
|         uint32_t m_traceSize;
 | |
|         uint32_t m_timeBase;
 | |
|         uint32_t m_timeOfsProMill;
 | |
|         uint32_t m_triggerPre;
 | |
|         bool m_freeRun;
 | |
| 
 | |
|         MsgConfigureScopeVisNG(
 | |
|                 uint32_t nbSources,
 | |
|                 uint32_t traceSize,
 | |
|                 uint32_t timeBase,
 | |
|                 uint32_t timeOfsProMill,
 | |
|                 uint32_t triggerPre,
 | |
|                 bool freeRun) :
 | |
|             m_nbSources(nbSources),
 | |
|             m_traceSize(traceSize),
 | |
|             m_timeBase(timeBase),
 | |
|             m_timeOfsProMill(timeOfsProMill),
 | |
|             m_triggerPre(triggerPre),
 | |
|             m_freeRun(freeRun)
 | |
|         {}
 | |
|     };
 | |
| 
 | |
|     // ---------------------------------------------
 | |
|     class MsgScopeVisNGAddTrigger : public Message {
 | |
|         MESSAGE_CLASS_DECLARATION
 | |
| 
 | |
|     public:
 | |
|         static MsgScopeVisNGAddTrigger* create(
 | |
|                 const TriggerData& triggerData)
 | |
|         {
 | |
|             return new MsgScopeVisNGAddTrigger(triggerData);
 | |
|         }
 | |
| 
 | |
|         const TriggerData& getTriggerData() const { return m_triggerData; }
 | |
| 
 | |
|     private:
 | |
|         TriggerData m_triggerData;
 | |
| 
 | |
|         MsgScopeVisNGAddTrigger(const TriggerData& triggerData) :
 | |
|             m_triggerData(triggerData)
 | |
|         {}
 | |
|     };
 | |
| 
 | |
|     // ---------------------------------------------
 | |
|     class MsgScopeVisNGChangeTrigger : public Message {
 | |
|         MESSAGE_CLASS_DECLARATION
 | |
| 
 | |
|     public:
 | |
|         static MsgScopeVisNGChangeTrigger* create(
 | |
|                 const TriggerData& triggerData, uint32_t triggerIndex)
 | |
|         {
 | |
|             return new MsgScopeVisNGChangeTrigger(triggerData, triggerIndex);
 | |
|         }
 | |
| 
 | |
|         const TriggerData& getTriggerData() const { return m_triggerData; }
 | |
|         uint32_t getTriggerIndex() const { return m_triggerIndex; }
 | |
| 
 | |
|     private:
 | |
|         TriggerData m_triggerData;
 | |
|         uint32_t m_triggerIndex;
 | |
| 
 | |
|         MsgScopeVisNGChangeTrigger(const TriggerData& triggerData, uint32_t triggerIndex) :
 | |
|             m_triggerData(triggerData),
 | |
|             m_triggerIndex(triggerIndex)
 | |
|         {}
 | |
|     };
 | |
| 
 | |
|     // ---------------------------------------------
 | |
|     class MsgScopeVisNGRemoveTrigger : public Message {
 | |
|         MESSAGE_CLASS_DECLARATION
 | |
| 
 | |
|     public:
 | |
|         static MsgScopeVisNGRemoveTrigger* create(
 | |
|                 uint32_t triggerIndex)
 | |
|         {
 | |
|             return new MsgScopeVisNGRemoveTrigger(triggerIndex);
 | |
|         }
 | |
| 
 | |
|         uint32_t getTriggerIndex() const { return m_triggerIndex; }
 | |
| 
 | |
|     private:
 | |
|         uint32_t m_triggerIndex;
 | |
| 
 | |
|         MsgScopeVisNGRemoveTrigger(uint32_t triggerIndex) :
 | |
|             m_triggerIndex(triggerIndex)
 | |
|         {}
 | |
|     };
 | |
| 
 | |
|     // ---------------------------------------------
 | |
|     class MsgScopeVisNGMoveTrigger : public Message {
 | |
|         MESSAGE_CLASS_DECLARATION
 | |
| 
 | |
|     public:
 | |
|         static MsgScopeVisNGMoveTrigger* create(
 | |
|                 uint32_t triggerIndex,
 | |
|                 bool moveUpElseDown)
 | |
|         {
 | |
|             return new MsgScopeVisNGMoveTrigger(triggerIndex, moveUpElseDown);
 | |
|         }
 | |
| 
 | |
|         uint32_t getTriggerIndex() const { return m_triggerIndex; }
 | |
|         bool getMoveUp() const { return m_moveUpElseDown; }
 | |
| 
 | |
|     private:
 | |
|         uint32_t m_triggerIndex;
 | |
|         bool m_moveUpElseDown;
 | |
| 
 | |
|         MsgScopeVisNGMoveTrigger(uint32_t triggerIndex, bool moveUpElseDown) :
 | |
|             m_triggerIndex(triggerIndex),
 | |
|             m_moveUpElseDown(moveUpElseDown)
 | |
|         {}
 | |
|     };
 | |
| 
 | |
|     // ---------------------------------------------
 | |
|     class MsgScopeVisNGFocusOnTrigger : public Message {
 | |
|         MESSAGE_CLASS_DECLARATION
 | |
| 
 | |
|     public:
 | |
|         static MsgScopeVisNGFocusOnTrigger* create(
 | |
|                 uint32_t triggerIndex)
 | |
|         {
 | |
|             return new MsgScopeVisNGFocusOnTrigger(triggerIndex);
 | |
|         }
 | |
| 
 | |
|         uint32_t getTriggerIndex() const { return m_triggerIndex; }
 | |
| 
 | |
|     private:
 | |
|         uint32_t m_triggerIndex;
 | |
| 
 | |
|         MsgScopeVisNGFocusOnTrigger(uint32_t triggerIndex) :
 | |
|             m_triggerIndex(triggerIndex)
 | |
|         {}
 | |
|     };
 | |
| 
 | |
|     // ---------------------------------------------
 | |
|     class MsgScopeVisNGAddTrace : public Message {
 | |
|         MESSAGE_CLASS_DECLARATION
 | |
| 
 | |
|     public:
 | |
|         static MsgScopeVisNGAddTrace* create(
 | |
|                 const TraceData& traceData)
 | |
|         {
 | |
|             return new MsgScopeVisNGAddTrace(traceData);
 | |
|         }
 | |
| 
 | |
|         const TraceData& getTraceData() const { return m_traceData; }
 | |
| 
 | |
|     private:
 | |
|         TraceData m_traceData;
 | |
| 
 | |
|         MsgScopeVisNGAddTrace(const TraceData& traceData) :
 | |
|             m_traceData(traceData)
 | |
|         {}
 | |
|     };
 | |
| 
 | |
|     // ---------------------------------------------
 | |
|     class MsgScopeVisNGChangeTrace : public Message {
 | |
|         MESSAGE_CLASS_DECLARATION
 | |
| 
 | |
|     public:
 | |
|         static MsgScopeVisNGChangeTrace* create(
 | |
|                 const TraceData& traceData, uint32_t traceIndex)
 | |
|         {
 | |
|             return new MsgScopeVisNGChangeTrace(traceData, traceIndex);
 | |
|         }
 | |
| 
 | |
|         const TraceData& getTraceData() const { return m_traceData; }
 | |
|         uint32_t getTraceIndex() const { return m_traceIndex; }
 | |
| 
 | |
|     private:
 | |
|         TraceData m_traceData;
 | |
|         uint32_t m_traceIndex;
 | |
| 
 | |
|         MsgScopeVisNGChangeTrace(TraceData traceData, uint32_t traceIndex) :
 | |
|             m_traceData(traceData),
 | |
|             m_traceIndex(traceIndex)
 | |
|         {}
 | |
|     };
 | |
| 
 | |
|     // ---------------------------------------------
 | |
|     class MsgScopeVisNGRemoveTrace : public Message {
 | |
|         MESSAGE_CLASS_DECLARATION
 | |
| 
 | |
|     public:
 | |
|         static MsgScopeVisNGRemoveTrace* create(
 | |
|                 uint32_t traceIndex)
 | |
|         {
 | |
|             return new MsgScopeVisNGRemoveTrace(traceIndex);
 | |
|         }
 | |
| 
 | |
|         uint32_t getTraceIndex() const { return m_traceIndex; }
 | |
| 
 | |
|     private:
 | |
|         uint32_t m_traceIndex;
 | |
| 
 | |
|         MsgScopeVisNGRemoveTrace(uint32_t traceIndex) :
 | |
|             m_traceIndex(traceIndex)
 | |
|         {}
 | |
|     };
 | |
| 
 | |
|     // ---------------------------------------------
 | |
|     class MsgScopeVisNGMoveTrace : public Message {
 | |
|         MESSAGE_CLASS_DECLARATION
 | |
| 
 | |
|     public:
 | |
|         static MsgScopeVisNGMoveTrace* create(
 | |
|                 uint32_t traceIndex,
 | |
|                 bool moveUpElseDown)
 | |
|         {
 | |
|             return new MsgScopeVisNGMoveTrace(traceIndex, moveUpElseDown);
 | |
|         }
 | |
| 
 | |
|         uint32_t getTraceIndex() const { return m_traceIndex; }
 | |
|         bool getMoveUp() const { return m_moveUpElseDown; }
 | |
| 
 | |
|     private:
 | |
|         uint32_t m_traceIndex;
 | |
|         bool m_moveUpElseDown;
 | |
| 
 | |
|         MsgScopeVisNGMoveTrace(uint32_t traceIndex, bool moveUpElseDown) :
 | |
|             m_traceIndex(traceIndex),
 | |
|             m_moveUpElseDown(moveUpElseDown)
 | |
|         {}
 | |
|     };
 | |
| 
 | |
|     // ---------------------------------------------
 | |
|     class MsgScopeVisNGFocusOnTrace : public Message {
 | |
|         MESSAGE_CLASS_DECLARATION
 | |
| 
 | |
|     public:
 | |
|         static MsgScopeVisNGFocusOnTrace* create(
 | |
|                 uint32_t traceIndex)
 | |
|         {
 | |
|             return new MsgScopeVisNGFocusOnTrace(traceIndex);
 | |
|         }
 | |
| 
 | |
|         uint32_t getTraceIndex() const { return m_traceIndex; }
 | |
| 
 | |
|     private:
 | |
|         uint32_t m_traceIndex;
 | |
| 
 | |
|         MsgScopeVisNGFocusOnTrace(uint32_t traceIndex) :
 | |
|             m_traceIndex(traceIndex)
 | |
|         {}
 | |
|     };
 | |
| 
 | |
|     // ---------------------------------------------
 | |
|     class 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 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)
 | |
|         {}
 | |
|     };
 | |
| 
 | |
|     // ---------------------------------------------
 | |
| 
 | |
|     /**
 | |
|      * Projection stuff
 | |
|      */
 | |
|     class Projector
 | |
|     {
 | |
|     public:
 | |
|         Projector(ProjectionType projectionType) :
 | |
|             m_projectionType(projectionType),
 | |
|             m_prevArg(0.0f),
 | |
|             m_cache(0),
 | |
|             m_cacheMaster(true)
 | |
|         {}
 | |
| 
 | |
|         ~Projector()
 | |
|         {}
 | |
| 
 | |
|         ProjectionType getProjectionType() const { return m_projectionType; }
 | |
|         void settProjectionType(ProjectionType projectionType) { m_projectionType = projectionType; }
 | |
|         void setCache(Real *cache) { m_cache = cache; }
 | |
|         void setCacheMaster(bool cacheMaster) { m_cacheMaster = cacheMaster; }
 | |
| 
 | |
|         Real run(const Sample& s)
 | |
|         {
 | |
|             Real v;
 | |
| 
 | |
|             if ((m_cache) && !m_cacheMaster) {
 | |
|                 return m_cache[(int) m_projectionType];
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 switch (m_projectionType)
 | |
|                 {
 | |
|                 case ProjectionImag:
 | |
|                     v = s.m_imag / 32768.0f;
 | |
|                     break;
 | |
|                 case ProjectionMagLin:
 | |
|                 {
 | |
|                     uint32_t magsq = s.m_real*s.m_real + s.m_imag*s.m_imag;
 | |
|                     v = std::sqrt(magsq/1073741824.0f);
 | |
|                 }
 | |
|                     break;
 | |
|                 case ProjectionMagDB:
 | |
|                 {
 | |
|                     uint32_t magsq = s.m_real*s.m_real + s.m_imag*s.m_imag;
 | |
|                     v = log10f(magsq/1073741824.0f) * 10.0f;
 | |
|                 }
 | |
|                     break;
 | |
|                 case ProjectionPhase:
 | |
|                     v = std::atan2((float) s.m_imag, (float) s.m_real) / M_PI;
 | |
|                     break;
 | |
|                 case ProjectionDPhase:
 | |
|                 {
 | |
|                     Real curArg = std::atan2((float) s.m_imag, (float) s.m_real);
 | |
|                     Real dPhi = (curArg - m_prevArg) / M_PI;
 | |
|                     m_prevArg = curArg;
 | |
| 
 | |
|                     if (dPhi < -1.0f) {
 | |
|                         dPhi += 2.0f;
 | |
|                     } else if (dPhi > 1.0f) {
 | |
|                         dPhi -= 2.0f;
 | |
|                     }
 | |
| 
 | |
|                     v = dPhi;
 | |
|                 }
 | |
|                     break;
 | |
|                 case ProjectionReal:
 | |
|                 default:
 | |
|                     v = s.m_real / 32768.0f;
 | |
|                     break;
 | |
|                 }
 | |
| 
 | |
|                 if (m_cache) {
 | |
|                     m_cache[(int) m_projectionType] = v;
 | |
|                 }
 | |
| 
 | |
|                 return v;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|     private:
 | |
|         ProjectionType m_projectionType;
 | |
|         Real m_prevArg;
 | |
|         Real *m_cache;
 | |
|         bool m_cacheMaster;
 | |
|     };
 | |
| 
 | |
|     /**
 | |
|      * 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
 | |
|         TriggerNewConfig,   //!< Special condition when a new configuration has been received
 | |
|     };
 | |
| 
 | |
|     struct TriggerCondition
 | |
|     {
 | |
|     public:
 | |
|         Projector m_projector;
 | |
|         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 occurences
 | |
| 
 | |
|         TriggerCondition(const TriggerData& triggerData) :
 | |
|             m_projector(ProjectionReal),
 | |
|             m_triggerData(triggerData),
 | |
|             m_prevCondition(false),
 | |
|             m_triggerDelayCount(0),
 | |
|             m_triggerCounter(0)
 | |
|         {
 | |
|         }
 | |
| 
 | |
|         ~TriggerCondition()
 | |
|         {
 | |
|         }
 | |
| 
 | |
|         void initProjector()
 | |
|         {
 | |
|             m_projector.settProjectionType(m_triggerData.m_projectionType);
 | |
|         }
 | |
| 
 | |
|         void releaseProjector()
 | |
|         {
 | |
|         }
 | |
| 
 | |
|         void setData(const 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;
 | |
|         }
 | |
| 
 | |
|         void operator=(const TriggerCondition& other)
 | |
|         {
 | |
|             setData(other.m_triggerData);
 | |
|         }
 | |
|     };
 | |
| 
 | |
|     /**
 | |
|      * Complex trace stuff
 | |
|      */
 | |
|     typedef DoubleBufferSimple<Sample> TraceBuffer;
 | |
| 
 | |
|     struct TraceBackBuffer
 | |
|     {
 | |
|         TraceBuffer m_traceBuffer;
 | |
|         SampleVector::iterator m_endPoint;
 | |
| 
 | |
|         TraceBackBuffer()
 | |
|         {
 | |
|             m_endPoint = m_traceBuffer.getCurrent();
 | |
|         }
 | |
| 
 | |
|         void resize(uint32_t size)
 | |
|         {
 | |
|             m_traceBuffer.resize(size);
 | |
|         }
 | |
| 
 | |
|         void reset()
 | |
|         {
 | |
|             m_traceBuffer.reset();
 | |
|         }
 | |
| 
 | |
|         void write(const SampleVector::const_iterator begin, const SampleVector::const_iterator end)
 | |
|         {
 | |
|             m_traceBuffer.write(begin, end);
 | |
|         }
 | |
| 
 | |
|         unsigned int absoluteFill() const {
 | |
|             return m_traceBuffer.absoluteFill();
 | |
|         }
 | |
| 
 | |
|         SampleVector::iterator getCurrent() { return m_traceBuffer.getCurrent(); }
 | |
|     };
 | |
| 
 | |
|     typedef std::vector<TraceBackBuffer> TBBVector;
 | |
| 
 | |
|     struct TraceBackDiscreteMemory
 | |
|     {
 | |
|         std::vector<TBBVector> m_traceBackBuffers;
 | |
|         std::vector<int> m_sourceFill;
 | |
|         uint32_t m_nbSources;
 | |
|         uint32_t m_memSize;
 | |
|         uint32_t m_currentMemIndex;
 | |
|         uint32_t m_traceSize;
 | |
|         int m_preTrigCount;
 | |
| 
 | |
|         /**
 | |
|          * Allocate with maximum number of traces
 | |
|          */
 | |
|         TraceBackDiscreteMemory() :
 | |
|             m_nbSources(1),
 | |
|             m_memSize(m_nbTraceMemories),
 | |
|             m_currentMemIndex(0),
 | |
|             m_traceSize(m_traceChunkSize)
 | |
|         {
 | |
|             m_traceBackBuffers.resize(m_nbSources);
 | |
|             m_sourceFill.resize(m_nbSources);
 | |
|             resizeBuffers(m_traceSize);
 | |
|         }
 | |
| 
 | |
|         /**
 | |
|          * Resize all trace buffers in memory
 | |
|          */
 | |
|         void resizeBuffers(uint32_t size)
 | |
|         {
 | |
|             m_traceSize = size;
 | |
|             std::vector<int>::iterator itFill = m_sourceFill.begin();
 | |
| 
 | |
|             for (std::vector<TBBVector>::iterator itTBB = m_traceBackBuffers.begin(); itTBB != m_traceBackBuffers.end(); ++itTBB)
 | |
|             {
 | |
|                 for (std::vector<TraceBackBuffer>::iterator it = itTBB->begin(); it != itTBB->end(); ++it)
 | |
|                 {
 | |
|                     it->resize(4*m_traceSize);
 | |
|                 }
 | |
| 
 | |
|                 *itFill = 0;
 | |
|                 ++itFill;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         /**
 | |
|          * Set the number of sources
 | |
|          */
 | |
|         void setNbSources(uint32_t nbSources)
 | |
|         {
 | |
|             if ((nbSources < 1) || (nbSources > m_maxNbTraceSources)) {
 | |
|                 return;
 | |
|             }
 | |
| 
 | |
|             if (nbSources != m_nbSources)
 | |
|             {
 | |
|                 m_traceBackBuffers.resize(nbSources);
 | |
|                 resizeBuffers(m_traceSize);
 | |
|                 m_nbSources = nbSources;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         /**
 | |
|          * Feed current buffer at source index with sample
 | |
|          */
 | |
|         void feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, uint32_t sourceIndex)
 | |
|         {
 | |
|             m_traceBackBuffers[sourceIndex][m_currentMemIndex].write(begin, end);
 | |
|             m_sourceFill[sourceIndex] += end - begin;
 | |
|         }
 | |
| 
 | |
|         /**
 | |
|          * Return the minimum number of samples in buffer
 | |
|          */
 | |
|         uint32_t minFill() const
 | |
|         {
 | |
|             return *std::min_element(m_sourceFill.begin(), m_sourceFill.end());
 | |
|         }
 | |
| 
 | |
|         /**
 | |
|          * Consume a number of samples from the buffers (that is reduce the fill count)
 | |
|          */
 | |
|         void consume(int nbSamples)
 | |
|         {
 | |
|             for (std::vector<int>::iterator itFill = m_sourceFill.begin(); itFill != m_sourceFill.end(); ++itFill)
 | |
|             {
 | |
|                 (*itFill) -= nbSamples;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         SampleVector::iterator getBeginIterator(int sourceIndex)
 | |
|         {
 | |
|             return m_traceBackBuffers[sourceIndex][m_currentMemIndex].getCurrent() - m_sourceFill[sourceIndex];
 | |
|         }
 | |
| 
 | |
|         uint32_t getNbSources() const
 | |
|         {
 | |
|             return m_nbSources;
 | |
|         }
 | |
| 
 | |
|         void markEnd(int sourceIndex, SampleVector::iterator& end)
 | |
|         {
 | |
|             m_traceBackBuffers[sourceIndex][m_currentMemIndex].m_endPoint = end;
 | |
|         }
 | |
| 
 | |
|         void store()
 | |
|         {
 | |
|             uint32_t nextMemIndex = m_currentMemIndex < (m_memSize-1) ? m_currentMemIndex+1 : 0;
 | |
| 
 | |
|             for (std::vector<TBBVector>::iterator itTBB = m_traceBackBuffers.begin(); itTBB != m_traceBackBuffers.end(); ++itTBB)
 | |
|             {
 | |
|                 (*itTBB)[nextMemIndex].reset();
 | |
|                 (*itTBB)[nextMemIndex].write(
 | |
|                         (*itTBB)[m_currentMemIndex].m_endPoint - m_traceSize,
 | |
|                         (*itTBB)[m_currentMemIndex].m_endPoint);
 | |
|             }
 | |
| 
 | |
|             m_currentMemIndex = nextMemIndex;
 | |
|         }
 | |
|     };
 | |
| 
 | |
|     /**
 | |
|      * 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)
 | |
|         Real m_maxPow;            //!< Maximum power over the current trace for MagDB overlay display
 | |
|         Real 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(ProjectionReal)
 | |
|         {
 | |
|             reset();
 | |
|         }
 | |
| 
 | |
|         ~TraceControl()
 | |
|         {
 | |
|         }
 | |
| 
 | |
|         void initProjector(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<TraceData> m_tracesData;          //!< Corresponding traces data
 | |
|         std::vector<float *> m_traces[2];             //!< Double buffer of traces processed by glScope
 | |
|         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()
 | |
|         {
 | |
|             if (m_x0) delete[] m_x0;
 | |
|             if (m_x1) delete[] m_x1;
 | |
|             m_maxTraceSize = 0;
 | |
|         }
 | |
| 
 | |
|         bool isVerticalDisplayChange(const 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 TraceData& traceData, int traceSize)
 | |
|         {
 | |
|             if (m_traces[0].size() < m_maxNbTraces)
 | |
|             {
 | |
|                 m_traces[0].push_back(0);
 | |
|                 m_traces[1].push_back(0);
 | |
|                 m_tracesData.push_back(traceData);
 | |
|                 m_tracesControl.push_back(TraceControl());
 | |
|                 m_tracesControl.back().initProjector(traceData.m_projectionType);
 | |
| 
 | |
|                 resize(traceSize);
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         void changeTrace(const TraceData& traceData, uint32_t traceIndex)
 | |
|         {
 | |
|             if (traceIndex < m_tracesControl.size()) {
 | |
|                 m_tracesControl[traceIndex].releaseProjector();
 | |
|                 m_tracesControl[traceIndex].initProjector(traceData.m_projectionType);
 | |
|                 m_tracesData[traceIndex] = traceData;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         void removeTrace(uint32_t traceIndex)
 | |
|         {
 | |
|             if (traceIndex < m_tracesControl.size())
 | |
|             {
 | |
|                 m_traces[0].erase(m_traces[0].begin() + traceIndex);
 | |
|                 m_traces[1].erase(m_traces[1].begin() + traceIndex);
 | |
|                 m_tracesControl[traceIndex].releaseProjector();
 | |
|                 m_tracesControl.erase(m_tracesControl.begin() + traceIndex);
 | |
|                 m_tracesData.erase(m_tracesData.begin() + traceIndex);
 | |
| 
 | |
|                 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
 | |
| 
 | |
|             m_tracesControl[traceIndex].releaseProjector();
 | |
|             m_tracesControl[nextControlIndex].releaseProjector();
 | |
| 
 | |
|             TraceControl nextControl = m_tracesControl[nextControlIndex];
 | |
|             m_tracesControl[nextControlIndex] = m_tracesControl[traceIndex];
 | |
|             m_tracesControl[traceIndex] = nextControl;
 | |
| 
 | |
|             TraceData nextData = m_tracesData[nextDataIndex];
 | |
|             m_tracesData[nextDataIndex] = m_tracesData[traceIndex];
 | |
|             m_tracesData[traceIndex] = nextData;
 | |
| 
 | |
|             m_tracesControl[traceIndex].initProjector(m_tracesData[traceIndex].m_projectionType);
 | |
|             m_tracesControl[nextControlIndex].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*m_maxNbTraces];
 | |
|                 m_x1 = new float[2*m_traceSize*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;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|     private:
 | |
|         float *m_x0;
 | |
|         float *m_x1;
 | |
|     };
 | |
| 
 | |
|     class TriggerComparator
 | |
|     {
 | |
|     public:
 | |
|         TriggerComparator() : m_level(0), m_reset(true)
 | |
|         {
 | |
|             computeLevels();
 | |
|         }
 | |
| 
 | |
|         bool triggered(const Sample& 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() == ProjectionMagDB) {
 | |
|                 condition = triggerCondition.m_projector.run(s) > m_levelPowerDB;
 | |
|             } else if (triggerCondition.m_projector.getProjectionType() == ProjectionMagLin) {
 | |
|                 condition = triggerCondition.m_projector.run(s) > m_levelPowerLin;
 | |
|             } else {
 | |
|                 condition = triggerCondition.m_projector.run(s) > m_level;
 | |
|             }
 | |
| 
 | |
|             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("ScopeVisNG::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;
 | |
|     };
 | |
| 
 | |
|     typedef std::vector<SampleVector::iterator> TBMemoriesBegins;
 | |
| 
 | |
|     GLScopeMulti* m_glScope;
 | |
|     uint32_t m_preTriggerDelay;                    //!< Pre-trigger delay in number of samples
 | |
|     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_traceSize;                          //!< Size of traces in number of samples
 | |
|     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
 | |
|     bool m_postTrigBuffering;                      //!< Buffering after trigger match to get enough samples for the display traces
 | |
|     int m_traceFill;                               //!< Count of samples accumulated into trace
 | |
|     int m_zTraceIndex;                             //!< Index of the trace used for Z input (luminance or false colors)
 | |
|     SampleVector::const_iterator m_triggerPoint;   //!< Trigger start location in the samples vector
 | |
|     int m_sampleRate;
 | |
|     TraceBackDiscreteMemory m_traceDiscreteMemory; //!< Complex trace memories for triggered states. One trace history per source
 | |
|     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
 | |
|     QMutex m_mutex;
 | |
|     Real m_projectorCache[(int) 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)
 | |
|     uint32_t m_nbSources;                          //!< Current number of sample sources
 | |
|     TBMemoriesBegins m_tbMemoriesBegins;           //!< Current begin iterators
 | |
| 
 | |
|     /**
 | |
|      * 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 triggerd it returns false
 | |
|      */
 | |
|     bool nextTrigger(); //!< Returns true if not final
 | |
| 
 | |
|     /**
 | |
|      * Process all input sources when ready. Assumes all memoruy traces are fed with enough samples
 | |
|      */
 | |
|     void processSources();
 | |
| 
 | |
|     /**
 | |
|      * process a trace in memory at current trace index in memory
 | |
|      */
 | |
|     void processMemorySources();
 | |
| 
 | |
|     /**
 | |
|      * 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
 | |
|      */
 | |
|     void processTraces(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool traceBack, uint32_t sourceIndex);
 | |
| 
 | |
|     /**
 | |
|      * 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();
 | |
| 
 | |
|     void lookForTrigger();
 | |
| };
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| #endif /* SDRBASE_DSP_SCOPEVISMULTI_H_ */
 |