Generating the band-edge filter taps based on the oversampling ratio (samples per...
authorTom <trondeau@vt.edu>
Wed, 16 Dec 2009 01:23:18 +0000 (20:23 -0500)
committerTom <trondeau@vt.edu>
Wed, 16 Dec 2009 01:23:18 +0000 (20:23 -0500)
gnuradio-core/src/lib/general/gr_fll_band_edge_cc.cc
gnuradio-core/src/lib/general/gr_fll_band_edge_cc.h
gnuradio-core/src/lib/general/gr_fll_band_edge_cc.i
grc/blocks/gr_fll_band_edge_cc.xml

index 156ad278a28529e2085e3da4370dbd30d504f44b..0f3d85c83f5e2936ed5b097ec1c57cc3194c43a3 100644 (file)
 
 #define M_TWOPI (2*M_PI)
 
-gr_fll_band_edge_cc_sptr gr_make_fll_band_edge_cc (float alpha, float beta,
-                                                  const std::vector<gr_complex> &taps)
+float sinc(float x)
 {
-  return gr_fll_band_edge_cc_sptr (new gr_fll_band_edge_cc (alpha, beta,
-                                                           taps));
+  if(x == 0)
+    return 1;
+  else
+    return sin(M_PI*x)/(M_PI*x);
 }
+  
 
 
-gr_fll_band_edge_cc::gr_fll_band_edge_cc (float alpha, float beta,
-                                         const std::vector<gr_complex> &taps)
+gr_fll_band_edge_cc_sptr gr_make_fll_band_edge_cc (float samps_per_sym, float rolloff,
+                                                  int filter_size, float gain_alpha, float gain_beta)
+{
+  return gr_fll_band_edge_cc_sptr (new gr_fll_band_edge_cc (samps_per_sym, rolloff,
+                                                           filter_size, gain_alpha, gain_beta));
+}
+
+
+gr_fll_band_edge_cc::gr_fll_band_edge_cc (float samps_per_sym, float rolloff,
+                                         int filter_size, float alpha, float beta)
   : gr_sync_block ("fll_band_edge_cc",
                   gr_make_io_signature (1, 1, sizeof(gr_complex)),
                   gr_make_io_signature (1, 1, sizeof(gr_complex))),
     d_alpha(alpha), d_beta(beta), d_updated (false)
 {
   // base this on the number of samples per symbol
-  d_max_freq = M_TWOPI * 0.25;
-  d_min_freq = M_TWOPI * -0.5;
+  d_max_freq =  M_TWOPI * (2.0/samps_per_sym);
+  d_min_freq = -M_TWOPI * (2.0/samps_per_sym);
 
   d_freq = 0;
   d_phase = 0;
 
-  std::vector<gr_complex> vtaps(0, taps.size());
+  int M = rint(filter_size / samps_per_sym);
+  float power = 0;
+  std::vector<float> bb_taps;
+  for(int i = 0; i < filter_size; i++) {
+    float k = -M + i*2.0/samps_per_sym;
+    float tap = sinc(rolloff*k - 0.5) + sinc(rolloff*k + 0.5);
+    power += tap;
+
+    bb_taps.push_back(tap);
+  }
+
+  int N = (bb_taps.size() - 1.0)/2.0;
+  std::vector<gr_complex> taps_lower;
+  std::vector<gr_complex> taps_upper;
+  for(int i = 0; i < bb_taps.size(); i++) {
+    float tap = bb_taps[i] / power;
+
+    float k = (-N + i)/(2.0*samps_per_sym);     //rng = scipy.arange(-nn2, nn2+1) / (2*spb);
+
+    gr_complex t1 = tap * gr_expj(-2*M_PI*(1+rolloff)*k);
+    gr_complex t2 = tap * gr_expj(2*M_PI*(1+rolloff)*k);
+
+    taps_lower.push_back(t1);
+    taps_upper.push_back(t2);
+  }
+
+  std::vector<gr_complex> vtaps(0, taps_lower.size());
   d_filter_upper = gr_fir_util::create_gr_fir_ccc(vtaps);
   d_filter_lower = gr_fir_util::create_gr_fir_ccc(vtaps);
 
-  set_taps(taps);
+  set_taps_lower(taps_lower);
+  set_taps_upper(taps_upper);
 }
 
 gr_fll_band_edge_cc::~gr_fll_band_edge_cc ()
@@ -69,17 +106,32 @@ gr_fll_band_edge_cc::~gr_fll_band_edge_cc ()
 }
 
 void
-gr_fll_band_edge_cc::set_taps (const std::vector<gr_complex> &taps)
+gr_fll_band_edge_cc::set_taps_lower (const std::vector<gr_complex> &taps)
+{
+  unsigned int i;
+
+  for(i = 0; i < taps.size(); i++) {
+    d_taps_lower.push_back(taps[i]);
+  }
+
+  d_filter_lower->set_taps(d_taps_lower);
+
+  // Set the history to ensure enough input items for each filter
+  set_history(d_taps_lower.size()+1);
+
+  d_updated = true;
+}
+
+void
+gr_fll_band_edge_cc::set_taps_upper (const std::vector<gr_complex> &taps)
 {
   unsigned int i;
 
   for(i = 0; i < taps.size(); i++) {
     d_taps_upper.push_back(taps[i]);
-    d_taps_lower.push_back(conj(taps[i]));
   }
 
   d_filter_upper->set_taps(d_taps_upper);
-  d_filter_lower->set_taps(d_taps_lower);
 
   // Set the history to ensure enough input items for each filter
   set_history(d_taps_upper.size()+1);
@@ -93,13 +145,13 @@ gr_fll_band_edge_cc::print_taps()
   unsigned int i;
   printf("Upper Band-edge: [");
   for(i = 0; i < d_taps_upper.size(); i++) {
-    printf(" %.4e + j%.4e,", d_taps_upper[i].real(), d_taps_upper[i].imag());
+    printf(" %.4e + %.4ej,", d_taps_upper[i].real(), d_taps_upper[i].imag());
   }
   printf("]\n\n");
 
   printf("Lower Band-edge: [");
   for(i = 0; i < d_taps_lower.size(); i++) {
-    printf(" %.4e + j%.4e,", d_taps_lower[i].real(), d_taps_lower[i].imag());
+    printf(" %.4e + %.4ej,", d_taps_lower[i].real(), d_taps_lower[i].imag());
   }
   printf("]\n\n");
 }
@@ -128,9 +180,10 @@ gr_fll_band_edge_cc::work (int noutput_items,
     out_upper = norm(d_filter_upper->filter(&out[i]));
     out_lower = norm(d_filter_lower->filter(&out[i]));
     error = out_lower - out_upper;
+    d_error = 0.1*error + 0.9*d_error;  // average error
 
     d_freq = d_freq + d_beta * error;
-    d_phase = d_phase + d_freq; // + d_alpha * error;
+    d_phase = d_phase + d_freq + d_alpha * error;
 
     if(d_phase > M_PI)
       d_phase -= M_TWOPI;
index feb5e0a77dd677366dfdb556f7534e233ba2d19d..86e69df16305f76f031c668e8db0b4446e5a0d9f 100644 (file)
@@ -28,8 +28,8 @@
 
 class gr_fll_band_edge_cc;
 typedef boost::shared_ptr<gr_fll_band_edge_cc> gr_fll_band_edge_cc_sptr;
-gr_fll_band_edge_cc_sptr gr_make_fll_band_edge_cc (float alpha, float beta,
-                                                  const std::vector<gr_complex> &taps);
+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);
 
 class gr_fir_ccc;
 class gri_fft_complex;
@@ -48,8 +48,8 @@ class gr_fll_band_edge_cc : public gr_sync_block
    * Build the FLL
    * \param taps    (vector/list of gr_complex) The taps of the band-edge filter
    */
