Spectrum: reworked phosphor display controls

This commit is contained in:
f4exb 2018-10-19 00:40:14 +02:00
parent 9158da20e0
commit e41df6f278
8 changed files with 52 additions and 83 deletions

3
debian/changelog vendored
View File

@ -2,8 +2,9 @@ sdrangel (4.2.3-1) unstable; urgency=medium
* Scope: fixed channel rate affecting scope in memory mode. Issue #227
* Spectrum: limit depth to 1000 when in moving average mode to avoid RAM exhaustion
* Spectrum: reworked phosphor display controls. Re-implements issue #207
-- Edouard Griffiths, F4EXB <f4exb06@gmail.com> Sun, 21 Oct 2018 21:14:18 +0200
-- Edouard Griffiths, F4EXB <f4exb06@gmail.com> Fri, 19 Oct 2018 21:14:18 +0200
sdrangel (4.2.2-1) unstable; urgency=medium

View File

@ -8,7 +8,7 @@ This plugin can be used to generate a narrowband frequency modulated signal. "Na
![NFM Modulator plugin GUI](../../../doc/img/NFMMod_plugin.png)
<h3>1: Frequency shift from center frequency of transmission/h3>
<h3>1: Frequency shift from center frequency of transmission</h3>
Use the wheels to adjust the frequency shift in Hz from the center frequency of transmission. Left click on a digit sets the cursor position at this digit. Right click on a digit sets all digits on the right to zero. This effectively floors value at the digit position. Wheels are moved with the mousewheel while pointing at the wheel or by selecting the wheel with the left mouse click and using the keyboard arrows. Pressing shift simultaneously moves digit by 5 and pressing control moves it by 2.

View File

