1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2024-09-28 15:56:33 -04:00

ATV Demod: implemented BFU with PLL for single sideband modes

This commit is contained in:
f4exb 2017-03-19 10:28:54 +01:00
parent a8adc84e89
commit 303fd3ccc7
9 changed files with 375 additions and 73 deletions

View File

@ -126,6 +126,7 @@ set(sdrbase_SOURCES
sdrbase/dsp/basebandsamplesink.cpp sdrbase/dsp/basebandsamplesink.cpp
sdrbase/dsp/basebandsamplesource.cpp sdrbase/dsp/basebandsamplesource.cpp
sdrbase/dsp/nullsink.cpp sdrbase/dsp/nullsink.cpp
sdrbase/dsp/recursivefilters.cpp
sdrbase/dsp/spectrumscopecombovis.cpp sdrbase/dsp/spectrumscopecombovis.cpp
sdrbase/dsp/spectrumscopengcombovis.cpp sdrbase/dsp/spectrumscopengcombovis.cpp
sdrbase/dsp/scopevis.cpp sdrbase/dsp/scopevis.cpp
@ -235,6 +236,7 @@ set(sdrbase_HEADERS
sdrbase/dsp/phasediscri.h sdrbase/dsp/phasediscri.h
sdrbase/dsp/phaselock.h sdrbase/dsp/phaselock.h
sdrbase/dsp/pidcontroller.h sdrbase/dsp/pidcontroller.h
sdrbase/dsp/recursivefilters.h
sdrbase/dsp/samplesinkfifo.h sdrbase/dsp/samplesinkfifo.h
sdrbase/dsp/samplesourcefifo.h sdrbase/dsp/samplesourcefifo.h
sdrbase/dsp/samplesinkfifodoublebuffered.h sdrbase/dsp/samplesinkfifodoublebuffered.h

View File

@ -51,6 +51,8 @@ ATVDemod::ATVDemod() :
m_fltAmpDelta(1.0), m_fltAmpDelta(1.0),
m_fltAmpLineAverage(0.0f), m_fltAmpLineAverage(0.0f),
m_intNumberSamplePerTop(0), m_intNumberSamplePerTop(0),
m_bfoPLL(200/1000000, 100/1000000, 0.01),
m_bfoFilter(200.0, 1000000.0, 0.9),
m_interpolatorDistanceRemain(0.0f), m_interpolatorDistanceRemain(0.0f),
m_interpolatorDistance(1.0f), m_interpolatorDistance(1.0f),
m_DSBFilter(0), m_DSBFilter(0),
@ -113,14 +115,16 @@ void ATVDemod::configureRF(
float fltRFBandwidth, float fltRFBandwidth,
float fltRFOppBandwidth, float fltRFOppBandwidth,
bool blnFFTFiltering, bool blnFFTFiltering,
bool blnDecimatorEnable) bool blnDecimatorEnable,
float fltBFOFrequency)
{ {
Message* msgCmd = MsgConfigureRFATVDemod::create( Message* msgCmd = MsgConfigureRFATVDemod::create(
enmModulation, enmModulation,
fltRFBandwidth, fltRFBandwidth,
fltRFOppBandwidth, fltRFOppBandwidth,
blnFFTFiltering, blnFFTFiltering,
blnDecimatorEnable); blnDecimatorEnable,
fltBFOFrequency);
objMessageQueue->push(msgCmd); objMessageQueue->push(msgCmd);
} }
@ -238,7 +242,7 @@ void ATVDemod::demod(Complex& c)
int n_out; int n_out;
fftfilt::cmplx *filtered; fftfilt::cmplx *filtered;
n_out = m_DSBFilter->runAsym(c, &filtered, m_objRFRunning.m_enmModulation != ATV_VAML); // all usb except explicitely lsb n_out = m_DSBFilter->runAsym(c, &filtered, m_objRFRunning.m_enmModulation != ATV_LSB); // all usb except explicitely lsb
if (n_out > 0) if (n_out > 0)
{ {
@ -308,7 +312,7 @@ void ATVDemod::demod(Complex& c)
m_fltBufferQ[0]=fltNormQ; m_fltBufferQ[0]=fltNormQ;
} }
else if ((m_objRFRunning.m_enmModulation == ATV_AM) || (m_objRFRunning.m_enmModulation == ATV_VAMU) || (m_objRFRunning.m_enmModulation == ATV_VAML)) else if (m_objRFRunning.m_enmModulation == ATV_AM)
{ {
//Amplitude AM //Amplitude AM
fltVal = fltNorm; fltVal = fltNorm;
@ -329,6 +333,39 @@ void ATVDemod::demod(Complex& c)
fltVal -= m_fltAmpMin; fltVal -= m_fltAmpMin;
fltVal /=m_fltAmpDelta; fltVal /=m_fltAmpDelta;
} }
else if ((m_objRFRunning.m_enmModulation == ATV_USB) || (m_objRFRunning.m_enmModulation == ATV_LSB))
{
Real bfoValues[2];
float fltFiltered = m_bfoFilter.run(fltI);
m_bfoPLL.process(fltFiltered, bfoValues);
// do the mix
float mixI = fltI * bfoValues[0] - fltQ * bfoValues[1];
float mixQ = fltI * bfoValues[1] + fltQ * bfoValues[0];
if (m_objRFRunning.m_enmModulation == ATV_USB) {
fltVal = (mixI + mixQ);
} else {
fltVal = (mixI - mixQ);
}
//********** Mini and Maxi Amplitude tracking **********
if(fltVal<m_fltEffMin)
{
m_fltEffMin=fltVal;
}
if(fltVal>m_fltEffMax)
{
m_fltEffMax=fltVal;
}
//Normalisation
fltVal -= m_fltAmpMin;
fltVal /=m_fltAmpDelta;
}
else else
{ {
fltVal = 0.0f; fltVal = 0.0f;
@ -560,14 +597,14 @@ bool ATVDemod::handleMessage(const Message& cmd)
m_objConfig = objCfg.m_objMsgConfig; m_objConfig = objCfg.m_objMsgConfig;
qDebug() << "ATVDemod::handleMessage: MsgConfigureATVDemod:" qDebug() << "ATVDemod::handleMessage: MsgConfigureATVDemod:"
<< " m_fltVoltLevelSynchroBlack" << m_objConfig.m_fltVoltLevelSynchroBlack << " m_fltVoltLevelSynchroBlack:" << m_objConfig.m_fltVoltLevelSynchroBlack
<< " m_fltVoltLevelSynchroTop" << m_objConfig.m_fltVoltLevelSynchroTop << " m_fltVoltLevelSynchroTop:" << m_objConfig.m_fltVoltLevelSynchroTop
<< " m_fltFramePerS" << m_objConfig.m_fltFramePerS << " m_fltFramePerS:" << m_objConfig.m_fltFramePerS
<< " m_fltLineDurationUs" << m_objConfig.m_fltLineDurationUs << " m_fltLineDurationUs:" << m_objConfig.m_fltLineDurationUs
<< " m_fltRatioOfRowsToDisplay" << m_objConfig.m_fltRatioOfRowsToDisplay << " m_fltRatioOfRowsToDisplay:" << m_objConfig.m_fltRatioOfRowsToDisplay
<< " m_fltTopDurationUs" << m_objConfig.m_fltTopDurationUs << " m_fltTopDurationUs:" << m_objConfig.m_fltTopDurationUs
<< " m_blnHSync" << m_objConfig.m_blnHSync << " m_blnHSync:" << m_objConfig.m_blnHSync
<< " m_blnVSync" << m_objConfig.m_blnVSync; << " m_blnVSync:" << m_objConfig.m_blnVSync;
applySettings(); applySettings();
@ -580,11 +617,12 @@ bool ATVDemod::handleMessage(const Message& cmd)
m_objRFConfig = objCfg.m_objMsgConfig; m_objRFConfig = objCfg.m_objMsgConfig;
qDebug() << "ATVDemod::handleMessage: MsgConfigureRFATVDemod:" qDebug() << "ATVDemod::handleMessage: MsgConfigureRFATVDemod:"
<< " m_enmModulation" << m_objRFConfig.m_enmModulation << " m_enmModulation:" << m_objRFConfig.m_enmModulation
<< " m_fltRFBandwidth" << m_objRFConfig.m_fltRFBandwidth << " m_fltRFBandwidth:" << m_objRFConfig.m_fltRFBandwidth
<< " m_fltRFOppBandwidth" << m_objRFConfig.m_fltRFOppBandwidth << " m_fltRFOppBandwidth:" << m_objRFConfig.m_fltRFOppBandwidth
<< " m_blnFFTFiltering" << m_objRFConfig.m_blnFFTFiltering << " m_blnFFTFiltering:" << m_objRFConfig.m_blnFFTFiltering
<< " m_blnDecimatorEnable" << m_objRFConfig.m_blndecimatorEnable; << " m_blnDecimatorEnable:" << m_objRFConfig.m_blndecimatorEnable
<< " m_fltBFOFrequency:" << m_objRFConfig.m_fltBFOFrequency;
applySettings(); applySettings();
@ -677,6 +715,14 @@ void ATVDemod::applySettings()
m_objSettingsMutex.unlock(); m_objSettingsMutex.unlock();
} }
if ((m_objConfigPrivate.m_intTVSampleRate != m_objRunningPrivate.m_intTVSampleRate)
|| (m_objRFConfig.m_fltBFOFrequency != m_objRFRunning.m_fltBFOFrequency))
{
m_bfoPLL.configure(m_objRFConfig.m_fltBFOFrequency / m_objConfigPrivate.m_intTVSampleRate,
100.0 / m_objConfigPrivate.m_intTVSampleRate,
0.01);
m_bfoFilter.setFrequencies(m_objRFConfig.m_fltBFOFrequency, m_objConfigPrivate.m_intTVSampleRate);
}
m_objRunning = m_objConfig; m_objRunning = m_objConfig;
m_objRFRunning = m_objRFConfig; m_objRFRunning = m_objRFConfig;
@ -692,3 +738,15 @@ int ATVDemod::getEffectiveSampleRate()
{ {
return m_objRFRunning.m_blndecimatorEnable ? m_objRunningPrivate.m_intTVSampleRate : m_objRunning.m_intSampleRate; return m_objRFRunning.m_blndecimatorEnable ? m_objRunningPrivate.m_intTVSampleRate : m_objRunning.m_intSampleRate;
} }
bool ATVDemod::getBFOLocked()
{
if ((m_objRFRunning.m_enmModulation == ATV_USB) || (m_objRFRunning.m_enmModulation == ATV_LSB))
{
return m_bfoPLL.locked();
}
else
{
return false;
}
}

View File

@ -31,6 +31,8 @@
#include "dsp/movingaverage.h" #include "dsp/movingaverage.h"
#include "dsp/fftfilt.h" #include "dsp/fftfilt.h"
#include "dsp/agc.h" #include "dsp/agc.h"
#include "dsp/phaselock.h"
#include "dsp/recursivefilters.h"
#include "audio/audiofifo.h" #include "audio/audiofifo.h"
#include "util/message.h" #include "util/message.h"
#include "atvscreen.h" #include "atvscreen.h"
@ -46,8 +48,8 @@ public:
ATV_FM1, //!< Classical frequency modulation with discriminator #1 ATV_FM1, //!< Classical frequency modulation with discriminator #1
ATV_FM2, //!< Classical frequency modulation with discriminator #2 ATV_FM2, //!< Classical frequency modulation with discriminator #2
ATV_AM, //!< Classical amplitude modulation ATV_AM, //!< Classical amplitude modulation
ATV_VAMU, //!< AM with vestigial lower side band (main signal is in the upper side) ATV_USB, //!< AM with vestigial lower side band (main signal is in the upper side)
ATV_VAML //!< AM with vestigial upper side band (main signal is in the lower side) ATV_LSB //!< AM with vestigial upper side band (main signal is in the lower side)
}; };
struct ATVConfig struct ATVConfig
@ -84,6 +86,7 @@ public:
float m_fltRFOppBandwidth; float m_fltRFOppBandwidth;
bool m_blnFFTFiltering; bool m_blnFFTFiltering;
bool m_blndecimatorEnable; bool m_blndecimatorEnable;
float m_fltBFOFrequency;
ATVRFConfig() : ATVRFConfig() :
m_intFrequencyOffset(0), m_intFrequencyOffset(0),
@ -91,7 +94,8 @@ public:
m_fltRFBandwidth(0), m_fltRFBandwidth(0),
m_fltRFOppBandwidth(0), m_fltRFOppBandwidth(0),
m_blnFFTFiltering(false), m_blnFFTFiltering(false),
m_blndecimatorEnable(false) m_blndecimatorEnable(false),
m_fltBFOFrequency(0.0f)
{ {
} }
}; };
@ -135,7 +139,8 @@ public:
float fltRFBandwidth, float fltRFBandwidth,
float fltRFOppBandwidth, float fltRFOppBandwidth,
bool blnFFTFiltering, bool blnFFTFiltering,
bool blndecimatorEnable); bool blndecimatorEnable,
float fltBFOFrequency);
virtual void feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool po); virtual void feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool po);
virtual void start(); virtual void start();
@ -146,6 +151,7 @@ public:
int getSampleRate(); int getSampleRate();
int getEffectiveSampleRate(); int getEffectiveSampleRate();
double getMagSq() const { return m_objMagSqAverage.average(); } //!< Beware this is scaled to 2^30 double getMagSq() const { return m_objMagSqAverage.average(); } //!< Beware this is scaled to 2^30
bool getBFOLocked();
private: private:
struct ATVConfigPrivate struct ATVConfigPrivate
@ -218,14 +224,16 @@ private:
float fltRFBandwidth, float fltRFBandwidth,
float fltRFOppBandwidth, float fltRFOppBandwidth,
bool blnFFTFiltering, bool blnFFTFiltering,
bool blndecimatorEnable) bool blndecimatorEnable,
int intBFOFrequency)
{ {
return new MsgConfigureRFATVDemod( return new MsgConfigureRFATVDemod(
enmModulation, enmModulation,
fltRFBandwidth, fltRFBandwidth,
fltRFOppBandwidth, fltRFOppBandwidth,
blnFFTFiltering, blnFFTFiltering,
blndecimatorEnable); blndecimatorEnable,
intBFOFrequency);
} }
ATVRFConfig m_objMsgConfig; ATVRFConfig m_objMsgConfig;
@ -236,7 +244,8 @@ private:
float fltRFBandwidth, float fltRFBandwidth,
float fltRFOppBandwidth, float fltRFOppBandwidth,
bool blnFFTFiltering, bool blnFFTFiltering,
bool blndecimatorEnable) : bool blndecimatorEnable,
float fltBFOFrequency) :
Message() Message()
{ {
m_objMsgConfig.m_enmModulation = enmModulation; m_objMsgConfig.m_enmModulation = enmModulation;
@ -244,6 +253,7 @@ private:
m_objMsgConfig.m_fltRFOppBandwidth = fltRFOppBandwidth; m_objMsgConfig.m_fltRFOppBandwidth = fltRFOppBandwidth;
m_objMsgConfig.m_blnFFTFiltering = blnFFTFiltering; m_objMsgConfig.m_blnFFTFiltering = blnFFTFiltering;
m_objMsgConfig.m_blndecimatorEnable = blndecimatorEnable; m_objMsgConfig.m_blndecimatorEnable = blndecimatorEnable;
m_objMsgConfig.m_fltBFOFrequency = fltBFOFrequency;
} }
}; };
@ -286,6 +296,8 @@ private:
MovingAverage<double> m_objMagSqAverage; MovingAverage<double> m_objMagSqAverage;
NCO m_nco; NCO m_nco;
SimplePhaseLock m_bfoPLL;
SecondOrderRecursiveFilter m_bfoFilter;
// Interpolator group for decimation and/or double sideband RF filtering // Interpolator group for decimation and/or double sideband RF filtering
Interpolator m_interpolator; Interpolator m_interpolator;

