diff --git a/debian/changelog b/debian/changelog index a71e6207f..3e95d948d 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,8 +1,10 @@ sdrangel (3.14.7-1) unstable; urgency=medium * ChanelAnalyzerNG: added PLL option + * RTL-SDR: fixed inf/sup decimators + * AM demod: syncrhronous AM detection option - -- Edouard Griffiths, F4EXB Sun, 13 May 2018 20:14:18 +0200 + -- Edouard Griffiths, F4EXB Sun, 20 May 2018 20:14:18 +0200 sdrangel (3.14.6-1) unstable; urgency=medium diff --git a/plugins/channelrx/chanalyzerng/chanalyzerng.cpp b/plugins/channelrx/chanalyzerng/chanalyzerng.cpp index 63f654cfc..67d464ab3 100644 --- a/plugins/channelrx/chanalyzerng/chanalyzerng.cpp +++ b/plugins/channelrx/chanalyzerng/chanalyzerng.cpp @@ -35,7 +35,6 @@ const QString ChannelAnalyzerNG::m_channelId = "ChannelAnalyzerNG"; ChannelAnalyzerNG::ChannelAnalyzerNG(DeviceSourceAPI *deviceAPI) : ChannelSinkAPI(m_channelIdURI), m_deviceAPI(deviceAPI), - m_pll(0,0.05,0.01), m_sampleSink(0), m_settingsMutex(QMutex::Recursive) { @@ -50,6 +49,7 @@ ChannelAnalyzerNG::ChannelAnalyzerNG(DeviceSourceAPI *deviceAPI) : m_interpolatorDistanceRemain = 0.0f; SSBFilter = new fftfilt(m_config.m_LowCutoff / m_config.m_inputSampleRate, m_config.m_Bandwidth / m_config.m_inputSampleRate, ssbFftLen); DSBFilter = new fftfilt(m_config.m_Bandwidth / m_config.m_inputSampleRate, 2*ssbFftLen); + m_pll.computeCoefficients(0.05f, 0.707f, 1000.0f); // bandwidth, damping factor, loop gain apply(true); @@ -249,6 +249,13 @@ void ChannelAnalyzerNG::apply(bool force) m_settingsMutex.unlock(); } + if (m_running.m_pll != m_config.m_pll || force) + { + if (m_config.m_pll) { + m_pll.reset(); + } + } + m_running.m_frequency = m_config.m_frequency; m_running.m_channelSampleRate = m_config.m_channelSampleRate; m_running.m_inputSampleRate = m_config.m_inputSampleRate; diff --git a/plugins/channelrx/chanalyzerng/chanalyzerng.h b/plugins/channelrx/chanalyzerng/chanalyzerng.h index f9f194bd2..d65786762 100644 --- a/plugins/channelrx/chanalyzerng/chanalyzerng.h +++ b/plugins/channelrx/chanalyzerng/chanalyzerng.h @@ -25,7 +25,7 @@ #include "dsp/interpolator.h" #include "dsp/ncof.h" #include "dsp/fftfilt.h" -#include "dsp/phaselock.h" +#include "dsp/phaselockcomplex.h" #include "audio/audiofifo.h" #include "util/message.h" @@ -148,6 +148,9 @@ public: int getChannelSampleRate() const { return m_running.m_channelSampleRate; } double getMagSq() const { return m_magsq; } bool isPllLocked() const { return m_running.m_pll && m_pll.locked(); } + Real getPllFrequency() const { return m_pll.getFrequency(); } + Real getPllDeltaPhase() const { return m_pll.getDeltaPhi(); } + Real getPllPhase() const { return m_pll.getPhiHat(); } virtual void feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool positiveOnly); virtual void start(); @@ -203,7 +206,7 @@ private: bool m_useInterpolator; NCOF m_nco; - SimplePhaseLock m_pll; + PhaseLockComplex m_pll; Interpolator m_interpolator; Real m_interpolatorDistance; Real m_interpolatorDistanceRemain; @@ -247,11 +250,13 @@ private: if (m_running.m_pll) { - Real ncopll[2]; - m_pll.process(re, im, ncopll); + m_pll.feed(re, im); - Real mixI = m_sum.real() * ncopll[0] - m_sum.imag() * ncopll[1]; - Real mixQ = m_sum.real() * ncopll[1] + m_sum.imag() * ncopll[0]; + // Use -fPLL to mix (exchange PLL real and image in the complex multiplication) + Real mixI = m_sum.real() * m_pll.getImag() - m_sum.imag() * m_pll.getReal(); + Real mixQ = m_sum.real() * m_pll.getReal() + m_sum.imag() * m_pll.getImag(); +// Real mixI = m_pll.getReal() * SDR_RX_SCALED; +// Real mixQ = m_pll.getImag() * SDR_RX_SCALED; if (m_running.m_ssb & !m_usb) { // invert spectrum for LSB diff --git a/plugins/channelrx/chanalyzerng/chanalyzernggui.cpp b/plugins/channelrx/chanalyzerng/chanalyzernggui.cpp index 14fba25a3..90dbd44e0 100644 --- a/plugins/channelrx/chanalyzerng/chanalyzernggui.cpp +++ b/plugins/channelrx/chanalyzerng/chanalyzernggui.cpp @@ -243,6 +243,15 @@ void ChannelAnalyzerNGGUI::tick() } else { ui->pll->setStyleSheet("QToolButton { background:rgb(79,79,79); }"); } + + if (ui->pll->isChecked()) + { + int fHz = round(m_channelAnalyzer->getPllFrequency()*m_rate); + ui->pll->setToolTip(tr("PLL lock (f:%1 Hz e:%2 rad p:%3 rad)") + .arg(fHz) + .arg(m_channelAnalyzer->getPllDeltaPhase()) + .arg(m_channelAnalyzer->getPllPhase())); + } } void ChannelAnalyzerNGGUI::on_channelSampleRate_changed(quint64 value) @@ -257,8 +266,13 @@ void ChannelAnalyzerNGGUI::on_channelSampleRate_changed(quint64 value) } } -void ChannelAnalyzerNGGUI::on_pll_toggled(bool checked __attribute__((unused))) +void ChannelAnalyzerNGGUI::on_pll_toggled(bool checked) { + if (!checked && m_usePll) { + ui->pll->setToolTip("PLL lock"); + } + + m_usePll = checked; applySettings(); } @@ -399,7 +413,8 @@ ChannelAnalyzerNGGUI::ChannelAnalyzerNGGUI(PluginAPI* pluginAPI, DeviceUISet *de m_channelMarker(this), m_doApplySettings(true), m_rate(6000), - m_spanLog2(0) + m_spanLog2(0), + m_usePll(false) { ui->setupUi(this); setAttribute(Qt::WA_DeleteOnClose, true); diff --git a/plugins/channelrx/chanalyzerng/chanalyzernggui.h b/plugins/channelrx/chanalyzerng/chanalyzernggui.h index c30a6087d..0bc962e92 100644 --- a/plugins/channelrx/chanalyzerng/chanalyzernggui.h +++ b/plugins/channelrx/chanalyzerng/chanalyzernggui.h @@ -66,6 +66,7 @@ private: bool m_doApplySettings; int m_rate; //!< sample rate after final in-channel decimation (spanlog2) int m_spanLog2; + bool m_usePll; MovingAverageUtil m_channelPowerDbAvg; ChannelAnalyzerNG* m_channelAnalyzer; diff --git a/plugins/channelrx/demodam/CMakeLists.txt b/plugins/channelrx/demodam/CMakeLists.txt index 0465d3345..adbc2d1e4 100644 --- a/plugins/channelrx/demodam/CMakeLists.txt +++ b/plugins/channelrx/demodam/CMakeLists.txt @@ -7,6 +7,7 @@ set(am_SOURCES amdemodgui.cpp amdemodsettings.cpp amdemodplugin.cpp + amdemodssbdialog.cpp ) set(am_HEADERS @@ -14,10 +15,12 @@ set(am_HEADERS amdemodgui.h amdemodsettings.h amdemodplugin.h + amdemodssbdialog.h ) set(am_FORMS amdemodgui.ui + amdemodssb.ui ) include_directories( diff --git a/plugins/channelrx/demodam/amdemod.cpp b/plugins/channelrx/demodam/amdemod.cpp index b93284476..d7a94dd99 100644 --- a/plugins/channelrx/demodam/amdemod.cpp +++ b/plugins/channelrx/demodam/amdemod.cpp @@ -67,6 +67,7 @@ AMDemod::AMDemod(DeviceSourceAPI *deviceAPI) : DSPEngine::instance()->getAudioDeviceManager()->addAudioSink(&m_audioFifo, getInputMessageQueue()); m_audioSampleRate = DSPEngine::instance()->getAudioDeviceManager()->getOutputSampleRate(); DSBFilter = new fftfilt((2.0f * m_settings.m_rfBandwidth) / m_audioSampleRate, 2 * 1024); + SSBFilter = new fftfilt(0.0f, m_settings.m_rfBandwidth / m_audioSampleRate, 1024); applyChannelSettings(m_inputSampleRate, m_inputFrequencyOffset, true); applySettings(m_settings, true); @@ -89,6 +90,7 @@ AMDemod::~AMDemod() delete m_threadedChannelizer; delete m_channelizer; delete DSBFilter; + delete SSBFilter; } void AMDemod::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool firstOfBurst __attribute__((unused))) @@ -233,6 +235,7 @@ void AMDemod::applyAudioSampleRate(int sampleRate) m_inputMessageQueue.push(channelConfigMsg); m_settingsMutex.lock(); + m_interpolator.create(16, m_inputSampleRate, m_settings.m_rfBandwidth / 2.2f); m_interpolatorDistanceRemain = 0; m_interpolatorDistance = (Real) m_inputSampleRate / (Real) sampleRate; @@ -241,8 +244,14 @@ void AMDemod::applyAudioSampleRate(int sampleRate) m_squelchDelayLine.resize(sampleRate/5); DSBFilter->create_dsb_filter((2.0f * m_settings.m_rfBandwidth) / (float) sampleRate); m_pllFilt.create(101, sampleRate, 500.0); - m_settingsMutex.unlock(); + if (m_settings.m_pll) { + m_volumeAGC.resizeNew(sampleRate, 0.003); + } else { + m_volumeAGC.resizeNew(sampleRate/10, 0.003); + } + + m_settingsMutex.unlock(); m_audioSampleRate = sampleRate; } @@ -282,6 +291,7 @@ void AMDemod::applySettings(const AMDemodSettings& settings, bool force) << " m_bandpassEnable: " << settings.m_bandpassEnable << " m_audioDeviceName: " << settings.m_audioDeviceName << " m_pll: " << settings.m_pll + << " m_syncAMOperation: " << (int) settings.m_syncAMOperation << " force: " << force; if((m_settings.m_rfBandwidth != settings.m_rfBandwidth) || @@ -314,6 +324,23 @@ void AMDemod::applySettings(const AMDemodSettings& settings, bool force) } } + if ((m_settings.m_pll != settings.m_pll) || force) + { + if (settings.m_pll) + { + m_volumeAGC.resizeNew(m_audioSampleRate/4, 0.003); + m_syncAMBuffIndex = 0; + } + else + { + m_volumeAGC.resizeNew(m_audioSampleRate/10, 0.003); + } + } + + if ((m_settings.m_syncAMOperation != settings.m_syncAMOperation) || force) { + m_syncAMBuffIndex = 0; + } + m_settings = settings; } diff --git a/plugins/channelrx/demodam/amdemod.h b/plugins/channelrx/demodam/amdemod.h index e9e380898..ff53b2ed3 100644 --- a/plugins/channelrx/demodam/amdemod.h +++ b/plugins/channelrx/demodam/amdemod.h @@ -167,11 +167,12 @@ private: int m_magsqCount; MovingAverageUtil m_movingAverage; - SimpleAGC<4096> m_volumeAGC; + SimpleAGC<4800> m_volumeAGC; Bandpass m_bandpass; Lowpass > m_pllFilt; PhaseLockComplex m_pll; fftfilt* DSBFilter; + fftfilt* SSBFilter; Real m_syncAMBuff[2*1024]; uint32_t m_syncAMBuffIndex; @@ -238,16 +239,29 @@ private: fftfilt::cmplx *sideband; std::complex cs(yr, yi); - int n_out = DSBFilter->runDSB(cs, &sideband, false); + int n_out; + + if (m_settings.m_syncAMOperation == AMDemodSettings::SyncAMDSB) { + n_out = DSBFilter->runDSB(cs, &sideband, false); + } else { + n_out = SSBFilter->runSSB(cs, &sideband, m_settings.m_syncAMOperation == AMDemodSettings::SyncAMUSB, false); + } for (int i = 0; i < n_out; i++) { - m_syncAMBuff[i] = (sideband[i].real() + sideband[i].imag()); + if (m_settings.m_syncAMOperation == AMDemodSettings::SyncAMDSB) { + m_syncAMBuff[i] = (sideband[i].real() + sideband[i].imag())/2.0f; + } else if (m_settings.m_syncAMOperation == AMDemodSettings::SyncAMUSB) { + m_syncAMBuff[i] = (sideband[i].real() + sideband[i].imag()); + } else { + m_syncAMBuff[i] = (sideband[i].real() + sideband[i].imag()); + } + m_syncAMBuffIndex = 0; } m_syncAMBuffIndex = m_syncAMBuffIndex < 2*1024 ? m_syncAMBuffIndex : 0; - demod = m_syncAMBuff[m_syncAMBuffIndex++]*0.7*(SDR_RX_SCALEF/602.0f); + demod = m_syncAMBuff[m_syncAMBuffIndex++]*(SDR_RX_SCALEF/602.0f); m_volumeAGC.feed(demod); demod /= (10.0*m_volumeAGC.getValue()); } diff --git a/plugins/channelrx/demodam/amdemodgui.cpp b/plugins/channelrx/demodam/amdemodgui.cpp index 4cc4faf8d..2c0eff5a4 100644 --- a/plugins/channelrx/demodam/amdemodgui.cpp +++ b/plugins/channelrx/demodam/amdemodgui.cpp @@ -18,6 +18,7 @@ #include #include "amdemodgui.h" +#include "amdemodssbdialog.h" #include "device/devicesourceapi.h" #include "device/deviceuiset.h" @@ -149,6 +150,12 @@ void AMDemodGUI::on_pll_toggled(bool checked) applySettings(); } +void AMDemodGUI::on_ssb_toggled(bool checked) +{ + m_settings.m_syncAMOperation = checked ? m_samUSB ? AMDemodSettings::SyncAMUSB : AMDemodSettings::SyncAMLSB : AMDemodSettings::SyncAMDSB; + applySettings(); +} + void AMDemodGUI::on_bandpassEnable_toggled(bool checked) { m_settings.m_bandpassEnable = checked; @@ -215,6 +222,7 @@ AMDemodGUI::AMDemodGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandS m_channelMarker(this), m_doApplySettings(true), m_squelchOpen(false), + m_samUSB(true), m_tickCount(0) { ui->setupUi(this); @@ -230,6 +238,9 @@ AMDemodGUI::AMDemodGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandS CRightClickEnabler *audioMuteRightClickEnabler = new CRightClickEnabler(ui->audioMute); connect(audioMuteRightClickEnabler, SIGNAL(rightClick()), this, SLOT(audioSelect())); + CRightClickEnabler *samSidebandRightClickEnabler = new CRightClickEnabler(ui->ssb); + connect(samSidebandRightClickEnabler, SIGNAL(rightClick()), this, SLOT(samSSBSelect())); + ui->deltaFrequencyLabel->setText(QString("%1f").arg(QChar(0x94, 0x03))); ui->deltaFrequency->setColorMapper(ColorMapper(ColorMapper::GrayGold)); ui->deltaFrequency->setValueRange(false, 7, -9999999, 9999999); @@ -254,6 +265,11 @@ AMDemodGUI::AMDemodGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandS connect(&m_channelMarker, SIGNAL(highlightedByCursor()), this, SLOT(channelMarkerHighlightedByCursor())); connect(getInputMessageQueue(), SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages())); + m_iconDSBUSB.addPixmap(QPixmap("://dsb.png"), QIcon::Normal, QIcon::Off); + m_iconDSBUSB.addPixmap(QPixmap("://usb.png"), QIcon::Normal, QIcon::On); + m_iconDSBLSB.addPixmap(QPixmap("://dsb.png"), QIcon::Normal, QIcon::Off); + m_iconDSBLSB.addPixmap(QPixmap("://lsb.png"), QIcon::Normal, QIcon::On); + displaySettings(); applySettings(true); } @@ -314,6 +330,20 @@ void AMDemodGUI::displaySettings() ui->bandpassEnable->setChecked(m_settings.m_bandpassEnable); ui->pll->setChecked(m_settings.m_pll); + if (m_settings.m_pll) { + if (m_settings.m_syncAMOperation == AMDemodSettings::SyncAMLSB) { + m_samUSB = false; + ui->ssb->setIcon(m_iconDSBLSB); + } else { + m_samUSB = true; + ui->ssb->setIcon(m_iconDSBUSB); + } + } + else + { + ui->ssb->setIcon(m_iconDSBUSB); + } + blockApplySettings(false); } @@ -340,6 +370,26 @@ void AMDemodGUI::audioSelect() } } +void AMDemodGUI::samSSBSelect() +{ + AMDemodSSBDialog ssbSelect(m_samUSB); + ssbSelect.exec(); + + ui->ssb->setIcon(ssbSelect.isUsb() ? m_iconDSBUSB : m_iconDSBLSB); + + if (ssbSelect.isUsb() != m_samUSB) + { + qDebug("AMDemodGUI::samSSBSelect: %s", ssbSelect.isUsb() ? "usb" : "lsb"); + m_samUSB = ssbSelect.isUsb(); + + if (m_settings.m_syncAMOperation != AMDemodSettings::SyncAMDSB) + { + m_settings.m_syncAMOperation = m_samUSB ? AMDemodSettings::SyncAMUSB : AMDemodSettings::SyncAMLSB; + applySettings(); + } + } +} + void AMDemodGUI::tick() { double magsqAvg, magsqPeak; diff --git a/plugins/channelrx/demodam/amdemodgui.h b/plugins/channelrx/demodam/amdemodgui.h index 464474a89..4849f1196 100644 --- a/plugins/channelrx/demodam/amdemodgui.h +++ b/plugins/channelrx/demodam/amdemodgui.h @@ -1,7 +1,9 @@ #ifndef INCLUDE_AMDEMODGUI_H #define INCLUDE_AMDEMODGUI_H -#include +#include + +#include "plugin/plugininstancegui.h" #include "gui/rollupwidget.h" #include "dsp/channelmarker.h" #include "dsp/movingaverage.h" @@ -50,9 +52,13 @@ private: AMDemod* m_amDemod; bool m_squelchOpen; + bool m_samUSB; uint32_t m_tickCount; MessageQueue m_inputMessageQueue; + QIcon m_iconDSBUSB; + QIcon m_iconDSBLSB; + explicit AMDemodGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSampleSink *rxChannel, QWidget* parent = 0); virtual ~AMDemodGUI(); @@ -66,6 +72,7 @@ private: private slots: void on_deltaFrequency_changed(qint64 value); void on_pll_toggled(bool checked); + void on_ssb_toggled(bool checked); void on_bandpassEnable_toggled(bool checked); void on_rfBW_valueChanged(int value); void on_volume_valueChanged(int value); @@ -75,6 +82,7 @@ private slots: void onMenuDialogCalled(const QPoint& p); void handleInputMessages(); void audioSelect(); + void samSSBSelect(); void tick(); }; diff --git a/plugins/channelrx/demodam/amdemodgui.ui b/plugins/channelrx/demodam/amdemodgui.ui index 6efd1cb09..c62321c77 100644 --- a/plugins/channelrx/demodam/amdemodgui.ui +++ b/plugins/channelrx/demodam/amdemodgui.ui @@ -154,6 +154,24 @@ + + + + Synchronous AM SSB/DSB toggle right click to select side band + + + + + + + :/dsb.png + :/usb.png:/dsb.png + + + true + + + diff --git a/plugins/channelrx/demodam/amdemodsettings.cpp b/plugins/channelrx/demodam/amdemodsettings.cpp index fb5192cb0..cf3c36ae5 100644 --- a/plugins/channelrx/demodam/amdemodsettings.cpp +++ b/plugins/channelrx/demodam/amdemodsettings.cpp @@ -39,6 +39,7 @@ void AMDemodSettings::resetToDefaults() m_title = "AM Demodulator"; m_audioDeviceName = AudioDeviceManager::m_defaultDeviceName; m_pll = false; + m_syncAMOperation = SyncAMDSB; } QByteArray AMDemodSettings::serialize() const @@ -58,6 +59,7 @@ QByteArray AMDemodSettings::serialize() const s.writeString(9, m_title); s.writeString(11, m_audioDeviceName); s.writeBool(12, m_pll); + s.writeS32(13, (int) m_syncAMOperation); return s.final(); } @@ -96,6 +98,8 @@ bool AMDemodSettings::deserialize(const QByteArray& data) d.readString(9, &m_title, "AM Demodulator"); d.readString(11, &m_audioDeviceName, AudioDeviceManager::m_defaultDeviceName); d.readBool(12, &m_pll, false); + d.readS32(13, &tmp, 0); + m_syncAMOperation = tmp < 0 ? SyncAMDSB : tmp > 2 ? SyncAMDSB : (SyncAMOperation) tmp; return true; } diff --git a/plugins/channelrx/demodam/amdemodsettings.h b/plugins/channelrx/demodam/amdemodsettings.h index 166875394..3aaebd230 100644 --- a/plugins/channelrx/demodam/amdemodsettings.h +++ b/plugins/channelrx/demodam/amdemodsettings.h @@ -23,6 +23,13 @@ class Serializable; struct AMDemodSettings { + enum SyncAMOperation + { + SyncAMDSB, + SyncAMUSB, + SyncAMLSB + }; + qint32 m_inputFrequencyOffset; Real m_rfBandwidth; Real m_squelch; @@ -34,6 +41,7 @@ struct AMDemodSettings Serializable *m_channelMarker; QString m_audioDeviceName; bool m_pll; + SyncAMOperation m_syncAMOperation; AMDemodSettings(); void resetToDefaults(); diff --git a/plugins/channelrx/demodam/amdemodssb.ui b/plugins/channelrx/demodam/amdemodssb.ui new file mode 100644 index 000000000..5e4b20a22 --- /dev/null +++ b/plugins/channelrx/demodam/amdemodssb.ui @@ -0,0 +1,96 @@ + + + AMDemodSSBDialog + + + + 0 + 0 + 199 + 115 + + + + + Liberation Sans + 9 + + + + Dialog + + + + + + SAM sideband selection + + + + + + LSB + + + + + + + USB + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + buttonBox + + + + + buttonBox + accepted() + AMDemodSSBDialog + accept() + + + 257 + 194 + + + 157 + 203 + + + + + buttonBox + rejected() + AMDemodSSBDialog + reject() + + + 314 + 194 + + + 286 + 203 + + + + + diff --git a/plugins/channelrx/demodam/amdemodssbdialog.cpp b/plugins/channelrx/demodam/amdemodssbdialog.cpp new file mode 100644 index 000000000..d7c42ed70 --- /dev/null +++ b/plugins/channelrx/demodam/amdemodssbdialog.cpp @@ -0,0 +1,41 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2018 Edouard Griffiths, F4EXB. // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#include "amdemodssbdialog.h" +#include "ui_amdemodssb.h" + +AMDemodSSBDialog::AMDemodSSBDialog(bool usb, QWidget* parent) : + QDialog(parent), + ui(new Ui::AMDemodSSBDialog), + m_usb(usb) +{ + ui->setupUi(this); + ui->usb->setChecked(usb); + ui->lsb->setChecked(!usb); +} + +AMDemodSSBDialog::~AMDemodSSBDialog() +{ + delete ui; +} + +void AMDemodSSBDialog::accept() +{ + m_usb = ui->usb->isChecked(); + QDialog::accept(); +} + + diff --git a/plugins/channelrx/demodam/amdemodssbdialog.h b/plugins/channelrx/demodam/amdemodssbdialog.h new file mode 100644 index 000000000..1ce527488 --- /dev/null +++ b/plugins/channelrx/demodam/amdemodssbdialog.h @@ -0,0 +1,43 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2018 Edouard Griffiths, F4EXB. // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef PLUGINS_CHANNELRX_DEMODAM_AMDEMODSSBDIALOG_H_ +#define PLUGINS_CHANNELRX_DEMODAM_AMDEMODSSBDIALOG_H_ + +#include + +namespace Ui { + class AMDemodSSBDialog; +} + +class AMDemodSSBDialog : public QDialog +{ + Q_OBJECT +public: + explicit AMDemodSSBDialog(bool usb, QWidget* parent = 0); + ~AMDemodSSBDialog(); + + bool isUsb() const { return m_usb; } + +private: + Ui::AMDemodSSBDialog* ui; + bool m_usb; + +private slots: + void accept(); +}; + +#endif /* PLUGINS_CHANNELRX_DEMODAM_AMDEMODSSBDIALOG_H_ */ diff --git a/sdrbase/dsp/agc.h b/sdrbase/dsp/agc.h index 4e0e2939c..196b523af 100644 --- a/sdrbase/dsp/agc.h +++ b/sdrbase/dsp/agc.h @@ -89,6 +89,13 @@ public: m_moving_average.resize(AvgSize, initial); } + void resizeNew(uint32_t newSize, Real initial, Real cutoff=0, Real clip=0) + { + m_cutoff = cutoff; + m_clip = clip; + m_moving_average.resize(newSize, initial); + } + void fill(double value) { m_moving_average.fill(value); diff --git a/sdrbase/dsp/recursivefilters.cpp b/sdrbase/dsp/recursivefilters.cpp index 2749bfab2..b63385e07 100644 --- a/sdrbase/dsp/recursivefilters.cpp +++ b/sdrbase/dsp/recursivefilters.cpp @@ -18,11 +18,12 @@ #include "recursivefilters.h" #undef M_PI -#define M_PI 3.14159265358979323846 +#define M_PI 3.14159265358979323846 SecondOrderRecursiveFilter::SecondOrderRecursiveFilter(float samplingFrequency, float centerFrequency, float r) : m_r(r), - m_frequencyRatio(centerFrequency/samplingFrequency) + m_frequencyRatio(centerFrequency/samplingFrequency), + m_f(cos(2.0*M_PI*(m_frequencyRatio))) { init(); } @@ -33,6 +34,7 @@ SecondOrderRecursiveFilter::~SecondOrderRecursiveFilter() void SecondOrderRecursiveFilter::setFrequencies(float samplingFrequency, float centerFrequency) { m_frequencyRatio = centerFrequency / samplingFrequency; + m_f = cos(2.0*M_PI*m_frequencyRatio); init(); } @@ -44,7 +46,7 @@ void SecondOrderRecursiveFilter::setR(float r) short SecondOrderRecursiveFilter::run(short sample) { - m_v[0] = ((1.0f - m_r) * (float) sample) + (2.0f * m_r * cos(2.0*M_PI*m_frequencyRatio) * m_v[1]) - (m_r * m_r * m_v[2]); + m_v[0] = ((1.0f - m_r) * (float) sample) + (2.0f * m_r * m_f * m_v[1]) - (m_r * m_r * m_v[2]); float y = m_v[0] - m_v[2]; m_v[2] = m_v[1]; m_v[1] = m_v[0]; @@ -54,7 +56,7 @@ short SecondOrderRecursiveFilter::run(short sample) float SecondOrderRecursiveFilter::run(float sample) { - m_v[0] = ((1.0f - m_r) * sample) + (2.0f * m_r * cos(2.0*M_PI*m_frequencyRatio) * m_v[1]) - (m_r * m_r * m_v[2]); + m_v[0] = ((1.0f - m_r) * sample) + (2.0f * m_r * m_f * m_v[1]) - (m_r * m_r * m_v[2]); float y = m_v[0] - m_v[2]; m_v[2] = m_v[1]; m_v[1] = m_v[0]; diff --git a/sdrbase/dsp/recursivefilters.h b/sdrbase/dsp/recursivefilters.h index 1c457df22..cd17b6dea 100644 --- a/sdrbase/dsp/recursivefilters.h +++ b/sdrbase/dsp/recursivefilters.h @@ -39,6 +39,7 @@ private: float m_r; float m_frequencyRatio; + float m_f; float m_v[3]; };