Finished pilot PLL (not tested).
This commit is contained in:
parent
f0d58eac10
commit
f371d1bef3
32
FmDecode.cc
32
FmDecode.cc
|
@ -84,8 +84,17 @@ void PhaseDiscriminator::process(const IQSampleVector& samples_in,
|
||||||
// Construct phase-locked loop.
|
// Construct phase-locked loop.
|
||||||
PilotPhaseLock::PilotPhaseLock(double freq, double bandwidth, double minsignal)
|
PilotPhaseLock::PilotPhaseLock(double freq, double bandwidth, double minsignal)
|
||||||
{
|
{
|
||||||
// This is a type-2, 4th order phase-locked loop.
|
/*
|
||||||
// I don't understand what I'm doing; hopefully it just works.
|
* This is a type-2, 4th order phase-locked loop.
|
||||||
|
*
|
||||||
|
* Open-loop transfer function:
|
||||||
|
* G(z) = K * (z - Qz) / ((z - Qp) * (z - Qp) * (z - 1) * (z - 1))
|
||||||
|
* K = 3.125 * (bandwidth * 2 * PI)**3
|
||||||
|
* Qz = exp(-0.2 * bandwidth * 2*PI)
|
||||||
|
* Qp = exp(-2.5 * bandwidth * 2*PI)
|
||||||
|
*
|
||||||
|
* I don't understand what I'm doing; hopefully it just works.
|
||||||
|
*/
|
||||||
|
|
||||||
// Set min/max locking frequencies.
|
// Set min/max locking frequencies.
|
||||||
m_minfreq = (freq - bandwidth) * 2.0 * M_PI;
|
m_minfreq = (freq - bandwidth) * 2.0 * M_PI;
|
||||||
|
@ -101,13 +110,16 @@ PilotPhaseLock::PilotPhaseLock(double freq, double bandwidth, double minsignal)
|
||||||
double t = exp(-2.5 * bandwidth * 2.0 * M_PI);
|
double t = exp(-2.5 * bandwidth * 2.0 * M_PI);
|
||||||
m_phasor_a1 = -2.0 * t;
|
m_phasor_a1 = -2.0 * t;
|
||||||
m_phasor_a2 = t * t;
|
m_phasor_a2 = t * t;
|
||||||
m_phasor_b0 = m_phasor_a1 + m_phasor_a2;
|
m_phasor_b0 = 1 + m_phasor_a1 + m_phasor_a2;
|
||||||
|
|
||||||
// Create loop filter to stabilize the loop.
|
// Create loop filter to stabilize the loop.
|
||||||
// Zero at z = exp(-0.2 * bandwidth * 2*PI),
|
// Filter has one Zero at z = exp(-0.2 * bandwidth * 2*PI).
|
||||||
m_loopfilter_b0 = 1.0;
|
m_loopfilter_b0 = 0.5 * bandwidth * 2.0 * M_PI;
|
||||||
m_loopfilter_b1 = - exp(-0.2 * bandwidth * 2.0 * M_PI);
|
m_loopfilter_b1 = - m_loopfilter_b0 * exp(-0.2 * bandwidth * 2.0 * M_PI);
|
||||||
// TODO : loop gain
|
|
||||||
|
// After the loop filter, the phase error is integrated to produce
|
||||||
|
// the frequency. Then the frequency is integrated to produce the phase.
|
||||||
|
// These two integrators form the two remaining poles, both at z = 1.
|
||||||
|
|
||||||
// Reset frequency and phase.
|
// Reset frequency and phase.
|
||||||
m_freq = freq * 2.0 * M_PI;
|
m_freq = freq * 2.0 * M_PI;
|
||||||
|
@ -159,10 +171,10 @@ void PilotPhaseLock::process(const SampleVector& samples_in,
|
||||||
// Use simple linear approximation of arctan.
|
// Use simple linear approximation of arctan.
|
||||||
phase_err = phasor_q / phasor_i;
|
phase_err = phasor_q / phasor_i;
|
||||||
} else if (phasor_q > 0) {
|
} else if (phasor_q > 0) {
|
||||||
// We are lagging more than 45 degrees behind the input.
|
// We are more than 45 degrees ahead of the input.
|
||||||
phase_err = 1;
|
phase_err = 1;
|
||||||
} else {
|
} else {
|
||||||
// We are more than 45 degrees ahead of the input.
|
// We are lagging more than 45 degrees behind the input.
|
||||||
phase_err = -1;
|
phase_err = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,7 +186,7 @@ void PilotPhaseLock::process(const SampleVector& samples_in,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run phase error through loop filter and update frequency estimate.
|
// Run phase error through loop filter and update frequency estimate.
|
||||||
m_freq += m_loopfilter_b0 * phase_err
|
m_freq -= m_loopfilter_b0 * phase_err
|
||||||
+ m_loopfilter_b1 * m_loopfilter_x1;
|
+ m_loopfilter_b1 * m_loopfilter_x1;
|
||||||
m_loopfilter_x1 = phase_err;
|
m_loopfilter_x1 = phase_err;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue