1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2024-11-13 20:01:46 -05:00

Tx ph.1: new AM modulator plugin (3). Implemented actual modulation code.

This commit is contained in:
f4exb 2016-10-20 19:34:30 +02:00
parent c28751124c
commit 9fff2b8477
5 changed files with 74 additions and 29 deletions

View File

@ -18,6 +18,7 @@
#include <QTime>
#include <QDebug>
#include <QMutexLocker>
#include <stdio.h>
#include <complex.h>
#include <dsp/upchannelizer.h>
@ -35,7 +36,7 @@ AMMod::AMMod() :
m_config.m_inputFrequencyOffset = 0;
m_config.m_rfBandwidth = 12500;
m_config.m_afBandwidth = 3000;
m_config.m_modPercent = 20;
m_config.m_modFactor = 20;
m_config.m_audioSampleRate = DSPEngine::instance()->getAudioSampleRate();
apply();
@ -46,6 +47,8 @@ AMMod::AMMod() :
m_movingAverage.resize(16, 0);
m_volumeAGC.resize(4096, 0.003, 0);
m_magsq = 0.0;
m_toneNco.setFreq(1000.0, m_config.m_audioSampleRate);
}
AMMod::~AMMod()
@ -60,7 +63,30 @@ void AMMod::configure(MessageQueue* messageQueue, Real rfBandwidth, Real afBandw
void AMMod::pull(Sample& sample)
{
// TODO
Complex ci;
if (m_interpolator.interpolate(&m_interpolatorDistanceRemain, m_modSample, &ci))
{
m_settingsMutex.lock();
m_carrierNco.nextPhase();
m_toneNco.nextPhase();
m_settingsMutex.unlock();
m_carrierNco.getIQ(m_modSample);
Real t = m_toneNco.get();
m_modSample *= (t+1.0f) * m_running.m_modFactor * 16384.0f; // modulate carrier
m_interpolatorDistanceRemain += m_interpolatorDistance;
}
Real magsq = ci.real() * ci.real() + ci.imag() * ci.imag();
magsq /= (1<<30);
m_movingAverage.feed(magsq);
m_magsq = m_movingAverage.average();
sample.m_real = (FixReal) ci.real();
sample.m_imag = (FixReal) ci.imag();
}
void AMMod::start()
@ -100,7 +126,7 @@ bool AMMod::handleMessage(const Message& cmd)
m_config.m_rfBandwidth = cfg.getRFBandwidth();
m_config.m_afBandwidth = cfg.getAFBandwidth();
m_config.m_modPercent = cfg.getModPercent();
m_config.m_modFactor = cfg.getModFactor();
m_config.m_audioMute = cfg.getAudioMute();
apply();
@ -108,7 +134,7 @@ bool AMMod::handleMessage(const Message& cmd)
qDebug() << "AMMod::handleMessage: MsgConfigureAMMod:"
<< " m_rfBandwidth: " << m_config.m_rfBandwidth
<< " m_afBandwidth: " << m_config.m_afBandwidth
<< " m_modPercent: " << m_config.m_modPercent
<< " m_modFactor: " << m_config.m_modFactor
<< " m_audioMute: " << m_config.m_audioMute;
return true;
@ -122,10 +148,9 @@ bool AMMod::handleMessage(const Message& cmd)
void AMMod::apply()
{
if((m_config.m_inputFrequencyOffset != m_running.m_inputFrequencyOffset) ||
(m_config.m_outputSampleRate != m_running.m_outputSampleRate))
if(m_config.m_inputFrequencyOffset != m_running.m_inputFrequencyOffset)
{
m_carrierNco.setFreq(-m_config.m_inputFrequencyOffset, m_config.m_outputSampleRate);
m_carrierNco.setFreq(-m_config.m_inputFrequencyOffset, m_config.m_audioSampleRate);
}
if((m_config.m_outputSampleRate != m_running.m_outputSampleRate) ||
@ -150,7 +175,7 @@ void AMMod::apply()
m_running.m_inputFrequencyOffset = m_config.m_inputFrequencyOffset;
m_running.m_rfBandwidth = m_config.m_rfBandwidth;
m_running.m_afBandwidth = m_config.m_afBandwidth;
m_running.m_modPercent = m_config.m_modPercent;
m_running.m_modFactor = m_config.m_modFactor;
m_running.m_audioSampleRate = m_config.m_audioSampleRate;
m_running.m_audioMute = m_config.m_audioMute;
}

View File

@ -51,7 +51,7 @@ private:
public:
Real getRFBandwidth() const { return m_rfBandwidth; }
Real getAFBandwidth() const { return m_afBandwidth; }
Real getModPercent() const { return m_modPercent; }
float getModFactor() const { return m_modFactor; }
bool getAudioMute() const { return m_audioMute; }
static MsgConfigureAMMod* create(Real rfBandwidth, Real afBandwidth, int modPercent, bool audioMute)
@ -62,14 +62,14 @@ private:
private:
Real m_rfBandwidth;
Real m_afBandwidth;
Real m_modPercent;
float m_modFactor;
bool m_audioMute;
MsgConfigureAMMod(Real rfBandwidth, Real afBandwidth, int modPercent, bool audioMute) :
MsgConfigureAMMod(Real rfBandwidth, Real afBandwidth, float modFactor, bool audioMute) :
Message(),
m_rfBandwidth(rfBandwidth),
m_afBandwidth(afBandwidth),
m_modPercent(modPercent),
m_modFactor(modFactor),
m_audioMute(audioMute)
{ }
};
@ -90,7 +90,7 @@ private:
qint64 m_inputFrequencyOffset;
Real m_rfBandwidth;
Real m_afBandwidth;
int m_modPercent;
float m_modFactor;
quint32 m_audioSampleRate;
bool m_audioMute;
@ -99,7 +99,7 @@ private:
m_inputFrequencyOffset(0),
m_rfBandwidth(-1),
m_afBandwidth(-1),
m_modPercent(20),
m_modFactor(0.2f),
m_audioSampleRate(0),
m_audioMute(false)
{ }
@ -110,6 +110,7 @@ private:
NCO m_carrierNco;
NCO m_toneNco;
Complex m_modSample;
Interpolator m_interpolator;
Real m_interpolatorDistance;
Real m_interpolatorDistanceRemain;

View File

@ -278,7 +278,7 @@ void AMModGUI::applySettings()
m_amMod->configure(m_amMod->getInputMessageQueue(),
m_rfBW[ui->rfBW->value()],
ui->afBW->value() * 1000.0,
ui->modPercent->value(),
ui->modPercent->value() / 100.0f,
ui->audioMute->isChecked());
}
}