-  friend gr_fll_band_edge_cc_sptr gr_make_fll_band_edge_cc (float alpha, float beta,
-                                                           const std::vector<gr_complex> &taps);
+  friend 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);
 
   float                   d_alpha;
   float                   d_beta;
@@ -61,6 +61,7 @@ class gr_fll_band_edge_cc : public gr_sync_block
   std::vector<gr_complex> d_taps_upper;
   std::vector<gr_complex> d_taps_lower;
   bool                   d_updated;
+  float                   d_error;
   float                   d_freq;
   float                   d_phase;
 
@@ -68,8 +69,8 @@ class gr_fll_band_edge_cc : public gr_sync_block
    * Build the FLL
    * \param taps    (vector/list of gr_complex) The taps of the band-edge filter
    */
-  gr_fll_band_edge_cc(float alpha, float beta,
-                     const std::vector<gr_complex> &taps);
+  gr_fll_band_edge_cc(float samps_per_sym, float rolloff,
+                     int filter_size, float alpha, float beta);
 
 public:
   ~gr_fll_band_edge_cc ();
@@ -78,7 +79,8 @@ public:
    * Resets the filter taps with the new prototype filter
    * \param taps    (vector/list of gr_complex) The band-edge filter
    */
-  void set_taps (const std::vector<gr_complex> &taps);
+  void set_taps_lower (const std::vector<gr_complex> &taps);
+  void set_taps_upper (const std::vector<gr_complex> &taps);
 
   /*!
    * Set the alpha gainvalue
index 13714951b193e08fd8b2e5a91f1fef39341ca629..545bad4f61c28b6b92257786867aabbfd937fa3c 100644 (file)
 
 GR_SWIG_BLOCK_MAGIC(gr,fll_band_edge_cc);
 
-gr_fll_band_edge_cc_sptr gr_make_fll_band_edge_cc (float alpha, float beta,
-                                                  const std::vector<gr_complex> &taps);
+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);
 
 class gr_fll_band_edge_cc : public gr_sync_block
 {
  private:
-  gr_fll_band_edge_cc (float alpha, float beta,
-                      const std::vector<gr_complex> &taps);
+  gr_fll_band_edge_cc (float samps_per_sym, float rolloff,
+                      int filter_size, float alpha, float beta);
 
  public:
   ~gr_fll_band_edge_cc ();
 
-  void set_taps (const std::vector<gr_complex> &taps);
   void set_alpha (float alpha);
   void set_beta (float beta);
+  void print_taps();
 };
index 61dc378a9d028c4aad38e7c8a5f04570dce8eca3..41c760cbb2c31fad9a25bcdfa9182a099283a17a 100644 (file)
@@ -8,8 +8,7 @@
        <name>FLL Band-Edge</name>
        <key>gr_fll_band_edge_cc</key>
        <import>from gnuradio import gr</import>
-       <make>gr.fll_band_edge_cc($alpha, $beta, $taps)</make>
-       <callback>set_taps($taps)</callback>
+       <make>gr.fll_band_edge_cc($samps_per_sym, $rolloff, $filter_size, $alpha, $beta)</make>
        <callback>set_alpha($alpha)</callback>
        <callback>set_beta($beta)</callback>
 
                        <key>cc</key>
                        <opt>input:complex</opt>
                        <opt>output:complex</opt>
-                       <opt>taps:complex_vector</opt>
                </option>
        </param>
 
+       <param>
+               <name>Samples Per Symbol</name>
+               <key>samps_per_sym</key>
+               <type>real</type>
+       </param>
+       <param>
+               <name>Filter Rolloff Factor</name>
+               <key>rolloff</key>
+               <type>real</type>
+       </param>
+       <param>
+               <name>Prototype Filter Size</name>
+               <key>filter_size</key>
+               <type>int</type>
+       </param>
+
        <param>
                <name>Alpha</name>
                <key>alpha</key>
                <key>beta</key>
                <type>real</type>
        </param>
-       <param>
-               <name>Taps</name>
-               <key>taps</key>
-               <type>complex_vector</type>
-       </param>
        <sink>
                <name>in</name>
                <type>$type.input</type>