SDRAngel  4.11.5
Developer docs for <a href="https://github.com/f4exb/sdrangel">SDRangel<\a>, an Open Source Qt5 / OpenGL 3.0+ SDR and signal analyzer frontend to various hardware.
Classes | Public Member Functions | Static Private Member Functions | Private Attributes | List of all members
PhaseLockComplex Class Reference

#include <phaselockcomplex.h>

+ Collaboration diagram for PhaseLockComplex:

Classes

class  ExpAvg
 

Public Member Functions

 PhaseLockComplex ()
 
void computeCoefficients (Real wn, Real zeta, Real K)
 
void setPskOrder (unsigned int order)
 
void setSampleRate (unsigned int sampleRate)
 
void reset ()
 
void feed (float re, float im)
 
const std::complex< float > & getComplex () const
 
float getReal () const
 
float getImag () const
 
bool locked () const
 
float getFreq () const
 
float getDeltaPhi () const
 
float getPhiHat () const
 

Static Private Member Functions

static float normalizeAngle (float angle)
 

Private Attributes

float m_a1
 
float m_a2
 
float m_b0
 
float m_b1
 
float m_b2
 
float m_v0
 
float m_v1
 
float m_v2
 
float m_deltaPhi
 
float m_phiHat
 
float m_phiHatPrev
 
std::complex< float > m_y
 
std::complex< float > m_p
 
float m_yRe
 
float m_yIm
 
float m_freq
 
float m_freqPrev
 
float m_freqTest
 
int m_lockCount
 
float m_lockFreq
 
unsigned int m_pskOrder
 
int m_lockTime
 
int m_lockTimeCount
 
ExpAvg m_expAvg
 

Detailed Description

General purpose Phase-locked loop using complex analytic signal input.

Definition at line 31 of file phaselockcomplex.h.

Constructor & Destructor Documentation

◆ PhaseLockComplex()

PhaseLockComplex::PhaseLockComplex ( )

Definition at line 29 of file phaselockcomplex.cpp.

29  :
30  m_a1(1.0),
31  m_a2(1.0),
32  m_b0(1.0),
33  m_b1(1.0),
34  m_b2(1.0),
35  m_v0(0.0),
36  m_v1(0.0),
37  m_v2(0.0),
38  m_deltaPhi(0.0),
39  m_phiHat(0.0),
40  m_phiHatPrev(0.0),
41  m_y(1.0, 0.0),
42  m_p(1.0, 0.0),
43  m_yRe(1.0),
44  m_yIm(0.0),
45  m_freq(0.0),
46  m_freqPrev(0.0),
47  m_freqTest(0.0),
48  m_lockCount(0),
49  m_lockFreq(0.026f),
50  m_pskOrder(1),
51  m_lockTime(480),
53 {
54 }
std::complex< float > m_y
unsigned int m_pskOrder
std::complex< float > m_p

Member Function Documentation

◆ computeCoefficients()

void PhaseLockComplex::computeCoefficients ( Real  wn,
Real  zeta,
Real  K 
)

Compute loop filter parameters (active PI design)

Parameters
wnPLL bandwidth relative to Nyquist frequency
zetaPLL damping factor
KPLL loop gain

Definition at line 56 of file phaselockcomplex.cpp.

References b0, b1, b2, m_a1, m_a2, m_b0, m_b1, m_b2, and reset().

Referenced by AMDemod::AMDemod(), ChannelAnalyzer::ChannelAnalyzer(), and FreqTracker::FreqTracker().

57 {
58  double t1 = K/(wn*wn); //
59  double t2 = 2*zeta/wn - 1/K; //
60 
61  double b0 = 2*K*(1.+t2/2.0f);
62  double b1 = 2*K*2.;
63  double b2 = 2*K*(1.-t2/2.0f);
64 
65  double a0 = 1 + t1/2.0f;
66  double a1 = -t1;
67  double a2 = -1 + t1/2.0f;
68 
69  qDebug("PhaseLockComplex::computeCoefficients: b_raw: %f %f %f", b0, b1, b2);
70  qDebug("PhaseLockComplex::computeCoefficients: a_raw: %f %f %f", a0, a1, a2);
71 
72  m_b0 = b0 / a0;
73  m_b1 = b1 / a0;
74  m_b2 = b2 / a0;
75 
76  // a0 = 1.0 is implied
77  m_a1 = a1 / a0;
78  m_a2 = a2 / a0;
79 
80  qDebug("PhaseLockComplex::computeCoefficients: b: %f %f %f", m_b0, m_b1, m_b2);
81  qDebug("PhaseLockComplex::computeCoefficients: a: 1.0 %f %f", m_a1, m_a2);
82 
83  reset();
84 }
uint8_t b2
Definition: decimators.h:57
uint8_t b1
Definition: decimators.h:56
uint8_t b0
Definition: decimators.h:55
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ feed()