@ -40,7 +40,7 @@ GLSpectrum::GLSpectrum(QWidget* parent) :
m_referenceLevel(0),
m_powerRange(100),
m_linear(false),
m_decay(0),
m_decay(1),
m_sampleRate(500000),
m_timingRate(1),
m_fftSize(512),
@ -51,16 +51,15 @@ GLSpectrum::GLSpectrum(QWidget* parent) :
m_displayMaxHold(false),
m_currentSpectrum(0),
m_displayCurrent(false),
m_waterfallBuffer(NULL),
m_waterfallBuffer(0),
m_waterfallBufferPos(0),
m_waterfallTextureHeight(-1),
m_waterfallTexturePos(0),
m_displayWaterfall(true),
m_ssbSpectrum(false),
m_lsbDisplay(false),
m_histogramBuffer(NULL),
m_histogram(NULL),
m_histogramHoldoff(NULL),
m_histogramBuffer(0),
m_histogram(0),
m_displayHistogram(true),
m_displayChanged(false),
m_matrixLoc(0),
@ -86,8 +85,8 @@ GLSpectrum::GLSpectrum(QWidget* parent) :
}
m_waterfallPalette[239] = 0xffffffff;
m_histogramPalette[0] = m_waterfallPalette[0];
for(int i = 1; i < 240; i++) {
m_histogramPalette[0] = 0;
for(int i = 16; i < 240; i++) {
QColor c;
c.setHsv(239 - i, 255 - ((i < 200) ? 0 : (i - 200) * 3), 150 + ((i < 100) ? i : 100));
((quint8*)&m_histogramPalette[i])[0] = c.red();
@ -97,17 +96,16 @@ GLSpectrum::GLSpectrum(QWidget* parent) :
}
for(int i = 1; i < 16; i++) {
QColor c;
c.setHsv(270, 128, 48 + i * 4);
c.setHsv(255, 128, 48 + i * 4);
((quint8*)&m_histogramPalette[i])[0] = c.red();
((quint8*)&m_histogramPalette[i])[1] = c.green();
((quint8*)&m_histogramPalette[i])[2] = c.blue();
((quint8*)&m_histogramPalette[i])[3] = c.alpha();
}
m_histogramHoldoffBase = 4; // was 2
m_histogramHoldoffCount = m_histogramHoldoffBase;
m_histogramLateHoldoff = 20; // was 1
m_histogramStroke = 4;
m_decayDivisor = 1;
m_decayDivisorCount = m_decayDivisor;
m_histogramStroke = 30;
m_timeScale.setFont(font());
m_timeScale.setOrientation(Qt::Vertical);
@ -141,10 +139,6 @@ GLSpectrum::~GLSpectrum()
delete[] m_histogram;
m_histogram = NULL;
}
if(m_histogramHoldoff != NULL) {
delete[] m_histogramHoldoff;
m_histogramHoldoff = NULL;
}
}
void GLSpectrum::setCenterFrequency(qint64 frequency)
@ -173,14 +167,14 @@ void GLSpectrum::setDecay(int decay)
m_decay = decay < 0 ? 0 : decay > 20 ? 20 : decay;
}
void GLSpectrum::setHistoHoldoffBase(int holdoffBase)
void GLSpectrum::setDecayDivisor(int decayDivisor)
{
m_histogramHoldoffBase = holdoffBase < 0 ? 0 : holdoffBase > 240 ? 240 : holdoffBase;
m_decayDivisor = decayDivisor < 1 ? 1 : decayDivisor > 20 ? 20 : decayDivisor;
}
void GLSpectrum::setHistoStroke(int stroke)
{
m_histogramStroke = stroke < 1 ? 1 : stroke > 40 ? 40 : stroke;
m_histogramStroke = stroke < 1 ? 1 : stroke > 60 ? 60 : stroke;
}
void GLSpectrum::setSampleRate(qint32 sampleRate)
@ -358,7 +352,6 @@ void GLSpectrum::updateWaterfall(const std::vector<Real>& spectrum)
void GLSpectrum::updateHistogram(const std::vector<Real>& spectrum)
{
quint8* b = m_histogram;
quint8* h = m_histogramHoldoff;
int sub = 0; // was 1;
int fftMulSize = 100 * m_fftSize;
@ -367,38 +360,22 @@ void GLSpectrum::updateHistogram(const std::vector<Real>& spectrum)
if (m_displayHistogram || m_displayMaxHold)
{
m_histogramHoldoffCount--;
m_decayDivisorCount--;
if (m_histogramHoldoffCount <= 0)
if ((m_decay > 1) || (m_decayDivisorCount <= 0))
{
for (int i = 0; i < fftMulSize; i++)
{
if (*b > 20) // must be more than max value of m_decay
{
*b = *b - sub;
}
else if (*b > 0)
{
if (*h >= sub)
{
*h = *h - sub;
}
else if (*h > 0)
{
*h = *h - 1;
}
else
{
*b = *b - 1;
*h = m_histogramLateHoldoff;
}
if (*b > m_decay) {
*b = *b - m_decay;
} else {
*b = 0;
}
b++;
h++;
}
m_histogramHoldoffCount = m_histogramHoldoffBase;
m_decayDivisorCount = m_decayDivisor;
}
}
@ -534,7 +511,6 @@ void GLSpectrum::clearSpectrumHistogram()
return;
memset(m_histogram, 0x00, 100 * m_fftSize);
memset(m_histogramHoldoff, 0x07, 100 * m_fftSize);
m_mutex.unlock();
update();
@ -1577,10 +1553,6 @@ void GLSpectrum::applyChanges()
delete[] m_histogram;
m_histogram = NULL;
}
if(m_histogramHoldoff != NULL) {
delete[] m_histogramHoldoff;
m_histogramHoldoff = NULL;
}
m_histogramBuffer = new QImage(m_fftSize, 100, QImage::Format_RGB32);
@ -1598,8 +1570,6 @@ void GLSpectrum::applyChanges()
m_histogram = new quint8[100 * m_fftSize];
memset(m_histogram, 0x00, 100 * m_fftSize);
m_histogramHoldoff = new quint8[100 * m_fftSize];
memset(m_histogramHoldoff, 0x07, 100 * m_fftSize);
m_q3FFT.allocate(2*m_fftSize);
}

View File

