20 #include <emmintrin.h> 23 #include <QMouseEvent> 24 #include <QOpenGLShaderProgram> 25 #include <QOpenGLFunctions> 36 m_cursorState(CSNormal),
39 m_changesPending(true),
40 m_centerFrequency(100000000),
49 m_displayGridIntensity(5),
50 m_displayTraceIntensity(50),
51 m_invertedWaterfall(false),
52 m_displayMaxHold(false),
54 m_displayCurrent(false),
57 m_waterfallBufferPos(0),
58 m_waterfallTextureHeight(-1),
59 m_waterfallTexturePos(0),
60 m_displayWaterfall(true),
65 m_displayHistogram(true),
66 m_displayChanged(false),
67 m_displaySourceOrSink(true),
68 m_displayStreamIndex(0),
71 m_messageQueueToGUI(0)
73 setAutoFillBackground(
false);
74 setAttribute(Qt::WA_OpaquePaintEvent,
true);
75 setAttribute(Qt::WA_NoSystemBackground,
true);
76 setMouseTracking(
true);
78 setMinimumSize(200, 200);
80 m_waterfallShare = 0.66;
82 for(
int i = 0;
i <= 239;
i++) {
84 c.setHsv(239 -
i, 255, 15 +
i);
85 ((quint8*)&m_waterfallPalette[
i])[0] = c.red();
86 ((quint8*)&m_waterfallPalette[i])[1] = c.green();
87 ((quint8*)&m_waterfallPalette[i])[2] = c.blue();
88 ((quint8*)&m_waterfallPalette[i])[3] = c.alpha();
90 m_waterfallPalette[239] = 0xffffffff;
92 m_histogramPalette[0] = 0;
94 for (
int i = 1;
i < 240;
i++)
97 int light =
i < 60 ? 128 + (60-
i) : 128;
98 int sat =
i < 60 ? 140 +
i :
i < 180 ? 200 : 200 - (
i-180);
99 c.setHsl(239 -
i, sat, light);
100 ((quint8*)&m_histogramPalette[
i])[0] = c.red();
101 ((quint8*)&m_histogramPalette[i])[1] = c.green();
102 ((quint8*)&m_histogramPalette[i])[2] = c.blue();
103 ((quint8*)&m_histogramPalette[i])[3] = c.alpha();
138 m_decayDivisorCount = m_decayDivisor;
139 m_histogramStroke = 30;
141 m_timeScale.setFont(font());
142 m_timeScale.setOrientation(Qt::Vertical);
144 m_powerScale.setFont(font());
145 m_powerScale.setOrientation(Qt::Vertical);
146 m_frequencyScale.setFont(font());
147 m_frequencyScale.setOrientation(Qt::Horizontal);
149 connect(&m_timer, SIGNAL(timeout()),
this, SLOT(tick()));
157 QMutexLocker mutexLocker(&
m_mutex);
198 m_decay = decay < 0 ? 0 : decay > 20 ? 20 : decay;
203 m_decayDivisor = decayDivisor < 1 ? 1 : decayDivisor > 20 ? 20 : decayDivisor;
317 QMutexLocker mutexLocker(&
m_mutex);
329 QMutexLocker mutexLocker(&
m_mutex);
333 channelMarker->disconnect(
this);
345 QMutexLocker mutexLocker(&
m_mutex);
366 if(m_waterfallBufferPos < m_waterfallBuffer->height()) {
394 for (
int i = 0;
i < fftMulSize;
i++)
415 const __m128 mul = {100.0f, 100.0f, 100.0f, 100.0f};
418 __m128 abc = _mm_loadu_ps (&spectrum[
i]);
419 abc = _mm_sub_ps(abc, refl);
420 abc = _mm_mul_ps(abc, mul);
421 abc = _mm_div_ps(abc, power);
422 abc = _mm_add_ps(abc, mul);
423 __m128i result = _mm_cvtps_epi32(abc);
425 for(
int j = 0; j < 4; j++) {
426 int v = ((
int*)&result)[j];
427 if((v >= 0) && (v <= 99)) {
440 const __m128 mul = {100.0f, 100.0f, 100.0f, 100.0f};
443 __m128 abc = _mm_loadu_ps (&spectrum[
i]);
444 abc = _mm_sub_ps(abc, refl);
445 abc = _mm_mul_ps(abc, mul);
446 abc = _mm_div_ps(abc, power);
447 abc = _mm_add_ps(abc, mul);
448 __m128i result = _mm_cvtps_epi32(abc);
450 for(
int j = 0; j < 4; j++) {
451 int v = ((
int*)&result)[j];
452 if((v >= 1) && (v <= 98)) {
466 }
else if((v >= 0) && (v <= 99)) {
481 if ((v >= 0) && (v <= 99))
498 QOpenGLContext *glCurrentContext = QOpenGLContext::currentContext();
500 if (glCurrentContext) {
501 if (QOpenGLContext::currentContext()->isValid()) {
502 qDebug() <<
"GLSpectrum::initializeGL: context:" 503 <<
" major: " << (QOpenGLContext::currentContext()->format()).majorVersion()
504 <<
" minor: " << (QOpenGLContext::currentContext()->format()).minorVersion()
505 <<
" ES: " << (QOpenGLContext::currentContext()->isOpenGLES() ?
"yes" :
"no");
508 qDebug() <<
"GLSpectrum::initializeGL: current context is invalid";
511 qCritical() <<
"GLSpectrum::initializeGL: no current context";
515 connect(glCurrentContext, &QOpenGLContext::aboutToBeDestroyed,
this, &
GLSpectrum::cleanup);
517 QOpenGLFunctions *glFunctions = QOpenGLContext::currentContext()->functions();
518 glFunctions->initializeOpenGLFunctions();
530 QOpenGLFunctions *glFunctions = QOpenGLContext::currentContext()->functions();
531 glFunctions->glViewport(0, 0, width, height);
559 QOpenGLFunctions *glFunctions = QOpenGLContext::currentContext()->functions();
560 glFunctions->glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
561 glFunctions->glClear(GL_COLOR_BUFFER_BIT);
586 m_waterfallTexturePos = linesLeft;
628 QVector4D colorLine(0.8f, 0.8f, 0.6f, 1.0f);
645 QVector4D color(1.0f, 1.0f, 1.0f, 0.5f);
660 for (
int y = 0; y < 100; y++)
719 QVector4D colorLine(0.8f, 0.8f, 0.6f, 1.0f);
741 QVector4D color(1.0f, 1.0f, 1.0f, 0.5f);
814 QVector4D colorLine(0.8f, 0.8f, 0.6f, 1.0f);
835 for (j = 99; j >= 0; j--)
881 }
else if(v < bottom) {
903 int effectiveTicks = 0;
905 for (
int i= 0;
i < tickList->count();
i++)
907 tick = &(*tickList)[
i];
914 q3[4*effectiveTicks] = 0;
915 q3[4*effectiveTicks+1] = y;
916 q3[4*effectiveTicks+2] = 1;
917 q3[4*effectiveTicks+3] = y;
931 int effectiveTicks = 0;
933 for (
int i= 0;
i < tickList->count();
i++)
935 tick = &(*tickList)[
i];
942 q3[4*effectiveTicks] = x;
943 q3[4*effectiveTicks+1] = 0;
944 q3[4*effectiveTicks+2] = x;
945 q3[4*effectiveTicks+3] = 1;
965 int effectiveTicks = 0;
967 for(
int i= 0;
i < tickList->count();
i++)
969 tick = &(*tickList)[
i];
976 q3[4*effectiveTicks] = 0;
977 q3[4*effectiveTicks+1] = 1-y;
978 q3[4*effectiveTicks+2] = 1;
979 q3[4*effectiveTicks+3] = 1-y;
993 int effectiveTicks = 0;
995 for(
int i= 0;
i < tickList->count();
i++)
997 tick = &(*tickList)[
i];
1004 q3[4*effectiveTicks] = x;
1005 q3[4*effectiveTicks+1] = 0;
1006 q3[4*effectiveTicks+2] = x;
1007 q3[4*effectiveTicks+3] = 1;
1026 setCursor(Qt::ArrowCursor);
1038 QFontMetrics fm(font());
1039 int M = fm.width(
"-");
1041 int topMargin = fm.ascent() * 1.5;
1042 int bottomMargin = fm.ascent() * 1.5;
1044 int waterfallHeight = 0;
1045 int waterfallTop = 0;
1046 int frequencyScaleHeight = fm.height() * 3;
1047 int frequencyScaleTop = 0;
1048 int histogramTop = 0;
1049 int histogramHeight = 20;
1051 int rightMargin = fm.width(
"000");
1058 if(waterfallHeight < 0)
1060 waterfallHeight = 0;
1065 waterfallTop = topMargin;
1066 frequencyScaleTop = waterfallTop + waterfallHeight + 1;
1067 histogramTop = waterfallTop + waterfallHeight + frequencyScaleHeight + 1;
1068 histogramHeight = height() - topMargin - waterfallHeight - frequencyScaleHeight - bottomMargin;
1072 histogramTop = topMargin;
1073 histogramHeight = height() - topMargin - waterfallHeight - frequencyScaleHeight - bottomMargin;
1074 waterfallTop = histogramTop + histogramHeight + frequencyScaleHeight + 1;
1075 frequencyScaleTop = histogramTop + histogramHeight + 1;
1122 1.0f - ((
float)(2*waterfallTop) / (
float) height())
1125 ((
float) 2 * (width() -
m_leftMargin - rightMargin)) / (
float) width(),
1126 (
float) (-2*waterfallHeight) / (
float) height()
1132 1.0f - ((
float)(2*histogramTop) / (
float) height())
1135 ((
float) 2 * (width() -
m_leftMargin - rightMargin)) / (
float) width(),
1136 (
float) (-2*histogramHeight) / (
float) height()
1142 1.0f - ((
float)(2*histogramTop) / (
float) height())
1153 frequencyScaleHeight
1159 1.0f - ((
float) 2*frequencyScaleTop / (
float) height())
1163 (
float) -2*frequencyScaleHeight / (
float) height()
1176 bottomMargin = frequencyScaleHeight;
1177 waterfallTop = topMargin;
1178 waterfallHeight = height() - topMargin - frequencyScaleHeight;
1179 frequencyScaleTop = topMargin + waterfallHeight + 1;
1219 1.0f - ((
float)(2*topMargin) / (
float) height())
1222 ((
float) 2 * (width() -
m_leftMargin - rightMargin)) / (
float) width(),
1223 (
float) (-2*waterfallHeight) / (
float) height()
1230 frequencyScaleHeight
1236 1.0f - ((
float) 2*frequencyScaleTop / (
float) height())
1240 (
float) -2*frequencyScaleHeight / (
float) height()
1253 bottomMargin = frequencyScaleHeight;
1254 frequencyScaleTop = height() - bottomMargin;
1255 histogramTop = topMargin - 1;
1256 waterfallHeight = 0;
1257 histogramHeight = height() - topMargin - frequencyScaleHeight;
1271 1.0f - ((
float)(2*histogramTop) / (
float) height())
1275 ((
float) 2*(height() - topMargin - frequencyScaleHeight) / height()) /
m_powerRange 1281 1.0f - ((
float)(2*histogramTop) / (
float) height())
1284 ((
float) 2 * (width() -
m_leftMargin - rightMargin)) / (
float) width(),
1285 (
float) (-2*(height() - topMargin - frequencyScaleHeight)) / (
float) height()
1292 frequencyScaleHeight
1298 1.0f - ((
float) 2*frequencyScaleTop / (
float) height())
1302 (
float) -2*frequencyScaleHeight / (
float) height()
1315 waterfallHeight = 0;
1323 qreal xc, pw, nw, dsbw;
1349 QMatrix4x4 glMatrixDsb;
1350 glMatrixDsb.setToIdentity();
1351 glMatrixDsb.translate(
1363 (
float) waterfallTop / (
float) height()
1366 (
float) (width() -
m_leftMargin - rightMargin) / (
float) width(),
1367 (
float) waterfallHeight / (
float) height()
1373 (
float) histogramTop / (
float) height()
1376 (
float) (width() -
m_leftMargin - rightMargin) / (
float) width(),
1377 (
float) histogramHeight / (
float) height()
1383 (
float) frequencyScaleTop / (
float) height()
1386 (
float) (width() -
m_leftMargin - rightMargin) / (
float) width(),
1387 (
float) frequencyScaleHeight / (
float) height()
1392 QMatrix4x4 glMatrix;
1393 glMatrix.setToIdentity();
1399 2.0f * ((pw-nw) / (
float)m_sampleRate),
1406 (
float) waterfallTop / (
float) height()
1409 (
float) (width() -
m_leftMargin - rightMargin) / (
float) width(),
1410 (
float) waterfallHeight / (
float) height()
1416 (
float) histogramTop / (
float) height()
1419 (
float) (width() -
m_leftMargin - rightMargin) / (
float) width(),
1420 (
float) histogramHeight / (
float) height()
1426 (
float) frequencyScaleTop / (
float) height()
1429 (
float) (width() -
m_leftMargin - rightMargin) / (
float) width(),
1430 (
float) frequencyScaleHeight / (
float) height()
1447 height() - topMargin - bottomMargin);
1466 painter.setPen(QColor(0xf0, 0xf0, 0xff));
1467 painter.setFont(font());
1472 for(
int i = 0;
i < tickList->count();
i++) {
1473 tick = &(*tickList)[
i];
1482 for(
int i = 0;
i < tickList->count();
i++) {
1483 tick = &(*tickList)[
i];
1500 painter.setPen(Qt::NoPen);
1501 painter.setBrush(Qt::black);
1502 painter.setBrush(Qt::transparent);
1504 painter.setPen(QColor(0xf0, 0xf0, 0xff));
1505 painter.setFont(font());
1508 for(
int i = 0;
i < tickList->count();
i++) {
1509 tick = &(*tickList)[
i];
1548 ftext =
" " + ftext;
1551 ftext = ftext +
" ";
1552 shift = - fm.width(ftext);
1563 bool fftSizeChanged =
true;
1571 if (fftSizeChanged || windowSizeChanged)
1606 if(fftSizeChanged || windowSizeChanged)
1625 setCursor(Qt::SizeVerCursor);
1634 setCursor(Qt::ArrowCursor);
1651 if (newShare < 0.1) {
1653 }
else if (newShare > 0.8) {
1690 setCursor(Qt::SizeHorCursor);
1713 setCursor(Qt::ArrowCursor);
1722 if(event->button() != 1)
1740 setCursor(Qt::SizeHorCursor);
1772 if (event->modifiers() & Qt::ShiftModifier) {
1774 }
else if (event->modifiers() & Qt::ControlModifier) {
1792 if (event->delta() > 0) {
1794 }
else if (event->delta() < 0) {
1808 QCursor c = cursor();
1809 QPoint cp_a = c.pos();
1810 QPoint cp_w = mapFromGlobal(cp_a);
1812 cp_a = mapToGlobal(cp_w);
1824 QGLWidget::enterEvent(event);
1831 QGLWidget::enterEvent(event);
1855 if (waterfallShare < 0.1f) {
1858 else if (waterfallShare > 0.8f) {
1868 qDebug() <<
"GLSpectrum::connectTimer";
1869 disconnect(&
m_timer, SIGNAL(timeout()),
this, SLOT(
tick()));
1870 connect(&timer, SIGNAL(timeout()),
this, SLOT(
tick()));
void setLsbDisplay(bool lsbDisplay)
void mouseMoveEvent(QMouseEvent *event)
void leaveEvent(QEvent *event)
int getOppositeBandwidth() const
void connectTimer(const QTimer &timer)
int getStreamIndex() const
int getCenterFrequency() const
void setDisplayGrid(bool display)
void setTimingRate(qint32 timingRate)
void push(Message *message, bool emitSignal=true)
Push message onto queue.
void setSampleRate(qint32 sampleRate)
sidebands_t getSidebands() const
int m_displayTraceIntensity
void setDisplayTraceIntensity(int intensity)
void setPowerRange(Real powerRange)
QMatrix4x4 m_glFrequencyScaleBoxMatrix
frequencyScaleDisplay_t getFrequencyScaleDisplayType() const
QMatrix4x4 m_glHistogramBoxMatrix
void drawSegments(const QMatrix4x4 &transformMatrix, const QVector4D &color, GLfloat *vertices, int nbVertices)
QList< ChannelMarkerState * > m_channelMarkerStates
QRgb m_histogramPalette[240]
QMatrix4x4 m_glMatrixWaterfall
const QString & getDisplayAddressSend() const
const QString & getDisplayAddressReceive() const
IncrementalArray< GLfloat > m_q3TickFrequency
std::vector< Real > m_maxHold
bool getSourceOrSinkStream() const
void channelMarkerChanged()
float getPosFromValue(double value)
ScaleEngine m_frequencyScale
void setReferenceLevel(Real referenceLevel)
CursorState m_cursorState
void initTexture(const QImage &image, QOpenGLTexture::WrapMode wrapMode=QOpenGLTexture::Repeat)
void setDisplayHistogram(bool display)
void mouseReleaseEvent(QMouseEvent *event)
void setDecayDivisor(int decayDivisor)
float getValueFromPos(double pos)
void updateWaterfall(const std::vector< Real > &spectrum)
QMatrix4x4 m_glWaterfallBoxMatrix
QMatrix4x4 m_glLeftScaleBoxMatrix
QRect m_frequencyScaleRect
void setDisplayCurrent(bool display)
IncrementalArray< GLfloat > m_q3TickTime
QPixmap m_leftMarginPixmap
#define MESSAGE_CLASS_DEFINITION(Name, BaseClass)
int m_waterfallTextureHeight
void drawSurface(const QMatrix4x4 &transformMatrix, const QVector4D &color, GLfloat *vertices, int nbVertices)
void drawSurface(const QMatrix4x4 &transformMatrix, GLfloat *textureCoords, GLfloat *vertices, int nbVertices)
void wheelEvent(QWheelEvent *)
bool m_displaySourceOrSink
void subTexture(int xOffset, int yOffset, int width, int height, const void *pixels)
QPixmap m_frequencyPixmap
GLShaderTextured m_glShaderFrequencyScale
GLShaderTextured m_glShaderWaterfall
QMatrix4x4 m_glMatrixDsbWaterfall
QMatrix4x4 m_glMatrixFreqScale
const std::vector< Real > * m_currentSpectrum
QImage * m_waterfallBuffer
void drawContour(const QMatrix4x4 &transformMatrix, const QVector4D &color, GLfloat *vertices, int nbVertices)
const QString & getTitle() const
void setInvertedWaterfall(bool inv)
QRgb m_waterfallPalette[240]
enum ChannelMarker::sidebands_e sidebands_t
bool getHighlighted() const
void addChannelMarker(ChannelMarker *channelMarker)
void newSpectrum(const std::vector< Real > &spectrum, int fftSize)
void setHistoStroke(int stroke)
int m_displayGridIntensity
QMatrix4x4 m_glMatrixDsbHistogram
int m_waterfallTexturePos
void updateHistogram(const std::vector< Real > &spectrum)
quint8 * m_histogram
Spectrum phosphor matrix of FFT width and PSD height scaled to 100. values [0..239].
QMatrix4x4 m_glHistogramSpectrumMatrix
void allocate(uint32_t size)
void setSsbSpectrum(bool ssbSpectrum)
void channelMarkerDestroyed(QObject *object)
const TickList & getTickList()
IncrementalArray< GLfloat > m_q3FFT
MessageQueue * m_messageQueueToGUI
void mousePressEvent(QMouseEvent *event)
void setLinear(bool linear)
void removeChannelMarker(ChannelMarker *channelMarker)
void setRange(Unit::Physical physicalUnit, float rangeMin, float rangeMax)
void drawPolyline(const QMatrix4x4 &transformMatrix, const QVector4D &color, GLfloat *vertices, int nbVertices)
void setCenterFrequency(qint64 frequency)
GLShaderTextured m_glShaderLeftScale
const QColor & getColor() const
void resizeGL(int width, int height)
QImage * m_histogramBuffer
void setDisplayGridIntensity(int intensity)
void setWaterfallShare(Real waterfallShare)
GLShaderTextured m_glShaderHistogram
QMatrix4x4 m_glMatrixHistogram
void setMakeOpposite(bool makeOpposite)
GLShaderSimple m_glShaderSimple
void clearSpectrumHistogram()
void setDisplayMaxHold(bool display)
QMatrix4x4 m_glMatrixDsbFreqScale
ChannelMarker * m_channelMarker
void enterEvent(QEvent *event)
void setDisplayWaterfall(bool display)
IncrementalArray< GLfloat > m_q3TickPower