GNU Radio 3.5.1 C++ API
|
00001 /* -*- c++ -*- */ 00002 /* 00003 * Copyright 2009,2011 Free Software Foundation, Inc. 00004 * 00005 * This file is part of GNU Radio 00006 * 00007 * GNU Radio is free software; you can redistribute it and/or modify 00008 * it under the terms of the GNU General Public License as published by 00009 * the Free Software Foundation; either version 3, or (at your option) 00010 * any later version. 00011 * 00012 * GNU Radio is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 * GNU General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU General Public License 00018 * along with GNU Radio; see the file COPYING. If not, write to 00019 * the Free Software Foundation, Inc., 51 Franklin Street, 00020 * Boston, MA 02110-1301, USA. 00021 */ 00022 00023 00024 #ifndef INCLUDED_DIGITAL_FLL_BAND_EDGE_CC_H 00025 #define INCLUDED_DIGITAL_FLL_BAND_EDGE_CC_H 00026 00027 #include <digital_api.h> 00028 #include <gr_sync_block.h> 00029 #include <gri_control_loop.h> 00030 00031 class digital_fll_band_edge_cc; 00032 typedef boost::shared_ptr<digital_fll_band_edge_cc> digital_fll_band_edge_cc_sptr; 00033 DIGITAL_API digital_fll_band_edge_cc_sptr digital_make_fll_band_edge_cc (float samps_per_sym, 00034 float rolloff, 00035 int filter_size, 00036 float bandwidth); 00037 00038 /*! 00039 * \class digital_fll_band_edge_cc 00040 * \brief Frequency Lock Loop using band-edge filters 00041 * 00042 * \ingroup general 00043 * \ingroup digital 00044 * 00045 * The frequency lock loop derives a band-edge filter that covers the 00046 * upper and lower bandwidths of a digitally-modulated signal. The 00047 * bandwidth range is determined by the excess bandwidth (e.g., 00048 * rolloff factor) of the modulated signal. The placement in frequency 00049 * of the band-edges is determined by the oversampling ratio (number 00050 * of samples per symbol) and the excess bandwidth. The size of the 00051 * filters should be fairly large so as to average over a number of 00052 * symbols. 00053 * 00054 * The FLL works by filtering the upper and lower band edges into 00055 * x_u(t) and x_l(t), respectively. These are combined to form cc(t) 00056 * = x_u(t) + x_l(t) and ss(t) = x_u(t) - x_l(t). Combining these to 00057 * form the signal e(t) = Re{cc(t) \\times ss(t)^*} (where ^* is the 00058 * complex conjugate) provides an error signal at the DC term that is 00059 * directly proportional to the carrier frequency. We then make a 00060 * second-order loop using the error signal that is the running 00061 * average of e(t). 00062 * 00063 * In practice, the above equation can be simplified by just comparing 00064 * the absolute value squared of the output of both filters: 00065 * abs(x_l(t))^2 - abs(x_u(t))^2 = norm(x_l(t)) - norm(x_u(t)). 00066 * 00067 * In theory, the band-edge filter is the derivative of the matched 00068 * filter in frequency, (H_be(f) = \\frac{H(f)}{df}. In practice, this 00069 * comes down to a quarter sine wave at the point of the matched 00070 * filter's rolloff (if it's a raised-cosine, the derivative of a 00071 * cosine is a sine). Extend this sine by another quarter wave to 00072 * make a half wave around the band-edges is equivalent in time to the 00073 * sum of two sinc functions. The baseband filter fot the band edges 00074 * is therefore derived from this sum of sincs. The band edge filters 00075 * are then just the baseband signal modulated to the correct place in 00076 * frequency. All of these calculations are done in the 00077 * 'design_filter' function. 00078 * 00079 * Note: We use FIR filters here because the filters have to have a 00080 * flat phase response over the entire frequency range to allow their 00081 * comparisons to be valid. 00082 * 00083 * It is very important that the band edge filters be the derivatives 00084 * of the pulse shaping filter, and that they be linear 00085 * phase. Otherwise, the variance of the error will be very large. 00086 * 00087 */ 00088 00089 class DIGITAL_API digital_fll_band_edge_cc : public gr_sync_block, public gri_control_loop 00090 { 00091 private: 00092 /*! 00093 * Build the FLL 00094 * \param samps_per_sym (float) Number of samples per symbol of signal 00095 * \param rolloff (float) Rolloff factor of signal 00096 * \param filter_size (int) Size (in taps) of the filter 00097 * \param bandwidth (float) Loop bandwidth 00098 */ 00099 friend DIGITAL_API digital_fll_band_edge_cc_sptr digital_make_fll_band_edge_cc (float samps_per_sym, 00100 float rolloff, 00101 int filter_size, 00102 float bandwidth); 00103 00104 float d_sps; 00105 float d_rolloff; 00106 int d_filter_size; 00107 00108 std::vector<gr_complex> d_taps_lower; 00109 std::vector<gr_complex> d_taps_upper; 00110 bool d_updated; 00111 00112 /*! 00113 * Build the FLL 00114 * \param samps_per_sym (float) number of samples per symbol 00115 * \param rolloff (float) Rolloff (excess bandwidth) of signal filter 00116 * \param filter_size (int) number of filter taps to generate 00117 * \param bandwidth (float) Loop bandwidth 00118 */ 00119 digital_fll_band_edge_cc(float samps_per_sym, float rolloff, 00120 int filter_size, float bandwidth); 00121 00122 /*! 00123 * Design the band-edge filter based on the number of samples per symbol, 00124 * filter rolloff factor, and the filter size 00125 * 00126 * \param samps_per_sym (float) Number of samples per symbol of signal 00127 * \param rolloff (float) Rolloff factor of signal 00128 * \param filter_size (int) Size (in taps) of the filter 00129 */ 00130 void design_filter(float samps_per_sym, float rolloff, int filter_size); 00131 00132 public: 00133 ~digital_fll_band_edge_cc (); 00134 00135 /******************************************************************* 00136 SET FUNCTIONS 00137 *******************************************************************/ 00138 00139 /*! 00140 * \brief Set the number of samples per symbol 00141 * 00142 * Set's the number of samples per symbol the system should 00143 * use. This value is uesd to calculate the filter taps and will 00144 * force a recalculation. 00145 * 00146 * \param sps (float) new samples per symbol 00147 * 00148 */ 00149 void set_samples_per_symbol(float sps); 00150 00151 /*! 00152 * \brief Set the rolloff factor of the shaping filter 00153 * 00154 * This sets the rolloff factor that is used in the pulse shaping 00155 * filter and is used to calculate the filter taps. Changing this 00156 * will force a recalculation of the filter taps. 00157 * 00158 * This should be the same value that is used in the transmitter's 00159 * pulse shaping filter. It must be between 0 and 1 and is usually 00160 * between 0.2 and 0.5 (where 0.22 and 0.35 are commonly used 00161 * values). 00162 * 00163 * \param rolloff (float) new shaping filter rolloff factor [0,1] 00164 * 00165 */ 00166 void set_rolloff(float rolloff); 00167 00168 /*! 00169 * \brief Set the number of taps in the filter 00170 * 00171 * This sets the number of taps in the band-edge filters. Setting 00172 * this will force a recalculation of the filter taps. 00173 * 00174 * This should be about the same number of taps used in the 00175 * transmitter's shaping filter and also not very large. A large 00176 * number of taps will result in a large delay between input and 00177 * frequency estimation, and so will not be as accurate. Between 30 00178 * and 70 taps is usual. 00179 * 00180 * \param filter_size (float) number of taps in the filters 00181 * 00182 */ 00183 void set_filter_size(int filter_size); 00184 00185 /******************************************************************* 00186 GET FUNCTIONS 00187 *******************************************************************/ 00188 00189 /*! 00190 * \brief Returns the number of sampler per symbol used for the filter 00191 */ 00192 float get_samples_per_symbol() const; 00193 00194 /*! 00195 * \brief Returns the rolloff factor used for the filter 00196 */ 00197 float get_rolloff() const; 00198 00199 /*! 00200 * \brief Returns the number of taps of the filter 00201 */ 00202 int get_filter_size() const; 00203 00204 /*! 00205 * Print the taps to screen. 00206 */ 00207 void print_taps(); 00208 00209 int work (int noutput_items, 00210 gr_vector_const_void_star &input_items, 00211 gr_vector_void_star &output_items); 00212 }; 00213 00214 #endif