GNU Radio Manual and C++ API Reference  3.7.9.2
The Free & Open Software Radio Ecosystem
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
control_loop.h
Go to the documentation of this file.
1 /* -*- c++ -*- */
2 /*
3  * Copyright 2011,2013 Free Software Foundation, Inc.
4  *
5  * This file is part of GNU Radio
6  *
7  * GNU Radio is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3, or (at your option)
10  * any later version.
11  *
12  * GNU Radio is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with GNU Radio; see the file COPYING. If not, write to
19  * the Free Software Foundation, Inc., 51 Franklin Street,
20  * Boston, MA 02110-1301, USA.
21  */
22 
23 #ifndef GR_BLOCKS_CONTROL_LOOP
24 #define GR_BLOCKS_CONTROL_LOOP
25 
26 #include <gnuradio/blocks/api.h>
27 
28 namespace gr {
29  namespace blocks {
30 
31  /*!
32  * \brief A second-order control loop implementation class.
33  *
34  * \details
35  * This class implements a second order control loop and is
36  * inteded to act as a parent class to blocks which need a control
37  * loop (e.g., gr::digital::costas_loop_cc,
38  * gr::analog::pll_refout_cc, etc.). It takes in a loop bandwidth
39  * as well as a max and min frequency and provides the functions
40  * that control the update of the loop.
41  *
42  * The loop works of alpha and beta gains. These gains are
43  * calculated using the input loop bandwidth and a pre-set damping
44  * factor. The damping factor can be changed using the
45  * #set_damping_factor after the block is
46  * constructed. The alpha and beta values can be set using their
47  * respective #set_alpha or #set_beta functions if very precise
48  * control over these is required.
49  *
50  * The class tracks both phase and frequency of a signal based on
51  * an error signal. The error calculation is unique for each
52  * algorithm and is calculated externally and passed to the
53  * advance_loop function, which uses this to update its phase and
54  * frequency estimates.
55  *
56  * This class also provides the functions #phase_wrap and
57  * #frequency_limit to easily keep the phase and frequency
58  * estimates within our set bounds (phase_wrap keeps it within
59  * +/-2pi).
60  */
62  {
63  protected:
64  float d_phase, d_freq;
65  float d_max_freq, d_min_freq;
66  float d_damping, d_loop_bw;
67  float d_alpha, d_beta;
68 
69  public:
70  control_loop(void) {}
71  control_loop(float loop_bw, float max_freq, float min_freq);
72  virtual ~control_loop();
73 
74  /*! \brief Update the system gains from the loop bandwidth and damping factor.
75  *
76  * \details
77  * This function updates the system gains based on the loop
78  * bandwidth and damping factor of the system. These two
79  * factors can be set separately through their own set
80  * functions.
81  */
82  void update_gains();
83 
84  /*! \brief Advance the control loop based on the current gain
85  * settings and the inputted error signal.
86  */
87  void advance_loop(float error);
88 
89  /*! \brief Keep the phase between -2pi and 2pi.
90  *
91  * \details
92  * This function keeps the phase between -2pi and 2pi. If the
93  * phase is greater than 2pi by d, it wraps around to be -2pi+d;
94  * similarly if it is less than -2pi by d, it wraps around to
95  * 2pi-d.
96  *
97  * This function should be called after advance_loop to keep the
98  * phase in a good operating region. It is set as a separate
99  * method in case another way is desired as this is fairly
100  * heavy-handed.
101  */
102  void phase_wrap();
103 
104  /*! \brief Keep the frequency between d_min_freq and d_max_freq.
105  *
106  * \details
107  * This function keeps the frequency between d_min_freq and
108  * d_max_freq. If the frequency is greater than d_max_freq, it
109  * is set to d_max_freq. If the frequency is less than
110  * d_min_freq, it is set to d_min_freq.
111  *
112  * This function should be called after advance_loop to keep the
113  * frequency in the specified region. It is set as a separate
114  * method in case another way is desired as this is fairly
115  * heavy-handed.
116  */
117  void frequency_limit();
118 
119  /*******************************************************************
120  * SET FUNCTIONS
121  *******************************************************************/
122 
123  /*!
124  * \brief Set the loop bandwidth.
125  *
126  * \details
127  * Set the loop filter's bandwidth to \p bw. This should be
128  * between 2*pi/200 and 2*pi/100 (in rads/samp). It must also be
129  * a positive number.
130  *
131  * When a new damping factor is set, the gains, alpha and beta,
132  * of the loop are recalculated by a call to update_gains().
133  *
134  * \param bw (float) new bandwidth
135  */
136  virtual void set_loop_bandwidth(float bw);
137 
138  /*!
139  * \brief Set the loop damping factor.
140  *
141  * \details
142  * Set the loop filter's damping factor to \p df. The damping
143  * factor should be sqrt(2)/2.0 for critically damped systems.
144  * Set it to anything else only if you know what you are
145  * doing. It must be a number between 0 and 1.
146  *
147  * When a new damping factor is set, the gains, alpha and beta,
148  * of the loop are recalculated by a call to update_gains().
149  *
150  * \param df (float) new damping factor
151  */
152  void set_damping_factor(float df);
153 
154  /*!
155  * \brief Set the loop gain alpha.
156  *
157  * \details
158  * Sets the loop filter's alpha gain parameter.
159  *
160  * This value should really only be set by adjusting the loop
161  * bandwidth and damping factor.
162  *
163  * \param alpha (float) new alpha gain
164  */
165  void set_alpha(float alpha);
166 
167  /*!
168  * \brief Set the loop gain beta.
169  *
170  * \details
171  * Sets the loop filter's beta gain parameter.
172  *
173  * This value should really only be set by adjusting the loop
174  * bandwidth and damping factor.
175  *
176  * \param beta (float) new beta gain
177  */
178  void set_beta(float beta);
179 
180  /*!
181  * \brief Set the control loop's frequency.
182  *
183  * \details
184  * Sets the control loop's frequency. While this is normally
185  * updated by the inner loop of the algorithm, it could be
186  * useful to manually initialize, set, or reset this under
187  * certain circumstances.
188  *
189  * \param freq (float) new frequency
190  */
191  void set_frequency(float freq);
192 
193  /*!
194  * \brief Set the control loop's phase.
195  *
196  * \details
197  * Sets the control loop's phase. While this is normally
198  * updated by the inner loop of the algorithm, it could be
199  * useful to manually initialize, set, or reset this under
200  * certain circumstances.
201  *
202  * \param phase (float) new phase
203  */
204  void set_phase(float phase);
205 
206  /*!
207  * \brief Set the control loop's maximum frequency.
208  *
209  * \details
210  * Set the maximum frequency the control loop can track.
211  *
212  * \param freq (float) new max frequency
213  */
214  void set_max_freq(float freq);
215 
216  /*!
217  * \brief Set the control loop's minimum frequency.
218  *
219  * \details
220  * Set the minimum frequency the control loop can track.
221  *
222  * \param freq (float) new min frequency
223  */
224  void set_min_freq(float freq);
225 
226  /*******************************************************************
227  * GET FUNCTIONS
228  *******************************************************************/
229 
230  /*!
231  * \brief Returns the loop bandwidth.
232  */
233  float get_loop_bandwidth() const;
234 
235  /*!
236  * \brief Returns the loop damping factor.
237  */
238  float get_damping_factor() const;
239 
240  /*!
241  * \brief Returns the loop gain alpha.
242  */
243  float get_alpha() const;
244 
245  /*!
246  * \brief Returns the loop gain beta.
247  */
248  float get_beta() const;
249 
250  /*!
251  * \brief Get the control loop's frequency estimate.
252  */
253  float get_frequency() const;
254 
255  /*!
256  * \brief Get the control loop's phase estimate.
257  */
258  float get_phase() const;
259 
260  /*!
261  * \brief Get the control loop's maximum frequency.
262  */
263  float get_max_freq() const;
264 
265  /*!
266  * \brief Get the control loop's minimum frequency.
267  */
268  float get_min_freq() const;
269  };
270 
271  // This is a table of tanh(x) for x in [-2, 2] used in tanh_lut.
272  static float
273  tanh_lut_table[256] = { -0.96402758, -0.96290241, -0.96174273, -0.96054753, -0.95931576,
274  -0.95804636, -0.95673822, -0.95539023, -0.95400122, -0.95257001,
275  -0.95109539, -0.9495761 , -0.94801087, -0.94639839, -0.94473732,
276  -0.94302627, -0.94126385, -0.93944862, -0.93757908, -0.93565374,
277  -0.93367104, -0.93162941, -0.92952723, -0.92736284, -0.92513456,
278  -0.92284066, -0.92047938, -0.91804891, -0.91554743, -0.91297305,
279  -0.91032388, -0.90759795, -0.9047933 , -0.90190789, -0.89893968,
280  -0.89588656, -0.89274642, -0.88951709, -0.88619637, -0.88278203,
281  -0.87927182, -0.87566342, -0.87195453, -0.86814278, -0.86422579,
282  -0.86020115, -0.85606642, -0.85181914, -0.84745683, -0.84297699,
283  -0.83837709, -0.83365461, -0.82880699, -0.82383167, -0.81872609,
284  -0.81348767, -0.80811385, -0.80260204, -0.7969497 , -0.79115425,
285  -0.78521317, -0.77912392, -0.772884 , -0.76649093, -0.75994227,
286  -0.75323562, -0.74636859, -0.73933889, -0.73214422, -0.7247824 ,
287  -0.71725127, -0.70954876, -0.70167287, -0.6936217 , -0.68539341,
288  -0.67698629, -0.66839871, -0.65962916, -0.65067625, -0.64153871,
289  -0.6322154 , -0.62270534, -0.61300768, -0.60312171, -0.59304692,
290  -0.58278295, -0.57232959, -0.56168685, -0.55085493, -0.53983419,
291  -0.52862523, -0.51722883, -0.50564601, -0.49387799, -0.48192623,
292  -0.46979241, -0.45747844, -0.44498647, -0.4323189 , -0.41947836,
293  -0.40646773, -0.39329014, -0.37994896, -0.36644782, -0.35279057,
294  -0.33898135, -0.32502449, -0.31092459, -0.2966865 , -0.28231527,
295  -0.26781621, -0.25319481, -0.23845682, -0.22360817, -0.208655 ,
296  -0.19360362, -0.17846056, -0.16323249, -0.14792623, -0.13254879,
297  -0.11710727, -0.10160892, -0.08606109, -0.07047123, -0.05484686,
298  -0.0391956 , -0.02352507, -0.00784298, 0.00784298, 0.02352507,
299  0.0391956 , 0.05484686, 0.07047123, 0.08606109, 0.10160892,
300  0.11710727, 0.13254879, 0.14792623, 0.16323249, 0.17846056,
301  0.19360362, 0.208655 , 0.22360817, 0.23845682, 0.25319481,
302  0.26781621, 0.28231527, 0.2966865 , 0.31092459, 0.32502449,
303  0.33898135, 0.35279057, 0.36644782, 0.37994896, 0.39329014,
304  0.40646773, 0.41947836, 0.4323189 , 0.44498647, 0.45747844,
305  0.46979241, 0.48192623, 0.49387799, 0.50564601, 0.51722883,
306  0.52862523, 0.53983419, 0.55085493, 0.56168685, 0.57232959,
307  0.58278295, 0.59304692, 0.60312171, 0.61300768, 0.62270534,
308  0.6322154 , 0.64153871, 0.65067625, 0.65962916, 0.66839871,
309  0.67698629, 0.68539341, 0.6936217 , 0.70167287, 0.70954876,
310  0.71725127, 0.7247824 , 0.73214422, 0.73933889, 0.74636859,
311  0.75323562, 0.75994227, 0.76649093, 0.772884 , 0.77912392,
312  0.78521317, 0.79115425, 0.7969497 , 0.80260204, 0.80811385,
313  0.81348767, 0.81872609, 0.82383167, 0.82880699, 0.83365461,
314  0.83837709, 0.84297699, 0.84745683, 0.85181914, 0.85606642,
315  0.86020115, 0.86422579, 0.86814278, 0.87195453, 0.87566342,
316  0.87927182, 0.88278203, 0.88619637, 0.88951709, 0.89274642,
317  0.89588656, 0.89893968, 0.90190789, 0.9047933 , 0.90759795,
318  0.91032388, 0.91297305, 0.91554743, 0.91804891, 0.92047938,
319  0.92284066, 0.92513456, 0.92736284, 0.92952723, 0.93162941,
320  0.93367104, 0.93565374, 0.93757908, 0.93944862, 0.94126385,
321  0.94302627, 0.94473732, 0.94639839, 0.94801087, 0.9495761 ,
322  0.95109539, 0.95257001, 0.95400122, 0.95539023, 0.95673822,
323  0.95804636, 0.95931576, 0.96054753, 0.96174273, 0.96290241,
324  0.96402758 };
325 
326  /*!
327  * A look-up table (LUT) tanh calcuation. This function returns an
328  * estimate to tanh(x) based on a 256-point LUT between -2 and
329  * 2. If x < -2, it returns -1; if > 2, it retursn 1.
330  *
331  * This LUT form of the tanh is "hidden" in this code because it
332  * is likely too coarse an estimate for any real uses of a
333  * tanh. It is useful, however, in certain control loop
334  * applications where the input is expected to be within these
335  * bounds and the noise will be greater than the quanitzation of
336  * this small LUT. For more accurate forms of tanh, see
337  * volk_32f_tanh_32f.
338  */
339  static inline float
340  tanhf_lut(float x)
341  {
342  if(x > 2)
343  return 1;
344  else if(x <= -2)
345  return -1;
346  else {
347  int index = 128 + 64*x;
348  return tanh_lut_table[index];
349  }
350  }
351 
352  } /* namespace blocks */
353 } /* namespace gr */
354 
355 #endif /* GR_BLOCKS_CONTROL_LOOP */
static float tanhf_lut(float x)
Definition: control_loop.h:340
float d_loop_bw
Definition: control_loop.h:66
float d_beta
Definition: control_loop.h:67
Include this header to use the message passing features.
Definition: logger.h:131
#define BLOCKS_API
Definition: gr-blocks/include/gnuradio/blocks/api.h:30
static float tanh_lut_table[256]
Definition: control_loop.h:273
float d_phase
Definition: control_loop.h:64
A second-order control loop implementation class.
Definition: control_loop.h:61
float d_min_freq
Definition: control_loop.h:65
control_loop(void)
Definition: control_loop.h:70