void PhaseLockComplex::feed ( float  re,
float  im 
)

Feed PLL with a new signa sample

Definition at line 121 of file phaselockcomplex.cpp.

References arg(), cos(), PhaseLockComplex::ExpAvg::feed(), m_a1, m_a2, m_b0, m_b1, m_b2, m_deltaPhi, m_expAvg, m_freq, m_freqPrev, m_freqTest, m_lockCount, m_lockFreq, m_lockTime, m_lockTimeCount, m_phiHat, m_phiHatPrev, M_PI, m_pskOrder, m_v0, m_v1, m_v2, m_y, m_yIm, m_yRe, normalizeAngle(), and sin().

Referenced by ChannelAnalyzer::processOneSample(), AMDemod::processOneSample(), and FreqTracker::processOneSample().

122 {
123  m_yRe = cos(m_phiHat);
124  m_yIm = sin(m_phiHat);
125  m_y.real(m_yRe);
126  m_y.imag(m_yIm);
127  std::complex<float> x(re, im);
128  m_deltaPhi = std::arg(x * std::conj(m_y));
129 
130  // bring phase 0 on any of the PSK symbols
131  if (m_pskOrder > 1) {
133  }
134 
135  // advance buffer
136  m_v2 = m_v1; // shift center register to upper register
137  m_v1 = m_v0; // shift lower register to center register
138 
139  // compute new lower register
141 
142  // compute new output
144 
145  // prevent saturation
146  if (m_phiHat > 2.0*M_PI)
147  {
148  m_v0 *= (m_phiHat - 2.0*M_PI) / m_phiHat;
149  m_v1 *= (m_phiHat - 2.0*M_PI) / m_phiHat;
150  m_v2 *= (m_phiHat - 2.0*M_PI) / m_phiHat;
151  m_phiHat -= 2.0*M_PI;
152  }
153 
154  if (m_phiHat < -2.0*M_PI)
155  {
156  m_v0 *= (m_phiHat + 2.0*M_PI) / m_phiHat;
157  m_v1 *= (m_phiHat + 2.0*M_PI) / m_phiHat;
158  m_v2 *= (m_phiHat + 2.0*M_PI) / m_phiHat;
159  m_phiHat += 2.0*M_PI;
160  }
161 
162  // lock and frequency estimation
163  if (m_pskOrder > 1)
164  {
165  float dPhi = normalizeAngle(m_phiHat - m_phiHatPrev);
166  m_freq = m_expAvg.feed(dPhi);
167 
168  if (m_lockTimeCount < m_lockTime-1)
169  {
170  m_lockTimeCount++;
171  }
172  else
173  {
174  float dF = m_freq - m_freqTest;
175 
176  if ((dF > -m_lockFreq) && (dF < m_lockFreq))
177  {
178  if (m_lockCount < 20) {
179  m_lockCount++;
180  }
181  }
182  else
183  {
184  if (m_lockCount > 0) {
185  m_lockCount--;
186  }
187  }
188 
189  m_freqTest = m_freq;
190  m_lockTimeCount = 0;
191  }
192 
194  }
195  else
196  {
197  m_freqTest = normalizeAngle(m_phiHat - m_phiHatPrev);
198  m_freq = m_expAvg.feed(m_freqTest);
199 
200  float dFreq = m_freqTest - m_freqPrev;
201 
202  if ((dFreq > -0.01) && (dFreq < 0.01))
203  {
204  if (m_lockCount < (m_lockTime-1)) { // [0..479]
205  m_lockCount++;
206  }
207  }
208  else
209  {
210  m_lockCount = 0;
211  }
212 
214  m_freqPrev = m_freqTest;
215  }
216 }
Fixed< IntType, IntBits > cos(Fixed< IntType, IntBits > const &x)
Definition: fixed.h:2271
#define M_PI
Definition: rdsdemod.cpp:27
Fixed< IntType, IntBits > arg(const std::complex< Fixed< IntType, IntBits > > &val)
Definition: fixed.h:2401
std::complex< float > m_y
static float normalizeAngle(float angle)
Fixed< IntType, IntBits > sin(Fixed< IntType, IntBits > const &x)
Definition: fixed.h:2265
unsigned int m_pskOrder
float feed(const float &x)
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ getComplex()

const std::complex<float>& PhaseLockComplex::getComplex ( ) const
inline

Definition at line 50 of file phaselockcomplex.h.

Referenced by ChannelAnalyzer::processOneSample().

