1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2024-11-04 16:01:14 -05:00
sdrangel/sdrbase/dsp/scopevisng.cpp

389 lines
12 KiB
C++
Raw Normal View History

2017-01-29 13:51:45 -05:00
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2017 F4EXB //
// written by Edouard Griffiths //
// //
// 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/>. //
///////////////////////////////////////////////////////////////////////////////////
#include <QDebug>
#include "scopevisng.h"
2017-01-31 02:26:13 -05:00
#include "dsp/dspcommands.h"
2017-01-29 13:51:45 -05:00
#include "gui/glscopeng.h"
MESSAGE_CLASS_DEFINITION(ScopeVisNG::MsgConfigureScopeVisNG, Message)
MESSAGE_CLASS_DEFINITION(ScopeVisNG::MsgScopeVisNGAddTrigger, Message)
MESSAGE_CLASS_DEFINITION(ScopeVisNG::MsgScopeVisNGChangeTrigger, Message)
2017-01-29 13:51:45 -05:00
MESSAGE_CLASS_DEFINITION(ScopeVisNG::MsgScopeVisNGRemoveTrigger, Message)
MESSAGE_CLASS_DEFINITION(ScopeVisNG::MsgScopeVisNGAddTrace, Message)
MESSAGE_CLASS_DEFINITION(ScopeVisNG::MsgScopeVisNGChangeTrace, Message)
MESSAGE_CLASS_DEFINITION(ScopeVisNG::MsgScopeVisNGRemoveTrace, Message)
2017-01-29 13:51:45 -05:00
const uint ScopeVisNG::m_traceChunkSize = 4800;
const Real ScopeVisNG::ProjectorMagDB::mult = (10.0f / log2f(10.0f));
ScopeVisNG::ScopeVisNG(GLScopeNG* glScope) :
m_glScope(glScope),
m_preTriggerDelay(0),
m_currentTriggerIndex(0),
m_triggerState(TriggerUntriggered),
m_traceSize(m_traceChunkSize),
2017-02-01 12:31:16 -05:00
m_memTraceSize(0),
2017-01-29 13:51:45 -05:00
m_traceStart(true),
m_traceFill(0),
m_zTraceIndex(-1),
2017-01-29 16:52:38 -05:00
m_traceCompleteCount(0),
m_timeOfsProMill(0),
2017-02-01 12:31:16 -05:00
m_sampleRate(0),
m_traceDiscreteMemory(10)
2017-01-29 13:51:45 -05:00
{
setObjectName("ScopeVisNG");
2017-02-01 12:31:16 -05:00
m_traceDiscreteMemory.resize(m_traceChunkSize); // arbitrary
2017-01-29 13:51:45 -05:00
}
ScopeVisNG::~ScopeVisNG()
{
std::vector<TriggerCondition>::iterator it = m_triggerConditions.begin();
for (; it != m_triggerConditions.end(); ++it)
{
delete it->m_projector;
}
}
2017-01-29 16:52:38 -05:00
void ScopeVisNG::setSampleRate(int sampleRate)
{
if (sampleRate != m_sampleRate)
{
m_sampleRate = sampleRate;
if (m_glScope) m_glScope->setSampleRate(m_sampleRate);
}
}
void ScopeVisNG::configure(uint traceSize)
2017-01-29 13:51:45 -05:00
{
Message* cmd = MsgConfigureScopeVisNG::create(traceSize);
getInputMessageQueue()->push(cmd);
}
void ScopeVisNG::addTrace(const TraceData& traceData)
{
Message* cmd = MsgScopeVisNGAddTrace::create(traceData);
getInputMessageQueue()->push(cmd);
}
void ScopeVisNG::changeTrace(const TraceData& traceData, uint32_t traceIndex)
{
Message* cmd = MsgScopeVisNGChangeTrace::create(traceData, traceIndex);
getInputMessageQueue()->push(cmd);
}
void ScopeVisNG::removeTrace(uint32_t traceIndex)
{
Message* cmd = MsgScopeVisNGRemoveTrace::create(traceIndex);
getInputMessageQueue()->push(cmd);
}
void ScopeVisNG::addTrigger(const TriggerData& triggerData)
{
Message* cmd = MsgScopeVisNGAddTrigger::create(triggerData);
getInputMessageQueue()->push(cmd);
}
void ScopeVisNG::changeTrigger(const TriggerData& triggerData, uint32_t triggerIndex)
{
Message* cmd = MsgScopeVisNGChangeTrigger::create(triggerData, triggerIndex);
getInputMessageQueue()->push(cmd);
}
void ScopeVisNG::removeTrigger(uint32_t triggerIndex)
{
Message* cmd = MsgScopeVisNGRemoveTrigger::create(triggerIndex);
getInputMessageQueue()->push(cmd);
2017-01-29 13:51:45 -05:00
}
void ScopeVisNG::feed(const SampleVector::const_iterator& cbegin, const SampleVector::const_iterator& end, bool positiveOnly)
{
if (m_triggerState == TriggerFreeRun) {
m_triggerPoint = cbegin;
}
else if (m_triggerState == TriggerTriggered) {
m_triggerPoint = cbegin;
}
else if (m_triggerState == TriggerUntriggered) {
m_triggerPoint = end;
}
else if (m_triggerState == TriggerWait) {
m_triggerPoint = end;
}
else {
m_triggerPoint = cbegin;
}
if (m_triggerState == TriggerNewConfig)
{
m_triggerState = TriggerUntriggered;
return;
}
if ((m_triggerConditions.size() > 0) && (m_triggerState == TriggerWait)) {
return;
}
SampleVector::const_iterator begin(cbegin);
2017-02-01 12:31:16 -05:00
// memory storage
2017-02-02 02:27:49 -05:00
m_traceDiscreteMemory.current().write(cbegin, end);
2017-02-01 12:31:16 -05:00
2017-02-02 02:27:49 -05:00
if (m_traceDiscreteMemory.current().absoluteFill() < m_traceSize)
{
return; // not enough samples in memory
}
2017-01-29 13:51:45 -05:00
// trigger process
2017-02-01 12:31:16 -05:00
if ((m_triggerConditions.size() > 0) && ((m_triggerState == TriggerUntriggered) || (m_triggerState == TriggerDelay)))
2017-01-29 13:51:45 -05:00
{
2017-02-01 12:31:16 -05:00
TriggerCondition& triggerCondition = m_triggerConditions[m_currentTriggerIndex]; // current trigger condition
2017-01-29 13:51:45 -05:00
while (begin < end)
{
2017-02-01 12:31:16 -05:00
if (m_triggerState == TriggerDelay)
{
if (triggerCondition.m_triggerDelayCount > 0)
{
triggerCondition.m_triggerDelayCount--; // pass
}
else // delay expired => fire this trigger
{
if (!nextTrigger()) // finished
{
m_traceStart = true; // start trace processing
2017-02-02 02:27:49 -05:00
m_triggerPoint = begin;
2017-02-01 12:31:16 -05:00
break;
}
}
}
else // look for trigger
{
bool condition = triggerCondition.m_projector->run(*begin) > triggerCondition.m_triggerData.m_triggerLevel;
bool trigger;
2017-01-29 13:51:45 -05:00
if (triggerCondition.m_triggerData.m_triggerBothEdges) {
2017-01-29 13:51:45 -05:00
trigger = triggerCondition.m_prevCondition ^ condition;
} else {
trigger = condition ^ !triggerCondition.m_triggerData.m_triggerPositiveEdge;
2017-01-29 13:51:45 -05:00
}
2017-02-01 12:31:16 -05:00
if (trigger) // trigger condition
2017-01-29 13:51:45 -05:00
{
2017-02-01 12:31:16 -05:00
if (triggerCondition.m_triggerData.m_triggerDelay > 0) // there is a delay => initialize the delay
2017-01-29 13:51:45 -05:00
{
triggerCondition.m_triggerDelayCount = triggerCondition.m_triggerData.m_triggerDelay;
2017-02-02 12:18:37 -05:00
m_triggerState = TriggerDelay;
2017-01-29 13:51:45 -05:00
}
else
{
2017-02-01 12:31:16 -05:00
if (!nextTrigger()) // finished
{
m_traceStart = true; // start trace processing
2017-02-02 02:27:49 -05:00
m_triggerPoint = begin;
2017-02-01 12:31:16 -05:00
break;
}
2017-01-29 13:51:45 -05:00
}
}
2017-02-01 12:31:16 -05:00
}
2017-01-29 13:51:45 -05:00
++begin;
} // begin < end
}
2017-02-02 02:27:49 -05:00
int remainder = -1;
int count = end - begin; // number of samples in traceback buffer past the current point
SampleVector::iterator nend = m_traceDiscreteMemory.current().current();
SampleVector::iterator nbegin = nend - count;
2017-01-29 13:51:45 -05:00
// trace process
2017-02-01 12:31:16 -05:00
if ((m_triggerState == TriggerFreeRun) || (m_triggerConditions.size() == 0) || (m_triggerState == TriggerTriggered))
2017-01-29 13:51:45 -05:00
{
// trace back
if (m_traceStart)
{
2017-02-01 12:31:16 -05:00
int maxTraceDelay = 0;
2017-01-29 13:51:45 -05:00
2017-02-01 12:31:16 -05:00
for (std::vector<Trace>::iterator itTrace = m_traces.begin(); itTrace != m_traces.end(); ++itTrace)
2017-01-29 13:51:45 -05:00
{
2017-02-01 12:31:16 -05:00
if (itTrace->m_traceData.m_traceDelay > maxTraceDelay)
{
maxTraceDelay = itTrace->m_traceData.m_traceDelay;
}
}
2017-02-02 02:27:49 -05:00
remainder = processTraces(count + m_preTriggerDelay + maxTraceDelay, count, m_traceDiscreteMemory.current(), true);
m_traceStart = false;
}
2017-02-01 12:31:16 -05:00
2017-02-02 02:27:49 -05:00
if (remainder < 0)
{
// live trace
remainder = processTraces(count, 0, m_traceDiscreteMemory.current());
}
2017-02-01 12:31:16 -05:00
2017-02-02 02:27:49 -05:00
if (remainder >= 0) // finished
{
m_glScope->newTraces();
2017-02-01 12:31:16 -05:00
2017-02-02 02:27:49 -05:00
nbegin = nend - remainder;
m_traceDiscreteMemory.current().m_endPoint = nbegin;
m_traceDiscreteMemory.store(); // next memory trace
2017-02-01 12:31:16 -05:00
2017-02-02 02:27:49 -05:00
for (std::vector<Trace>::iterator itTrace = m_traces.begin(); itTrace != m_traces.end(); ++itTrace) {
itTrace->reset();
}
2017-01-29 13:51:45 -05:00
2017-02-02 02:27:49 -05:00
m_traceCompleteCount = 0;
2017-01-29 13:51:45 -05:00
}
2017-02-02 02:27:49 -05:00
}
2017-01-29 13:51:45 -05:00
2017-02-02 02:27:49 -05:00
// process remainder recursively
2017-01-29 13:51:45 -05:00
2017-02-02 02:27:49 -05:00
if (remainder > 0)
{
feed(nbegin, nend, positiveOnly);
2017-01-29 13:51:45 -05:00
}
}
2017-02-01 12:31:16 -05:00
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
}
2017-02-02 02:27:49 -05:00
int ScopeVisNG::processTraces(int beginPointDelta, int endPointDelta, TraceBackBuffer& traceBuffer, bool traceStart)
2017-01-29 13:51:45 -05:00
{
2017-02-02 02:27:49 -05:00
SampleVector::iterator begin = traceBuffer.current() - beginPointDelta;
SampleVector::const_iterator end = traceBuffer.current() - endPointDelta;
2017-01-29 13:51:45 -05:00
int shift = (m_timeOfsProMill / 1000.0) * m_traceSize;
while (begin < end)
{
2017-02-02 02:27:49 -05:00
for (std::vector<Trace>::iterator itTrace = m_traces.begin(); itTrace != m_traces.end(); ++itTrace)
{
if (traceStart && ((end - begin) > m_preTriggerDelay + itTrace->m_traceData.m_traceDelay)) {
continue;
}
2017-01-29 13:51:45 -05:00
2017-02-02 02:27:49 -05:00
if (itTrace->m_traceCount < m_traceSize)
{
float posLimit = 1.0 / itTrace->m_traceData.m_amp;
float negLimit = -1.0 / itTrace->m_traceData.m_amp;
float v = itTrace->m_projector->run(*begin) * itTrace->m_traceData.m_amp + itTrace->m_traceData.m_ofs;
if(v > posLimit) {
v = posLimit;
} else if (v < negLimit) {
v = negLimit;
}
itTrace->m_trace[2*(itTrace->m_traceCount)] = (itTrace->m_traceCount - shift); // display x
itTrace->m_trace[2*(itTrace->m_traceCount) + 1] = v; // display y
itTrace->m_traceCount++;
}
else if (itTrace->m_traceCount < m_traceSize)
{
itTrace->m_traceCount++;
2017-01-29 13:51:45 -05:00
2017-02-02 02:27:49 -05:00
if (m_traceCompleteCount < m_traces.size())
{
m_traceCompleteCount++;
}
else // finished
{
break;
}
}
}
2017-01-29 13:51:45 -05:00
begin++;
}
2017-02-02 02:27:49 -05:00
if (m_traceCompleteCount == m_traces.size()) // finished
{
m_glScope->newTraces();
traceBuffer.m_endPoint = begin;
return end - begin; // return remainder count
}
else
{
return -1; // mark not finished
}
2017-01-29 13:51:45 -05:00
}
void ScopeVisNG::start()
{
}
void ScopeVisNG::stop()
{
}
bool ScopeVisNG::handleMessage(const Message& message)
{
qDebug() << "ScopeVisNG::handleMessage" << message.getIdentifier();
2017-01-31 02:26:13 -05:00
if (DSPSignalNotification::match(message))
{
DSPSignalNotification& notif = (DSPSignalNotification&) message;
setSampleRate(notif.getSampleRate());
qDebug() << "ScopeVisNG::handleMessage: DSPSignalNotification: m_sampleRate: " << m_sampleRate;
return true;
}
else if (MsgConfigureScopeVisNG::match(message))
{
MsgConfigureScopeVisNG& conf = (MsgConfigureScopeVisNG&) message;
}
2017-01-29 13:51:45 -05:00
}