GNU Radio 3.6.4.1 C++ API
digital_fll_band_edge_cc.h
Go to the documentation of this file.
1 /* -*- c++ -*- */
2 /*
3  * Copyright 2009,2011,2012 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 
24 #ifndef INCLUDED_DIGITAL_FLL_BAND_EDGE_CC_H
25 #define INCLUDED_DIGITAL_FLL_BAND_EDGE_CC_H
26 
27 #include <digital_api.h>
28 #include <gr_sync_block.h>
29 #include <gri_control_loop.h>
30 #include <gr_fir_util.h>
31 #include <gr_fir_ccc.h>
32 
33 typedef gr_fir_ccc* (*fir_maker_t)(const std::vector<gr_complex> &taps);
34 typedef gr_fir_ccc filter_t;
35 
39 digital_make_fll_band_edge_cc(float samps_per_sym,
40  float rolloff,
41  int filter_size,
42  float bandwidth);
43 
44 /*!
45  * \class digital_fll_band_edge_cc
46  * \brief Frequency Lock Loop using band-edge filters
47  *
48  * \ingroup general
49  * \ingroup digital
50  *
51  * The frequency lock loop derives a band-edge filter that covers the
52  * upper and lower bandwidths of a digitally-modulated signal. The
53  * bandwidth range is determined by the excess bandwidth (e.g.,
54  * rolloff factor) of the modulated signal. The placement in frequency
55  * of the band-edges is determined by the oversampling ratio (number
56  * of samples per symbol) and the excess bandwidth. The size of the
57  * filters should be fairly large so as to average over a number of
58  * symbols.
59  *
60  * The FLL works by filtering the upper and lower band edges into
61  * x_u(t) and x_l(t), respectively. These are combined to form cc(t)
62  * = x_u(t) + x_l(t) and ss(t) = x_u(t) - x_l(t). Combining these to
63  * form the signal e(t) = Re{cc(t) \\times ss(t)^*} (where ^* is the
64  * complex conjugate) provides an error signal at the DC term that is
65  * directly proportional to the carrier frequency. We then make a
66  * second-order loop using the error signal that is the running
67  * average of e(t).
68  *
69  * In practice, the above equation can be simplified by just comparing
70  * the absolute value squared of the output of both filters:
71  * abs(x_l(t))^2 - abs(x_u(t))^2 = norm(x_l(t)) - norm(x_u(t)).
72  *
73  * In theory, the band-edge filter is the derivative of the matched
74  * filter in frequency, (H_be(f) = frac{H(f)}{df}). In practice,
75  * this comes down to a quarter sine wave at the point of the matched
76  * filter's rolloff (if it's a raised-cosine, the derivative of a
77  * cosine is a sine). Extend this sine by another quarter wave to
78  * make a half wave around the band-edges is equivalent in time to the
79  * sum of two sinc functions. The baseband filter fot the band edges
80  * is therefore derived from this sum of sincs. The band edge filters
81  * are then just the baseband signal modulated to the correct place in
82  * frequency. All of these calculations are done in the
83  * 'design_filter' function.
84  *
85  * Note: We use FIR filters here because the filters have to have a
86  * flat phase response over the entire frequency range to allow their
87  * comparisons to be valid.
88  *
89  * It is very important that the band edge filters be the derivatives
90  * of the pulse shaping filter, and that they be linear
91  * phase. Otherwise, the variance of the error will be very large.
92  *
93  */
94 
96  public gr_sync_block, public gri_control_loop
97 {
98  private:
99  /*!
100  * Build the FLL
101  * \param samps_per_sym (float) Number of samples per symbol of signal
102  * \param rolloff (float) Rolloff factor of signal
103  * \param filter_size (int) Size (in taps) of the filter
104  * \param bandwidth (float) Loop bandwidth
105  */
107  digital_make_fll_band_edge_cc(float samps_per_sym,
108  float rolloff,
109  int filter_size,
110  float bandwidth);
111 
112  float d_sps;
113  float d_rolloff;
114  int d_filter_size;
115 
116  std::vector<gr_complex> d_taps_lower;
117  std::vector<gr_complex> d_taps_upper;
118  bool d_updated;
119  filter_t* d_filter_lower;
120  filter_t* d_filter_upper;
121  std::vector<gr_complex> d_output_hist;
122  std::vector<gr_complex> d_fllbuffer;
123 
124  /*!
125  * Build the FLL
126  * \param samps_per_sym (float) number of samples per symbol
127  * \param rolloff (float) Rolloff (excess bandwidth) of signal filter
128  * \param filter_size (int) number of filter taps to generate
129  * \param bandwidth (float) Loop bandwidth
130  */
131  digital_fll_band_edge_cc(float samps_per_sym, float rolloff,
132  int filter_size, float bandwidth);
133 
134  /*!
135  * Design the band-edge filter based on the number of samples per symbol,
136  * filter rolloff factor, and the filter size
137  *
138  * \param samps_per_sym (float) Number of samples per symbol of signal
139  * \param rolloff (float) Rolloff factor of signal
140  * \param filter_size (int) Size (in taps) of the filter
141  */
142  void design_filter(float samps_per_sym, float rolloff, int filter_size);
143 
144 public:
146 
147  /*******************************************************************
148  SET FUNCTIONS
149  *******************************************************************/
150 
151  /*!
152  * \brief Set the number of samples per symbol
153  *
154  * Set's the number of samples per symbol the system should
155  * use. This value is uesd to calculate the filter taps and will
156  * force a recalculation.
157  *
158  * \param sps (float) new samples per symbol
159  *
160  */
161  void set_samples_per_symbol(float sps);
162 
163  /*!
164  * \brief Set the rolloff factor of the shaping filter
165  *
166  * This sets the rolloff factor that is used in the pulse shaping
167  * filter and is used to calculate the filter taps. Changing this
168  * will force a recalculation of the filter taps.
169  *
170  * This should be the same value that is used in the transmitter's
171  * pulse shaping filter. It must be between 0 and 1 and is usually
172  * between 0.2 and 0.5 (where 0.22 and 0.35 are commonly used
173  * values).
174  *
175  * \param rolloff (float) new shaping filter rolloff factor [0,1]
176  *
177  */
178  void set_rolloff(float rolloff);
179 
180  /*!
181  * \brief Set the number of taps in the filter
182  *
183  * This sets the number of taps in the band-edge filters. Setting
184  * this will force a recalculation of the filter taps.
185  *
186  * This should be about the same number of taps used in the
187  * transmitter's shaping filter and also not very large. A large
188  * number of taps will result in a large delay between input and
189  * frequency estimation, and so will not be as accurate. Between 30
190  * and 70 taps is usual.
191  *
192  * \param filter_size (float) number of taps in the filters
193  *
194  */
195  void set_filter_size(int filter_size);
196 
197  /*******************************************************************
198  GET FUNCTIONS
199  *******************************************************************/
200 
201  /*!
202  * \brief Returns the number of sampler per symbol used for the filter
203  */
204  float get_samples_per_symbol() const;
205 
206  /*!
207  * \brief Returns the rolloff factor used for the filter
208  */
209  float get_rolloff() const;
210 
211  /*!
212  * \brief Returns the number of taps of the filter
213  */
214  int get_filter_size() const;
215 
216  /*!
217  * Print the taps to screen.
218  */
219  void print_taps();
220 
221  int work(int noutput_items,
222  gr_vector_const_void_star &input_items,
223  gr_vector_void_star &output_items);
224 };
225 
226 #endif