View File

@ -105,6 +105,7 @@ QByteArray ATVDemodGUI::serialize() const
s.writeBool(11, ui->halfImage->isChecked()); s.writeBool(11, ui->halfImage->isChecked());
s.writeS32(12, ui->rfBW->value()); s.writeS32(12, ui->rfBW->value());
s.writeS32(13, ui->rfOppBW->value()); s.writeS32(13, ui->rfOppBW->value());
s.writeS32(14, ui->bfo->value());
return s.final(); return s.final();
} }
@ -160,6 +161,8 @@ bool ATVDemodGUI::deserialize(const QByteArray& arrData)
ui->rfBW->setValue(tmp); ui->rfBW->setValue(tmp);
d.readS32(13, &tmp, 10); d.readS32(13, &tmp, 10);
ui->rfOppBW->setValue(tmp); ui->rfOppBW->setValue(tmp);
d.readS32(14, &tmp, 10);
ui->bfo->setValue(tmp);
blockApplySettings(false); blockApplySettings(false);
m_objChannelMarker.blockSignals(false); m_objChannelMarker.blockSignals(false);
@ -336,7 +339,8 @@ void ATVDemodGUI::applyRFSettings()
ui->rfBW->value() * 100000.0f, ui->rfBW->value() * 100000.0f,
ui->rfOppBW->value() * 100000.0f, ui->rfOppBW->value() * 100000.0f,
ui->rfFiltering->isChecked(), ui->rfFiltering->isChecked(),
ui->decimatorEnable->isChecked()); ui->decimatorEnable->isChecked(),
ui->bfo->value() * 10.0f);
} }
} }
@ -349,9 +353,9 @@ void ATVDemodGUI::setChannelMarkerBandwidth()
m_objChannelMarker.setBandwidth(ui->rfBW->value()*100000); m_objChannelMarker.setBandwidth(ui->rfBW->value()*100000);
m_objChannelMarker.setOppositeBandwidth(ui->rfOppBW->value()*100000); m_objChannelMarker.setOppositeBandwidth(ui->rfOppBW->value()*100000);
if (ui->modulation->currentIndex() == (int) ATVDemod::ATV_VAML) { if (ui->modulation->currentIndex() == (int) ATVDemod::ATV_LSB) {
m_objChannelMarker.setSidebands(ChannelMarker::vlsb); m_objChannelMarker.setSidebands(ChannelMarker::vlsb);
} else if (ui->modulation->currentIndex() == (int) ATVDemod::ATV_VAMU) { } else if (ui->modulation->currentIndex() == (int) ATVDemod::ATV_USB) {
m_objChannelMarker.setSidebands(ChannelMarker::vusb); m_objChannelMarker.setSidebands(ChannelMarker::vusb);
} else { } else {
m_objChannelMarker.setSidebands(ChannelMarker::vusb); m_objChannelMarker.setSidebands(ChannelMarker::vusb);
@ -413,6 +417,12 @@ void ATVDemodGUI::tick()
m_objMagSqAverage.feed(m_objATVDemod->getMagSq()); m_objMagSqAverage.feed(m_objATVDemod->getMagSq());
double magSqDB = CalcDb::dbPower(m_objMagSqAverage.average() / (1<<30)); double magSqDB = CalcDb::dbPower(m_objMagSqAverage.average() / (1<<30));
ui->channePowerText->setText(tr("%1 dB").arg(magSqDB, 0, 'f', 1)); ui->channePowerText->setText(tr("%1 dB").arg(magSqDB, 0, 'f', 1));
if (m_objATVDemod->getBFOLocked()) {
ui->bfoLockedLabel->setStyleSheet("QLabel { background-color : green; }");
} else {
ui->bfoLockedLabel->setStyleSheet("QLabel { background:rgb(79,79,79); }");
}
} }
m_intTickCount = 0; m_intTickCount = 0;
@ -525,3 +535,9 @@ void ATVDemodGUI::on_deltaFrequencyMinus_toggled(bool minus)
} }
} }
void ATVDemodGUI::on_bfo_valueChanged(int value)
{
ui->bfoText->setText(QString("%1").arg(value * 10.0, 0, 'f', 0));
applyRFSettings();
}

