From 5fb03c15b10db4990648d5f255a204bc0d3eed8a Mon Sep 17 00:00:00 2001 From: n1gp Date: Sun, 5 Apr 2015 17:29:31 -0400 Subject: [PATCH] Removed ADC Overload message and temporalily changed Wideband scope to 30.72 max frequency. --- Source/src/GL/cusdr_oglReceiverPanel.cpp | 2 + Source/src/GL/cusdr_oglReceiverPanel.cpp~ | 4486 +++++++++++++++++++++ Source/src/cusdr_settings.h | 3 +- Source/src/cusdr_settings.h~ | 1586 ++++++++ bak/README.md | 7 + 5 files changed, 6083 insertions(+), 1 deletion(-) create mode 100644 Source/src/GL/cusdr_oglReceiverPanel.cpp~ create mode 100644 Source/src/cusdr_settings.h~ create mode 100644 bak/README.md diff --git a/Source/src/GL/cusdr_oglReceiverPanel.cpp b/Source/src/GL/cusdr_oglReceiverPanel.cpp index be79f11..46d60bb 100644 --- a/Source/src/GL/cusdr_oglReceiverPanel.cpp +++ b/Source/src/GL/cusdr_oglReceiverPanel.cpp @@ -760,6 +760,7 @@ void QGLReceiverPanel::drawPanadapter() { glEnd(); } +#if 0 // remove big red overload indicator if (m_adcStatus == 2) { glBegin(GL_TRIANGLE_STRIP); @@ -775,6 +776,7 @@ void QGLReceiverPanel::drawPanadapter() { qglColor(QColor(255, 0, 0, 155)); m_oglTextHuge->renderText((x2-rectWidth)/2, y1+30, -3.5f, str); } +#endif } else { diff --git a/Source/src/GL/cusdr_oglReceiverPanel.cpp~ b/Source/src/GL/cusdr_oglReceiverPanel.cpp~ new file mode 100644 index 0000000..be79f11 --- /dev/null +++ b/Source/src/GL/cusdr_oglReceiverPanel.cpp~ @@ -0,0 +1,4486 @@ +/** +* @file cusdr_oglReceiverPanel.cpp +* @brief Receiver panel class for cuSDR +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2011-03-14 +*/ + +/* + * Copyright 2011 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#define LOG_GRAPHICS + +// use: GRAPHICS_DEBUG + +#include "cusdr_oglReceiverPanel.h" + +//#include +//#include +//#include +//#include +//#include +//#include +//#include + +#ifndef GL_MULTISAMPLE +#define GL_MULTISAMPLE 0x809D +#endif + +#define btn_height 14 +#define btn_width 60 +#define btn_widthb 70 +#define btn_widths 34 + +QGLReceiverPanel::QGLReceiverPanel(QWidget *parent, int rx) + : QGLWidget(QGLFormat(QGL::SampleBuffers|QGL::AlphaChannel), parent) + + , set(Settings::instance()) + , m_serverMode(set->getCurrentServerMode()) + , m_hwInterface(set->getHWInterface()) + , m_dataEngineState(QSDR::DataEngineDown) + , m_mousePos(QPoint(-1, -1)) + , m_mouseDownPos(QPoint(-1, -1)) + , m_panSpectrumBinsLength(0) + , m_filterLeft(0) + , m_filterRight(0) + , m_filterTop(0) + , m_filterBottom(0) + , m_receiver(rx) + //, m_frequencyRxOnRx(0) + , m_spectrumSize(set->getSpectrumSize()) + , m_sampleSize(0) + , m_oldSampleSize(0) + , m_specAveragingCnt(set->getSpectrumAveragingCnt(m_receiver)) + , m_currentReceiver(set->getCurrentReceiver()) + , m_waterfallAlpha(255) + , m_freqRulerDisplayWidth(0) + , m_oldWaterfallWidth(0) + , m_panSpectrumMinimumHeight(0) + , m_snapMouse(3) + , m_sampleRate(set->getSampleRate()) + , m_downRate(set->getChirpDownSampleRate()) + , m_adcStatus(0) + , m_fftMult(1) + , m_smallSize(true) + , m_spectrumVertexColorUpdate(false) + , m_spectrumColorsChanged(true) + , m_spectrumAveraging(set->getSpectrumAveraging(m_receiver)) + //, m_spectrumAveragingOld(m_spectrumAveraging) + , m_crossHair(set->getHairCrossStatus(m_receiver)) + , m_crossHairCursor(false) + , m_panGrid(set->getPanGridStatus(m_receiver)) + , m_peakHold(false) + , m_filterChanged(true) + , m_showFilterLeftBoundary(false) + , m_showFilterRightBoundary(false) + , m_highlightFilter(false) + , m_peakHoldBufferResize(true) + , m_dragMouse(false) + , m_panLocked(set->getPanLockedStatus(m_receiver)) + , m_clickVFO(set->getClickVFOStatus(m_receiver)) + , m_freqScaleZoomFactor(1.0f) + , m_scaleMult(1.0f) + , m_filterLowerFrequency(-3050.0) + , m_filterUpperFrequency(-150.0) + //, m_freqRulerPosition(0.5) +{ +// QGL::setPreferredPaintEngine(QPaintEngine::OpenGL); + + setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + + setAutoBufferSwap(true); + setAutoFillBackground(false); + + setMouseTracking(true); + setFocusPolicy(Qt::StrongFocus); + + //GRAPHICS_DEBUG << "set spectrum buffer size to: " << m_spectrumSize; + + m_bigHeight = 600; + m_bigWidth = 1000; + + setupDisplayRegions(size()); + m_oldWidth = size().width(); + + m_rxDataList = set->getReceiverDataList(); + m_freqRulerPosition = m_rxDataList.at(m_receiver).freqRulerPosition; + m_centerFrequency = m_rxDataList.at(m_receiver).ctrFrequency; + m_vfoFrequency = m_rxDataList.at(m_receiver).vfoFrequency; + + if (m_vfoFrequency > m_centerFrequency + m_sampleRate/2) + m_vfoFrequency = m_centerFrequency + m_sampleRate/2; + else if (m_vfoFrequency < m_centerFrequency - m_sampleRate/2) + m_vfoFrequency = m_centerFrequency - m_sampleRate/2; + else + + m_deltaFrequency = m_centerFrequency - m_vfoFrequency; + m_deltaF = (qreal)(1.0*m_deltaFrequency/m_sampleRate); + + m_dBmScalePanadapterRenew = true; + m_dBmScalePanadapterUpdate = true; + m_freqScalePanadapterRenew = true; + m_freqScalePanadapterUpdate = true; + m_panGridRenew = true; + m_panGridUpdate = true; + m_waterfallUpdate = true; + m_secScaleWaterfallUpdate = true; + m_secScaleWaterfallRenew = true; + m_waterfallDisplayUpdate = true; + + m_panMode = m_rxDataList.at(m_receiver).panMode; + m_waterfallMode = m_rxDataList.at(m_receiver).waterfallMode; + + HamBand band = m_rxDataList.at(m_receiver).hamBand; + + m_dBmPanMin = m_rxDataList.at(m_receiver).dBmPanScaleMinList.at(band); + m_dBmPanMax = m_rxDataList.at(m_receiver).dBmPanScaleMaxList.at(band); + + m_waterfallOffsetLo = m_rxDataList.at(m_receiver).waterfallOffsetLo; + m_waterfallOffsetHi = m_rxDataList.at(m_receiver).waterfallOffsetHi; + + m_secWaterfallMin = 0.0; + m_secWaterfallMax = 0.0; + + m_filterLowerFrequency = m_rxDataList.at(m_receiver).filterLo; + m_filterUpperFrequency = m_rxDataList.at(m_receiver).filterHi; + m_filterWidth = qAbs((int)(m_filterUpperFrequency - m_filterLowerFrequency)); + + m_mouseWheelFreqStep = m_rxDataList.at(m_receiver).mouseWheelFreqStep; + + m_agcMode = m_rxDataList.at(m_receiver).agcMode; + m_agcModeString = set->getAGCModeString(m_receiver); + m_agcFixedGain = m_rxDataList.at(m_receiver).agcFixedGain_dB; + + m_dspModeString = set->getDSPModeString(m_rxDataList.at(m_receiver).dspModeList.at(m_receiver)); +// m_agcThresholdOld = m_rxDataList.at(m_receiver).acgThreshold; +// m_agcThresholdNew = m_agcThresholdOld; +// m_agcHangLevelOld = m_rxDataList.at(m_receiver).agcHangLevel; +// m_agcHangLevelNew = m_agcHangLevelOld; + + m_agcHangEnabled = m_rxDataList.at(m_receiver).hangEnabled; + m_showAGCLines = m_rxDataList.at(m_receiver).agcLines; + + averager = new DualModeAverager(m_receiver, m_spectrumSize); + radioPopup = new RadioPopupWidget(this, m_receiver); + + fonts = new CFonts(this); + m_fonts = fonts->getFonts(); + + m_fonts.smallFont.setBold(true); + m_fonts.bigFont1.setBold(false); + m_fonts.bigFont2.setBold(false); + + m_oglTextTiny = new OGLText(m_fonts.tinyFont); + m_oglTextSmall = new OGLText(m_fonts.smallFont); + m_oglTextNormal = new OGLText(m_fonts.normalFont); + m_oglTextFreq1 = new OGLText(m_fonts.freqFont1); + m_oglTextFreq2 = new OGLText(m_fonts.freqFont2); + m_oglTextBig1 = new OGLText(m_fonts.bigFont1); + m_oglTextBig2 = new OGLText(m_fonts.bigFont2); + m_oglTextHuge = new OGLText(m_fonts.hugeFont); + + timer = 0; + + setupConnections(); + + m_displayTime.start(); + m_resizeTime.start(); + peakHoldTimer.start(); + //freqChangeTimer.start(); + + m_fps = set->getFramesPerSecond(m_receiver); + m_secWaterfallMin = -(1.0/m_fps) * m_secScaleWaterfallRect.height(); + + + m_dBmPanLogGain = 47;//49;//69 // allow user to calibrate this value + + m_cameraDistance = 0; + m_cameraAngle = QPoint(0, 0); + + m_mousePos = QPoint(-100, -100); + + m_gridColor = set->getPanadapterColors().gridLineColor; + m_darkColor = QColor(150, 150, 150, 100); + + m_redGrid = (GLfloat)(m_gridColor.red()/256.0); + m_greenGrid = (GLfloat)(m_gridColor.green()/256.0); + m_blueGrid = (GLfloat)(m_gridColor.blue()/256.0); + + m_bkgRed = (GLfloat)(set->getPanadapterColors().panBackgroundColor.red() / 256.0); + m_bkgGreen = (GLfloat)(set->getPanadapterColors().panBackgroundColor.green() / 256.0); + m_bkgBlue = (GLfloat)(set->getPanadapterColors().panBackgroundColor.blue() / 256.0); + + m_red = (GLfloat)(set->getPanadapterColors().panLineColor.red() / 256.0); + m_green = (GLfloat)(set->getPanadapterColors().panLineColor.green() / 256.0); + m_blue = (GLfloat)(set->getPanadapterColors().panLineColor.blue() / 256.0); + + m_redF = (GLfloat)(set->getPanadapterColors().panLineFilledColor.red() / 256.0); + m_greenF = (GLfloat)(set->getPanadapterColors().panLineFilledColor.green() / 256.0); + m_blueF = (GLfloat)(set->getPanadapterColors().panLineFilledColor.blue() / 256.0); + + m_redST = (GLfloat)(set->getPanadapterColors().panSolidTopColor.red() / 256.0); + m_greenST = (GLfloat)(set->getPanadapterColors().panSolidTopColor.green() / 256.0); + m_blueST = (GLfloat)(set->getPanadapterColors().panSolidTopColor.blue() / 256.0); + + m_redSB = (GLfloat)(set->getPanadapterColors().panSolidBottomColor.red() / 256.0); + m_greenSB = (GLfloat)(set->getPanadapterColors().panSolidBottomColor.green() / 256.0); + m_blueSB = (GLfloat)(set->getPanadapterColors().panSolidBottomColor.blue() / 256.0); + + m_waterfallLoColor = QColor(0, 0, 0, m_waterfallAlpha); + m_waterfallHiColor = QColor(192, 124, 255, m_waterfallAlpha); + m_waterfallMidColor = set->getPanadapterColors().waterfallColor.toRgb(); + m_waterfallColorRange = (int)(m_dBmPanMax - m_dBmPanMin); + + m_frequencyScaleFBO = 0; + m_dBmScaleFBO = 0; + m_panadapterGridFBO = 0; + m_textureFBO = 0; + m_waterfallLineFBO = 0; + m_waterfallFBO = 0; + m_secScaleWaterfallFBO = 0; + + m_waterfallLineCnt = 0; + + m_haircrossOffsetRight = 30; + m_haircrossOffsetLeft = 116; + m_haircrossMaxRight = 110; + m_haircrossMinTop = 40; + + if (m_specAveragingCnt > 0) + m_scale = 1.0f / m_specAveragingCnt; + else + m_scale = 1.0f; + +} + +QGLReceiverPanel::~QGLReceiverPanel() { + + disconnect(set, 0, this, 0); + + makeCurrent(); + glFinish(); + + if (m_frequencyScaleFBO) { + + delete m_frequencyScaleFBO; + m_frequencyScaleFBO = 0; + } + + if (m_waterfallLineFBO) { + + delete m_waterfallLineFBO; + m_waterfallLineFBO = 0; + } + + if (m_waterfallFBO) { + + delete m_waterfallFBO; + m_waterfallFBO = 0; + } + + if (m_textureFBO) { + + delete m_textureFBO; + m_textureFBO = 0; + } + + if (m_dBmScaleFBO) { + + delete m_dBmScaleFBO; + m_dBmScaleFBO = 0; + } + + if (m_panadapterGridFBO) { + + delete m_panadapterGridFBO; + m_panadapterGridFBO = 0; + } + + if (m_secScaleWaterfallFBO) { + + delete m_secScaleWaterfallFBO; + m_secScaleWaterfallFBO = 0; + } + + if (averager) + delete averager; + + while (!specAv_queue.isEmpty()) + specAv_queue.dequeue(); +} + +QSize QGLReceiverPanel::minimumSizeHint() const { + + if (m_receiver == 0) + return QSize(width(), 250); + else + return QSize(250, 120); + //return QSize(width(), height()); +} + +QSize QGLReceiverPanel::sizeHint() const { + + return QSize(width(), height()); +} + +void QGLReceiverPanel::setupConnections() { + + CHECKED_CONNECT( + set, + SIGNAL(systemStateChanged( + QObject *, + QSDR::_Error, + QSDR::_HWInterfaceMode, + QSDR::_ServerMode, + QSDR::_DataEngineState)), + this, + SLOT(systemStateChanged( + QObject *, + QSDR::_Error, + QSDR::_HWInterfaceMode, + QSDR::_ServerMode, + QSDR::_DataEngineState))); + + CHECKED_CONNECT( + set, + SIGNAL(graphicModeChanged( + QObject *, + int, + PanGraphicsMode, + WaterfallColorMode)), + this, + SLOT(graphicModeChanged( + QObject *, + int, + PanGraphicsMode, + WaterfallColorMode))); + +// CHECKED_CONNECT( +// set, +// SIGNAL(spectrumSizeChanged(QObject *, int)), +// this, +// SLOT(setSpectrumSize(QObject *, int))); + + CHECKED_CONNECT( + set, + SIGNAL(freqRulerPositionChanged(QObject *, int, float)), + this, + SLOT(freqRulerPositionChanged(QObject *, int, float))); + + CHECKED_CONNECT( + set, + SIGNAL(ctrFrequencyChanged(QObject *, int, int, long)), + this, + SLOT(setCtrFrequency(QObject *, int, int, long))); + + CHECKED_CONNECT( + set, + SIGNAL(vfoFrequencyChanged(QObject *, int, int, long)), + this, + SLOT(setVFOFrequency(QObject *, int, int, long))); + + CHECKED_CONNECT( + set, + SIGNAL(hamBandChanged(QObject *, int, bool, HamBand)), + this, + SLOT(setHamBand(QObject *, int, bool, HamBand))); + + CHECKED_CONNECT( + set, + SIGNAL(currentReceiverChanged(QObject *, int)), + this, + SLOT(setCurrentReceiver(QObject *, int))); + + CHECKED_CONNECT( + set, + SIGNAL(sampleRateChanged(QObject *, int)), + this, + SLOT(sampleRateChanged(QObject *, int))); + + CHECKED_CONNECT( + set, + SIGNAL(filterFrequenciesChanged(QObject *, int, qreal, qreal)), + this, + SLOT(setFilterFrequencies(QObject *, int, qreal, qreal))); + +// CHECKED_CONNECT( +// set, +// SIGNAL(waterfallTimeChanged(int, int)), +// this, +// SLOT(setWaterfallTime(int, int))); + + CHECKED_CONNECT( + set, + SIGNAL(waterfallOffesetLoChanged(int, int)), + this, + SLOT(setWaterfallOffesetLo(int, int))); + + CHECKED_CONNECT( + set, + SIGNAL(waterfallOffesetHiChanged(int, int)), + this, + SLOT(setWaterfallOffesetHi(int, int))); + + CHECKED_CONNECT( + set, + SIGNAL(spectrumAveragingChanged(QObject *, int, bool)), + this, + SLOT(setSpectrumAveraging(QObject *, int, bool))); + + /*CHECKED_CONNECT( + set, + SIGNAL(spectrumAveragingCntChanged(int)), + this, + SLOT(setSpectrumAveragingCnt(int)));*/ + + CHECKED_CONNECT( + set, + SIGNAL(spectrumBufferChanged(int, const qVectorFloat&)), + this, + SLOT(setSpectrumBuffer(int, const qVectorFloat&))); + + CHECKED_CONNECT( + set, + SIGNAL(panGridStatusChanged(bool, int)), + this, + SLOT(setPanGridStatus(bool, int))); + + CHECKED_CONNECT( + set, + SIGNAL(peakHoldStatusChanged(bool, int)), + this, + SLOT(setPeakHoldStatus(bool, int))); + + CHECKED_CONNECT( + set, + SIGNAL(panLockedStatusChanged(bool, int)), + this, + SLOT(setPanLockedStatus(bool, int))); + + CHECKED_CONNECT( + set, + SIGNAL(clickVFOStatusChanged(bool, int)), + this, + SLOT(setClickVFOStatus(bool, int))); + + CHECKED_CONNECT( + set, + SIGNAL(hairCrossStatusChanged(bool, int)), + this, + SLOT(setHairCrossStatus(bool, int))); + + /*CHECKED_CONNECT( + set, + SIGNAL(panadapterColorChanged()), + this, + SLOT(setSimpleWaterfallColor()));*/ + + CHECKED_CONNECT( + set, + SIGNAL(panadapterColorChanged()), + this, + SLOT(setPanadapterColors())); + + CHECKED_CONNECT( + set, + SIGNAL(mercuryAttenuatorChanged(QObject *, HamBand, int)), + this, + SLOT(setMercuryAttenuator(QObject *, HamBand, int))); + + CHECKED_CONNECT( + set, + SIGNAL(adcOverflowChanged(int)), + this, + SLOT(setADCStatus(int))); + + CHECKED_CONNECT( + set, + SIGNAL(framesPerSecondChanged(QObject*, int, int)), + this, + SLOT(setFramesPerSecond(QObject*, int, int))); + +// CHECKED_CONNECT( +// set, +// SIGNAL(agcThresholdLine_dBmChanged(QObject *, int, qreal)), +// this, +// SLOT(setAGCThresholdLine_dBm(QObject *, int, qreal))); + + CHECKED_CONNECT( + set, + SIGNAL(agcFixedGainChanged_dB(QObject *, int, qreal)), + this, + SLOT(setAGCLineFixedLevel(QObject *, int, qreal))); + + CHECKED_CONNECT( + set, + SIGNAL(agcLineLevelsChanged(QObject *, int, qreal, qreal)), + this, + SLOT(setAGCLineLevels(QObject *, int, qreal, qreal))); + + CHECKED_CONNECT( + set, + SIGNAL(agcModeChanged(QObject *, int, AGCMode, bool)), + this, + SLOT(setAGCMode(QObject *, int, AGCMode, bool))); + + CHECKED_CONNECT( + set, + SIGNAL(showAGCLinesStatusChanged(QObject *, bool, int)), + this, + SLOT(setAGCLinesStatus(QObject *, bool, int))); + + CHECKED_CONNECT( + set, + SIGNAL(dspModeChanged(QObject *, int, DSPMode)), + this, + SLOT(setDSPMode(QObject *, int, DSPMode))); + +// CHECKED_CONNECT( +// set, +// SIGNAL(agcHangEnabledChanged(QObject *, int, bool)), +// this, +// SLOT(setAGCHangEnabled(QObject *, int, bool))); + + CHECKED_CONNECT( + set, + SIGNAL(mouseWheelFreqStepChanged(QObject *, int, qreal)), + this, + SLOT(setMouseWheelFreqStep(QObject *, int, qreal))); + + CHECKED_CONNECT( + radioPopup, + SIGNAL(vfoToMidBtnEvent()), + this, + SLOT(setVfoToMidFrequency())); + + CHECKED_CONNECT( + radioPopup, + SIGNAL(midToVfoBtnEvent()), + this, + SLOT(setMidToVfoFrequency())); +} + +void QGLReceiverPanel::initializeGL() { + + if (!isValid()) return; + + + /*QOpenGLInfo glInfo; + glInfo.getInfo(); + glInfo.printSelf();*/ + + //***************************************************************** + // default initialization + + //glShadeModel(GL_FLAT); + glShadeModel(GL_SMOOTH); + //glClearColor(0.0f, 0.0f, 0.0f, 0.5f); + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + glPixelStorei(GL_UNPACK_ALIGNMENT, 4); // 4-byte pixel alignment + //glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); + //glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST); + + glDepthFunc(GL_LESS); + glEnable(GL_DEPTH_TEST); + glDisable(GL_CULL_FACE); + + m_cnt = 0; + + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); +} + +void QGLReceiverPanel::paintGL() { + + switch (m_serverMode) { + + case QSDR::ChirpWSPR: + case QSDR::ChirpWSPRFile: + case QSDR::NoServerMode: + case QSDR::DemoMode: + + drawGLRect(QRect(0, 0, width(), height()), QColor(0, 0, 0)); + break; + + case QSDR::SDRMode: + + //if (freqChangeTimer.elapsed() > 50) m_spectrumAveraging = m_spectrumAveragingOld; + + if (m_resizeTime.elapsed() > 200 || m_dataEngineState == QSDR::DataEngineDown) + paintReceiverDisplay(); + + break; + } +} + +void QGLReceiverPanel::paintReceiverDisplay() { + + QRect mouse_rect(0, 0, 100, 100); + mouse_rect.moveCenter(m_mousePos); + + if (m_filterChanged) { + + m_filterLo = m_filterLowerFrequency / m_sampleRate; + m_filterHi = m_filterUpperFrequency / m_sampleRate; + m_filterWidth = qAbs((int)(m_filterUpperFrequency - m_filterLowerFrequency)); + + if (m_filterWidth < 1000) { + + QString str = "%1"; + m_filterWidthString = str.arg(m_filterWidth); + } + else { + + QString str = "%1k%2"; + m_filterWidthString = str.arg((int)(m_filterWidth/1000)).arg((int)((m_filterWidth%1000)/100)); + } + + m_filterChanged = false; + } + //m_displayTime.restart(); + + drawPanadapter(); + drawPanHorizontalScale(); + drawPanVerticalScale(); + drawPanadapterGrid(); + drawCenterLine(); + drawPanFilter(); + + if (m_dataEngineState == QSDR::DataEngineUp && m_showAGCLines && (m_receiver == m_currentReceiver)) + drawAGCControl(); + + if (m_panRect.width() > 300 && m_panRect.height() > 80) { + + drawVFOControl(); + drawReceiverInfo(); + } + + if (m_waterfallDisplayUpdate && m_waterfallRect.height() > 10) { + + drawWaterfall(); + drawWaterfallVerticalScale(); + m_waterfallDisplayUpdate = false; + } + + if (m_crossHair) { + + if (m_mouseRegion != freqScalePanadapterRegion && + m_mouseRegion != dBmScalePanadapterRegion && + m_mouseRegion != filterRegion && + m_mouseRegion != filterRegionLow && + m_mouseRegion != filterRegionHigh && + m_mouseRegion != agcThresholdLine && + m_mouseRegion != agcHangLine && + m_mouseRegion != agcFixedGainLine && + m_crossHairCursor) + drawCrossHair(); + } + } + +void QGLReceiverPanel::paint3DPanadapterMode() { +} + +void QGLReceiverPanel::drawPanadapter() { + + GLint vertexArrayLength = (GLint)m_panadapterBins.size(); + + GLint height = m_panRect.height(); + GLint x1 = m_panRect.left(); + GLint y1 = m_panRect.top(); + //GLint y3 = y1 - m_displayTop; + GLint x2 = x1 + m_panRect.width(); + GLint y2 = y1 + m_panRect.height(); + + // y scale + float yScale; + //float yScaleColor; + float yTop; + + qreal dBmRange = qAbs(m_dBmPanMax - m_dBmPanMin); + + yScale = m_panRect.height() / dBmRange; + //yScaleColor = 1.0f / dBmRange; + //yScaleColor = 0.05f * yScale; + yTop = (float) y2; + + if (m_dataEngineState == QSDR::DataEngineUp) + glClear(GL_DEPTH_BUFFER_BIT); + else + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glEnable(GL_MULTISAMPLE); + glEnable(GL_LINE_SMOOTH); + + //glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND); + + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); + glLineWidth(1); + + // draw background + if (m_dataEngineState == QSDR::DataEngineUp) { + + if (m_receiver == m_currentReceiver) { + +// glBegin(GL_TRIANGLE_STRIP); +// glColor3f(0.2f * m_bkgRed, 0.2f * m_bkgGreen, 0.2f * m_bkgBlue); glVertex3f(x1, y1, -4.0); // top left corner +// glColor3f(0.2f * m_bkgRed, 0.2f * m_bkgGreen, 0.2f * m_bkgBlue); glVertex3f(x2, y1, -4.0); // top right corner +// glColor3f(0.8f * m_bkgRed, 0.8f * m_bkgGreen, 0.8f * m_bkgBlue); glVertex3f(x1, y2, -4.0); // bottom left corner +// glColor3f( m_bkgRed, m_bkgGreen, m_bkgBlue); glVertex3f(x2, y2, -4.0); // bottom right corner +// glEnd(); + glBegin(GL_TRIANGLE_STRIP); + glColor3f(0.8f * m_bkgRed, 0.8f * m_bkgGreen, 0.8f * m_bkgBlue); glVertex3f(x1, y1, -4.0); // top left corner + glColor3f(0.6f * m_bkgRed, 0.6f * m_bkgGreen, 0.6f * m_bkgBlue); glVertex3f(x2, y1, -4.0); // top right corner + glColor3f(0.4f * m_bkgRed, 0.4f * m_bkgGreen, 0.4f * m_bkgBlue); glVertex3f(x1, y2, -4.0); // bottom left corner + glColor3f(0.2f * m_bkgRed, 0.2f * m_bkgGreen, 0.2f * m_bkgBlue); glVertex3f(x2, y2, -4.0); // bottom right corner + glEnd(); + } + else { + + glBegin(GL_TRIANGLE_STRIP); + glColor3f(0.4f * m_bkgRed, 0.4f * m_bkgGreen, 0.4f * m_bkgBlue); glVertex3f(x1, y1, -4.0); // top left corner + glColor3f(0.4f * m_bkgRed, 0.4f * m_bkgGreen, 0.4f * m_bkgBlue); glVertex3f(x2, y1, -4.0); // top right corner + glColor3f(0.4f * m_bkgRed, 0.4f * m_bkgGreen, 0.4f * m_bkgBlue); glVertex3f(x1, y2, -4.0); // bottom left corner + glColor3f(0.4f * m_bkgRed, 0.4f * m_bkgGreen, 0.4f * m_bkgBlue); glVertex3f(x2, y2, -4.0); // bottom right corner + glEnd(); + } + + if (m_adcStatus == 2) { + + glBegin(GL_TRIANGLE_STRIP); + glColor3f(m_bkgRed, 0.2f * m_bkgGreen, 0.2f * m_bkgBlue); glVertex3f(x1, y1, -4.0); // top left corner + glColor3f(m_bkgRed, 0.2f * m_bkgGreen, 0.2f * m_bkgBlue); glVertex3f(x2, y1, -4.0); // top right corner + glColor3f(m_bkgRed, 0.2f * m_bkgGreen, 0.2f * m_bkgBlue); glVertex3f(x1, y2, -4.0); // bottom left corner + glColor3f(m_bkgRed, 0.2f * m_bkgGreen, 0.2f * m_bkgBlue); glVertex3f(x2, y2, -4.0); // bottom right corner + glEnd(); + + QString str = "ADC Overload"; + int rectWidth = m_fonts.hugeFontMetrics->boundingRect(str).width(); + + qglColor(QColor(255, 0, 0, 155)); + m_oglTextHuge->renderText((x2-rectWidth)/2, y1+30, -3.5f, str); + } + } + else { + + drawGLRect(m_panRect, QColor(30, 30, 50, 155), -4.0f); + } + + // set a scissor box + glScissor(x1, size().height() - y2, x2, height); + glEnable(GL_SCISSOR_TEST); + + spectrumBufferMutex.lock(); + + TGL3float *vertexArray = new TGL3float[vertexArrayLength]; + TGL3float *vertexColorArray = new TGL3float[vertexArrayLength]; + + TGL3float *vertexArrayBg = new TGL3float[2*vertexArrayLength]; + TGL3float *vertexColorArrayBg = new TGL3float[2*vertexArrayLength]; + + TGL3float *vertexArrayBgPH = new TGL3float[2*vertexArrayLength]; + TGL3float *vertexColorArrayBgPH = new TGL3float[2*vertexArrayLength]; + + TGL3float *vertexArrayPH = new TGL3float[vertexArrayLength]; + TGL3float *vertexColorArrayPH = new TGL3float[vertexArrayLength]; + + switch (m_panMode) { + + case (PanGraphicsMode) FilledLine: + + for (int i = 0; i < vertexArrayLength; i++) { + + mutex.lock(); + vertexColorArrayBg[2*i].x = 0.7 * m_redF; + vertexColorArrayBg[2*i].y = 0.7 * m_greenF; + vertexColorArrayBg[2*i].z = 0.7 * m_blueF; + + vertexColorArrayBg[2*i+1].x = 0.3 * m_redF; + vertexColorArrayBg[2*i+1].y = 0.3 * m_greenF; + vertexColorArrayBg[2*i+1].z = 0.3 * m_blueF; + + if (!m_peakHold) { + + vertexColorArray[i].x = m_red; + vertexColorArray[i].y = m_green; + vertexColorArray[i].z = m_blue; + + /*vertexColorArray[i].x = m_red * (yScaleColor * (m_panadapterBins.at(i) - m_dBmPanMin)); + vertexColorArray[i].y = m_green * (yScaleColor * (m_panadapterBins.at(i) - m_dBmPanMin)); + vertexColorArray[i].z = m_blue * (yScaleColor * (m_panadapterBins.at(i) - m_dBmPanMin));*/ + } + else { + + vertexColorArray[i].x = 0.7f; + vertexColorArray[i].y = 0.7f; + vertexColorArray[i].z = 0.7f; + + vertexColorArrayPH[i].x = m_red; + vertexColorArrayPH[i].y = m_green; + vertexColorArrayPH[i].z = m_blue; + + /*vertexColorArray[i].x = m_red * (yScaleColor * (m_panadapterBins.at(i) - m_dBmPanMin)); + vertexColorArray[i].y = m_green * (yScaleColor * (m_panadapterBins.at(i) - m_dBmPanMin)); + vertexColorArray[i].z = m_blue * (yScaleColor * (m_panadapterBins.at(i) - m_dBmPanMin));*/ + } + mutex.unlock(); + + vertexArrayBg[2*i].x = (GLfloat)(i/m_scaleMult); + vertexArrayBg[2*i].y = (GLfloat)(yTop - yScale * m_panadapterBins.at(i)); + vertexArrayBg[2*i].z = -1.5; + + vertexArrayBg[2*i+1].x = (GLfloat)(i/m_scaleMult); + vertexArrayBg[2*i+1].y = (GLfloat)yTop; + vertexArrayBg[2*i+1].z = -1.5; + + /*vertexArray[i].x = (GLfloat)(i/m_scaleMult); + vertexArray[i].y = (GLfloat)(yTop - yScale * m_panadapterBins.at(i)); + vertexArray[i].z = -1.0;*/ + + if (m_peakHold) { + + vertexArrayPH[i].x = (GLfloat)(i/m_scaleMult); + vertexArrayPH[i].y = (GLfloat)(yTop - yScale * m_panPeakHoldBins.at(i)); + vertexArrayPH[i].z = -0.5; + } + } + + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_COLOR_ARRAY); + + glVertexPointer(3, GL_FLOAT, 0, vertexArrayBg); + glColorPointer(3, GL_FLOAT, 0, vertexColorArrayBg); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 2*vertexArrayLength); + + if (m_peakHold) { + + glVertexPointer(3, GL_FLOAT, 0, vertexArrayPH); + glColorPointer(3, GL_FLOAT, 0, vertexColorArrayPH); + glDrawArrays(GL_LINE_STRIP, 0, vertexArrayLength); + } + else { + + glVertexPointer(3, GL_FLOAT, 6*sizeof(float), vertexArrayBg); + glColorPointer(3, GL_FLOAT, 0, vertexColorArray); + glDrawArrays(GL_LINE_STRIP, 0, vertexArrayLength); + } + + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); + + break; + + case (PanGraphicsMode) Line: + + for (int i = 0; i < vertexArrayLength; i++) { + + mutex.lock(); + if (!m_peakHold) { + + vertexColorArray[i].x = m_red; + vertexColorArray[i].y = m_green; + vertexColorArray[i].z = m_blue; + + /*vertexColorArray[i].x = m_red * (yScaleColor * (m_panadapterBins.at(i) - m_dBmPanMin)); + vertexColorArray[i].y = m_green * (yScaleColor * (m_panadapterBins.at(i) - m_dBmPanMin)); + vertexColorArray[i].z = m_blue * (yScaleColor * (m_panadapterBins.at(i) - m_dBmPanMin));*/ + + /*vertexColorArray[i].x = m_red * (yScaleColor * m_panadapterBins.at(i)); + vertexColorArray[i].y = m_green * (yScaleColor * m_panadapterBins.at(i)); + vertexColorArray[i].z = m_blue * (yScaleColor * m_panadapterBins.at(i));*/ + } + else { + + vertexColorArray[i].x = 0.6f; + vertexColorArray[i].y = 0.6f; + vertexColorArray[i].z = 0.6f; + + vertexColorArrayPH[i].x = m_red; + vertexColorArrayPH[i].y = m_green; + vertexColorArrayPH[i].z = m_blue; + } + mutex.unlock(); + + vertexArray[i].x = (GLfloat)(i/m_scaleMult); + vertexArray[i].y = (GLfloat)(yTop - yScale * m_panadapterBins.at(i)); + vertexArray[i].z = -1.0; + + if (m_peakHold) { + + vertexArrayPH[i].x = (GLfloat)(i/m_scaleMult); + vertexArrayPH[i].y = (GLfloat)(yTop - yScale * m_panPeakHoldBins.at(i)); + vertexArrayPH[i].z = -0.5; + } + } + + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_COLOR_ARRAY); + + glVertexPointer(3, GL_FLOAT, 0, vertexArray); + glColorPointer(3, GL_FLOAT, 0, vertexColorArray); + glDrawArrays(GL_LINE_STRIP, 0, vertexArrayLength); + + if (m_peakHold) { + + glVertexPointer(3, GL_FLOAT, 0, vertexArrayPH); + glColorPointer(3, GL_FLOAT, 0, vertexColorArrayPH); + glDrawArrays(GL_LINE_STRIP, 0, vertexArrayLength); + } + + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); + + break; + + case (PanGraphicsMode) Solid: + + glDisable(GL_MULTISAMPLE); + glDisable(GL_LINE_SMOOTH); + + for (int i = 0; i < vertexArrayLength; i++) { + + mutex.lock(); + if (!m_peakHold) { + + vertexColorArrayBg[2*i].x = m_redST; + vertexColorArrayBg[2*i].y = m_greenST; + vertexColorArrayBg[2*i].z = m_blueST; + + vertexColorArrayBg[2*i+1].x = m_redSB; + vertexColorArrayBg[2*i+1].y = m_greenSB; + vertexColorArrayBg[2*i+1].z = m_blueSB; + } + else { + + vertexColorArrayBg[2*i].x = m_redSB; + vertexColorArrayBg[2*i].y = m_greenSB; + vertexColorArrayBg[2*i].z = m_blueSB; + + vertexColorArrayBg[2*i+1].x = m_redSB; + vertexColorArrayBg[2*i+1].y = m_greenSB; + vertexColorArrayBg[2*i+1].z = m_blueSB; + + vertexColorArrayBgPH[2*i].x = 0.9f;//m_redST; + vertexColorArrayBgPH[2*i].y = 0.9f;//m_greenST; + vertexColorArrayBgPH[2*i].z = 0.9f;//m_blueST; + + vertexColorArrayBgPH[2*i+1].x = 0.9f;// * m_redSB; + vertexColorArrayBgPH[2*i+1].y = 0.9f;// * m_greenSB; + vertexColorArrayBgPH[2*i+1].z = 0.9f;// * m_blueSB; + } + mutex.unlock(); + + vertexArrayBg[2*i].x = (GLfloat)(i/m_scaleMult); + vertexArrayBg[2*i].y = (GLfloat)(yTop - yScale * m_panadapterBins.at(i)); + vertexArrayBg[2*i].z = -1.0f; + + vertexArrayBg[2*i+1].x = (GLfloat)(i/m_scaleMult); + vertexArrayBg[2*i+1].y = (GLfloat)yTop; + //vertexArrayBg[2*i+1].y = (GLfloat)(m_panRect.bottom()); + //vertexArrayBg[2*i].y = (GLfloat)(yScale * m_panadapterBins.at(i)); + vertexArrayBg[2*i+1].z = -1.0f; + + if (m_peakHold) { + + vertexArrayBgPH[2*i].x = (GLfloat)(i/m_scaleMult); + vertexArrayBgPH[2*i].y = (GLfloat)(yTop - yScale * m_panPeakHoldBins.at(i)); + vertexArrayBgPH[2*i].z = -2.0f; + + vertexArrayBgPH[2*i+1].x = (GLfloat)(i/m_scaleMult); + vertexArrayBgPH[2*i+1].y = (GLfloat)yTop; + vertexArrayBgPH[2*i+1].z = -2.0f; + } + } + + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_COLOR_ARRAY); + + glVertexPointer(3, GL_FLOAT, 0, vertexArrayBg); + glColorPointer(3, GL_FLOAT, 0, vertexColorArrayBg); + //glDrawArrays(GL_QUAD_STRIP, 0, 2*vertexArrayLength); + glDrawArrays(GL_LINES, 0, 2*vertexArrayLength); + + if (m_peakHold) { + + glVertexPointer(3, GL_FLOAT, 0, vertexArrayBgPH); + glColorPointer(3, GL_FLOAT, 0, vertexColorArrayBgPH); + glDrawArrays(GL_LINES, 0, 2*vertexArrayLength); + } + + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); + + break; + } + spectrumBufferMutex.unlock(); + + delete[] vertexArray; + delete[] vertexColorArray; + delete[] vertexArrayBg; + delete[] vertexColorArrayBg; + delete[] vertexArrayBgPH; + delete[] vertexColorArrayBgPH; + delete[] vertexArrayPH; + delete[] vertexColorArrayPH; + + //glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + + glDisable(GL_MULTISAMPLE); + glDisable(GL_LINE_SMOOTH); + + // disable scissor box + glDisable(GL_SCISSOR_TEST); +} + +void QGLReceiverPanel::drawPanVerticalScale() { + + if (!m_dBmScalePanRect.isValid()) return; + + int width = m_dBmScalePanRect.width(); + int height = m_dBmScalePanRect.height(); + + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + glColor3f(0.65f, 0.76f, 0.81f); + + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); + + if (!m_dBmScaleFBO || m_dBmScalePanadapterUpdate || m_dBmScalePanadapterRenew) { + + if (!m_dBmScaleFBO || m_dBmScalePanadapterRenew) { + + if (m_dBmScaleFBO) { + + delete m_dBmScaleFBO; + m_dBmScaleFBO = 0; + } + m_dBmScaleFBO = new QGLFramebufferObject(width, height); + //if (m_dBmScaleFBO) + // GRAPHICS_DEBUG << "m_dBmScaleFBO generated."; + + } + + m_dBmScaleFBO->bind(); + renderPanVerticalScale(); + m_dBmScaleFBO->release(); + + m_dBmScalePanadapterUpdate = false; + m_dBmScalePanadapterRenew = false; + } + + renderTexture(m_dBmScalePanRect, m_dBmScaleFBO->texture(), 0.0f); + + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + glColor3f(0.65f, 0.76f, 0.81f); +} + +void QGLReceiverPanel::drawPanHorizontalScale() { + + if (!m_freqScalePanRect.isValid()) return; + + int width = m_freqScalePanRect.width(); + int height = m_freqScalePanRect.height(); + + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + glColor3f(0.65f, 0.76f, 0.81f); + + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); + + if (!m_frequencyScaleFBO || m_freqScalePanadapterUpdate || m_freqScalePanadapterRenew) { + + if (!m_frequencyScaleFBO || m_freqScalePanadapterRenew) { + + if (m_frequencyScaleFBO) { + + delete m_frequencyScaleFBO; + m_frequencyScaleFBO = 0; + } + + m_frequencyScaleFBO = new QGLFramebufferObject(width, height); + //if (m_frequencyScaleFBO) + // GRAPHICS_DEBUG << "m_frequencyScaleFBO generated."; + } + + glPushAttrib(GL_VIEWPORT_BIT); + glViewport(0, 0, width, height); + setProjectionOrthographic(width, height); + + m_frequencyScaleFBO->bind(); + renderPanHorizontalScale(); + m_frequencyScaleFBO->release(); + + glPopAttrib(); + glViewport(0, 0, size().width(), size().height()); + setProjectionOrthographic(size().width(), size().height()); + + m_freqScalePanadapterUpdate = false; + m_freqScalePanadapterRenew = false; + } + + renderTexture(m_freqScalePanRect, m_frequencyScaleFBO->texture(), 0.0f); + + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + glColor3f(0.65f, 0.76f, 0.81f); +} + +void QGLReceiverPanel::drawPanadapterGrid() { + + if (!m_panGrid) return; + + int width = m_panRect.width(); + int height = m_panRect.height(); + + //glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND); + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + + if (m_receiver == m_currentReceiver) + glColor4f(m_redGrid, m_greenGrid, m_blueGrid, 1.0f); + else + glColor4f(m_redGrid, m_greenGrid, m_blueGrid, 0.8f); + + + glDisable(GL_MULTISAMPLE); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); + + if (!m_panadapterGridFBO || m_panGridUpdate || m_panGridRenew) { + + if (!m_panadapterGridFBO || m_panGridRenew) { + + if (m_panadapterGridFBO) { + + delete m_panadapterGridFBO; + m_panadapterGridFBO = 0; + } + + m_panadapterGridFBO = new QGLFramebufferObject(width, height); + //if (m_panadapterGridFBO) + // GRAPHICS_DEBUG << "m_panadapterGridFBO generated."; + } + + glPushAttrib(GL_VIEWPORT_BIT); + glViewport(0, 0, width, height); + setProjectionOrthographic(width, height); + + m_panadapterGridFBO->bind(); + renderPanadapterGrid(); + m_panadapterGridFBO->release(); + + glPopAttrib(); + glViewport(0, 0, size().width(), size().height()); + setProjectionOrthographic(size().width(), size().height()); + + m_panGridUpdate = false; + m_panGridRenew = false; + } + + renderTexture(m_panRect, m_panadapterGridFBO->texture(), -3.0f); + + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + glColor3f(0.65f, 0.76f, 0.81f); + glEnable(GL_MULTISAMPLE); +} + +void QGLReceiverPanel::drawCenterLine() { + + // draw a line for the center frequency + GLint y1, y2; + + y1 = m_panRect.top(); + y2 = m_displayCenterlineHeight; + + if (y2 > y1 + 3) { + + GLint x = m_panRect.width()/2; + GLint y = m_panRect.top() + m_panRect.height() - 1; + //GLint y = m_panRect.top() + m_panRect.height() + m_freqScalePanRect.height() + m_waterfallRect.height() - 1; + //color = set->getPanadapterColors().panCenterLineColor; + QColor col = QColor(80, 180, 240, 180); + + glDisable(GL_MULTISAMPLE); + glLineWidth(1); + glColor4ub(col.red(), col.green(), col.blue(), col.alpha()); + + // center frequency line + glBegin(GL_LINES); + glVertex3f(x, y1 + 1, 3.5f); + glVertex3f(x, y - 1, 3.5f); + glEnd(); + + x = m_panRect.left() + qRound((qreal)(m_panRect.width()/2.0f) - m_deltaF * m_panRect.width() / m_freqScaleZoomFactor); + col = set->getPanadapterColors().panCenterLineColor; + glColor4ub(col.red(), col.green(), col.blue(), 255); + + // VFO frequency line + if (m_dragMouse && !m_panLocked) { + + //glLineWidth(3); + glBegin(GL_LINES); + glVertex3f(x, m_freqScalePanRect.bottom() + 1, 3.0f); + glVertex3f(x, m_freqScalePanRect.bottom() + m_waterfallRect.height() - 1, 3.0f); + glEnd(); + } + glBegin(GL_LINES); + glVertex3f(x, y1 + 1, 4.0f); + glVertex3f(x, y - 1, 4.0f); + glEnd(); + glEnable(GL_MULTISAMPLE); + } + + // draw a frequency line from a different receiver + /*if (m_frequencyRxOnRx != 0) { + + y1 = m_waterfallRect.top(); + y2 = m_waterfallRect.bottom(); + + if (y2 > y1 + 3) { + + qreal unit = (qreal)((m_sampleRate * m_freqScaleZoomFactor) / m_panRect.width()); + qreal df = m_centerFrequency - m_rxDataList.at(m_frequencyRxOnRx%10 - 1).frequency; + + GLint dx = (GLint)(df/unit); + GLint x = m_panRect.width()/2 - dx; + + color = QColor(255, 255, 0, 255); + + glDisable(GL_MULTISAMPLE); + glLineWidth(2); + glColor4ub(color.red(), color.green(), color.blue(), color.alpha()); + glBegin(GL_LINES); + glVertex3f(x-1, y1, 4.0f); + glVertex3f(x-1, y2, 4.0f); + glEnd(); + glEnable(GL_MULTISAMPLE); + } + }*/ +} + +void QGLReceiverPanel::drawPanFilter() { + + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); + + QColor color; + //QString str; + + if (m_highlightFilter) + color = QColor(150, 150, 150, 140); + else + color = QColor(150, 150, 150, 100); + + m_filterLeft = m_panRect.left() + qRound((qreal)(m_panRect.width()/2.0f) + (m_filterLo - m_deltaF) * m_panRect.width() / m_freqScaleZoomFactor); + m_filterRight = m_panRect.left() + qRound((qreal)(m_panRect.width()/2.0f) + (m_filterHi - m_deltaF) * m_panRect.width() / m_freqScaleZoomFactor); + m_filterTop = m_panRect.top() + 1; + m_filterBottom = m_panRect.top() + m_panRect.height() - 1; + //m_filterBottom = m_panRect.top() + m_panRect.height() + m_freqScalePanRect.height() + m_waterfallRect.height() - 1; + + m_filterRect = QRect(m_filterLeft, m_filterTop, m_filterRight - m_filterLeft, m_filterBottom - m_filterTop); + + if ((m_filterLeft >= m_panRect.left() && m_filterLeft <= m_panRect.right()) || + (m_filterRight >= m_panRect.left() && m_filterRight <= m_panRect.right()) || + (m_filterLeft < m_panRect.left() && m_filterRight > m_panRect.right())) + { + if (m_filterRect.height() > 5) drawGLRect(m_filterRect, color, 0.0f); + } + + // filter boundaries + if (m_showFilterLeftBoundary) { + + color = QColor(150, 150, 150, 230); + + glDisable(GL_MULTISAMPLE); + glLineWidth(1); + qglColor(color); + glBegin(GL_LINES); + glVertex3f(m_filterLeft, m_filterTop, 4.0f); + glVertex3f(m_filterLeft, m_filterBottom, 4.0f); + glEnd(); + glEnable(GL_MULTISAMPLE); + + // text + QString str1 = QString("Filter Lo"); + QString str2 = frequencyString(m_filterLowerFrequency, true); + + qglColor(QColor(0, 0, 0, 255)); + if (m_smallSize) { + + m_oglTextSmall->renderText(m_filterLeft + 5, m_filterTop + 44, 4.0f, str1); + m_oglTextSmall->renderText(m_filterLeft + 5, m_filterTop + 64, 4.0f, str2); + } + else { + + m_oglTextBig1->renderText(m_filterLeft + 5, m_filterTop + 44, 4.0f, str1); + m_oglTextBig1->renderText(m_filterLeft + 5, m_filterTop + 64, 4.0f, str2); + } + + qglColor(QColor(255, 255, 255, 255)); + if (m_smallSize) { + + m_oglTextSmall->renderText(m_filterLeft + 3, m_filterTop + 42, 5.0f, str1); + m_oglTextSmall->renderText(m_filterLeft + 3, m_filterTop + 62, 5.0f, str2); + } + else { + + m_oglTextBig1->renderText(m_filterLeft + 3, m_filterTop + 42, 5.0f, str1); + m_oglTextBig1->renderText(m_filterLeft + 3, m_filterTop + 62, 5.0f, str2); + } + } + + if (m_showFilterRightBoundary) { + + color = QColor(150, 150, 150, 230); + + glDisable(GL_MULTISAMPLE); + glLineWidth(1); + qglColor(color); + glBegin(GL_LINES); + glVertex3f(m_filterRight, m_filterTop, 4.0f); + glVertex3f(m_filterRight, m_filterBottom, 4.0f); + glEnd(); + glEnable(GL_MULTISAMPLE); + + // text + QString str1 = QString("Filter Hi"); + QString str2 = frequencyString(m_filterUpperFrequency, true); + + qglColor(QColor(0, 0, 0, 255)); + if (m_smallSize) { + + m_oglTextSmall->renderText(m_filterRight + 5, m_filterTop + 44, 4.0f, str1); + m_oglTextSmall->renderText(m_filterRight + 5, m_filterTop + 64, 4.0f, str2); + } + else { + + m_oglTextBig1->renderText(m_filterRight + 5, m_filterTop + 44, 4.0f, str1); + m_oglTextBig1->renderText(m_filterRight + 5, m_filterTop + 64, 4.0f, str2); + } + + qglColor(QColor(255, 255, 255, 255)); + if (m_smallSize) { + + m_oglTextSmall->renderText(m_filterRight + 3, m_filterTop + 42, 5.0f, str1); + m_oglTextSmall->renderText(m_filterRight + 3, m_filterTop + 62, 5.0f, str2); + } + else { + + m_oglTextBig1->renderText(m_filterRight + 3, m_filterTop + 42, 5.0f, str1); + m_oglTextBig1->renderText(m_filterRight + 3, m_filterTop + 62, 5.0f, str2); + + } + } +} + +void QGLReceiverPanel::drawWaterfall() { + + if (m_waterfallRect.isEmpty()) return; + + int top = m_waterfallRect.top(); + int left = m_waterfallRect.left(); + int width = m_waterfallRect.width(); + int height = m_waterfallRect.height(); + //int height = this->size().height(); + + + glColor4f(1.0, 1.0, 1.0, 1.0); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); + + // check for framebuffer objects + if (set->getFBOPresence()) { + + // create the FBOs if not exist + if (!m_textureFBO || !m_waterfallLineFBO || !m_waterfallFBO || m_waterfallUpdate) { + + if (m_waterfallLineFBO) { + + delete m_waterfallLineFBO; + m_waterfallLineFBO = 0; + } + + if (m_waterfallFBO) { + + delete m_waterfallFBO; + m_waterfallFBO = 0; + } + + if (m_textureFBO) { + + delete m_textureFBO; + m_textureFBO = 0; + } + + if (QGLFramebufferObject::hasOpenGLFramebufferBlit()) { + + //QGLFramebufferObjectFormat format; + //format.setSamples(2); + //format.setAttachment(QGLFramebufferObject::CombinedDepthStencil); + + m_waterfallLineFBO = new QGLFramebufferObject(width, 1); + //if (m_waterfallLineFBO) + //GRAPHICS_DEBUG << "m_waterfallLineFBO generated."; + + m_waterfallFBO = new QGLFramebufferObject(width, height); + //if (m_waterfallFBO) + //GRAPHICS_DEBUG << "m_waterfallFBO generated."; + + m_textureFBO = new QGLFramebufferObject(width, height); + //if (m_textureFBO) + //GRAPHICS_DEBUG << "m_textureFBO generated."; + + } + else { + + GRAPHICS_DEBUG << "has no OpenGL FramebufferBlit"; + } + + m_waterfallUpdate = false; + drawGLRect(m_waterfallRect, Qt::black); + + m_waterfallLineCnt = 0; + + if (width > 0) { + + m_waterfallPixel.clear(); + m_waterfallPixel.resize(width); + + TGL_ubyteRGBA col; + col.red = 0; col.green = 0; col.blue = 0; col.alpha = 255; + + for (int i = 0; i < width; i++) + m_waterfallPixel[i] = col; + } + } + + if (m_dataEngineState == QSDR::DataEngineUp) { + + GLint oldTex; + glGetIntegerv(GL_TEXTURE_BINDING_2D, &oldTex); + + m_waterfallLineFBO->bind(); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, m_waterfallPixel.data()); + m_waterfallLineFBO->release(); + + m_waterfallLineCnt++; + if (m_waterfallLineCnt > height) m_waterfallLineCnt = height; + + // draw the waterfall + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, m_waterfallFBO->texture()); + + glBegin(GL_QUADS); + glTexCoord2f(0, 1); glVertex2i(left, top); // top left corner + glTexCoord2f(1, 1); glVertex2i(left + width, top); // top right corner + glTexCoord2f(1, 0); glVertex2i(left + width, top + height); // bottom right corner + glTexCoord2f(0, 0); glVertex2i(left, top + height); // bottom left corner + glEnd(); + glBindTexture(GL_TEXTURE_2D, oldTex); + glDisable(GL_TEXTURE_2D); + + glPushAttrib(GL_VIEWPORT_BIT); + glViewport(0, 0, width, height); + setProjectionOrthographic(width, height); + + // render to the next waterfall texture + m_textureFBO->bind(); + + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, m_waterfallFBO->texture()); + + // the waterfall FBO + glBegin(GL_QUADS); + glTexCoord2f(0, 1); glVertex2i(0, 1); // top left corner + glTexCoord2f(1, 1); glVertex2i(width, 1); // top right corner + glTexCoord2f(1, 0); glVertex2i(width, 1 + height); // bottom right corner + glTexCoord2f(0, 0); glVertex2i(0, 1 + height); // bottom left corner + glEnd(); + + // the new waterfall line + glBindTexture(GL_TEXTURE_2D, m_waterfallLineFBO->texture()); + + glBegin(GL_QUADS); + glTexCoord2f(0, 1); glVertex2i(0, 0); // top left corner + glTexCoord2f(1, 1); glVertex2i(width, 0); // top right corner + glTexCoord2f(1, 0); glVertex2i(width, 1); // bottom right corner + glTexCoord2f(0, 0); glVertex2i(0, 1); // bottom left corner + glEnd(); + + m_textureFBO->release(); + + glDisable(GL_TEXTURE_2D); + glPopAttrib(); + glViewport(0, 0, size().width(), size().height()); + setProjectionOrthographic(size().width(), size().height()); + + if (m_waterfallLineCnt < height) { + + QRect rect(0, top + m_waterfallLineCnt, width, height - m_waterfallLineCnt); + drawGLRect(rect, QColor(0, 0, 0, 255), 3.0f); + } + + // copy the next waterfall image to the waterfall FBO + QRect copyRect(0, 0, width, height); + QGLFramebufferObject::blitFramebuffer(m_waterfallFBO, copyRect, m_textureFBO, copyRect); + } + else { + + drawGLRect(m_waterfallRect, Qt::black); + } + } + else { + } +} + +void QGLReceiverPanel::drawWaterfallVerticalScale() { + + if (!m_secScaleWaterfallRect.isValid()) return; + + int width = m_secScaleWaterfallRect.width(); + int height = m_secScaleWaterfallRect.height(); + + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + glColor3f(0.65f, 0.76f, 0.81f); + + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); + + if (!m_secScaleWaterfallFBO || m_secScaleWaterfallUpdate || m_secScaleWaterfallRenew) { + + if (!m_secScaleWaterfallFBO || m_secScaleWaterfallRenew) { + + if (m_secScaleWaterfallFBO) { + + delete m_secScaleWaterfallFBO; + m_secScaleWaterfallFBO = 0; + } + m_secScaleWaterfallFBO = new QGLFramebufferObject(width, height); + //if (m_secScaleWaterfallFBO) + // GRAPHICS_DEBUG << "m_secScaleWaterfallFBO generated."; + } + + m_secScaleWaterfallFBO->bind(); + renderWaterfallVerticalScale(); + m_secScaleWaterfallFBO->release(); + + m_secScaleWaterfallUpdate = false; + m_secScaleWaterfallRenew = false; + } + + renderTexture(m_secScaleWaterfallRect, m_secScaleWaterfallFBO->texture(), 4.0f); + + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + glColor3f(0.65f, 0.76f, 0.81f); +} + +void QGLReceiverPanel::drawCrossHair() { + + QRect rect(0, m_panRect.top(), width(), height() - m_panRect.top()); + + int x = m_mousePos.x(); + int y = m_mousePos.y(); + + int textOffset = 20; + int spacing = 6; + + glDisable(GL_MULTISAMPLE); + glDisable(GL_BLEND); + glDisable(GL_LINE_SMOOTH); + glLineWidth(1.0f); + + qglColor(QColor(95, 95, 95, 255)); + + // set a scissor box + glScissor(rect.left(), rect.top(), rect.width() - 1, rect.height()); + glEnable(GL_SCISSOR_TEST); + + // horizontal line + glBegin(GL_LINES); + glVertex3f(m_dBmScalePanRect.right() - 2, y, 4.0f); + glVertex3f(rect.right() - 1, y, 4.0f); + glEnd(); + + // vertical line + glBegin(GL_LINES); + glVertex3f(x, rect.top() + 1, 4.0f); + glVertex3f(x, rect.bottom() - 1, 4.0f); + glEnd(); + + // cross hair + qglColor(QColor(180, 180, 180, 255)); + glBegin(GL_LINES); + glVertex3f(x , y - 20, 5.0f); + glVertex3f(x , y + 20, 5.0f); + glVertex3f(x - 20, y, 5.0f); + glVertex3f(x + 20, y, 5.0f); + glEnd(); + + // text + QString dFstr; + QString fstr; + QString dBstr; + + int dx = m_panRect.width()/2 - x; + qreal unit = (qreal)((m_sampleRate * m_freqScaleZoomFactor) / m_panRect.width()); + qreal df = unit * dx; + qreal frequency = m_centerFrequency - df; + + dFstr = frequencyString(m_deltaFrequency - df, true); + fstr = frequencyString(frequency); + + qreal dBm = glPixelTodBm(m_panRect, m_dBmPanMax, m_dBmPanMin, y); + dBstr = QString::number(dBm, 'f', 1) + " dBm"; + + int rectWidth; + int fontHeight; + if (m_smallSize) { + + rectWidth = m_fonts.smallFontMetrics->boundingRect(fstr).width(); + fontHeight = m_fonts.smallFontMetrics->tightBoundingRect("0").height() + spacing; + } + else { + + rectWidth = m_fonts.bigFont1Metrics->width(fstr); + fontHeight = m_fonts.bigFont1Metrics->tightBoundingRect("0").height() + spacing; + } + + m_haircrossMaxRight = rectWidth + textOffset; + m_smallSize ? m_haircrossMinTop = 40 : m_haircrossMinTop = 60; + + + int tx, ty; + if (x > m_panRect.width() - m_haircrossMaxRight) { + + tx = x - m_haircrossMaxRight; + if (y > m_haircrossMinTop) + m_smallSize ? ty = y - 42 : ty = y - 62; + else + m_smallSize ? ty = y + 10 : ty = y + 30; + } + else { + + tx = x + textOffset; + if (y > m_haircrossMinTop) + m_smallSize ? ty = y - 42 : ty = y - 62; + else + m_smallSize ? ty = y + 10 : ty = y + 30; + } + + // delta frequency and frequency + //qglColor(QColor(200, 55, 55, 255)); + qglColor(QColor(200, 200, 200, 255)); + if (m_smallSize) { + + m_oglTextSmall->renderText(tx, ty, 5.0f, dFstr); + //qglColor(QColor(200, 200, 200, 255)); + m_oglTextSmall->renderText(tx, ty + fontHeight, 5.0f, fstr); + } + else { + + m_oglTextBig1->renderText(tx, ty, 5.0f, dFstr); + //qglColor(QColor(200, 200, 200, 255)); + m_oglTextBig1->renderText(tx, ty + fontHeight, 5.0f, fstr); + } + + + // dBm value + if (m_mouseRegion == panadapterRegion) { + + if (m_smallSize) + m_oglTextSmall->renderText(tx, ty + 2*fontHeight, 5.0f, dBstr); + else + m_oglTextBig1->renderText(tx, ty + 2*fontHeight, 5.0f, dBstr); + } + + // Ham band text + /*if (m_oldMousePosX != m_mousePos.x()) { + + m_bandText = getHamBandTextString(set->getHamBandTextList(), true, frequency); + m_oldMousePosX = m_mousePos.x(); + }*/ + + glColor3f(0.94f, 0.82f, 0.43f); + if (m_smallSize) + m_oglTextSmall->renderText(tx, ty + 4*fontHeight, 5.0f, m_bandText); + else + m_oglTextBig1->renderText(tx, ty + 5*fontHeight, 5.0f, m_bandText); + + + glDisable(GL_SCISSOR_TEST); + glEnable(GL_MULTISAMPLE); +} + +void QGLReceiverPanel::drawVFOControl() { + + // lock Panadapter + QString str = "PAN LOCKED"; + int x1 = m_dBmScalePanRect.right() + 5; + int y1 = 3; + + if (m_panLocked) { + + if (m_dataEngineState == QSDR::DataEngineUp) { + + qglColor(QColor(0, 0, 0, 255)); + m_oglTextSmall->renderText(x1+3, y1, 0.0f, str); + qglColor(QColor(255, 170, 90, 200)); + m_oglTextSmall->renderText(x1+1, y1-2, 1.0f, str); + } + else { + + qglColor(QColor(0, 0, 0, 255)); + m_oglTextSmall->renderText(x1+3, y1, 0.0f, str); + qglColor(QColor(150, 150, 150, 100)); + m_oglTextSmall->renderText(x1+1, y1-2, 1.0f, str); + } + } + + // click VFO + x1 += m_fonts.smallFontMetrics->width(str) + 12; + str = "CLICK VFO"; + + if (m_clickVFO) { + + if (m_dataEngineState == QSDR::DataEngineUp) { + + qglColor(QColor(0, 0, 0, 255)); + m_oglTextSmall->renderText(x1+3, y1, 0.0f, str); + qglColor(QColor(255, 170, 90, 200)); + m_oglTextSmall->renderText(x1+1, y1-2, 1.0f, str); + } + else { + + qglColor(QColor(0, 0, 0, 255)); + m_oglTextSmall->renderText(x1+3, y1, 0.0f, str); + qglColor(QColor(150, 150, 150, 100)); + m_oglTextSmall->renderText(x1+1, y1-2, 1.0f, str); + } + } + + // FFT size + if (m_receiver == 0) { + + str = "FFT: %1"; + //float res; + QString s; + + switch (m_fftMult) { + + case 1: + s = "4k"; + break; + + case 2: + s = "8k"; + break; + + case 4: + s = "16k"; + break; + + case 8: + s = "32k"; + break; + } + x1 = m_panRect.right() - m_fonts.smallFontMetrics->width(str) - 5; + + if (m_dataEngineState == QSDR::DataEngineUp) { + + qglColor(QColor(0, 0, 0, 255)); + m_oglTextSmall->renderText(x1+3, y1, 0.0f, str.arg(s)); + qglColor(QColor(255, 170, 90, 200)); + m_oglTextSmall->renderText(x1+1, y1-2, 1.0f, str.arg(s)); + } + } + + int delta = qRound((m_deltaF * m_panRect.width())/m_freqScaleZoomFactor); + //GRAPHICS_DEBUG << "delta = " << delta; + + if (delta > m_panRect.width()/2) { + + QColor col = QColor(255, 40, 40, 255); + str = "<< VFO %1"; + str = str.arg(frequencyString(m_vfoFrequency, false)); + + int x = m_dBmScalePanRect.right(); + int y = 25; + + QRect rect = QRect(x, y, m_fonts.smallFontMetrics->width(str) + 4, m_fonts.fontHeightSmallFont + 2); + drawGLRect(rect, col, 2.0f); + qglColor(QColor(255, 255, 255, 255)); + m_oglTextSmall->renderText(x+1, y-2, 3.0f, str); + } + + if (delta < -m_panRect.width()/2) { + + QColor col = QColor(255, 40, 40, 255); + str = "%1 VFO >>"; + str = str.arg(frequencyString(m_vfoFrequency, false)); + + int x = m_panRect.right() - m_fonts.smallFontMetrics->width(str); + int y = 25; + + QRect rect = QRect(x, y, m_fonts.smallFontMetrics->width(str) + 4, m_fonts.fontHeightSmallFont + 2); + drawGLRect(rect, col, 2.0f); + qglColor(QColor(255, 255, 255, 255)); + m_oglTextSmall->renderText(x+1, y-2, 3.0f, str); + } + + //qglColor(QColor(0, 0, 0)); + //m_oglTextSmall->renderText(x1+1, y1-2, 3.0f, str); + + // set Center = VFO frequency button + /*QColor col; + x1 += m_fonts.smallFontMetrics->width(str) + 7; + str = "mid = vfo"; + + if (m_dataEngineState == QSDR::DataEngineUp) { + + if (m_receiver == m_currentReceiver) { + + if (m_panLocked) + col = QColor(1, 150, 140, 140); + else + col = QColor(1, 230, 220, 140); + } + else + col = QColor(90, 100, 90, 140); + } + else + col = m_darkColor; + + m_midToVfoButtonRect = QRect(x1, y1, m_fonts.smallFontMetrics->width(str) + 5, m_fonts.fontHeightSmallFont + 2); + drawGLRect(m_midToVfoButtonRect, col, 2.0f); + qglColor(QColor(0, 0, 0)); + m_oglTextSmall->renderText(x1+1, y1-2, 3.0f, str);*/ + + + // set VFO = Center frequency button + /*x1 += m_fonts.smallFontMetrics->width(str) + 7; + str = "vfo = mid"; + + if (m_dataEngineState == QSDR::DataEngineUp) { + + if (m_receiver == m_currentReceiver) + col = QColor(1, 230, 220, 140); + else + col = QColor(90, 100, 90, 140); + } + else + col = m_darkColor; + + m_vfoToMidButtonRect = QRect(x1, y1, m_fonts.smallFontMetrics->width(str) + 5, m_fonts.fontHeightSmallFont + 2); + drawGLRect(m_vfoToMidButtonRect, col, 2.0f); + qglColor(QColor(0, 0, 0)); + m_oglTextSmall->renderText(x1+1, y1-2, 3.0f, str);*/ +} + +void QGLReceiverPanel::drawReceiverInfo() { + + QString str; + + // mouse wheel freq step size + /*if (m_dataEngineState == QSDR::DataEngineUp) { + + if (m_receiver == m_currentReceiver) + col = QColor(1, 190, 180, 180); + else + col = QColor(1, 100, 90, 180); + } + else + col = m_darkColor; + + str = "%1"; + str = str.arg(set->getValue1000(m_mouseWheelFreqStep, 0, "Hz")); + + int x1 = m_panRect.width() - (m_fonts.smallFontMetrics->tightBoundingRect(str).width() + 9); + int y1 = 3; + + rect = QRect(x1+2, y1, m_fonts.smallFontMetrics->tightBoundingRect(str).width() + 5, m_fonts.fontHeightSmallFont + 2); + drawGLRect(rect, col, 2.0f); + qglColor(QColor(0, 0, 0)); + m_oglTextSmall->renderText(x1+3, y1-2, 3.0f, str);*/ + + + // AGC mode + //if (m_dataEngineState == QSDR::DataEngineUp) { + + // if (m_receiver == m_currentReceiver) { + + // if (m_showAGCLines) + // col = QColor(255, 170, 90, 180); + // else + // col = QColor(215, 130, 50, 180); + // } + // else + // col = QColor(165, 80, 1); + //} + //else + // col = m_darkColor; + + //str = "%1"; + ////str = str.arg(set->getAGCModeString(m_receiver)); + //str = str.arg(m_agcModeString); + + //x1 -= m_fonts.smallFontMetrics->tightBoundingRect(str).width() + 7; + //y1 = 3; + + //m_agcButtonRect = QRect(x1+2, y1, m_fonts.smallFontMetrics->tightBoundingRect(str).width() + 5, m_fonts.fontHeightSmallFont + 2); + //drawGLRect(m_agcButtonRect, col, 2.0f); + //qglColor(QColor(0, 0, 0)); + //m_oglTextSmall->renderText(x1+3, y1-2, 3.0f, str); + + + // main frequency display + glDisable(GL_MULTISAMPLE); + if (m_panRect.height() > 15) { + + int fLength = m_fonts.bigFont1Metrics->width("55.555.555") + 30; + //GLint x = m_panRect.width()/2 - 65; + GLint x = m_panRect.left() + qRound((qreal)(m_panRect.width()/2.0f) - m_deltaF * m_panRect.width() / m_freqScaleZoomFactor) + 10; + if (x > m_panRect.right() - fLength) x -= fLength + 20; + + int alpha; + QColor colFlt; + QColor colAGC; + QColor colDSP; + QRect rect; + + if (m_dataEngineState == QSDR::DataEngineUp) { + + if (m_receiver == set->getCurrentReceiver()) { + + colDSP = QColor(1, 190, 180, 180); + colFlt = QColor(200, 190, 50, 180); + if (m_showAGCLines) + colAGC = QColor(255, 170, 90, 180); + else + colAGC = QColor(215, 130, 50, 180); + + alpha = 255; + } + else { + + alpha = 155; + colFlt = QColor(110, 100, 1, 180); + colDSP = QColor(1, 100, 90, 180); + colAGC = QColor(165, 80, 1); + } + } + else { + + alpha = 100; + colFlt = m_darkColor; + colAGC = m_darkColor; + colDSP = m_darkColor; + } + + + // Filter width + str = "%1"; + str = str.arg(m_filterWidthString); + + int x1 = x; + int y1 = 3; + + rect = QRect(x1, y1, m_fonts.smallFontMetrics->width(str) + 4, m_fonts.fontHeightSmallFont + 2); + drawGLRect(rect, colFlt, 2.0f); + qglColor(QColor(0, 0, 0)); + m_oglTextSmall->renderText(x1+1, y1-2, 3.0f, str); + + // DSP mode + x1 += m_fonts.smallFontMetrics->width(str) + 5; + + str = "%1"; + str = str.arg(m_dspModeString); + + rect = QRect(x1, y1, m_fonts.smallFontMetrics->width(str) + 3, m_fonts.fontHeightSmallFont + 2); + drawGLRect(rect, colDSP, 2.0f); + qglColor(QColor(0, 0, 0)); + m_oglTextSmall->renderText(x1+1, y1-2, 3.0f, str); + + // AGC mode + x1 += m_fonts.smallFontMetrics->width(str) + 4; + + str = "%1"; + str = str.arg(m_agcModeString); + + rect = QRect(x1, y1, m_fonts.smallFontMetrics->width(str) + 4, m_fonts.fontHeightSmallFont + 2); + drawGLRect(rect, colAGC, 2.0f); + qglColor(QColor(0, 0, 0)); + m_oglTextSmall->renderText(x1+1, y1-2, 3.0f, str); + + // VFO frequency + TFrequency f; + f.freqMHz = (int)(m_vfoFrequency / 1000); + f.freqkHz = (int)(m_vfoFrequency % 1000); + + str = "%1.%2"; + int f1 = f.freqMHz; + int f2 = f.freqkHz; + + QString fstr = str.arg(f1/1000).arg(f1 - 1000 * (int)(f1/1000), 3, 10, QLatin1Char('0')); + //int fLength = m_fonts.bigFont1Metrics->width(fstr) + 55; + + qglColor(QColor(0, 0, 0, alpha)); + m_oglTextBig1->renderText(x+2, 14, 4.0f, fstr); + + qglColor(QColor(255, 255, 255, alpha)); + m_oglTextBig1->renderText(x, 12, 5.0f, fstr); + + str = "%1"; + if (f1 / 1000 < 10) { + + qglColor(QColor(0, 0, 0, alpha)); + m_oglTextBig2->renderText(x + 36, 14, 4.0f, str.arg(f2, 3, 10, QLatin1Char('0'))); + m_oglTextBig1->renderText(x + 60, 14, 4.0f, "MHz"); + + qglColor(QColor(255, 255, 255, alpha)); + m_oglTextBig2->renderText(x + 34, 12, 5.0f, str.arg(f2, 3, 10, QLatin1Char('0'))); + m_oglTextBig1->renderText(x + 58, 12, 5.0f, "MHz"); + } + else { + + qglColor(QColor(0, 0, 0, alpha)); + m_oglTextBig2->renderText(x + 39, 13, 4.0f, str.arg(f2, 3, 10, QLatin1Char('0'))); + m_oglTextBig1->renderText(x + 65, 13, 4.0f, "MHz"); + + qglColor(QColor(255, 255, 255, alpha)); + m_oglTextBig2->renderText(x + 41, 11, 5.0f, str.arg(f2, 3, 10, QLatin1Char('0'))); + m_oglTextBig1->renderText(x + 63, 11, 5.0f, "MHz"); + } + } + + if (m_panRect.height() > 15 && m_deltaFrequency != 0) { + + // center frequency + TFrequency f; + f.freqMHz = (int)(m_centerFrequency / 1000); + f.freqkHz = (int)(m_centerFrequency % 1000); + + str = "%1.%2"; + int f1 = f.freqMHz; + int f2 = f.freqkHz; + + QString fstr = str.arg(f1/1000).arg(f1 - 1000 * (int)(f1/1000), 3, 10, QLatin1Char('0')); + GLint x = m_panRect.width()/2 + 10; + + qglColor(QColor(80, 180, 240, 180)); + m_oglTextBig1->renderText(x, 27, 5.0f, fstr); + + str = "%1"; + if (f1 / 1000 < 10) { + + m_oglTextBig2->renderText(x + 34, 27, 5.0f, str.arg(f2, 3, 10, QLatin1Char('0'))); + m_oglTextBig1->renderText(x + 58, 27, 5.0f, "MHz"); + } + else { + + m_oglTextBig2->renderText(x + 41, 27, 5.0f, str.arg(f2, 3, 10, QLatin1Char('0'))); + m_oglTextBig1->renderText(x + 63, 27, 5.0f, "MHz"); + } + } + glEnable(GL_MULTISAMPLE); +} + +void QGLReceiverPanel::drawAGCControl() { + + glDisable(GL_MULTISAMPLE); + glLineStipple(1, 0x0C0C); + glEnable(GL_LINE_STIPPLE); + glLineWidth(1.0f); + + glScissor(m_panRect.left(), size().height() - (m_panRect.top() + m_panRect.height()), m_panRect.left() + m_panRect.width(), m_panRect.height()); + glEnable(GL_SCISSOR_TEST); + + if (m_agcMode == (AGCMode) agcOFF) { + + m_agcFixedGainLevelPixel = dBmToGLPixel(m_panRect, m_dBmPanMax, m_dBmPanMin, -m_agcFixedGain); + //GRAPHICS_DEBUG << "m_agcFixedGainLevelPixel = " << m_agcFixedGainLevelPixel; + + QString str = "AGC-F"; + qglColor(QColor(0, 0, 0, 255)); + m_oglTextSmall->renderText(m_panRect.right() - 32, m_agcFixedGainLevelPixel - 13, 4.0f, str); + qglColor(QColor(225, 125, 225, 255)); + m_oglTextSmall->renderText(m_panRect.right() - 34, m_agcFixedGainLevelPixel - 15, 5.0f, str); + + // AGC fixed gain line + glBegin(GL_LINES); + qglColor(QColor(0, 0, 0, 255)); + glVertex3f(m_dBmScalePanRect.right() - 1, m_agcFixedGainLevelPixel + 2, 4.0f); + glVertex3f(m_panRect.right() - 1, m_agcFixedGainLevelPixel, 4.0f); + qglColor(QColor(225, 125, 225, 255)); + glVertex3f(m_dBmScalePanRect.right() - 3, m_agcFixedGainLevelPixel, 5.0f); + glVertex3f(m_panRect.right() - 1, m_agcFixedGainLevelPixel, 4.0f); + glEnd(); + + } + else { + + m_agcThresholdPixel = dBmToGLPixel(m_panRect, m_dBmPanMax, m_dBmPanMin, m_agcThresholdOld); + + if (m_agcHangEnabled) + m_agcHangLevelPixel = dBmToGLPixel(m_panRect, m_dBmPanMax, m_dBmPanMin, m_agcHangLevelOld); + + QString str = "AGC-T"; + qglColor(QColor(0, 0, 0, 255)); + m_oglTextSmall->renderText(m_panRect.right() - 32, m_agcThresholdPixel - 13, 4.0f, str); + qglColor(QColor(225, 125, 125, 255)); + m_oglTextSmall->renderText(m_panRect.right() - 34, m_agcThresholdPixel - 15, 5.0f, str); + + // AGC threshold line + glBegin(GL_LINES); + qglColor(QColor(0, 0, 0, 255)); + glVertex3f(m_dBmScalePanRect.right() - 1, m_agcThresholdPixel + 2, 4.0f); + glVertex3f(m_panRect.right() - 1, m_agcThresholdPixel, 4.0f); + qglColor(QColor(225, 125, 125, 255)); + glVertex3f(m_dBmScalePanRect.right() - 3, m_agcThresholdPixel, 5.0f); + glVertex3f(m_panRect.right() - 1, m_agcThresholdPixel, 4.0f); + glEnd(); + + // AGC hang threshold line + if (m_agcHangEnabled) { + + str = "AGC-H"; + qglColor(QColor(0, 0, 0, 255)); + m_oglTextSmall->renderText(m_panRect.right() - 32, m_agcHangLevelPixel - 13, 4.0f, str); + qglColor(QColor(125, 225, 125, 255)); + m_oglTextSmall->renderText(m_panRect.right() - 34, m_agcHangLevelPixel - 15, 5.0f, str); + + glBegin(GL_LINES); + qglColor(QColor(0, 0, 0, 255)); + glVertex3f(m_dBmScalePanRect.right() - 1, m_agcHangLevelPixel + 2, 4.0f); + glVertex3f(m_panRect.right() - 1, m_agcHangLevelPixel, 4.0f); + qglColor(QColor(125, 225, 125, 255)); + glVertex3f(m_dBmScalePanRect.right() - 3, m_agcHangLevelPixel, 5.0f); + glVertex3f(m_panRect.right() - 1, m_agcHangLevelPixel, 4.0f); + glEnd(); + } + } + + glDisable(GL_SCISSOR_TEST); + glDisable(GL_LINE_STIPPLE); + glEnable(GL_MULTISAMPLE); +} + +//********************************************************************************************** +// The algorithms of the scale functions renderPanVerticalScale() and renderPanHorizontalScale() +// are taken from SDRMAXIII (c) Catherine Moss, with permission. + +void QGLReceiverPanel::renderPanVerticalScale() { + + QString str; + + int spacing = 7; + int fontHeight; + int fontMaxWidth; + if (m_smallSize) { + + fontHeight = m_fonts.smallFontMetrics->tightBoundingRect(".0dBm").height() + spacing; + fontMaxWidth = m_fonts.smallFontMetrics->boundingRect("-000.0").width(); + } + else { + + fontHeight = m_fonts.bigFont1Metrics->tightBoundingRect(".0dBm").height() + spacing; + fontMaxWidth = m_fonts.bigFont1Metrics->boundingRect("-000.0").width(); + } + + + GLint width = m_dBmScalePanRect.width(); + GLint height = m_dBmScalePanRect.height(); + + qreal unit = (qreal)(height / qAbs(m_dBmPanMax - m_dBmPanMin)); + + m_dBmScale = getYRuler2(m_dBmScalePanRect, fontHeight, unit, m_dBmPanMin, m_dBmPanMax); + + glClear(GL_COLOR_BUFFER_BIT); + + QRect textRect(0, 0, fontMaxWidth, fontHeight); + if (m_smallSize) + textRect.moveLeft(3); + else + textRect.moveLeft(-1); + + int yOld = -textRect.height(); + + int len = m_dBmScale.mainPointPositions.length(); + int sublen = m_dBmScale.subPointPositions.length(); + + glViewport(0, 0, width, height); + setProjectionOrthographic(width, height); + + // draw the scale background + drawGLScaleBackground(QRect(0, 0, width, height), QColor(30, 30, 30, 180)); + + if (len > 0) { + + glColor3f(0.65f, 0.76f, 0.81f); + glLineWidth(1); + + glBegin(GL_LINES); + for (int i = 0; i < len; i++) { + + glVertex3f(width, m_dBmScale.mainPointPositions.at(i), 0.0f); // origin of the line + glVertex3f(width - 4, m_dBmScale.mainPointPositions.at(i), 0.0f); // ending point of the line + } + glEnd(); + + glColor3f(0.45f, 0.56f, 0.61f); + if (sublen > 0) { + + glBegin(GL_LINES); + for (int i = 0; i < sublen; i++) { + + glVertex3f(width, m_dBmScale.subPointPositions.at(i), 0.0f); // origin of the line + glVertex3f(width - 2, m_dBmScale.subPointPositions.at(i), 0.0f); // ending point of the line + } + glEnd(); + } + + glColor3f(0.75f, 0.86f, 0.91f); + for (int i = 0; i < len; i++) { + + textRect.moveBottom(m_dBmScale.mainPointPositions.at(i) + textRect.height()/2); + + if (textRect.y() >= yOld && textRect.bottom() <= (m_dBmScalePanRect.height() - textRect.height())) { + + str = QString::number(m_dBmScale.mainPoints.at(i), 'f', 1); + if (m_smallSize) + m_oglTextSmall->renderText(textRect.x() + fontMaxWidth - m_fonts.smallFontMetrics->tightBoundingRect(str).width(), textRect.y(), str); + else + m_oglTextBig1->renderText(textRect.x() + fontMaxWidth - m_fonts.bigFont1Metrics->tightBoundingRect(str).width(), textRect.y(), str); + yOld = textRect.bottom(); + } + } + } + + textRect.moveTop(m_dBmScalePanRect.height() - textRect.height()); + glColor3f(0.94f, 0.22f, 0.43f); + + str = QString("dBm"); + if (m_smallSize) + m_oglTextSmall->renderText(textRect.x(), textRect.y(), str); + else + m_oglTextBig1->renderText(textRect.x() + 10, textRect.y(), str); + + glViewport(0, 0, size().width(), size().height()); + setProjectionOrthographic(size().width(), size().height()); +} + +void QGLReceiverPanel::renderPanHorizontalScale() { + + //GRAPHICS_DEBUG << "render frequency scale"; + int fontHeight; + int fontMaxWidth; + if (m_smallSize) { + + fontHeight = m_fonts.smallFontMetrics->tightBoundingRect(".0kMGHz").height(); + fontMaxWidth = m_fonts.smallFontMetrics->boundingRect("000.000.0").width(); + } + else { + + fontHeight = m_fonts.bigFont1Metrics->tightBoundingRect(".0kMGHz").height(); + fontMaxWidth = m_fonts.bigFont1Metrics->boundingRect("000.000.0").width(); + } + + qreal freqSpan = (qreal)(m_sampleRate * m_freqScaleZoomFactor); + qreal lowerFreq = (qreal)m_centerFrequency - freqSpan / 2; + qreal upperFreq = (qreal)m_centerFrequency + freqSpan / 2; + qreal unit = (qreal)(m_freqScalePanRect.width() / freqSpan); + + m_frequencyScale = getXRuler(m_freqScalePanRect, fontMaxWidth, unit, lowerFreq, upperFreq); + + // draw the frequency scale + int offset_X = -1; + int textOffset_y = 5; + double freqScale = 1; + + QString fstr = QString(" Hz "); + if (upperFreq >= 1e6) { freqScale = 1e6; fstr = QString(" MHz "); } + else + if (upperFreq >= 1e3) { freqScale = 1e3; fstr = QString(" kHz "); } + + // draw the scale background + drawGLScaleBackground(QRect(0, 0, m_freqScalePanRect.width(), m_freqScalePanRect.height()), QColor(0, 0, 0, 255)); + + QRect scaledTextRect(0, textOffset_y, 1, m_freqScalePanRect.height()); + + if (m_smallSize) + scaledTextRect.setWidth(m_fonts.smallFontMetrics->width(fstr)); + else + scaledTextRect.setWidth(m_fonts.bigFont1Metrics->width(fstr)); + + scaledTextRect.moveLeft(m_freqScalePanRect.width() - scaledTextRect.width()); + + glColor3f(0.65f, 0.76f, 0.81f); + int len = m_frequencyScale.mainPointPositions.length(); + if (len > 0) { + + glLineWidth(3); + glBegin(GL_LINES); + for (int i = 0; i < len; i++) { + + glVertex3f(m_frequencyScale.mainPointPositions.at(i), 1.0f, 0.0f); + glVertex3f(m_frequencyScale.mainPointPositions.at(i), 4.0f, 0.0f); + } + glEnd(); + + for (int i = 0; i < len; i++) { + + QString str = QString::number(m_frequencyScale.mainPoints.at(i) / freqScale, 'f', 3); + + if (i > 0) { + + double delta = m_frequencyScale.mainPoints.at(i) - m_frequencyScale.mainPoints.at(i-1); + if (delta < 1000.0) + str = QString::number(m_frequencyScale.mainPoints.at(i) / freqScale, 'f', 4); + else + if (freqScale == 1e3) + while (str.endsWith('0')) str.remove(str.size() - 1, 1); + } + if (str.endsWith('.')) str.remove(str.size() - 1, 1); + + int textWidth; + if (m_smallSize) + textWidth = m_fonts.smallFontMetrics->width(str); + else + textWidth = m_fonts.bigFont1Metrics->width(str); + QRect textRect(m_frequencyScale.mainPointPositions.at(i) + offset_X - (textWidth / 2), textOffset_y, textWidth, fontHeight); + + if (textRect.left() < 0 || textRect.right() >= scaledTextRect.left()) continue; + + if (m_smallSize) + m_oglTextSmall->renderText(textRect.x(), textRect.y(), str); + else + m_oglTextBig1->renderText(textRect.x(), textRect.y(), str); + } + } + + if (m_frequencyScale.subPointPositions.length() > 0) { + + glLineWidth(1); + glBegin(GL_LINES); + for (int i = 0; i < m_frequencyScale.subPointPositions.length(); i++) { + + glVertex3f(m_frequencyScale.subPointPositions.at(i), 1.0f, 0.0f); + glVertex3f(m_frequencyScale.subPointPositions.at(i), 3.0f, 0.0f); + } + glEnd(); + } + + glColor3f(0.94f, 0.22f, 0.43f); + + if (m_smallSize) + m_oglTextSmall->renderText(m_freqScalePanRect.width() - 30, textOffset_y, fstr); + else + m_oglTextBig1->renderText(m_freqScalePanRect.width() - 33, textOffset_y, fstr); +} + +void QGLReceiverPanel::renderPanadapterGrid() { + + //GRAPHICS_DEBUG << "render panadapter grid"; + glClear(GL_COLOR_BUFFER_BIT); + glLineStipple(1, 0x9999); + //glLineStipple(1, 0xCCCC); + glEnable(GL_LINE_STIPPLE); + glLineWidth(1.0f); + + // vertical lines + int len = m_frequencyScale.mainPointPositions.length(); + if (len > 0) { + + GLint x1 = m_panRect.left(); + GLint x2 = 1; + if (m_dBmScalePanRect.isValid()) x2 += m_dBmScalePanRect.width(); + + //GLint y1 = rect.top() + 1; + GLint y1 = 1; + GLint y2 = m_panRect.bottom() - 1; + + TGL2int *vertexArray = new TGL2int[len * 2]; + int vertexArrayLen = 0; + + TGL2int point1, point2; + point1.y = y1; + point2.y = y2; + for (int i = 0; i < len; i++) { + + GLint x = m_frequencyScale.mainPointPositions.at(i); + if (x < x2) continue; + x += x1; + point1.x = x; + point2.x = x; + vertexArray[vertexArrayLen++] = point1; + vertexArray[vertexArrayLen++] = point2; + } + + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(2, GL_INT, 0, vertexArray); + glDrawArrays(GL_LINES, 0, vertexArrayLen); + glDisableClientState(GL_VERTEX_ARRAY); + + delete[] vertexArray; + } + + // horizontal lines + len = m_dBmScale.mainPointPositions.length(); + if (len > 0) { + + TGL2float *vertexArray = new TGL2float[len * 2]; + int vertexArrayLen = 0; + + TGL2float point1, point2; + point1.x = m_panRect.left() + m_dBmScalePanRect.width(); + point2.x = m_panRect.right(); + + for (int i = 0; i < len; i++) { + + GLfloat y = m_dBmScale.mainPointPositions.at(i); + + point1.y = y; + point2.y = y; + + vertexArray[vertexArrayLen++] = point1; + vertexArray[vertexArrayLen++] = point2; + } + + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(2, GL_FLOAT, 0, vertexArray); + glDrawArrays(GL_LINES, 0, vertexArrayLen); + glDisableClientState(GL_VERTEX_ARRAY); + + delete[] vertexArray; + + } + glDisable(GL_LINE_STIPPLE); +} + +void QGLReceiverPanel::renderWaterfallVerticalScale() { + + QString str; + + int spacing = 7; + int fontHeight; + int fontMaxWidth; + if (m_smallSize) { + + fontHeight = m_fonts.smallFontMetrics->tightBoundingRect(".0s").height() + spacing; + fontMaxWidth = m_fonts.smallFontMetrics->boundingRect("000.0").width(); + } + else { + + fontHeight = m_fonts.bigFont1Metrics->tightBoundingRect(".0s").height() + spacing; + fontMaxWidth = m_fonts.bigFont1Metrics->boundingRect("000.0").width(); + } + + GLint width = m_secScaleWaterfallRect.width(); + GLint height = m_secScaleWaterfallRect.height(); + + qreal unit = (qreal)(height / qAbs(m_secWaterfallMax - m_secWaterfallMin)); + + m_secScale = getYRuler2(m_secScaleWaterfallRect, fontHeight, unit, m_secWaterfallMin, m_secWaterfallMax); + //m_secScale = getYRuler3(m_secScaleWaterfallRect, fontHeight, unit, m_secWaterfallMin, m_secWaterfallMax, 10.0f); + + glClear(GL_COLOR_BUFFER_BIT); + + QRect textRect(0, 0, fontMaxWidth, fontHeight); + if (m_smallSize) + textRect.moveLeft(3); + else + textRect.moveLeft(-1); + + int yOld = -textRect.height(); + + int len = m_secScale.mainPointPositions.length(); + int sublen = m_secScale.subPointPositions.length(); + + glViewport(0, 0, width, height); + setProjectionOrthographic(width, height); + + // draw the scale background + drawGLScaleBackground(QRect(0, 0, width, height), QColor(40, 40, 40, 180)); + + if (len > 0) { + + glColor3f(0.65f, 0.76f, 0.81f); + glLineWidth(1); + + glBegin(GL_LINES); + for (int i = 0; i < len; i++) { + + glVertex3f(width, m_secScale.mainPointPositions.at(i), 0.0f); // origin of the line + glVertex3f(width - 4, m_secScale.mainPointPositions.at(i), 0.0f); // ending point of the line + } + glEnd(); + + glColor3f(0.45f, 0.56f, 0.61f); + if (sublen > 0) { + + glBegin(GL_LINES); + for (int i = 0; i < sublen; i++) { + + glVertex3f(width, m_secScale.subPointPositions.at(i), 0.0f); // origin of the line + glVertex3f(width - 2, m_secScale.subPointPositions.at(i), 0.0f); // ending point of the line + } + glEnd(); + } + + glColor3f(0.95f, 0.96f, 0.91f); + for (int i = 0; i < len; i++) { + + textRect.moveBottom(m_secScale.mainPointPositions.at(i) + textRect.height()/2); + + if (textRect.y() >= yOld && textRect.bottom() <= (height - textRect.height())) { + + str = QString::number(m_secScale.mainPoints.at(i), 'f', 1); + if (m_smallSize) + m_oglTextSmall->renderText(textRect.x() + fontMaxWidth - m_fonts.smallFontMetrics->tightBoundingRect(str).width(), textRect.y(), str); + else + m_oglTextBig1->renderText(textRect.x() + fontMaxWidth - m_fonts.bigFont1Metrics->tightBoundingRect(str).width(), textRect.y(), str); + yOld = textRect.bottom(); + } + } + } + + textRect.moveTop(height - textRect.height()); + glColor3f(0.94f, 0.22f, 0.43f); + + str = QString("sec"); + if (m_smallSize) + m_oglTextSmall->renderText(textRect.x(), textRect.y(), str); + else + m_oglTextBig1->renderText(textRect.x() + 10, textRect.y(), str); + + glViewport(0, 0, size().width(), size().height()); + setProjectionOrthographic(size().width(), size().height()); +} + +//******************************************************************** + +void QGLReceiverPanel::getRegion(QPoint p) { + + //QRect mouse_rect(0, 0, 100, 100); + //mouse_rect.moveCenter(p); + /*if (m_lockedPanButtonRect.contains(p)) { + + m_mouseRegion = lockedPanButtonRegion; + } + else if (m_vfoToMidButtonRect.contains(p)) { + + m_mouseRegion = vfoToMidButtonRegion; + } + else if (m_midToVfoButtonRect.contains(p)) { + + m_mouseRegion = midToVfoButtonRegion; + }*/ + if (m_agcButtonRect.contains(p)) { + + m_mouseRegion = agcButtonRegion; + + /*if (m_displayTime.elapsed() >= 50) { + + m_displayTime.restart(); + update(); + }*/ + } + else if (m_freqScalePanRect.contains(p)) { + + m_mouseRegion = freqScalePanadapterRegion; + + /*if (m_displayTime.elapsed() >= 50) { + + m_displayTime.restart(); + update(); + }*/ + } + else if (m_dBmScalePanRect.contains(p)) { + + m_mouseRegion = dBmScalePanadapterRegion; + + /*if (m_displayTime.elapsed() >= 50) { + + m_displayTime.restart(); + update(); + }*/ + } + else if (qAbs(p.x() - m_filterRect.left()) < m_snapMouse && + m_panRect.contains(p) + ) { + m_mouseRegion = filterRegionLow; + m_mouseDownFilterFrequencyLo = m_filterLowerFrequency; + } + else if (qAbs(p.x() - m_filterRect.right()) < m_snapMouse && + m_panRect.contains(p) + ) { + m_mouseRegion = filterRegionHigh; + m_mouseDownFilterFrequencyHi = m_filterUpperFrequency; + } + else if (m_filterRect.contains(p)) { + + m_mouseRegion = filterRegion; + + /*if (m_displayTime.elapsed() >= 50) { + + m_displayTime.restart(); + update(); + }*/ + } + //else if (qAbs(p.y() - m_agcThresholdPixel) < m_snapMouse && !m_crossHairCursor) { + else if (qAbs(p.y() - m_agcThresholdPixel) < m_snapMouse) { + + m_mouseRegion = agcThresholdLine; + m_mouseDownAGCThreshold = m_agcThresholdOld; + } + //else if (qAbs(p.y() - m_agcHangLevelPixel) < m_snapMouse && !m_crossHairCursor) { + else if (qAbs(p.y() - m_agcHangLevelPixel) < m_snapMouse) { + + m_mouseRegion = agcHangLine; + m_mouseDownAGCHangLevel = m_agcHangLevelOld; + } + //else if (qAbs(p.y() - m_agcFixedGainLevelPixel) < m_snapMouse && !m_crossHairCursor) { + else if (qAbs(p.y() - m_agcFixedGainLevelPixel) < m_snapMouse) { + + m_mouseRegion = agcFixedGainLine; + m_mouseDownFixedGainLevel = -m_agcFixedGain; + } + else if (m_panRect.contains(p)) { + + m_mouseRegion = panadapterRegion; + + /*if (m_displayTime.elapsed() >= 50) { + + m_displayTime.restart(); + update(); + }*/ + } + else if (m_waterfallRect.contains(p)) { + + m_mouseRegion = waterfallRegion; + + /*if (m_displayTime.elapsed() >= 50) { + + m_displayTime.restart(); + update(); + }*/ + } + else + m_mouseRegion = elsewhere; + + //GRAPHICS_DEBUG << "region" << m_mouseRegion; +} + +void QGLReceiverPanel::resizeGL(int iWidth, int iHeight) { + + int width = (int)(iWidth/2) * 2; + int height = iHeight; + + if (width != m_oldWidth) { + + m_freqScalePanadapterRenew = true; + m_panGridRenew = true; + + m_oldWidth = width; + } + + m_spectrumVertexColorUpdate = true; + m_waterfallUpdate = true; + m_peakHoldBufferResize = true; + + glFinish(); + + m_resizeTime.restart(); + setupDisplayRegions(QSize(width, height)); + glViewport(0, 0, (GLsizei)width, (GLsizei)height); + + setProjectionOrthographic(width, height); +} + +void QGLReceiverPanel::setupDisplayRegions(QSize size) { + + m_displayTop = 0; + //m_displayTop = m_fonts.fontHeightSmallFont + 2; + int freqScaleRectHeight = 20; + //int dBmScaleWidth = 45; + + m_freqScalePanRect = QRect( + 0, + m_displayTop + qRound((size.height() - m_displayTop - freqScaleRectHeight) * m_freqRulerPosition), + size.width(), + freqScaleRectHeight); + + m_panRect = QRect( + 0, + m_displayTop, + size.width(), + m_freqScalePanRect.top() - m_displayTop); + + + if (m_panRect.height() != m_oldPanRectHeight) { + + m_dBmScalePanadapterRenew = true; + m_panGridRenew = true; + m_secScaleWaterfallRenew = true; + } + + m_oldPanRectHeight = m_panRect.height(); + m_panRectWidth = (GLint)m_panRect.width(); + m_displayCenterlineHeight = m_panRect.top() + (m_panRect.height() - 3); + + m_waterfallRect = QRect( + m_freqScalePanRect.left(), + m_freqScalePanRect.top() + m_freqScalePanRect.height(), + //m_freqScalePanRect.top(), + m_freqScalePanRect.width(), + //size.height() - m_displayTop - m_freqScalePanRect.top() - m_freqScalePanRect.height()); + size.height() - m_freqScalePanRect.top() - m_freqScalePanRect.height()); + //size.height() - m_freqScalePanRect.top()); + + m_waterfallUpdate = true; + + if ((m_panRect.height() + m_waterfallRect.height()) > m_bigHeight && m_panRect.width() > m_bigWidth) + m_smallSize = false; + else + m_smallSize = true; + + m_dBmScalePanRect = QRect( + m_panRect.left(), + m_displayTop, + 45, + m_panRect.height()); + + m_secScaleWaterfallRect = QRect( + m_waterfallRect.left(), + m_freqScalePanRect.top() + m_freqScalePanRect.height(), + 45, + m_waterfallRect.height()); + + m_secWaterfallMin = -(1.0/m_fps) * m_secScaleWaterfallRect.height(); + + m_freqScalePanadapterUpdate = true; + m_dBmScalePanadapterUpdate = true; + m_secScaleWaterfallUpdate = true; + m_panGridUpdate = true; + +// GRAPHICS_DEBUG << "***************************************************************************"; +// GRAPHICS_DEBUG << "receiver:" << m_receiver; +// GRAPHICS_DEBUG << "total size" << size.height(); +// GRAPHICS_DEBUG << "sizes (top, bottom, height):"; +// GRAPHICS_DEBUG << "panRect" << m_panRect.top() << m_panRect.bottom() << m_panRect.height(); +// //GRAPHICS_DEBUG << "panRect (H/W): " << m_panRect.height() << ": " << m_panRect.width(); +// GRAPHICS_DEBUG << "waterfallRect" << m_waterfallRect.top() << m_waterfallRect.bottom() << m_waterfallRect.height(); +// GRAPHICS_DEBUG << "freqScalePanRect" << m_freqScalePanRect.top() << m_freqScalePanRect.bottom() << m_freqScalePanRect.height(); +// GRAPHICS_DEBUG << "dBmScalePanRect" << m_dBmScalePanRect.top() << m_dBmScalePanRect.bottom() << m_dBmScalePanRect.height(); +// GRAPHICS_DEBUG << ""; + +} + +void QGLReceiverPanel::saveGLState() { + + glPushAttrib(GL_ALL_ATTRIB_BITS); + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); +} + +void QGLReceiverPanel::restoreGLState() { + + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + glPopAttrib(); +} + +void QGLReceiverPanel::showText(float x, float y, float z = 0.0f, const QString &text = "", bool smallText = true) { + + if (smallText) + m_oglTextSmall->renderText(x, y, z, text); + else + m_oglTextBig1->renderText(x, y, z, text); +} + +//******************************************************************** +// HMI control + +void QGLReceiverPanel::enterEvent(QEvent *event) { + + setFocus(Qt::MouseFocusReason); + + m_mousePos = QPoint(-1, -1); + m_mouseRegion = elsewhere; + + setCursor(Qt::BlankCursor); + update(); + + QGLWidget::enterEvent(event); +} + +void QGLReceiverPanel::leaveEvent(QEvent *event) { + + m_mousePos = QPoint(-100, -100); + m_mouseRegion = elsewhere; + + update(); + + QGLWidget::leaveEvent(event); +} + +void QGLReceiverPanel::wheelEvent(QWheelEvent* event) { + + //GRAPHICS_DEBUG << "wheelEvent"; + QPoint pos = event->pos(); + + if (event->buttons() == Qt::NoButton) getRegion(pos); + + double freqStep = set->getMouseWheelFreqStep(m_currentReceiver); + + switch (m_mouseRegion) { + + case panadapterRegion: + case waterfallRegion: + case filterRegion: + case filterRegionLow: + case filterRegionHigh: + + double delta = 0; + if (event->delta() < 0) + delta = -freqStep; + else if (event->delta() > 0) + delta = freqStep; + + if (!m_panLocked) { + + if (m_centerFrequency + delta > MAXFREQUENCY) + m_centerFrequency = MAXFREQUENCY; + else if (m_centerFrequency + delta < 0) + m_centerFrequency = 0; + else + // snap to the frequency step + m_centerFrequency = (long)(qRound((m_centerFrequency + delta) / qAbs(freqStep)) * qAbs(freqStep)); + + m_vfoFrequency = m_centerFrequency - m_deltaFrequency; + } + else { + + if (m_vfoFrequency + delta > m_centerFrequency + m_sampleRate/2) + m_vfoFrequency = m_centerFrequency + m_sampleRate/2; + else if (m_vfoFrequency + delta < m_centerFrequency - m_sampleRate/2) + m_vfoFrequency = m_centerFrequency - m_sampleRate/2; + else + // snap to the frequency step + m_vfoFrequency = (long)(qRound((m_vfoFrequency + delta) / qAbs(freqStep)) * qAbs(freqStep)); + + m_deltaFrequency = m_centerFrequency - m_vfoFrequency; + m_deltaF = (qreal)(1.0*m_deltaFrequency/m_sampleRate); + //GRAPHICS_DEBUG << "m_deltaFrequency: " << m_deltaFrequency; + } + + set->setCtrFrequency(this, 0, m_receiver, m_centerFrequency); + set->setVFOFrequency(this, 0, m_receiver, m_vfoFrequency); + + break; + } + + //updateGL(); + update(); +} + +void QGLReceiverPanel::mousePressEvent(QMouseEvent* event) { + + //GRAPHICS_DEBUG << "mousePressEvent"; + m_mousePos = event->pos(); + m_mouseDownPos = m_mousePos; + + getRegion(m_mousePos); + + if (m_mouseRegion == agcButtonRegion) { + + if (event->buttons() == Qt::LeftButton) { + + if (m_showAGCLines) { + + m_showAGCLines = false; + set->setAGCShowLines(this, m_receiver, false); + } + else { + + m_showAGCLines = true; + set->setAGCShowLines(this, m_receiver, true); + } + } + } + else if (m_mouseRegion == panadapterRegion || m_mouseRegion == waterfallRegion) { + + if (event->buttons() == Qt::LeftButton && m_receiver != set->getCurrentReceiver()) { + + set->setCurrentReceiver(this, m_receiver); + } + else if (event->buttons() == Qt::LeftButton && m_clickVFO) { + + m_crossHairCursor = false; + setCursor(Qt::OpenHandCursor); + m_dragMouse = true; + + double freqStep = set->getMouseWheelFreqStep(m_currentReceiver); + int dx = m_panRect.width()/2 - m_mousePos.x(); + qreal unit = (qreal)((m_sampleRate * m_freqScaleZoomFactor) / m_panRect.width()); + + m_vfoFrequency = (long)(qRound((m_centerFrequency - unit * dx) / qAbs(freqStep)) * qAbs(freqStep)); + + /*if (m_vfoFrequency > m_centerFrequency + m_sampleRate/2) + m_vfoFrequency = m_centerFrequency + m_sampleRate/2; + else if (m_vfoFrequency < m_centerFrequency - m_sampleRate/2) + m_vfoFrequency = m_centerFrequency - m_sampleRate/2;*/ + + m_deltaFrequency = m_centerFrequency - m_vfoFrequency; + m_deltaF = (qreal)(1.0*m_deltaFrequency/m_sampleRate); + + set->setVFOFrequency(this, 0, m_receiver, m_vfoFrequency); + update(); + } + else if (event->buttons() == Qt::LeftButton) { + + m_crossHairCursor = false; + setCursor(Qt::OpenHandCursor); + m_dragMouse = true; + } + else if (event->buttons() == Qt::RightButton) { + + showRadioPopup(true); + } + } + else if (m_mouseRegion == filterRegion) { + + //setCursor(Qt::ArrowCursor); + if (event->buttons() == Qt::LeftButton) + m_highlightFilter = true; + } + else if (m_mouseRegion == freqScalePanadapterRegion) { + + m_rulerMouseDownPos = m_freqScalePanRect.topLeft(); + + if (event->buttons() == Qt::RightButton) setCursor(Qt::SplitHCursor); + update(); + + return; + } + else if (m_mouseRegion == dBmScalePanadapterRegion) { + + m_rulerMouseDownPos = m_dBmScalePanRect.topLeft(); + + if (event->buttons() == Qt::RightButton) + setCursor(Qt::SplitVCursor); + update(); + + return; + } + + update(); +} + +void QGLReceiverPanel::mouseReleaseEvent(QMouseEvent *event) { + + //GRAPHICS_DEBUG << "mouseReleaseEvent"; + m_mousePos = event->pos(); + m_mouseDownPos = m_mousePos; + + getRegion(m_mousePos); + + if (m_mouseRegion == freqScalePanadapterRegion) { + + return; + } + //else if (m_mouseRegion == panadapterRegion || m_mouseRegion == waterfallRegion) { + //} + m_dragMouse = false; + m_crossHairCursor = true; + if (m_crossHair) + setCursor(Qt::BlankCursor); + else + setCursor(Qt::ArrowCursor); + + update(); +} + +void QGLReceiverPanel::mouseDoubleClickEvent(QMouseEvent *event) { + + //GRAPHICS_DEBUG << "mouseDoubleClickEvent"; + m_mousePos = event->pos(); + m_mouseDownPos = m_mousePos; + + getRegion(m_mousePos); + + if (m_mouseRegion == panadapterRegion) { + + if (event->buttons() == Qt::LeftButton) { + + //set->showRadioPopupWidget(); +// if (!band160mBtn->isVisible()) +// band160mBtn->show(); +// else +// band160mBtn->hide(); + } + } +} + +void QGLReceiverPanel::mouseMoveEvent(QMouseEvent* event) { + + //GRAPHICS_DEBUG << "mouseMoveEvent"; + QPoint pos = event->pos(); + m_mousePos = event->pos(); + + if (event->buttons() == Qt::NoButton) getRegion(pos); + + switch (m_mouseRegion) { + + //case lockedPanButtonRegion: + //case vfoToMidButtonRegion: + //case midToVfoButtonRegion: + + //if (m_crossHairCursor) setCursor(Qt::ArrowCursor); + + // break; + + case agcThresholdLine: + + //GRAPHICS_DEBUG << "agcThresholdLine Rx:" << m_receiver; + if (!m_showAGCLines || (m_agcMode == (AGCMode) agcOFF)) + break; + + m_crossHairCursor = false; + setCursor(Qt::SizeVerCursor); + + if (event->buttons() == Qt::LeftButton) { + + QPoint dPos = m_mouseDownPos - pos; + + qreal unit = qAbs(m_dBmPanMax - m_dBmPanMin) / m_panRect.height(); + qreal dAGCThreshold = dPos.y() * unit; + + m_agcThresholdNew = m_mouseDownAGCThreshold + dAGCThreshold; + if (m_agcThresholdNew > m_dBmPanMax-2) + m_agcThresholdNew = m_dBmPanMax-2; + + if (m_agcThresholdNew < m_dBmPanMin+2) + m_agcThresholdNew = m_dBmPanMin+2; + + set->setAGCThreshold_dB(this, m_receiver, m_agcThresholdNew); + } + break; + + case agcHangLine: + + //GRAPHICS_DEBUG << "agcHangLine Rx:" << m_receiver; + if (!m_showAGCLines || (m_agcMode == (AGCMode) agcOFF) || !m_agcHangEnabled) + break; + + m_crossHairCursor = false; + setCursor(Qt::SizeVerCursor); + + if (event->buttons() == Qt::LeftButton) { + + QPoint dPos = m_mouseDownPos - pos; + + qreal unit = qAbs(m_dBmPanMax - m_dBmPanMin) / m_panRect.height(); + qreal dAGCThreshold = dPos.y() * unit; + + m_agcHangLevelNew = m_mouseDownAGCHangLevel + dAGCThreshold; + + if (m_agcHangLevelNew > m_dBmPanMax-2) + m_agcHangLevelNew = m_dBmPanMax-2; + + if (m_agcHangLevelNew < m_dBmPanMin+2) + m_agcHangLevelNew = m_dBmPanMin+2; + + set->setAGCHangLevel_dB(this, m_receiver, m_agcHangLevelNew); + //GRAPHICS_DEBUG << "set m_agcHangLevelNew = " << m_agcHangLevelNew; + } + break; + + case agcFixedGainLine: + + //GRAPHICS_DEBUG << "agcFixedGainLine Rx:" << m_receiver; + if (!m_showAGCLines || (m_agcMode != (AGCMode) agcOFF)) + break; + + m_crossHairCursor = false; + setCursor(Qt::SizeVerCursor); + + if (event->buttons() == Qt::LeftButton) { + + QPoint dPos = m_mouseDownPos - pos; + + qreal unit = qAbs(m_dBmPanMax - m_dBmPanMin) / m_panRect.height(); + qreal dAGCFixedGain = dPos.y() * unit; + + qreal agcFixedGain = m_mouseDownFixedGainLevel + dAGCFixedGain; + + if (agcFixedGain > m_dBmPanMax-2) + agcFixedGain = m_dBmPanMax-2; + + if (agcFixedGain < m_dBmPanMin+2) + agcFixedGain = m_dBmPanMin+2; + + set->setAGCFixedGain_dB(this, m_receiver, -agcFixedGain); + } + break; + + case panadapterRegion: + case waterfallRegion: + + //GRAPHICS_DEBUG << "panadapterRegion Rx:" << m_receiver; + if (!m_dragMouse) { + + m_crossHairCursor = true; + if (m_crossHair) + setCursor(Qt::BlankCursor); + else + setCursor(Qt::ArrowCursor); + } + + if (event->buttons() == Qt::LeftButton) { + + QPoint dPos = m_mouseDownPos - pos; + + qreal unit = (qreal)((m_sampleRate * m_freqScaleZoomFactor) / m_freqScalePanRect.width()); + qreal deltaFreq = unit * dPos.x(); + + long newFrequency = m_centerFrequency + deltaFreq; + if (newFrequency > MAXFREQUENCY) + newFrequency = MAXFREQUENCY; + else + if (newFrequency + deltaFreq < 0) + newFrequency = 0; + else { + + if (m_panLocked) { + + if (m_vfoFrequency > m_centerFrequency + m_sampleRate/2) + m_vfoFrequency = m_centerFrequency + m_sampleRate/2; + else if (m_vfoFrequency < m_centerFrequency - m_sampleRate/2) + m_vfoFrequency = m_centerFrequency - m_sampleRate/2; + + m_vfoFrequency -= deltaFreq; + } + else + m_centerFrequency += deltaFreq; + } + + if (m_panLocked) { + + set->setVFOFrequency(this, 0, m_receiver, m_vfoFrequency); + + m_deltaFrequency = m_centerFrequency - m_vfoFrequency; + m_deltaF = (qreal)(1.0*m_deltaFrequency/m_sampleRate); + } + else { + + m_vfoFrequency = m_centerFrequency - m_deltaFrequency; + + set->setVFOFrequency(this, 0, m_receiver, m_vfoFrequency); + set->setCtrFrequency(this, 0, m_receiver, m_centerFrequency); + } + + m_mouseDownPos = pos; + + m_displayCenterlineHeight = m_panRect.top() + (m_panRect.height() - 3); + + m_showFilterLeftBoundary = false; + m_showFilterRightBoundary = false; + m_highlightFilter = false; + +// if (m_displayTime.elapsed() >= 50) { +// +// m_displayTime.restart(); +// update(); +// } + } + m_displayCenterlineHeight = m_panRect.top() + (m_panRect.height() - 3); + + m_showFilterLeftBoundary = false; + m_showFilterRightBoundary = false; + m_highlightFilter = false; + break; + + //case waterfallRegion: + + //GRAPHICS_DEBUG << "waterfallRegion Rx:" << m_receiver; + //m_crossHairCursor = true; + //setCursor(Qt::BlankCursor); + + /*if (event->buttons() == Qt::LeftButton) { + + m_cameraAngle += (pos - m_mouseDownPos); + m_mouseDownPos = pos; + } + else + if (event->buttons() == Qt::RightButton) { + + m_cameraDistance += (pos.y() - m_mouseDownPos.y()) * 0.2f; + m_mouseDownPos = pos; + } + setCursor(Qt::ArrowCursor);*/ + //update(); + //break; + + case dBmScalePanadapterRegion: + //GRAPHICS_DEBUG << "dBmScalePanadapterRegion"; + if (event->buttons() == Qt::LeftButton) { + + QPoint dPos = m_mouseDownPos - pos; + qreal unit = (qreal)(qAbs(m_dBmPanMax - m_dBmPanMin) / m_panRect.height()); + + qreal newMin = m_dBmPanMin - unit * dPos.y(); + qreal newMax = m_dBmPanMax - unit * dPos.y(); + + if (newMin > MINDBM && newMax < MAXDBM) { + + m_dBmPanMin = newMin; + m_dBmPanMax = newMax; + + set->setdBmPanScaleMin(m_receiver, m_dBmPanMin); + set->setdBmPanScaleMax(m_receiver, m_dBmPanMax); + } + + m_mouseDownPos = pos; + m_dBmScalePanadapterUpdate = true; + m_panGridUpdate = true; + m_peakHoldBufferResize = true; + +// if (m_displayTime.elapsed() >= 50) { +// +// m_displayTime.restart(); +// update(); +// } + } + else + if (event->buttons() == Qt::RightButton && + event->modifiers() == Qt::ControlModifier) { + + QPoint dPos = m_mouseDownPos - pos; + if (dPos.y() > 0) + m_dBmPanDelta = 0.5f; + else if (dPos.y() < 0) + m_dBmPanDelta = -0.5f; + + m_dBmPanMin += m_dBmPanDelta; + m_dBmPanMax -= m_dBmPanDelta; + + if (qAbs(m_dBmPanMax - m_dBmPanMin) < 10) { + + m_dBmPanMin -= m_dBmPanDelta; + m_dBmPanMax += m_dBmPanDelta; + } + if (m_dBmPanMin < MINDBM) m_dBmPanMin = MINDBM; + if (m_dBmPanMax > MAXDBM) m_dBmPanMax = MAXDBM; + + set->setdBmPanScaleMin(m_receiver, m_dBmPanMin); + set->setdBmPanScaleMax(m_receiver, m_dBmPanMax); + + m_mouseDownPos = pos; + m_dBmScalePanadapterUpdate = true; + m_panGridUpdate = true; + m_peakHoldBufferResize = true; + +// if (m_displayTime.elapsed() >= 50) { +// +// m_displayTime.restart(); +// update(); +// } + } + if (event->buttons() == Qt::RightButton) { + + QPoint dPos = m_mouseDownPos - pos; + if (dPos.y() > 0) + m_dBmPanDelta = 0.5f; + else if (dPos.y() < 0) + m_dBmPanDelta = -0.5f; + + m_dBmPanMax -= m_dBmPanDelta; + + if (qAbs(m_dBmPanMax - m_dBmPanMin) < 10) { + + m_dBmPanMin -= m_dBmPanDelta; + m_dBmPanMax += m_dBmPanDelta; + } + if (m_dBmPanMin < MINDBM) m_dBmPanMin = MINDBM; + if (m_dBmPanMax > MAXDBM) m_dBmPanMax = MAXDBM; + + set->setdBmPanScaleMin(m_receiver, m_dBmPanMin); + set->setdBmPanScaleMax(m_receiver, m_dBmPanMax); + + m_mouseDownPos = pos; + m_dBmScalePanadapterUpdate = true; + m_panGridUpdate = true; + m_peakHoldBufferResize = true; + +// if (m_displayTime.elapsed() >= 50) { +// +// m_displayTime.restart(); +// update(); +// } + } + else { + + setCursor(Qt::ArrowCursor); + +// if (m_displayTime.elapsed() >= 50) { +// +// m_displayTime.restart(); +// update(); +// } + } + break; + + case freqScalePanadapterRegion: + //GRAPHICS_DEBUG << "freqScalePanadapterRegion Rx" << m_receiver; + if (event->buttons() == Qt::LeftButton && + event->modifiers() == Qt::ShiftModifier) { + + QPoint dPos = m_mouseDownPos - pos; + int bottom_y = height() - m_freqScalePanRect.height(); + int new_y = m_rulerMouseDownPos.y() - dPos.y(); + + if (new_y < m_panRect.top() + m_panSpectrumMinimumHeight) + new_y = m_panRect.top() + m_panSpectrumMinimumHeight; + if (new_y > bottom_y) + new_y = bottom_y; + + m_freqRulerPosition = (float)(new_y - m_panRect.top()) / (bottom_y - m_panRect.top()); + set->setFreqRulerPosition(this, m_receiver, m_freqRulerPosition); + +// if (m_displayTime.elapsed() >= 50) { +// +// m_displayTime.restart(); +// update(); +// } + } + else if (event->buttons() == Qt::LeftButton) { + + QPoint dPos = m_mouseDownPos - pos; + + qreal unit = (qreal)((m_sampleRate * m_freqScaleZoomFactor) / m_freqScalePanRect.width()); + qreal deltaFreq = unit * dPos.x(); + + /*if (m_freqScaleZoomFactor < 1.0) { + + } + else {*/ + + long newFrequency = m_centerFrequency + deltaFreq; + if (newFrequency > MAXFREQUENCY) + newFrequency = MAXFREQUENCY; + else + if (newFrequency + deltaFreq < 0) + newFrequency = 0; + else { + + m_centerFrequency += deltaFreq; + } + + if (!m_panLocked) { + + m_vfoFrequency = m_centerFrequency - m_deltaFrequency; + set->setVFOFrequency(this, 0, m_receiver, m_vfoFrequency); + set->setCtrFrequency(this, 0, m_receiver, m_centerFrequency); + } + + //set->setVFOFrequency(this, 0, m_receiver, m_vfoFrequency); + //set->setCtrFrequency(this, 0, m_receiver, m_centerFrequency); + + else { + + m_deltaFrequency = m_centerFrequency - m_vfoFrequency; + m_deltaF = (qreal)(1.0*m_deltaFrequency/m_sampleRate); + + qreal vol = set->getMainVolume(m_receiver); + set->setMainVolume(this, m_receiver, 0.0f); + set->setCtrFrequency(this, 0, m_receiver, m_centerFrequency); + set->setNCOFrequency(this, true, m_receiver, -m_deltaFrequency); + set->setMainVolume(this, m_receiver, vol); + } + + //set->setCtrFrequency(this, 0, m_receiver, m_centerFrequency); + //} + m_mouseDownPos = pos; + + m_displayCenterlineHeight = m_panRect.top() + (m_panRect.height() - 3); + + m_showFilterLeftBoundary = false; + m_showFilterRightBoundary = false; + m_highlightFilter = false; + } + else + if (event->buttons() == Qt::RightButton) { + + QPoint dPos = m_mouseDownPos - pos; + if (dPos.x() > 0) + m_freqScaleZoomFactor += 0.01; + else if (dPos.x() < 0) + m_freqScaleZoomFactor -= 0.01; + + if (m_freqScaleZoomFactor > 1.0) m_freqScaleZoomFactor = 1.0; + if (m_freqScaleZoomFactor < 0.05) m_freqScaleZoomFactor = 0.05; + //if (m_freqScaleZoomFactor < 0.15) m_freqScaleZoomFactor = 0.15; + + m_mouseDownPos = pos; + m_freqScalePanadapterUpdate = true; + m_panGridUpdate = true; + m_peakHoldBufferResize = true; + +// if (m_displayTime.elapsed() >= 50) { +// +// m_displayTime.restart(); +// update(); +// } + } + else + setCursor(Qt::ArrowCursor); + + m_showFilterLeftBoundary = false; + m_showFilterRightBoundary = false; + m_highlightFilter = false; + break; + + case filterRegionLow: + + setCursor(Qt::SizeHorCursor); + m_showFilterLeftBoundary = true; + if (event->buttons() == Qt::LeftButton) { + + QPoint dPos = m_mouseDownPos - pos; + qreal dFreq = (qreal)(dPos.x() * m_sampleRate * m_freqScaleZoomFactor) / m_panRect.width(); + + m_filterLowerFrequency = qRound(m_mouseDownFilterFrequencyLo - dFreq); + set->setRXFilter(this, m_receiver, m_filterLowerFrequency, m_filterUpperFrequency); + +// if (m_displayTime.elapsed() >= 50) { +// +// m_displayTime.restart(); +// update(); +// } + } + + m_highlightFilter = false; + break; + + case filterRegionHigh: + + setCursor(Qt::SizeHorCursor); + m_showFilterRightBoundary = true; + if (event->buttons() == Qt::LeftButton) { + + QPoint dPos = m_mouseDownPos - pos; + qreal dFreq = (qreal)(dPos.x() * m_sampleRate * m_freqScaleZoomFactor) / m_panRect.width(); + + m_filterUpperFrequency = qRound(m_mouseDownFilterFrequencyHi - dFreq); + set->setRXFilter(this, m_receiver, m_filterLowerFrequency, m_filterUpperFrequency); + +// if (m_displayTime.elapsed() >= 50) { +// +// m_displayTime.restart(); +// update(); +// } + } + + m_highlightFilter = false; + break; + + case filterRegion: + + setCursor(Qt::ArrowCursor); + m_displayCenterlineHeight = m_panRect.top() + (size().height() - 3); + + if (event->buttons() == Qt::LeftButton) { + + m_highlightFilter = true; + QPoint dPos = m_mouseDownPos - pos; + qreal dFreq = (qreal)(dPos.x() * m_sampleRate * m_freqScaleZoomFactor) / m_panRect.width(); + + m_filterUpperFrequency = qRound(m_mouseDownFilterFrequencyHi - dFreq); + m_filterLowerFrequency = qRound(m_mouseDownFilterFrequencyLo - dFreq); + set->setRXFilter(this, m_receiver, m_filterLowerFrequency, m_filterUpperFrequency); + +// if (m_displayTime.elapsed() >= 50) { +// +// m_displayTime.restart(); +// update(); +// } + } + m_showFilterLeftBoundary = false; + m_showFilterRightBoundary = false; + break; + + case elsewhere: + //GRAPHICS_DEBUG << "elsewhere"; + break; + } + + if (m_displayTime.elapsed() >= 50) { + + m_displayTime.restart(); + update(); + } +} + +void QGLReceiverPanel::keyPressEvent(QKeyEvent* event) { + + //GRAPHICS_DEBUG << "keyPressEvent"; + if (event->key() == Qt::Key_Control) { + + //m_keyCTRLpressed = true; + //GRAPHICS_DEBUG << "m_keyCTRLpressed =" << m_keyCTRLpressed; + //printf("Ry %f\n",ry); + //ry+=10.0f; + } + else if (event->key() == Qt::Key_T) { + + //printf("Ry %f\n",ry); + //ry-=10.0f; + } + else if (event->key() == Qt::Key_P) { + + //drawTeapot = !drawTeapot; + } + else if (event->key() == Qt::Key_W) { + + //approach -= 0.1f; + } + else if (event->key() == Qt::Key_S) { + + //approach += 0.1f; + } + else { + + //m_keyCTRLpressed = false; + //GRAPHICS_DEBUG << "m_keyCTRLpressed =" << m_keyCTRLpressed; + //event->ignore(); + } + + QWidget::keyPressEvent(event); + //updateGL(); + update(); +} + +//void QGLReceiverPanel::timerEvent(QTimerEvent *) { +// +// update(); +//} + +//******************************************************************** + +void QGLReceiverPanel::setSpectrumSize(QObject *sender, int value) { + + Q_UNUSED(sender) + + if (m_dataEngineState == QSDR::DataEngineDown) { + + GRAPHICS_DEBUG << "set spectrum size to: " << value; + m_spectrumSize = value; + update(); + } +} + +void QGLReceiverPanel::setCtrFrequency(QObject *sender, int mode, int rx, long freq) { + + Q_UNUSED(sender) + Q_UNUSED(mode) + + //if (sender == this) return; + if (m_receiver != rx) return; + + if (m_peakHold) { + + //spectrumBufferMutex.lock(); + m_panPeakHoldBins.clear(); + m_panPeakHoldBins.resize(m_panSpectrumBinsLength); + m_panPeakHoldBins.fill(-500.0); + //spectrumBufferMutex.unlock(); + } + + for (int i = 0; i < set->getNumberOfReceivers(); i++) { + + m_rxDataList[i].ctrFrequency = freq; + } + + //GRAPHICS_DEBUG << "set center F = " << freq; + m_centerFrequency = freq; + m_freqScalePanadapterUpdate = true; + m_panGridUpdate = true; + update(); +} + +void QGLReceiverPanel::setVFOFrequency(QObject *sender, int mode, int rx, long freq) { + + Q_UNUSED(sender) + Q_UNUSED(mode) + + //if (sender == this) return; + if (m_receiver != rx) return; + + if (m_peakHold) { + + //spectrumBufferMutex.lock(); + m_panPeakHoldBins.clear(); + m_panPeakHoldBins.resize(m_panSpectrumBinsLength); + m_panPeakHoldBins.fill(-500.0); + //spectrumBufferMutex.unlock(); + } + + for (int i = 0; i < set->getNumberOfReceivers(); i++) { + + m_rxDataList[i].vfoFrequency = freq; + } + + //GRAPHICS_DEBUG << "set vfo F = " << freq; + m_vfoFrequency = freq; + if (m_vfoFrequency > m_centerFrequency + m_sampleRate/2) + m_vfoFrequency = m_centerFrequency + m_sampleRate/2; + else if (m_vfoFrequency < m_centerFrequency - m_sampleRate/2) + m_vfoFrequency = m_centerFrequency - m_sampleRate/2; + + m_deltaFrequency = m_centerFrequency - m_vfoFrequency; + m_deltaF = (qreal)(1.0*m_deltaFrequency/m_sampleRate); + + m_freqScalePanadapterUpdate = true; + m_panGridUpdate = true; + update(); +} + +void QGLReceiverPanel::setVfoToMidFrequency() { + + m_vfoFrequency = m_centerFrequency; + m_deltaFrequency = 0; + m_deltaF = 0; + + set->setVFOFrequency(this, 0, m_receiver, m_vfoFrequency); + set->setNCOFrequency(this, false, m_receiver, 0); +} + +void QGLReceiverPanel::setMidToVfoFrequency() { + + m_centerFrequency = m_vfoFrequency; + m_deltaFrequency = 0; + m_deltaF = 0; + + set->setCtrFrequency(this, 0, m_receiver, m_centerFrequency); + set->setNCOFrequency(this, false, m_receiver, 0); +} + +void QGLReceiverPanel::setFilterFrequencies(QObject *sender, int rx, qreal lo, qreal hi) { + + Q_UNUSED(sender) + + if (m_receiver != rx) return; + + m_filterLowerFrequency = lo; + m_filterUpperFrequency = hi; + m_filterChanged = true; + update(); +} + +void QGLReceiverPanel::setCurrentReceiver(QObject *sender, int value) { + + Q_UNUSED(sender) + + m_currentReceiver = value; + m_panGridUpdate = true; + update(); +} + +void QGLReceiverPanel::freqRulerPositionChanged(QObject *sender, int rx, float pos) { + + Q_UNUSED (sender) + + if (rx == m_receiver) { + + m_freqRulerPosition = pos; + + setupDisplayRegions(size()); + update(); + } +} + +void QGLReceiverPanel::setSpectrumBuffer(int rx, const qVectorFloat& buffer) { + + if (m_receiver != rx) return; + + QVector specBuf(m_spectrumSize); + QVector waterBuf(m_spectrumSize); + waterBuf = buffer; + + + if (m_dataEngineState == QSDR::DataEngineUp) { + + if (m_spectrumAveraging) { + + spectrumBufferMutex.lock(); + specBuf = buffer; + averager->ProcessDBAverager(specBuf, specBuf); + computeDisplayBins(specBuf, waterBuf); + spectrumBufferMutex.unlock(); + } + else { + + specBuf = buffer; + if (m_dataEngineState == QSDR::DataEngineUp) + computeDisplayBins(specBuf, waterBuf); + } + } +} + +void QGLReceiverPanel::computeDisplayBins(QVector& buffer, QVector& waterfallBuffer) { + + //int m_sampleSize = 0; + int deltaSampleSize = 0; + int idx = 0; + int lIdx = 0; + int rIdx = 0; + qreal localMax; + + if (m_serverMode == QSDR::ChirpWSPRFile) { + + m_sampleSize = (int)floor(2 * BUFFER_SIZE * m_freqScaleZoomFactor); + deltaSampleSize = 2 * BUFFER_SIZE - m_sampleSize; + } + else { + + m_sampleSize = (int)floor(m_fftMult * m_spectrumSize * m_freqScaleZoomFactor); + deltaSampleSize = m_spectrumSize - m_sampleSize; + } + + if (m_receiver == 0) { + + if (m_sampleSize < 2048) { + + if (m_fftMult == 1) { + + GRAPHICS_DEBUG << "set sample size to 8192"; + set->setSampleSize(this, 0, 8192); + m_dBmPanLogGain += 6.0; + m_fftMult = 2; + + return; + } + else if (m_fftMult == 2) { + + GRAPHICS_DEBUG << "set sample size to 16384"; + set->setSampleSize(this, 0, 16384); + m_dBmPanLogGain += 6.0; + m_fftMult = 4; + + return; + } + else if (m_fftMult == 4) { + + GRAPHICS_DEBUG << "set sample size to 32768"; + set->setSampleSize(this, 0, 32768); + m_dBmPanLogGain += 6.0; + m_fftMult = 8; + + return; + } + } + else if (m_sampleSize > 4096) { + + if (m_fftMult == 2) { + + GRAPHICS_DEBUG << "set sample size to 4096"; + set->setSampleSize(this, 0, 4096); + m_dBmPanLogGain -= 6.0; + m_fftMult = 1; + + return; + } + else if (m_fftMult == 4) { + + GRAPHICS_DEBUG << "set sample size to 8192"; + set->setSampleSize(this, 0, 8192); + m_dBmPanLogGain -= 6.0; + m_fftMult = 2; + + return; + } + else if (m_fftMult == 8) { + + GRAPHICS_DEBUG << "set sample size to 16384"; + set->setSampleSize(this, 0, 16384); + m_dBmPanLogGain -= 6.0; + m_fftMult = 4; + + return; + } + } + } + + m_panScale = (qreal)(1.0 * m_sampleSize / m_panRectWidth); + m_scaleMultOld = m_scaleMult; + + if (m_panScale < 0.125) { + m_scaleMult = 0.0625; + } + else if (m_panScale < 0.25) { + m_scaleMult = 0.125; + } + else if (m_panScale < 0.5) { + m_scaleMult = 0.25; + } + else if (m_panScale < 1.0) { + m_scaleMult = 0.5; + } + else { + m_scaleMult = 1.0; + } + + m_panSpectrumBinsLength = (GLint)(m_scaleMult * m_panRectWidth); + + /*if (m_sampleSize != m_oldSampleSize) { + + GRAPHICS_DEBUG << "m_panSpectrumBinsLength = " << m_panSpectrumBinsLength; + GRAPHICS_DEBUG << "m_sampleSize = " << m_sampleSize; + GRAPHICS_DEBUG << "deltaSampleSize = " << deltaSampleSize; + GRAPHICS_DEBUG << ""; + + m_oldSampleSize = m_sampleSize; + }*/ + + if (m_scaleMultOld != m_scaleMult) { + + m_waterfallUpdate = true; + } + + m_waterfallPixel.clear(); + m_waterfallPixel.resize(4 * m_panRectWidth); + + m_panadapterBins.clear(); + + if (m_peakHoldBufferResize) { + + //spectrumBufferMutex.lock(); + m_panPeakHoldBins.clear(); + m_panPeakHoldBins.resize(m_panSpectrumBinsLength); + m_panPeakHoldBins.fill(-300.0); + //spectrumBufferMutex.unlock(); + + m_peakHoldBufferResize = false; + } + + for (int i = 0; i < m_panSpectrumBinsLength; i++) { + + //qreal max; + idx = 0; + lIdx = (int)qFloor((qreal)(i * m_panScale / m_scaleMult)); + rIdx = (int)qFloor((qreal)(i * m_panScale / m_scaleMult) + m_panScale / m_scaleMult); + + // max value; later we try mean value also! + localMax = -10000.0F; + for (int j = lIdx; j < rIdx; j++) { + + if (buffer.at(j) > localMax) { + + localMax = buffer.at(j); + idx = j; + } + } + // shift the beginning of the bins by half of the difference between + // full spectrum size and reduced spectrum size due to zooming + idx += deltaSampleSize/2; + + QColor pColor; + if (m_mercuryAttenuator) { + + m_panadapterBins << buffer.at(idx) - m_dBmPanMin - m_dBmPanLogGain - 20.0f; + pColor = getWaterfallColorAtPixel(waterfallBuffer.at(idx) - m_dBmPanLogGain - 20.0f); + } + else { + + m_panadapterBins << buffer.at(idx) - m_dBmPanMin - m_dBmPanLogGain; + pColor = getWaterfallColorAtPixel(waterfallBuffer.at(idx) - m_dBmPanLogGain); + } + + if (m_peakHold && (m_panadapterBins.at(i) > m_panPeakHoldBins.at(i))) { + + m_panPeakHoldBins[i] = m_panadapterBins.at(i); + } + + + TGL_ubyteRGBA color; + color.red = (uchar)(pColor.red()); + color.green = (uchar)(pColor.green()); + color.blue = (uchar)(pColor.blue()); + color.alpha = 255; + + for (int j = 0; j < (int)(1/m_scaleMult); j++) { + + m_waterfallPixel[(int)(i/m_scaleMult) + j] = color; + } + } + m_waterfallDisplayUpdate = true; + update(); +} + +// get waterfall colors - taken from PowerSDR/KISS Konsole +QColor QGLReceiverPanel::getWaterfallColorAtPixel(qreal value) { + + QColor color; + //int r = 0; int g = 0; int b = 0; + int r, g, b; + int lowerThreshold = (int)m_dBmPanMin - m_waterfallOffsetLo; + int upperThreshold = (int)m_dBmPanMax + m_waterfallOffsetHi; + + float offset; + float globalRange; + float localRange; + float percent; + + switch (m_waterfallMode) { + + case (WaterfallColorMode) Simple: + + if (value <= lowerThreshold) + color = m_waterfallLoColor; + else + if (value >= upperThreshold) + color = QColor(255, 255, 255);//m_waterfallHiColor; + else { + + percent = (value - lowerThreshold) / (upperThreshold - lowerThreshold); + if (percent <= 0.5) { // use a gradient between low and mid colors + + percent *= 2; + + r = (int)((1 - percent) * m_waterfallLoColor.red() + percent * m_waterfallMidColor.red()); + g = (int)((1 - percent) * m_waterfallLoColor.green() + percent * m_waterfallMidColor.green()); + b = (int)((1 - percent) * m_waterfallLoColor.blue() + percent * m_waterfallMidColor.blue()); + } + else { // use a gradient between mid and high colors + + percent = (float)(percent - 0.5) * 2; + + r = (int)((1 - percent) * m_waterfallMidColor.red() + percent * 255);//m_waterfallHiColor.red()); + g = (int)((1 - percent) * m_waterfallMidColor.green() + percent * 255);//m_waterfallHiColor.green()); + b = (int)((1 - percent) * m_waterfallMidColor.blue() + percent * 255);//m_waterfallHiColor.blue()); + } + + if (r > 255) r = 255; + if (g > 255) g = 255; + if (b > 255) b = 255; + color = QColor(r, g, b, m_waterfallAlpha); + } + + break; + + case (WaterfallColorMode) Enhanced: + + if (value <= lowerThreshold) + color = m_waterfallLoColor; + else + if (value >= upperThreshold) + color = m_waterfallHiColor; + else { + + offset = value - lowerThreshold; + globalRange = offset / m_waterfallColorRange; // value from 0.0 to 1.0 where 1.0 is high and 0.0 is low. + + if (globalRange < (float)2/9) { // background to blue + + localRange = globalRange / ((float)2/9); + r = (int)((1.0 - localRange) * m_waterfallLoColor.red()); + g = (int)((1.0 - localRange) * m_waterfallLoColor.green()); + b = (int)(m_waterfallLoColor.blue() + localRange * (255 - m_waterfallLoColor.blue())); + } + else + if (globalRange < (float)3/9) { // blue to blue-green + + localRange = (globalRange - (float)2/9) / ((float)1/9); + r = 0; + g = (int)(localRange * 255); + b = 255; + } + else + if (globalRange < (float)4/9) { // blue-green to green + + localRange = (globalRange - (float)3/9) / ((float)1/9); + r = 0; + g = 255; + b = (int)((1.0 - localRange) * 255); + } + else + if (globalRange < (float)5/9) { // green to red-green + + localRange = (globalRange - (float)4/9) / ((float)1/9); + r = (int)(localRange * 255); + g = 255; + b = 0; + } + else + if (globalRange < (float)7/9) { // red-green to red + + localRange = (globalRange - (float)5/9) / ((float)2/9); + r = 255; + g = (int)((1.0 - localRange) * 255); + b = 0; + } + else + if (globalRange < (float)8/9) { // red to red-blue + + localRange = (globalRange - (float)7/9) / ((float)1/9); + r = 255; + g = 0; + b = (int)(localRange * 255); + } + else { // red-blue to purple end + + localRange = (globalRange - (float)8/9) / ((float)1/9); + r = (int)((0.75 + 0.25 * (1.0 - localRange)) * 255); + g = (int)(localRange * 255 * 0.5); + b = 255; + } + if (r > 255) r = 255; + if (g > 255) g = 255; + if (b > 255) b = 255; + if (r < 0) r = 0; + if (g < 0) g = 0; + if (b < 0) b = 0; + color = QColor(r, g, b, m_waterfallAlpha); + } + + break; + } + + return color; +} + +void QGLReceiverPanel::setFramesPerSecond(QObject* sender, int rx, int value) { + + Q_UNUSED(sender) + + if (m_receiver != rx) return; + + m_fps = value; + + m_secWaterfallMin = -(1.0/m_fps) * m_secScaleWaterfallRect.height(); + m_secScaleWaterfallRenew = true; + m_secScaleWaterfallUpdate = true; + update(); +} + +void QGLReceiverPanel::systemStateChanged( + QObject *sender, + QSDR::_Error err, + QSDR::_HWInterfaceMode hwmode, + QSDR::_ServerMode mode, + QSDR::_DataEngineState state) +{ + Q_UNUSED (sender) + Q_UNUSED (err) + Q_UNUSED (hwmode) + Q_UNUSED (state) + + if (m_dataEngineState != state) + m_dataEngineState = state; + + if (state == QSDR::DataEngineDown) + m_fftMult = 1; + // m_panadapterBins.clear(); + + if (state == QSDR::DataEngineDown) + averager->clearBuffer(); + + if (m_serverMode != mode) + m_serverMode = mode; + +// if (m_serverMode == mode) +// return; +// else +// m_serverMode = mode; + + //resizeGL(width(), height()); + m_displayTime.restart(); + + update(); +} + +void QGLReceiverPanel::graphicModeChanged( + QObject *sender, + int rx, + PanGraphicsMode panMode, + WaterfallColorMode waterfallColorMode) +{ + Q_UNUSED (sender) + + if (m_receiver != rx) return; + + + if (m_panMode != panMode) + m_panMode = panMode; + + if (m_waterfallMode != waterfallColorMode) + m_waterfallMode = waterfallColorMode; + + update(); +} + + void QGLReceiverPanel::setSpectrumAveraging(QObject* sender, int rx, bool value) { + + Q_UNUSED (sender) + + if (m_receiver != rx) return; + + spectrumBufferMutex.lock(); + + if (m_spectrumAveraging == value) + return; + else + m_spectrumAveraging = value; + + spectrumBufferMutex.unlock(); + } + +void QGLReceiverPanel::setSpectrumAveragingCnt(int value) { + + spectrumBufferMutex.lock(); + + //m_tmp.clear(); + + while (!specAv_queue.isEmpty()) + specAv_queue.dequeue(); + + m_specAveragingCnt = value; + + if (m_specAveragingCnt > 0) + m_scale = 1.0f / m_specAveragingCnt; + else + m_scale = 1.0f; + + spectrumBufferMutex.unlock(); +} + +void QGLReceiverPanel::setPanGridStatus(bool value, int rx) { + + if (m_receiver != rx) return; + + spectrumBufferMutex.lock(); + + if (m_panGrid == value) + return; + else + m_panGrid = value; + + spectrumBufferMutex.unlock(); + update(); +} + +void QGLReceiverPanel::setPeakHoldStatus(bool value, int rx) { + + if (m_receiver != rx) return; + + spectrumBufferMutex.lock(); + + if (m_peakHold == value) + return; + else + m_peakHold = value; + + m_panPeakHoldBins.clear(); + m_panPeakHoldBins.resize(m_panSpectrumBinsLength); + m_panPeakHoldBins.fill(-500.0); + spectrumBufferMutex.unlock(); +} + +void QGLReceiverPanel::setPanLockedStatus(bool value, int rx) { + + if (m_receiver != rx) return; + + if (m_panLocked == value) + return; + else + m_panLocked = value; + + update(); +} + +void QGLReceiverPanel::setClickVFOStatus(bool value, int rx) { + + if (m_receiver != rx) return; + + if (m_clickVFO == value) + return; + else + m_clickVFO = value; + + update(); +} + +void QGLReceiverPanel::setHairCrossStatus(bool value, int rx) { + + if (m_receiver != rx) return; + + if (m_crossHair == value) + return; + else + m_crossHair = value; + + update(); +} + +void QGLReceiverPanel::sampleRateChanged(QObject *sender, int value) { + + Q_UNUSED(sender) + + m_sampleRate = value; + m_deltaF = (qreal)(1.0*m_deltaFrequency/m_sampleRate); + + m_freqScalePanadapterUpdate = true; + m_panGridUpdate = true; + m_peakHoldBufferResize = true; + m_filterChanged = true; + + update(); +} + +void QGLReceiverPanel::setMercuryAttenuator(QObject* sender, HamBand band, int value) { + + Q_UNUSED(sender) + Q_UNUSED(band) + + m_mercuryAttenuator = value; + update(); +} + +void QGLReceiverPanel::setPanadapterColors() { + + m_spectrumColorsChanged = true; + + mutex.lock(); + m_bkgRed = (GLfloat)(set->getPanadapterColors().panBackgroundColor.red() / 256.0); + m_bkgGreen = (GLfloat)(set->getPanadapterColors().panBackgroundColor.green() / 256.0); + m_bkgBlue = (GLfloat)(set->getPanadapterColors().panBackgroundColor.blue() / 256.0); + + m_red = (GLfloat)(set->getPanadapterColors().panLineColor.red() / 256.0); + m_green = (GLfloat)(set->getPanadapterColors().panLineColor.green() / 256.0); + m_blue = (GLfloat)(set->getPanadapterColors().panLineColor.blue() / 256.0); + + m_redF = (GLfloat)(set->getPanadapterColors().panLineFilledColor.red() / 256.0); + m_greenF = (GLfloat)(set->getPanadapterColors().panLineFilledColor.green() / 256.0); + m_blueF = (GLfloat)(set->getPanadapterColors().panLineFilledColor.blue() / 256.0); + + m_redST = (GLfloat)(set->getPanadapterColors().panSolidTopColor.red() / 256.0); + m_greenST = (GLfloat)(set->getPanadapterColors().panSolidTopColor.green() / 256.0); + m_blueST = (GLfloat)(set->getPanadapterColors().panSolidTopColor.blue() / 256.0); + + m_redSB = (GLfloat)(set->getPanadapterColors().panSolidBottomColor.red() / 256.0); + m_greenSB = (GLfloat)(set->getPanadapterColors().panSolidBottomColor.green() / 256.0); + m_blueSB = (GLfloat)(set->getPanadapterColors().panSolidBottomColor.blue() / 256.0); + + m_waterfallMidColor = set->getPanadapterColors().waterfallColor.toRgb() ; + + QColor gridColor = m_gridColor; + m_gridColor = set->getPanadapterColors().gridLineColor; + + if (gridColor != m_gridColor) { + + m_redGrid = (GLfloat)(m_gridColor.red()/256.0); + m_greenGrid = (GLfloat)(m_gridColor.green()/256.0); + m_blueGrid = (GLfloat)(m_gridColor.blue()/256.0); + + m_panGridUpdate = true; + } + mutex.unlock(); + + update(); +} + +void QGLReceiverPanel::setWaterfallOffesetLo(int rx, int value) { + + if (m_receiver != rx) return; + + m_waterfallOffsetLo = value; + update(); +} + +void QGLReceiverPanel::setWaterfallOffesetHi(int rx, int value) { + + if (m_receiver != rx) return; + + m_waterfallOffsetHi = value; + update(); +} + +void QGLReceiverPanel::setdBmScaleMin(int rx, qreal value) { + + if (m_receiver != rx) return; + + m_dBmPanMin = value; + + m_dBmScalePanadapterUpdate = true; + m_panGridUpdate = true; + m_peakHoldBufferResize = true; + + update(); +} + +void QGLReceiverPanel::setdBmScaleMax(int rx, qreal value) { + + if (m_receiver != rx) return; + + m_dBmPanMax = value; + + m_dBmScalePanadapterUpdate = true; + m_panGridUpdate = true; + m_peakHoldBufferResize = true; + + update(); +} + +void QGLReceiverPanel::setMouseWheelFreqStep(QObject *sender, int rx, qreal step) { + + Q_UNUSED(sender) + + if (m_receiver != rx) return; + + m_mouseWheelFreqStep = step; + update(); +} + +void QGLReceiverPanel::setHamBand(QObject *sender, int rx, bool byButton, HamBand band) { + + Q_UNUSED(sender) + + if (m_receiver != rx || !byButton) return; + // we change the dBm-scale only, if the frequency is changed by changing the band by button. + // That is, if we change band by changing the frequency, the dBm scale stays constant. + + //m_panLocked = false; + //m_deltaFrequency = 0; + //m_deltaF = 0; + + m_rxDataList[m_receiver].hamBand = band; + //m_dspModeString = set->getDSPModeString(m_rxDataList[m_receiver].dspMode); + + m_dBmPanMin = m_rxDataList.at(m_receiver).dBmPanScaleMinList.at(band); + m_dBmPanMax = m_rxDataList.at(m_receiver).dBmPanScaleMaxList.at(band); + + m_dBmScalePanadapterUpdate = true; + m_panGridUpdate = true; + m_peakHoldBufferResize = true; + + update(); +} + +void QGLReceiverPanel::setADCStatus(int value) { + + m_adcStatus = value; + update(); + + QTimer::singleShot(50, this, SLOT(updateADCStatus())); +} + +void QGLReceiverPanel::updateADCStatus() { + + if (m_dataEngineState == QSDR::DataEngineUp) + m_adcStatus = 1; + else + m_adcStatus = 0; + + //qDebug() << "m_adcStatus: " << m_adcStatus; + update(); +} + +void QGLReceiverPanel::setAGCLineLevels(QObject *sender, int rx, qreal thresh, qreal hang) { + + Q_UNUSED(sender) + + if (m_receiver != rx) return; + if (m_agcThresholdOld == thresh && m_agcHangLevelOld == hang) return; + + m_agcThresholdOld = thresh; + m_agcHangLevelOld = hang; + //GRAPHICS_DEBUG << "m_agcThresholdOld = " << m_agcThresholdOld; + //GRAPHICS_DEBUG << "m_agcHangLevelOld = " << m_agcHangLevelOld; +} + +void QGLReceiverPanel::setAGCLineFixedLevel(QObject *sender, int rx, qreal value) { + + Q_UNUSED(sender) + + if (m_receiver != rx) return; + if (m_agcFixedGain == value) return; + + m_agcFixedGain = value; + //GRAPHICS_DEBUG << "m_agcFixedGain = " << m_agcFixedGain; +} + +void QGLReceiverPanel::setAGCMode(QObject *sender, int rx, AGCMode mode, bool hangEnabled) { + + Q_UNUSED(sender) + + if (m_receiver != rx) return; + + if (m_agcHangEnabled == hangEnabled && m_agcMode == mode) return; + + m_agcMode = mode; + m_agcModeString = set->getAGCModeString(m_receiver); + m_agcHangEnabled = hangEnabled; + GRAPHICS_DEBUG << "m_agcHangEnabled = " << m_agcHangEnabled; + + update(); +} + +void QGLReceiverPanel::setAGCLinesStatus(QObject* sender, bool value, int rx) { + + Q_UNUSED (sender) + + if (m_receiver != rx) return; + + m_showAGCLines = value; + + update(); +} + +void QGLReceiverPanel::setDSPMode(QObject* sender, int rx, DSPMode mode) { + + Q_UNUSED(sender) + + if (m_receiver != rx) return; + + m_dspMode = mode; + m_dspModeString = set->getDSPModeString(m_dspMode); + + update(); +} + +void QGLReceiverPanel::showRadioPopup(bool value) { + + Q_UNUSED (value) + + radioPopup->showPopupWidget(this, QCursor::pos()); +} + +//void QGLReceiverPanel::setAGCHangEnabled(QObject *sender, int rx, bool hangEnabled) { +// +// Q_UNUSED(sender) +// +// if (m_receiver != rx) return; +// +// if (m_agcHangEnabled == hangEnabled) return; +// m_agcHangEnabled = hangEnabled; +// GRAPHICS_DEBUG << "m_agcHangEnabled = " << m_agcHangEnabled; +// +// update(); +//} diff --git a/Source/src/cusdr_settings.h b/Source/src/cusdr_settings.h index 1787840..f511d34 100644 --- a/Source/src/cusdr_settings.h +++ b/Source/src/cusdr_settings.h @@ -69,7 +69,8 @@ //#define AGCOFFSET 33.0 #define MAXFREQUENCY 961440000 -#define MAXHPFREQUENCY 61440000 +//#define MAXHPFREQUENCY 61440000 +#define MAXHPFREQUENCY 30720000 #define MINDBM -180 #define MAXDBM 10 #define MINDISTDBM -150 diff --git a/Source/src/cusdr_settings.h~ b/Source/src/cusdr_settings.h~ new file mode 100644 index 0000000..1787840 --- /dev/null +++ b/Source/src/cusdr_settings.h~ @@ -0,0 +1,1586 @@ +/** +* @file cusdr_settings.h +* @brief settings header file for cuSDR +* @author by Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2010-11-18 +*/ + +/* + * Copyright 2010, 2011, 2012 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef CUSDR_SETTINGS_H +#define CUSDR_SETTINGS_H + +//#define DEBUG + + +#include +#include +#include +#include +#include +#include +#include + +#include "cusdr_hamDatabase.h" + +// test for OpenCL +//#include "CL/qclcontext.h" + + +// ************************************** +// messages + +#define BANDSCOPE_IN_USE "Error: bandscope in use" +#define BANDSCOPE_NOT_OWNER "Error: Not owner of bandscope" + +#define RECEIVER_INVALID "Error: Invalid Receiver" +#define RECEIVER_IN_USE "Error: Receiver in use" +#define RECEIVER_NOT_OWNER "Error: Not owner of receiver" + +#define CLIENT_ATTACHED "Error: Client is already attached to receiver" +#define CLIENT_DETACHED "Error: Client is not attached to receiver" + +#define INVALID_COMMAND "Error: Invalid Command" + +#define OK "OK" + +// ************************************** +// constants + +#define ONEPI 3.14159265358979323846264338328 +#define TWOPI 6.28318530717958647692528676656 +//#define AGCOFFSET 33.0 + +#define MAXFREQUENCY 961440000 +#define MAXHPFREQUENCY 61440000 +#define MINDBM -180 +#define MAXDBM 10 +#define MINDISTDBM -150 +#define MAXDISTDBM 150 +#define MAX_FFTSIZE 262144 + +// ************************************** +// receiver settings + +#define MAX_RECEIVERS 8 +#define MAX_BANDS 14 +#define BUFFER_SIZE 1024 +#define SAMPLE_BUFFER_SIZE 4096 +#define BANDSCOPE_BUFFER_SIZE 4096 + +#define SMALL_PACKETS +#define BIGWIDEBANDSIZE 16384 +//#define BIGWIDEBANDSIZE 32768 +#define SMALLWIDEBANDSIZE 4096 + + +// ************************************** +// IO buffer, command & control settings + +#define IO_BUFFERS 16 +#define IO_BUFFER_SIZE 512 +#define IO_HEADER_SIZE 8 +#define IO_AUDIOBUFFER_SIZE 8192 + +#define SYNC 0x7F + +#define IQ_DATAGRAM_BUFFERS 512 +#define AUDIO_DATAGRAM_BUFFERS 512 + +#define METIS_HEADER_SIZE 8 +#define METIS_DATA_SIZE 1032 + +#define ALEX_PARAMETERS 15 + +// uncomment to compile code that allows for SYNC error recovery +#define RESYNC + +#define MOX_DISABLED 0x00 +#define MOX_ENABLED 0x01 + +#define ATLAS_10MHZ_SOURCE 0x00 +#define PENELOPE_10MHZ_SOURCE 0x04 +#define MERCURY_10MHZ_SOURCE 0x08 +#define PENELOPE_122_88MHZ_SOURCE 0x00 +#define MERCURY_122_88MHZ_SOURCE 0x10 +#define PENELOPE_PRESENT 0x20 +#define MERCURY_PRESENT 0x40 +#define MIC_SOURCE_PENELOPE 0x80 + +//#define MIC_SOURCE_JANUS 0x00 +//#define CONFIG_NONE 0x00 +//#define CONFIG_BOTH 0x60 + + +//#define SPEED_48KHZ 0x00 +//#define SPEED_96KHZ 0x01 +//#define SPEED_192KHZ 0x02 + +#define MODE_CLASS_E 0x01 +#define MODE_OTHERS 0x00 + +#define ALEX_ATTENUATION_0DB 0x00 +#define ALEX_ATTENUATION_10DB 0x01 +#define ALEX_ATTENUATION_20DB 0x02 +#define ALEX_ATTENUATION_30DB 0x03 +#define LT2208_GAIN_OFF 0x00 +#define LT2208_GAIN_ON 0x04 +#define LT2208_DITHER_OFF 0x00 +#define LT2208_DITHER_ON 0x08 +#define LT2208_RANDOM_OFF 0x00 +#define LT2208_RANDOM_ON 0x10 + +//#define SIMPLEX 0x00 +//#define DUPLEX 0x04 + + +// ************************************** +// Metis definitions + +//#define MAX_METIS_CARDS 10 +//#define DISCOVER_IDLE 0 +//#define DISCOVER_SENT 1 +#define DEVICE_PORT 1024 +#define DATA_PORT 8886 + +// ************************************** +// Audio definitions + +#define WAVEFORM_WINDOW_DURATION 250000 +#define WAVEFORM_TILE_LENGTH 4096 + +//#include "cusdr_about.h" +#include "AudioEngine/cusdr_fspectrum.h" +#include "Util/cusdr_queue.h" + + +// ************************************** +// Server modes + +namespace QSDR { + + enum _Error { + + NoError, + NotImplemented, + HwIOError, + ServerModeError, + OpenError, + DataReceiverThreadError, + DataProcessThreadError, + WideBandDataProcessThreadError, + AudioThreadError, + ChirpDataProcessThreadError, + UnderrunError, + FirmwareError, + FatalError + }; + + enum _DataEngineState { + + DataEngineDown, + DataEngineUp + }; + + enum _DSPCore { + + QtDSP, + CudaDSP, + ExternalDSP + }; + + enum _ServerMode { + + NoServerMode, + SDRMode, + ChirpWSPR, + ChirpWSPRFile, + DemoMode + }; + + enum _HWInterfaceMode { + + NoInterfaceMode, + Metis, + Hermes + }; +} + +Q_DECLARE_METATYPE(QSDR::_Error) +Q_DECLARE_METATYPE(QSDR::_DataEngineState) +Q_DECLARE_METATYPE(QSDR::_ServerMode) +Q_DECLARE_METATYPE(QSDR::_HWInterfaceMode) + + +// ************************************** +enum { + prefixNothing = 0, /*!< No prefix. */ + + /* SI units. */ + prefixKilo = 1, /*!< Kilo prefix 1000^1 = 10^3. */ + prefixMega = 2, /*!< Mega prefix 1000^2 = 10^6. */ + prefixGiga = 3, /*!< Giga prefix 1000^3 = 10^9. */ + prefixTera = 4, /*!< Tera prefix 1000^4 = 10^12. */ + prefixPeta = 5, /*!< Peta prefix 1000^5 = 10^15. */ + prefixExa = 6, /*!< Exa prefix 1000^6 = 10^18. */ + prefixZetta = 7, /*!< Zetta prefix 1000^7 = 10^21. */ + prefixYotta = 8, /*!< Yotta prefix 1000^8 = 10^24. */ + prefixSiMax = prefixYotta, + + /* IEC 60027 units. */ + prefixKibi = 1, /*!< Kibi prefix 1024^1 = 2^10. */ + prefixMebi = 2, /*!< Mebi prefix 1024^2 = 2^20. */ + prefixGibi = 3, /*!< Gibi prefix 1024^3 = 2^30. */ + prefixTebi = 4, /*!< Tebi prefix 1024^4 = 2^40. */ + prefixPebi = 5, /*!< Pebi prefix 1024^5 = 2^50. */ + prefixExbi = 6, /*!< Exbi prefix 1024^6 = 2^60. */ + prefixZebi = 7, /*!< Zebi prefix 1024^7 = 2^70. */ + prefixYobi = 8, /*!< Yobi prefix 1024^8 = 2^80. */ + prefixIecMax = prefixYobi, +}; + + +// ************************************** +// type definitions + +typedef QVector qVectorFloat; + +typedef struct _frequency { + + int freqMHz; + int freqkHz; + + long frequency; + +} TFrequency; + +typedef struct _hpsdrDevices { + + bool mercuryPresence; + bool penelopePresence; + bool pennylanePresence; + bool excaliburPresence; + bool alexPresence; + bool hermesPresence; + bool metisPresence; + + int mercuryFWVersion; + int penelopeFWVersion; + int pennylaneFWVersion; + int excaliburFWVersion; + int alexFWVersion; + int hermesFWVersion; + int metisFWVersion; + +} THPSDRDevices; + +typedef struct _ccParameterRx { + + THPSDRDevices devices; + + uchar roundRobin; // roundRobin is varied in a round-robin fashion in order to decode + // all values which are sent in sequence. + + bool ptt; // PTT (1 = active, 0 = inactive), GPIO[23]= Ozy J8-8, Hermes J16-1 + bool dash; // DASH (1 = active, 0 = inactive), GPIO[21]= Ozy J8-6, Hermes J6-2 + bool dot; // DOT (1 = active, 0 = inactive), GPIO[22]= Ozy J8-7, Hermes J6-3 + bool lt2208; // LT2208 Overflow (1 = active, 0 = inactive) + bool hermesI01; // Hermes I01 (0 = active, 1 = inactive) + bool hermesI02; // Hermes I02 (0 = active, 1 = inactive) + bool hermesI03; // Hermes I03 (0 = active, 1 = inactive) + bool hermesI04; // Hermes I04 (0 = active, 1 = inactive) + bool cyclopsPLL; // Cyclops PLL locked (0 = unlocked, 1 = locked) + bool cyclops; // Cyclops - Mercury frequency changed, bit toggles + + //int mercuryFirmwareVersion; // Mercury firmware version + //int penelopeFirmwareVersion; // Penelope firmware version + //int networkDeviceFirmwareVersion; // Metis/Hermes firmware version + + quint16 ain1; // Forward Power from Alex or Apollo + quint16 ain2; // Reverse Power from Alex or Apollo + quint16 ain3; // AIN3 from Penny or Hermes + quint16 ain4; // AIN4 from Penny or Hermes + quint16 ain5; // Forward Power from Penelope or Hermes + quint16 ain6; // AIN6,13.8v supply on Hermes + + bool mercury1_LT2208; //Mercury 1 LT2208 Overflow (1 = active, 0 = inactive) + bool mercury2_LT2208; //Mercury 2 LT2208 Overflow (1 = active, 0 = inactive) + bool mercury3_LT2208; //Mercury 3 LT2208 Overflow (1 = active, 0 = inactive) + bool mercury4_LT2208; //Mercury 4 LT2208 Overflow (1 = active, 0 = inactive) + + +} TCCParameterRx; + +typedef struct _ccParameterTx { + + bool mox; + bool ptt; + bool lineIn; + bool micGain20dB; + bool pennyOCenabled; + bool vnaMode; + + uchar clockByte; + uchar timeStamp; + uchar commonMercuryFrequencies; + + int hpsdr10MhzSource; + int hpsdr122_88MhzSource; + int hpsdrConfig; + int duplex; + int mercuryAttenuator; + int dither; + int random; + int currentAlexState; + + HamBand currentBand; + + QList mercuryAttenuators; + QList alexStates; + //QList alexConfiguration; + quint16 alexConfig; + QList rxJ6pinList; + QList txJ6pinList; + +} TCCParameterTx; + +typedef struct _hpsdrParameter { + + uchar control_in[5]; + uchar control_out[5]; + + QByteArray ccIn; + QByteArray ccOut; + + uchar output_buffer[IO_BUFFER_SIZE]; + //float in_buffer[2*BUFFER_SIZE]; + float out_buffer[2*BUFFER_SIZE]; + + qVectorFloat wbWindow; + + //CPX cpxIn; + //CPX cpxOut; + //CPX cpxTmp; + + QByteArray audioDatagram; + + QHQueue iq_queue; + QHQueue au_queue; + QHQueue wb_queue; + QHQueue > chirp_queue; + QHQueue > data_queue; + + QList inputBuffer; + + QList clientList; + + QMutex mutex; + QMutex networkIOMutex; + + QWaitCondition devicefound; + //QMutex iqMutex; + + QHostAddress hpsdrDeviceIPAddress; + QString hpsdrDeviceName; + + TCCParameterRx ccRx; + TCCParameterTx ccTx; + + int samplerate; + int speed; + int outputMultiplier; + + int metisFW; + int hermesFW; + int mercuryFW; + int penelopeFW; + int pennylaneFW; + + int clients; + int current_client; + int receivers; + int currentReceiver; + int audio_rx; + int timing; + + int currentMetisCard; + + //int hpsdr_10MhzSource; + //int hpsdr_122_88MhzSource; + int mic_source; + int rxClass; + int rx_freq_change; + int tx_freq_change; + + float mic_gain; + float mic_left_buffer[BUFFER_SIZE]; + float mic_right_buffer[BUFFER_SIZE]; + + qreal penelopeForwardVolts; + qreal penelopeForwardPower; + qreal alexForwardVolts; + qreal alexForwardPower; + qreal alexReverseVolts; + qreal alexReversePower; + qreal ain3Volts; + qreal ain4Volts; + qreal supplyVolts; + + bool rcveIQ_toggle; + bool sendIQ_toggle; + bool timeStamp; + bool mute; + + qint16 audiofileChannels; + +} THPSDRParameter; + +typedef struct _networkDeviceCard { + + QHostAddress ip_address; + char mac_address[18]; + int boardID; + QString boardName; + +} TNetworkDevicecard; + +typedef enum _panGraphicsMode { + + Line, // 0 + FilledLine, // 1 + Solid // 2 + +} PanGraphicsMode; + +typedef enum _waterfallColorMode { + + Simple, // 0 + Enhanced // 1 + +} WaterfallColorMode; + +Q_DECLARE_METATYPE (TNetworkDevicecard) +Q_DECLARE_METATYPE (QList) + +typedef struct _receiver { + + QSDR::_DSPCore dspCore; + + HamBand hamBand; + HamBand lastHamBand; + DSPMode dspMode; + AGCMode agcMode; + TDefaultFilterMode defaultFilterMode; + PanGraphicsMode panMode; + WaterfallColorMode waterfallMode; + + QList lastCenterFrequencyList; + QList lastVfoFrequencyList; + QList mercuryAttenuators; + QList dBmPanScaleMinList; + QList dBmPanScaleMaxList; + QList dspModeList; + + bool hangEnabled; + bool agcLines; + bool panLocked; + bool spectrumAveraging; + bool hairCross; + bool panGrid; + bool peakHold; + bool clickVFO; + + long ctrFrequency; + long vfoFrequency; + long ncoFrequency; + + float freqRulerPosition; + float audioVolume; + + qreal mouseWheelFreqStep; + qreal filterLo; + qreal filterHi; + qreal agcSlope; + qreal acgGain; + qreal acgThreshold_dB; + qreal agcHangThreshold; + qreal agcHangLevel; + qreal agcMaximumGain_dB; + qreal agcAttackTime; + qreal agcDecayTime; + qreal agcHangTime; + qreal agcFixedGain_dB; + qreal agcVariableGain; + + int sampleRate; + int framesPerSecond; + int waterfallOffsetLo; + int waterfallOffsetHi; + int averagingCnt; + +} TReceiver; + +typedef struct _wideband { + + PanGraphicsMode panMode; + + bool wideBandData; + bool wideBandDisplayStatus; + bool averaging; + + int numberOfBuffers; + int averagingCnt; + + float scalePosition; + + qreal dBmWBScaleMin; + qreal dBmWBScaleMax; + +} TWideband; + +typedef struct _transmitter { + + QSDR::_DSPCore dspCore; + + HamBand hamBand; + DSPMode dspMode; + AGCMode agcMode; + TDefaultFilterMode defaultFilterMode; + + bool txAllowed; + long frequency; + + float audioVolume; + +} TTransmitter; + +typedef struct t_panadapterColors { + + QColor panBackgroundColor; + QColor waterfallColor; + QColor panLineColor; + QColor panLineFilledColor; + QColor panSolidTopColor; + QColor panSolidBottomColor; + QColor wideBandLineColor; + QColor wideBandFilledColor; + QColor wideBandSolidTopColor; + QColor wideBandSolidBottomColor; + QColor distanceLineColor; + QColor distanceLineFilledColor; + QColor panCenterLineColor; + QColor gridLineColor; + +} TPanadapterColors; + + +typedef enum _smeterType { + + SIGNAL_STRENGTH, + AVG_SIGNAL_STRENGTH, + ADC_REAL, + ADC_IMAG, + AGC_GAIN, + MIC, + PWR, + ALC, + EQtap, + LEVELER, + COMP, + CPDR, + ALC_G, + LVL_G, + MIC_PK, + ALC_PK, + EQ_PK, + LEVELER_PK, + COMP_PK, + CPDR_PK + +} TMeterType; + +typedef enum _windowtype { + + RECTANGULAR_WINDOW, + HANNING_WINDOW, + WELCH_WINDOW, + PARZEN_WINDOW, + BARTLETT_WINDOW, + HAMMING_WINDOW, + BLACKMAN2_WINDOW, + BLACKMAN3_WINDOW, + BLACKMAN4_WINDOW, + EXPONENTIAL_WINDOW, + RIEMANN_WINDOW, + BLACKMANHARRIS_WINDOW, + NUTTALL_WINDOW + +} TWindowtype; + + +class Receiver; + +// ********************************************************************* +// thread class + +class QThreadEx : public QThread { + +protected: + void run() { exec(); } + +}; + +// ************************************** +// Settings class + +class Settings : public QObject { + + Q_OBJECT + +public: + static Settings *instance(QObject *parent = 0) { + + if (Settings::m_instance) + return Settings::m_instance; + + Settings::m_instance = new Settings(parent); + + return Settings::m_instance; + } + + static void delete_instance() { + + if (Settings::m_instance) { + + disconnect(Settings::m_instance, 0, 0, 0); + delete Settings::m_instance; + Settings::m_instance = 0; + } + } + + virtual ~Settings(); + + QMutex settingsMutex; + +private: + Settings(QObject *parent = 0); + + static Settings *m_instance; + + QSettings *settings; + QSettings *debugLog; + QErrorMessage *error; + +signals: + void systemMessageEvent(const QString &msg, int); + + void masterSwitchChanged(QObject *sender, bool power); + + void systemStateChanged( + QObject *sender, + QSDR::_Error err, + QSDR::_HWInterfaceMode hwmode, + QSDR::_ServerMode mode, + QSDR::_DataEngineState state); + + void graphicModeChanged( + QObject *sender, + int rx, + PanGraphicsMode panMode, + WaterfallColorMode waterfallColorMode); + + void cpuLoadChanged(short load); + void txAllowedChanged(QObject* sender, bool value); + void multiRxViewChanged(int view); + void sMeterValueChanged(int rx, float value); + void spectrumBufferChanged(int rx, const qVectorFloat& buffer); + void postSpectrumBufferChanged(int rx, const float* buffer); + + void sampleSizeChanged(int rx, int size); + void rxListChanged(QList rxList); + void clientConnectedChanged(QObject* sender, bool connect); + void clientNoConnectedChanged(QObject* sender, int client); + void audioRxChanged(QObject* sender, int rx); + void receiverChanged(int value); + void currentReceiverChanged(QObject *sender, int rx); + void connectedChanged(QObject *sender, bool connect); + + void clientConnectedEvent(int client); + void clientDisconnectedEvent(int client); + void rxConnectedStatusChanged(QObject* sender, int rx, bool value); + void framesPerSecondChanged(QObject* sender, int rx, int value); + + void settingsFilenameChanged(QString filename); + void settingsLoadedChanged(bool loaded); + + void newServerNetworkInterface(QString nicName, QString ipAddress); + void newHPSDRDeviceNIC(QString nicName, QString ipAddress); + void serverNICChanged(int); + void hpsdrDeviceNICChanged(int); + void socketBufferSizeChanged(QObject* sender, int value); + void manualSocketBufferChanged(QObject* sender, bool value); + //void metisCardListChanged(QList list); + void metisCardListChanged(const QList &list); + void hpsdrDevicesChanged(QObject *sender, THPSDRDevices devices); + void hpsdrNetworkDeviceChanged(TNetworkDevicecard card); + void networkDeviceNumberChanged(int value); + void networkIOComboBoxEntryAdded(QString str); + void clearNetworkIOComboBoxEntrySignal(); + void searchMetisSignal(); + void serverAddrChanged(QObject *sender, QString addr); + void hpsdrDeviceLocalAddrChanged(QObject *sender, QString addr); + void serverPortChanged(QObject *sender, quint16 port); + void listenPortChanged(QObject *sender, quint16 port); + void audioPortChanged(QObject *sender, quint16 port); + void metisPortChanged(QObject *sender, quint16 port); + + void showNetworkIO(); + void showWarning(const QString &msg); + + void callsignChanged(); + + void mouseWheelFreqStepChanged(QObject *sender, int rx, qreal value); + void mainVolumeChanged(QObject *sender, int rx, float volume ); + + //void hermesPresenceChanged(bool value); + void hpsdrHardwareChanged(int value); + void hermesVersionChanged(int value); + void mercuryPresenceChanged(bool value); + void mercuryVersionChanged(int value); + void penelopePresenceChanged(bool value); + void penelopeVersionChanged(int value); + void pennyLanePresenceChanged(bool value); + void pennyLaneVersionChanged(int value); + void alexPresenceChanged(bool value); + void excaliburPresenceChanged(bool value); + void metisVersionChanged(int value); + //void alexConfigurationChanged(const QList &conf); + void alexConfigurationChanged(quint16 config); + //void alexParametersChanged(TAlexParameters p); + void alexStatesChanged(const QList &states); + void alexStateChanged(HamBand band, const QList &states); + void alexStateChanged(int pos, int value); + void alexManualStateChanged(QObject *sender, bool value); + void checkFirmwareVersionChanged(QObject *sender, bool value); + void pennyOCEnabledChanged(bool value); + void rxJ6PinsChanged(const QList &states); + void txJ6PinsChanged(const QList &states); + + void protocolSyncChanged(int value); + void adcOverflowChanged(int value); + void packetLossChanged(int value); + void sendIQSignalChanged(int value); + void rcveIQSignalChanged(int value); + + void numberOfRXChanged(QObject *sender, int value); + void sampleRateChanged(QObject *sender, int value); + void mercuryAttenuatorChanged(QObject *sender, HamBand band, int value); + //void mercuryAttenuatorsChanged(QObject *sender, const QList &values); + void ditherChanged(QObject *sender, int value); + void randomChanged(QObject *sender, int value); + void src10MhzChanged(QObject *sender, int source); + void src122_88MhzChanged(QObject *sender, int source); + void micSourceChanged(QObject *sender, int source); + void classChanged(QObject *sender, int value); + void timingChanged(QObject *sender, int value); + void controlBytesOutChanged(QObject *sender, unsigned char *values); + //void ctrFrequencyChanged(QObject* sender, bool value, int rx, long frequency); + void ctrFrequencyChanged(QObject* sender, int mode, int rx, long frequency); + //void vfoFrequencyChanged(QObject* sender, bool value, int rx, long frequency); + void vfoFrequencyChanged(QObject* sender, int mode, int rx, long frequency); + void ncoFrequencyChanged(int rx, long frequency); + + // wideband data + void widebandSpectrumBufferChanged(const qVectorFloat& buffer); + void widebandOptionsChanged(QObject* sender, TWideband options); + void widebandSpectrumBufferReset(); + void widebandStatusChanged(QObject* sender, bool value); + void widebandDataChanged(QObject* sender, bool value); + void widebanddBmScaleMinChanged(QObject *sender, qreal value); + void widebanddBmScaleMaxChanged(QObject *sender, qreal value); + void wideBandScalePositionChanged(QObject *sender, float position); + //void widebandAveragingChanged(QObject *sender, bool value); + //void widebandAveragingCntChanged(QObject *sender, int value); + + + void iqPortChanged(QObject* sender, int rx, int port); + + void hamBandChanged(QObject *sender, int rx, bool byButton, HamBand band); + void dspModeChanged(QObject *sender, int rx, DSPMode mode); + void agcModeChanged(QObject *sender, int rx, AGCMode mode, bool hangEnabled); + void agcHangEnabledChanged(QObject *sender, int rx, bool hang); + void agcGainChanged(QObject *sender, int rx, int value); + void agcThresholdChanged_dB(QObject *sender, int rx, qreal value); + void agcFixedGainChanged_dB(QObject *sender, int rx, qreal value); + void agcMaximumGainChanged_dB(QObject *sender, int rx, qreal value); + void agcHangThresholdChanged(QObject *sender, int rx, int value); + void agcHangThresholdSliderChanged(QObject *sender, int rx, qreal value); + void agcHangLevelChanged_dB(QObject *sender, int rx, qreal value); + void agcLineLevelsChanged(QObject *sender, int rx, qreal thresh, qreal hang); + void agcVariableGainChanged_dB(QObject *sender, int rx, qreal value); + void agcAttackTimeChanged(QObject *sender, int rx, qreal value); + void agcDecayTimeChanged(QObject *sender, int rx, qreal value); + void agcHangTimeChanged(QObject *sender, int rx, qreal value); + void filterFrequenciesChanged(QObject *sender, int rx, qreal low, qreal high); + + void cudaDevicesChanged(QObject *sender, int value); + void cudaDriverChanged(QObject *sender, int value); + void cudaRuntimeChanged(QObject *sender, int value); + void cudaCurrentDeviceChanged(QObject *sender, int value); + void cudaLastDeviceChanged(QObject* sender, int value); + + void freqRulerPositionChanged(QObject *sender, int rx, float position); + + + void audioFormatChanged(QObject *sender, const QAudioFormat &format); + void audioPositionChanged(QObject *sender, qint64 position); + void audioBufferChanged(QObject *sender, qint64 position, qint64 length, const QByteArray &buffer); + //void audioBufferChanged(QObject *sender, const QByteArray &buffer); + + void chirpSignalModeChanged(QObject *sender); + void lowerChirpFreqChanged(QObject *sender, int value); + void upperChirpFreqChanged(QObject *sender, int value); + void chirpAmplitudeChanged(QObject *sender, qreal value); + void chirpSamplingFreqChanged(QObject *sender, int value); + void chirpBufferDurationUsChanged(QObject *sender, qint64 value); + void chirpRepetitionTimesChanged(QObject *sender, int value); + void chirpReceiverChanged(QObject *sender, int value); + void chirpBufferChanged(qint64 length, const QList &buffer); + void chirpAvgLengthChanged(int length); + void chirpFFTShowChanged(bool value); + void chirpSidebandChanged(bool value); + void chirpFilterLowerFrequencyChanged(int value); + void chirpFilterUpperFrequencyChanged(int value); + void chirpSpectrumBufferChanged(int sampleRate, qint64 length, const float *buffer); + void chirpSpectrumChanged(qint64 position, qint64 length, const FrequencySpectrum &spectrum); + void chirpSpectrumListChanged(const QList &spectrumList); + + void displayWidgetHeightChanged(int value); + void spectrumSizeChanged(QObject *sender, int value); + void panadapterColorChanged(); + void panGridStatusChanged(bool value, int rx); + void peakHoldStatusChanged(bool value, int rx); + void panLockedStatusChanged(bool value, int rx); + void clickVFOStatusChanged(bool value, int rx); + void hairCrossStatusChanged(bool value, int rx); + void showAGCLinesStatusChanged(QObject *sender, bool value, int rx); + + void spectrumAveragingChanged(QObject *sender, int rx, bool value); + void spectrumAveragingCntChanged(QObject *sender, int rx, int value); + + + void waterfallTimeChanged(int rx, int value); + void waterfallOffesetLoChanged(int rx, int value); + void waterfallOffesetHiChanged(int rx, int value); + + void sMeterHoldTimeChanged(int value); + void dBmScaleMinChanged(int rx, qreal value); + void dBmScaleMaxChanged(int rx, qreal value); + + + void showRadioPopupChanged(bool value); + + void receiverDataReady(); + +public: + void debugSystemState(); + + int loadSettings(); + int saveSettings(); + + QSDR::_ServerMode getCurrentServerMode(); + QSDR::_HWInterfaceMode getHWInterface(); + QSDR::_DataEngineState getDataEngineState(); + + PanGraphicsMode getPanadapterMode(int rx); + WaterfallColorMode getWaterfallColorMode(int rx); + + QString getServerModeString(QSDR::_ServerMode mode); + QString getHWInterfaceModeString(QSDR::_HWInterfaceMode mode); + QString getHDataEngineStateString(QSDR::_DataEngineState mode); + QString getErrorString(QSDR::_Error err); + + QString getValue1000(double value, int valuePrefix, QString unitBase); + QString getValue1024(double value, int valuePrefix, QString unitBase); + + THPSDRDevices getHPSDRDevices(); + + bool getSettingsLoaded(); + bool getMainPower(); + bool getDefaultSkin(); + + int getMinimumWidgetWidth(); + int getMinimumGroupBoxWidth(); + int getMultiRxView(); + bool getPBOPresence(); + bool getFBOPresence(); + + bool getConnected(); + bool getClientConnected(); + bool getTxAllowed(); + + QString getTitleStr(); + QString getVersionStr(); + QString getSettingsFilename(); + QString getCallsign(); + + QString getSDRStyle(); + QString getWidgetStyle(); + QString getMainWindowStyle(); + QString getDockStyle(); + QString getDisplayToolbarStyle(); + QString getMainBtnToolbarStyle(); + QString getStatusbarStyle(); + QString getMessageBoxStyle(); + QString getLineEditStyle(); + QString getDialogStyle(); + QString getColorDialogStyle(); + QString getItemStyle(); + QString getLabelStyle(); + QString getSliderLabelStyle(); + QString getTableStyle(); + QString getComboBoxStyle(); + QString getSpinBoxStyle(); + QString getDoubleSpinBoxStyle(); + QString getMenuStyle(); + QString getMiniButtonStyle(); + QString getVolSliderStyle(); + QString getSplitterStyle(); + QString getFrameStyle(); + QString getTabWidgetStyle(); + //QString getNewSliderStyle(); + + + QString getServerAddr(); + QString getHPSDRDeviceLocalAddr(); + + quint16 getServerPort(); + quint16 getListenPort(); + quint16 getAudioPort(); + quint16 getMetisPort(); + + TNetworkDevicecard getCurrentMetisCard() { return m_currentHPSDRDevice; } + QList getMetisCardsList() { return m_metisCards; } + QList getReceiverDataList() { return m_receiverDataList; } + QList getBandFrequencyList() { return m_bandList; } + QList getHamBandTextList() { return m_bandTextList; } + QList getDefaultFilterList() { return m_defaultFilterList; } + TDefaultFilterMode getCurrentFilterMode() { return m_filterMode; } + quint16 getAlexConfig() { return m_alexConfig; } + QList getAlexStates() { return m_alexStates; } + QList getHPFLoFrequencies() { return m_HPFLoFrequencyList; } + QList getHPFHiFrequencies() { return m_HPFHiFrequencyList; } + QList getLPFLoFrequencies() { return m_LPFLoFrequencyList; } + QList getLPFHiFrequencies() { return m_LPFHiFrequencyList; } + QList getRxJ6Pins() { return m_rxJ6pinList; } + QList getTxJ6Pins() { return m_txJ6pinList; } + int getFramesPerSecond(int rx); + QString getDSPModeString(int mode); + + HamBand getCurrentHamBand(int rx); + QList getMercuryAttenuators(int rx); + //int getMercuryAttenuator(); + + bool getPennyOCEnabled() { return m_pennyOCEnabled; } + int getHpsdrNetworkDevices() { return m_hpsdrNetworkDevices; } + int getNetworkInterfacesNo() { return m_NetworkInterfacesNo; } + bool getMercuryPresence() { return m_devices.mercuryPresence; } + int getMercuryVersion() { return m_devices.mercuryFWVersion; } + bool getPenelopePresence() { return m_devices.penelopePresence; } + int getPenelopeVersion() { return m_devices.penelopeFWVersion; } + bool getPennyLanePresence() { return m_devices.pennylanePresence; } + int getPennyLaneVersion() { return m_devices.pennylaneFWVersion; } + bool getHermesPresence() { return m_devices.hermesPresence; } + int getHermesVersion() { return m_devices.hermesFWVersion; } + int getHPSDRHardware() { return m_hpsdrHardware; } + bool getAlexPresence() { return m_devices.alexPresence; } + bool getExcaliburPresence() { return m_devices.excaliburPresence; } + bool getMetisPresence() { return m_devices.metisPresence; } + int getMetisVersion() { return m_devices.metisFWVersion; } + int getSocketBufferSize() { return m_socketBufferSize; } + bool getManualSocketBufferSize() { return m_manualSocketBufferSize; } + bool getFirmwareVersionCheck() { return m_checkFirmwareVersions; } + + // wideband data & options + TWideband getWidebandOptions() { return m_widebandOptions; } + + bool getWidebandStatus() { return m_widebandOptions.wideBandDisplayStatus; } + bool getWidebandData() { return m_widebandOptions.wideBandData; } + qreal getWidebanddBmScaleMin() { return m_widebandOptions.dBmWBScaleMin; } + qreal getWidebanddBmScaleMax() { return m_widebandOptions.dBmWBScaleMax; } + int getWidebandBuffers() { return m_widebandOptions.numberOfBuffers; } + + + + bool getPanGridStatus(int rx); + bool getPeakHoldStatus(int rx); + bool getPanLockedStatus(int rx); + bool getClickVFOStatus(int rx); + bool getHairCrossStatus(int rx); + + int getMercurySpeed() { return m_mercurySpeed; } + int getOutputSampleIncrement() { return m_outputSampleIncrement; } + int getNumberOfReceivers() { return m_mercuryReceivers; } + //int getCurrentReceivers() { return m_mercuryReceivers; } + int getCurrentReceiver() { return m_currentReceiver; } + bool getFrequencyRx1onRx2() { return m_frequencyRx1onRx2; } + int getSampleRate() { return m_sampleRate; } + + //int getMercuryAttenuator() { return m_mercuryAttenuator; } + int getMercuryDither() { return m_mercuryDither; } + int getMercuryRandom() { return m_mercuryRandom; } + int get10MHzSource() { return m_10MHzSource; } + int get122_8MHzSource() { return m_122_8MHzSource; } + int getMicSource() { return m_micSource; } + int getRxClass() { return m_RxClass; } + int getRxTiming() { return m_RxTiming; } + + qreal getMainVolume(int rx); + qreal getMouseWheelFreqStep(int rx);// { return m_mouseWheelFreqStep; } + AGCMode getAGCMode(int rx); + QString getAGCModeString(int rx); + int getAGCGain(int rx); + qreal getAGCMaximumGain_dB(int rx); + qreal getAGCFixedGain_dB(int rx); + int getAGCHangThreshold(int rx); + int getAGCHangLeveldB(int rx); + + int getLowerChirpFreq() { return m_lowerChirpFreq; } + int getUpperChirpFreq() { return m_upperChirpFreq; } + qreal getChirpAmplitude() { return m_chirpAmplitude; } + int getChirpSamplingFreq() { return m_chirpSamplingFreq; } + qint64 getChirpBufferDurationUs() { return m_chirpBufferDurationUs; } + qint64 getChirpBufferLength() { return m_chirpBufferLength; } + int getChirpChannels() { return m_chirpChannels; } + int getChirpRepetitionTimes() { return m_chirpRepetitionTimes; } + int getChirpDownSampleRate() { return m_chirpDownSampleRate; } + int getChirpAvgLength() { return m_chirpAvgLength; } + int getChirpFilterLowerFrequency() { return m_chirpFilterLowerFrequency; } + int getChirpFilterUpperFrequency() { return m_chirpFilterUpperFrequency; } + bool getChirpReceiver() { return m_chirpReceiverOn; } + bool getChirpFFTShow() { return m_showChirpFFT; } + bool getChirpSideband() { return m_chirpUSB; } + + int getSpectrumSize() { return m_spectrumSize; } + + qreal getdBmDistScaleMin() { return m_dBmDistScaleMin; } + qreal getdBmDistScaleMax() { return m_dBmDistScaleMax; } + + int getSMeterHoldTime() { return m_sMeterHoldTime; } + + qreal getFilterFrequencyLow() { return m_filterFrequencyLow; } + qreal getFilterFrequencyHigh() { return m_filterFrequencyHigh; } + + QList m_ipAddressesList; + QList m_networkInterfaces; + + // audio + QAudio::Mode mode() const { return m_audioMode; } + QAudio::State state() const { return m_audioState; } + QAudioFormat getAudioFormat() const { return m_format; } + + // colors + TPanadapterColors getPanadapterColors() { return m_panadapterColors; } + + bool getSpectrumAveraging(int rx); + int getSpectrumAveragingCnt(int rx); + + int getFFTMultiplicator() { return m_fft; } + + QMutex debugMutex; + +public slots: + void setMainPower(QObject *sender, bool power); + void setDefaultSkin(QObject *sender, bool value); + void setSettingsFilename(QString filename); + + void setSystemMessage(const QString &msg, int time); + void setSettingsLoaded(bool loaded); + void setCPULoad(short load); + void setCallsign(const QString &callsign); + + void setPBOPresence(bool value); + void setFBOPresence(bool value); + + void setMainVolume(QObject *sender, int rx, float volume); + void setMainVolumeMute(QObject *sender, int rx, bool value); + + void setSystemState( + QObject *sender, + QSDR::_Error err, + QSDR::_HWInterfaceMode hwmode, + QSDR::_ServerMode mode, + QSDR::_DataEngineState state); + + void setGraphicsState( + QObject *sender, + int rx, + PanGraphicsMode panMode, + WaterfallColorMode waterfallColorMode); + + void setTxAllowed(QObject* sender, bool value); + void setMultiRxView(int view); + void setSMeterValue(int rx, float value); + void setSpectrumBuffer(int rx, const qVectorFloat &buffer); + void setPostSpectrumBuffer(int rx, const float*); + void setSampleSize(QObject* sender, int rx, int size); + void setRxList(QList rxList); + void setMetisCardList(QList list); + void searchHpsdrNetworkDevices(); + void clearMetisCardList(); + void setHPSDRDeviceNumber(int value); + void setCurrentHPSDRDevice(TNetworkDevicecard card); + void addNetworkIOComboBoxEntry(QString str); + void clearNetworkIOComboBoxEntry(); + void addServerNetworkInterface(QString nicName, QString ipAddress); + void addHPSDRDeviceNIC(QString nicName, QString ipAddress); + void setNumberOfNetworkInterfaces(int value); + void setServerNetworkInterface(int index); + void setHPSDRDeviceNIC(int index); + void setServerWidgetNIC(int index); + void setHPSDRWidgetNIC(int index); + void setServerAddr(QObject *sender, QString addr); + void setHPSDRDeviceLocalAddr(QObject *sender, QString addr); + void setServerPort(QObject *sender, quint16 port); + void setListenPort(QObject *sender, quint16 port); + void setAudioPort(QObject *sender, quint16 port); + void setMetisPort(QObject *sender, quint16 port); + void setClientConnected(QObject *sender, bool value); + void setClientNoConnected(QObject* sender, int client); + void setRxConnectedStatus(QObject* sender, int rx, bool value); + void setAudioRx(QObject* sender, int rx); + void setConnected(QObject *sender, bool value); + void setCheckFirmwareVersion(QObject *sender, bool value); + + void setHPSDRDevices(QObject *sender, THPSDRDevices devices); + //void setHermesPresence(bool value); + void setHermesVersion(int value); + void setHPSDRHardware(int value); + void setMercuryPresence(bool value); + void setMercuryVersion(int value); + void setPenelopePresence(bool value); + void setPenelopeVersion(int value); + void setPennyLanePresence(bool value); + void setPennyLaneVersion(int value); + void setAlexPresence(bool value); + void setExcaliburPresence(bool value); + void setMetisVersion(int value); + + //void setAlexConfiguration(QObject *sender, const QList &conf); + void setAlexConfiguration(QObject *sender, quint16 conf); + void setAlexHPFLoFrequencies(int filter, long value); + void setAlexHPFHiFrequencies(int filter, long value); + void setAlexLPFLoFrequencies(int filter, long value); + void setAlexLPFHiFrequencies(int filter, long value); + void setAlexStates(QObject *sender, const QList &states); + void setAlexState(QObject *sender, int pos, int value); + void setAlexState(QObject *sender, int value); + void setAlexToManual(QObject *sender, bool value); + int checkAlexState(int state); + + void setPennyOCEnabled(QObject *sender, bool value); + void setRxJ6Pin(QObject *sender, HamBand band, int value); + void setRxJ6Pins(QObject * sender, const QList &states); + void setTxJ6Pin(QObject *sender, HamBand band, int value); + void setTxJ6Pins(QObject * sender, const QList &states); + + void setIQPort(QObject *sender, int rx, int port); + + void setProtocolSync(int value); + void setADCOverflow(int value); + void setPacketLoss(int value); + void setSendIQ(int value); + void setRcveIQ(int value); + + void setReceivers(QObject *sender, int value); + //void setReceiver(QObject *sender, int value); + void setCurrentReceiver(QObject *sender, int value); + void setSampleRate(QObject *sender, int value); + void setMercuryAttenuator(QObject *sender, int value); + void setDither(QObject *sender, int value); + void setRandom(QObject *sender, int value); + void set10MhzSource(QObject *sender, int source); + void set122_88MhzSource(QObject *sender, int source); + void setMicSource(QObject *sender, int source); + void setClass(QObject *sender, int value); + void setTiming(QObject *sender, int value); + void setCtrFrequency(QObject *sender, int mode, int rx, long frequency); + void setCtrFrequency(int rx, long frequency); + long getCtrFrequency(int rx); + void setVFOFrequency(QObject *sender, int mode, int rx, long frequency); + void setVfoFrequency(int rx, long frequency); + long getVfoFrequency(int rx); + void setNCOFrequency(QObject *sender, bool value, int rx, long frequency); + + void clientDisconnected(int client); + void setFramesPerSecond(QObject *sender, int rx, int value); + void setMouseWheelFreqStep(QObject *sender, int rx, qreal value); + void setSocketBufferSize(QObject *sender, int value); + void setManualSocketBufferSize(QObject *sender, bool value); + + void setReceiverDataReady(); + + void setSpectrumSize(QObject *sender, int value); + void setdBmPanScaleMin(int rx, qreal value); + void setdBmPanScaleMax(int rx, qreal value); + + void setdBmDistScaleMin(qreal value); + void setdBmDistScaleMax(qreal value); + + void setHamBand(QObject* sender, int rx, bool byButton, HamBand band); + void setDSPMode(QObject* sender, int rx, DSPMode mode); + void setAGCMode(QObject* sender, int rx, AGCMode mode); + void setAGCGain(QObject* sender, int rx, int value); + void setAGCMaximumGain_dB(QObject *sender, int rx, qreal value); + void setAGCFixedGain_dB(QObject *sender, int rx, qreal value); + void setAGCThreshold_dB(QObject *sender, int rx, qreal value); + + void setAGCHangThresholdSlider(QObject *sender, int rx, qreal value); + void setAGCHangThreshold(QObject *sender, int rx, int value); + void setAGCHangLevel_dB(QObject *sender, int rx, qreal value); + void setAGCLineLevels(QObject *sender, int rx, qreal thresh, qreal hang); + void setAGCShowLines(QObject *sender, int rx, bool value); + void setAGCVariableGain_dB(QObject *sender, int rx, qreal value); + void setAGCAttackTime(QObject *sender, int rx, qreal value); + void setAGCDecayTime(QObject *sender, int rx, qreal value); + void setAGCHangTime(QObject *sender, int rx, qreal value); + void setRXFilter(QObject* sender, int rx, qreal low, qreal high); + + + // wideband data & options + void setWidebandBuffers(QObject *sender, int value); + void setWidebandSpectrumBuffer(const qVectorFloat &buffer); + void resetWidebandSpectrumBuffer(); + void setWidebandOptions(QObject* sender, TWideband options); + void setWidebandStatus(QObject* sender, bool value); + void setWidebandData(QObject* sender, bool value); + void setWidebanddBmScaleMin(QObject* sender, qreal value); + void setWidebanddBmScaleMax(QObject* sender, qreal value); + //void setWidebandAveraging(QObject *sender, bool value); + //void setWidebandAveragingCnt(QObject *sender, int value); + void setWideBandRulerPosition(QObject* sender, float pos); + + //void setOpenCLDevices(QList dev); + + /*void setCudaPresence(bool value); + void setCudaDevices(int value); + void setCudaLastDevice(QObject *sender, int vlaue); + void setCudaDriver(QObject *sender, int value); + void setCudaRuntime(QObject *sender, int value); + void setCurrentCudaDevice(QObject *sender, int value);*/ + + void setFreqRulerPosition(QObject* sender, int rx, float pos); + //void setRulerPosition(QObject *sender, float pos); + + void setAudioFormat(QObject *sender, const QAudioFormat &format); + void setAudioPosition(QObject *sender, qint64 position); + void setAudioBuffer(QObject *sender, qint64 position, qint64 length, const QByteArray &buffer); + //void setAudioBuffer(QObject *sender, const QByteArray &buffer); + + void switchToChirpSignalMode(QObject *sender); + void setLowerChirpFreq(int value); + void setUpperChirpFreq(int value); + void setChirpAmplitude(qreal value); + void setChirpSamplingFreq(int value); + void setChirpBufferDurationUs(int value); + void setChirpRepetitionTimes(int value); + void setChirpReceiver(bool value); + void setChirpAvgLength(int value); + void setChirpFFTShow(bool value); + void setChirpUSB(bool value); + void setChirpFilterLowerFrequency(int value); + void setChirpFilterUpperFrequency(int value); + //void setChirpDownSampleRate(int value); + //void setChirpBufferLength(qint64 length); + void setChirpBuffer(qint64 length, const QList &buffer); + //void setChirpSpectrumBuffer(const QList &buffer); + void setChirpSpectrumBuffer(int sampleRate, qint64 length, const float *buffer); + + //void setSpectrumBuffer(const float *buffer); + void setChirpSpectrum(qint64 position, qint64 length, const FrequencySpectrum &spectrum); + void setChirpSpectrumList(const QList &spectrumList); + + void moveDisplayWidget(int value); + + void setPanadapterColors(TPanadapterColors type); + void setPanGrid(bool value, int rx); + void setPeakHold(bool value, int rx); + void setPanLocked(bool value, int rx); + void setClickVFO(bool value, int rx); + void setHairCross(bool value, int rx); + + void setSpectrumAveraging(QObject *sender, int rx, bool value); + void setSpectrumAveragingCnt(QObject *sender, int rx, int value); + + + void setWaterfallTime(int rx, int value); + void setWaterfallOffesetLo(int rx, int value); + void setWaterfallOffesetHi(int rx, int value); + + void setSMeterHoldTime(int value); + + void showNetworkIODialog(); + void showWarningDialog(const QString &msg); + + void showRadioPopupWidget(); + + QList getCtrFrequencies(); + QList getVfoFrequencies(); + +private slots: + +private: + QSDR::_Error m_systemError; + QSDR::_ServerMode m_serverMode; + QSDR::_HWInterfaceMode m_hwInterface; + QSDR::_DataEngineState m_dataEngineState; + + QAudio::Mode m_audioMode; + QAudio::State m_audioState; + QAudioFormat m_format; + + THPSDRDevices m_devices; + TDefaultFilterMode m_filterMode; + TPanadapterColors m_panadapterColors; + TNetworkDevicecard m_currentHPSDRDevice; + TTransmitter m_transmitter; + TWideband m_widebandOptions; + + QList m_metisCards; + QList m_receiverDataList; + QList m_bandList; + QList m_bandTextList; + QList m_defaultFilterList; + //QList m_clDevices; + QList m_rxStringList; + QList m_alexStates; + QList m_HPFLoFrequencyList; + QList m_HPFHiFrequencyList; + QList m_LPFLoFrequencyList; + QList m_LPFHiFrequencyList; + QList m_rxJ6pinList; + QList m_txJ6pinList; + + QString m_titleString; + QString m_versionString; + QString m_serverAddress; + QString m_hpsdrDeviceLocalAddr; + QString m_callsignString; + QString settingsFilename; + + QDateTime startTime; + QDateTime now; + + QHostAddress m_hostAddress; + + + quint16 m_serverPort; + quint16 m_listenerPort; + quint16 m_audioPort; + quint16 m_metisPort; + quint16 m_alexConfig; + + bool setLoaded; + + bool m_mainPower; + bool m_defaultSkin; + bool m_connected; + bool m_clientConnected; + bool m_pboFound; + bool m_fboFound; + bool m_manualSocketBufferSize; + bool m_pennyOCEnabled; + + //bool main_mute; + bool m_checkFirmwareVersions; + bool m_specAveraging; + bool m_panGrid; + bool m_peakHold; + bool m_packetsToggle; + + bool m_frequencyRx1onRx2; + bool m_radioPopupVisible; + + int m_hpsdrHardware; + int m_hpsdrNetworkDevices; + int m_NetworkInterfacesNo; + int m_socketBufferSize; + int m_clientNoConnected; + int m_minimumWidgetWidth; + int m_minimumGroupBoxWidth; + + int m_mercuryReceivers; + int m_currentReceiver; + int m_sampleRate; + int m_mercurySpeed; + + int m_mercuryAttenuator; + int m_mercuryDither; + int m_mercuryRandom; + + int m_outputSampleIncrement; + int m_10MHzSource; + int m_122_8MHzSource; + int m_micSource; + int m_RxClass; + int m_RxTiming; + + int m_framesPerSecond; + int m_multiRxView; + + //int m_wbBuffers; + int m_spectrumSize; + int m_sMeterHoldTime; + + long freq1; + + float m_mainVolume; + + int control_register; + bool connect_at_startup; + + qreal m_dBmDistScaleMin; + qreal m_dBmDistScaleMax; + + qreal m_filterFrequencyLow; + qreal m_filterFrequencyHigh; + + qreal m_chirpAmplitude; + + qint64 m_chirpBufferDurationUs; + qint64 m_chirpBufferLength; + + bool m_chirpReceiverOn; + bool m_showChirpFFT; + bool m_chirpUSB; + + int m_lowerChirpFreq; + int m_upperChirpFreq; + int m_chirpSamplingFreq; + int m_chirpChannels; + int m_chirpRepetitionTimes; + int m_chirpDownSampleRate; + int m_chirpAvgLength; + int m_chirpFilterLowerFrequency; + int m_chirpFilterUpperFrequency; + + int m_fft; + + /*bool m_cudaPresence; + int m_cuda_devices; + int m_cudaLastDevice; + int m_cuda_driver_version; + int m_cuda_runtime_version; + int m_current_cuda_device;*/ + + void checkHPSDRDevices(); +}; + + +//****************************************************** +// Macros + +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** The following Macro "CHECKED_CONNECT" is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ +// Macro which connects a signal to a slot, and which causes application to +// abort if the connection fails. This is intended to catch programming errors +// such as mis-typing a signal or slot name. It is necessary to write our own +// macro to do this - the following idiom +// Q_ASSERT(connect(source, signal, receiver, slot)); +// will not work because Q_ASSERT compiles to a no-op in release builds. + +#define CHECKED_CONNECT(source, signal, receiver, slot) \ + if(!connect(source, signal, receiver, slot)) \ + qt_assert_x(Q_FUNC_INFO, "CHECKED_CONNECT failed", __FILE__, __LINE__); + +#define CHECKED_CONNECT_OPT(source, signal, receiver, slot, opt) \ + if(!connect(source, signal, receiver, slot, opt)) \ + qt_assert_x(Q_FUNC_INFO, "CHECKED_CONNECT failed", __FILE__, __LINE__); + + + +//****************************************************** +// Debug output + +class NullDebug { + +public: + template + NullDebug& operator << (const T) { return *this; } +}; + +inline NullDebug nullDebug() { return NullDebug(); } + + +#ifdef LOG_SETTINGS +# define SETTINGS_DEBUG qDebug().nospace() << "Settings::\t" +#else +# define SETTINGS_DEBUG nullDebug() +#endif + + +//****************************************************** +// sleeper function + +class SleeperThread : public QThread { + + public: + static void msleep(unsigned long msecs) {QThread::msleep(msecs);} + static void usleep(unsigned long usecs) {QThread::usleep(usecs);} +}; + +#endif // CUSDR_SETTINGS_H diff --git a/bak/README.md b/bak/README.md new file mode 100644 index 0000000..e712f2e --- /dev/null +++ b/bak/README.md @@ -0,0 +1,7 @@ +This is a copy of VK5ABN, Berndt's cuSDR source +derived from his post: http://www.ping.net.au/20140126_cuSDR64src.tar.gz + +I added local sound and up'd the number of recievers to 8 +for librtlhpsdr. + +I have only compiled and used this on linux.