View File

@ -49,22 +49,28 @@ void NCO::setFreq(Real freq, Real sampleRate)
float NCO::next()
{
m_phase += m_phaseIncrement;
while(m_phase >= TableSize)
m_phase -= TableSize;
while(m_phase < 0)
m_phase += TableSize;
nextPhase();
return m_table[m_phase];
}
Complex NCO::nextIQ()
{
m_phase += m_phaseIncrement;
while(m_phase >= TableSize)
m_phase -= TableSize;
while(m_phase < 0)
m_phase += TableSize;
nextPhase();
return Complex(m_table[m_phase], -m_table[(m_phase + TableSize / 4) % TableSize]);
}
float NCO::get()
{
return m_table[m_phase];
}
Complex NCO::getIQ()
{
return Complex(m_table[m_phase], -m_table[(m_phase + TableSize / 4) % TableSize]);
}
void NCO::getIQ(Complex& c)
{
c.real(m_table[m_phase]);
c.imag(-m_table[(m_phase + TableSize / 4) % TableSize]);
}

View File

@ -38,8 +38,21 @@ public:
NCO();
void setFreq(Real freq, Real sampleRate);
Real next();
Complex nextIQ();
void nextPhase() //!< Increment phase
{
m_phase += m_phaseIncrement;
while(m_phase >= TableSize)
m_phase -= TableSize;
while(m_phase < 0)
m_phase += TableSize;
}
Real next(); //!< Return next real sample
Complex nextIQ(); //!< Return next complex sample
Real get(); //!< Return current real sample (no phase increment)
Complex getIQ(); //!< Return current complex sample (no phase increment)
void getIQ(Complex& c); //!< Sets to the current complex sample (no phase increment)
};
#endif // INCLUDE_NCO_H