kopia lustrzana https://gitlab.com/eliggett/wfview
Move scope to it's own widget
rodzic
6f09497d75
commit
2b51bab4f5
|
@ -2237,6 +2237,7 @@ void rigCommander::parseCommand()
|
||||||
}
|
}
|
||||||
// 0x27
|
// 0x27
|
||||||
case funcScopeMainWaveData:
|
case funcScopeMainWaveData:
|
||||||
|
case funcScopeSubWaveData:
|
||||||
{
|
{
|
||||||
scopeData d;
|
scopeData d;
|
||||||
if (parseSpectrum(d))
|
if (parseSpectrum(d))
|
||||||
|
@ -2245,16 +2246,13 @@ void rigCommander::parseCommand()
|
||||||
}
|
}
|
||||||
case funcScopeOnOff:
|
case funcScopeOnOff:
|
||||||
// confirming scope is on
|
// confirming scope is on
|
||||||
value.setValue(static_cast<bool>(payloadIn[2]));
|
|
||||||
break;
|
|
||||||
case funcScopeDataOutput:
|
case funcScopeDataOutput:
|
||||||
// confirming output enabled/disabled of wf data.
|
// confirming output enabled/disabled of wf data.
|
||||||
break;
|
|
||||||
case funcScopeMainSub:
|
case funcScopeMainSub:
|
||||||
// This tells us whether we are receiving main or sub data
|
// This tells us whether we are receiving main or sub data
|
||||||
break;
|
|
||||||
case funcScopeSingleDual:
|
case funcScopeSingleDual:
|
||||||
// This tells us whether we are receiving single or dual scopes
|
// This tells us whether we are receiving single or dual scopes
|
||||||
|
value.setValue(static_cast<bool>(payloadIn[2]));
|
||||||
break;
|
break;
|
||||||
case funcScopeMainMode:
|
case funcScopeMainMode:
|
||||||
// fixed or center
|
// fixed or center
|
||||||
|
|
|
@ -0,0 +1,538 @@
|
||||||
|
#include "spectrumscope.h"
|
||||||
|
|
||||||
|
#include "logcategories.h"
|
||||||
|
|
||||||
|
spectrumScope::spectrumScope(QWidget *parent)
|
||||||
|
: QWidget{parent}
|
||||||
|
{
|
||||||
|
QMutexLocker locker(&mutex);
|
||||||
|
|
||||||
|
spectrum = new QCustomPlot();
|
||||||
|
layout = new QVBoxLayout(this);
|
||||||
|
splitter = new QSplitter(this);
|
||||||
|
layout->addWidget(splitter);
|
||||||
|
splitter->setOrientation(Qt::Vertical);
|
||||||
|
|
||||||
|
|
||||||
|
spectrum = new QCustomPlot();
|
||||||
|
waterfall = new QCustomPlot();
|
||||||
|
|
||||||
|
splitter->addWidget(spectrum);
|
||||||
|
splitter->addWidget(waterfall);
|
||||||
|
splitter->setHandleWidth(5);
|
||||||
|
|
||||||
|
spectrum->axisRect()->setMargins(QMargins(0,0,0,0));
|
||||||
|
waterfall->axisRect()->setMargins(QMargins(0,0,0,0));
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
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");
|
||||||
|
|
||||||
|
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;
|
||||||
|
#if QCUSTOMPLOT_VERSION < 0x020001
|
||||||
|
this->addPlottable(colorMap);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool spectrumScope::prepareWf(uint wf)
|
||||||
|
{
|
||||||
|
QMutexLocker locker(&mutex);
|
||||||
|
bool ret=true;
|
||||||
|
|
||||||
|
this->wfLength = wf;
|
||||||
|
this->wfLengthMax = 1024;
|
||||||
|
|
||||||
|
// Initialize before use!
|
||||||
|
QByteArray empty((int)spectWidth, '\x01');
|
||||||
|
spectrumPeaks = QByteArray( (int)spectWidth, '\x01' );
|
||||||
|
|
||||||
|
if((unsigned int)wfimage.size() < wfLengthMax)
|
||||||
|
{
|
||||||
|
unsigned int i=0;
|
||||||
|
unsigned int oldSize = wfimage.size();
|
||||||
|
for(i=oldSize; i<(wfLengthMax); i++)
|
||||||
|
{
|
||||||
|
wfimage.append(empty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
wfimage.squeeze();
|
||||||
|
//colorMap->clearData();
|
||||||
|
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));
|
||||||
|
|
||||||
|
colorMap->setData(colorMapData);
|
||||||
|
|
||||||
|
waterfall->yAxis->setRangeReversed(true);
|
||||||
|
waterfall->xAxis->setVisible(false);
|
||||||
|
|
||||||
|
scopePrepared = true;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void spectrumScope::setRange(int floor, int ceiling)
|
||||||
|
{
|
||||||
|
maxAmp = ceiling;
|
||||||
|
if (spectrum != Q_NULLPTR)
|
||||||
|
spectrum->yAxis->setRange(QCPRange(floor, ceiling));
|
||||||
|
if (colorMap != Q_NULLPTR)
|
||||||
|
colorMap->setDataRange(QCPRange(floor,ceiling));
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool spectrumScope::update(scopeData data)
|
||||||
|
{
|
||||||
|
if (!scopePrepared )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
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();
|
||||||
|
} else {
|
||||||
|
plasmaPrepared = false;
|
||||||
|
preparePlasma();
|
||||||
|
}
|
||||||
|
// Inform other threads (cluster) that the frequency range has changed.
|
||||||
|
//emit frequencyRange(data.startFreq, data.endFreq);
|
||||||
|
}
|
||||||
|
|
||||||
|
lowerFreq = data.startFreq;
|
||||||
|
upperFreq = data.endFreq;
|
||||||
|
|
||||||
|
//qInfo(logSystem()) << "start: " << data.startFreq << " end: " << data.endFreq;
|
||||||
|
quint16 specLen = data.data.length();
|
||||||
|
|
||||||
|
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();
|
||||||
|
spectrumPlasma.push_front(data.data);
|
||||||
|
if(spectrumPlasma.size() > (int)spectrumPlasmaSize)
|
||||||
|
{
|
||||||
|
spectrumPlasma.pop_back();
|
||||||
|
}
|
||||||
|
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
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
switch (rigMode.mk)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
pbStart = freq.MHzDouble + passbandCenterFrequency - (passbandWidth / 2);
|
||||||
|
pbEnd = freq.MHzDouble + passbandCenterFrequency + (passbandWidth / 2);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
passbandIndicator->topLeft->setCoords(pbStart, 0);
|
||||||
|
passbandIndicator->bottomRight->setCoords(pbEnd, maxAmp);
|
||||||
|
|
||||||
|
if ((rigMode.mk == modeCW || rigMode.mk == modeCW_R) && passbandWidth > 0.0006)
|
||||||
|
{
|
||||||
|
pbtDefault = round((passbandWidth - (cwPitch / 1000000.0)) * 200000.0) / 200000.0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pbtDefault = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((PBTInner - pbtDefault || PBTOuter - pbtDefault) && passbandAction != passbandResizing && rigMode.mk != modeFM)
|
||||||
|
{
|
||||||
|
pbtIndicator->setVisible(true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pbtIndicator->setVisible(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
pbtIndicator displays the intersection between PBTInner and PBTOuter
|
||||||
|
*/
|
||||||
|
if (rigMode.mk == modeLSB || rigMode.mk == modeCW || rigMode.mk == modeRTTY) {
|
||||||
|
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);
|
||||||
|
spectrum->replot();
|
||||||
|
|
||||||
|
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);
|
||||||
|
waterfall->replot();
|
||||||
|
|
||||||
|
/*
|
||||||
|
#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);
|
||||||
|
//oorIndicator->position->setCoords((oldLowerFreq+oldUpperFreq)/2,ui->topLevelSlider->value() - 20);
|
||||||
|
qInfo(logSystem()) << "Scope out of range";
|
||||||
|
} else if (!data.oor && oorIndicator->visible()) {
|
||||||
|
oorIndicator->setVisible(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
//ovfIndicator->setVisible(true);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Plasma functions
|
||||||
|
void spectrumScope::preparePlasma()
|
||||||
|
{
|
||||||
|
QMutexLocker locker(&plasmaMutex);
|
||||||
|
|
||||||
|
if(plasmaPrepared)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(spectrumPlasmaSize == 0)
|
||||||
|
spectrumPlasmaSize = 128;
|
||||||
|
|
||||||
|
spectrumPlasma.clear();
|
||||||
|
spectrumPlasma.squeeze();
|
||||||
|
plasmaPrepared = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void spectrumScope::resizePlasmaBuffer(int size) {
|
||||||
|
QMutexLocker locker(&plasmaMutex);
|
||||||
|
QByteArray empty((int)spectWidth, '\x01');
|
||||||
|
|
||||||
|
int oldSize = spectrumPlasma.size();
|
||||||
|
|
||||||
|
if(oldSize < size)
|
||||||
|
{
|
||||||
|
spectrumPlasma.resize(size);
|
||||||
|
for(int p=oldSize; p < size; p++)
|
||||||
|
{
|
||||||
|
spectrumPlasma.append(empty);
|
||||||
|
}
|
||||||
|
} else if (oldSize > size){
|
||||||
|
for(int p = oldSize; p > size; p--)
|
||||||
|
{
|
||||||
|
spectrumPlasma.pop_back();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
spectrumPlasma.squeeze();
|
||||||
|
}
|
||||||
|
|
||||||
|
void spectrumScope::clearPeaks()
|
||||||
|
{
|
||||||
|
spectrumPeaks = QByteArray( (int)spectWidth, '\x01' );
|
||||||
|
clearPlasma();
|
||||||
|
}
|
||||||
|
|
||||||
|
void spectrumScope::clearPlasma()
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
spectrumPlasmaLine.clear();
|
||||||
|
spectrumPlasmaLine.resize(spectWidth);
|
||||||
|
int specPlasmaSize = spectrumPlasma.size();
|
||||||
|
if(underlayMode == underlayAverageBuffer)
|
||||||
|
{
|
||||||
|
for(int col=0; col < spectWidth; col++)
|
||||||
|
{
|
||||||
|
for(int pos=0; pos < specPlasmaSize; pos++)
|
||||||
|
{
|
||||||
|
spectrumPlasmaLine[col] += (unsigned char)spectrumPlasma[pos][col];
|
||||||
|
}
|
||||||
|
spectrumPlasmaLine[col] = spectrumPlasmaLine[col] / specPlasmaSize;
|
||||||
|
}
|
||||||
|
} else if (underlayMode == underlayPeakBuffer){
|
||||||
|
// peak mode, running peak display
|
||||||
|
for(int col=0; col < spectWidth; col++)
|
||||||
|
{
|
||||||
|
for(int pos=0; pos < specPlasmaSize; pos++)
|
||||||
|
{
|
||||||
|
if((double)((unsigned char)spectrumPlasma[pos][col]) > spectrumPlasmaLine[col])
|
||||||
|
spectrumPlasmaLine[col] = (unsigned char)spectrumPlasma[pos][col];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,108 @@
|
||||||
|
#ifndef SPECTRUMSCOPE_H
|
||||||
|
#define SPECTRUMSCOPE_H
|
||||||
|
|
||||||
|
#include <QWidget>
|
||||||
|
#include <QMutex>
|
||||||
|
#include <QMutexLocker>
|
||||||
|
#include <QSplitter>
|
||||||
|
#include <qcustomplot.h>
|
||||||
|
#include "wfviewtypes.h"
|
||||||
|
#include "colorprefs.h"
|
||||||
|
|
||||||
|
enum scopeTypes {
|
||||||
|
scopeSpectrum=0,
|
||||||
|
scopeWaterfall,
|
||||||
|
scopeNone
|
||||||
|
};
|
||||||
|
|
||||||
|
class spectrumScope : public QWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit spectrumScope(QWidget *parent = nullptr);
|
||||||
|
|
||||||
|
bool prepareWf(uint wfLength);
|
||||||
|
bool update(scopeData spectrum);
|
||||||
|
void preparePlasma();
|
||||||
|
void setRange(int floor, int ceiling);
|
||||||
|
void wfInterpolate(bool en) { colorMap->setInterpolate(en); }
|
||||||
|
void wfAntiAliased(bool en) { colorMap->setAntialiased(en); }
|
||||||
|
void wfTheme(int num) { colorMap->setGradient(static_cast<QCPColorGradient::GradientPreset>(num));}
|
||||||
|
void setUnderlayMode(underlay_t un) { underlayMode = un; clearPeaks();}
|
||||||
|
void overflow(bool en) {ovfIndicator->setVisible(en);}
|
||||||
|
void resizePlasmaBuffer(int size);
|
||||||
|
void colorPreset(colorPrefsType *p);
|
||||||
|
void setCenterFreq (double hz) { passbandCenterFrequency = hz;}
|
||||||
|
double getCenterFreq () { return passbandCenterFrequency;}
|
||||||
|
void setPassbandWidth (double hz) { passbandWidth = hz;}
|
||||||
|
double getPassbandWidth () { return passbandWidth;}
|
||||||
|
void setFrequency (freqt f) { freq = f;}
|
||||||
|
freqt getFrequency () { return freq;}
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void frequencyRange(double start, double end);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
void clearPeaks();
|
||||||
|
void clearPlasma();
|
||||||
|
void computePlasma();
|
||||||
|
|
||||||
|
QMutex mutex;
|
||||||
|
QCustomPlot* spectrum = Q_NULLPTR;
|
||||||
|
QCustomPlot* waterfall = Q_NULLPTR;
|
||||||
|
QSplitter* splitter;
|
||||||
|
QVBoxLayout* layout;
|
||||||
|
int currentTheme = 1;
|
||||||
|
colorPrefsType colors;
|
||||||
|
freqt freq;
|
||||||
|
modeInfo rigMode;
|
||||||
|
bool scopePrepared=false;
|
||||||
|
quint16 spectWidth=689;
|
||||||
|
quint16 maxAmp=200;
|
||||||
|
quint16 wfLength;
|
||||||
|
quint16 wfLengthMax;
|
||||||
|
|
||||||
|
double lowerFreq=0.0;
|
||||||
|
double upperFreq=0.0;
|
||||||
|
|
||||||
|
// Spectrum items;
|
||||||
|
QCPItemLine * freqIndicatorLine;
|
||||||
|
QCPItemRect* passbandIndicator;
|
||||||
|
QCPItemRect* pbtIndicator;
|
||||||
|
QCPItemText* oorIndicator;
|
||||||
|
QCPItemText* ovfIndicator;
|
||||||
|
QByteArray spectrumPeaks;
|
||||||
|
QVector <double> spectrumPlasmaLine;
|
||||||
|
QVector <QByteArray> spectrumPlasma;
|
||||||
|
unsigned int spectrumPlasmaSize = 64;
|
||||||
|
underlay_t underlayMode = underlayNone;
|
||||||
|
bool plasmaPrepared = false;
|
||||||
|
QMutex plasmaMutex;
|
||||||
|
|
||||||
|
double plotFloor = 0;
|
||||||
|
double plotCeiling = 160;
|
||||||
|
double wfFloor = 0;
|
||||||
|
double wfCeiling = 160;
|
||||||
|
double oldPlotFloor = -1;
|
||||||
|
double oldPlotCeiling = 999;
|
||||||
|
double mousePressFreq = 0.0;
|
||||||
|
double mouseReleaseFreq = 0.0;
|
||||||
|
|
||||||
|
passbandActions passbandAction = passbandStatic;
|
||||||
|
|
||||||
|
double PBTInner = 0.0;
|
||||||
|
double PBTOuter = 0.0;
|
||||||
|
double passbandWidth = 0.0;
|
||||||
|
double passbandCenterFrequency = 0.0;
|
||||||
|
double pbtDefault = 0.0;
|
||||||
|
quint16 cwPitch = 600;
|
||||||
|
|
||||||
|
// Waterfall items;
|
||||||
|
QCPColorMap * colorMap = Q_NULLPTR;
|
||||||
|
QCPColorMapData * colorMapData = Q_NULLPTR;
|
||||||
|
QCPColorScale * colorScale = Q_NULLPTR;
|
||||||
|
QVector <QByteArray> wfimage;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SPECTRUMSCOPE_H
|
1010
wfmain.cpp
1010
wfmain.cpp
Plik diff jest za duży
Load Diff
22
wfmain.h
22
wfmain.h
|
@ -51,6 +51,7 @@
|
||||||
#include "audiodevices.h"
|
#include "audiodevices.h"
|
||||||
#include "sidebandchooser.h"
|
#include "sidebandchooser.h"
|
||||||
#include "debugwindow.h"
|
#include "debugwindow.h"
|
||||||
|
#include "spectrumscope.h"
|
||||||
|
|
||||||
#include <qcustomplot.h>
|
#include <qcustomplot.h>
|
||||||
#include <qserialportinfo.h>
|
#include <qserialportinfo.h>
|
||||||
|
@ -370,7 +371,7 @@ private slots:
|
||||||
void receiveCommReady();
|
void receiveCommReady();
|
||||||
void receiveFreq(freqt);
|
void receiveFreq(freqt);
|
||||||
void receiveMode(modeInfo mode);
|
void receiveMode(modeInfo mode);
|
||||||
void receiveSpectrumData(scopeData data);
|
|
||||||
void receivespectrumMode(spectrumMode_t spectMode);
|
void receivespectrumMode(spectrumMode_t spectMode);
|
||||||
void receiveSpectrumSpan(freqt freqspan, bool isSub);
|
void receiveSpectrumSpan(freqt freqspan, bool isSub);
|
||||||
void receivePTTstatus(bool pttOn);
|
void receivePTTstatus(bool pttOn);
|
||||||
|
@ -610,9 +611,7 @@ private:
|
||||||
QCPItemText* ovfIndicator;
|
QCPItemText* ovfIndicator;
|
||||||
void setAppTheme(bool isCustom);
|
void setAppTheme(bool isCustom);
|
||||||
void prepareWf(unsigned int wfLength);
|
void prepareWf(unsigned int wfLength);
|
||||||
void preparePlasma();
|
|
||||||
bool plasmaPrepared = false;
|
|
||||||
void computePlasma();
|
|
||||||
void showHideSpectrum(bool show);
|
void showHideSpectrum(bool show);
|
||||||
void getInitialRigState();
|
void getInitialRigState();
|
||||||
void showButton(QPushButton *btn);
|
void showButton(QPushButton *btn);
|
||||||
|
@ -685,7 +684,6 @@ private:
|
||||||
uint16_t slowCmdNum=0;
|
uint16_t slowCmdNum=0;
|
||||||
uint16_t rapidCmdNum=0;
|
uint16_t rapidCmdNum=0;
|
||||||
|
|
||||||
void setupPlots();
|
|
||||||
void makeRig();
|
void makeRig();
|
||||||
void rigConnections();
|
void rigConnections();
|
||||||
void removeRig();
|
void removeRig();
|
||||||
|
@ -714,15 +712,6 @@ private:
|
||||||
quint16 wfLength;
|
quint16 wfLength;
|
||||||
bool spectrumDrawLock;
|
bool spectrumDrawLock;
|
||||||
|
|
||||||
QByteArray spectrumPeaks;
|
|
||||||
QVector <double> spectrumPlasmaLine;
|
|
||||||
QVector <QByteArray> spectrumPlasma;
|
|
||||||
unsigned int spectrumPlasmaSize = 64;
|
|
||||||
underlay_t underlayMode = underlayNone;
|
|
||||||
QMutex plasmaMutex;
|
|
||||||
void resizePlasmaBuffer(int newSize);
|
|
||||||
void clearPlasmaBuffer();
|
|
||||||
|
|
||||||
double plotFloor = 0;
|
double plotFloor = 0;
|
||||||
double plotCeiling = 160;
|
double plotCeiling = 160;
|
||||||
double wfFloor = 0;
|
double wfFloor = 0;
|
||||||
|
@ -743,8 +732,8 @@ private:
|
||||||
|
|
||||||
double oldLowerFreq;
|
double oldLowerFreq;
|
||||||
double oldUpperFreq;
|
double oldUpperFreq;
|
||||||
freqt freq;
|
//freqt freq;
|
||||||
freqt freqb;
|
//freqt freqb;
|
||||||
float tsKnobMHz;
|
float tsKnobMHz;
|
||||||
|
|
||||||
unsigned char setModeVal=0;
|
unsigned char setModeVal=0;
|
||||||
|
@ -865,6 +854,7 @@ private:
|
||||||
frequencyinputwidget* finputbtns;
|
frequencyinputwidget* finputbtns;
|
||||||
settingswidget* setupui;
|
settingswidget* setupui;
|
||||||
|
|
||||||
|
|
||||||
udpServer* udp = Q_NULLPTR;
|
udpServer* udp = Q_NULLPTR;
|
||||||
rigCtlD* rigCtl = Q_NULLPTR;
|
rigCtlD* rigCtl = Q_NULLPTR;
|
||||||
QThread* serverThread = Q_NULLPTR;
|
QThread* serverThread = Q_NULLPTR;
|
||||||
|
|
31
wfmain.ui
31
wfmain.ui
|
@ -18,7 +18,7 @@
|
||||||
<item>
|
<item>
|
||||||
<widget class="QTabWidget" name="tabWidget">
|
<widget class="QTabWidget" name="tabWidget">
|
||||||
<property name="currentIndex">
|
<property name="currentIndex">
|
||||||
<number>1</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QWidget" name="mainTab">
|
<widget class="QWidget" name="mainTab">
|
||||||
<attribute name="title">
|
<attribute name="title">
|
||||||
|
@ -44,13 +44,18 @@
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QSplitter" name="splitter">
|
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||||
<property name="orientation">
|
<item>
|
||||||
<enum>Qt::Vertical</enum>
|
<widget class="spectrumScope" name="mainScope" native="true"/>
|
||||||
</property>
|
</item>
|
||||||
<widget class="QCustomPlot" name="plot" native="true"/>
|
<item>
|
||||||
<widget class="QCustomPlot" name="waterfall" native="true"/>
|
<widget class="spectrumScope" name="subScope" native="true">
|
||||||
</widget>
|
<property name="enabled">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
|
@ -3418,16 +3423,18 @@ Please use the "Radio Server" page to select server audio</string>
|
||||||
</widget>
|
</widget>
|
||||||
<layoutdefault spacing="6" margin="11"/>
|
<layoutdefault spacing="6" margin="11"/>
|
||||||
<customwidgets>
|
<customwidgets>
|
||||||
<customwidget>
|
|
||||||
<class>QCustomPlot</class>
|
|
||||||
<container>1</container>
|
|
||||||
</customwidget>
|
|
||||||
<customwidget>
|
<customwidget>
|
||||||
<class>meter</class>
|
<class>meter</class>
|
||||||
<extends>QWidget</extends>
|
<extends>QWidget</extends>
|
||||||
<header>meter.h</header>
|
<header>meter.h</header>
|
||||||
<container>1</container>
|
<container>1</container>
|
||||||
</customwidget>
|
</customwidget>
|
||||||
|
<customwidget>
|
||||||
|
<class>spectrumScope</class>
|
||||||
|
<extends>QWidget</extends>
|
||||||
|
<header location="global">spectrumscope.h</header>
|
||||||
|
<container>1</container>
|
||||||
|
</customwidget>
|
||||||
</customwidgets>
|
</customwidgets>
|
||||||
<resources/>
|
<resources/>
|
||||||
<connections/>
|
<connections/>
|
||||||
|
|
|
@ -240,6 +240,7 @@ SOURCES += main.cpp\
|
||||||
settingswidget.cpp \
|
settingswidget.cpp \
|
||||||
memories.cpp \
|
memories.cpp \
|
||||||
rigcreator.cpp \
|
rigcreator.cpp \
|
||||||
|
spectrumscope.cpp \
|
||||||
tablewidget.cpp \
|
tablewidget.cpp \
|
||||||
wfmain.cpp \
|
wfmain.cpp \
|
||||||
commhandler.cpp \
|
commhandler.cpp \
|
||||||
|
@ -293,6 +294,7 @@ HEADERS += wfmain.h \
|
||||||
rigidentities.h \
|
rigidentities.h \
|
||||||
settingswidget.h \
|
settingswidget.h \
|
||||||
sidebandchooser.h \
|
sidebandchooser.h \
|
||||||
|
spectrumscope.h \
|
||||||
tablewidget.h \
|
tablewidget.h \
|
||||||
udpbase.h \
|
udpbase.h \
|
||||||
udphandler.h \
|
udphandler.h \
|
||||||
|
|
Ładowanie…
Reference in New Issue