From 016ec0182643355e26e8edfc7375d3b0b4c1e4b2 Mon Sep 17 00:00:00 2001 From: f4exb Date: Mon, 7 Jun 2021 01:46:11 +0200 Subject: [PATCH] GLScope redesign: ScopeVis multiple I/Q streams support --- sdrbase/dsp/scopevis.cpp | 70 ++++++++++++++++++------------ sdrbase/dsp/scopevis.h | 30 +++++++++---- sdrgui/gui/glscopegui.cpp | 91 ++++++++++++++++++++++++--------------- 3 files changed, 121 insertions(+), 70 deletions(-) diff --git a/sdrbase/dsp/scopevis.cpp b/sdrbase/dsp/scopevis.cpp index c368a2a58..2ca211a93 100644 --- a/sdrbase/dsp/scopevis.cpp +++ b/sdrbase/dsp/scopevis.cpp @@ -50,6 +50,7 @@ ScopeVis::ScopeVis() : m_focusedTriggerIndex(0), m_triggerState(TriggerUntriggered), m_focusedTraceIndex(0), + m_nbStreams(1), m_traceChunkSize(GLScopeSettings::m_traceChunkDefaultSize), m_traceSize(GLScopeSettings::m_traceChunkDefaultSize), m_liveTraceSize(GLScopeSettings::m_traceChunkDefaultSize), @@ -129,9 +130,16 @@ void ScopeVis::setPreTriggerDelay(uint32_t preTriggerDelay, bool emitSignal) } } -void ScopeVis::configure(uint32_t traceSize, uint32_t timeBase, uint32_t timeOfsProMill, uint32_t triggerPre, bool freeRun) +void ScopeVis::configure( + uint32_t nbStreams, + uint32_t traceSize, + uint32_t timeBase, + uint32_t timeOfsProMill, + uint32_t triggerPre, + bool freeRun +) { - Message* cmd = MsgConfigureScopeVisNG::create(traceSize, timeBase, timeOfsProMill, triggerPre, freeRun); + Message* cmd = MsgConfigureScopeVisNG::create(nbStreams, traceSize, timeBase, timeOfsProMill, triggerPre, freeRun); getInputMessageQueue()->push(cmd); } @@ -311,8 +319,8 @@ void ScopeVis::processMemoryTrace() TraceBackDiscreteMemory::moveIt(mbegin, mbegin_tb, -m_maxTraceDelay); m_nbSamples = m_traceSize + m_maxTraceDelay; - processTraces(mbegin_tb[0], m_maxTraceDelay, true); // traceback - processTraces(mbegin[0], m_traceSize, false); + processTraces(mbegin_tb, m_maxTraceDelay, true); // traceback + processTraces(mbegin, m_traceSize, false); } } @@ -454,24 +462,24 @@ void ScopeVis::processTrace(const std::vector& vcb { // trace back std::vector tbegin(mbegin.size()); TraceBackDiscreteMemory::moveIt(mbegin, tbegin, - m_preTriggerDelay - m_maxTraceDelay); - processTraces(tbegin[0] , m_maxTraceDelay, true); + processTraces(tbegin, m_maxTraceDelay, true); } if (m_preTriggerDelay > 0) { // pre-trigger std::vector tbegin(mbegin.size()); TraceBackDiscreteMemory::moveIt(mbegin, tbegin, -m_preTriggerDelay); - processTraces(tbegin[0], m_preTriggerDelay); + processTraces(tbegin, m_preTriggerDelay); } // process the rest of the trace - remainder = processTraces(mbegin[0], count); + remainder = processTraces(mbegin, count); m_traceStart = false; } else // process the current trace { - remainder = processTraces(mbegin[0], count); + remainder = processTraces(mbegin, count); } if (remainder >= 0) // finished @@ -535,15 +543,15 @@ bool ScopeVis::nextTrigger() } } -int ScopeVis::processTraces(const SampleVector::const_iterator& cbegin, int ilength, bool traceBack) +int ScopeVis::processTraces(const std::vector& vcbegin, int ilength, bool traceBack) { - SampleVector::const_iterator begin(cbegin); + std::vector vbegin(vcbegin); uint32_t shift = (m_timeOfsProMill / 1000.0) * m_traceSize; uint32_t length = m_traceSize / m_timeBase; int remainder = ilength; if (m_spectrumVis) { - m_spectrumVis->feed(cbegin, cbegin + ilength, false); + m_spectrumVis->feed(vcbegin[0], vcbegin[0] + ilength, false); // TODO: use spectrum stream index } while ((remainder > 0) && (m_nbSamples > 0)) @@ -564,14 +572,15 @@ int ScopeVis::processTraces(const SampleVector::const_iterator& cbegin, int ilen { uint32_t& traceCount = (*itCtl)->m_traceCount[m_traces.currentBufferIndex()]; // reference for code clarity float v; + uint32_t streamIndex = itData->m_streamIndex; if (projectionType == Projector::ProjectionMagLin) { - v = ((*itCtl)->m_projector.run(*begin) - itData->m_ofs)*itData->m_amp - 1.0f; + v = ((*itCtl)->m_projector.run(*vbegin[streamIndex]) - itData->m_ofs)*itData->m_amp - 1.0f; } else if (projectionType == Projector::ProjectionMagSq) { - Real magsq = (*itCtl)->m_projector.run(*begin); + Real magsq = (*itCtl)->m_projector.run(*vbegin[streamIndex]); v = (magsq - itData->m_ofs)*itData->m_amp - 1.0f; if ((traceCount >= shift) && (traceCount < shift+length)) // power display overlay values construction @@ -604,8 +613,8 @@ int ScopeVis::processTraces(const SampleVector::const_iterator& cbegin, int ilen } else if (projectionType == Projector::ProjectionMagDB) { - Real re = begin->m_real / SDR_RX_SCALEF; - Real im = begin->m_imag / SDR_RX_SCALEF; + Real re = vbegin[streamIndex]->m_real / SDR_RX_SCALEF; + Real im = vbegin[streamIndex]->m_imag / SDR_RX_SCALEF; double magsq = re*re + im*im; float pdB = log10f(magsq) * 10.0f; float p = pdB - (100.0f * itData->m_ofs); @@ -643,7 +652,7 @@ int ScopeVis::processTraces(const SampleVector::const_iterator& cbegin, int ilen } else { - v = ((*itCtl)->m_projector.run(*begin) - itData->m_ofs) * itData->m_amp; + v = ((*itCtl)->m_projector.run(*vbegin[streamIndex]) - itData->m_ofs) * itData->m_amp; } if(v > 1.0f) { @@ -659,7 +668,9 @@ int ScopeVis::processTraces(const SampleVector::const_iterator& cbegin, int ilen } } - ++begin; + for (unsigned int i = 0; i < vbegin.size(); i++) { + ++vbegin[i]; + } remainder--; m_nbSamples--; } @@ -731,17 +742,23 @@ bool ScopeVis::handleMessage(const Message& message) QMutexLocker configLocker(&m_mutex); MsgConfigureScopeVisNG& conf = (MsgConfigureScopeVisNG&) message; + uint32_t nbStreams = conf.getNbStreams(); uint32_t traceSize = conf.getTraceSize(); uint32_t timeBase = conf.getTimeBase(); uint32_t timeOfsProMill = conf.getTimeOfsProMill(); uint32_t triggerPre = conf.getTriggerPre(); bool freeRun = conf.getFreeRun(); - if (m_traceSize != traceSize) - { + if (m_traceSize != traceSize) { setTraceSize(traceSize); } + if (m_nbStreams != nbStreams) + { + m_traceDiscreteMemory.setNbStreams(nbStreams); + m_nbStreams = nbStreams; + } + if (m_timeBase != timeBase) { m_timeBase = timeBase; @@ -760,21 +777,20 @@ bool ScopeVis::handleMessage(const Message& message) } } - if (m_preTriggerDelay != triggerPre) - { + if (m_preTriggerDelay != triggerPre) { setPreTriggerDelay(triggerPre); } - if (freeRun != m_freeRun) - { + if (freeRun != m_freeRun) { m_freeRun = freeRun; } qDebug() << "ScopeVis::handleMessage: MsgConfigureScopeVisNG:" - << " m_traceSize: " << m_traceSize - << " m_timeOfsProMill: " << m_timeOfsProMill - << " m_preTriggerDelay: " << m_preTriggerDelay - << " m_freeRun: " << m_freeRun; + << " m_nbStreams: " << m_nbStreams + << " m_traceSize: " << m_traceSize + << " m_timeOfsProMill: " << m_timeOfsProMill + << " m_preTriggerDelay: " << m_preTriggerDelay + << " m_freeRun: " << m_freeRun; if ((m_glScope) && (m_currentTraceMemoryIndex > 0)) { processMemoryTrace(); diff --git a/sdrbase/dsp/scopevis.h b/sdrbase/dsp/scopevis.h index cc06aa420..6a0c872fb 100644 --- a/sdrbase/dsp/scopevis.h +++ b/sdrbase/dsp/scopevis.h @@ -54,7 +54,7 @@ public: MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } //!< Get the queue for asynchronous inbound communication void setLiveRate(int sampleRate); - void configure(uint32_t traceSize, uint32_t timeBase, uint32_t timeOfsProMill, uint32_t triggerPre, bool freeRun); + void configure(uint32_t nbStreams, uint32_t traceSize, uint32_t timeBase, uint32_t timeOfsProMill, uint32_t triggerPre, bool freeRun); void addTrace(const GLScopeSettings::TraceData& traceData); void changeTrace(const GLScopeSettings::TraceData& traceData, uint32_t traceIndex); void removeTrace(uint32_t traceIndex); @@ -152,15 +152,17 @@ private: public: static MsgConfigureScopeVisNG* create( + uint32_t nbStreams, uint32_t traceSize, uint32_t timeBase, uint32_t timeOfsProMill, uint32_t triggerPre, bool freeRun) { - return new MsgConfigureScopeVisNG(traceSize, timeBase, timeOfsProMill, triggerPre, freeRun); + return new MsgConfigureScopeVisNG(nbStreams, traceSize, timeBase, timeOfsProMill, triggerPre, freeRun); } + uint32_t getNbStreams() const { return m_nbStreams; } uint32_t getTraceSize() const { return m_traceSize; } uint32_t getTimeBase() const { return m_timeBase; } uint32_t getTimeOfsProMill() const { return m_timeOfsProMill; } @@ -168,17 +170,22 @@ private: bool getFreeRun() const { return m_freeRun; } private: + uint32_t m_nbStreams; uint32_t m_traceSize; uint32_t m_timeBase; uint32_t m_timeOfsProMill; uint32_t m_triggerPre; bool m_freeRun; - MsgConfigureScopeVisNG(uint32_t traceSize, - uint32_t timeBase, - uint32_t timeOfsProMill, - uint32_t triggerPre, - bool freeRun) : + MsgConfigureScopeVisNG( + uint32_t nbStreams, + uint32_t traceSize, + uint32_t timeBase, + uint32_t timeOfsProMill, + uint32_t triggerPre, + bool freeRun + ) : + m_nbStreams(nbStreams), m_traceSize(traceSize), m_timeBase(timeBase), m_timeOfsProMill(timeOfsProMill), @@ -628,6 +635,12 @@ private: } } + void setNbStreams(uint32_t nbStreams) + { + m_traceBackBuffersStreams.resize(nbStreams); + resize(m_traceSize); + } + /** * Resize all trace buffers in memory */ @@ -1178,6 +1191,7 @@ private: 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 @@ -1220,7 +1234,7 @@ private: * - if finished it returns the number of unprocessed samples left in the buffer * - if not finished it returns -1 */ - int processTraces(const SampleVector::const_iterator& begin, int length, bool traceBack = false); + int processTraces(const std::vector& vbegin, int length, bool traceBack = false); /** * Get maximum trace delay diff --git a/sdrgui/gui/glscopegui.cpp b/sdrgui/gui/glscopegui.cpp index 8f7690b7a..8902eb2f6 100644 --- a/sdrgui/gui/glscopegui.cpp +++ b/sdrgui/gui/glscopegui.cpp @@ -114,17 +114,23 @@ void GLScopeGUI::setBuddies(MessageQueue* messageQueue, ScopeVis* scopeVis, GLSc ui->trigMode->clear(); fillProjectionCombo(ui->trigMode); - m_scopeVis->configure(2*m_traceLenMult*m_scopeVis->getTraceChunkSize(), - m_timeBase, - m_timeOffset*10, - (uint32_t) (m_glScope->getTraceSize() * (ui->trigPre->value()/100.0f)), - ui->freerun->isChecked()); + m_scopeVis->configure( + 1, + 2*m_traceLenMult*m_scopeVis->getTraceChunkSize(), + m_timeBase, + m_timeOffset*10, + (uint32_t) (m_glScope->getTraceSize() * (ui->trigPre->value()/100.0f)), + ui->freerun->isChecked() + ); - m_scopeVis->configure(m_traceLenMult*m_scopeVis->getTraceChunkSize(), - m_timeBase, - m_timeOffset*10, - (uint32_t) (m_glScope->getTraceSize() * (ui->trigPre->value()/100.0f)), - ui->freerun->isChecked()); + m_scopeVis->configure( + 1, + m_traceLenMult*m_scopeVis->getTraceChunkSize(), + m_timeBase, + m_timeOffset*10, + (uint32_t) (m_glScope->getTraceSize() * (ui->trigPre->value()/100.0f)), + ui->freerun->isChecked() + ); setTraceLenDisplay(); setTimeScaleDisplay(); @@ -568,11 +574,14 @@ void GLScopeGUI::on_time_valueChanged(int value) m_timeBase = value; setTimeScaleDisplay(); setTraceDelayDisplay(); - m_scopeVis->configure(m_traceLenMult*m_scopeVis->getTraceChunkSize(), - m_timeBase, - m_timeOffset*10, - (uint32_t) (m_glScope->getTraceSize() * (ui->trigPre->value()/100.0f)), - ui->freerun->isChecked()); + m_scopeVis->configure( + 1, + m_traceLenMult*m_scopeVis->getTraceChunkSize(), + m_timeBase, + m_timeOffset*10, + (uint32_t) (m_glScope->getTraceSize() * (ui->trigPre->value()/100.0f)), + ui->freerun->isChecked() + ); } void GLScopeGUI::on_timeOfs_valueChanged(int value) @@ -583,11 +592,14 @@ void GLScopeGUI::on_timeOfs_valueChanged(int value) m_timeOffset = value; setTimeOfsDisplay(); - m_scopeVis->configure(m_traceLenMult*m_scopeVis->getTraceChunkSize(), - m_timeBase, - m_timeOffset*10, - (uint32_t) (m_glScope->getTraceSize() * (ui->trigPre->value()/100.0f)), - ui->freerun->isChecked()); + m_scopeVis->configure( + 1, + m_traceLenMult*m_scopeVis->getTraceChunkSize(), + m_timeBase, + m_timeOffset*10, + (uint32_t) (m_glScope->getTraceSize() * (ui->trigPre->value()/100.0f)), + ui->freerun->isChecked() + ); if (value > 0) { @@ -603,11 +615,14 @@ void GLScopeGUI::on_traceLen_valueChanged(int value) } m_traceLenMult = value; - m_scopeVis->configure(m_traceLenMult*m_scopeVis->getTraceChunkSize(), - m_timeBase, - m_timeOffset*10, - (uint32_t) (m_glScope->getTraceSize() * (ui->trigPre->value()/100.0f)), - ui->freerun->isChecked()); + m_scopeVis->configure( + 1, + m_traceLenMult*m_scopeVis->getTraceChunkSize(), + m_timeBase, + m_timeOffset*10, + (uint32_t) (m_glScope->getTraceSize() * (ui->trigPre->value()/100.0f)), + ui->freerun->isChecked() + ); setTraceLenDisplay(); setTimeScaleDisplay(); setTimeOfsDisplay(); @@ -972,11 +987,14 @@ void GLScopeGUI::on_trigPre_valueChanged(int value) { (void) value; setTrigPreDisplay(); - m_scopeVis->configure(m_traceLenMult*m_scopeVis->getTraceChunkSize(), - m_timeBase, - m_timeOffset*10, - (uint32_t) (m_glScope->getTraceSize() * (ui->trigPre->value()/100.0f)), - ui->freerun->isChecked()); + m_scopeVis->configure( + 1, + m_traceLenMult*m_scopeVis->getTraceChunkSize(), + m_timeBase, + m_timeOffset*10, + (uint32_t) (m_glScope->getTraceSize() * (ui->trigPre->value()/100.0f)), + ui->freerun->isChecked() + ); } void GLScopeGUI::on_trigColor_clicked() @@ -1010,11 +1028,14 @@ void GLScopeGUI::on_freerun_toggled(bool checked) ui->trigOneShot->setEnabled(true); } - m_scopeVis->configure(m_traceLenMult*m_scopeVis->getTraceChunkSize(), - m_timeBase, - m_timeOffset*10, - (uint32_t) (m_glScope->getTraceSize() * (ui->trigPre->value()/100.0f)), - ui->freerun->isChecked()); + m_scopeVis->configure( + 1, + m_traceLenMult*m_scopeVis->getTraceChunkSize(), + m_timeBase, + m_timeOffset*10, + (uint32_t) (m_glScope->getTraceSize() * (ui->trigPre->value()/100.0f)), + ui->freerun->isChecked() + ); } void GLScopeGUI::setTraceIndexDisplay()