2023-06-01 16:57:44 +00:00
# include "spectrumscope.h"
# include "logcategories.h"
2023-06-05 08:27:37 +00:00
# include "rigidentities.h"
2023-06-01 16:57:44 +00:00
spectrumScope : : spectrumScope ( QWidget * parent )
2023-06-05 08:27:37 +00:00
: QGroupBox { parent }
2023-06-01 16:57:44 +00:00
{
2023-06-05 08:27:37 +00:00
QMutexLocker locker ( & mutex ) ;
2023-09-19 22:04:48 +00:00
2023-06-08 07:20:50 +00:00
this - > setObjectName ( " Spectrum Scope " ) ;
2023-06-05 08:27:37 +00:00
this - > setTitle ( " Band " ) ;
2023-09-25 13:55:27 +00:00
this - > defaultStyleSheet = this - > styleSheet ( ) ;
2023-06-05 08:27:37 +00:00
queue = cachingQueue : : getInstance ( ) ;
2023-06-01 16:57:44 +00:00
spectrum = new QCustomPlot ( ) ;
2023-09-24 23:11:37 +00:00
mainLayout = new QHBoxLayout ( this ) ;
2023-09-25 13:55:27 +00:00
layout = new QVBoxLayout ( ) ;
2023-09-24 23:11:37 +00:00
mainLayout - > addLayout ( layout ) ;
2023-06-01 16:57:44 +00:00
splitter = new QSplitter ( this ) ;
layout - > addWidget ( splitter ) ;
splitter - > setOrientation ( Qt : : Vertical ) ;
2023-09-26 17:46:04 +00:00
displayLayout = new QHBoxLayout ( ) ;
freqDisplay = new freqCtrl ( ) ;
freqDisplay - > setMinimumSize ( 280 , 30 ) ;
freqDisplay - > setMaximumSize ( 280 , 30 ) ;
displayLayout - > addWidget ( freqDisplay ) ;
displaySpacer = new QSpacerItem ( 0 , 0 , QSizePolicy : : Expanding , QSizePolicy : : Fixed ) ;
displayLayout - > addSpacerItem ( displaySpacer ) ;
2024-01-21 20:36:52 +00:00
controlLayout = new QHBoxLayout ( ) ;
detachButton = new QPushButton ( " Detach " ) ;
detachButton - > setCheckable ( true ) ;
detachButton - > setToolTip ( " Detach/re-attach scope from main window " ) ;
detachButton - > setChecked ( false ) ;
2023-06-05 08:27:37 +00:00
//scopeModeLabel = new QLabel("Spectrum Mode:");
scopeModeCombo = new QComboBox ( ) ;
scopeModeCombo - > setAccessibleDescription ( " Spectrum Mode " ) ;
//spanLabel = new QLabel("Span:");
spanCombo = new QComboBox ( ) ;
spanCombo - > setAccessibleDescription ( " Spectrum Span " ) ;
spanCombo - > setSizeAdjustPolicy ( QComboBox : : AdjustToContents ) ;
//edgeLabel = new QLabel("Edge:");
edgeCombo = new QComboBox ( ) ;
edgeCombo - > setAccessibleDescription ( " Spectrum Edge " ) ;
edgeButton = new QPushButton ( " Custom Edge " ) ;
edgeButton - > setToolTip ( " Define a custom (fixed) scope edge " ) ;
toFixedButton = new QPushButton ( " To Fixed " ) ;
toFixedButton - > setToolTip ( " <html><head/><body><p>Press button to convert center mode spectrum to fixed mode, preserving the range. This allows you to tune without the spectrum moving, in the same currently-visible range that you see now. </p><p><br/></p><p>The currently-selected edge slot will be overridden.</p></body></html> " ) ;
2023-06-08 20:58:22 +00:00
holdButton = new QPushButton ( " HOLD " ) ;
holdButton - > setCheckable ( true ) ;
holdButton - > setFocusPolicy ( Qt : : NoFocus ) ;
2023-06-05 08:27:37 +00:00
controlSpacer = new QSpacerItem ( 0 , 0 , QSizePolicy : : Expanding , QSizePolicy : : Fixed ) ;
midSpacer = new QSpacerItem ( 0 , 0 , QSizePolicy : : Expanding , QSizePolicy : : Fixed ) ;
2023-09-25 13:55:27 +00:00
2023-06-05 08:27:37 +00:00
clearPeaksButton = new QPushButton ( " Clear Peaks " ) ;
2023-07-16 09:08:28 +00:00
2023-09-25 18:21:31 +00:00
confButton = new QPushButton ( " < " ) ;
confButton - > setAccessibleName ( " Configure Scope " ) ;
confButton - > setAccessibleDescription ( " Change various settings of the current Scope " ) ;
confButton - > setToolTip ( " Configure Scope " ) ;
confButton - > setFocusPolicy ( Qt : : NoFocus ) ;
2023-06-05 08:27:37 +00:00
modeCombo = new QComboBox ( ) ;
dataCombo = new QComboBox ( ) ;
filterCombo = new QComboBox ( ) ;
spanCombo - > setVisible ( false ) ;
edgeCombo - > setVisible ( false ) ;
edgeButton - > setVisible ( false ) ;
toFixedButton - > setVisible ( false ) ;
2023-06-01 16:57:44 +00:00
spectrum = new QCustomPlot ( ) ;
2023-09-27 10:06:55 +00:00
spectrum - > xAxis - > axisRect ( ) - > setAutoMargins ( QCP : : MarginSide : : msBottom ) ;
spectrum - > yAxis - > axisRect ( ) - > setAutoMargins ( QCP : : MarginSide : : msBottom ) ;
spectrum - > xAxis - > setPadding ( 0 ) ;
spectrum - > yAxis - > setPadding ( 0 ) ;
2023-06-01 16:57:44 +00:00
waterfall = new QCustomPlot ( ) ;
2023-09-27 10:06:55 +00:00
waterfall - > xAxis - > axisRect ( ) - > setAutoMargins ( QCP : : MarginSide : : msNone ) ;
waterfall - > yAxis - > axisRect ( ) - > setAutoMargins ( QCP : : MarginSide : : msNone ) ;
waterfall - > xAxis - > setPadding ( 0 ) ;
waterfall - > yAxis - > setPadding ( 0 ) ;
2023-06-01 16:57:44 +00:00
splitter - > addWidget ( spectrum ) ;
splitter - > addWidget ( waterfall ) ;
splitter - > setHandleWidth ( 5 ) ;
2023-09-27 10:06:55 +00:00
spectrum - > axisRect ( ) - > setMargins ( QMargins ( 30 , 0 , 0 , 0 ) ) ;
waterfall - > axisRect ( ) - > setMargins ( QMargins ( 30 , 0 , 0 , 0 ) ) ;
2023-06-01 16:57:44 +00:00
2023-09-26 17:46:04 +00:00
layout - > addLayout ( displayLayout ) ;
2023-06-05 08:27:37 +00:00
layout - > addLayout ( controlLayout ) ;
2024-01-21 20:36:52 +00:00
controlLayout - > addWidget ( detachButton ) ;
2023-06-05 08:27:37 +00:00
controlLayout - > addWidget ( scopeModeCombo ) ;
controlLayout - > addWidget ( spanCombo ) ;
controlLayout - > addWidget ( edgeCombo ) ;
controlLayout - > addWidget ( edgeButton ) ;
controlLayout - > addWidget ( toFixedButton ) ;
2023-06-08 20:58:22 +00:00
controlLayout - > addWidget ( holdButton ) ;
2023-06-05 08:27:37 +00:00
controlLayout - > addSpacerItem ( controlSpacer ) ;
controlLayout - > addWidget ( modeCombo ) ;
controlLayout - > addWidget ( dataCombo ) ;
controlLayout - > addWidget ( filterCombo ) ;
controlLayout - > addSpacerItem ( midSpacer ) ;
controlLayout - > addWidget ( clearPeaksButton ) ;
2023-09-25 18:21:31 +00:00
controlLayout - > addWidget ( confButton ) ;
2023-06-05 08:27:37 +00:00
this - > layout - > setContentsMargins ( 5 , 5 , 5 , 5 ) ;
scopeModeCombo - > addItem ( " Center Mode " , ( spectrumMode_t ) spectModeCenter ) ;
scopeModeCombo - > addItem ( " Fixed Mode " , ( spectrumMode_t ) spectModeFixed ) ;
scopeModeCombo - > addItem ( " Scroll-C " , ( spectrumMode_t ) spectModeScrollC ) ;
scopeModeCombo - > addItem ( " Scroll-F " , ( spectrumMode_t ) spectModeScrollF ) ;
scopeModeCombo - > setSizeAdjustPolicy ( QComboBox : : AdjustToContents ) ;
edgeCombo - > insertItems ( 0 , QStringList ( { " Fixed Edge 1 " , " Fixed Edge 2 " , " Fixed Edge 3 " , " Fixed Edge 4 " } ) ) ;
//edgeCombo->setSizeAdjustPolicy(QComboBox::AdjustToContentsOnFirstShow);
2023-06-01 16:57:44 +00:00
// Spectrum Plot setup
passbandIndicator = new QCPItemRect ( spectrum ) ;
passbandIndicator - > setAntialiased ( true ) ;
passbandIndicator - > setPen ( QPen ( Qt : : red ) ) ;
passbandIndicator - > setBrush ( QBrush ( Qt : : red ) ) ;
passbandIndicator - > setSelectable ( true ) ;
pbtIndicator = new QCPItemRect ( spectrum ) ;
pbtIndicator - > setAntialiased ( true ) ;
pbtIndicator - > setPen ( QPen ( Qt : : red ) ) ;
pbtIndicator - > setBrush ( QBrush ( Qt : : red ) ) ;
pbtIndicator - > setSelectable ( true ) ;
pbtIndicator - > setVisible ( false ) ;
freqIndicatorLine = new QCPItemLine ( spectrum ) ;
freqIndicatorLine - > setAntialiased ( true ) ;
freqIndicatorLine - > setPen ( QPen ( Qt : : blue ) ) ;
oorIndicator = new QCPItemText ( spectrum ) ;
oorIndicator - > setVisible ( false ) ;
oorIndicator - > setAntialiased ( true ) ;
oorIndicator - > setPen ( QPen ( Qt : : red ) ) ;
oorIndicator - > setBrush ( QBrush ( Qt : : red ) ) ;
oorIndicator - > setFont ( QFont ( font ( ) . family ( ) , 14 ) ) ;
oorIndicator - > setPositionAlignment ( Qt : : AlignVCenter | Qt : : AlignHCenter ) ;
oorIndicator - > position - > setType ( QCPItemPosition : : ptAxisRectRatio ) ; // Positioned relative to the current plot rect
oorIndicator - > setText ( " SCOPE OUT OF RANGE " ) ;
oorIndicator - > position - > setCoords ( 0.5f , 0.5f ) ;
ovfIndicator = new QCPItemText ( spectrum ) ;
ovfIndicator - > setVisible ( false ) ;
ovfIndicator - > setAntialiased ( true ) ;
ovfIndicator - > setPen ( QPen ( Qt : : red ) ) ;
ovfIndicator - > setColor ( Qt : : red ) ;
ovfIndicator - > setFont ( QFont ( font ( ) . family ( ) , 10 ) ) ;
ovfIndicator - > setPositionAlignment ( Qt : : AlignLeft | Qt : : AlignTop ) ;
ovfIndicator - > position - > setType ( QCPItemPosition : : ptAxisRectRatio ) ; // Positioned relative to the current plot rect
ovfIndicator - > setText ( " OVF " ) ;
ovfIndicator - > position - > setCoords ( 0.01f , 0.0f ) ;
2024-01-22 12:19:31 +00:00
redrawSpeed = new QCPItemText ( spectrum ) ;
redrawSpeed - > setVisible ( true ) ;
redrawSpeed - > setColor ( Qt : : gray ) ;
redrawSpeed - > setFont ( QFont ( font ( ) . family ( ) , 8 ) ) ;
redrawSpeed - > setPositionAlignment ( Qt : : AlignRight | Qt : : AlignTop ) ;
redrawSpeed - > position - > setType ( QCPItemPosition : : ptAxisRectRatio ) ;
redrawSpeed - > setText ( " 0ms/0ms " ) ;
redrawSpeed - > position - > setCoords ( 1.0f , 0.0f ) ;
2023-06-01 16:57:44 +00:00
spectrum - > addGraph ( ) ; // primary
spectrum - > addGraph ( 0 , 0 ) ; // secondary, peaks, same axis as first.
spectrum - > addLayer ( " Top Layer " , spectrum - > layer ( " main " ) ) ;
spectrum - > graph ( 0 ) - > setLayer ( " Top Layer " ) ;
2024-02-05 19:25:27 +00:00
spectrumPlasma . resize ( spectrumPlasmaSizeMax ) ;
2024-02-06 22:27:29 +00:00
for ( unsigned int p = 0 ; p < spectrumPlasmaSizeMax ; p + + ) {
2024-02-05 19:25:27 +00:00
spectrumPlasma [ p ] = 0 ;
}
2023-06-01 16:57:44 +00:00
QColor color ( 20 + 200 / 4.0 * 1 , 70 * ( 1.6 - 1 / 4.0 ) , 150 , 150 ) ;
spectrum - > graph ( 1 ) - > setLineStyle ( QCPGraph : : lsLine ) ;
spectrum - > graph ( 1 ) - > setPen ( QPen ( color . lighter ( 200 ) ) ) ;
spectrum - > graph ( 1 ) - > setBrush ( QBrush ( color ) ) ;
freqIndicatorLine - > start - > setCoords ( 0.5 , 0 ) ;
freqIndicatorLine - > end - > setCoords ( 0.5 , 160 ) ;
passbandIndicator - > topLeft - > setCoords ( 0.5 , 0 ) ;
passbandIndicator - > bottomRight - > setCoords ( 0.5 , 160 ) ;
pbtIndicator - > topLeft - > setCoords ( 0.5 , 0 ) ;
pbtIndicator - > bottomRight - > setCoords ( 0.5 , 160 ) ;
// Waterfall setup
waterfall - > addGraph ( ) ;
colorMap = new QCPColorMap ( waterfall - > xAxis , waterfall - > yAxis ) ;
colorMapData = NULL ;
2023-06-05 08:27:37 +00:00
2023-06-01 16:57:44 +00:00
# if QCUSTOMPLOT_VERSION < 0x020001
this - > addPlottable ( colorMap ) ;
# endif
2023-09-24 23:11:37 +00:00
// Config Screen
2023-09-25 13:55:27 +00:00
rhsLayout = new QVBoxLayout ( ) ;
rhsTopSpacer = new QSpacerItem ( 0 , 0 , QSizePolicy : : Fixed , QSizePolicy : : Expanding ) ;
rhsLayout - > addSpacerItem ( rhsTopSpacer ) ;
configGroup = new QGroupBox ( ) ;
rhsLayout - > addWidget ( configGroup ) ;
configLayout = new QFormLayout ( ) ;
configGroup - > setLayout ( configLayout ) ;
mainLayout - > addLayout ( rhsLayout ) ;
rhsBottomSpacer = new QSpacerItem ( 0 , 0 , QSizePolicy : : Fixed , QSizePolicy : : Expanding ) ;
rhsLayout - > addSpacerItem ( rhsBottomSpacer ) ;
2023-09-24 23:11:37 +00:00
QFont font = configGroup - > font ( ) ;
2023-09-25 13:55:27 +00:00
configGroup - > setStyleSheet ( QString ( " QGroupBox{border:1px solid gray;} *{padding: 0px 0px 0px 0px; margin: 0px 0px 0px 0px; font-size: %0px;} " ) . arg ( font . pointSize ( ) - 1 ) ) ;
2023-09-24 23:11:37 +00:00
configGroup - > setMaximumWidth ( 240 ) ;
configRef = new QSlider ( Qt : : Orientation : : Horizontal ) ;
configRef - > setRange ( - 200 , 200 ) ;
configRef - > setTickInterval ( 50 ) ;
configRef - > setSingleStep ( 20 ) ;
configRef - > setValue ( 0 ) ;
configRef - > setAccessibleName ( " Scope display reference " ) ;
configRef - > setAccessibleDescription ( " Selects the display reference for the Scope display " ) ;
configRef - > setToolTip ( " Select display reference of scope " ) ;
configLayout - > addRow ( " Ref " , configRef ) ;
configLength = new QSlider ( Qt : : Orientation : : Horizontal ) ;
configLength - > setRange ( 100 , 1024 ) ;
2023-09-26 09:32:56 +00:00
configLength - > setValue ( wfLength ) ;
2023-09-24 23:11:37 +00:00
configLayout - > addRow ( " Length " , configLength ) ;
configTop = new QSlider ( Qt : : Orientation : : Horizontal ) ;
configTop - > setRange ( 1 , 160 ) ;
2023-09-26 09:32:56 +00:00
configTop - > setValue ( plotCeiling ) ;
2023-09-24 23:11:37 +00:00
configTop - > setAccessibleName ( " Scope display ceiling " ) ;
configTop - > setAccessibleDescription ( " Selects the display ceiling for the Scope display " ) ;
configTop - > setToolTip ( " Select display ceiling of scope " ) ;
configLayout - > addRow ( " Ceiling " , configTop ) ;
configBottom = new QSlider ( Qt : : Orientation : : Horizontal ) ;
configBottom - > setRange ( 0 , 160 ) ;
2023-09-26 09:32:56 +00:00
configBottom - > setValue ( plotFloor ) ;
2023-09-24 23:11:37 +00:00
configBottom - > setAccessibleName ( " Scope display floor " ) ;
configBottom - > setAccessibleDescription ( " Selects the display floor for the Scope display " ) ;
configBottom - > setToolTip ( " Select display floor of scope " ) ;
configLayout - > addRow ( " Floor " , configBottom ) ;
configSpeed = new QComboBox ( ) ;
configSpeed - > addItem ( " Speed Fast " , QVariant : : fromValue ( uchar ( 0 ) ) ) ;
configSpeed - > addItem ( " Speed Mid " , QVariant : : fromValue ( uchar ( 1 ) ) ) ;
configSpeed - > addItem ( " Speed Slow " , QVariant : : fromValue ( uchar ( 2 ) ) ) ;
configSpeed - > setCurrentIndex ( configSpeed - > findData ( currentSpeed ) ) ;
configSpeed - > setAccessibleName ( " Waterfall display speed " ) ;
configSpeed - > setAccessibleDescription ( " Selects the speed for the waterfall display " ) ;
configSpeed - > setToolTip ( " Waterfall Speed " ) ;
configLayout - > addRow ( " Speed " , configSpeed ) ;
configTheme = new QComboBox ( ) ;
configTheme - > setAccessibleName ( " Waterfall display color theme " ) ;
configTheme - > setAccessibleDescription ( " Selects the color theme for the waterfall display " ) ;
configTheme - > setToolTip ( " Waterfall color theme " ) ;
configTheme - > addItem ( " Theme Jet " , QCPColorGradient : : gpJet ) ;
configTheme - > addItem ( " Theme Cold " , QCPColorGradient : : gpCold ) ;
configTheme - > addItem ( " Theme Hot " , QCPColorGradient : : gpHot ) ;
configTheme - > addItem ( " Theme Therm " , QCPColorGradient : : gpThermal ) ;
configTheme - > addItem ( " Theme Night " , QCPColorGradient : : gpNight ) ;
configTheme - > addItem ( " Theme Ion " , QCPColorGradient : : gpIon ) ;
configTheme - > addItem ( " Theme Gray " , QCPColorGradient : : gpGrayscale ) ;
configTheme - > addItem ( " Theme Geo " , QCPColorGradient : : gpGeography ) ;
configTheme - > addItem ( " Theme Hues " , QCPColorGradient : : gpHues ) ;
configTheme - > addItem ( " Theme Polar " , QCPColorGradient : : gpPolar ) ;
configTheme - > addItem ( " Theme Spect " , QCPColorGradient : : gpSpectrum ) ;
configTheme - > addItem ( " Theme Candy " , QCPColorGradient : : gpCandy ) ;
configTheme - > setSizeAdjustPolicy ( QComboBox : : AdjustToContents ) ;
configLayout - > addRow ( " Theme " , configTheme ) ;
configPbtInner = new QSlider ( Qt : : Orientation : : Horizontal ) ;
configPbtInner - > setRange ( 0 , 255 ) ;
configLayout - > addRow ( " PBT Inner " , configPbtInner ) ;
configPbtOuter = new QSlider ( Qt : : Orientation : : Horizontal ) ;
configPbtOuter - > setRange ( 0 , 255 ) ;
configLayout - > addRow ( " PBT Outer " , configPbtOuter ) ;
configIfShift = new QSlider ( Qt : : Orientation : : Horizontal ) ;
configIfShift - > setRange ( 0 , 255 ) ;
configLayout - > addRow ( " IF Shift " , configIfShift ) ;
configFilterWidth = new QSlider ( Qt : : Orientation : : Horizontal ) ;
configFilterWidth - > setRange ( 0 , 10000 ) ;
configLayout - > addRow ( " Fil Width " , configFilterWidth ) ;
connect ( configLength , & QSlider : : valueChanged , this , [ = ] ( const int & val ) {
prepareWf ( val ) ;
2024-01-27 22:13:47 +00:00
emit updateSettings ( vfo , currentTheme , wfLength , plotFloor , plotCeiling ) ;
2023-09-24 23:11:37 +00:00
} ) ;
connect ( configBottom , & QSlider : : valueChanged , this , [ = ] ( const int & val ) {
this - > plotFloor = val ;
2023-09-26 09:32:56 +00:00
this - > wfFloor = val ;
2023-09-24 23:11:37 +00:00
this - > setRange ( plotFloor , plotCeiling ) ;
2024-01-27 22:13:47 +00:00
emit updateSettings ( vfo , currentTheme , wfLength , plotFloor , plotCeiling ) ;
2023-09-24 23:11:37 +00:00
} ) ;
connect ( configTop , & QSlider : : valueChanged , this , [ = ] ( const int & val ) {
this - > plotCeiling = val ;
2023-09-26 09:32:56 +00:00
this - > wfCeiling = val ;
2023-09-24 23:11:37 +00:00
this - > setRange ( plotFloor , plotCeiling ) ;
2024-01-27 22:13:47 +00:00
emit updateSettings ( vfo , currentTheme , wfLength , plotFloor , plotCeiling ) ;
2023-09-24 23:11:37 +00:00
} ) ;
connect ( configRef , & QSlider : : valueChanged , this , [ = ] ( const int & val ) {
currentRef = ( val / 5 ) * 5 ; // rounded to "nearest 5"
2024-01-27 22:13:47 +00:00
queue - > add ( priorityImmediate , queueItem ( vfo ? funcScopeSubRef : funcScopeMainRef , QVariant : : fromValue ( currentRef ) , false , this - > vfo ) ) ;
2023-09-24 23:11:37 +00:00
} ) ;
connect ( configSpeed , QOverload < int > : : of ( & QComboBox : : currentIndexChanged ) , this , [ = ] ( const int & val ) {
2024-01-27 22:13:47 +00:00
queue - > add ( priorityImmediate , queueItem ( vfo ? funcScopeSubSpeed : funcScopeMainSpeed , configSpeed - > itemData ( val ) , false , this - > vfo ) ) ;
2023-09-24 23:11:37 +00:00
} ) ;
connect ( configTheme , QOverload < int > : : of ( & QComboBox : : currentIndexChanged ) , this , [ = ] ( const int & val ) {
Q_UNUSED ( val )
currentTheme = configTheme - > currentData ( ) . value < QCPColorGradient : : GradientPreset > ( ) ;
colorMap - > setGradient ( currentTheme ) ;
2024-01-27 22:13:47 +00:00
emit updateSettings ( vfo , currentTheme , wfLength , plotFloor , plotCeiling ) ;
2023-09-24 23:11:37 +00:00
} ) ;
connect ( configPbtInner , & QSlider : : valueChanged , this , [ = ] ( const int & val ) {
2024-01-27 22:13:47 +00:00
queue - > add ( priorityImmediate , queueItem ( funcPBTInner , QVariant : : fromValue < ushort > ( val ) , false , vfo ) ) ;
2023-09-24 23:11:37 +00:00
} ) ;
connect ( configPbtOuter , & QSlider : : valueChanged , this , [ = ] ( const int & val ) {
2024-01-27 22:13:47 +00:00
queue - > add ( priorityImmediate , queueItem ( funcPBTInner , QVariant : : fromValue < ushort > ( val ) , false , vfo ) ) ;
2023-09-24 23:11:37 +00:00
} ) ;
connect ( configIfShift , & QSlider : : valueChanged , this , [ = ] ( const int & val ) {
2024-01-27 22:13:47 +00:00
queue - > add ( priorityImmediate , queueItem ( funcIFShift , QVariant : : fromValue < ushort > ( val ) , false , vfo ) ) ;
2023-09-24 23:11:37 +00:00
} ) ;
connect ( configFilterWidth , & QSlider : : valueChanged , this , [ = ] ( const int & val ) {
2024-01-27 22:13:47 +00:00
queue - > add ( priorityImmediate , queueItem ( funcFilterWidth , QVariant : : fromValue < ushort > ( val ) , false , vfo ) ) ;
2023-09-24 23:11:37 +00:00
} ) ;
configGroup - > setVisible ( false ) ;
// Connections
2023-06-05 08:27:37 +00:00
2024-01-21 20:36:52 +00:00
connect ( detachButton , SIGNAL ( toggled ( bool ) ) , this , SLOT ( detachScope ( bool ) ) ) ;
2023-06-05 08:27:37 +00:00
connect ( scopeModeCombo , SIGNAL ( currentIndexChanged ( int ) ) , this , SLOT ( updatedScopeMode ( int ) ) ) ;
connect ( spanCombo , SIGNAL ( currentIndexChanged ( int ) ) , this , SLOT ( updatedSpan ( int ) ) ) ;
2023-09-25 18:35:22 +00:00
connect ( confButton , SIGNAL ( clicked ( ) ) , this , SLOT ( configPressed ( ) ) , Qt : : QueuedConnection ) ;
2023-06-05 08:27:37 +00:00
2023-09-25 18:35:22 +00:00
connect ( toFixedButton , SIGNAL ( clicked ( ) ) , this , SLOT ( toFixedPressed ( ) ) ) ;
2023-06-05 08:27:37 +00:00
connect ( edgeCombo , SIGNAL ( currentIndexChanged ( int ) ) , this , SLOT ( updatedEdge ( int ) ) ) ;
2023-09-25 18:35:22 +00:00
connect ( edgeButton , SIGNAL ( clicked ( ) ) , this , SLOT ( customSpanPressed ( ) ) ) ;
2023-06-05 08:27:37 +00:00
2023-06-08 20:58:22 +00:00
connect ( holdButton , SIGNAL ( toggled ( bool ) ) , this , SLOT ( holdPressed ( bool ) ) ) ;
2023-06-05 08:27:37 +00:00
connect ( modeCombo , SIGNAL ( currentIndexChanged ( int ) ) , this , SLOT ( updatedMode ( int ) ) ) ;
connect ( filterCombo , SIGNAL ( currentIndexChanged ( int ) ) , this , SLOT ( updatedMode ( int ) ) ) ;
connect ( dataCombo , SIGNAL ( currentIndexChanged ( int ) ) , this , SLOT ( updatedMode ( int ) ) ) ;
2023-09-25 18:35:22 +00:00
connect ( clearPeaksButton , SIGNAL ( clicked ( ) ) , this , SLOT ( clearPeaks ( ) ) ) ;
2023-06-05 08:27:37 +00:00
2023-06-05 20:08:01 +00:00
connect ( spectrum , SIGNAL ( mouseDoubleClick ( QMouseEvent * ) ) , this , SLOT ( doubleClick ( QMouseEvent * ) ) ) ;
connect ( waterfall , SIGNAL ( mouseDoubleClick ( QMouseEvent * ) ) , this , SLOT ( doubleClick ( QMouseEvent * ) ) ) ;
2023-06-05 08:27:37 +00:00
connect ( spectrum , SIGNAL ( mousePress ( QMouseEvent * ) ) , this , SLOT ( scopeClick ( QMouseEvent * ) ) ) ;
connect ( waterfall , SIGNAL ( mousePress ( QMouseEvent * ) ) , this , SLOT ( waterfallClick ( QMouseEvent * ) ) ) ;
connect ( spectrum , SIGNAL ( mouseRelease ( QMouseEvent * ) ) , this , SLOT ( scopeMouseRelease ( QMouseEvent * ) ) ) ;
connect ( spectrum , SIGNAL ( mouseMove ( QMouseEvent * ) ) , this , SLOT ( scopeMouseMove ( QMouseEvent * ) ) ) ;
connect ( waterfall , SIGNAL ( mouseWheel ( QWheelEvent * ) ) , this , SLOT ( scroll ( QWheelEvent * ) ) ) ;
connect ( spectrum , SIGNAL ( mouseWheel ( QWheelEvent * ) ) , this , SLOT ( scroll ( QWheelEvent * ) ) ) ;
2023-09-26 17:46:04 +00:00
connect ( freqDisplay , SIGNAL ( newFrequency ( qint64 ) ) , this , SLOT ( newFrequency ( qint64 ) ) ) ;
2023-06-05 08:27:37 +00:00
showHideControls ( spectrumMode_t : : spectModeCenter ) ;
2023-06-01 16:57:44 +00:00
}
2023-06-11 09:33:16 +00:00
void spectrumScope : : prepareScope ( uint maxAmp , uint spectWidth )
{
this - > spectWidth = spectWidth ;
this - > maxAmp = maxAmp ;
}
2023-06-05 08:27:37 +00:00
2023-06-01 16:57:44 +00:00
bool spectrumScope : : prepareWf ( uint wf )
{
QMutexLocker locker ( & mutex ) ;
bool ret = true ;
this - > wfLength = wf ;
2023-09-26 09:32:56 +00:00
configLength - > blockSignals ( true ) ;
configLength - > setValue ( this - > wfLength ) ;
configLength - > blockSignals ( false ) ;
2023-06-01 16:57:44 +00:00
this - > wfLengthMax = 1024 ;
// Initialize before use!
QByteArray empty ( ( int ) spectWidth , ' \x01 ' ) ;
spectrumPeaks = QByteArray ( ( int ) spectWidth , ' \x01 ' ) ;
2023-07-06 09:36:11 +00:00
//unsigned int oldSize = wfimage.size();
if ( ! wfimage . empty ( ) & & wfimage . first ( ) . size ( ) ! = spectWidth )
2023-06-01 16:57:44 +00:00
{
2023-07-06 09:36:11 +00:00
// Width of waterfall has changed!
wfimage . clear ( ) ;
2023-06-01 16:57:44 +00:00
}
2023-07-06 09:36:11 +00:00
for ( unsigned int i = wfimage . size ( ) ; i < wfLength ; i + + )
{
wfimage . append ( empty ) ;
}
wfimage . remove ( wfLength , wfimage . size ( ) - wfLength ) ;
2023-06-01 16:57:44 +00:00
wfimage . squeeze ( ) ;
2023-07-06 09:36:11 +00:00
2023-06-01 16:57:44 +00:00
colorMap - > data ( ) - > clear ( ) ;
colorMap - > data ( ) - > setValueRange ( QCPRange ( 0 , wfLength - 1 ) ) ;
colorMap - > data ( ) - > setKeyRange ( QCPRange ( 0 , spectWidth - 1 ) ) ;
colorMap - > setDataRange ( QCPRange ( plotFloor , plotCeiling ) ) ;
colorMap - > setGradient ( static_cast < QCPColorGradient : : GradientPreset > ( currentTheme ) ) ;
if ( colorMapData ! = Q_NULLPTR )
{
delete colorMapData ;
}
colorMapData = new QCPColorMapData ( spectWidth , wfLength , QCPRange ( 0 , spectWidth - 1 ) , QCPRange ( 0 , wfLength - 1 ) ) ;
2023-07-06 09:36:11 +00:00
colorMap - > setData ( colorMapData , true ) ; // Copy the colorMap so deleting it won't result in crash!
2023-06-01 16:57:44 +00:00
waterfall - > yAxis - > setRangeReversed ( true ) ;
waterfall - > xAxis - > setVisible ( false ) ;
2024-02-05 19:25:27 +00:00
clearPeaks ( ) ;
clearPlasma ( ) ;
2023-06-01 16:57:44 +00:00
scopePrepared = true ;
return ret ;
}
void spectrumScope : : setRange ( int floor , int ceiling )
{
2023-09-26 09:32:56 +00:00
plotFloor = floor ;
plotCeiling = ceiling ;
2024-02-06 05:39:23 +00:00
wfFloor = floor ;
wfCeiling = ceiling ;
2023-06-01 16:57:44 +00:00
maxAmp = ceiling ;
if ( spectrum ! = Q_NULLPTR )
spectrum - > yAxis - > setRange ( QCPRange ( floor , ceiling ) ) ;
if ( colorMap ! = Q_NULLPTR )
colorMap - > setDataRange ( QCPRange ( floor , ceiling ) ) ;
2023-09-26 09:32:56 +00:00
configBottom - > blockSignals ( true ) ;
configBottom - > setValue ( floor ) ;
configBottom - > blockSignals ( false ) ;
configTop - > blockSignals ( true ) ;
configTop - > setValue ( ceiling ) ;
configTop - > blockSignals ( false ) ;
2023-06-01 16:57:44 +00:00
}
void spectrumScope : : colorPreset ( colorPrefsType * cp )
{
if ( cp = = Q_NULLPTR )
{
return ;
}
colors = * cp ;
spectrum - > setBackground ( cp - > plotBackground ) ;
spectrum - > xAxis - > grid ( ) - > setPen ( cp - > gridColor ) ;
spectrum - > yAxis - > grid ( ) - > setPen ( cp - > gridColor ) ;
spectrum - > legend - > setTextColor ( cp - > textColor ) ;
spectrum - > legend - > setBorderPen ( cp - > gridColor ) ;
spectrum - > legend - > setBrush ( cp - > gridColor ) ;
spectrum - > xAxis - > setTickLabelColor ( cp - > textColor ) ;
spectrum - > xAxis - > setLabelColor ( cp - > gridColor ) ;
spectrum - > yAxis - > setTickLabelColor ( cp - > textColor ) ;
spectrum - > yAxis - > setLabelColor ( cp - > gridColor ) ;
spectrum - > xAxis - > setBasePen ( cp - > axisColor ) ;
spectrum - > xAxis - > setTickPen ( cp - > axisColor ) ;
spectrum - > yAxis - > setBasePen ( cp - > axisColor ) ;
spectrum - > yAxis - > setTickPen ( cp - > axisColor ) ;
freqIndicatorLine - > setPen ( QPen ( cp - > tuningLine ) ) ;
passbandIndicator - > setPen ( QPen ( cp - > passband ) ) ;
passbandIndicator - > setBrush ( QBrush ( cp - > passband ) ) ;
pbtIndicator - > setPen ( QPen ( cp - > pbt ) ) ;
pbtIndicator - > setBrush ( QBrush ( cp - > pbt ) ) ;
spectrum - > graph ( 0 ) - > setPen ( QPen ( cp - > spectrumLine ) ) ;
spectrum - > graph ( 0 ) - > setBrush ( QBrush ( cp - > spectrumFill ) ) ;
spectrum - > graph ( 1 ) - > setPen ( QPen ( cp - > underlayLine ) ) ;
spectrum - > graph ( 1 ) - > setBrush ( QBrush ( cp - > underlayFill ) ) ;
waterfall - > yAxis - > setBasePen ( cp - > wfAxis ) ;
waterfall - > yAxis - > setTickPen ( cp - > wfAxis ) ;
waterfall - > xAxis - > setBasePen ( cp - > wfAxis ) ;
waterfall - > xAxis - > setTickPen ( cp - > wfAxis ) ;
waterfall - > xAxis - > setLabelColor ( cp - > wfGrid ) ;
waterfall - > yAxis - > setLabelColor ( cp - > wfGrid ) ;
waterfall - > xAxis - > setTickLabelColor ( cp - > wfText ) ;
waterfall - > yAxis - > setTickLabelColor ( cp - > wfText ) ;
waterfall - > setBackground ( cp - > wfBackground ) ;
}
2024-01-27 22:13:47 +00:00
bool spectrumScope : : updateScope ( scopeData data )
2023-06-01 16:57:44 +00:00
{
if ( ! scopePrepared )
{
return false ;
}
2023-09-19 22:04:48 +00:00
2024-01-22 12:19:31 +00:00
qint64 spectime = 0 ;
2024-01-22 12:23:51 +00:00
2023-09-19 22:04:48 +00:00
QElapsedTimer elapsed ;
2023-06-01 16:57:44 +00:00
bool updateRange = false ;
if ( data . startFreq ! = lowerFreq | | data . endFreq ! = upperFreq )
{
if ( underlayMode = = underlayPeakHold )
{
// TODO: create non-button function to do this
// This will break if the button is ever moved or renamed.
clearPeaks ( ) ;
}
// Inform other threads (cluster) that the frequency range has changed.
2024-01-27 22:13:47 +00:00
emit frequencyRange ( vfo , data . startFreq , data . endFreq ) ;
2023-06-01 16:57:44 +00:00
}
lowerFreq = data . startFreq ;
upperFreq = data . endFreq ;
//qInfo(logSystem()) << "start: " << data.startFreq << " end: " << data.endFreq;
quint16 specLen = data . data . length ( ) ;
2023-09-23 10:37:55 +00:00
if ( specLen ! = spectWidth )
{
qCritical ( logSystem ( ) ) < < " Spectrum length error! Expected " < < spectWidth < < " got " < < specLen ;
return false ;
}
2023-06-01 16:57:44 +00:00
QVector < double > x ( spectWidth ) , y ( spectWidth ) , y2 ( spectWidth ) ;
for ( int i = 0 ; i < spectWidth ; i + + )
{
x [ i ] = ( i * ( data . endFreq - data . startFreq ) / spectWidth ) + data . startFreq ;
}
for ( int i = 0 ; i < specLen ; i + + )
{
y [ i ] = ( unsigned char ) data . data . at ( i ) ;
if ( underlayMode = = underlayPeakHold )
{
if ( ( unsigned char ) data . data . at ( i ) > ( unsigned char ) spectrumPeaks . at ( i ) )
{
spectrumPeaks [ i ] = data . data . at ( i ) ;
}
y2 [ i ] = ( unsigned char ) spectrumPeaks . at ( i ) ;
}
}
plasmaMutex . lock ( ) ;
2024-02-05 19:25:27 +00:00
spectrumPlasma [ spectrumPlasmaPosition ] = data . data ;
spectrumPlasmaPosition = ( spectrumPlasmaPosition + 1 ) % spectrumPlasmaSizeCurrent ;
//spectrumPlasma.push_front(data.data);
// if(spectrumPlasma.size() > (int)spectrumPlasmaSizeCurrent)
// {
// // If we have pushed_front more than spectrumPlasmaSize,
// // then we cut one off the back.
// spectrumPlasma.pop_back();
// }
2023-06-01 16:57:44 +00:00
plasmaMutex . unlock ( ) ;
QMutexLocker locker ( & mutex ) ;
if ( ( plotFloor ! = oldPlotFloor ) | | ( plotCeiling ! = oldPlotCeiling ) ) {
updateRange = true ;
}
# if QCUSTOMPLOT_VERSION < 0x020000
spectrum - > graph ( 0 ) - > setData ( x , y ) ;
# else
spectrum - > graph ( 0 ) - > setData ( x , y , true ) ;
# endif
2024-01-22 12:19:31 +00:00
2023-06-01 16:57:44 +00:00
if ( ( freq . MHzDouble < data . endFreq ) & & ( freq . MHzDouble > data . startFreq ) )
{
freqIndicatorLine - > start - > setCoords ( freq . MHzDouble , 0 ) ;
freqIndicatorLine - > end - > setCoords ( freq . MHzDouble , maxAmp ) ;
double pbStart = 0.0 ;
double pbEnd = 0.0 ;
2023-06-05 08:27:37 +00:00
switch ( mode . mk )
2023-06-01 16:57:44 +00:00
{
case modeLSB :
case modeRTTY :
case modePSK_R :
pbStart = freq . MHzDouble - passbandCenterFrequency - ( passbandWidth / 2 ) ;
pbEnd = freq . MHzDouble - passbandCenterFrequency + ( passbandWidth / 2 ) ;
break ;
case modeCW :
if ( passbandWidth < 0.0006 ) {
pbStart = freq . MHzDouble - ( passbandWidth / 2 ) ;
pbEnd = freq . MHzDouble + ( passbandWidth / 2 ) ;
}
else {
pbStart = freq . MHzDouble + passbandCenterFrequency - passbandWidth ;
pbEnd = freq . MHzDouble + passbandCenterFrequency ;
}
break ;
case modeCW_R :
if ( passbandWidth < 0.0006 ) {
pbStart = freq . MHzDouble - ( passbandWidth / 2 ) ;
pbEnd = freq . MHzDouble + ( passbandWidth / 2 ) ;
}
else {
pbStart = freq . MHzDouble - passbandCenterFrequency ;
pbEnd = freq . MHzDouble + passbandWidth - passbandCenterFrequency ;
}
2023-12-24 16:22:13 +00:00
break ;
2023-06-01 16:57:44 +00:00
default :
pbStart = freq . MHzDouble + passbandCenterFrequency - ( passbandWidth / 2 ) ;
pbEnd = freq . MHzDouble + passbandCenterFrequency + ( passbandWidth / 2 ) ;
break ;
}
passbandIndicator - > topLeft - > setCoords ( pbStart , 0 ) ;
passbandIndicator - > bottomRight - > setCoords ( pbEnd , maxAmp ) ;
2023-06-05 08:27:37 +00:00
if ( ( mode . mk = = modeCW | | mode . mk = = modeCW_R ) & & passbandWidth > 0.0006 )
2023-06-01 16:57:44 +00:00
{
pbtDefault = round ( ( passbandWidth - ( cwPitch / 1000000.0 ) ) * 200000.0 ) / 200000.0 ;
}
else
{
pbtDefault = 0.0 ;
}
2023-06-05 08:27:37 +00:00
if ( ( PBTInner - pbtDefault | | PBTOuter - pbtDefault ) & & passbandAction ! = passbandResizing & & mode . mk ! = modeFM )
2023-06-01 16:57:44 +00:00
{
pbtIndicator - > setVisible ( true ) ;
}
else
{
pbtIndicator - > setVisible ( false ) ;
}
/*
pbtIndicator displays the intersection between PBTInner and PBTOuter
*/
2023-06-05 08:27:37 +00:00
if ( mode . mk = = modeLSB | | mode . mk = = modeCW | | mode . mk = = modeRTTY ) {
2023-06-01 16:57:44 +00:00
pbtIndicator - > topLeft - > setCoords ( qMax ( pbStart - ( PBTInner / 2 ) + ( pbtDefault / 2 ) , pbStart - ( PBTOuter / 2 ) + ( pbtDefault / 2 ) ) , 0 ) ;
pbtIndicator - > bottomRight - > setCoords ( qMin ( pbStart - ( PBTInner / 2 ) + ( pbtDefault / 2 ) + passbandWidth ,
pbStart - ( PBTOuter / 2 ) + ( pbtDefault / 2 ) + passbandWidth ) , maxAmp ) ;
}
else
{
pbtIndicator - > topLeft - > setCoords ( qMax ( pbStart + ( PBTInner / 2 ) - ( pbtDefault / 2 ) , pbStart + ( PBTOuter / 2 ) - ( pbtDefault / 2 ) ) , 0 ) ;
pbtIndicator - > bottomRight - > setCoords ( qMin ( pbStart + ( PBTInner / 2 ) - ( pbtDefault / 2 ) + passbandWidth ,
pbStart + ( PBTOuter / 2 ) - ( pbtDefault / 2 ) + passbandWidth ) , maxAmp ) ;
}
//qDebug() << "Default" << pbtDefault << "Inner" << PBTInner << "Outer" << PBTOuter << "Pass" << passbandWidth << "Center" << passbandCenterFrequency << "CW" << cwPitch;
}
# if QCUSTOMPLOT_VERSION < 0x020000
if ( underlayMode = = underlayPeakHold ) {
spectrum - > graph ( 1 ) - > setData ( x , y2 ) ; // peaks
}
else if ( underlayMode ! = underlayNone ) {
computePlasma ( ) ;
spectrum - > graph ( 1 ) - > setData ( x , spectrumPlasmaLine ) ;
}
else {
spectrum - > graph ( 1 ) - > setData ( x , y2 ) ; // peaks, but probably cleared out
}
# else
if ( underlayMode = = underlayPeakHold ) {
spectrum - > graph ( 1 ) - > setData ( x , y2 , true ) ; // peaks
}
else if ( underlayMode ! = underlayNone ) {
computePlasma ( ) ;
spectrum - > graph ( 1 ) - > setData ( x , spectrumPlasmaLine , true ) ;
}
else {
spectrum - > graph ( 1 ) - > setData ( x , y2 , true ) ; // peaks, but probably cleared out
}
# endif
if ( updateRange )
spectrum - > yAxis - > setRange ( plotFloor , plotCeiling ) ;
spectrum - > xAxis - > setRange ( data . startFreq , data . endFreq ) ;
2024-01-22 12:23:51 +00:00
elapsed . start ( ) ;
2023-06-01 16:57:44 +00:00
spectrum - > replot ( ) ;
2024-01-22 12:19:31 +00:00
spectime = elapsed . elapsed ( ) ;
2023-06-01 16:57:44 +00:00
if ( specLen = = spectWidth )
{
wfimage . prepend ( data . data ) ;
wfimage . pop_back ( ) ;
QByteArray wfRow ;
// Waterfall:
for ( int row = 0 ; row < wfLength ; row + + )
{
wfRow = wfimage . at ( row ) ;
for ( int col = 0 ; col < spectWidth ; col + + )
{
colorMap - > data ( ) - > setCell ( col , row , ( unsigned char ) wfRow . at ( col ) ) ;
}
}
if ( updateRange )
{
colorMap - > setDataRange ( QCPRange ( wfFloor , wfCeiling ) ) ;
}
waterfall - > yAxis - > setRange ( 0 , wfLength - 1 ) ;
waterfall - > xAxis - > setRange ( 0 , spectWidth - 1 ) ;
2024-01-22 12:23:51 +00:00
elapsed . start ( ) ;
2023-06-01 16:57:44 +00:00
waterfall - > replot ( ) ;
2024-01-22 12:23:51 +00:00
redrawSpeed - > setText ( QString ( " %0ms/%1ms " ) . arg ( spectime ) . arg ( elapsed . elapsed ( ) ) ) ;
2023-06-01 16:57:44 +00:00
/*
# if defined (USB_CONTROLLER)
// Send to USB Controllers if requested
auto i = usbDevices . begin ( ) ;
while ( i ! = usbDevices . end ( ) )
{
if ( i . value ( ) . connected & & i . value ( ) . type . model = = usbDeviceType : : StreamDeckPlus & & i . value ( ) . lcd = = funcLCDWaterfall )
{
lcdImage = waterfall - > toPixmap ( ) . toImage ( ) ;
emit sendControllerRequest ( & i . value ( ) , usbFeatureType : : featureLCD , 0 , " " , & lcdImage ) ;
}
else if ( i . value ( ) . connected & & i . value ( ) . type . model = = usbDeviceType : : StreamDeckPlus & & i . value ( ) . lcd = = funcLCDSpectrum )
{
lcdImage = spectrum - > toPixmap ( ) . toImage ( ) ;
emit sendControllerRequest ( & i . value ( ) , usbFeatureType : : featureLCD , 0 , " " , & lcdImage ) ;
}
+ + i ;
}
# endif
*/
}
oldPlotFloor = plotFloor ;
oldPlotCeiling = plotCeiling ;
if ( data . oor & & ! oorIndicator - > visible ( ) ) {
oorIndicator - > setVisible ( true ) ;
qInfo ( logSystem ( ) ) < < " Scope out of range " ;
} else if ( ! data . oor & & oorIndicator - > visible ( ) ) {
oorIndicator - > setVisible ( false ) ;
}
2024-01-22 12:23:51 +00:00
2024-01-27 22:13:47 +00:00
emit elapsedTime ( vfo , elapsed . elapsed ( ) ) ;
2023-06-01 16:57:44 +00:00
return true ;
}
// Plasma functions
void spectrumScope : : resizePlasmaBuffer ( int size ) {
2024-02-05 19:25:27 +00:00
// QMutexLocker locker(&plasmaMutex);
qDebug ( ) < < " Resizing plasma buffer via parameter, from oldsize " < < spectrumPlasmaSizeCurrent < < " to new size: " < < size ;
spectrumPlasmaSizeCurrent = size ;
return ;
2023-06-01 16:57:44 +00:00
}
void spectrumScope : : clearPeaks ( )
{
2024-02-05 19:25:27 +00:00
// Clear the spectrum peaks as well as the plasma buffer
2023-06-01 16:57:44 +00:00
spectrumPeaks = QByteArray ( ( int ) spectWidth , ' \x01 ' ) ;
2024-02-05 19:25:27 +00:00
//clearPlasma();
2023-06-01 16:57:44 +00:00
}
void spectrumScope : : clearPlasma ( )
{
2024-02-05 19:25:27 +00:00
// Clear the buffer of spectrum used for peak and average computation.
// This is only needed one time, when the VFO is created with spectrum size info.
2023-06-01 16:57:44 +00:00
QMutexLocker locker ( & plasmaMutex ) ;
QByteArray empty ( ( int ) spectWidth , ' \x01 ' ) ;
int pSize = spectrumPlasma . size ( ) ;
for ( int i = 0 ; i < pSize ; i + + )
{
spectrumPlasma [ i ] = empty ;
}
}
void spectrumScope : : computePlasma ( )
{
QMutexLocker locker ( & plasmaMutex ) ;
2024-02-05 19:25:27 +00:00
// Spec PlasmaLine is a single line of spectrum, ~~600 pixels or however many the radio provides.
// This changes width only when we connect to a new radio.
if ( spectrumPlasmaLine . size ( ) ! = spectWidth ) {
spectrumPlasmaLine . clear ( ) ;
spectrumPlasmaLine . resize ( spectWidth ) ;
}
// spectrumPlasma is the bufffer of spectrum lines to use when computing the average or peak.
int specPlasmaSize = spectrumPlasmaSizeCurrent ; // go only this far in
2023-06-01 16:57:44 +00:00
if ( underlayMode = = underlayAverageBuffer )
{
for ( int col = 0 ; col < spectWidth ; col + + )
{
for ( int pos = 0 ; pos < specPlasmaSize ; pos + + )
{
2024-02-05 19:25:27 +00:00
spectrumPlasmaLine [ col ] + = ( unsigned char ) spectrumPlasma . at ( pos ) . at ( col ) ;
2023-06-01 16:57:44 +00:00
}
2024-02-05 19:25:27 +00:00
spectrumPlasmaLine [ col ] = spectrumPlasmaLine . at ( col ) / specPlasmaSize ;
2023-06-01 16:57:44 +00:00
}
} else if ( underlayMode = = underlayPeakBuffer ) {
// peak mode, running peak display
for ( int col = 0 ; col < spectWidth ; col + + )
{
2024-02-05 19:25:27 +00:00
spectrumPlasmaLine [ col ] = spectrumPlasma . at ( 0 ) . at ( col ) ; // initial value
2023-06-01 16:57:44 +00:00
for ( int pos = 0 ; pos < specPlasmaSize ; pos + + )
{
2024-02-05 19:25:27 +00:00
if ( ( double ) ( ( unsigned char ) spectrumPlasma . at ( pos ) . at ( col ) ) > spectrumPlasmaLine . at ( col ) )
spectrumPlasmaLine [ col ] = ( unsigned char ) spectrumPlasma . at ( pos ) . at ( col ) ;
2023-06-01 16:57:44 +00:00
}
}
}
}
2023-06-05 08:27:37 +00:00
void spectrumScope : : showHideControls ( spectrumMode_t mode )
{
if ( ( mode = = spectModeCenter ) | | ( mode = = spectModeScrollC ) )
{
edgeCombo - > hide ( ) ;
edgeButton - > hide ( ) ;
toFixedButton - > show ( ) ;
spanCombo - > show ( ) ;
} else {
edgeCombo - > show ( ) ;
edgeButton - > show ( ) ;
toFixedButton - > hide ( ) ;
spanCombo - > hide ( ) ;
}
}
2023-06-11 21:31:32 +00:00
void spectrumScope : : enableScope ( bool en )
{
this - > splitter - > setVisible ( en ) ;
// Hide these controls if disabled
if ( ! en ) {
this - > edgeCombo - > setVisible ( en ) ;
this - > edgeButton - > setVisible ( en ) ;
this - > toFixedButton - > setVisible ( en ) ;
this - > spanCombo - > setVisible ( en ) ;
}
this - > clearPeaksButton - > setVisible ( en ) ;
this - > holdButton - > setVisible ( en ) ;
}
2023-06-05 08:27:37 +00:00
void spectrumScope : : selectScopeMode ( spectrumMode_t m )
{
scopeModeCombo - > blockSignals ( true ) ;
scopeModeCombo - > setCurrentIndex ( scopeModeCombo - > findData ( m ) ) ;
scopeModeCombo - > blockSignals ( false ) ;
showHideControls ( m ) ;
}
void spectrumScope : : selectSpan ( centerSpanData s )
{
spanCombo - > blockSignals ( true ) ;
spanCombo - > setCurrentIndex ( spanCombo - > findText ( s . name ) ) ;
spanCombo - > blockSignals ( false ) ;
}
void spectrumScope : : updatedScopeMode ( int index )
{
//spectrumMode_t s = static_cast<spectrumMode_t>(scopeModeCombo->itemData(index).toInt());
spectrumMode_t s = scopeModeCombo - > itemData ( index ) . value < spectrumMode_t > ( ) ;
2024-01-27 22:13:47 +00:00
queue - > add ( priorityImmediate , queueItem ( ( vfo ? funcScopeSubMode : funcScopeMainMode ) , QVariant : : fromValue ( s ) , false , vfo ) ) ;
2023-06-05 08:27:37 +00:00
showHideControls ( s ) ;
}
void spectrumScope : : updatedSpan ( int index )
{
2024-01-27 22:13:47 +00:00
queue - > add ( priorityImmediate , queueItem ( ( vfo ? funcScopeSubSpan : funcScopeMainSpan ) , spanCombo - > itemData ( index ) , false , vfo ) ) ;
2023-06-05 08:27:37 +00:00
}
void spectrumScope : : updatedMode ( int index )
{
Q_UNUSED ( index ) // We don't know where it came from!
modeInfo mi = modeCombo - > currentData ( ) . value < modeInfo > ( ) ;
mi . filter = filterCombo - > currentData ( ) . toInt ( ) ;
2024-01-28 09:42:50 +00:00
if ( mi . mk = = modeCW | | mi . mk = = modeCW_R | | mi . mk = = modeRTTY | | mi . mk = = modeRTTY_R | | mi . mk = = modePSK | | mi . mk = = modePSK_R )
{
mi . data = 0 ;
dataCombo - > setEnabled ( false ) ;
} else {
mi . data = dataCombo - > currentIndex ( ) ;
dataCombo - > setEnabled ( true ) ;
}
2024-01-27 22:13:47 +00:00
queue - > add ( priorityImmediate , queueItem ( ( vfo ? funcUnselectedMode : funcSelectedMode ) , QVariant : : fromValue ( mi ) , false , vfo ) ) ;
2023-12-24 16:22:13 +00:00
2023-06-05 08:27:37 +00:00
}
void spectrumScope : : updatedEdge ( int index )
{
2024-01-27 22:13:47 +00:00
queue - > add ( priorityImmediate , queueItem ( ( vfo ? funcScopeSubEdge : funcScopeMainEdge ) , QVariant : : fromValue < uchar > ( index + 1 ) , false , vfo ) ) ;
2023-06-05 08:27:37 +00:00
}
void spectrumScope : : toFixedPressed ( )
{
int currentEdge = edgeCombo - > currentIndex ( ) ;
bool dialogOk = false ;
bool numOk = false ;
QStringList edges ;
edges < < " 1 " < < " 2 " < < " 3 " < < " 4 " ;
QString item = QInputDialog : : getItem ( this , " Select Edge " , " Edge to replace: " , edges , currentEdge , false , & dialogOk ) ;
if ( dialogOk )
{
int edge = QString ( item ) . toInt ( & numOk , 10 ) ;
if ( numOk )
{
edgeCombo - > blockSignals ( true ) ;
edgeCombo - > setCurrentIndex ( edge - 1 ) ;
edgeCombo - > blockSignals ( false ) ;
2024-01-27 22:13:47 +00:00
queue - > add ( priorityImmediate , queueItem ( funcScopeFixedEdgeFreq , QVariant : : fromValue ( spectrumBounds ( lowerFreq , upperFreq , edge ) ) , false , vfo ) ) ;
queue - > add ( priorityImmediate , queueItem ( ( vfo ? funcScopeSubMode : funcScopeMainMode ) , QVariant : : fromValue < uchar > ( spectrumMode_t : : spectModeFixed ) , false , vfo ) ) ;
2023-06-05 08:27:37 +00:00
}
}
}
void spectrumScope : : customSpanPressed ( )
{
double lowFreq = lowerFreq ;
double highFreq = upperFreq ;
QString freqstring = QString ( " %1, %2 " ) . arg ( lowFreq ) . arg ( highFreq ) ;
bool ok ;
QString userFreq = QInputDialog : : getText ( this , " Scope Edges " ,
" Please enter desired scope edges, in MHz, \n with a comma between the low and high range. " ,
QLineEdit : : Normal , freqstring , & ok ) ;
if ( ! ok )
return ;
QString clean = userFreq . trimmed ( ) . replace ( " " , " " ) ;
QStringList freqs = clean . split ( " , " ) ;
if ( freqs . length ( ) = = 2 )
{
lowFreq = QString ( freqs . at ( 0 ) ) . toDouble ( & ok ) ;
if ( ok )
{
highFreq = QString ( freqs . at ( 1 ) ) . toDouble ( & ok ) ;
if ( ok )
{
qDebug ( logGui ( ) ) < < " setting edge to: " < < lowFreq < < " , " < < highFreq < < " , edge num: " < < edgeCombo - > currentIndex ( ) + 1 ;
queue - > add ( priorityImmediate , queueItem ( funcScopeFixedEdgeFreq ,
QVariant : : fromValue ( spectrumBounds ( lowFreq , highFreq , edgeCombo - > currentIndex ( ) + 1 ) ) ) ) ;
return ;
}
}
goto errMsg ;
} else {
goto errMsg ;
}
errMsg :
{
QMessageBox URLmsgBox ;
URLmsgBox . setText ( " Error, could not interpret your input. \
< br / > Please make sure to place a comma between the frequencies . \
< br / > For example : ' 7.200 , 7.300 ' " );
URLmsgBox . exec ( ) ;
return ;
}
}
2023-06-05 20:08:01 +00:00
void spectrumScope : : doubleClick ( QMouseEvent * me )
2023-06-05 08:27:37 +00:00
{
if ( me - > button ( ) = = Qt : : LeftButton )
{
double x ;
freqt freqGo ;
if ( ! lock )
{
//y = plot->yAxis->pixelToCoord(me->pos().y());
x = spectrum - > xAxis - > pixelToCoord ( me - > pos ( ) . x ( ) ) ;
freqGo . Hz = x * 1E6 ;
freqGo . Hz = roundFrequency ( freqGo . Hz , stepSize ) ;
freqGo . MHzDouble = ( float ) freqGo . Hz / 1E6 ;
2023-09-26 17:46:04 +00:00
setFrequency ( freqGo ) ;
2024-01-27 22:13:47 +00:00
queue - > add ( priorityImmediate , queueItem ( ( vfo ? funcUnselectedFreq : funcSelectedFreq ) , QVariant : : fromValue < freqt > ( freqGo ) , false , vfo ) ) ;
2023-06-05 08:27:37 +00:00
}
}
else if ( me - > button ( ) = = Qt : : RightButton )
{
QCPAbstractItem * item = spectrum - > itemAt ( me - > pos ( ) , true ) ;
QCPItemRect * rectItem = dynamic_cast < QCPItemRect * > ( item ) ;
if ( rectItem ! = nullptr )
{
double pbFreq = ( pbtDefault / passbandWidth ) * 127.0 ;
qint16 newFreq = pbFreq + 128 ;
2024-01-27 22:13:47 +00:00
queue - > add ( priorityImmediate , queueItem ( funcPBTInner , QVariant : : fromValue < ushort > ( newFreq ) , false , vfo ) ) ;
queue - > add ( priorityImmediate , queueItem ( funcPBTOuter , QVariant : : fromValue < ushort > ( newFreq ) , false , vfo ) ) ;
2023-06-05 08:27:37 +00:00
}
}
}
void spectrumScope : : scopeClick ( QMouseEvent * me )
{
QCPAbstractItem * item = spectrum - > itemAt ( me - > pos ( ) , true ) ;
2023-06-05 20:08:01 +00:00
QCPItemText * textItem = dynamic_cast < QCPItemText * > ( item ) ;
2023-06-05 08:27:37 +00:00
QCPItemRect * rectItem = dynamic_cast < QCPItemRect * > ( item ) ;
# if QCUSTOMPLOT_VERSION < 0x020000
int leftPix = ( int ) passbandIndicator - > left - > pixelPoint ( ) . x ( ) ;
int rightPix = ( int ) passbandIndicator - > right - > pixelPoint ( ) . x ( ) ;
int pbtLeftPix = ( int ) pbtIndicator - > left - > pixelPoint ( ) . x ( ) ;
int pbtRightPix = ( int ) pbtIndicator - > right - > pixelPoint ( ) . x ( ) ;
# else
int leftPix = ( int ) passbandIndicator - > left - > pixelPosition ( ) . x ( ) ;
int rightPix = ( int ) passbandIndicator - > right - > pixelPosition ( ) . x ( ) ;
int pbtLeftPix = ( int ) pbtIndicator - > left - > pixelPosition ( ) . x ( ) ;
int pbtRightPix = ( int ) pbtIndicator - > right - > pixelPosition ( ) . x ( ) ;
# endif
int pbtCenterPix = pbtLeftPix + ( ( pbtRightPix - pbtLeftPix ) / 2 ) ;
int cursor = me - > pos ( ) . x ( ) ;
if ( me - > button ( ) = = Qt : : LeftButton ) {
2023-06-05 20:08:01 +00:00
this - > mousePressFreq = spectrum - > xAxis - > pixelToCoord ( cursor ) ;
2023-06-05 08:27:37 +00:00
if ( textItem ! = nullptr )
{
QMap < QString , spotData * > : : iterator spot = clusterSpots . find ( textItem - > text ( ) ) ;
if ( spot ! = clusterSpots . end ( ) & & spot . key ( ) = = textItem - > text ( ) )
{
qInfo ( logGui ( ) ) < < " Clicked on spot: " < < textItem - > text ( ) ;
freqt freqGo ;
freqGo . Hz = ( spot . value ( ) - > frequency ) * 1E6 ;
freqGo . MHzDouble = spot . value ( ) - > frequency ;
2023-09-26 17:46:04 +00:00
setFrequency ( freqGo ) ;
2024-01-27 22:13:47 +00:00
queue - > add ( priorityImmediate , queueItem ( ( vfo ? funcUnselectedFreq : funcSelectedFreq ) , QVariant : : fromValue < freqt > ( freqGo ) , false , vfo ) ) ;
2023-06-05 08:27:37 +00:00
}
}
2023-06-05 20:08:01 +00:00
else if ( passbandAction = = passbandStatic & & rectItem ! = nullptr )
2023-06-05 08:27:37 +00:00
{
if ( ( cursor < = leftPix & & cursor > leftPix - 10 ) | | ( cursor > = rightPix & & cursor < rightPix + 10 ) )
{
passbandAction = passbandResizing ;
}
}
// TODO clickdragtuning and sending messages to statusbar
2023-06-08 07:20:50 +00:00
else if ( clickDragTuning )
2023-06-05 08:27:37 +00:00
{
showStatusBarText ( QString ( " Selected %1 MHz " ) . arg ( this - > mousePressFreq ) ) ;
}
else {
2023-06-08 07:20:50 +00:00
showStatusBarText ( QString ( " Selected %1 MHz " ) . arg ( this - > mousePressFreq ) ) ;
2023-06-05 08:27:37 +00:00
}
2023-06-08 07:20:50 +00:00
2023-06-05 08:27:37 +00:00
}
else if ( me - > button ( ) = = Qt : : RightButton )
{
if ( textItem ! = nullptr ) {
QMap < QString , spotData * > : : iterator spot = clusterSpots . find ( textItem - > text ( ) ) ;
if ( spot ! = clusterSpots . end ( ) & & spot . key ( ) = = textItem - > text ( ) ) {
// parent and children are destroyed on close
QDialog * spotDialog = new QDialog ( ) ;
QVBoxLayout * vlayout = new QVBoxLayout ;
//spotDialog->setFixedSize(240, 100);
spotDialog - > setBaseSize ( 1 , 1 ) ;
spotDialog - > setWindowTitle ( spot . value ( ) - > dxcall ) ;
QLabel * dxcall = new QLabel ( QString ( " DX:%1 " ) . arg ( spot . value ( ) - > dxcall ) ) ;
QLabel * spotter = new QLabel ( QString ( " Spotter:%1 " ) . arg ( spot . value ( ) - > spottercall ) ) ;
QLabel * frequency = new QLabel ( QString ( " Frequency:%1 MHz " ) . arg ( spot . value ( ) - > frequency ) ) ;
QLabel * comment = new QLabel ( QString ( " Comment:%1 " ) . arg ( spot . value ( ) - > comment ) ) ;
QAbstractButton * bExit = new QPushButton ( " Close " ) ;
vlayout - > addWidget ( dxcall ) ;
vlayout - > addWidget ( spotter ) ;
vlayout - > addWidget ( frequency ) ;
vlayout - > addWidget ( comment ) ;
vlayout - > addWidget ( bExit ) ;
spotDialog - > setLayout ( vlayout ) ;
spotDialog - > show ( ) ;
spotDialog - > connect ( bExit , SIGNAL ( clicked ( ) ) , spotDialog , SLOT ( close ( ) ) ) ;
}
}
2023-06-11 09:33:16 +00:00
else if ( passbandAction = = passbandStatic & & rectItem ! = nullptr )
2023-06-05 08:27:37 +00:00
{
if ( cursor < = pbtLeftPix & & cursor > pbtLeftPix - 10 )
{
passbandAction = pbtInnerMove ;
}
else if ( cursor > = pbtRightPix & & cursor < pbtRightPix + 10 )
{
passbandAction = pbtOuterMove ;
}
else if ( cursor > pbtCenterPix - 20 & & cursor < pbtCenterPix + 20 )
{
passbandAction = pbtMoving ;
}
this - > mousePressFreq = spectrum - > xAxis - > pixelToCoord ( cursor ) ;
}
}
}
void spectrumScope : : scopeMouseRelease ( QMouseEvent * me )
{
2023-06-08 07:20:50 +00:00
2023-06-05 08:27:37 +00:00
QCPAbstractItem * item = spectrum - > itemAt ( me - > pos ( ) , true ) ;
QCPItemText * textItem = dynamic_cast < QCPItemText * > ( item ) ;
2023-06-08 07:20:50 +00:00
if ( textItem = = nullptr & & clickDragTuning ) {
this - > mouseReleaseFreq = spectrum - > xAxis - > pixelToCoord ( me - > pos ( ) . x ( ) ) ;
2023-06-05 08:27:37 +00:00
double delta = mouseReleaseFreq - mousePressFreq ;
qInfo ( logGui ( ) ) < < " Mouse release delta: " < < delta ;
}
2023-06-08 07:20:50 +00:00
2023-06-05 08:27:37 +00:00
if ( passbandAction ! = passbandStatic ) {
passbandAction = passbandStatic ;
}
}
void spectrumScope : : scopeMouseMove ( QMouseEvent * me )
{
QCPAbstractItem * item = spectrum - > itemAt ( me - > pos ( ) , true ) ;
QCPItemText * textItem = dynamic_cast < QCPItemText * > ( item ) ;
QCPItemRect * rectItem = dynamic_cast < QCPItemRect * > ( item ) ;
# if QCUSTOMPLOT_VERSION < 0x020000
int leftPix = ( int ) passbandIndicator - > left - > pixelPoint ( ) . x ( ) ;
int rightPix = ( int ) passbandIndicator - > right - > pixelPoint ( ) . x ( ) ;
int pbtLeftPix = ( int ) pbtIndicator - > left - > pixelPoint ( ) . x ( ) ;
int pbtRightPix = ( int ) pbtIndicator - > right - > pixelPoint ( ) . x ( ) ;
# else
int leftPix = ( int ) passbandIndicator - > left - > pixelPosition ( ) . x ( ) ;
int rightPix = ( int ) passbandIndicator - > right - > pixelPosition ( ) . x ( ) ;
int pbtLeftPix = ( int ) pbtIndicator - > left - > pixelPosition ( ) . x ( ) ;
int pbtRightPix = ( int ) pbtIndicator - > right - > pixelPosition ( ) . x ( ) ;
# endif
int pbtCenterPix = pbtLeftPix + ( ( pbtRightPix - pbtLeftPix ) / 2 ) ;
int cursor = me - > pos ( ) . x ( ) ;
double movedFrequency = spectrum - > xAxis - > pixelToCoord ( cursor ) - mousePressFreq ;
if ( passbandAction = = passbandStatic & & rectItem ! = nullptr )
{
if ( ( cursor < = leftPix & & cursor > leftPix - 10 ) | |
( cursor > = rightPix & & cursor < rightPix + 10 ) | |
( cursor < = pbtLeftPix & & cursor > pbtLeftPix - 10 ) | |
( cursor > = pbtRightPix & & cursor < pbtRightPix + 10 ) )
{
setCursor ( Qt : : SizeHorCursor ) ;
}
else if ( cursor > pbtCenterPix - 20 & & cursor < pbtCenterPix + 20 ) {
setCursor ( Qt : : OpenHandCursor ) ;
}
}
else if ( passbandAction = = passbandResizing )
{
2023-06-05 20:08:01 +00:00
static double lastFreq = movedFrequency ;
if ( lastFreq - movedFrequency > 0.000049 | | movedFrequency - lastFreq > 0.000049 ) {
2023-06-05 08:27:37 +00:00
2023-06-05 20:08:01 +00:00
// We are currently resizing the passband.
double pb = 0.0 ;
double origin = passbandCenterFrequency ;
if ( mode . mk = = modeLSB )
{
origin = - passbandCenterFrequency ;
}
2023-06-05 08:27:37 +00:00
2023-06-05 20:08:01 +00:00
if ( spectrum - > xAxis - > pixelToCoord ( cursor ) > = freq . MHzDouble + origin ) {
pb = spectrum - > xAxis - > pixelToCoord ( cursor ) - passbandIndicator - > topLeft - > coords ( ) . x ( ) ;
}
else {
pb = passbandIndicator - > bottomRight - > coords ( ) . x ( ) - spectrum - > xAxis - > pixelToCoord ( cursor ) ;
}
2024-01-27 22:13:47 +00:00
queue - > add ( priorityImmediate , queueItem ( funcFilterWidth , QVariant : : fromValue < ushort > ( pb * 1000000 ) , false , vfo ) ) ;
2023-06-05 20:08:01 +00:00
//qInfo() << "New passband" << uint(pb * 1000000);
lastFreq = movedFrequency ;
2023-06-05 08:27:37 +00:00
}
}
else if ( passbandAction = = pbtMoving ) {
//qint16 shift = (qint16)(level - 128);
//TPBFInner = (double)(shift / 127.0) * (passbandWidth);
// Only move if more than 100Hz
static double lastFreq = movedFrequency ;
if ( lastFreq - movedFrequency > 0.000049 | | movedFrequency - lastFreq > 0.000049 ) {
double innerFreq = ( ( double ) ( PBTInner + movedFrequency ) / passbandWidth ) * 127.0 ;
double outerFreq = ( ( double ) ( PBTOuter + movedFrequency ) / passbandWidth ) * 127.0 ;
qint16 newInFreq = innerFreq + 128 ;
qint16 newOutFreq = outerFreq + 128 ;
if ( newInFreq > = 0 & & newInFreq < = 255 & & newOutFreq > = 0 & & newOutFreq < = 255 ) {
qDebug ( ) < < QString ( " Moving passband by %1 Hz (Inner %2) (Outer %3) Mode:%4 " ) . arg ( ( qint16 ) ( movedFrequency * 1000000 ) )
. arg ( newInFreq ) . arg ( newOutFreq ) . arg ( mode . mk ) ;
2024-01-27 22:13:47 +00:00
queue - > add ( priorityImmediate , queueItem ( funcPBTInner , QVariant : : fromValue < ushort > ( newInFreq ) , false , vfo ) ) ;
queue - > add ( priorityImmediate , queueItem ( funcPBTOuter , QVariant : : fromValue < ushort > ( newOutFreq ) , false , vfo ) ) ;
2023-06-05 08:27:37 +00:00
}
lastFreq = movedFrequency ;
}
}
else if ( passbandAction = = pbtInnerMove ) {
static double lastFreq = movedFrequency ;
if ( lastFreq - movedFrequency > 0.000049 | | movedFrequency - lastFreq > 0.000049 ) {
double pbFreq = ( ( double ) ( PBTInner + movedFrequency ) / passbandWidth ) * 127.0 ;
qint16 newFreq = pbFreq + 128 ;
if ( newFreq > = 0 & & newFreq < = 255 ) {
2024-01-27 22:13:47 +00:00
queue - > add ( priorityImmediate , queueItem ( funcPBTInner , QVariant : : fromValue < ushort > ( newFreq ) , false , vfo ) ) ;
2023-06-05 08:27:37 +00:00
}
lastFreq = movedFrequency ;
}
}
else if ( passbandAction = = pbtOuterMove ) {
static double lastFreq = movedFrequency ;
if ( lastFreq - movedFrequency > 0.000049 | | movedFrequency - lastFreq > 0.000049 ) {
double pbFreq = ( ( double ) ( PBTOuter + movedFrequency ) / passbandWidth ) * 127.0 ;
qint16 newFreq = pbFreq + 128 ;
if ( newFreq > = 0 & & newFreq < = 255 ) {
2024-01-27 22:13:47 +00:00
queue - > add ( priorityImmediate , queueItem ( funcPBTOuter , QVariant : : fromValue < ushort > ( newFreq ) , false , vfo ) ) ;
2023-06-05 08:27:37 +00:00
}
lastFreq = movedFrequency ;
}
}
2023-06-08 07:20:50 +00:00
else if ( passbandAction = = passbandStatic & & me - > buttons ( ) = = Qt : : LeftButton & & textItem = = nullptr & & clickDragTuning )
2023-06-05 08:27:37 +00:00
{
2023-06-08 07:20:50 +00:00
double delta = spectrum - > xAxis - > pixelToCoord ( cursor ) - mousePressFreq ;
2023-06-05 08:27:37 +00:00
qDebug ( logGui ( ) ) < < " Mouse moving delta: " < < delta ;
if ( ( ( delta < - 0.0001 ) | | ( delta > 0.0001 ) ) & & ( ( delta < 0.501 ) & & ( delta > - 0.501 ) ) )
{
freqt freqGo ;
freqGo . Hz = ( freq . MHzDouble + delta ) * 1E6 ;
2023-06-08 07:20:50 +00:00
freqGo . Hz = roundFrequency ( freqGo . Hz , stepSize ) ;
2023-06-05 08:27:37 +00:00
freqGo . MHzDouble = ( float ) freqGo . Hz / 1E6 ;
2023-09-26 17:46:04 +00:00
setFrequency ( freqGo ) ;
2024-01-27 22:13:47 +00:00
queue - > add ( priorityImmediate , queueItem ( ( vfo ? funcUnselectedFreq : funcSelectedFreq ) , QVariant : : fromValue < freqt > ( freqGo ) , false , vfo ) ) ;
2023-06-05 08:27:37 +00:00
}
}
else {
setCursor ( Qt : : ArrowCursor ) ;
}
}
void spectrumScope : : waterfallClick ( QMouseEvent * me )
{
2023-06-08 07:20:50 +00:00
double x = spectrum - > xAxis - > pixelToCoord ( me - > pos ( ) . x ( ) ) ;
emit showStatusBarText ( QString ( " Selected %1 MHz " ) . arg ( x ) ) ;
2023-06-05 08:27:37 +00:00
}
void spectrumScope : : scroll ( QWheelEvent * we )
{
2023-09-23 20:03:38 +00:00
// angleDelta is supposed to be eights of a degree of mouse wheel rotation
2023-09-25 17:03:31 +00:00
int deltaY = we - > angleDelta ( ) . y ( ) ;
int deltaX = we - > angleDelta ( ) . x ( ) ;
int delta = ( deltaX = = 0 ) ? deltaY : deltaX ;
qreal offset = qreal ( delta ) / qreal ( ( deltaX = = 0 ) ? scrollYperClick : scrollXperClick ) ;
//qreal offset = qreal(delta) / 120;
qreal stepsToScroll = QApplication : : wheelScrollLines ( ) * offset ;
// Did we change direction?
if ( ( scrollWheelOffsetAccumulated > 0 ) & & ( offset > 0 ) ) {
scrollWheelOffsetAccumulated + = stepsToScroll ;
} else if ( ( scrollWheelOffsetAccumulated < 0 ) & & ( offset < 0 ) ) {
scrollWheelOffsetAccumulated + = stepsToScroll ;
} else {
// Changed direction, zap the old accumulation:
scrollWheelOffsetAccumulated = stepsToScroll ;
//qInfo() << "Scroll changed direction";
}
int clicks = int ( scrollWheelOffsetAccumulated ) ;
2023-06-05 08:27:37 +00:00
2023-09-23 20:03:38 +00:00
if ( ! clicks ) {
2023-09-25 17:03:31 +00:00
// qInfo() << "Rejecting minor scroll motion, too small. Wheel Clicks: " << clicks << ", angleDelta: " << delta;
// qInfo() << "Accumulator value: " << offsetAccumulated;
// qInfo() << "stepsToScroll: " << stepsToScroll;
// qInfo() << "Storing scroll motion for later use.";
2023-06-05 08:27:37 +00:00
return ;
2023-09-25 17:03:31 +00:00
} else {
// qInfo() << "Accepted scroll motion. Wheel Clicks: " << clicks << ", angleDelta: " << delta;
// qInfo() << "Accumulator value: " << offsetAccumulated;
// qInfo() << "stepsToScroll: " << stepsToScroll;
2023-09-23 20:03:38 +00:00
}
2023-06-05 08:27:37 +00:00
2023-09-25 17:03:31 +00:00
// If we made it this far, it's time to scroll and to ultimately
// clear the scroll accumulator.
2023-06-05 08:27:37 +00:00
unsigned int stepsHz = stepSize ;
Qt : : KeyboardModifiers key = we - > modifiers ( ) ;
if ( ( key = = Qt : : ShiftModifier ) & & ( stepsHz ! = 1 ) )
{
stepsHz / = 10 ;
}
else if ( key = = Qt : : ControlModifier )
{
stepsHz * = 10 ;
}
freqt f ;
f . Hz = roundFrequency ( freq . Hz , clicks , stepsHz ) ;
f . MHzDouble = f . Hz / ( double ) 1E6 ;
freq = f ; // Do we need to do this?
2023-09-26 17:46:04 +00:00
setFrequency ( f ) ;
2024-01-27 22:13:47 +00:00
queue - > add ( priorityImmediate , queueItem ( ( vfo ? funcUnselectedFreq : funcSelectedFreq ) , QVariant : : fromValue < freqt > ( f ) , false , vfo ) ) ;
2023-09-25 17:03:31 +00:00
//qInfo() << "Moving to freq:" << f.Hz << "step" << stepsHz;
scrollWheelOffsetAccumulated = 0 ;
2023-06-05 08:27:37 +00:00
}
void spectrumScope : : receiveMode ( modeInfo m )
{
// Update mode information if mode/filter/data has changed.
// Not all rigs send data so this "might" need to be updated independantly?
if ( mode . reg ! = m . reg | | m . filter ! = mode . filter | | m . data ! = mode . data )
{
2023-07-23 10:17:10 +00:00
2023-06-05 08:27:37 +00:00
qInfo ( logSystem ( ) ) < < __func__ < < QString ( " Received new mode for %0: %1 (%2) filter:%3 data:%4 " )
2024-01-27 22:13:47 +00:00
. arg ( ( vfo ? " Sub " : " Main " ) ) . arg ( QString : : number ( m . mk , 16 ) ) . arg ( m . name ) . arg ( m . filter ) . arg ( m . data ) ;
2023-06-05 08:27:37 +00:00
if ( mode . mk ! = m . mk ) {
for ( int i = 0 ; i < modeCombo - > count ( ) ; i + + )
{
modeInfo mi = modeCombo - > itemData ( i ) . value < modeInfo > ( ) ;
if ( mi . mk = = m . mk )
{
modeCombo - > blockSignals ( true ) ;
modeCombo - > setCurrentIndex ( i ) ;
modeCombo - > blockSignals ( false ) ;
break ;
}
}
}
if ( m . filter & & mode . filter ! = m . filter )
{
filterCombo - > blockSignals ( true ) ;
filterCombo - > setCurrentIndex ( filterCombo - > findData ( m . filter ) ) ;
filterCombo - > blockSignals ( false ) ;
}
if ( mode . data ! = m . data )
{
2023-10-01 09:22:09 +00:00
emit dataChanged ( m ) ; // Signal wfmain that the data mode has been changed.
2023-06-05 08:27:37 +00:00
dataCombo - > blockSignals ( true ) ;
dataCombo - > setCurrentIndex ( m . data ) ;
dataCombo - > blockSignals ( false ) ;
}
2024-01-28 09:42:50 +00:00
if ( m . mk = = modeCW | | m . mk = = modeCW_R | | m . mk = = modeRTTY | | m . mk = = modeRTTY_R | | m . mk = = modePSK | | m . mk = = modePSK_R )
{
dataCombo - > setEnabled ( false ) ;
} else {
dataCombo - > setEnabled ( true ) ;
}
2023-06-05 20:08:01 +00:00
if ( m . mk ! = mode . mk ) {
// We have changed mode so "may" need to change regular commands
2023-10-01 09:22:09 +00:00
2023-06-05 20:08:01 +00:00
passbandCenterFrequency = 0.0 ;
2023-06-05 08:27:37 +00:00
2023-12-24 16:22:13 +00:00
// Set config specific options)
configFilterWidth - > blockSignals ( true ) ;
configFilterWidth - > setMinimum ( m . bwMin ) ;
configFilterWidth - > setMaximum ( m . bwMax ) ;
configFilterWidth - > blockSignals ( false ) ;
2023-07-23 10:17:10 +00:00
// If new mode doesn't allow bandwidth control, disable filterwidth and pbt.
2023-09-26 11:58:37 +00:00
if ( m . bwMin > 0 & & m . bwMax > 0 ) {
2024-01-27 22:13:47 +00:00
queue - > addUnique ( priorityHigh , funcPBTInner , true , vfo ) ;
queue - > addUnique ( priorityHigh , funcPBTOuter , true , vfo ) ;
queue - > addUnique ( priorityHigh , funcFilterWidth , true , vfo ) ;
2023-07-23 10:17:10 +00:00
} else {
2024-01-27 22:13:47 +00:00
queue - > del ( funcPBTInner , vfo ) ;
queue - > del ( funcPBTOuter , vfo ) ;
queue - > del ( funcFilterWidth , vfo ) ;
2023-07-23 10:17:10 +00:00
}
2023-06-05 20:08:01 +00:00
switch ( m . mk ) {
case modeLSB :
case modeUSB :
passbandCenterFrequency = 0.0015 ;
case modeRTTY :
case modeRTTY_R :
case modePSK :
case modePSK_R :
2023-07-23 10:17:10 +00:00
case modeAM :
2024-01-27 22:13:47 +00:00
queue - > del ( funcCwPitch , vfo ) ;
queue - > del ( funcDashRatio , vfo ) ;
queue - > del ( funcKeySpeed , vfo ) ;
2023-06-05 20:08:01 +00:00
break ;
case modeCW :
case modeCW_R :
2024-01-27 22:13:47 +00:00
queue - > addUnique ( priorityLow , funcCwPitch , true , vfo ) ;
queue - > addUnique ( priorityLow , funcDashRatio , true , vfo ) ;
queue - > addUnique ( priorityLow , funcKeySpeed , true , vfo ) ;
2023-06-05 20:08:01 +00:00
break ;
default :
// FM and digital modes are fixed width, not sure about any other modes?
if ( mode . filter = = 1 )
passbandWidth = 0.015 ;
else if ( mode . filter = = 2 )
passbandWidth = 0.010 ;
else
passbandWidth = 0.007 ;
break ;
2024-01-27 22:13:47 +00:00
queue - > del ( funcCwPitch , vfo ) ;
queue - > del ( funcDashRatio , vfo ) ;
queue - > del ( funcKeySpeed , vfo ) ;
2023-06-05 20:08:01 +00:00
break ;
}
2023-06-05 08:27:37 +00:00
2023-06-05 20:08:01 +00:00
}
2023-06-05 08:27:37 +00:00
mode = m ;
}
}
quint64 spectrumScope : : roundFrequency ( quint64 frequency , unsigned int tsHz )
{
return roundFrequency ( frequency , 0 , tsHz ) ;
}
quint64 spectrumScope : : roundFrequency ( quint64 frequency , int steps , unsigned int tsHz )
{
if ( steps > 0 )
{
frequency = frequency + ( quint64 ) ( steps * tsHz ) ;
} else if ( steps < 0 ) {
frequency = frequency - std : : min ( ( quint64 ) ( abs ( steps ) * tsHz ) , frequency ) ;
}
quint64 rounded = frequency ;
if ( tuningFloorZeros )
{
rounded = ( ( frequency % tsHz ) > tsHz / 2 ) ? frequency + tsHz - frequency % tsHz : frequency - frequency % tsHz ;
}
return rounded ;
}
void spectrumScope : : receiveCwPitch ( uchar pitch )
{
if ( mode . mk = = modeCW | | mode . mk = = modeCW_R ) {
quint16 p = round ( ( ( ( 600.0 / 255.0 ) * pitch ) + 300 ) / 5.0 ) * 5.0 ;
2024-02-07 13:06:23 +00:00
if ( p ! = this - > cwPitch )
2023-06-05 08:27:37 +00:00
{
passbandCenterFrequency = p / 2000000.0 ;
2024-01-27 22:13:47 +00:00
qInfo ( logSystem ( ) ) < < QString ( " %0 Received new CW Pitch %1 Hz was %2 (center freq %3 MHz) " ) . arg ( ( vfo ? " Sub " : " Main " ) ) . arg ( p ) . arg ( cwPitch ) . arg ( passbandCenterFrequency ) ;
2024-02-07 13:06:23 +00:00
this - > cwPitch = p ;
2023-06-05 08:27:37 +00:00
}
}
}
void spectrumScope : : receivePassband ( quint16 pass )
{
double pb = ( double ) ( pass / 1000000.0 ) ;
if ( passbandWidth ! = pb ) {
passbandWidth = pb ;
//trxadj->updatePassband(pass);
2024-01-27 22:13:47 +00:00
qInfo ( logSystem ( ) ) < < QString ( " %0 Received new IF Filter/Passband %1 Hz " ) . arg ( vfo ? " Sub " : " Main " ) . arg ( pass ) ;
emit showStatusBarText ( QString ( " %0 IF filter width %1 Hz (%2 MHz) " ).arg(vfo? " Sub " : " Main " ).arg(pass).arg(passbandWidth)) ;
2023-06-05 08:27:37 +00:00
}
}
2023-06-08 20:58:22 +00:00
void spectrumScope : : selected ( bool en )
{
if ( en )
2023-09-25 13:55:27 +00:00
this - > setStyleSheet ( " QGroupBox { border:1px solid red;} " ) ;
2023-06-08 20:58:22 +00:00
else
2023-09-25 13:55:27 +00:00
this - > setStyleSheet ( defaultStyleSheet ) ;
//this->setStyleSheet("QGroupBox { border:2px solid gray;}");
2023-06-08 20:58:22 +00:00
}
void spectrumScope : : holdPressed ( bool en )
{
2024-01-27 22:13:47 +00:00
queue - > add ( priorityImmediate , queueItem ( vfo ? funcScopeSubHold : funcScopeMainHold , QVariant : : fromValue ( en ) , false , vfo ) ) ;
2023-06-08 20:58:22 +00:00
}
2023-06-11 09:33:16 +00:00
void spectrumScope : : setHold ( bool h )
{
this - > holdButton - > blockSignals ( true ) ;
this - > holdButton - > setChecked ( h ) ;
this - > holdButton - > blockSignals ( false ) ;
}
void spectrumScope : : setSpeed ( uchar s )
{
2023-07-16 09:08:28 +00:00
this - > currentSpeed = s ;
2023-09-25 13:55:27 +00:00
configSpeed - > setCurrentIndex ( configSpeed - > findData ( currentSpeed ) ) ;
2023-06-11 09:33:16 +00:00
}
2024-01-28 13:14:47 +00:00
void spectrumScope : : receiveSpots ( uchar vfo , QList < spotData > spots )
2023-06-11 09:33:16 +00:00
{
2024-01-28 13:14:47 +00:00
if ( vfo ! = this - > vfo ) {
return ;
}
2023-06-11 09:33:16 +00:00
//QElapsedTimer timer;
//timer.start();
bool current = false ;
if ( clusterSpots . size ( ) > 0 ) {
current = clusterSpots . begin ( ) . value ( ) - > current ;
}
foreach ( spotData s , spots )
{
bool found = false ;
QMap < QString , spotData * > : : iterator spot = clusterSpots . find ( s . dxcall ) ;
while ( spot ! = clusterSpots . end ( ) & & spot . key ( ) = = s . dxcall & & spot . value ( ) - > frequency = = s . frequency ) {
spot . value ( ) - > current = ! current ;
found = true ;
+ + spot ;
}
if ( ! found )
{
QCPRange xrange = spectrum - > xAxis - > range ( ) ;
QCPRange yrange = spectrum - > yAxis - > range ( ) ;
double left = s . frequency ;
double top = yrange . upper - 10.0 ;
bool conflict = true ;
while ( conflict ) {
# if QCUSTOMPLOT_VERSION < 0x020000
2023-07-22 19:55:10 +00:00
QCPAbstractItem * absitem = spectrum - > itemAt ( QPointF ( spectrum - > xAxis - > coordToPixel ( left ) , spectrum - > yAxis - > coordToPixel ( top ) ) , true ) ;
2023-06-11 09:33:16 +00:00
# else
2023-07-22 19:55:10 +00:00
QCPAbstractItem * absitem = spectrum - > itemAt ( QPointF ( spectrum - > xAxis - > coordToPixel ( left ) , spectrum - > yAxis - > coordToPixel ( top ) ) , true ) ;
2023-06-11 09:33:16 +00:00
# endif
2023-07-22 19:55:10 +00:00
QCPItemText * item = dynamic_cast < QCPItemText * > ( absitem ) ;
2023-06-11 09:33:16 +00:00
if ( item ! = nullptr ) {
top = top - 10.0 ;
if ( top < 10.0 )
{
top = yrange . upper - 10.0 ;
left = left + ( xrange . size ( ) / 20 ) ;
}
}
else {
conflict = false ;
}
}
spotData * sp = new spotData ( s ) ;
//qDebug(logCluster()) << "ADD:" << sp->dxcall;
sp - > current = ! current ;
sp - > text = new QCPItemText ( spectrum ) ;
sp - > text - > setAntialiased ( true ) ;
sp - > text - > setColor ( colors . clusterSpots ) ;
sp - > text - > setText ( sp - > dxcall ) ;
sp - > text - > setFont ( QFont ( font ( ) . family ( ) , 10 ) ) ;
sp - > text - > setPositionAlignment ( Qt : : AlignVCenter | Qt : : AlignHCenter ) ;
sp - > text - > position - > setType ( QCPItemPosition : : ptPlotCoords ) ;
sp - > text - > setSelectable ( true ) ;
QMargins margin ;
int width = ( sp - > text - > right - sp - > text - > left ) / 2 ;
margin . setLeft ( width ) ;
margin . setRight ( width ) ;
sp - > text - > setPadding ( margin ) ;
sp - > text - > position - > setCoords ( left , top ) ;
sp - > text - > setVisible ( true ) ;
clusterSpots . insert ( sp - > dxcall , sp ) ;
}
}
QMap < QString , spotData * > : : iterator spot2 = clusterSpots . begin ( ) ;
while ( spot2 ! = clusterSpots . end ( ) ) {
if ( spot2 . value ( ) - > current = = current ) {
spectrum - > removeItem ( spot2 . value ( ) - > text ) ;
//qDebug(logCluster()) << "REMOVE:" << spot2.value()->dxcall;
delete spot2 . value ( ) ; // Stop memory leak?
spot2 = clusterSpots . erase ( spot2 ) ;
}
else {
+ + spot2 ;
}
}
//qDebug(logCluster()) << "Processing took" << timer.nsecsElapsed() / 1000 << "us";
}
2023-07-16 09:08:28 +00:00
void spectrumScope : : configPressed ( )
{
2023-09-25 18:21:31 +00:00
this - > configGroup - > setVisible ( ! this - > configGroup - > isVisible ( ) ) ;
2023-09-25 18:35:22 +00:00
//QTimer::singleShot(200, this, [this]() {
2023-09-25 18:21:31 +00:00
if ( this - > configGroup - > isVisible ( ) )
this - > confButton - > setText ( " > " ) ;
else
this - > confButton - > setText ( " < " ) ;
2023-09-25 18:35:22 +00:00
//});
2023-07-16 09:08:28 +00:00
}
void spectrumScope : : wfTheme ( int num )
{
2023-07-16 09:46:30 +00:00
currentTheme = QCPColorGradient : : GradientPreset ( num ) ;
2023-07-16 09:08:28 +00:00
colorMap - > setGradient ( static_cast < QCPColorGradient : : GradientPreset > ( num ) ) ;
2023-09-25 13:55:27 +00:00
configTheme - > setCurrentIndex ( configTheme - > findData ( currentTheme ) ) ;
}
void spectrumScope : : setPBTInner ( double hz ) {
PBTInner = hz ;
double pbFreq = ( ( double ) ( this - > PBTInner ) / this - > passbandWidth ) * 127.0 ;
qint16 newFreq = pbFreq + 128 ;
if ( newFreq > = 0 & & newFreq < = 255 ) {
configPbtInner - > setValue ( newFreq ) ;
}
2023-07-16 09:08:28 +00:00
}
2023-09-25 13:55:27 +00:00
void spectrumScope : : setPBTOuter ( double hz ) {
PBTOuter = hz ;
double pbFreq = ( ( double ) ( this - > PBTOuter ) / this - > passbandWidth ) * 127.0 ;
qint16 newFreq = pbFreq + 128 ;
if ( newFreq > = 0 & & newFreq < = 255 ) {
configPbtOuter - > setValue ( newFreq ) ;
}
}
2023-09-26 17:46:04 +00:00
void spectrumScope : : setFrequency ( freqt f )
{
freqDisplay - > blockSignals ( true ) ;
freqDisplay - > setFrequency ( f . Hz ) ;
freqDisplay - > blockSignals ( false ) ;
freq = f ;
}
void spectrumScope : : displaySettings ( int numDigits , qint64 minf , qint64 maxf , int minStep , FctlUnit unit , std : : vector < bandType > * bands )
{
freqDisplay - > setup ( numDigits , minf , maxf , minStep , unit , bands ) ;
}
void spectrumScope : : setUnit ( FctlUnit unit )
{
freqDisplay - > setUnit ( unit ) ;
}
2023-09-25 13:55:27 +00:00
2023-09-26 17:46:04 +00:00
void spectrumScope : : newFrequency ( qint64 freq )
{
freqt f ;
f . Hz = freq ;
f . MHzDouble = f . Hz / ( double ) 1E6 ;
if ( f . Hz > 0 )
{
2024-01-27 22:13:47 +00:00
queue - > add ( priorityImmediate , queueItem ( ( vfo ? funcUnselectedFreq : funcSelectedFreq ) , QVariant : : fromValue < freqt > ( f ) , false , vfo ) ) ;
2023-09-26 17:46:04 +00:00
}
}
2023-09-27 11:28:43 +00:00
void spectrumScope : : setRef ( int ref )
{
configRef - > setValue ( ref ) ;
}
void spectrumScope : : setRefLimits ( int lower , int upper )
{
configRef - > setRange ( lower , upper ) ;
}
2024-01-21 20:36:52 +00:00
void spectrumScope : : detachScope ( bool state )
{
if ( state )
{
2024-01-27 22:13:47 +00:00
windowLabel = new QLabel ( ) ;
2024-01-21 20:36:52 +00:00
detachButton - > setText ( " Attach " ) ;
2024-01-27 22:13:47 +00:00
qInfo ( logGui ( ) ) < < " Detaching scope " < < ( vfo ? " Sub " : " Main " ) ;
2024-01-21 20:36:52 +00:00
this - > parentWidget ( ) - > layout ( ) - > replaceWidget ( this , windowLabel ) ;
this - > setParent ( NULL ) ;
this - > setWindowFlags ( Qt : : Window | Qt : : WindowMinimizeButtonHint | Qt : : WindowMaximizeButtonHint ) ;
this - > move ( screen ( ) - > geometry ( ) . center ( ) - frameGeometry ( ) . center ( ) ) ;
} else {
detachButton - > setText ( " Detach " ) ;
2024-01-27 22:13:47 +00:00
qInfo ( logGui ( ) ) < < " Attaching scope " < < ( vfo ? " Sub " : " Main " ) ;
2024-01-21 20:36:52 +00:00
windowLabel - > parentWidget ( ) - > layout ( ) - > replaceWidget ( windowLabel , this ) ;
windowLabel - > setParent ( NULL ) ;
delete windowLabel ;
}
2024-01-27 22:13:47 +00:00
// Force a redraw?
this - > show ( ) ;
2024-01-21 20:36:52 +00:00
}