1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2024-11-26 01:39:05 -05:00

New scope: interim state (3)

This commit is contained in:
f4exb 2017-02-01 18:31:16 +01:00
parent ce41ded86e
commit e6f80c8474
3 changed files with 226 additions and 105 deletions

View File

@ -38,16 +38,17 @@ ScopeVisNG::ScopeVisNG(GLScopeNG* glScope) :
m_currentTriggerIndex(0), m_currentTriggerIndex(0),
m_triggerState(TriggerUntriggered), m_triggerState(TriggerUntriggered),
m_traceSize(m_traceChunkSize), m_traceSize(m_traceChunkSize),
m_memTraceSize(0),
m_traceStart(true), m_traceStart(true),
m_traceFill(0), m_traceFill(0),
m_zTraceIndex(-1), m_zTraceIndex(-1),
m_traceCompleteCount(0), m_traceCompleteCount(0),
m_timeOfsProMill(0), m_timeOfsProMill(0),
m_sampleRate(0) m_sampleRate(0),
m_traceDiscreteMemory(10)
{ {
setObjectName("ScopeVisNG"); setObjectName("ScopeVisNG");
m_tracebackBuffers.resize(1); m_traceDiscreteMemory.resize(m_traceChunkSize); // arbitrary
m_tracebackBuffers[0].resize(4*m_traceChunkSize);
} }
ScopeVisNG::~ScopeVisNG() ScopeVisNG::~ScopeVisNG()
@ -114,8 +115,6 @@ void ScopeVisNG::removeTrigger(uint32_t triggerIndex)
void ScopeVisNG::feed(const SampleVector::const_iterator& cbegin, const SampleVector::const_iterator& end, bool positiveOnly) void ScopeVisNG::feed(const SampleVector::const_iterator& cbegin, const SampleVector::const_iterator& end, bool positiveOnly)
{ {
uint32_t feedIndex = 0; // TODO: redefine feed interface so it can be passed a feed index
if (m_triggerState == TriggerFreeRun) { if (m_triggerState == TriggerFreeRun) {
m_triggerPoint = cbegin; m_triggerPoint = cbegin;
} }
@ -142,19 +141,51 @@ void ScopeVisNG::feed(const SampleVector::const_iterator& cbegin, const SampleVe
return; return;
} }
m_tracebackBuffers[feedIndex].write(cbegin, end);
SampleVector::const_iterator begin(cbegin); SampleVector::const_iterator begin(cbegin);
TriggerCondition& triggerCondition = m_triggerConditions[m_currentTriggerIndex];
// memory storage
if ((m_triggerState == TriggerFreeRun) && (m_triggerConditions.size() > 0))
{
m_traceDiscreteMemory.current().write(cbegin, end);
if (m_traceDiscreteMemory.current().absoluteFill() < m_traceSize)
{
return; // not enough samples in memory
}
}
else
{
// TODO: continuous memory
}
// trigger process // trigger process
if ((m_triggerConditions.size() > 0) && (feedIndex == triggerCondition.m_triggerData.m_inputIndex))
if ((m_triggerConditions.size() > 0) && ((m_triggerState == TriggerUntriggered) || (m_triggerState == TriggerDelay)))
{ {
TriggerCondition& triggerCondition = m_triggerConditions[m_currentTriggerIndex]; // current trigger condition
while (begin < end) while (begin < end)
{ {
if (m_triggerState == TriggerUntriggered) if (m_triggerState == TriggerDelay)
{ {
bool condition = triggerCondition.m_projector->run(*begin) > triggerCondition.m_triggerData.m_triggerLevel; if (triggerCondition.m_triggerDelayCount > 0)
bool trigger; {
triggerCondition.m_triggerDelayCount--; // pass
}
else // delay expired => fire this trigger
{
if (!nextTrigger()) // finished
{
m_traceStart = true; // start trace processing
break;
}
}
}
else // look for trigger
{
bool condition = triggerCondition.m_projector->run(*begin) > triggerCondition.m_triggerData.m_triggerLevel;
bool trigger;
if (triggerCondition.m_triggerData.m_triggerBothEdges) { if (triggerCondition.m_triggerData.m_triggerBothEdges) {
trigger = triggerCondition.m_prevCondition ^ condition; trigger = triggerCondition.m_prevCondition ^ condition;
@ -162,103 +193,68 @@ void ScopeVisNG::feed(const SampleVector::const_iterator& cbegin, const SampleVe
trigger = condition ^ !triggerCondition.m_triggerData.m_triggerPositiveEdge; trigger = condition ^ !triggerCondition.m_triggerData.m_triggerPositiveEdge;
} }
if (trigger) if (trigger) // trigger condition
{ {
if (triggerCondition.m_triggerData.m_triggerDelay > 0) if (triggerCondition.m_triggerData.m_triggerDelay > 0) // there is a delay => initialize the delay
{ {
triggerCondition.m_triggerDelayCount = triggerCondition.m_triggerData.m_triggerDelay; triggerCondition.m_triggerDelayCount = triggerCondition.m_triggerData.m_triggerDelay;
m_triggerState == TriggerDelay; m_triggerState == TriggerDelay;
} }
else else
{ {
if (triggerCondition.m_triggerCounter > 0) if (!nextTrigger()) // finished
{ {
triggerCondition.m_triggerCounter--; m_traceStart = true; // start trace processing
m_triggerState = TriggerUntriggered; break;
} }
else
{
// next trigger
m_currentTriggerIndex++;
if (m_currentTriggerIndex == m_triggerConditions.size())
{
m_currentTriggerIndex = 0;
m_triggerState = TriggerTriggered;
m_triggerPoint = begin;
triggerCondition.m_triggerCounter = triggerCondition.m_triggerData.m_triggerCounts;
m_traceStart = true;
break;
}
else
{
m_triggerState = TriggerUntriggered;
}
}
} }
} }
} }
else if (m_triggerState == TriggerDelay)
{
if (triggerCondition.m_triggerDelayCount > 0)
{
triggerCondition.m_triggerDelayCount--;
}
else
{
triggerCondition.m_triggerDelayCount = 0;
// next trigger
m_currentTriggerIndex++;
if (m_currentTriggerIndex == m_triggerConditions.size())
{
m_currentTriggerIndex = 0;
m_triggerState = TriggerTriggered;
m_triggerPoint = begin;
triggerCondition.m_triggerCounter = triggerCondition.m_triggerData.m_triggerCounts;
m_traceStart = true;
break;
}
else
{
// initialize a new trace
m_triggerState = TriggerUntriggered;
m_traceCompleteCount = 0;
m_triggerState = TriggerUntriggered;
feed(begin, end, positiveOnly); // process the rest of samples
}
}
}
else
{
break;
}
++begin; ++begin;
} // begin < end } // begin < end
} }
// trace process // trace process
if ((m_triggerConditions.size() == 0) || (m_triggerState == TriggerTriggered)) if ((m_triggerState == TriggerFreeRun) || (m_triggerConditions.size() == 0) || (m_triggerState == TriggerTriggered))
{ {
// trace back // trace back
if (m_traceStart) if (m_traceStart)
{ {
int count = end - begin; // number of samples in traceback buffer past the current point int count = end - begin; // number of samples in traceback buffer past the current point
std::vector<Trace>::iterator itTrace = m_traces.begin(); int maxTraceDelay = 0;
for (;itTrace != m_traces.end(); ++itTrace) for (std::vector<Trace>::iterator itTrace = m_traces.begin(); itTrace != m_traces.end(); ++itTrace)
{ {
if (itTrace->m_traceData.m_inputIndex == feedIndex) if (itTrace->m_traceData.m_traceDelay > maxTraceDelay)
{ {
// TODO: store current point in traceback (current - count) maxTraceDelay = itTrace->m_traceData.m_traceDelay;
SampleVector::const_iterator startPoint = m_tracebackBuffers[feedIndex].getCurrent() - count; }
SampleVector::const_iterator prevPoint = m_tracebackBuffers[feedIndex].getCurrent() - count - m_preTriggerDelay - itTrace->m_traceData.m_traceDelay; }
processPrevTrace(prevPoint, startPoint, itTrace);
} if ((m_triggerState != TriggerFreeRun) && (m_triggerConditions.size() > 0)) // trigger mode
{
processPrevTraces(count + m_preTriggerDelay + maxTraceDelay, count, m_traceDiscreteMemory.current());
}
else
{
// TODO: continuous memory mode
}
for (std::vector<Trace>::iterator itTrace = m_traces.begin(); itTrace != m_traces.end(); ++itTrace)
{
if ((m_triggerState != TriggerFreeRun) && (m_triggerConditions.size() > 0)) // trigger mode
{
SampleVector::const_iterator prevPoint = startPoint - m_preTriggerDelay - itTrace->m_traceData.m_traceDelay;
}
else // free run mode
{
// TODO:
}
} }
m_traceStart = false; m_traceStart = false;
@ -316,7 +312,39 @@ void ScopeVisNG::feed(const SampleVector::const_iterator& cbegin, const SampleVe
} }
} }
void ScopeVisNG::processPrevTrace(SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, std::vector<Trace>::iterator& trace) bool ScopeVisNG::nextTrigger()
{
TriggerCondition& triggerCondition = m_triggerConditions[m_currentTriggerIndex]; // current trigger condition
if (triggerCondition.m_triggerData.m_triggerRepeat > 0)
{
if (triggerCondition.m_triggerCounter < triggerCondition.m_triggerData.m_triggerRepeat)
{
triggerCondition.m_triggerCounter++;
m_triggerState = TriggerUntriggered; // repeat operations for next occurence
return true;
}
else
{
triggerCondition.m_triggerCounter = 0; // reset for next time
}
}
if (m_currentTriggerIndex < m_triggerConditions.size())
{
m_currentTriggerIndex++;
m_triggerState = TriggerUntriggered; // repeat operations for next trigger
return true; // not final keep going
}
// now this is really finished
m_triggerState == TriggerTriggered;
m_currentTriggerIndex = 0;
return false; // final
}
// TODO: should handle previous and live traces the same way from a stored buffer
void ScopeVisNG::processPrevTraces(int beginPoint, int endPoint, TraceBackBuffer& traceBuffer)
{ {
int shift = (m_timeOfsProMill / 1000.0) * m_traceSize; int shift = (m_timeOfsProMill / 1000.0) * m_traceSize;
float posLimit = 1.0 / trace->m_traceData.m_amp; float posLimit = 1.0 / trace->m_traceData.m_amp;

View File

@ -78,7 +78,7 @@ public:
bool m_triggerPositiveEdge; //!< Trigger on the positive edge (else negative) bool m_triggerPositiveEdge; //!< Trigger on the positive edge (else negative)
bool m_triggerBothEdges; //!< Trigger on both edges (else only one) 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 uint32_t m_triggerDelay; //!< Delay before the trigger is kicked off in number of samples
uint32_t m_triggerCounts; //!< Number of trigger conditions before the final decisive trigger uint32_t m_triggerRepeat; //!< Number of trigger conditions before the final decisive trigger
TriggerData() : TriggerData() :
m_projectionType(ProjectionReal), m_projectionType(ProjectionReal),
@ -87,7 +87,7 @@ public:
m_triggerPositiveEdge(true), m_triggerPositiveEdge(true),
m_triggerBothEdges(false), m_triggerBothEdges(false),
m_triggerDelay(0), m_triggerDelay(0),
m_triggerCounts(0) m_triggerRepeat(0)
{} {}
}; };
@ -115,8 +115,6 @@ public:
SampleVector::const_iterator getTriggerPoint() const { return m_triggerPoint; } SampleVector::const_iterator getTriggerPoint() const { return m_triggerPoint; }
private: private:
typedef DoubleBufferSimple<Sample> TraceBuffer;
// === messages === // === messages ===
// --------------------------------------------- // ---------------------------------------------
class MsgConfigureScopeVisNG : public Message { class MsgConfigureScopeVisNG : public Message {
@ -345,6 +343,9 @@ private:
}; };
/**
* Trigger stuff
*/
enum TriggerState enum TriggerState
{ {
TriggerFreeRun, //!< Trigger is disabled TriggerFreeRun, //!< Trigger is disabled
@ -391,6 +392,95 @@ private:
} }
}; };
/**
* Complex trace stuff
*/
typedef DoubleBufferSimple<Sample> TraceBuffer;
struct TraceBackBuffer
{
TraceBuffer m_traceBuffer;
SampleVector::iterator m_endPoint;
TraceBackBuffer()
{
m_startPoint = m_traceBuffer.getCurrent();
m_endPoint = m_traceBuffer.getCurrent();
}
void resize(uint32_t size)
{
m_traceBuffer.resize(size);
}
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 current() { return m_traceBuffer.getCurrent(); }
};
struct TraceBackDiscreteMemory
{
std::vector<TraceBackBuffer> m_traceBackBuffers;
uint32_t m_memSize;
uint32_t m_currentMemIndex;
/**
* Give memory size in number of traces
*/
TraceBackDiscreteMemory(uint32_t size) : m_memSize(size), m_currentMemIndex(0)
{
m_traceBackBuffers.resize(m_memSize);
}
/**
* Resize all trace buffers in memory
*/
void resize(uint32_t size)
{
for (std::vector<TraceBackBuffer>::iterator it = m_traceBackBuffers.begin(); it != m_traceBackBuffers.end(); ++it)
{
it->resize(size);
}
}
/**
* Move index forward by one position and return reference to the trace at this position
*/
TraceBackBuffer &store()
{
m_currentMemIndex = m_currentMemIndex < m_memSize ? m_currentMemIndex+1 : 0;
m_traceBackBuffers[m_currentMemIndex].reset();
return m_traceBackBuffers[m_currentMemIndex]; // new trace
}
/**
* Recalls trace at shift positions back. Therefore 0 is current. Wraps around memory size.
*/
TraceBackBuffer& recall(uint32_t shift)
{
int index = (m_currentMemIndex + (m_memSize - (shift % m_memSize))) % m_memSize;
return m_traceBackBuffers[index];
}
/**
* Return trace at current memory position
*/
TraceBackBuffer& current()
{
return m_traceBackBuffers[m_currentMemIndex];
}
};
/**
* Displayable trace stuff
*/
struct Trace : public DisplayTrace struct Trace : public DisplayTrace
{ {
Projector *m_projector; //!< Projector transform from complex trace to real (displayable) trace Projector *m_projector; //!< Projector transform from complex trace to real (displayable) trace
@ -440,23 +530,24 @@ private:
}; };
GLScopeNG* m_glScope; GLScopeNG* m_glScope;
std::vector<TraceBuffer> m_tracebackBuffers; //!< One complex (Sample type) trace buffer per input source or feed int m_preTriggerDelay; //!< Pre-trigger delay in number of samples
DoubleBufferSimple<Sample> m_traceback; //!< FIFO to handle delayed processes
int m_preTriggerDelay; //!< Pre-trigger delay in number of samples
std::vector<TriggerCondition> m_triggerConditions; //!< Chain of triggers std::vector<TriggerCondition> m_triggerConditions; //!< Chain of triggers
int m_currentTriggerIndex; //!< Index of current index in the chain int m_currentTriggerIndex; //!< Index of current index in the chain
TriggerState m_triggerState; //!< Current trigger state TriggerState m_triggerState; //!< Current trigger state
std::vector<Trace> m_traces; //!< One trace control object per display trace allocated to X, Y[n] or Z std::vector<Trace> m_traces; //!< One trace control object per display trace allocated to X, Y[n] or Z
int m_traceSize; //!< Size of traces in number of samples int m_traceSize; //!< Size of traces in number of samples
int m_timeOfsProMill; //!< Start trace shift in 1/1000 trace size int m_memTraceSize; //!< Trace size in memory in number of samples up to trace size
bool m_traceStart; //!< Trace is at start point int m_timeOfsProMill; //!< Start trace shift in 1/1000 trace size
int m_traceFill; //!< Count of samples accumulated into trace bool m_traceStart; //!< Trace is at start point
int m_zTraceIndex; //!< Index of the trace used for Z input (luminance or false colors) int m_traceFill; //!< Count of samples accumulated into trace
int m_traceCompleteCount; //!< Count of completed traces 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_traceCompleteCount; //!< Count of completed traces
SampleVector::const_iterator m_triggerPoint; //!< Trigger start location in the samples vector
int m_sampleRate; int m_sampleRate;
TraceBackDiscreteMemory m_traceDiscreteMemory; //!< Complex trace memory for triggered states TODO: vectorize when more than on input is allowed
void processPrevTrace(SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, std::vector<Trace>::iterator& trace); bool nextTrigger();
void processPrevTraces(int beginPoint, int endPoint, TraceBackBuffer& traceBuffer);
}; };

View File

@ -67,6 +67,8 @@ public:
} }
typename std::vector<T>::iterator getCurrent() const { return m_current + m_size; } typename std::vector<T>::iterator getCurrent() const { return m_current + m_size; }
unsigned int absoluteFill() const { return m_current - m_data.begin(); }
void reset() { m_current = m_data.begin(); }
private: private:
int m_size; int m_size;