From 83ceae4ba3155bec7dd3c5383add4b80eccf7870 Mon Sep 17 00:00:00 2001 From: srcejon Date: Tue, 3 Oct 2023 16:09:54 +0100 Subject: [PATCH] Use full bandwidth --- plugins/channelrx/freqscanner/freqscanner.cpp | 32 ++++++++++++++++++- plugins/channelrx/freqscanner/freqscanner.h | 18 +---------- .../freqscanner/freqscannerbaseband.cpp | 5 +-- .../freqscanner/freqscannerbaseband.h | 1 + .../channelrx/freqscanner/freqscannergui.cpp | 24 +++++++++++--- .../channelrx/freqscanner/freqscannergui.h | 1 + .../channelrx/freqscanner/freqscannersink.cpp | 9 +++--- plugins/channelrx/freqscanner/readme.md | 4 ++- 8 files changed, 64 insertions(+), 30 deletions(-) diff --git a/plugins/channelrx/freqscanner/freqscanner.cpp b/plugins/channelrx/freqscanner/freqscanner.cpp index 14b00720a..392faa30d 100644 --- a/plugins/channelrx/freqscanner/freqscanner.cpp +++ b/plugins/channelrx/freqscanner/freqscanner.cpp @@ -44,6 +44,7 @@ #include "util/db.h" #include "channel/channelwebapiutils.h" #include "maincore.h" +#include "dsp/spectrumvis.h" MESSAGE_CLASS_DEFINITION(FreqScanner::MsgConfigureFreqScanner, Message) MESSAGE_CLASS_DEFINITION(FreqScanner::MsgReportChannels, Message) @@ -337,7 +338,7 @@ void FreqScanner::processScanResults(const QDateTime& fftStartTime, const QList< // Calculate how many channels can be scanned in one go int fftSize; int binsPerChannel; - FreqScanner::calcScannerSampleRate(m_settings.m_channelBandwidth, m_basebandSampleRate, m_scannerSampleRate, fftSize, binsPerChannel); + calcScannerSampleRate(m_settings.m_channelBandwidth, m_basebandSampleRate, m_scannerSampleRate, fftSize, binsPerChannel); // Align first frequency so we cover as many channels as possible, while avoiding DC bin m_stepStartFrequency = frequencies.front() + m_scannerSampleRate / 2 - m_settings.m_channelBandwidth + m_settings.m_channelBandwidth / 2; @@ -351,6 +352,8 @@ void FreqScanner::processScanResults(const QDateTime& fftStartTime, const QList< int spareChannelsEachSide = spareBWEachSide / m_settings.m_channelBandwidth; int offset = spareChannelsEachSide * m_settings.m_channelBandwidth; m_stepStartFrequency -= offset; + + qDebug() << "*********** Starting scan: m_stepStartFrequency:" << m_stepStartFrequency << "offset:" << offset; } initScan(); @@ -582,6 +585,32 @@ void FreqScanner::timeout() initScan(); } +void FreqScanner::calcScannerSampleRate(int channelBW, int basebandSampleRate, int& scannerSampleRate, int& fftSize, int& binsPerChannel) +{ + const int maxFFTSize = 16384; + const int minBinsPerChannel = 8; + + // Base FFT size on that used for main spectrum + std::vector& deviceSets = MainCore::instance()->getDeviceSets(); + DeviceSet* deviceSet = deviceSets[m_deviceAPI->getDeviceSetIndex()]; + const SpectrumSettings& spectrumSettings = deviceSet->m_spectrumVis->getSettings(); + fftSize = spectrumSettings.m_fftSize; + + // But ensure we have several bins per channel + // Adjust sample rate, to ensure we don't get massive FFT size + scannerSampleRate = basebandSampleRate; + while (fftSize / (scannerSampleRate / channelBW) < minBinsPerChannel) + { + if (fftSize == maxFFTSize) { + scannerSampleRate /= 2; + } else { + fftSize *= 2; + } + } + + binsPerChannel = fftSize / (scannerSampleRate / (float)channelBW); +} + void FreqScanner::setCenterFrequency(qint64 frequency) { FreqScannerSettings settings = m_settings; @@ -647,6 +676,7 @@ void FreqScanner::applySettings(const FreqScannerSettings& settings, const QStri || settingsKeys.contains("priority") || settingsKeys.contains("measurement") || settingsKeys.contains("mode") + || settingsKeys.contains("channelBandwidth") || force) { // Restart scan if any settings change diff --git a/plugins/channelrx/freqscanner/freqscanner.h b/plugins/channelrx/freqscanner/freqscanner.h index b4ab200f1..80a53b79a 100644 --- a/plugins/channelrx/freqscanner/freqscanner.h +++ b/plugins/channelrx/freqscanner/freqscanner.h @@ -348,23 +348,7 @@ public: uint32_t getNumberOfDeviceStreams() const; - static void calcScannerSampleRate(int channelBW, int basebandSampleRate, int& scannerSampleRate, int& fftSize, int& binsPerChannel) - { - const int maxFFTSize = 2048; - const int maxBinsPerChannel = 32; - const int minBinsPerChannel = 8; - - // Use multiple bins per channel, to account for FFT spectral leakage - binsPerChannel = maxFFTSize / (basebandSampleRate / channelBW); - binsPerChannel = std::min(binsPerChannel, maxBinsPerChannel); - binsPerChannel = std::max(binsPerChannel, minBinsPerChannel); - double binBW = channelBW / (double)binsPerChannel; - - // Find next smallest power of 2 - fftSize = pow(2.0, floor(log2(basebandSampleRate / binBW))); - fftSize = std::min(maxFFTSize, fftSize); - scannerSampleRate = binBW * fftSize; - } + void calcScannerSampleRate(int channelBW, int basebandSampleRate, int& scannerSampleRate, int& fftSize, int& binsPerChannel); static const char * const m_channelIdURI; static const char * const m_channelId; diff --git a/plugins/channelrx/freqscanner/freqscannerbaseband.cpp b/plugins/channelrx/freqscanner/freqscannerbaseband.cpp index d717ee3a8..189753c42 100644 --- a/plugins/channelrx/freqscanner/freqscannerbaseband.cpp +++ b/plugins/channelrx/freqscanner/freqscannerbaseband.cpp @@ -28,6 +28,7 @@ MESSAGE_CLASS_DEFINITION(FreqScannerBaseband::MsgConfigureFreqScannerBaseband, Message) FreqScannerBaseband::FreqScannerBaseband(FreqScanner *freqScanner) : + m_freqScanner(freqScanner), m_sink(freqScanner), m_messageQueueToGUI(nullptr) { @@ -147,7 +148,7 @@ bool FreqScannerBaseband::handleMessage(const Message& cmd) void FreqScannerBaseband::applySettings(const FreqScannerSettings& settings, const QStringList& settingsKeys, bool force) { - if ((settings.m_channelBandwidth != m_settings.m_channelBandwidth) || (settings.m_inputFrequencyOffset != m_settings.m_inputFrequencyOffset) || force) + if (settingsKeys.contains("channelBandwidth") || settingsKeys.contains("inputFrequencyOffset") || force) { int basebandSampleRate = m_channelizer->getBasebandSampleRate(); if ((basebandSampleRate != 0) && (settings.m_channelBandwidth != 0)) { @@ -182,7 +183,7 @@ void FreqScannerBaseband::calcScannerSampleRate(int basebandSampleRate, float rf int fftSize; int binsPerChannel; - FreqScanner::calcScannerSampleRate(rfBandwidth, basebandSampleRate, m_scannerSampleRate, fftSize, binsPerChannel); + m_freqScanner->calcScannerSampleRate(rfBandwidth, basebandSampleRate, m_scannerSampleRate, fftSize, binsPerChannel); m_channelizer->setChannelization(m_scannerSampleRate, inputFrequencyOffset); m_channelSampleRate = m_channelizer->getChannelSampleRate(); diff --git a/plugins/channelrx/freqscanner/freqscannerbaseband.h b/plugins/channelrx/freqscanner/freqscannerbaseband.h index f638d7de9..bcd0ae6dc 100644 --- a/plugins/channelrx/freqscanner/freqscannerbaseband.h +++ b/plugins/channelrx/freqscanner/freqscannerbaseband.h @@ -75,6 +75,7 @@ public: void setFifoLabel(const QString& label) { m_sampleFifo.setLabel(label); } private: + FreqScanner *m_freqScanner; SampleSinkFifo m_sampleFifo; DownChannelizer *m_channelizer; int m_channelSampleRate; diff --git a/plugins/channelrx/freqscanner/freqscannergui.cpp b/plugins/channelrx/freqscanner/freqscannergui.cpp index 520d4dbbc..73c019430 100644 --- a/plugins/channelrx/freqscanner/freqscannergui.cpp +++ b/plugins/channelrx/freqscanner/freqscannergui.cpp @@ -103,7 +103,7 @@ bool FreqScannerGUI::handleMessage(const Message& message) m_basebandSampleRate = notif.getSampleRate(); ui->deltaFrequency->setValueRange(true, 7, 0, m_basebandSampleRate/2); ui->deltaFrequencyLabel->setToolTip(tr("Range %1 %L2 Hz").arg(QChar(0xB1)).arg(m_basebandSampleRate/2)); - ui->channelBandwidth->setValueRange(true, 7, 8, m_basebandSampleRate); + ui->channelBandwidth->setValueRange(true, 7, 0, m_basebandSampleRate); if (m_channelMarker.getBandwidth() == 0) { m_channelMarker.setBandwidth(m_basebandSampleRate); } @@ -164,6 +164,7 @@ bool FreqScannerGUI::handleMessage(const Message& message) FreqScanner::MsgReportScanRange& report = (FreqScanner::MsgReportScanRange&)message; m_channelMarker.setCenterFrequency(report.getCenterFrequency()); m_channelMarker.setBandwidth(report.getTotalBandwidth()); + m_channelMarker.setVisible(report.getTotalBandwidth() < m_basebandSampleRate); // Hide marker if full bandwidth return true; } else if (FreqScanner::MsgScanResult::match(message)) @@ -417,7 +418,7 @@ FreqScannerGUI::FreqScannerGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, B m_channelMarker.setCenterFrequency(m_settings.m_inputFrequencyOffset); m_channelMarker.setTitle("Frequency Scanner"); m_channelMarker.blockSignals(false); - m_channelMarker.setVisible(true); // activate signal on the last setting only + m_channelMarker.setVisible(true); setTitleColor(m_channelMarker.getColor()); m_settings.setChannelMarker(&m_channelMarker); @@ -459,6 +460,8 @@ FreqScannerGUI::FreqScannerGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, B ui->table->setItemDelegateForColumn(COL_FREQUENCY, new FrequencyDelegate("Auto", 3)); ui->table->setItemDelegateForColumn(COL_POWER, new DecimalDelegate(1)); + + connect(m_deviceUISet->m_spectrum->getSpectrumView(), &GLSpectrumView::updateAnnotations, this, &FreqScannerGUI::updateAnnotations); } FreqScannerGUI::~FreqScannerGUI() @@ -784,9 +787,13 @@ void FreqScannerGUI::updateAnnotation(int row) // Exact match annotationItem->setText(marker.m_text); return; - } else if (!closest) { + } + else if (!closest) + { closest = ▮ - } else { + } + else + { if (marker.m_bandwidth < closest->m_bandwidth) { closest = ▮ } @@ -799,6 +806,13 @@ void FreqScannerGUI::updateAnnotation(int row) } } +void FreqScannerGUI::updateAnnotations() +{ + for (int i = 0; i < ui->table->rowCount(); i++) { + updateAnnotation(i); + } +} + void FreqScannerGUI::table_customContextMenuRequested(QPoint pos) { QTableWidgetItem* item = ui->table->itemAt(pos); @@ -927,7 +941,7 @@ void FreqScannerGUI::resizeTable() int row = ui->table->rowCount(); ui->table->setRowCount(row + 1); ui->table->setItem(row, COL_FREQUENCY, new QTableWidgetItem("800,000.5 MHz")); - ui->table->setItem(row, COL_ANNOTATION, new QTableWidgetItem("An annotation")); + ui->table->setItem(row, COL_ANNOTATION, new QTableWidgetItem("London VOLMET")); ui->table->setItem(row, COL_ENABLE, new QTableWidgetItem("Enable")); ui->table->setItem(row, COL_POWER, new QTableWidgetItem("-100.0")); ui->table->setItem(row, COL_ACTIVE_COUNT, new QTableWidgetItem("10000")); diff --git a/plugins/channelrx/freqscanner/freqscannergui.h b/plugins/channelrx/freqscanner/freqscannergui.h index 9113fe514..34979d1bf 100644 --- a/plugins/channelrx/freqscanner/freqscannergui.h +++ b/plugins/channelrx/freqscanner/freqscannergui.h @@ -94,6 +94,7 @@ private: void updateAbsoluteCenterFrequency(); void addRow(qint64 frequency, bool enabled, const QString& notes = ""); void updateAnnotation(int row); + void updateAnnotations(); void updateChannelsList(const QList& channels); void leaveEvent(QEvent*); diff --git a/plugins/channelrx/freqscanner/freqscannersink.cpp b/plugins/channelrx/freqscanner/freqscannersink.cpp index 01d8ed203..b4d9689dc 100644 --- a/plugins/channelrx/freqscanner/freqscannersink.cpp +++ b/plugins/channelrx/freqscanner/freqscannersink.cpp @@ -107,7 +107,7 @@ void FreqScannerSink::processOneSample(Complex &ci) if (m_fftAverage.nextAverage()) { // Send results to channel - if (getMessageQueueToChannel()) + if (getMessageQueueToChannel() && (m_settings.m_channelBandwidth != 0) && (m_binsPerChannel != 0)) { FreqScanner::MsgScanResult* msg = FreqScanner::MsgScanResult::create(m_fftStartTime); QList& results = msg->getScanResults(); @@ -119,11 +119,11 @@ void FreqScannerSink::processOneSample(Complex &ci) qint64 frequency = m_settings.m_frequencies[i]; qint64 startFrequency = m_centerFrequency - m_scannerSampleRate / 2; qint64 diff = frequency - startFrequency; - int binBW = m_settings.m_channelBandwidth / m_binsPerChannel; + float binBW = m_scannerSampleRate / (float)m_fftSize; if ((diff < m_scannerSampleRate) && (diff >= 0)) { - int bin = diff / binBW; + int bin = std::round(diff / binBW); // Calculate power at that frequency Real power; @@ -132,7 +132,7 @@ void FreqScannerSink::processOneSample(Complex &ci) } else { power = totalPower(bin); } - + //qDebug() << "startFrequency:" << startFrequency << "m_scannerSampleRate:" << m_scannerSampleRate << "m_centerFrequency:" << m_centerFrequency << "frequency" << frequency << "bin" << bin << "power" << power; FreqScanner::MsgScanResult::ScanResult result = {frequency, power}; results.append(result); } @@ -177,6 +177,7 @@ Real FreqScannerSink::peakPower(int bin) const if ((idx < 0) || (idx >= m_fftSize)) { continue; } + //qDebug() << "idx:" << idx << "power:" << CalcDb::dbPower(m_magSq[idx]); maxMagSq = std::max(maxMagSq, m_magSq[idx]); } Real db = CalcDb::dbPower(maxMagSq); diff --git a/plugins/channelrx/freqscanner/readme.md b/plugins/channelrx/freqscanner/readme.md index 9f2de848f..737c8325b 100644 --- a/plugins/channelrx/freqscanner/readme.md +++ b/plugins/channelrx/freqscanner/readme.md @@ -56,7 +56,9 @@ Specifies which frequency will be chosen as the active frequency, when multiple

10: Meas - Power Measurement

-Specifies how power is measured. In both cases, a FFT is used, with the channel bandwidth being spread over 8 to 32 bins, with the first and last bins being excluded from the measurement (to reduce spectral leakage from adjacent channels): +Specifies how power is measured. In both cases, a FFT is used. +FFT size is typically the same as used for the Main Spectrum, but may be increased to ensure at least 8 bins cover the channel bandwidth (8). +The first and last bins are excluded from the measurement (to reduce spectral leakage from adjacent channels): - Peak: Power is the highest value in all of the bins, averaged over the scan time (6). - Total: Power is the sum of power in all of the bins, averaged over the scan time (6).