mirror of
https://github.com/f4exb/sdrangel.git
synced 2024-11-26 01:39:05 -05:00
Use full bandwidth
This commit is contained in:
parent
d2526cdc5b
commit
83ceae4ba3
@ -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<DeviceSet*>& 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
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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"));
|
||||
|
@ -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<FreqScannerSettings::AvailableChannel>& channels);
|
||||
|
||||
void leaveEvent(QEvent*);
|
||||
|
@ -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<FreqScanner::MsgScanResult::ScanResult>& 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);
|
||||
|
@ -56,7 +56,9 @@ Specifies which frequency will be chosen as the active frequency, when multiple
|
||||
|
||||
<h3>10: Meas - Power Measurement</h3>
|
||||
|
||||
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).
|
||||
|
Loading…
Reference in New Issue
Block a user