@ -69,7 +69,7 @@ public:
void setReferenceLevel(Real referenceLevel);
void setPowerRange(Real powerRange);
void setDecay(int decay);
void setHistoHoldoffBase(int holdoffBase);
void setDecayDivisor(int decayDivisor);
void setHistoStroke(int stroke);
void setDisplayWaterfall(bool display);
void setSsbSpectrum(bool ssbSpectrum);
@ -171,11 +171,9 @@ private:
QRgb m_histogramPalette[240];
QImage* m_histogramBuffer;
quint8* m_histogram;
quint8* m_histogramHoldoff;
int m_histogramHoldoffBase;
int m_histogramHoldoffCount;
int m_histogramLateHoldoff;
quint8* m_histogram; //!< Spectrum phosphor matrix of FFT width and PSD height scaled to 100. values [0..239]
int m_decayDivisor;
int m_decayDivisorCount;
int m_histogramStroke;
QMatrix4x4 m_glHistogramSpectrumMatrix;
QMatrix4x4 m_glHistogramBoxMatrix;

View File

@ -16,9 +16,9 @@ GLSpectrumGUI::GLSpectrumGUI(QWidget* parent) :
m_fftWindow(FFTWindow::Hamming),
m_refLevel(0),
m_powerRange(100),
m_decay(0),
m_histogramHoldoffBase(0),
m_histogramStroke(40),
m_decay(1),
m_decayDivisor(1),
m_histogramStroke(30),
m_displayGridIntensity(5),
m_displayTraceIntensity(50),
m_displayWaterfall(true),
@ -66,9 +66,9 @@ void GLSpectrumGUI::resetToDefaults()
m_fftWindow = FFTWindow::Hamming;
m_refLevel = 0;
m_powerRange = 100;
m_decay = 0;
m_histogramHoldoffBase = 0;
m_histogramStroke = 4;
m_decay = 1;
m_decayDivisor = 1;
m_histogramStroke = 30;
m_displayGridIntensity = 5,
m_displayWaterfall = true;
m_invertedWaterfall = false;
@ -98,7 +98,7 @@ QByteArray GLSpectrumGUI::serialize() const
s.writeBool(11, m_displayGrid);
s.writeBool(12, m_invert);
s.writeS32(13, m_displayGridIntensity);
s.writeS32(14, m_histogramHoldoffBase);
s.writeS32(14, m_decayDivisor);
s.writeS32(15, m_histogramStroke);
s.writeBool(16, m_displayCurrent);
s.writeS32(17, m_displayTraceIntensity);
@ -130,12 +130,12 @@ bool GLSpectrumGUI::deserialize(const QByteArray& data)
d.readBool(7, &m_invertedWaterfall, false);
d.readBool(8, &m_displayMaxHold, false);
d.readBool(9, &m_displayHistogram, false);
d.readS32(10, &m_decay, 0);
d.readS32(10, &m_decay, 1);
d.readBool(11, &m_displayGrid, false);
d.readBool(12, &m_invert, true);
d.readS32(13, &m_displayGridIntensity, 5);
d.readS32(14, &m_histogramHoldoffBase, 0);
d.readS32(15, &m_histogramStroke, 4);
d.readS32(14, &m_decayDivisor, 1);
d.readS32(15, &m_histogramStroke, 30);
d.readBool(16, &m_displayCurrent, false);
d.readS32(17, &m_displayTraceIntensity, 50);
Real waterfallShare;
@ -171,7 +171,7 @@ void GLSpectrumGUI::applySettings()
ui->averagingMode->setCurrentIndex((int) m_averagingMode);
ui->linscale->setChecked(m_linear);
ui->decay->setSliderPosition(m_decay);
ui->holdoff->setSliderPosition(m_histogramHoldoffBase);
ui->decayDivisor->setSliderPosition(m_decayDivisor);
ui->stroke->setSliderPosition(m_histogramStroke);
ui->waterfall->setChecked(m_displayWaterfall);
ui->maxHold->setChecked(m_displayMaxHold);
@ -182,7 +182,7 @@ void GLSpectrumGUI::applySettings()
ui->gridIntensity->setSliderPosition(m_displayGridIntensity);
ui->decay->setToolTip(QString("Decay: %1").arg(m_decay));
ui->holdoff->setToolTip(QString("Holdoff: %1").arg(m_histogramHoldoffBase));
ui->decayDivisor->setToolTip(QString("Decay divisor: %1").arg(m_decayDivisor));
ui->stroke->setToolTip(QString("Stroke: %1").arg(m_histogramStroke));
ui->gridIntensity->setToolTip(QString("Grid intensity: %1").arg(m_displayGridIntensity));
ui->traceIntensity->setToolTip(QString("Trace intensity: %1").arg(m_displayTraceIntensity));
@ -193,7 +193,7 @@ void GLSpectrumGUI::applySettings()
m_glSpectrum->setDisplayCurrent(m_displayCurrent);
m_glSpectrum->setDisplayHistogram(m_displayHistogram);
m_glSpectrum->setDecay(m_decay);
m_glSpectrum->setHistoHoldoffBase(m_histogramHoldoffBase);
m_glSpectrum->setDecayDivisor(m_decayDivisor);
m_glSpectrum->setHistoStroke(m_histogramStroke);
m_glSpectrum->setInvertedWaterfall(m_invert);
m_glSpectrum->setDisplayGrid(m_displayGrid);
@ -367,10 +367,10 @@ void GLSpectrumGUI::on_decay_valueChanged(int index)
}
}
void GLSpectrumGUI::on_holdoff_valueChanged(int index)
void GLSpectrumGUI::on_decayDivisor_valueChanged(int index)
{
m_histogramHoldoffBase = index;
//ui->holdoff->setToolTip(QString("Holdoff: %1").arg(m_histogramHoldoffBase));
m_decayDivisor = index;
//ui->decayDivisor->setToolTip(QString("Decay divisor: %1").arg(m_decayDivisor));
if(m_glSpectrum != 0) {
applySettings();
}

View File

@ -49,7 +49,7 @@ private:
Real m_refLevel;
Real m_powerRange;
int m_decay;
int m_histogramHoldoffBase;
int m_decayDivisor;
int m_histogramStroke;
int m_displayGridIntensity;
int m_displayTraceIntensity;
@ -81,7 +81,7 @@ private slots:
void on_refLevel_currentIndexChanged(int index);
void on_levelRange_currentIndexChanged(int index);
void on_decay_valueChanged(int index);
void on_holdoff_valueChanged(int index);
void on_decayDivisor_valueChanged(int index);
void on_stroke_valueChanged(int index);
void on_gridIntensity_valueChanged(int index);
void on_traceIntensity_valueChanged(int index);

View File

@ -60,7 +60,7 @@
</widget>
</item>
<item>
<widget class="QDial" name="holdoff">
<widget class="QDial" name="decayDivisor">
<property name="maximumSize">
<size>
<width>24</width>
@ -68,10 +68,10 @@
</size>
</property>
<property name="toolTip">
<string>Holdoff:</string>
<string>Decay divisor:</string>
</property>
<property name="minimum">
<number>0</number>
<number>1</number>
</property>
<property name="maximum">
<number>20</number>
@ -96,7 +96,7 @@
<number>1</number>
</property>
<property name="maximum">
<number>40</number>
<number>60</number>
</property>
<property name="pageStep">
<number>1</number>

View File

@ -280,11 +280,11 @@ Averaging reduces the noise variance and can be used to better detect weak conti
<h4>4.7. Phosphor display stroke decay</h4>
This controls the decay rate of the stroke when phosphor display is engaged (4.C). A value of zero means no decay and thus phosphor history and max hold (red line) will be kept until the clear button (4.B) is pressed.
This controls the decay rate of the stroke when phosphor display is engaged (4.C). The histogram pixel value is diminished by this value each time a new FFT is produced. A value of zero means no decay and thus phosphor history and max hold (red line) will be kept until the clear button (4.B) is pressed.
<h4>4.8. Phosphor display holdoff</h4>
<h4>4.8. Phosphor display stroke decay divisor</h4>
This controls the holdoff value when phosphor display is engaged (4.C). The holdoff value will drive how much hits are needed before an even appears in the history. Practically you increase this value to trim larger transient signals. A value of 0 means no holdoff and all signals are contributing.
When phosphor display is engaged (4.C) and stroke decay is 1 (4.7) this divides the unit decay by this value by diminishing histogram pixel value by one each time a decay divisor of FFTs have been produced. So actual decay rate is 1 over this value.
<h4>4.9. Phosphor display stroke strength</h4>