View File

@ -79,6 +79,7 @@ private slots:
void on_decimatorEnable_toggled(bool checked); void on_decimatorEnable_toggled(bool checked);
void on_deltaFrequency_changed(quint64 value); void on_deltaFrequency_changed(quint64 value);
void on_deltaFrequencyMinus_toggled(bool minus); void on_deltaFrequencyMinus_toggled(bool minus);
void on_bfo_valueChanged(int value);
private: private:
Ui::ATVDemodGUI* ui; Ui::ATVDemodGUI* ui;

View File

@ -40,7 +40,7 @@
<x>10</x> <x>10</x>
<y>10</y> <y>10</y>
<width>501</width> <width>501</width>
<height>71</height> <height>81</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@ -52,23 +52,6 @@
</property> </property>
<item> <item>
<layout class="QHBoxLayout" name="rfSettings1Layout"> <layout class="QHBoxLayout" name="rfSettings1Layout">
<item>
<widget class="ButtonSwitch" name="decimatorEnable">
<property name="toolTip">
<string>Toggle decimator on/off</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../../../sdrbase/resources/res.qrc">
<normaloff>:/arrow_down.png</normaloff>:/arrow_down.png</iconset>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item> <item>
<layout class="QHBoxLayout" name="deltaFrequencyLayout"> <layout class="QHBoxLayout" name="deltaFrequencyLayout">
<item> <item>
@ -124,6 +107,30 @@
</item> </item>
</layout> </layout>
</item> </item>
<item>
<widget class="Line" name="line_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item>
<widget class="ButtonSwitch" name="decimatorEnable">
<property name="toolTip">
<string>Toggle decimator on/off</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../../../sdrbase/resources/res.qrc">
<normaloff>:/arrow_down.png</normaloff>:/arrow_down.png</iconset>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item> <item>
<widget class="QLabel" name="channelSampleRateText"> <widget class="QLabel" name="channelSampleRateText">
<property name="minimumSize"> <property name="minimumSize">
@ -144,35 +151,77 @@
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QComboBox" name="modulation"> <widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="bfoLockedLabel">
<property name="maximumSize">
<size>
<width>22</width>
<height>22</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap resource="../../../sdrbase/resources/res.qrc">:/carrier.png</pixmap>
</property>
</widget>
</item>
<item>
<widget class="QDial" name="bfo">
<property name="maximumSize">
<size>
<width>22</width>
<height>22</height>
</size>
</property>
<property name="toolTip"> <property name="toolTip">
<string>Modulation type</string> <string>BFO frequency adjust</string>
</property> </property>
<item> <property name="minimum">
<property name="text"> <number>-500</number>
<string>FM 1</string>
</property> </property>
<property name="maximum">
<number>500</number>
</property>
<property name="pageStep">
<number>1</number>
</property>
<property name="value">
<number>0</number>
</property>
</widget>
</item> </item>
<item> <item>
<property name="text"> <widget class="QLabel" name="bfoText">
<string>FM 2</string> <property name="minimumSize">
<size>
<width>40</width>
<height>0</height>
</size>
</property> </property>
<property name="toolTip">
<string>BFO frequency (Hz)</string>
</property>
<property name="text">
<string>0</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item> </item>
<item> <item>
<property name="text"> <widget class="Line" name="line_2">
<string>AM</string> <property name="orientation">
<enum>Qt::Vertical</enum>
</property> </property>
</item>
<item>
<property name="text">
<string>VAMU</string>
</property>
</item>
<item>
<property name="text">
<string>VAML</string>
</property>
</item>
</widget> </widget>
</item> </item>
<item> <item>
@ -211,6 +260,38 @@
</item> </item>
<item> <item>
<layout class="QHBoxLayout" name="rfSettings2Layout"> <layout class="QHBoxLayout" name="rfSettings2Layout">
<item>
<widget class="QComboBox" name="modulation">
<property name="toolTip">
<string>Modulation type</string>
</property>
<item>
<property name="text">
<string>FM 1</string>
</property>
</item>
<item>
<property name="text">
<string>FM 2</string>
</property>
</item>
<item>
<property name="text">
<string>AM</string>
</property>
</item>
<item>
<property name="text">
<string>USB</string>
</property>
</item>
<item>
<property name="text">
<string>LSB</string>
</property>
</item>
</widget>
</item>
<item> <item>
<widget class="ButtonSwitch" name="rfFiltering"> <widget class="ButtonSwitch" name="rfFiltering">
<property name="toolTip"> <property name="toolTip">

