diff --git a/plugins/channelrx/freqscanner/freqscanner.cpp b/plugins/channelrx/freqscanner/freqscanner.cpp index 9e5aef364..31a45e8ef 100644 --- a/plugins/channelrx/freqscanner/freqscanner.cpp +++ b/plugins/channelrx/freqscanner/freqscanner.cpp @@ -292,16 +292,21 @@ void FreqScanner::stopScan() } } +void FreqScanner::setDeviceCenterFrequency(qint64 frequency) +{ + // For RTL SDR, ChannelWebAPIUtils::setCenterFrequency takes ~50ms, which means tuneTime can be 0 + if (!ChannelWebAPIUtils::setCenterFrequency(getDeviceSetIndex(), frequency)) { + qWarning() << "Freq Scanner failed to set frequency" << frequency; + } + m_minFFTStartTime = QDateTime::currentDateTime().addMSecs(m_settings.m_tuneTime); +} + void FreqScanner::initScan() { ChannelWebAPIUtils::setAudioMute(m_scanDeviceSetIndex, m_scanChannelIndex, true); - if (m_centerFrequency != m_stepStartFrequency) - { - if (!ChannelWebAPIUtils::setCenterFrequency(getDeviceSetIndex(), m_stepStartFrequency)) { - qWarning() << "Freq Scanner failed to set frequency" << m_stepStartFrequency; - } - m_minFFTStartTime = QDateTime::currentDateTime().addMSecs(m_settings.m_tuneTime); + if (m_centerFrequency != m_stepStartFrequency) { + setDeviceCenterFrequency(m_stepStartFrequency); } m_scanResults.clear(); @@ -340,13 +345,14 @@ void FreqScanner::processScanResults(const QDateTime& fftStartTime, const QList< int 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; + // Align first frequency so we cover as many channels as possible, while channel guard band + // Can we adjust this to avoid DC bin? + m_stepStartFrequency = frequencies.front() + m_scannerSampleRate / 2 - m_scannerSampleRate * 0.125f; m_stepStopFrequency = frequencies.back(); - // If all frequencies fit within bandwidth, we can have the first frequency more central + // If all frequencies fit within usable bandwidth, we can have the first frequency more central int totalBW = frequencies.back() - frequencies.front() + 2 * m_settings.m_channelBandwidth; - if (totalBW < m_scannerSampleRate) + if (totalBW < m_scannerSampleRate * 0.75f) { int spareBWEachSide = (m_scannerSampleRate - totalBW) / 2; int spareChannelsEachSide = spareBWEachSide / m_settings.m_channelBandwidth; @@ -370,16 +376,17 @@ void FreqScanner::processScanResults(const QDateTime& fftStartTime, const QList< bool complete = false; // Have all frequencies been scanned? bool freqInRange = false; qint64 nextCenterFrequency = m_centerFrequency; + float usableBW = m_scannerSampleRate * 0.75f; do { - if (nextCenterFrequency + m_scannerSampleRate / 2 > m_stepStopFrequency) + if (nextCenterFrequency + usableBW / 2 > m_stepStopFrequency) { nextCenterFrequency = m_stepStartFrequency; complete = true; } else { - nextCenterFrequency += m_scannerSampleRate; + nextCenterFrequency += usableBW; complete = false; } @@ -387,8 +394,8 @@ void FreqScanner::processScanResults(const QDateTime& fftStartTime, const QList< for (int i = 0; i < m_settings.m_frequencies.size(); i++) { if (m_settings.m_enabled[i] - && (m_settings.m_frequencies[i] >= nextCenterFrequency - m_scannerSampleRate / 2) - && (m_settings.m_frequencies[i] < nextCenterFrequency + m_scannerSampleRate / 2)) + && (m_settings.m_frequencies[i] >= nextCenterFrequency - usableBW / 2) + && (m_settings.m_frequencies[i] < nextCenterFrequency + usableBW / 2)) { freqInRange = true; break; @@ -457,7 +464,7 @@ void FreqScanner::processScanResults(const QDateTime& fftStartTime, const QList< // Tune device/channel to frequency int offset; - if ((frequency < m_centerFrequency - m_scannerSampleRate / 2) || (frequency >= m_centerFrequency + m_scannerSampleRate / 2)) + if ((frequency < m_centerFrequency - usableBW / 2) || (frequency >= m_centerFrequency + usableBW / 2)) { nextCenterFrequency = frequency; offset = 0; @@ -519,13 +526,8 @@ void FreqScanner::processScanResults(const QDateTime& fftStartTime, const QList< } } - if (nextCenterFrequency != m_centerFrequency) - { - // For RTL SDR, setCenterFrequency takes ~50ms, which means tuneTime can be 0 - if (!ChannelWebAPIUtils::setCenterFrequency(getDeviceSetIndex(), nextCenterFrequency)) { - qWarning() << "Freq Scanner failed to set frequency" << nextCenterFrequency; - } - m_minFFTStartTime = QDateTime::currentDateTime().addMSecs(m_settings.m_tuneTime); + if (nextCenterFrequency != m_centerFrequency) { + setDeviceCenterFrequency(nextCenterFrequency); } if (complete) { diff --git a/plugins/channelrx/freqscanner/freqscanner.h b/plugins/channelrx/freqscanner/freqscanner.h index 80a53b79a..cd65b1fcf 100644 --- a/plugins/channelrx/freqscanner/freqscanner.h +++ b/plugins/channelrx/freqscanner/freqscanner.h @@ -405,6 +405,7 @@ private: void stopScan(); void initScan(); void processScanResults(const QDateTime& fftStartTime, const QList& results); + void setDeviceCenterFrequency(qint64 frequency); private slots: void networkManagerFinished(QNetworkReply *reply); diff --git a/plugins/channelrx/freqscanner/freqscannersink.cpp b/plugins/channelrx/freqscanner/freqscannersink.cpp index ab1408967..79488e0cc 100644 --- a/plugins/channelrx/freqscanner/freqscannersink.cpp +++ b/plugins/channelrx/freqscanner/freqscannersink.cpp @@ -58,11 +58,7 @@ void FreqScannerSink::feed(const SampleVector::const_iterator& begin, const Samp Complex c(it->real(), it->imag()); c *= m_nco.nextIQ(); - if (m_interpolatorDistance == 1.0f) // Don't call decimate, as we don't want filter applied if possible - { - processOneSample(c); - } - else if (m_interpolatorDistance < 1.0f) // interpolate + if (m_interpolatorDistance < 1.0f) // interpolate { while (!m_interpolator.interpolate(&m_interpolatorDistanceRemain, c, &ci)) { @@ -70,7 +66,7 @@ void FreqScannerSink::feed(const SampleVector::const_iterator& begin, const Samp m_interpolatorDistanceRemain += m_interpolatorDistance; } } - else // decimate + else // decimate (and filter) { if (m_interpolator.decimate(&m_interpolatorDistanceRemain, c, &ci)) { @@ -121,7 +117,8 @@ void FreqScannerSink::processOneSample(Complex &ci) qint64 diff = frequency - startFrequency; float binBW = m_scannerSampleRate / (float)m_fftSize; - if ((diff < m_scannerSampleRate) && (diff >= 0)) + // Ignore results in uppper and lower 12.5%, as there may be aliasing here from half-band filters + if ((diff < m_scannerSampleRate * 0.875f) && (diff >= m_scannerSampleRate * 0.125f)) { int bin = std::round(diff / binBW); @@ -210,7 +207,7 @@ void FreqScannerSink::applyChannelSettings(int channelSampleRate, int channelFre if ((m_channelSampleRate != channelSampleRate) || (m_scannerSampleRate != scannerSampleRate) || force) { - m_interpolator.create(16, channelSampleRate, scannerSampleRate / 2.0); // Highest cutoff, so we don't attentuate first/last channel + m_interpolator.create(16, channelSampleRate, scannerSampleRate / 2.2); // Filter potential aliasing resulting from half-band filters m_interpolatorDistance = (Real) channelSampleRate / (Real)scannerSampleRate; m_interpolatorDistanceRemain = m_interpolatorDistance; }