diff --git a/sdrbase/dsp/scopevisng.cpp b/sdrbase/dsp/scopevisng.cpp
index 044d70303..fab38df77 100644
--- a/sdrbase/dsp/scopevisng.cpp
+++ b/sdrbase/dsp/scopevisng.cpp
@@ -28,6 +28,7 @@ MESSAGE_CLASS_DEFINITION(ScopeVisNG::MsgScopeVisNGFocusOnTrigger, Message)
MESSAGE_CLASS_DEFINITION(ScopeVisNG::MsgScopeVisNGAddTrace, Message)
MESSAGE_CLASS_DEFINITION(ScopeVisNG::MsgScopeVisNGChangeTrace, Message)
MESSAGE_CLASS_DEFINITION(ScopeVisNG::MsgScopeVisNGRemoveTrace, Message)
+MESSAGE_CLASS_DEFINITION(ScopeVisNG::MsgScopeVisNGFocusOnTrace, Message)
const uint ScopeVisNG::m_traceChunkSize = 4800;
const Real ScopeVisNG::ProjectorMagDB::mult = (10.0f / log2f(10.0f));
@@ -39,6 +40,7 @@ ScopeVisNG::ScopeVisNG(GLScopeNG* glScope) :
m_currentTriggerIndex(0),
m_focusedTriggerIndex(0),
m_triggerState(TriggerUntriggered),
+ m_focusedTraceIndex(0),
m_traceSize(m_traceChunkSize),
m_nbSamples(0),
m_traceStart(true),
@@ -96,6 +98,12 @@ void ScopeVisNG::removeTrace(uint32_t traceIndex)
getInputMessageQueue()->push(cmd);
}
+void ScopeVisNG::focusOnTrace(uint32_t traceIndex)
+{
+ Message* cmd = MsgScopeVisNGFocusOnTrace::create(traceIndex);
+ getInputMessageQueue()->push(cmd);
+}
+
void ScopeVisNG::addTrigger(const TriggerData& triggerData)
{
Message* cmd = MsgScopeVisNGAddTrigger::create(triggerData);
@@ -573,6 +581,21 @@ bool ScopeVisNG::handleMessage(const Message& message)
m_glScope->updateDisplay();
return true;
}
+ else if (MsgScopeVisNGFocusOnTrace::match(message))
+ {
+ MsgScopeVisNGFocusOnTrace& conf = (MsgScopeVisNGFocusOnTrace&) message;
+ int traceIndex = conf.getTraceIndex();
+
+ if (traceIndex < m_traces.m_tracesData.size())
+ {
+ m_focusedTraceIndex = traceIndex;
+ computeDisplayTriggerLevels();
+ m_glScope->setFocusedTraceIndex(m_focusedTraceIndex);
+ m_glScope->updateDisplay();
+ }
+
+ return true;
+ }
else
{
return false;
diff --git a/sdrbase/dsp/scopevisng.h b/sdrbase/dsp/scopevisng.h
index c7dee023d..c42499735 100644
--- a/sdrbase/dsp/scopevisng.h
+++ b/sdrbase/dsp/scopevisng.h
@@ -50,8 +50,12 @@ public:
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_traceDelayValue; //!< Trace 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
@@ -62,8 +66,12 @@ public:
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_traceDelayValue(0),
m_triggerDisplayLevel(2.0), // OVer scale by default (2.0)
m_traceColor(255,255,64)
{
@@ -141,6 +149,7 @@ public:
void addTrace(const TraceData& traceData);
void changeTrace(const TraceData& traceData, uint32_t traceIndex);
void removeTrace(uint32_t traceIndex);
+ void focusOnTrace(uint32_t traceIndex);
void addTrigger(const TriggerData& triggerData);
void changeTrigger(const TriggerData& triggerData, uint32_t triggerIndex);
void removeTrigger(uint32_t triggerIndex);
@@ -359,6 +368,27 @@ private:
{}
};
+ // ---------------------------------------------
+ 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)
+ {}
+ };
+
// === projectors ===
// ---------------------------------------------
class Projector
@@ -852,6 +882,7 @@ private:
int 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
int m_traceSize; //!< Size of traces in number of samples
int m_nbSamples; //!< Number of samples yet to process in one complex trace
int m_timeOfsProMill; //!< Start trace shift in 1/1000 trace size
diff --git a/sdrbase/gui/glscopeng.cpp b/sdrbase/gui/glscopeng.cpp
index 51f596915..66be14569 100644
--- a/sdrbase/gui/glscopeng.cpp
+++ b/sdrbase/gui/glscopeng.cpp
@@ -40,7 +40,7 @@ GLScopeNG::GLScopeNG(QWidget* parent) :
m_sampleRate(0),
m_triggerPre(0),
m_timeOfsProMill(0),
- m_highlightedTraceIndex(0),
+ m_focusedTraceIndex(0),
m_timeOffset(0)
{
setAttribute(Qt::WA_OpaquePaintEvent);
@@ -295,8 +295,6 @@ void GLScopeNG::paintGL()
m_glShaderBottom1Scale.drawSurface(m_glBot1ScaleMatrix, tex1, vtx1, 4);
}
- // TODO: paint trigger level #1
-
// paint trace #1
if (m_traceSize > 0)
{
@@ -346,13 +344,172 @@ void GLScopeNG::paintGL()
mat.translate(-1.0f + 2.0f * rectX, 1.0f - 2.0f * rectY);
mat.scale(2.0f * rectW, -2.0f * rectH);
m_glShaderSimple.drawSegments(mat, color, q3, 2);
- }
- }
- }
+ } // display trace
+ } // trace length > 0
+ } // Display X only
else if (m_displayMode == DisplayY) // display only traces #1..n
{
- }
+ // draw rect around
+ {
+ GLfloat q3[] {
+ 1, 1,
+ 0, 1,
+ 0, 0,
+ 1, 0
+ };
+
+ QVector4D color(1.0f, 1.0f, 1.0f, 0.5f);
+ m_glShaderSimple.drawContour(m_glScopeMatrix1, color, q3, 4);
+ }
+
+ // paint grid
+ const ScaleEngine::TickList* tickList;
+ const ScaleEngine::Tick* tick;
+
+ // Y2 (Focused Y trace)
+ {
+ tickList = &m_y2Scale.getTickList();
+
+ GLfloat q3[4*tickList->count()];
+ int effectiveTicks = 0;
+
+ for (int i= 0; i < tickList->count(); i++)
+ {
+ tick = &(*tickList)[i];
+
+ if (tick->major)
+ {
+ if (tick->textSize > 0)
+ {
+ float y = 1 - (tick->pos / m_y2Scale.getSize());
+ q3[4*effectiveTicks] = 0;
+ q3[4*effectiveTicks+1] = y;
+ q3[4*effectiveTicks+2] = 1;
+ q3[4*effectiveTicks+3] = y;
+ effectiveTicks++;
+ }
+ }
+ }
+
+ float blue = 1.0f;
+ QVector4D color(1.0f, 1.0f, blue, (float) m_displayGridIntensity / 100.0f);
+ m_glShaderSimple.drawSegments(m_glScopeMatrix1, color, q3, 2*effectiveTicks);
+ }
+
+ // X1 (time)
+ {
+ tickList = &m_x1Scale.getTickList();
+
+ GLfloat q3[4*tickList->count()];
+ int effectiveTicks = 0;
+ for(int i= 0; i < tickList->count(); i++) {
+ tick = &(*tickList)[i];
+ if(tick->major) {
+ if(tick->textSize > 0) {
+ float x = tick->pos / m_x1Scale.getSize();
+ q3[4*effectiveTicks] = x;
+ q3[4*effectiveTicks+1] = 0;
+ q3[4*effectiveTicks+2] = x;
+ q3[4*effectiveTicks+3] = 1;
+ effectiveTicks++;
+ }
+ }
+ }
+
+ QVector4D color(1.0f, 1.0f, 1.0f, (float) m_displayGridIntensity / 100.0f);
+ m_glShaderSimple.drawSegments(m_glScopeMatrix1, color, q3, 2*effectiveTicks);
+ }
+
+ // paint left #1 scale
+ {
+ GLfloat vtx1[] = {
+ 0, 1,
+ 1, 1,
+ 1, 0,
+ 0, 0
+ };
+ GLfloat tex1[] = {
+ 0, 1,
+ 1, 1,
+ 1, 0,
+ 0, 0
+ };
+ m_glShaderLeft1Scale.drawSurface(m_glLeft1ScaleMatrix, tex1, vtx1, 4);
+ }
+
+ // paint bottom #1 scale
+ {
+ GLfloat vtx1[] = {
+ 0, 1,
+ 1, 1,
+ 1, 0,
+ 0, 0
+ };
+ GLfloat tex1[] = {
+ 0, 1,
+ 1, 1,
+ 1, 0,
+ 0, 0
+ };
+ m_glShaderBottom1Scale.drawSurface(m_glBot1ScaleMatrix, tex1, vtx1, 4);
+ }
+
+ // paint traces #1..n
+ if (m_traceSize > 0)
+ {
+ for (int i = 1; i < m_traces->size(); i++)
+ {
+ const float *trace = (*m_traces)[i];
+ const ScopeVisNG::TraceData& traceData = (*m_tracesData)[i];
+
+ int start = (m_timeOfsProMill/1000.0) * m_traceSize;
+ int end = std::min(start + m_traceSize/m_timeBase, m_traceSize);
+
+ if(end - start < 2)
+ start--;
+
+ float rectX = m_glScopeRect1.x();
+ float rectY = m_glScopeRect1.y() + m_glScopeRect1.height() / 2.0f;
+ float rectW = m_glScopeRect1.width() * (float)m_timeBase / (float)(m_traceSize - 1);
+ //float rectH = -(m_glScopeRect1.height() / 2.0f) * traceData.m_amp;
+ float rectH = -m_glScopeRect1.height() / 2.0f;
+
+ //QVector4D color(1.0f, 1.0f, 0.25f, m_displayTraceIntensity / 100.0f);
+ QVector4D color(traceData.m_traceColorR, traceData.m_traceColorG, traceData.m_traceColorB, m_displayTraceIntensity / 100.0f);
+ QMatrix4x4 mat;
+ mat.setToIdentity();
+ mat.translate(-1.0f + 2.0f * rectX, 1.0f - 2.0f * rectY);
+ mat.scale(2.0f * rectW, -2.0f * rectH);
+ m_glShaderSimple.drawPolyline(mat, color, (GLfloat *) &trace[2*start], end - start);
+
+ // Paint trigger level if any
+ if ((traceData.m_triggerDisplayLevel > -1.0f) && (traceData.m_triggerDisplayLevel < 1.0f))
+ {
+ GLfloat q3[] {
+ 0, traceData.m_triggerDisplayLevel,
+ 1, traceData.m_triggerDisplayLevel
+ };
+
+ float rectX = m_glScopeRect1.x();
+ float rectY = m_glScopeRect1.y() + m_glScopeRect1.height() / 2.0f;
+ float rectW = m_glScopeRect1.width();
+ float rectH = -m_glScopeRect1.height() / 2.0f;
+
+ QVector4D color(
+ m_focusedTriggerData.m_triggerColorR,
+ m_focusedTriggerData.m_triggerColorG,
+ m_focusedTriggerData.m_triggerColorB,
+ 0.4f);
+ QMatrix4x4 mat;
+ mat.setToIdentity();
+ mat.translate(-1.0f + 2.0f * rectX, 1.0f - 2.0f * rectY);
+ mat.scale(2.0f * rectW, -2.0f * rectH);
+ m_glShaderSimple.drawSegments(mat, color, q3, 2);
+ }
+ } // one trace display
+ } // trace length > 0
+ } // Display Y only
m_mutex.unlock();
}
@@ -386,9 +543,9 @@ void GLScopeNG::setTimeOfsProMill(int timeOfsProMill)
update();
}
-void GLScopeNG::setHighlightedTraceIndex(uint32_t traceIndex)
+void GLScopeNG::setFocusedTraceIndex(uint32_t traceIndex)
{
- m_highlightedTraceIndex = traceIndex;
+ m_focusedTraceIndex = traceIndex;
m_configChanged = true;
update();
}
@@ -431,9 +588,9 @@ void GLScopeNG::applyConfig()
setYScale(m_y1Scale, 0); // This is always the X trace (trace #0)
}
- if ((m_traces->size() > 1) && (m_highlightedTraceIndex < m_traces->size()))
+ if ((m_traces->size() > 1) && (m_focusedTraceIndex < m_traces->size()))
{
- setYScale(m_y2Scale, m_highlightedTraceIndex > 0 ? m_highlightedTraceIndex : 1); // if Highlighted trace is #0 (X trace) set it to first Y trace (trace #1)
+ setYScale(m_y2Scale, m_focusedTraceIndex > 0 ? m_focusedTraceIndex : 1); // if Highlighted trace is #0 (X trace) set it to first Y trace (trace #1)
}
else
{
diff --git a/sdrbase/gui/glscopeng.h b/sdrbase/gui/glscopeng.h
index 75fb3800a..a353d4a3f 100644
--- a/sdrbase/gui/glscopeng.h
+++ b/sdrbase/gui/glscopeng.h
@@ -61,7 +61,7 @@ public:
void setTimeOfsProMill(int timeOfsProMill);
void setSampleRate(int sampleRate);
void setTimeBase(int timeBase);
- void setHighlightedTraceIndex(uint32_t traceIndex);
+ void setFocusedTraceIndex(uint32_t traceIndex);
void setDisplayMode(DisplayMode displayMode);
void setTraceSize(int trceSize);
void updateDisplay();
@@ -92,7 +92,7 @@ private:
int m_traceSize;
int m_timeBase;
int m_timeOffset;
- uint32_t m_highlightedTraceIndex;
+ uint32_t m_focusedTraceIndex;
// graphics stuff
QRectF m_glScopeRect1;
diff --git a/sdrbase/gui/glscopenggui.cpp b/sdrbase/gui/glscopenggui.cpp
index 350b23525..627b3a2ff 100644
--- a/sdrbase/gui/glscopenggui.cpp
+++ b/sdrbase/gui/glscopenggui.cpp
@@ -270,6 +270,64 @@ void GLScopeNGGUI::on_traceLen_valueChanged(int value)
setTrigPreDisplay();
}
+void GLScopeNGGUI::on_trace_valueChanged(int value)
+{
+ ui->traceText->setText(tr("%1").arg(value));
+
+ ScopeVisNG::TraceData traceData;
+ m_scopeVis->getTraceData(traceData, value);
+
+ qDebug() << "GLScopeNGGUI::on_trace_valueChanged:"
+ << " m_projectionType: " << (int) traceData.m_projectionType
+ << " m_amp" << traceData.m_amp
+ << " m_ofs" << traceData.m_ofs
+ << " m_traceDelay" << traceData.m_traceDelay;
+
+ setTraceUI(traceData);
+
+ m_scopeVis->focusOnTrace(value);
+}
+
+void GLScopeNGGUI::on_traceAdd_clicked(bool checked)
+{
+ if (ui->trace->maximum() < 9)
+ {
+ if (ui->trace->value() == 0)
+ {
+ ui->onlyY->setEnabled(true);
+ ui->horizontalXY->setEnabled(true);
+ ui->verticalXY->setEnabled(true);
+ ui->polar->setEnabled(true);
+ }
+
+ ScopeVisNG::TraceData traceData;
+ fillTraceData(traceData);
+ m_scopeVis->addTrace(traceData);
+ ui->trace->setMaximum(ui->trace->maximum() + 1);
+ }
+}
+
+void GLScopeNGGUI::on_traceDel_clicked(bool checked)
+{
+ if (ui->trace->value() > 0)
+ {
+ ui->trace->setMaximum(ui->trace->maximum() - 1);
+
+ if (ui->trace->value() == 0)
+ {
+ ui->onlyX->setChecked(true);
+ ui->onlyY->setEnabled(false);
+ ui->horizontalXY->setEnabled(false);
+ ui->verticalXY->setEnabled(false);
+ ui->polar->setEnabled(false);
+ m_glScope->setDisplayMode(GLScopeNG::DisplayX);
+ }
+
+ m_scopeVis->removeTrace(ui->trace->value());
+ }
+}
+
+
void GLScopeNGGUI::on_trig_valueChanged(int value)
{
ui->trigText->setText(tr("%1").arg(value));
@@ -720,7 +778,12 @@ void GLScopeNGGUI::fillTraceData(ScopeVisNG::TraceData& traceData)
traceData.m_projectionType = (ScopeVisNG::ProjectionType) ui->traceMode->currentIndex();
traceData.m_inputIndex = 0;
traceData.m_amp = 0.2 / amps[ui->amp->value()];
- traceData.m_traceDelay = 0;
+ traceData.m_ampIndex = ui->amp->value();
+ traceData.m_traceDelay = 0; // TODO
+ traceData.m_traceDelayValue = 0; // TODO
+
+ traceData.m_ofsCoarse = ui->ofsCoarse->value();
+ traceData.m_ofsFine = ui->ofsFine->value();
if (traceData.m_projectionType == ScopeVisNG::ProjectionMagLin) {
traceData.m_ofs = ((10.0 * ui->ofsCoarse->value()) + (ui->ofsFine->value() / 20.0)) / 2000.0f;
@@ -748,6 +811,43 @@ void GLScopeNGGUI::fillTriggerData(ScopeVisNG::TriggerData& triggerData)
triggerData.setColor(m_focusedTriggerColor);
}
+void GLScopeNGGUI::setTraceUI(ScopeVisNG::TraceData& traceData)
+{
+ bool oldStateTraceMode = ui->traceMode->blockSignals(true);
+ bool oldStateAmp = ui->amp->blockSignals(true);
+ bool oldStateOfsCoarse = ui->ofsCoarse->blockSignals(true);
+ bool oldStateOfsFine = ui->ofsFine->blockSignals(true);
+ bool oldStateTraceDelay = ui->traceDelay->blockSignals(true);
+ bool oldStateZSelect = ui->zSelect->blockSignals(true);
+ bool oldStateZTraceMode = ui->zTraceMode->blockSignals(true);
+ bool oldStateTraceColor = ui->traceColor->blockSignals(true);
+
+ ui->traceMode->setCurrentIndex((int) traceData.m_projectionType);
+ ui->amp->setValue(traceData.m_ampIndex);
+ setAmpScaleDisplay();
+
+ ui->ofsCoarse->setValue(traceData.m_ofsCoarse);
+ ui->ofsFine->setValue(traceData.m_ofsFine);
+ setAmpOfsDisplay();
+
+ ui->traceDelay->setValue(traceData.m_traceDelayValue);
+ // TODO: set trace delay display
+
+ m_focusedTraceColor = traceData.m_traceColor;
+ int r, g, b, a;
+ m_focusedTraceColor.getRgb(&r, &g, &b, &a);
+ ui->traceColor->setStyleSheet(tr("QLabel { background-color : rgb(%1,%2,%3); }").arg(r).arg(g).arg(b));
+
+ ui->traceMode->blockSignals(oldStateTraceMode);
+ ui->amp->blockSignals(oldStateAmp);
+ ui->ofsCoarse->blockSignals(oldStateOfsCoarse);
+ ui->ofsFine->blockSignals(oldStateOfsFine);
+ ui->traceDelay->blockSignals(oldStateTraceDelay);
+ ui->zSelect->blockSignals(oldStateZSelect);
+ ui->zTraceMode->blockSignals(oldStateZTraceMode);
+ ui->traceColor->blockSignals(oldStateTraceColor);
+}
+
void GLScopeNGGUI::setTriggerUI(ScopeVisNG::TriggerData& triggerData)
{
bool oldStateTrigMode = ui->trigMode->blockSignals(true);
diff --git a/sdrbase/gui/glscopenggui.h b/sdrbase/gui/glscopenggui.h
index 06c57db63..fae6a219d 100644
--- a/sdrbase/gui/glscopenggui.h
+++ b/sdrbase/gui/glscopenggui.h
@@ -87,6 +87,7 @@ private:
void fillTraceData(ScopeVisNG::TraceData& traceData);
void fillTriggerData(ScopeVisNG::TriggerData& triggerData);
void setTriggerUI(ScopeVisNG::TriggerData& triggerData);
+ void setTraceUI(ScopeVisNG::TraceData& traceData);
void fillProjectionCombo(QComboBox* comboBox);
@@ -104,6 +105,9 @@ private slots:
void on_timeOfs_valueChanged(int value);
void on_traceLen_valueChanged(int value);
// Second row
+ void on_trace_valueChanged(int value);
+ void on_traceAdd_clicked(bool checked);
+ void on_traceDel_clicked(bool checked);
void on_traceMode_currentIndexChanged(int index);
void on_amp_valueChanged(int value);
void on_ofsCoarse_valueChanged(int value);
diff --git a/sdrbase/gui/glscopenggui.ui b/sdrbase/gui/glscopenggui.ui
index 7fe32818c..379bd67ec 100644
--- a/sdrbase/gui/glscopenggui.ui
+++ b/sdrbase/gui/glscopenggui.ui
@@ -515,7 +515,7 @@ kS/s
0
-
-
+
18
@@ -573,7 +573,7 @@ kS/s
-
-
+
18