View File

@ -112,6 +112,24 @@ private:
std::vector<PpsEvent> m_pps_events; std::vector<PpsEvent> m_pps_events;
}; };
class SimplePhaseLock : public PhaseLock
{
public:
SimplePhaseLock(Real freq, Real bandwidth, Real minsignal) :
PhaseLock(freq, bandwidth, minsignal)
{}
virtual ~SimplePhaseLock()
{}
protected:
virtual void processPhase(Real *samples_out) const
{
samples_out[0] = m_psin; // f Pilot
samples_out[1] = m_pcos; // f Pilot
}
};
class StereoPhaseLock : public PhaseLock class StereoPhaseLock : public PhaseLock
{ {
public: public:

View File

@ -0,0 +1,69 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2017 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 <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#include <cmath>
#include "recursivefilters.h"
SecondOrderRecursiveFilter::SecondOrderRecursiveFilter(float samplingFrequency, float centerFrequency, float r) :
m_r(r),
m_frequencyRatio(centerFrequency/samplingFrequency)
{
init();
}
SecondOrderRecursiveFilter::~SecondOrderRecursiveFilter()
{}
void SecondOrderRecursiveFilter::setFrequencies(float samplingFrequency, float centerFrequency)
{
m_frequencyRatio = centerFrequency / samplingFrequency;
init();
}
void SecondOrderRecursiveFilter::setR(float r)
{
m_r = r;
init();
}
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]);
float y = m_v[0] - m_v[2];
m_v[2] = m_v[1];
m_v[1] = m_v[0];
return (short) y;
}
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]);
float y = m_v[0] - m_v[2];
m_v[2] = m_v[1];
m_v[1] = m_v[0];
return y;
}
void SecondOrderRecursiveFilter::init()
{
for (int i = 0; i < 3; i++)
{
m_v[i] = 0.0f;
}
}

View File

@ -0,0 +1,45 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2017 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 <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#ifndef SDRBASE_DSP_RECURSIVEFILTERS_H_
#define SDRBASE_DSP_RECURSIVEFILTERS_H_
/**
* \Brief: This is a second order bandpass filter using recursive method. r is in range ]0..1[ the higher the steeper the filter.
* inspired by:http://www.ece.umd.edu/~tretter/commlab/c6713slides/FSKSlides.pdf
*/
class SecondOrderRecursiveFilter
{
public:
SecondOrderRecursiveFilter(float samplingFrequency, float centerFrequency, float r);
~SecondOrderRecursiveFilter();
void setFrequencies(float samplingFrequency, float centerFrequency);
void setR(float r);
short run(short sample);
float run(float sample);
private:
void init();
float m_r;
float m_frequencyRatio;
float m_v[3];
};
#endif /* SDRBASE_DSP_RECURSIVEFILTERS_H_ */