GNU Radio 3.4.2 C++ API
|
Frequency Lock Loop using band-edge filters. More...
#include <gr_fll_band_edge_cc.h>
Public Member Functions | |
~gr_fll_band_edge_cc () | |
void | design_filter (float samps_per_sym, float rolloff, int filter_size) |
void | set_alpha (float alpha) |
void | set_beta (float beta) |
void | print_taps () |
int | work (int noutput_items, gr_vector_const_void_star &input_items, gr_vector_void_star &output_items) |
just like gr_block::general_work, only this arranges to call consume_each for you | |
Friends | |
gr_fll_band_edge_cc_sptr | gr_make_fll_band_edge_cc (float samps_per_sym, float rolloff, int filter_size, float alpha, float beta) |
Frequency Lock Loop using band-edge filters.
The frequency lock loop derives a band-edge filter that covers the upper and lower bandwidths of a digitally-modulated signal. The bandwidth range is determined by the excess bandwidth (e.g., rolloff factor) of the modulated signal. The placement in frequency of the band-edges is determined by the oversampling ratio (number of samples per symbol) and the excess bandwidth. The size of the filters should be fairly large so as to average over a number of symbols.
The FLL works by filtering the upper and lower band edges into x_u(t) and x_l(t), respectively. These are combined to form cc(t) = x_u(t) + x_l(t) and ss(t) = x_u(t) - x_l(t). Combining these to form the signal e(t) = Re{cc(t) \times ss(t)^*} (where ^* is the complex conjugate) provides an error signal at the DC term that is directly proportional to the carrier frequency. We then make a second-order loop using the error signal that is the running average of e(t).
In theory, the band-edge filter is the derivative of the matched filter in frequency, (H_be(f) = \frac{H(f)}{df}. In practice, this comes down to a quarter sine wave at the point of the matched filter's rolloff (if it's a raised-cosine, the derivative of a cosine is a sine). Extend this sine by another quarter wave to make a half wave around the band-edges is equivalent in time to the sum of two sinc functions. The baseband filter fot the band edges is therefore derived from this sum of sincs. The band edge filters are then just the baseband signal modulated to the correct place in frequency. All of these calculations are done in the 'design_filter' function.
Note: We use FIR filters here because the filters have to have a flat phase response over the entire frequency range to allow their comparisons to be valid.
gr_fll_band_edge_cc::~gr_fll_band_edge_cc | ( | ) |
void gr_fll_band_edge_cc::design_filter | ( | float | samps_per_sym, |
float | rolloff, | ||
int | filter_size | ||
) |
Design the band-edge filter based on the number of samples per symbol, filter rolloff factor, and the filter size
samps_per_sym | (float) Number of samples per symbol of signal |
rolloff | (float) Rolloff factor of signal |
filter_size | (int) Size (in taps) of the filter |
void gr_fll_band_edge_cc::print_taps | ( | ) |
Print the taps to screen.
void gr_fll_band_edge_cc::set_alpha | ( | float | alpha | ) |
Set the alpha gainvalue
alpha | (float) new gain value |
void gr_fll_band_edge_cc::set_beta | ( | float | beta | ) | [inline] |
Set the beta gain value
beta | (float) new gain value |
int gr_fll_band_edge_cc::work | ( | int | noutput_items, |
gr_vector_const_void_star & | input_items, | ||
gr_vector_void_star & | output_items | ||
) | [virtual] |
just like gr_block::general_work, only this arranges to call consume_each for you
The user must override work to define the signal processing code
Implements gr_sync_block.
gr_fll_band_edge_cc_sptr gr_make_fll_band_edge_cc | ( | float | samps_per_sym, |
float | rolloff, | ||
int | filter_size, | ||
float | alpha, | ||
float | beta | ||
) | [friend] |
Build the FLL
samps_per_sym | (float) Number of samples per symbol of signal |
rolloff | (float) Rolloff factor of signal |
filter_size | (int) Size (in taps) of the filter |
alpha | (float) Loop gain 1 |
beta | (float) Loop gain 2 |