50 { return m_y; }
std::complex< float > m_y
+ Here is the caller graph for this function:

◆ getDeltaPhi()

float PhaseLockComplex::getDeltaPhi ( ) const
inline

Definition at line 55 of file phaselockcomplex.h.

Referenced by ChannelAnalyzer::getPllDeltaPhase().

55 { return m_deltaPhi; }
+ Here is the caller graph for this function:

◆ getFreq()

float PhaseLockComplex::getFreq ( ) const
inline

Definition at line 54 of file phaselockcomplex.h.

Referenced by FreqTracker::getFrequency(), ChannelAnalyzer::getPllFrequency(), and AMDemod::getPllFrequency().

54 { return m_freq; }
+ Here is the caller graph for this function:

◆ getImag()

float PhaseLockComplex::getImag ( ) const
inline

Definition at line 52 of file phaselockcomplex.h.

Referenced by AMDemod::processOneSample().

52 { return m_yIm; }
+ Here is the caller graph for this function:

◆ getPhiHat()

float PhaseLockComplex::getPhiHat ( ) const
inline

Definition at line 56 of file phaselockcomplex.h.

Referenced by ChannelAnalyzer::getPllPhase().

56 { return m_phiHat; }
+ Here is the caller graph for this function:

◆ getReal()

float PhaseLockComplex::getReal ( ) const
inline

Definition at line 51 of file phaselockcomplex.h.

Referenced by AMDemod::processOneSample().

51 { return m_yRe; }
+ Here is the caller graph for this function:

◆ locked()

bool PhaseLockComplex::locked ( ) const
inline

Definition at line 53 of file phaselockcomplex.h.

Referenced by AMDemod::getPllLocked(), FreqTracker::getPllLocked(), and ChannelAnalyzer::isPllLocked().

+ Here is the caller graph for this function:

◆ normalizeAngle()

float PhaseLockComplex::normalizeAngle ( float  angle)
staticprivate

Normalize angle in radians into the [-pi,+pi] region

Definition at line 218 of file phaselockcomplex.cpp.

References M_PI.

Referenced by feed().

219 {
220  while (angle <= -M_PI) {
221  angle += 2.0*M_PI;
222  }
223  while (angle > M_PI) {
224  angle -= 2.0*M_PI;
225  }
226  return angle;
227 }
#define M_PI
Definition: rdsdemod.cpp:27
+ Here is the caller graph for this function:

◆ reset()

void PhaseLockComplex::reset ( )

Definition at line 99 of file phaselockcomplex.cpp.

References m_deltaPhi, m_freq, m_freqPrev, m_freqTest, m_lockCount, m_lockTimeCount, m_p, m_phiHat, m_phiHatPrev, m_v0, m_v1, m_v2, m_y, m_yIm, and m_yRe.

Referenced by ChannelAnalyzer::applySettings(), FreqTracker::applySettings(), computeCoefficients(), setPskOrder(), and setSampleRate().

100 {
101  // reset filter accumulators and phase
102  m_v0 = 0.0f;
103  m_v1 = 0.0f;
104  m_v2 = 0.0f;
105  m_deltaPhi = 0.0f;
106  m_phiHat = 0.0f;
107  m_phiHatPrev = 0.0f;
108  m_y.real(1.0);
109  m_y.imag(0.0);
110  m_p.real(1.0);
111  m_p.imag(0.0);
112  m_yRe = 1.0f;
113  m_yIm = 0.0f;
114  m_freq = 0.0f;
115  m_freqPrev = 0.0f;
116  m_freqTest = 0.0f;
117  m_lockCount = 0;
118  m_lockTimeCount = 0;
119 }
std::complex< float > m_y
std::complex< float > m_p
+ Here is the caller graph for this function:

◆ setPskOrder()

void PhaseLockComplex::setPskOrder ( unsigned int  order)

Set the PSK order for the phase comparator

Parameters
order0,1: no PSK (CW), 2: BPSK, 4: QPSK, 8: 8-PSK, ... use powers of two for real cases

Definition at line 86 of file phaselockcomplex.cpp.

References m_pskOrder, and reset().

Referenced by ChannelAnalyzer::applySettings(), and FreqTracker::applySettings().

87 {
88  m_pskOrder = order > 0 ? order : 1;
89  reset();
90 }
unsigned int m_pskOrder
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ setSampleRate()

void PhaseLockComplex::setSampleRate ( unsigned int  sampleRate)

Set sample rate information only for frequency and lock condition calculation

Definition at line 92 of file phaselockcomplex.cpp.

References m_lockFreq, m_lockTime, M_PI, m_pskOrder, and reset().

