mirror of
https://github.com/f4exb/sdrangel.git
synced 2024-11-26 01:39:05 -05:00
ATV Demod: implemented BFU with PLL for single sideband modes
This commit is contained in:
parent
a8adc84e89
commit
303fd3ccc7
@ -126,6 +126,7 @@ set(sdrbase_SOURCES
|
||||
sdrbase/dsp/basebandsamplesink.cpp
|
||||
sdrbase/dsp/basebandsamplesource.cpp
|
||||
sdrbase/dsp/nullsink.cpp
|
||||
sdrbase/dsp/recursivefilters.cpp
|
||||
sdrbase/dsp/spectrumscopecombovis.cpp
|
||||
sdrbase/dsp/spectrumscopengcombovis.cpp
|
||||
sdrbase/dsp/scopevis.cpp
|
||||
@ -235,6 +236,7 @@ set(sdrbase_HEADERS
|
||||
sdrbase/dsp/phasediscri.h
|
||||
sdrbase/dsp/phaselock.h
|
||||
sdrbase/dsp/pidcontroller.h
|
||||
sdrbase/dsp/recursivefilters.h
|
||||
sdrbase/dsp/samplesinkfifo.h
|
||||
sdrbase/dsp/samplesourcefifo.h
|
||||
sdrbase/dsp/samplesinkfifodoublebuffered.h
|
||||
|
@ -51,6 +51,8 @@ ATVDemod::ATVDemod() :
|
||||
m_fltAmpDelta(1.0),
|
||||
m_fltAmpLineAverage(0.0f),
|
||||
m_intNumberSamplePerTop(0),
|
||||
m_bfoPLL(200/1000000, 100/1000000, 0.01),
|
||||
m_bfoFilter(200.0, 1000000.0, 0.9),
|
||||
m_interpolatorDistanceRemain(0.0f),
|
||||
m_interpolatorDistance(1.0f),
|
||||
m_DSBFilter(0),
|
||||
@ -113,14 +115,16 @@ void ATVDemod::configureRF(
|
||||
float fltRFBandwidth,
|
||||
float fltRFOppBandwidth,
|
||||
bool blnFFTFiltering,
|
||||
bool blnDecimatorEnable)
|
||||
bool blnDecimatorEnable,
|
||||
float fltBFOFrequency)
|
||||
{
|
||||
Message* msgCmd = MsgConfigureRFATVDemod::create(
|
||||
enmModulation,
|
||||
fltRFBandwidth,
|
||||
fltRFOppBandwidth,
|
||||
blnFFTFiltering,
|
||||
blnDecimatorEnable);
|
||||
blnDecimatorEnable,
|
||||
fltBFOFrequency);
|
||||
objMessageQueue->push(msgCmd);
|
||||
}
|
||||
|
||||
@ -238,7 +242,7 @@ void ATVDemod::demod(Complex& c)
|
||||
int n_out;
|
||||
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)
|
||||
{
|
||||
@ -308,7 +312,7 @@ void ATVDemod::demod(Complex& c)
|
||||
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
|
||||
fltVal = fltNorm;
|
||||
@ -329,6 +333,39 @@ void ATVDemod::demod(Complex& c)
|
||||
fltVal -= m_fltAmpMin;
|
||||
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
|
||||
{
|
||||
fltVal = 0.0f;
|
||||
@ -560,14 +597,14 @@ bool ATVDemod::handleMessage(const Message& cmd)
|
||||
m_objConfig = objCfg.m_objMsgConfig;
|
||||
|
||||
qDebug() << "ATVDemod::handleMessage: MsgConfigureATVDemod:"
|
||||
<< " m_fltVoltLevelSynchroBlack" << m_objConfig.m_fltVoltLevelSynchroBlack
|
||||
<< " m_fltVoltLevelSynchroTop" << m_objConfig.m_fltVoltLevelSynchroTop
|
||||
<< " m_fltFramePerS" << m_objConfig.m_fltFramePerS
|
||||
<< " m_fltLineDurationUs" << m_objConfig.m_fltLineDurationUs
|
||||
<< " m_fltRatioOfRowsToDisplay" << m_objConfig.m_fltRatioOfRowsToDisplay
|
||||
<< " m_fltTopDurationUs" << m_objConfig.m_fltTopDurationUs
|
||||
<< " m_blnHSync" << m_objConfig.m_blnHSync
|
||||
<< " m_blnVSync" << m_objConfig.m_blnVSync;
|
||||
<< " m_fltVoltLevelSynchroBlack:" << m_objConfig.m_fltVoltLevelSynchroBlack
|
||||
<< " m_fltVoltLevelSynchroTop:" << m_objConfig.m_fltVoltLevelSynchroTop
|
||||
<< " m_fltFramePerS:" << m_objConfig.m_fltFramePerS
|
||||
<< " m_fltLineDurationUs:" << m_objConfig.m_fltLineDurationUs
|
||||
<< " m_fltRatioOfRowsToDisplay:" << m_objConfig.m_fltRatioOfRowsToDisplay
|
||||
<< " m_fltTopDurationUs:" << m_objConfig.m_fltTopDurationUs
|
||||
<< " m_blnHSync:" << m_objConfig.m_blnHSync
|
||||
<< " m_blnVSync:" << m_objConfig.m_blnVSync;
|
||||
|
||||
applySettings();
|
||||
|
||||
@ -580,11 +617,12 @@ bool ATVDemod::handleMessage(const Message& cmd)
|
||||
m_objRFConfig = objCfg.m_objMsgConfig;
|
||||
|
||||
qDebug() << "ATVDemod::handleMessage: MsgConfigureRFATVDemod:"
|
||||
<< " m_enmModulation" << m_objRFConfig.m_enmModulation
|
||||
<< " m_fltRFBandwidth" << m_objRFConfig.m_fltRFBandwidth
|
||||
<< " m_fltRFOppBandwidth" << m_objRFConfig.m_fltRFOppBandwidth
|
||||
<< " m_blnFFTFiltering" << m_objRFConfig.m_blnFFTFiltering
|
||||
<< " m_blnDecimatorEnable" << m_objRFConfig.m_blndecimatorEnable;
|
||||
<< " m_enmModulation:" << m_objRFConfig.m_enmModulation
|
||||
<< " m_fltRFBandwidth:" << m_objRFConfig.m_fltRFBandwidth
|
||||
<< " m_fltRFOppBandwidth:" << m_objRFConfig.m_fltRFOppBandwidth
|
||||
<< " m_blnFFTFiltering:" << m_objRFConfig.m_blnFFTFiltering
|
||||
<< " m_blnDecimatorEnable:" << m_objRFConfig.m_blndecimatorEnable
|
||||
<< " m_fltBFOFrequency:" << m_objRFConfig.m_fltBFOFrequency;
|
||||
|
||||
applySettings();
|
||||
|
||||
@ -677,6 +715,14 @@ void ATVDemod::applySettings()
|
||||
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_objRFRunning = m_objRFConfig;
|
||||
@ -692,3 +738,15 @@ int ATVDemod::getEffectiveSampleRate()
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -31,6 +31,8 @@
|
||||
#include "dsp/movingaverage.h"
|
||||
#include "dsp/fftfilt.h"
|
||||
#include "dsp/agc.h"
|
||||
#include "dsp/phaselock.h"
|
||||
#include "dsp/recursivefilters.h"
|
||||
#include "audio/audiofifo.h"
|
||||
#include "util/message.h"
|
||||
#include "atvscreen.h"
|
||||
@ -46,8 +48,8 @@ public:
|
||||
ATV_FM1, //!< Classical frequency modulation with discriminator #1
|
||||
ATV_FM2, //!< Classical frequency modulation with discriminator #2
|
||||
ATV_AM, //!< Classical amplitude modulation
|
||||
ATV_VAMU, //!< 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_USB, //!< AM with vestigial lower side band (main signal is in the upper side)
|
||||
ATV_LSB //!< AM with vestigial upper side band (main signal is in the lower side)
|
||||
};
|
||||
|
||||
struct ATVConfig
|
||||
@ -84,6 +86,7 @@ public:
|
||||
float m_fltRFOppBandwidth;
|
||||
bool m_blnFFTFiltering;
|
||||
bool m_blndecimatorEnable;
|
||||
float m_fltBFOFrequency;
|
||||
|
||||
ATVRFConfig() :
|
||||
m_intFrequencyOffset(0),
|
||||
@ -91,7 +94,8 @@ public:
|
||||
m_fltRFBandwidth(0),
|
||||
m_fltRFOppBandwidth(0),
|
||||
m_blnFFTFiltering(false),
|
||||
m_blndecimatorEnable(false)
|
||||
m_blndecimatorEnable(false),
|
||||
m_fltBFOFrequency(0.0f)
|
||||
{
|
||||
}
|
||||
};
|
||||
@ -135,7 +139,8 @@ public:
|
||||
float fltRFBandwidth,
|
||||
float fltRFOppBandwidth,
|
||||
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 start();
|
||||
@ -146,6 +151,7 @@ public:
|
||||
int getSampleRate();
|
||||
int getEffectiveSampleRate();
|
||||
double getMagSq() const { return m_objMagSqAverage.average(); } //!< Beware this is scaled to 2^30
|
||||
bool getBFOLocked();
|
||||
|
||||
private:
|
||||
struct ATVConfigPrivate
|
||||
@ -218,14 +224,16 @@ private:
|
||||
float fltRFBandwidth,
|
||||
float fltRFOppBandwidth,
|
||||
bool blnFFTFiltering,
|
||||
bool blndecimatorEnable)
|
||||
bool blndecimatorEnable,
|
||||
int intBFOFrequency)
|
||||
{
|
||||
return new MsgConfigureRFATVDemod(
|
||||
enmModulation,
|
||||
fltRFBandwidth,
|
||||
fltRFOppBandwidth,
|
||||
blnFFTFiltering,
|
||||
blndecimatorEnable);
|
||||
blndecimatorEnable,
|
||||
intBFOFrequency);
|
||||
}
|
||||
|
||||
ATVRFConfig m_objMsgConfig;
|
||||
@ -236,7 +244,8 @@ private:
|
||||
float fltRFBandwidth,
|
||||
float fltRFOppBandwidth,
|
||||
bool blnFFTFiltering,
|
||||
bool blndecimatorEnable) :
|
||||
bool blndecimatorEnable,
|
||||
float fltBFOFrequency) :
|
||||
Message()
|
||||
{
|
||||
m_objMsgConfig.m_enmModulation = enmModulation;
|
||||
@ -244,6 +253,7 @@ private:
|
||||
m_objMsgConfig.m_fltRFOppBandwidth = fltRFOppBandwidth;
|
||||
m_objMsgConfig.m_blnFFTFiltering = blnFFTFiltering;
|
||||
m_objMsgConfig.m_blndecimatorEnable = blndecimatorEnable;
|
||||
m_objMsgConfig.m_fltBFOFrequency = fltBFOFrequency;
|
||||
}
|
||||
};
|
||||
|
||||
@ -286,6 +296,8 @@ private:
|
||||
MovingAverage<double> m_objMagSqAverage;
|
||||
|
||||
NCO m_nco;
|
||||
SimplePhaseLock m_bfoPLL;
|
||||
SecondOrderRecursiveFilter m_bfoFilter;
|
||||
|
||||
// Interpolator group for decimation and/or double sideband RF filtering
|
||||
Interpolator m_interpolator;
|
||||
|
@ -105,6 +105,7 @@ QByteArray ATVDemodGUI::serialize() const
|
||||
s.writeBool(11, ui->halfImage->isChecked());
|
||||
s.writeS32(12, ui->rfBW->value());
|
||||
s.writeS32(13, ui->rfOppBW->value());
|
||||
s.writeS32(14, ui->bfo->value());
|
||||
|
||||
return s.final();
|
||||
}
|
||||
@ -160,6 +161,8 @@ bool ATVDemodGUI::deserialize(const QByteArray& arrData)
|
||||
ui->rfBW->setValue(tmp);
|
||||
d.readS32(13, &tmp, 10);
|
||||
ui->rfOppBW->setValue(tmp);
|
||||
d.readS32(14, &tmp, 10);
|
||||
ui->bfo->setValue(tmp);
|
||||
|
||||
blockApplySettings(false);
|
||||
m_objChannelMarker.blockSignals(false);
|
||||
@ -336,7 +339,8 @@ void ATVDemodGUI::applyRFSettings()
|
||||
ui->rfBW->value() * 100000.0f,
|
||||
ui->rfOppBW->value() * 100000.0f,
|
||||
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.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);
|
||||
} else if (ui->modulation->currentIndex() == (int) ATVDemod::ATV_VAMU) {
|
||||
} else if (ui->modulation->currentIndex() == (int) ATVDemod::ATV_USB) {
|
||||
m_objChannelMarker.setSidebands(ChannelMarker::vusb);
|
||||
} else {
|
||||
m_objChannelMarker.setSidebands(ChannelMarker::vusb);
|
||||
@ -413,6 +417,12 @@ void ATVDemodGUI::tick()
|
||||
m_objMagSqAverage.feed(m_objATVDemod->getMagSq());
|
||||
double magSqDB = CalcDb::dbPower(m_objMagSqAverage.average() / (1<<30));
|
||||
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;
|
||||
@ -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();
|
||||
}
|
||||
|
||||
|
@ -79,6 +79,7 @@ private slots:
|
||||
void on_decimatorEnable_toggled(bool checked);
|
||||
void on_deltaFrequency_changed(quint64 value);
|
||||
void on_deltaFrequencyMinus_toggled(bool minus);
|
||||
void on_bfo_valueChanged(int value);
|
||||
|
||||
private:
|
||||
Ui::ATVDemodGUI* ui;
|
||||
|
@ -40,7 +40,7 @@
|
||||
<x>10</x>
|
||||
<y>10</y>
|
||||
<width>501</width>
|
||||
<height>71</height>
|
||||
<height>81</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@ -52,23 +52,6 @@
|
||||
</property>
|
||||
<item>
|
||||
<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>
|
||||
<layout class="QHBoxLayout" name="deltaFrequencyLayout">
|
||||
<item>
|
||||
@ -124,6 +107,30 @@
|
||||
</item>
|
||||
</layout>
|
||||
</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>
|
||||
<widget class="QLabel" name="channelSampleRateText">
|
||||
<property name="minimumSize">
|
||||
@ -144,35 +151,77 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="modulation">
|
||||
<property name="toolTip">
|
||||
<string>Modulation type</string>
|
||||
<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">
|
||||
<string>BFO frequency adjust</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>-500</number>
|
||||
</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>
|
||||
<widget class="QLabel" name="bfoText">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</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>
|
||||
<widget class="Line" name="line_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</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>VAMU</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>VAML</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
@ -211,6 +260,38 @@
|
||||
</item>
|
||||
<item>
|
||||
<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>
|
||||
<widget class="ButtonSwitch" name="rfFiltering">
|
||||
<property name="toolTip">
|
||||
|
@ -112,6 +112,24 @@ private:
|
||||
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
|
||||
{
|
||||
public:
|
||||
|
69
sdrbase/dsp/recursivefilters.cpp
Normal file
69
sdrbase/dsp/recursivefilters.cpp
Normal 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;
|
||||
}
|
||||
}
|
||||
|
45
sdrbase/dsp/recursivefilters.h
Normal file
45
sdrbase/dsp/recursivefilters.h
Normal 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_ */
|
Loading…
Reference in New Issue
Block a user