mirror of
https://github.com/f4exb/sdrangel.git
synced 2024-12-23 10:05:46 -05:00
New scope: mag (dB) power overlay on XY polar trace - basic
This commit is contained in:
parent
3e9db6af09
commit
6c60189fdc
@ -49,6 +49,7 @@ ScopeVisNG::ScopeVisNG(GLScopeNG* glScope) :
|
||||
m_traceStart(true),
|
||||
m_traceFill(0),
|
||||
m_zTraceIndex(-1),
|
||||
m_timeBase(1),
|
||||
m_timeOfsProMill(0),
|
||||
m_sampleRate(0),
|
||||
m_traceDiscreteMemory(m_nbTraceMemories),
|
||||
@ -424,20 +425,53 @@ int ScopeVisNG::processTraces(const SampleVector::const_iterator& cbegin, const
|
||||
continue;
|
||||
}
|
||||
|
||||
ProjectionType projectionType = itData->m_projectionType;
|
||||
|
||||
if (itCtl->m_traceCount[m_traces.currentBufferIndex()] < m_traceSize)
|
||||
{
|
||||
ProjectionType projectionType = itData->m_projectionType;
|
||||
float v;
|
||||
|
||||
if (projectionType == ProjectionMagLin) {
|
||||
if (projectionType == ProjectionMagLin)
|
||||
{
|
||||
v = (itCtl->m_projector.run(*begin) - itData->m_ofs)*itData->m_amp - 1.0f;
|
||||
} else if (projectionType == ProjectionMagDB) {
|
||||
}
|
||||
else if (projectionType == ProjectionMagDB)
|
||||
{
|
||||
// there is no processing advantage in direct calculation without projector
|
||||
// uint32_t magsq = begin->m_real*begin->m_real + begin->m_imag*begin->m_imag;
|
||||
// v = ((log10f(magsq/1073741824.0f)*0.2f - 2.0f*itData->m_ofs) + 2.0f)*itData->m_amp - 1.0f;
|
||||
float p = itCtl->m_projector.run(*begin) - (100.0f * itData->m_ofs);
|
||||
float pdB = itCtl->m_projector.run(*begin);
|
||||
float p = pdB - (100.0f * itData->m_ofs);
|
||||
v = ((p/50.0f) + 2.0f)*itData->m_amp - 1.0f;
|
||||
} else {
|
||||
|
||||
if (itCtl->m_nbPow == 0)
|
||||
{
|
||||
itCtl->m_maxPow = -200.0f;
|
||||
itCtl->m_sumPow = 0.0f;
|
||||
itCtl->m_nbPow = 1;
|
||||
}
|
||||
|
||||
if (pdB > -200.0f)
|
||||
{
|
||||
if (pdB > itCtl->m_maxPow)
|
||||
{
|
||||
itCtl->m_maxPow = pdB;
|
||||
}
|
||||
|
||||
itCtl->m_sumPow += pdB;
|
||||
itCtl->m_nbPow++;
|
||||
}
|
||||
|
||||
if ((m_nbSamples == 1) && (itCtl->m_nbPow > 0))
|
||||
{
|
||||
double avgPow = itCtl->m_sumPow / itCtl->m_nbPow;
|
||||
double peakToAvgPow = itCtl->m_maxPow - avgPow;
|
||||
itData->m_textOverlay = QString("%1 %2 %3").arg(itCtl->m_maxPow, 0, 'f', 1).arg(avgPow, 0, 'f', 1).arg(peakToAvgPow, 0, 'f', 1);
|
||||
itCtl->m_nbPow = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
v = (itCtl->m_projector.run(*begin) - itData->m_ofs) * itData->m_amp;
|
||||
}
|
||||
|
||||
@ -452,6 +486,12 @@ int ScopeVisNG::processTraces(const SampleVector::const_iterator& cbegin, const
|
||||
(*itTrace)[2*(itCtl->m_traceCount[m_traces.currentBufferIndex()]) + 1] = v; // display y
|
||||
itCtl->m_traceCount[m_traces.currentBufferIndex()]++;
|
||||
}
|
||||
else
|
||||
{
|
||||
// if (projectionType == ProjectionMagDB) // create power display overlay
|
||||
// {
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
++begin;
|
||||
|
@ -64,6 +64,8 @@ public:
|
||||
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
|
||||
|
||||
TraceData() :
|
||||
m_projectionType(ProjectionReal),
|
||||
@ -77,7 +79,8 @@ public:
|
||||
m_traceDelayCoarse(0),
|
||||
m_traceDelayFine(0),
|
||||
m_triggerDisplayLevel(2.0), // OVer scale by default (2.0)
|
||||
m_traceColor(255,255,64)
|
||||
m_traceColor(255,255,64),
|
||||
m_hasTextOverlay(false)
|
||||
{
|
||||
setColor(m_traceColor);
|
||||
}
|
||||
@ -705,6 +708,9 @@ private:
|
||||
{
|
||||
Projector m_projector; //!< Projector transform from complex trace to real (displayable) trace
|
||||
int 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)
|
||||
{
|
||||
@ -728,6 +734,9 @@ private:
|
||||
{
|
||||
m_traceCount[0] = 0;
|
||||
m_traceCount[1] = 0;
|
||||
m_maxPow = 0.0f;
|
||||
m_sumPow = 0.0f;
|
||||
m_nbPow = 0;
|
||||
}
|
||||
};
|
||||
|
||||
@ -920,6 +929,7 @@ private:
|
||||
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_timeBase; //!< Trace display time divisor
|
||||
int m_timeOfsProMill; //!< Start trace shift in 1/1000 trace size
|
||||
bool m_traceStart; //!< Trace is at start point
|
||||
int m_traceFill; //!< Count of samples accumulated into trace
|
||||
|
@ -56,8 +56,8 @@ GLScopeNG::GLScopeNG(QWidget* parent) :
|
||||
m_x2Scale.setFont(font());
|
||||
m_x2Scale.setOrientation(Qt::Horizontal);
|
||||
|
||||
m_powerOverlayFont.setBold(true);
|
||||
m_powerOverlayFont.setPointSize(font().pointSize()+1);
|
||||
m_channelOverlayFont.setBold(true);
|
||||
m_channelOverlayFont.setPointSize(font().pointSize()+1);
|
||||
|
||||
//m_traceCounter = 0;
|
||||
}
|
||||
@ -715,6 +715,12 @@ void GLScopeNG::paintGL()
|
||||
mat.scale(2.0f * rectW, -2.0f * rectH);
|
||||
m_glShaderSimple.drawSegments(mat, color, q3, 2);
|
||||
}
|
||||
|
||||
// Paint overlay if any
|
||||
if ((i == m_focusedTraceIndex) && (traceData.m_hasTextOverlay))
|
||||
{
|
||||
drawChannelOverlay(traceData.m_textOverlay, m_channelOverlayPixmap1, m_glScopeRect1);
|
||||
}
|
||||
} // all traces display
|
||||
} // trace length > 0
|
||||
|
||||
@ -1824,6 +1830,54 @@ void GLScopeNG::setYScale(ScaleEngine& scale, uint32_t highlightedTraceIndex)
|
||||
}
|
||||
}
|
||||
|
||||
void GLScopeNG::drawChannelOverlay(const QString& text, QPixmap& channelOverlayPixmap, QRectF& glScopeRect)
|
||||
{
|
||||
if (text.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
QFontMetricsF metrics(m_channelOverlayFont);
|
||||
QRectF rect = metrics.boundingRect(text);
|
||||
channelOverlayPixmap = QPixmap(rect.width() + 4.0f, rect.height());
|
||||
channelOverlayPixmap.fill(Qt::transparent);
|
||||
QPainter painter(&channelOverlayPixmap);
|
||||
painter.setRenderHints(QPainter::Antialiasing|QPainter::TextAntialiasing, false);
|
||||
painter.fillRect(rect, QColor(0, 0, 0, 0x80));
|
||||
painter.setPen(QColor(0xff, 0xff, 0xff, 0x80));
|
||||
painter.setFont(m_channelOverlayFont);
|
||||
painter.drawText(QPointF(0, rect.height() - 2.0f), text);
|
||||
painter.end();
|
||||
|
||||
m_glShaderPowerOverlay.initTexture(channelOverlayPixmap.toImage());
|
||||
|
||||
{
|
||||
GLfloat vtx1[] = {
|
||||
0, 1,
|
||||
1, 1,
|
||||
1, 0,
|
||||
0, 0
|
||||
};
|
||||
GLfloat tex1[] = {
|
||||
0, 1,
|
||||
1, 1,
|
||||
1, 0,
|
||||
0, 0
|
||||
};
|
||||
|
||||
float shiftX = glScopeRect.width() - ((rect.width() + 4.0f) / width());
|
||||
float rectX = glScopeRect.x() + shiftX;
|
||||
float rectY = 0;
|
||||
float rectW = rect.width() / (float) width();
|
||||
float rectH = rect.height() / (float) height();
|
||||
|
||||
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_glShaderPowerOverlay.drawSurface(mat, tex1, vtx1, 4);
|
||||
}
|
||||
}
|
||||
|
||||
void GLScopeNG::tick()
|
||||
{
|
||||
if(m_dataChanged) {
|
||||
|
@ -111,7 +111,8 @@ private:
|
||||
QPixmap m_left2ScalePixmap;
|
||||
QPixmap m_bot1ScalePixmap;
|
||||
QPixmap m_bot2ScalePixmap;
|
||||
QPixmap m_powerOverlayPixmap1;
|
||||
QPixmap m_channelOverlayPixmap1;
|
||||
QPixmap m_channelOverlayPixmap2;
|
||||
|
||||
int m_displayGridIntensity;
|
||||
int m_displayTraceIntensity;
|
||||
@ -121,7 +122,7 @@ private:
|
||||
ScaleEngine m_y1Scale; //!< Display #1 Y scale. Always connected to trace #0 (X trace)
|
||||
ScaleEngine m_y2Scale; //!< Display #2 Y scale. Connected to highlighted Y trace (#1..n)
|
||||
|
||||
QFont m_powerOverlayFont;
|
||||
QFont m_channelOverlayFont;
|
||||
|
||||
GLShaderSimple m_glShaderSimple;
|
||||
GLShaderTextured m_glShaderLeft1Scale;
|
||||
@ -146,6 +147,11 @@ private:
|
||||
void setHorizontalDisplays(); //!< Arrange displays when X and Y are stacked horizontally
|
||||
void setPolarDisplays(); //!< Arrange displays when X and Y are stacked over on the left and polar display is on the right
|
||||
|
||||
void drawChannelOverlay( //!< Draws a text overlay
|
||||
const QString& text,
|
||||
QPixmap& channelOverlayPixmap,
|
||||
QRectF& glScopeRect);
|
||||
|
||||
protected slots:
|
||||
void cleanup();
|
||||
void tick();
|
||||
|
@ -309,6 +309,7 @@ bool GLScopeNGGUI::deserialize(const QByteArray& data)
|
||||
|
||||
ui->trace->setMaximum(nbTracesSaved-1);
|
||||
ui->trace->setValue(nbTracesSaved-1);
|
||||
m_glScope->setFocusedTraceIndex(nbTracesSaved-1);
|
||||
|
||||
int r,g,b,a;
|
||||
m_focusedTraceColor.getRgb(&r, &g, &b, &a);
|
||||
@ -379,6 +380,11 @@ bool GLScopeNGGUI::deserialize(const QByteArray& data)
|
||||
{
|
||||
m_scopeVis->addTrigger(triggerData);
|
||||
}
|
||||
|
||||
if (iTrigger == nbTriggersSaved-1)
|
||||
{
|
||||
m_glScope->setFocusedTriggerData(triggerData);
|
||||
}
|
||||
}
|
||||
|
||||
ui->trig->setMaximum(nbTriggersSaved-1);
|
||||
@ -1107,6 +1113,8 @@ void GLScopeNGGUI::disableLiveMode(bool disable)
|
||||
void GLScopeNGGUI::fillTraceData(ScopeVisNG::TraceData& traceData)
|
||||
{
|
||||
traceData.m_projectionType = (ScopeVisNG::ProjectionType) ui->traceMode->currentIndex();
|
||||
traceData.m_hasTextOverlay = (traceData.m_projectionType == ScopeVisNG::ProjectionMagDB);
|
||||
traceData.m_textOverlay.clear();
|
||||
traceData.m_inputIndex = 0;
|
||||
traceData.m_amp = 0.2 / amps[ui->amp->value()];
|
||||
traceData.m_ampIndex = ui->amp->value();
|
||||
|
Loading…
Reference in New Issue
Block a user