Referenced by AMDemod::applyAudioSampleRate(), ChannelAnalyzer::applyChannelSettings(), ChannelAnalyzer::applySettings(), and FreqTracker::configureChannelizer().

93 {
94  m_lockTime = sampleRate / 100; // 10ms for order 1
95  m_lockFreq = (2.0*M_PI*(m_pskOrder > 1 ? 6.0 : 1.0)) / sampleRate; // +/- 6 Hz frequency swing
96  reset();
97 }
#define M_PI
Definition: rdsdemod.cpp:27
unsigned int m_pskOrder
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Member Data Documentation

◆ m_a1

float PhaseLockComplex::m_a1
private

Definition at line 85 of file phaselockcomplex.h.

Referenced by computeCoefficients(), and feed().

◆ m_a2

float PhaseLockComplex::m_a2
private

Definition at line 86 of file phaselockcomplex.h.

Referenced by computeCoefficients(), and feed().

◆ m_b0

float PhaseLockComplex::m_b0
private

Definition at line 87 of file phaselockcomplex.h.

Referenced by computeCoefficients(), and feed().

◆ m_b1

float PhaseLockComplex::m_b1
private

Definition at line 88 of file phaselockcomplex.h.

Referenced by computeCoefficients(), and feed().

◆ m_b2

float PhaseLockComplex::m_b2
private

Definition at line 89 of file phaselockcomplex.h.

Referenced by computeCoefficients(), and feed().

◆ m_deltaPhi

float PhaseLockComplex::m_deltaPhi
private

Definition at line 93 of file phaselockcomplex.h.

Referenced by feed(), and reset().

◆ m_expAvg

ExpAvg PhaseLockComplex::m_expAvg
private

Definition at line 108 of file phaselockcomplex.h.

Referenced by feed().

◆ m_freq

float PhaseLockComplex::m_freq
private

Definition at line 100 of file phaselockcomplex.h.

Referenced by feed(), and reset().

◆ m_freqPrev

float PhaseLockComplex::m_freqPrev
private

Definition at line 101 of file phaselockcomplex.h.

Referenced by feed(), and reset().

◆ m_freqTest

float PhaseLockComplex::m_freqTest
private

Definition at line 102 of file phaselockcomplex.h.

Referenced by feed(), and reset().

◆ m_lockCount

int PhaseLockComplex::m_lockCount
private

Definition at line 103 of file phaselockcomplex.h.

Referenced by feed(), and reset().

◆ m_lockFreq

float PhaseLockComplex::m_lockFreq
private

Definition at line 104 of file phaselockcomplex.h.

Referenced by feed(), and setSampleRate().

◆ m_lockTime

int PhaseLockComplex::m_lockTime
private

Definition at line 106 of file phaselockcomplex.h.

Referenced by feed(), and setSampleRate().

◆ m_lockTimeCount

int PhaseLockComplex::m_lockTimeCount
private

Definition at line 107 of file phaselockcomplex.h.

Referenced by feed(), and reset().

◆ m_p

std::complex<float> PhaseLockComplex::m_p
private

Definition at line 97 of file phaselockcomplex.h.

Referenced by reset().

◆ m_phiHat

float PhaseLockComplex::m_phiHat
private

Definition at line 94 of file phaselockcomplex.h.

Referenced by feed(), and reset().

◆ m_phiHatPrev

float PhaseLockComplex::m_phiHatPrev
private

Definition at line 95 of file phaselockcomplex.h.

Referenced by feed(), and reset().

◆ m_pskOrder

unsigned int PhaseLockComplex::m_pskOrder
private

Definition at line 105 of file phaselockcomplex.h.

Referenced by feed(), setPskOrder(), and setSampleRate().

◆ m_v0

float PhaseLockComplex::m_v0
private

Definition at line 90 of file phaselockcomplex.h.

Referenced by feed(), and reset().

◆ m_v1

float PhaseLockComplex::m_v1
private

Definition at line 91 of file phaselockcomplex.h.

Referenced by feed(), and reset().

◆ m_v2

float PhaseLockComplex::m_v2
private

Definition at line 92 of file phaselockcomplex.h.

Referenced by feed(), and reset().

◆ m_y

std::complex<float> PhaseLockComplex::m_y
private

Definition at line 96 of file phaselockcomplex.h.

Referenced by feed(), and reset().

◆ m_yIm

float PhaseLockComplex::m_yIm
private

Definition at line 99 of file phaselockcomplex.h.

Referenced by feed(), and reset().

◆ m_yRe

float PhaseLockComplex::m_yRe
private

Definition at line 98 of file phaselockcomplex.h.

Referenced by feed(), and reset().


The documentation for this class was generated from the following files: