GNU Radio C++ API Reference 3.10.12.0
The Free & Open Software Radio Ecosystem
Loading...
Searching...
No Matches
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 * Copyright 2025 Daniel Estevez <daniel@destevez.net>
5 *
6 * This file is part of GNU Radio
7 *
8 * SPDX-License-Identifier: GPL-3.0-or-later
9 *
10 */
11
12#ifndef INCLUDED_DIGITAL_FLL_BAND_EDGE_CC_H
13#define INCLUDED_DIGITAL_FLL_BAND_EDGE_CC_H
14
17#include <gnuradio/sync_block.h>
18
19namespace gr {
20namespace digital {
21
22/*!
23 * \brief Frequency Lock Loop using band-edge filters
24 * \ingroup synchronizers_blk
25 *
26 * \details
27 * The frequency lock loop derives a band-edge filter that covers
28 * the upper and lower bandwidths of a digitally-modulated
29 * signal. The bandwidth range is determined by the excess
30 * bandwidth (e.g., rolloff factor) of the modulated signal. The
31 * placement in frequency of the band-edges is determined by the
32 * oversampling ratio (number of samples per symbol) and the
33 * excess bandwidth. The size of the filters should be fairly
34 * large so as to average over a number of symbols.
35 *
36 * The FLL works by filtering the upper and lower band edges into
37 * x_u(t) and x_l(t), respectively. These are combined to form
38 * cc(t) = x_u(t) + x_l(t) and ss(t) = x_u(t) - x_l(t). Combining
39 * these to form the signal e(t) = Re{cc(t) \\times ss(t)^*}
40 * (where ^* is the complex conjugate) provides an error signal at
41 * the DC term that is directly proportional to the carrier
42 * frequency. We then make a second-order loop using the error
43 * signal that is the running average of e(t).
44 *
45 * In practice, the above equation can be simplified by just
46 * comparing the absolute value squared of the output of both
47 * filters: abs(x_l(t))^2 - abs(x_u(t))^2 = norm(x_l(t)) -
48 * norm(x_u(t)).
49 *
50 * In theory, the band-edge filter is the derivative of the
51 * matched filter in frequency, (H_be(f) = frac{H(f)}{df}). In
52 * practice, this comes down to a quarter sine wave at the point
53 * of the matched filter's rolloff (if it's a raised-cosine, the
54 * derivative of a cosine is a sine). Extend this sine by another
55 * quarter wave to make a half wave around the band-edges is
56 * equivalent in time to the sum of two sinc functions. The
57 * baseband filter for the band edges is therefore derived from
58 * this sum of sincs. The band edge filters are then just the
59 * baseband signal modulated to the correct place in
60 * frequency. All of these calculations are done in the
61 * 'design_filter' function.
62 *
63 * Note: We use FIR filters here because the filters have to have
64 * a flat phase response over the entire frequency range to allow
65 * their comparisons to be valid.
66 *
67 * It is very important that the band edge filters be the
68 * derivatives of the pulse shaping filter, and that they be
69 * linear phase. Otherwise, the variance of the error will be very
70 * large.
71 */
73 virtual public blocks::control_loop
74{
75public:
76 // gr::digital::fll_band_edge_cc::sptr
77 typedef std::shared_ptr<fll_band_edge_cc> sptr;
78
79 /*!
80 * Make an FLL block.
81 *
82 * \param samps_per_sym (float) number of samples per symbol
83 * \param rolloff (float) Rolloff (excess bandwidth) of signal filter
84 * \param filter_size (int) number of filter taps to generate
85 * \param bandwidth (float) Loop bandwidth. If improved_loop_filter is true, then
86 * this paramter is BL*T, where BL is the loop noise bandwidth in Hz, and
87 * T is the sampling period in seconds.
88 * \param improved_loop_filter (bool) Improved loop filter. If true, the
89 * loop filter is implemented correctly, but the loop bandwidth parameter is
90 * not backwards compatible. If false, the legacy behavior is maintained.
91 */
92 static sptr make(float samps_per_sym,
93 float rolloff,
94 int filter_size,
95 float bandwidth,
96 bool improved_loop_filter = false);
97
98 /*******************************************************************
99 SET FUNCTIONS
100 *******************************************************************/
101
102 /*!
103 * \brief Set the number of samples per symbol
104 *
105 * Set's the number of samples per symbol the system should
106 * use. This value is used to calculate the filter taps and will
107 * force a recalculation.
108 *
109 * \param sps (float) new samples per symbol
110 */
111 virtual void set_samples_per_symbol(float sps) = 0;
112
113 /*!
114 * \brief Set the rolloff factor of the shaping filter
115 *
116 * This sets the rolloff factor that is used in the pulse
117 * shaping filter and is used to calculate the filter
118 * taps. Changing this will force a recalculation of the filter
119 * taps.
120 *
121 * This should be the same value that is used in the
122 * transmitter's pulse shaping filter. It must be between 0 and
123 * 1 and is usually between 0.2 and 0.5 (where 0.22 and 0.35 are
124 * commonly used values).
125 *
126 * \param rolloff (float) new shaping filter rolloff factor [0,1]
127 */
128 virtual void set_rolloff(float rolloff) = 0;
129
130 /*!
131 * \brief Set the number of taps in the filter
132 *
133 * This sets the number of taps in the band-edge
134 * filters. Setting this will force a recalculation of the
135 * filter taps.
136 *
137 * This should be about the same number of taps used in the
138 * transmitter's shaping filter and also not very large. A large
139 * number of taps will result in a large delay between input and
140 * frequency estimation, and so will not be as accurate. Between
141 * 30 and 70 taps is usual.
142 *
143 * \param filter_size (float) number of taps in the filters
144 */
145 virtual void set_filter_size(int filter_size) = 0;
146
147 /*******************************************************************
148 GET FUNCTIONS
149 *******************************************************************/
150
151 /*!
152 * \brief Returns the number of sampler per symbol used for the filter
153 */
154 virtual float samples_per_symbol() const = 0;
155
156 /*!
157 * \brief Returns the rolloff factor used for the filter
158 */
159 virtual float rolloff() const = 0;
160
161 /*!
162 * \brief Returns the number of taps of the filter
163 */
164 virtual int filter_size() const = 0;
165
166 /*!
167 * Print the taps to screen.
168 */
169 virtual void print_taps() = 0;
170};
171
172} /* namespace digital */
173} /* namespace gr */
174
175#endif /* INCLUDED_DIGITAL_FLL_BAND_EDGE_CC_H */
A second-order control loop implementation class.
Definition control_loop.h:51
Frequency Lock Loop using band-edge filters.
Definition fll_band_edge_cc.h:74
virtual void set_filter_size(int filter_size)=0
Set the number of taps in the filter.
virtual int filter_size() const =0
Returns the number of taps of the filter.
virtual void set_rolloff(float rolloff)=0
Set the rolloff factor of the shaping filter.
static sptr make(float samps_per_sym, float rolloff, int filter_size, float bandwidth, bool improved_loop_filter=false)
virtual void set_samples_per_symbol(float sps)=0
Set the number of samples per symbol.
virtual float samples_per_symbol() const =0
Returns the number of sampler per symbol used for the filter.
virtual float rolloff() const =0
Returns the rolloff factor used for the filter.
std::shared_ptr< fll_band_edge_cc > sptr
Definition fll_band_edge_cc.h:77
sync_block(void)
Definition sync_block.h:28
#define DIGITAL_API
Definition gr-digital/include/gnuradio/digital/api.h:18
Definition adaptive_algorithm.h:22
GNU Radio logging wrapper.
Definition basic_block.h:29