Merge branch 'grc/dualusrp' of git://gnuradio.org/jblum
authorJohnathan Corgan <jcorgan@corganenterprises.com>
Sun, 21 Mar 2010 16:09:13 +0000 (09:09 -0700)
committerJohnathan Corgan <jcorgan@corganenterprises.com>
Sun, 21 Mar 2010 16:09:13 +0000 (09:09 -0700)
58 files changed:
gnuradio-core/src/lib/filter/Makefile.am
gnuradio-core/src/lib/filter/gr_fft_filter_ccc.cc
gnuradio-core/src/lib/filter/gr_fft_filter_ccc.h
gnuradio-core/src/lib/filter/gr_fft_filter_fff.cc
gnuradio-core/src/lib/filter/gr_fft_filter_fff.h
gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.cc
gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.h
gnuradio-core/src/lib/filter/gr_pfb_clock_sync_fff.cc
gnuradio-core/src/lib/filter/gr_pfb_clock_sync_fff.h
gnuradio-core/src/lib/filter/gri_fft_filter_ccc_generic.cc [new file with mode: 0644]
gnuradio-core/src/lib/filter/gri_fft_filter_ccc_generic.h [new file with mode: 0644]
gnuradio-core/src/lib/filter/gri_fft_filter_ccc_sse.cc [new file with mode: 0644]
gnuradio-core/src/lib/filter/gri_fft_filter_ccc_sse.h [new file with mode: 0644]
gnuradio-core/src/lib/filter/gri_fft_filter_fff_generic.cc [new file with mode: 0644]
gnuradio-core/src/lib/filter/gri_fft_filter_fff_generic.h [new file with mode: 0644]
gnuradio-core/src/lib/filter/gri_fft_filter_fff_sse.cc [new file with mode: 0644]
gnuradio-core/src/lib/filter/gri_fft_filter_fff_sse.h [new file with mode: 0644]
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/python/gnuradio/Makefile.am
gnuradio-core/src/python/gnuradio/blks2impl/Makefile.am
gnuradio-core/src/python/gnuradio/blks2impl/dbpsk.py
gnuradio-core/src/python/gnuradio/blks2impl/dbpsk2.py
gnuradio-core/src/python/gnuradio/blks2impl/dqpsk2.py
gnuradio-core/src/python/gnuradio/modulation_utils2.py [new file with mode: 0644]
gnuradio-core/src/python/gnuradio/packet_utils.py
gnuradio-examples/grc/demod/digital_freq_lock.grc
gnuradio-examples/grc/demod/pam_sync.grc
gnuradio-examples/python/digital/benchmark_loopback.py
gnuradio-examples/python/digital/benchmark_qt_loopback2.py
gnuradio-examples/python/digital/benchmark_qt_rx2.py
gnuradio-examples/python/digital/benchmark_rx2.py [new file with mode: 0755]
gnuradio-examples/python/digital/benchmark_tx2.py [new file with mode: 0755]
gnuradio-examples/python/digital/pick_bitrate2.py [new file with mode: 0644]
gnuradio-examples/python/digital/receive_path.py
gnuradio-examples/python/digital/transmit_path.py
gnuradio-examples/python/digital/usrp_receive_path.py
gnuradio-examples/python/digital/usrp_receive_path2.py [new file with mode: 0644]
gnuradio-examples/python/digital/usrp_transmit_path.py
gnuradio-examples/python/digital/usrp_transmit_path2.py [new file with mode: 0644]
gr-gpio/src/python/gpio.py
gr-howto-write-a-block/Makefile.common
gr-howto-write-a-block/Makefile.swig.gen.t
gr-howto-write-a-block/apps/howto_square.py
gr-howto-write-a-block/grc/howto_square2_ff.xml
gr-howto-write-a-block/grc/howto_square_ff.xml
gr-howto-write-a-block/lib/Makefile.am
gr-howto-write-a-block/python/Makefile.am
gr-howto-write-a-block/swig/Makefile.am
gr-howto-write-a-block/swig/Makefile.swig.gen
gr-utils/src/python/Makefile.am
gr-utils/src/python/create-gnuradio-out-of-tree-project [new file with mode: 0755]
grc/gui/DrawingArea.py
grc/gui/FlowGraph.py
gruel/src/include/gruel/pmt.h
gruel/src/lib/pmt/pmt.cc
gruel/src/lib/pmt/pmt_int.h
gruel/src/lib/pmt/qa_pmt_prims.cc

index 9cd6e9f389b85178a1610125d35fecd9f52311c5..23c1dadc3607d870d004ed2de1c66cfbb6f70a9e 100644 (file)
@@ -184,6 +184,8 @@ libfilter_la_common_SOURCES =               \
        $(GENERATED_CC)                 \
        gr_adaptive_fir_ccf.cc          \
        gr_cma_equalizer_cc.cc          \
+       gri_fft_filter_fff_generic.cc   \
+       gri_fft_filter_ccc_generic.cc   \
        gr_fft_filter_ccc.cc            \
        gr_fft_filter_fff.cc            \
        gr_goertzel_fc.cc               \
@@ -259,6 +261,8 @@ grinclude_HEADERS =                         \
        gr_altivec.h                    \
        gr_cma_equalizer_cc.h           \
        gr_cpu.h                        \
+       gri_fft_filter_fff_generic.h    \
+       gri_fft_filter_ccc_generic.h    \
        gr_fft_filter_ccc.h             \
        gr_fft_filter_fff.h             \
        gr_filter_delay_fc.h            \
index 3dd40d56dcd3c7a31a9f3b1bcc698b97155e30f3..4540c6e4ad00a4812e26d72d9b19e8cd290557cf 100644 (file)
@@ -30,6 +30,8 @@
 #endif
 
 #include <gr_fft_filter_ccc.h>
+//#include <gri_fft_filter_ccc_sse.h>
+#include <gri_fft_filter_ccc_generic.h>
 #include <gr_io_signature.h>
 #include <gri_fft.h>
 #include <math.h>
@@ -52,32 +54,23 @@ gr_fft_filter_ccc::gr_fft_filter_ccc (int decimation, const std::vector<gr_compl
                       gr_make_io_signature (1, 1, sizeof (gr_complex)),
                       gr_make_io_signature (1, 1, sizeof (gr_complex)),
                       decimation),
-    d_fftsize(-1), d_fwdfft(0), d_invfft(0), d_updated(false)
+    d_updated(false)
 {
-  // if (decimation != 1)
-  //    throw std::invalid_argument("gr_fft_filter_ccc: decimation must be 1");
-
   set_history(1);
-  actual_set_taps(taps);
+#if 1 // don't enable the sse version until handling it is worked out
+  d_filter = new gri_fft_filter_ccc_generic(decimation, taps);
+#else
+  d_filter = new gri_fft_filter_ccc_sse(decimation, taps);
+#endif
+  d_nsamples = d_filter->set_taps(taps);
+  set_output_multiple(d_nsamples);
 }
 
 gr_fft_filter_ccc::~gr_fft_filter_ccc ()
 {
-  delete d_fwdfft;
-  delete d_invfft;
+  delete d_filter;
 }
 
-#if 0
-static void 
-print_vector_complex(const std::string label, const std::vector<gr_complex> &x)
-{
-  std::cout << label;
-  for (unsigned i = 0; i < x.size(); i++)
-    std::cout << x[i] << " ";
-  std::cout << "\n";
-}
-#endif
-
 void
 gr_fft_filter_ccc::set_taps (const std::vector<gr_complex> &taps)
 {
@@ -85,130 +78,26 @@ gr_fft_filter_ccc::set_taps (const std::vector<gr_complex> &taps)
   d_updated = true;
 }
 
-/*
- * determines d_ntaps, d_nsamples, d_fftsize, d_xformed_taps
- */
-void
-gr_fft_filter_ccc::actual_set_taps (const std::vector<gr_complex> &taps)
-{
-  int i = 0;
-  compute_sizes(taps.size());
-
-  d_tail.resize(tailsize());
-  for (i = 0; i < tailsize(); i++)
-    d_tail[i] = 0;
-
-  gr_complex *in = d_fwdfft->get_inbuf();
-  gr_complex *out = d_fwdfft->get_outbuf();
-
-  float scale = 1.0 / d_fftsize;
-  
-  // Compute forward xform of taps.
-  // Copy taps into first ntaps slots, then pad with zeros
-  for (i = 0; i < d_ntaps; i++)
-    in[i] = taps[i] * scale;
-
-  for (; i < d_fftsize; i++)
-    in[i] = 0;
-
-  d_fwdfft->execute();         // do the xform
-
-  // now copy output to d_xformed_taps
-  for (i = 0; i < d_fftsize; i++)
-    d_xformed_taps[i] = out[i];
-
-  //print_vector_complex("transformed taps:", d_xformed_taps);
-}
-
-// determine and set d_ntaps, d_nsamples, d_fftsize
-
-void
-gr_fft_filter_ccc::compute_sizes(int ntaps)
-{
-  int old_fftsize = d_fftsize;
-  d_ntaps = ntaps;
-  d_fftsize = (int) (2 * pow(2.0, ceil(log(ntaps) / log(2))));
-  d_nsamples = d_fftsize - d_ntaps + 1;
-
-  if (0)
-    fprintf(stderr, "gr_fft_filter: ntaps = %d, fftsize = %d, nsamples = %d\n",
-           d_ntaps, d_fftsize, d_nsamples);
-
-  assert(d_fftsize == d_ntaps + d_nsamples -1 );
-
-  if (d_fftsize != old_fftsize){       // compute new plans
-    delete d_fwdfft;
-    delete d_invfft;
-    d_fwdfft = new gri_fft_complex(d_fftsize, true);
-    d_invfft = new gri_fft_complex(d_fftsize, false);
-    d_xformed_taps.resize(d_fftsize);
-  }
-
-  set_output_multiple(d_nsamples);
-}
-
 int
 gr_fft_filter_ccc::work (int noutput_items,
                         gr_vector_const_void_star &input_items,
                         gr_vector_void_star &output_items)
 {
-  gr_complex *in = (gr_complex *) input_items[0];
+  const gr_complex *in = (const gr_complex *) input_items[0];
   gr_complex *out = (gr_complex *) output_items[0];
 
   if (d_updated){
-    actual_set_taps(d_new_taps);
+    d_nsamples = d_filter->set_taps(d_new_taps);
     d_updated = false;
+    set_output_multiple(d_nsamples);
     return 0;                          // output multiple may have changed
   }
 
   assert(noutput_items % d_nsamples == 0);
 
-  int dec_ctr = 0;
-  int j = 0;
-  int ninput_items = noutput_items * decimation();
-
-  for (int i = 0; i < ninput_items; i += d_nsamples){
-    
-    memcpy(d_fwdfft->get_inbuf(), &in[i], d_nsamples * sizeof(gr_complex));
-
-    for (j = d_nsamples; j < d_fftsize; j++)
-      d_fwdfft->get_inbuf()[j] = 0;
-
-    d_fwdfft->execute();       // compute fwd xform
-
-    gr_complex *a = d_fwdfft->get_outbuf();
-    gr_complex *b = &d_xformed_taps[0];
-    gr_complex *c = d_invfft->get_inbuf();
-
-    for (j = 0; j < d_fftsize; j++)    // filter in the freq domain
-      c[j] = a[j] * b[j];
-    
-    d_invfft->execute();       // compute inv xform
-
-    // add in the overlapping tail
-
-    for (j = 0; j < tailsize(); j++)
-      d_invfft->get_outbuf()[j] += d_tail[j];
-
-    // copy nsamples to output
-
-    //memcpy(out, d_invfft->get_outbuf(), d_nsamples * sizeof(gr_complex));
-    //out += d_nsamples;
-
-    j = dec_ctr;
-    while (j < d_nsamples) {
-      *out++ = d_invfft->get_outbuf()[j];
-      j += decimation();
-    }
-    dec_ctr = (j - d_nsamples);
-
-    // stash the tail
-    memcpy(&d_tail[0], d_invfft->get_outbuf() + d_nsamples,
-          tailsize() * sizeof(gr_complex));
-  }
+  d_filter->filter(noutput_items, in, out);
 
-  assert((out - (gr_complex *) output_items[0]) == noutput_items);
-  assert(dec_ctr == 0);
+  //assert((out - (gr_complex *) output_items[0]) == noutput_items);
 
   return noutput_items;
 }
index c5363dcbb0f1208797879b2c88657e934124f418..68b19e775b9da1c70d0b5f1e0966f73f0ef2e32e 100644 (file)
@@ -28,8 +28,8 @@ class gr_fft_filter_ccc;
 typedef boost::shared_ptr<gr_fft_filter_ccc> gr_fft_filter_ccc_sptr;
 gr_fft_filter_ccc_sptr gr_make_fft_filter_ccc (int decimation, const std::vector<gr_complex> &taps);
 
-class gr_fir_ccc;
-class gri_fft_complex;
+//class gri_fft_filter_ccc_sse;
+class gri_fft_filter_ccc_generic;
 
 /*!
  * \brief Fast FFT filter with gr_complex input, gr_complex output and gr_complex taps
@@ -40,15 +40,14 @@ class gr_fft_filter_ccc : public gr_sync_decimator
  private:
   friend gr_fft_filter_ccc_sptr gr_make_fft_filter_ccc (int decimation, const std::vector<gr_complex> &taps);
 
-  int                     d_ntaps;
   int                     d_nsamples;
-  int                     d_fftsize;           // fftsize = ntaps + nsamples - 1
-  gri_fft_complex        *d_fwdfft;            // forward "plan"
-  gri_fft_complex        *d_invfft;            // inverse "plan"
-  std::vector<gr_complex>  d_tail;             // state carried between blocks for overlap-add
-  std::vector<gr_complex>  d_xformed_taps;     // Fourier xformed taps
-  std::vector<gr_complex>  d_new_taps;
   bool                    d_updated;
+#if 1  // don't enable the sse version until handling it is worked out
+  gri_fft_filter_ccc_generic  *d_filter;  
+#else
+  gri_fft_filter_ccc_sse  *d_filter;  
+#endif
+  std::vector<gr_complex>  d_new_taps;
 
   /*!
    * Construct a FFT filter with the given taps
@@ -58,10 +57,6 @@ class gr_fft_filter_ccc : public gr_sync_decimator
    */
   gr_fft_filter_ccc (int decimation, const std::vector<gr_complex> &taps);
 
-  void compute_sizes(int ntaps);
-  int tailsize() const { return d_ntaps - 1; }
-  void actual_set_taps (const std::vector<gr_complex> &taps);
-
  public:
   ~gr_fft_filter_ccc ();
 
index 57232f3fb2e354e1e4beeeb5f2af29294ce6ab13..e8857fe8cfbd5d45fdfed39bbc95cd6c85e21f47 100644 (file)
@@ -1,6 +1,6 @@
 /* -*- c++ -*- */
 /*
- * Copyright 2005 Free Software Foundation, Inc.
+ * Copyright 2005,2010 Free Software Foundation, Inc.
  * 
  * This file is part of GNU Radio
  * 
 #endif
 
 #include <gr_fft_filter_fff.h>
+#include <gri_fft_filter_fff_generic.h>
+//#include <gri_fft_filter_fff_sse.h>
 #include <gr_io_signature.h>
-#include <gri_fft.h>
-#include <math.h>
 #include <assert.h>
 #include <stdexcept>
-#include <gr_firdes.h>
-
 
 #include <cstdio>
 #include <iostream>
@@ -48,37 +46,24 @@ gr_fft_filter_fff::gr_fft_filter_fff (int decimation, const std::vector<float> &
                       gr_make_io_signature (1, 1, sizeof (float)),
                       gr_make_io_signature (1, 1, sizeof (float)),
                       decimation),
-    d_fftsize(-1), d_fwdfft(0), d_invfft(0), d_updated(false)
+    d_updated(false)
 {
   set_history(1);
-  actual_set_taps(taps);
-}
-
-gr_fft_filter_fff::~gr_fft_filter_fff ()
-{
-  delete d_fwdfft;
-  delete d_invfft;
-}
+  
+#if 1 // don't enable the sse version until handling it is worked out
+    d_filter = new gri_fft_filter_fff_generic(decimation, taps);
+#else
+    d_filter = new gri_fft_filter_fff_sse(decimation, taps);
+#endif
 
-#if 0
-static void 
-print_vector_complex(const std::string label, const std::vector<gr_complex> &x)
-{
-  std::cout << label;
-  for (unsigned i = 0; i < x.size(); i++)
-    std::cout << x[i] << " ";
-  std::cout << "\n";
+  d_nsamples = d_filter->set_taps(taps);
+  set_output_multiple(d_nsamples);
 }
 
-static void 
-print_vector_float(const std::string label, const std::vector<float> &x)
+gr_fft_filter_fff::~gr_fft_filter_fff ()
 {
-  std::cout << label;
-  for (unsigned i = 0; i < x.size(); i++)
-    std::cout << x[i] << " ";
-  std::cout << "\n";
+  delete d_filter;
 }
-#endif
 
 void
 gr_fft_filter_fff::set_taps (const std::vector<float> &taps)
@@ -87,68 +72,6 @@ gr_fft_filter_fff::set_taps (const std::vector<float> &taps)
   d_updated = true;
 }
 
-/*
- * determines d_ntaps, d_nsamples, d_fftsize, d_xformed_taps
- */
-void
-gr_fft_filter_fff::actual_set_taps (const std::vector<float> &taps)
-{
-  int i = 0;
-  compute_sizes(taps.size());
-
-  d_tail.resize(tailsize());
-  for (i = 0; i < tailsize(); i++)
-    d_tail[i] = 0;
-
-  float *in = d_fwdfft->get_inbuf();
-  gr_complex *out = d_fwdfft->get_outbuf();
-
-  float scale = 1.0 / d_fftsize;
-  
-  // Compute forward xform of taps.
-  // Copy taps into first ntaps slots, then pad with zeros
-  for (i = 0; i < d_ntaps; i++)
-    in[i] = taps[i] * scale;
-
-  for (; i < d_fftsize; i++)
-    in[i] = 0;
-
-  d_fwdfft->execute();         // do the xform
-
-  // now copy output to d_xformed_taps
-  for (i = 0; i < d_fftsize/2+1; i++)
-    d_xformed_taps[i] = out[i];
-
-  //print_vector_complex("transformed taps:", d_xformed_taps);
-}
-
-// determine and set d_ntaps, d_nsamples, d_fftsize
-
-void
-gr_fft_filter_fff::compute_sizes(int ntaps)
-{
-  int old_fftsize = d_fftsize;
-  d_ntaps = ntaps;
-  d_fftsize = (int) (2 * pow(2.0, ceil(log(ntaps) / log(2))));
-  d_nsamples = d_fftsize - d_ntaps + 1;
-
-  if (0)
-    fprintf(stderr, "gr_fft_filter: ntaps = %d, fftsize = %d, nsamples = %d\n",
-           d_ntaps, d_fftsize, d_nsamples);
-
-  assert(d_fftsize == d_ntaps + d_nsamples -1 );
-
-  if (d_fftsize != old_fftsize){       // compute new plans
-    delete d_fwdfft;
-    delete d_invfft;
-    d_fwdfft = new gri_fft_real_fwd(d_fftsize);
-    d_invfft = new gri_fft_real_rev(d_fftsize);
-    d_xformed_taps.resize(d_fftsize/2+1);
-  }
-
-  set_output_multiple(d_nsamples);
-}
-
 int
 gr_fft_filter_fff::work (int noutput_items,
                         gr_vector_const_void_star &input_items,
@@ -158,59 +81,17 @@ gr_fft_filter_fff::work (int noutput_items,
   float *out = (float *) output_items[0];
 
   if (d_updated){
-    actual_set_taps(d_new_taps);
+    d_nsamples = d_filter->set_taps(d_new_taps);
     d_updated = false;
+    set_output_multiple(d_nsamples);
     return 0;                          // output multiple may have changed
   }
 
   assert(noutput_items % d_nsamples == 0);
+  
+  d_filter->filter(noutput_items, in, out);
 
-  int dec_ctr = 0;
-  int j = 0;
-  int ninput_items = noutput_items * decimation();
-
-  for (int i = 0; i < ninput_items; i += d_nsamples){
-    
-    memcpy(d_fwdfft->get_inbuf(), &in[i], d_nsamples * sizeof(float));
-
-    for (j = d_nsamples; j < d_fftsize; j++)
-      d_fwdfft->get_inbuf()[j] = 0;
-
-    d_fwdfft->execute();       // compute fwd xform
-
-    gr_complex *a = d_fwdfft->get_outbuf();
-    gr_complex *b = &d_xformed_taps[0];
-    gr_complex *c = d_invfft->get_inbuf();
-
-    for (j = 0; j < d_fftsize/2+1; j++)        // filter in the freq domain
-      c[j] = a[j] * b[j];
-    
-    d_invfft->execute();       // compute inv xform
-
-    // add in the overlapping tail
-
-    for (j = 0; j < tailsize(); j++)
-      d_invfft->get_outbuf()[j] += d_tail[j];
-
-    // copy nsamples to output
-
-    //memcpy(out, d_invfft->get_outbuf(), d_nsamples * sizeof(float));
-    //out += d_nsamples;
-
-    j = dec_ctr;
-    while (j < d_nsamples) {
-      *out++ = d_invfft->get_outbuf()[j];
-      j += decimation();
-    }
-    dec_ctr = (j - d_nsamples);
-
-    // stash the tail
-    memcpy(&d_tail[0], d_invfft->get_outbuf() + d_nsamples,
-          tailsize() * sizeof(float));
-  }
-
-  assert((out - (float *) output_items[0]) == noutput_items);
-  assert(dec_ctr == 0);
+  //assert((out - (float *) output_items[0]) == noutput_items);
 
   return noutput_items;
 }
index b26361107925640d4bfa0303de76b83cf0d2bc5e..6eaa21500a8c0923cf13eb11eba8dc00ce9c0073 100644 (file)
@@ -28,9 +28,8 @@ class gr_fft_filter_fff;
 typedef boost::shared_ptr<gr_fft_filter_fff> gr_fft_filter_fff_sptr;
 gr_fft_filter_fff_sptr gr_make_fft_filter_fff (int decimation, const std::vector<float> &taps);
 
-class gr_fir_fff;
-class gri_fft_real_fwd;
-class gri_fft_real_rev;
+class gri_fft_filter_fff_generic;
+//class gri_fft_filter_fff_sse;
 
 /*!
  * \brief Fast FFT filter with float input, float output and float taps
@@ -41,15 +40,14 @@ class gr_fft_filter_fff : public gr_sync_decimator
  private:
   friend gr_fft_filter_fff_sptr gr_make_fft_filter_fff (int decimation, const std::vector<float> &taps);
 
-  int                     d_ntaps;
   int                     d_nsamples;
-  int                     d_fftsize;           // fftsize = ntaps + nsamples - 1
-  gri_fft_real_fwd       *d_fwdfft;            // forward "plan"
-  gri_fft_real_rev       *d_invfft;            // inverse "plan"
-  std::vector<float>       d_tail;             // state carried between blocks for overlap-add
-  std::vector<gr_complex>  d_xformed_taps;     // Fourier xformed taps
-  std::vector<float>      d_new_taps;
   bool                    d_updated;
+#if 1 // don't enable the sse version until handling it is worked out
+  gri_fft_filter_fff_generic  *d_filter;
+#else
+  gri_fft_filter_fff_sse  *d_filter;
+#endif
+  std::vector<float>      d_new_taps;
 
   /*!
    * Construct a FFT filter with the given taps
@@ -58,10 +56,6 @@ class gr_fft_filter_fff : public gr_sync_decimator
    * \param taps        float filter taps
    */
   gr_fft_filter_fff (int decimation, const std::vector<float> &taps);
-
-  void compute_sizes(int ntaps);
-  int tailsize() const { return d_ntaps - 1; }
-  void actual_set_taps (const std::vector<float> &taps);
   
  public:
   ~gr_fft_filter_fff ();
index 59454afe5fa60b02f88af37577ae6101f9b6eccd..ff4fb70a36eed08aa623374a0ccf3e2128c622f3 100644 (file)
@@ -1,6 +1,6 @@
 /* -*- c++ -*- */
 /*
- * Copyright 2009 Free Software Foundation, Inc.
+ * Copyright 2009,2010 Free Software Foundation, Inc.
  * 
  * This file is part of GNU Radio
  * 
@@ -93,9 +93,16 @@ gr_pfb_clock_sync_ccf::~gr_pfb_clock_sync_ccf ()
 {
   for(int i = 0; i < d_nfilters; i++) {
     delete d_filters[i];
+    delete d_diff_filters[i];
   }
 }
 
+bool
+gr_pfb_clock_sync_ccf::check_topology(int ninputs, int noutputs)
+{
+  return noutputs == 1 || noutputs == 4;
+}
+
 void
 gr_pfb_clock_sync_ccf::set_taps (const std::vector<float> &newtaps,
                                 std::vector< std::vector<float> > &ourtaps,
@@ -219,8 +226,8 @@ gr_pfb_clock_sync_ccf::general_work (int noutput_items,
   gr_complex *in = (gr_complex *) input_items[0];
   gr_complex *out = (gr_complex *) output_items[0];
 
-  float *err, *outrate, *outk;
-  if(output_items.size() > 2) {
+  float *err = 0, *outrate = 0, *outk = 0;
+  if(output_items.size() == 4) {
     err = (float *) output_items[1];
     outrate = (float*)output_items[2];
     outk = (float*)output_items[3];
@@ -271,7 +278,7 @@ gr_pfb_clock_sync_ccf::general_work (int noutput_items,
     i++;
     count += (int)floor(d_sps);
 
-    if(output_items.size() > 2) {
+    if(output_items.size() == 4) {
       err[i] = error;
       outrate[i] = d_rate_f;
       outk[i] = d_k;
index a07192a7f34dcfeb52b4f2290601bf3bc632e705..70857173bfdf2929d03b9df9f6b7d9fbec6c9e36 100644 (file)
@@ -1,6 +1,6 @@
 /* -*- c++ -*- */
 /*
- * Copyright 2009 Free Software Foundation, Inc.
+ * Copyright 2009,2010 Free Software Foundation, Inc.
  * 
  * This file is part of GNU Radio
  * 
@@ -119,6 +119,8 @@ public:
     d_max_dev = m;
   }
   
+  bool check_topology(int ninputs, int noutputs);
+
   int general_work (int noutput_items,
                    gr_vector_int &ninput_items,
                    gr_vector_const_void_star &input_items,
index d1d2f05dbe25e9d431f824b8b6fdd0641803ffdf..86de3b5a1c17fe2ec3e3864a9344a1839e8a148e 100644 (file)
@@ -1,6 +1,6 @@
 /* -*- c++ -*- */
 /*
- * Copyright 2009 Free Software Foundation, Inc.
+ * Copyright 2009,2010 Free Software Foundation, Inc.
  * 
  * This file is part of GNU Radio
  * 
@@ -93,9 +93,16 @@ gr_pfb_clock_sync_fff::~gr_pfb_clock_sync_fff ()
 {
   for(int i = 0; i < d_nfilters; i++) {
     delete d_filters[i];
+    delete d_diff_filters[i];
   }
 }
 
+bool
+gr_pfb_clock_sync_fff::check_topology(int ninputs, int noutputs)
+{
+  return noutputs == 1 || noutputs == 4;
+}
+
 void
 gr_pfb_clock_sync_fff::set_taps (const std::vector<float> &newtaps,
                                 std::vector< std::vector<float> > &ourtaps,
@@ -219,8 +226,8 @@ gr_pfb_clock_sync_fff::general_work (int noutput_items,
   float *in = (float *) input_items[0];
   float *out = (float *) output_items[0];
 
-  float *err, *outrate, *outk;
-  if(output_items.size() > 2) {
+  float *err = 0, *outrate = 0, *outk = 0;
+  if(output_items.size() == 4) {
     err = (float *) output_items[1];
     outrate = (float*)output_items[2];
     outk = (float*)output_items[3];
@@ -269,7 +276,7 @@ gr_pfb_clock_sync_fff::general_work (int noutput_items,
     i++;
     count += (int)floor(d_sps);
 
-    if(output_items.size() > 2) {
+    if(output_items.size() == 4) {
       err[i] = error;
       outrate[i] = d_rate_f;
       outk[i] = d_k;
index 913f798fefccb6fdac3c7de4622f047ff3fad971..10eec4f5407c705fb5eddda7651b55a8a0c53895 100644 (file)
@@ -1,6 +1,6 @@
 /* -*- c++ -*- */
 /*
- * Copyright 2009 Free Software Foundation, Inc.
+ * Copyright 2009,2010 Free Software Foundation, Inc.
  * 
  * This file is part of GNU Radio
  * 
@@ -118,7 +118,9 @@ public:
   {
     d_max_dev = m;
   }
-  
+
+  bool check_topology(int ninputs, int noutputs);
+
   int general_work (int noutput_items,
                    gr_vector_int &ninput_items,
                    gr_vector_const_void_star &input_items,
diff --git a/gnuradio-core/src/lib/filter/gri_fft_filter_ccc_generic.cc b/gnuradio-core/src/lib/filter/gri_fft_filter_ccc_generic.cc
new file mode 100644 (file)
index 0000000..1bf4a6f
--- /dev/null
@@ -0,0 +1,167 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2010 Free Software Foundation, Inc.
+ * 
+ * This file is part of GNU Radio
+ * 
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ * 
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gri_fft_filter_ccc_generic.h>
+#include <gri_fft.h>
+#include <assert.h>
+#include <stdexcept>
+#include <cstdio>
+#include <cstring>
+#include <fftw3.h>
+
+gri_fft_filter_ccc_generic::gri_fft_filter_ccc_generic (int decimation, 
+                                                       const std::vector<gr_complex> &taps)
+  : d_fftsize(-1), d_decimation(decimation), d_fwdfft(0), d_invfft(0)
+{
+  set_taps(taps);
+}
+
+gri_fft_filter_ccc_generic::~gri_fft_filter_ccc_generic ()
+{
+  delete d_fwdfft;
+  delete d_invfft;
+}
+
+#if 0
+static void 
+print_vector_complex(const std::string label, const std::vector<gr_complex> &x)
+{
+  std::cout << label;
+  for (unsigned i = 0; i < x.size(); i++)
+    std::cout << x[i] << " ";
+  std::cout << "\n";
+}
+#endif
+
+
+/*
+ * determines d_ntaps, d_nsamples, d_fftsize, d_xformed_taps
+ */
+int
+gri_fft_filter_ccc_generic::set_taps (const std::vector<gr_complex> &taps)
+{
+  int i = 0;
+  compute_sizes(taps.size());
+
+  d_tail.resize(tailsize());
+  for (i = 0; i < tailsize(); i++)
+    d_tail[i] = 0;
+
+  gr_complex *in = d_fwdfft->get_inbuf();
+  gr_complex *out = d_fwdfft->get_outbuf();
+
+  float scale = 1.0 / d_fftsize;
+  
+  // Compute forward xform of taps.
+  // Copy taps into first ntaps slots, then pad with zeros
+  for (i = 0; i < d_ntaps; i++)
+    in[i] = taps[i] * scale;
+
+  for (; i < d_fftsize; i++)
+    in[i] = 0;
+
+  d_fwdfft->execute();         // do the xform
+
+  // now copy output to d_xformed_taps
+  for (i = 0; i < d_fftsize; i++)
+    d_xformed_taps[i] = out[i];
+  
+  return d_nsamples;
+}
+
+// determine and set d_ntaps, d_nsamples, d_fftsize
+
+void
+gri_fft_filter_ccc_generic::compute_sizes(int ntaps)
+{
+  int old_fftsize = d_fftsize;
+  d_ntaps = ntaps;
+  d_fftsize = (int) (2 * pow(2.0, ceil(log(ntaps) / log(2))));
+  d_nsamples = d_fftsize - d_ntaps + 1;
+
+  if (0)
+    fprintf(stderr, "gri_fft_filter_ccc_generic: ntaps = %d, fftsize = %d, nsamples = %d\n",
+           d_ntaps, d_fftsize, d_nsamples);
+
+  assert(d_fftsize == d_ntaps + d_nsamples -1 );
+
+  if (d_fftsize != old_fftsize){       // compute new plans
+    delete d_fwdfft;
+    delete d_invfft;
+    d_fwdfft = new gri_fft_complex(d_fftsize, true);
+    d_invfft = new gri_fft_complex(d_fftsize, false);
+    d_xformed_taps.resize(d_fftsize);
+  }
+}
+
+int
+gri_fft_filter_ccc_generic::filter (int nitems, const gr_complex *input, gr_complex *output)
+{
+  int dec_ctr = 0;
+  int j = 0;
+  int ninput_items = nitems * d_decimation;
+
+  for (int i = 0; i < ninput_items; i += d_nsamples){
+    
+    memcpy(d_fwdfft->get_inbuf(), &input[i], d_nsamples * sizeof(gr_complex));
+
+    for (j = d_nsamples; j < d_fftsize; j++)
+      d_fwdfft->get_inbuf()[j] = 0;
+
+    d_fwdfft->execute();       // compute fwd xform
+    
+    gr_complex *a = d_fwdfft->get_outbuf();
+    gr_complex *b = &d_xformed_taps[0];
+    gr_complex *c = d_invfft->get_inbuf();
+
+    for (j = 0; j < d_fftsize; j+=1) { // filter in the freq domain
+      c[j] = a[j] * b[j];
+    } 
+    
+    d_invfft->execute();       // compute inv xform
+
+    // add in the overlapping tail
+
+    for (j = 0; j < tailsize(); j++)
+      d_invfft->get_outbuf()[j] += d_tail[j];
+
+    // copy nsamples to output
+    j = dec_ctr;
+    while (j < d_nsamples) {
+      *output++ = d_invfft->get_outbuf()[j];
+      j += d_decimation;
+    }
+    dec_ctr = (j - d_nsamples);
+
+    // stash the tail
+    memcpy(&d_tail[0], d_invfft->get_outbuf() + d_nsamples,
+          tailsize() * sizeof(gr_complex));
+  }
+
+  assert(dec_ctr == 0);
+
+  return nitems;
+}
diff --git a/gnuradio-core/src/lib/filter/gri_fft_filter_ccc_generic.h b/gnuradio-core/src/lib/filter/gri_fft_filter_ccc_generic.h
new file mode 100644 (file)
index 0000000..3cd9105
--- /dev/null
@@ -0,0 +1,82 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2010 Free Software Foundation, Inc.
+ * 
+ * This file is part of GNU Radio
+ * 
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ * 
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_GRI_FFT_FILTER_CCC_GENERIC_H
+#define INCLUDED_GRI_FFT_FILTER_CCC_GENERIC_H
+
+#include <gr_complex.h>
+#include <vector>
+
+class gri_fft_complex;
+
+/*!
+ * \brief Fast FFT filter with gr_complex input, gr_complex output and gr_complex taps
+ * \ingroup filter_blk
+ */
+class gri_fft_filter_ccc_generic
+{
+ private:
+  int                     d_ntaps;
+  int                     d_nsamples;
+  int                     d_fftsize;           // fftsize = ntaps + nsamples - 1
+  int                      d_decimation;
+  gri_fft_complex        *d_fwdfft;            // forward "plan"
+  gri_fft_complex        *d_invfft;            // inverse "plan"
+  std::vector<gr_complex>  d_tail;             // state carried between blocks for overlap-add
+  std::vector<gr_complex>  d_xformed_taps;     // Fourier xformed taps
+  std::vector<gr_complex>  d_new_taps;
+
+  void compute_sizes(int ntaps);
+  int tailsize() const { return d_ntaps - 1; }
+  
+ public:
+  /*!
+   * \brief Construct an FFT filter for complex vectors with the given taps and decimation rate.
+   *
+   * This is the basic implementation for performing FFT filter for fast convolution
+   * in other blocks for complex vectors (such as gr_fft_filter_ccc).
+   * \param decimation The decimation rate of the filter (int)
+   * \param taps       The filter taps (complex)
+   */
+  gri_fft_filter_ccc_generic (int decimation, const std::vector<gr_complex> &taps);
+  ~gri_fft_filter_ccc_generic ();
+
+  /*!
+   * \brief Set new taps for the filter.
+   *
+   * Sets new taps and resets the class properties to handle different sizes
+   * \param taps       The filter taps (complex)
+   */
+  int set_taps (const std::vector<gr_complex> &taps);
+  
+  /*!
+   * \brief Perform the filter operation
+   *
+   * \param nitems  The number of items to produce
+   * \param input   The input vector to be filtered
+   * \param output  The result of the filter operation
+   */
+  int filter (int nitems, const gr_complex *input, gr_complex *output);
+
+};
+
+#endif /* INCLUDED_GRI_FFT_FILTER_CCC_GENERIC_H */
diff --git a/gnuradio-core/src/lib/filter/gri_fft_filter_ccc_sse.cc b/gnuradio-core/src/lib/filter/gri_fft_filter_ccc_sse.cc
new file mode 100644 (file)
index 0000000..b7d925f
--- /dev/null
@@ -0,0 +1,186 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2010 Free Software Foundation, Inc.
+ * 
+ * This file is part of GNU Radio
+ * 
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ * 
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gri_fft_filter_ccc_sse.h>
+#include <gri_fft.h>
+#include <assert.h>
+#include <stdexcept>
+#include <cstdio>
+#include <xmmintrin.h>
+#include <fftw3.h>
+
+gri_fft_filter_ccc_sse::gri_fft_filter_ccc_sse (int decimation,
+                                               const std::vector<gr_complex> &taps)
+  : d_fftsize(-1), d_decimation(decimation), d_fwdfft(0), d_invfft(0)
+{
+  d_xformed_taps = (gr_complex*)fftwf_malloc(1*sizeof(gr_complex));
+  set_taps(taps);
+}
+
+gri_fft_filter_ccc_sse::~gri_fft_filter_ccc_sse ()
+{
+  fftwf_free(d_xformed_taps);
+  delete d_fwdfft;
+  delete d_invfft;
+}
+
+#if 0
+static void 
+print_vector_complex(const std::string label, const std::vector<gr_complex> &x)
+{
+  std::cout << label;
+  for (unsigned i = 0; i < x.size(); i++)
+    std::cout << x[i] << " ";
+  std::cout << "\n";
+}
+#endif
+
+
+/*
+ * determines d_ntaps, d_nsamples, d_fftsize, d_xformed_taps
+ */
+int
+gri_fft_filter_ccc_sse::set_taps (const std::vector<gr_complex> &taps)
+{
+  int i = 0;
+  compute_sizes(taps.size());
+
+  d_tail.resize(tailsize());
+  for (i = 0; i < tailsize(); i++)
+    d_tail[i] = 0;
+
+  gr_complex *in = d_fwdfft->get_inbuf();
+  gr_complex *out = d_fwdfft->get_outbuf();
+
+  float scale = 1.0 / d_fftsize;
+  
+  // Compute forward xform of taps.
+  // Copy taps into first ntaps slots, then pad with zeros
+  for (i = 0; i < d_ntaps; i++)
+    in[i] = taps[i] * scale;
+
+  for (; i < d_fftsize; i++)
+    in[i] = 0;
+
+  d_fwdfft->execute();         // do the xform
+
+  // now copy output to d_xformed_taps
+  for (i = 0; i < d_fftsize; i++)
+    d_xformed_taps[i] = out[i];
+  
+  return d_nsamples;
+}
+
+// determine and set d_ntaps, d_nsamples, d_fftsize
+
+void
+gri_fft_filter_ccc_sse::compute_sizes(int ntaps)
+{
+  int old_fftsize = d_fftsize;
+  d_ntaps = ntaps;
+  d_fftsize = (int) (2 * pow(2.0, ceil(log(ntaps) / log(2))));
+  d_nsamples = d_fftsize - d_ntaps + 1;
+
+  if (0)
+    fprintf(stderr, "gri_fft_filter_ccc_sse: ntaps = %d, fftsize = %d, nsamples = %d\n",
+           d_ntaps, d_fftsize, d_nsamples);
+
+  assert(d_fftsize == d_ntaps + d_nsamples -1 );
+
+  if (d_fftsize != old_fftsize){       // compute new plans
+    delete d_fwdfft;
+    delete d_invfft;
+    d_fwdfft = new gri_fft_complex(d_fftsize, true);
+    d_invfft = new gri_fft_complex(d_fftsize, false);
+    
+    fftwf_free(d_xformed_taps);
+    d_xformed_taps = (gr_complex*)fftwf_malloc((d_fftsize)*sizeof(gr_complex));
+  }
+}
+
+int
+gri_fft_filter_ccc_sse::filter (int nitems, const gr_complex *input, gr_complex *output)
+{
+  int dec_ctr = 0;
+  int j = 0;
+  int ninput_items = nitems * d_decimation;
+
+  for (int i = 0; i < ninput_items; i += d_nsamples){
+    
+    memcpy(d_fwdfft->get_inbuf(), &input[i], d_nsamples * sizeof(gr_complex));
+
+    for (j = d_nsamples; j < d_fftsize; j++)
+      d_fwdfft->get_inbuf()[j] = 0;
+
+    d_fwdfft->execute();       // compute fwd xform
+    
+    float *a = (float*)(d_fwdfft->get_outbuf());
+    float *b = (float*)(&d_xformed_taps[0]);
+    float *c = (float*)(d_invfft->get_inbuf());
+
+    __m128 x0, x1, x2, t0, t1, m;
+    m = _mm_set_ps(-1, 1, -1, 1);
+    for (j = 0; j < 2*d_fftsize; j+=4) {       // filter in the freq domain
+      x0 = _mm_load_ps(&a[j]);
+      t0 = _mm_load_ps(&b[j]);
+      
+      t1 = _mm_shuffle_ps(t0, t0, _MM_SHUFFLE(3, 3, 1, 1));
+      t0 = _mm_shuffle_ps(t0, t0, _MM_SHUFFLE(2, 2, 0, 0));
+      t1 = _mm_mul_ps(t1, m);
+
+      x1 = _mm_mul_ps(x0, t0);
+      x2 = _mm_mul_ps(x0, t1);
+
+      x2 = _mm_shuffle_ps(x2, x2, _MM_SHUFFLE(2, 3, 0, 1));
+      x2 = _mm_add_ps(x1, x2);
+
+      _mm_store_ps(&c[j], x2);
+    }
+
+    d_invfft->execute();       // compute inv xform
+
+    // add in the overlapping tail
+
+    for (j = 0; j < tailsize(); j++)
+      d_invfft->get_outbuf()[j] += d_tail[j];
+
+    // copy nsamples to output
+    j = dec_ctr;
+    while (j < d_nsamples) {
+      *output++ = d_invfft->get_outbuf()[j];
+      j += d_decimation;
+    }
+    dec_ctr = (j - d_nsamples);
+
+    // stash the tail
+    memcpy(&d_tail[0], d_invfft->get_outbuf() + d_nsamples,
+          tailsize() * sizeof(gr_complex));
+  }
+
+  assert(dec_ctr == 0);
+
+  return nitems;
+}
diff --git a/gnuradio-core/src/lib/filter/gri_fft_filter_ccc_sse.h b/gnuradio-core/src/lib/filter/gri_fft_filter_ccc_sse.h
new file mode 100644 (file)
index 0000000..d1c54f0
--- /dev/null
@@ -0,0 +1,82 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2010 Free Software Foundation, Inc.
+ * 
+ * This file is part of GNU Radio
+ * 
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ * 
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_GRI_FFT_FILTER_CCC_SSE_H
+#define INCLUDED_GRI_FFT_FILTER_CCC_SSE_H
+
+#include <gr_complex.h>
+#include <vector>
+
+class gri_fft_complex;
+
+/*!
+ * \brief Fast FFT filter with gr_complex input, gr_complex output and gr_complex taps
+ * \ingroup filter_blk
+ */
+class gri_fft_filter_ccc_sse
+{
+ private:
+  int                     d_ntaps;
+  int                     d_nsamples;
+  int                     d_fftsize;           // fftsize = ntaps + nsamples - 1
+  int                      d_decimation;
+  gri_fft_complex        *d_fwdfft;            // forward "plan"
+  gri_fft_complex        *d_invfft;            // inverse "plan"
+  std::vector<gr_complex>  d_tail;             // state carried between blocks for overlap-add
+  gr_complex              *d_xformed_taps;
+  std::vector<gr_complex>  d_new_taps;
+
+  void compute_sizes(int ntaps);
+  int tailsize() const { return d_ntaps - 1; }
+  
+ public:
+  /*!
+   * \brief Construct an FFT filter for complex vectors with the given taps and decimation rate.
+   *
+   * This is the basic implementation for performing FFT filter for fast convolution
+   * in other blocks for complex vectors (such as gr_fft_filter_ccc).
+   * \param decimation The decimation rate of the filter (int)
+   * \param taps       The filter taps (complex)
+   */
+  gri_fft_filter_ccc_sse (int decimation, const std::vector<gr_complex> &taps);
+  ~gri_fft_filter_ccc_sse ();
+
+  /*!
+   * \brief Set new taps for the filter.
+   *
+   * Sets new taps and resets the class properties to handle different sizes
+   * \param taps       The filter taps (complex)
+   */
+  int set_taps (const std::vector<gr_complex> &taps);
+  
+  /*!
+   * \brief Perform the filter operation
+   *
+   * \param nitems  The number of items to produce
+   * \param input   The input vector to be filtered
+   * \param output  The result of the filter operation
+   */
+  int filter (int nitems, const gr_complex *input, gr_complex *output);
+
+};
+
+#endif /* INCLUDED_GRI_FFT_FILTER_CCC_SSE_H */
diff --git a/gnuradio-core/src/lib/filter/gri_fft_filter_fff_generic.cc b/gnuradio-core/src/lib/filter/gri_fft_filter_fff_generic.cc
new file mode 100644 (file)
index 0000000..74058fa
--- /dev/null
@@ -0,0 +1,158 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2010 Free Software Foundation, Inc.
+ * 
+ * This file is part of GNU Radio
+ * 
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ * 
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gri_fft_filter_fff_generic.h>
+#include <gri_fft.h>
+#include <assert.h>
+#include <stdexcept>
+#include <cstdio>
+#include <cstring>
+
+gri_fft_filter_fff_generic::gri_fft_filter_fff_generic (int decimation, 
+                                                       const std::vector<float> &taps)
+  : d_fftsize(-1), d_decimation(decimation), d_fwdfft(0), d_invfft(0)
+{
+  set_taps(taps);
+}
+
+gri_fft_filter_fff_generic::~gri_fft_filter_fff_generic ()
+{
+  delete d_fwdfft;
+  delete d_invfft;
+}
+
+/*
+ * determines d_ntaps, d_nsamples, d_fftsize, d_xformed_taps
+ */
+int
+gri_fft_filter_fff_generic::set_taps (const std::vector<float> &taps)
+{
+  int i = 0;
+  compute_sizes(taps.size());
+
+  d_tail.resize(tailsize());
+  for (i = 0; i < tailsize(); i++)
+    d_tail[i] = 0;
+
+  float *in = d_fwdfft->get_inbuf();
+  gr_complex *out = d_fwdfft->get_outbuf();
+
+  float scale = 1.0 / d_fftsize;
+  
+  // Compute forward xform of taps.
+  // Copy taps into first ntaps slots, then pad with zeros
+  for (i = 0; i < d_ntaps; i++)
+    in[i] = taps[i] * scale;
+
+  for (; i < d_fftsize; i++)
+    in[i] = 0;
+
+  d_fwdfft->execute();         // do the xform
+
+  // now copy output to d_xformed_taps
+  for (i = 0; i < d_fftsize/2+1; i++)
+    d_xformed_taps[i] = out[i];
+  
+  return d_nsamples;
+}
+
+// determine and set d_ntaps, d_nsamples, d_fftsize
+
+void
+gri_fft_filter_fff_generic::compute_sizes(int ntaps)
+{
+  int old_fftsize = d_fftsize;
+  d_ntaps = ntaps;
+  d_fftsize = (int) (2 * pow(2.0, ceil(log(ntaps) / log(2))));
+  d_nsamples = d_fftsize - d_ntaps + 1;
+
+  if (0)
+    fprintf(stderr, "gri_fft_filter_fff_generic: ntaps = %d, fftsize = %d, nsamples = %d\n",
+           d_ntaps, d_fftsize, d_nsamples);
+
+  assert(d_fftsize == d_ntaps + d_nsamples -1 );
+
+  if (d_fftsize != old_fftsize){       // compute new plans
+    delete d_fwdfft;
+    delete d_invfft;
+    d_fwdfft = new gri_fft_real_fwd(d_fftsize);
+    d_invfft = new gri_fft_real_rev(d_fftsize);
+    d_xformed_taps.resize(d_fftsize/2+1);
+  }
+}
+
+int
+gri_fft_filter_fff_generic::filter (int nitems, const float *input, float *output)
+{
+  int dec_ctr = 0;
+  int j = 0;
+  int ninput_items = nitems * d_decimation;
+
+  for (int i = 0; i < ninput_items; i += d_nsamples){
+    
+    memcpy(d_fwdfft->get_inbuf(), &input[i], d_nsamples * sizeof(float));
+
+    for (j = d_nsamples; j < d_fftsize; j++)
+      d_fwdfft->get_inbuf()[j] = 0;
+
+    d_fwdfft->execute();       // compute fwd xform
+
+    gr_complex *a = d_fwdfft->get_outbuf();
+    gr_complex *b = &d_xformed_taps[0];
+    gr_complex *c = d_invfft->get_inbuf();
+
+    for (j = 0; j < d_fftsize/2+1; j++) {      // filter in the freq domain
+      c[j] = a[j] * b[j];
+    }      
+   
+    d_invfft->execute();       // compute inv xform
+
+    // add in the overlapping tail
+
+    for (j = 0; j < tailsize(); j++)
+      d_invfft->get_outbuf()[j] += d_tail[j];
+
+    // copy nsamples to output
+
+    //memcpy(out, d_invfft->get_outbuf(), d_nsamples * sizeof(float));
+    //out += d_nsamples;
+
+    j = dec_ctr;
+    while (j < d_nsamples) {
+      *output++ = d_invfft->get_outbuf()[j];
+      j += d_decimation;
+    }
+    dec_ctr = (j - d_nsamples);
+
+    // stash the tail
+    memcpy(&d_tail[0], d_invfft->get_outbuf() + d_nsamples,
+          tailsize() * sizeof(float));
+  }
+
+  assert(dec_ctr == 0);
+
+  return nitems;
+}
diff --git a/gnuradio-core/src/lib/filter/gri_fft_filter_fff_generic.h b/gnuradio-core/src/lib/filter/gri_fft_filter_fff_generic.h
new file mode 100644 (file)
index 0000000..6c31632
--- /dev/null
@@ -0,0 +1,80 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2010 Free Software Foundation, Inc.
+ * 
+ * This file is part of GNU Radio
+ * 
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ * 
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_GRI_FFT_FILTER_FFF_GENERIC_H
+#define INCLUDED_GRI_FFT_FILTER_FFF_GENERIC_H
+
+#include <gr_complex.h>
+#include <vector>
+
+class gri_fft_real_fwd;
+class gri_fft_real_rev;
+
+class gri_fft_filter_fff_generic
+{
+ private:
+  int                     d_ntaps;
+  int                     d_nsamples;
+  int                     d_fftsize;           // fftsize = ntaps + nsamples - 1
+  int                      d_decimation;
+  gri_fft_real_fwd       *d_fwdfft;            // forward "plan"
+  gri_fft_real_rev       *d_invfft;            // inverse "plan"
+  std::vector<float>       d_tail;             // state carried between blocks for overlap-add
+  std::vector<gr_complex>  d_xformed_taps;     // Fourier xformed taps
+  std::vector<float>      d_new_taps;
+
+
+  void compute_sizes(int ntaps);
+  int tailsize() const { return d_ntaps - 1; }
+  
+ public:
+  /*!
+   * \brief Construct a FFT filter for float vectors with the given taps and decimation rate.
+   *
+   * This is the basic implementation for performing FFT filter for fast convolution
+   * in other blocks for floating point vectors (such as gr_fft_filter_fff).
+   * \param decimation The decimation rate of the filter (int)
+   * \param taps       The filter taps (float)
+   */
+  gri_fft_filter_fff_generic (int decimation, const std::vector<float> &taps);
+  ~gri_fft_filter_fff_generic ();
+
+  /*!
+   * \brief Set new taps for the filter.
+   *
+   * Sets new taps and resets the class properties to handle different sizes
+   * \param taps       The filter taps (float)
+   */
+  int set_taps (const std::vector<float> &taps);
+  
+  /*!
+   * \brief Perform the filter operation
+   *
+   * \param nitems  The number of items to produce
+   * \param input   The input vector to be filtered
+   * \param output  The result of the filter operation
+   */
+  int filter (int nitems, const float *input, float *output);
+
+};
+
+#endif /* INCLUDED_GRI_FFT_FILTER_FFF_GENERIC_H */
diff --git a/gnuradio-core/src/lib/filter/gri_fft_filter_fff_sse.cc b/gnuradio-core/src/lib/filter/gri_fft_filter_fff_sse.cc
new file mode 100644 (file)
index 0000000..2680e65
--- /dev/null
@@ -0,0 +1,184 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2010 Free Software Foundation, Inc.
+ * 
+ * This file is part of GNU Radio
+ * 
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ * 
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gri_fft_filter_fff_sse.h>
+#include <gri_fft.h>
+#include <assert.h>
+#include <stdexcept>
+#include <cstdio>
+#include <xmmintrin.h>
+#include <fftw3.h>
+
+gri_fft_filter_fff_sse::gri_fft_filter_fff_sse (int decimation, 
+                                                       const std::vector<float> &taps)
+  : d_fftsize(-1), d_decimation(decimation), d_fwdfft(0), d_invfft(0)
+{
+  d_xformed_taps = (gr_complex*)fftwf_malloc(1*sizeof(gr_complex));
+  set_taps(taps);
+}
+
+gri_fft_filter_fff_sse::~gri_fft_filter_fff_sse ()
+{
+  fftwf_free(d_xformed_taps);
+  delete d_fwdfft;
+  delete d_invfft;
+}
+
+/*
+ * determines d_ntaps, d_nsamples, d_fftsize, d_xformed_taps
+ */
+int
+gri_fft_filter_fff_sse::set_taps (const std::vector<float> &taps)
+{
+  int i = 0;
+  compute_sizes(taps.size());
+
+  d_tail.resize(tailsize());
+  for (i = 0; i < tailsize(); i++)
+    d_tail[i] = 0;
+
+  float *in = d_fwdfft->get_inbuf();
+  gr_complex *out = d_fwdfft->get_outbuf();
+
+  float scale = 1.0 / d_fftsize;
+  
+  // Compute forward xform of taps.
+  // Copy taps into first ntaps slots, then pad with zeros
+  for (i = 0; i < d_ntaps; i++)
+    in[i] = taps[i] * scale;
+
+  for (; i < d_fftsize; i++)
+    in[i] = 0;
+
+  d_fwdfft->execute();         // do the xform
+
+  // now copy output to d_xformed_taps
+  for (i = 0; i < d_fftsize/2+1; i++)
+    d_xformed_taps[i] = out[i];
+  
+  return d_nsamples;
+}
+
+// determine and set d_ntaps, d_nsamples, d_fftsize
+
+void
+gri_fft_filter_fff_sse::compute_sizes(int ntaps)
+{
+  int old_fftsize = d_fftsize;
+  d_ntaps = ntaps;
+  d_fftsize = (int) (2 * pow(2.0, ceil(log(ntaps) / log(2))));
+  d_nsamples = d_fftsize - d_ntaps + 1;
+
+  if (0)
+    fprintf(stderr, "gri_fft_filter_fff_sse: ntaps = %d, fftsize = %d, nsamples = %d\n",
+           d_ntaps, d_fftsize, d_nsamples);
+
+  assert(d_fftsize == d_ntaps + d_nsamples -1 );
+
+  if (d_fftsize != old_fftsize){       // compute new plans
+    delete d_fwdfft;
+    delete d_invfft;
+    d_fwdfft = new gri_fft_real_fwd(d_fftsize);
+    d_invfft = new gri_fft_real_rev(d_fftsize);
+    //d_xformed_taps.resize(d_fftsize/2+1);
+
+    fftwf_free(d_xformed_taps);
+    d_xformed_taps = (gr_complex*)fftwf_malloc((d_fftsize/2+1)*sizeof(gr_complex));
+  }
+}
+
+int
+gri_fft_filter_fff_sse::filter (int nitems, const float *input, float *output)
+{
+  int dec_ctr = 0;
+  int j = 0;
+  int ninput_items = nitems * d_decimation;
+
+  for (int i = 0; i < ninput_items; i += d_nsamples){
+    
+    memcpy(d_fwdfft->get_inbuf(), &input[i], d_nsamples * sizeof(float));
+
+    for (j = d_nsamples; j < d_fftsize; j++)
+      d_fwdfft->get_inbuf()[j] = 0;
+
+    d_fwdfft->execute();       // compute fwd xform
+
+    float *a = (float*)(d_fwdfft->get_outbuf());
+    float *b = (float*)(&d_xformed_taps[0]);
+    float *c = (float*)(d_invfft->get_inbuf());
+
+    __m128 x0, x1, x2, t0, t1, m;
+    m = _mm_set_ps(-1, 1, -1, 1);
+    for (j = 0; j < d_fftsize; j+=4) { // filter in the freq domain
+      x0 = _mm_load_ps(&a[j]);
+      t0 = _mm_load_ps(&b[j]);
+      
+      t1 = _mm_shuffle_ps(t0, t0, _MM_SHUFFLE(3, 3, 1, 1));
+      t0 = _mm_shuffle_ps(t0, t0, _MM_SHUFFLE(2, 2, 0, 0));
+      t1 = _mm_mul_ps(t1, m);
+
+      x1 = _mm_mul_ps(x0, t0);
+      x2 = _mm_mul_ps(x0, t1);
+
+      x2 = _mm_shuffle_ps(x2, x2, _MM_SHUFFLE(2, 3, 0, 1));
+      x2 = _mm_add_ps(x1, x2);
+
+      _mm_store_ps(&c[j], x2);
+    }
+    
+    // Finish off the last one; do the complex multiply as floats
+    j = d_fftsize/2;
+    c[j] = (a[j] * b[j]) - (a[j+1] * b[j+1]);
+    c[j+1] = (a[j] * b[j+1]) + (a[j+1] * b[j]);
+
+    d_invfft->execute();       // compute inv xform
+
+    // add in the overlapping tail
+
+    for (j = 0; j < tailsize(); j++)
+      d_invfft->get_outbuf()[j] += d_tail[j];
+
+    // copy nsamples to output
+
+    //memcpy(out, d_invfft->get_outbuf(), d_nsamples * sizeof(float));
+    //out += d_nsamples;
+
+    j = dec_ctr;
+    while (j < d_nsamples) {
+      *output++ = d_invfft->get_outbuf()[j];
+      j += d_decimation;
+    }
+    dec_ctr = (j - d_nsamples);
+
+    // stash the tail
+    memcpy(&d_tail[0], d_invfft->get_outbuf() + d_nsamples,
+          tailsize() * sizeof(float));
+  }
+
+  assert(dec_ctr == 0);
+
+  return nitems;
+}
diff --git a/gnuradio-core/src/lib/filter/gri_fft_filter_fff_sse.h b/gnuradio-core/src/lib/filter/gri_fft_filter_fff_sse.h
new file mode 100644 (file)
index 0000000..8258bb8
--- /dev/null
@@ -0,0 +1,81 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2010 Free Software Foundation, Inc.
+ * 
+ * This file is part of GNU Radio
+ * 
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ * 
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_GRI_FFT_FILTER_FFF_SSE_H
+#define INCLUDED_GRI_FFT_FILTER_FFF_SSE_H
+
+#include <gr_complex.h>
+#include <vector>
+
+class gri_fft_real_fwd;
+class gri_fft_real_rev;
+
+class gri_fft_filter_fff_sse
+{
+ private:
+  int                     d_ntaps;
+  int                     d_nsamples;
+  int                     d_fftsize;           // fftsize = ntaps + nsamples - 1
+  int                      d_decimation;
+  gri_fft_real_fwd       *d_fwdfft;            // forward "plan"
+  gri_fft_real_rev       *d_invfft;            // inverse "plan"
+  std::vector<float>       d_tail;             // state carried between blocks for overlap-add
+  //std::vector<gr_complex>  d_xformed_taps;   // Fourier xformed taps
+  gr_complex              *d_xformed_taps;
+  std::vector<float>      d_new_taps;
+
+
+  void compute_sizes(int ntaps);
+  int tailsize() const { return d_ntaps - 1; }
+  
+ public:
+  /*!
+   * \brief Construct a FFT filter for float vectors with the given taps and decimation rate.
+   *
+   * This is the basic implementation for performing FFT filter for fast convolution
+   * in other blocks for floating point vectors (such as gr_fft_filter_fff).
+   * \param decimation The decimation rate of the filter (int)
+   * \param taps       The filter taps (float)
+   */
+  gri_fft_filter_fff_sse (int decimation, const std::vector<float> &taps);
+  ~gri_fft_filter_fff_sse ();
+
+  /*!
+   * \brief Set new taps for the filter.
+   *
+   * Sets new taps and resets the class properties to handle different sizes
+   * \param taps       The filter taps (float)
+   */
+  int set_taps (const std::vector<float> &taps);
+  
+  /*!
+   * \brief Perform the filter operation
+   *
+   * \param nitems  The number of items to produce
+   * \param input   The input vector to be filtered
+   * \param output  The result of the filter operation
+   */
+  int filter (int nitems, const float *input, float *output);
+
+};
+
+#endif /* INCLUDED_GRI_FFT_FILTER_FFF_SSE_H */
index 030e45ddfb803f1b724540774ab9247792a0a923..7f2c468b724529107e916c0f4b7f6c476f870488 100644 (file)
@@ -53,7 +53,7 @@ gr_fll_band_edge_cc_sptr gr_make_fll_band_edge_cc (float samps_per_sym, float ro
 }
 
 
-static int ios[] = {sizeof(gr_complex), sizeof(float), sizeof(float), sizeof(float)};
+static int ios[] = {sizeof(gr_complex), sizeof(float), sizeof(float), sizeof(gr_complex)};
 static std::vector<int> iosig(ios, ios+sizeof(ios)/sizeof(int));
 gr_fll_band_edge_cc::gr_fll_band_edge_cc (float samps_per_sym, float rolloff,
                                          int filter_size, float alpha, float beta)
@@ -83,10 +83,11 @@ gr_fll_band_edge_cc::~gr_fll_band_edge_cc ()
 void
 gr_fll_band_edge_cc::set_alpha(float alpha) 
 { 
-  float eta = sqrt(2.0)/2.0;
-  float theta = alpha;
-  d_alpha = (4*eta*theta) / (1.0 + 2.0*eta*theta + theta*theta);
-  d_beta = (4*theta*theta) / (1.0 + 2.0*eta*theta + theta*theta);
+  //float eta = sqrt(2.0)/2.0;
+  //float theta = alpha;
+  //d_alpha = (4*eta*theta) / (1.0 + 2.0*eta*theta + theta*theta);
+  //d_beta = (4*theta*theta) / (1.0 + 2.0*eta*theta + theta*theta);
+  d_alpha = alpha;
 }
 
 void
@@ -160,11 +161,12 @@ gr_fll_band_edge_cc::work (int noutput_items,
   const gr_complex *in  = (const gr_complex *) input_items[0];
   gr_complex *out = (gr_complex *) output_items[0];
 
-  float *frq, *phs, *err;
+  float *frq, *phs;
+  gr_complex *err;
   if(output_items.size() > 2) {
     frq = (float *) output_items[1];
     phs = (float *) output_items[2];
-    err = (float *) output_items[3];
+    err = (gr_complex *) output_items[3];
   }
 
   if (d_updated) {
@@ -174,16 +176,17 @@ gr_fll_band_edge_cc::work (int noutput_items,
 
   int i;
   gr_complex nco_out;
-  float out_upper, out_lower;
+  gr_complex out_upper, out_lower;
   float error;
+  float avg_k = 0.1;
   for(i = 0; i < noutput_items; i++) {
     nco_out = gr_expj(d_phase);
     out[i] = in[i] * nco_out;
 
-    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.01*error + 0.99*d_error;  // average error
+    out_upper = (d_filter_upper->filter(&out[i]));
+    out_lower = (d_filter_lower->filter(&out[i]));
+    error = -real((out_upper + out_lower) * conj(out_upper - out_lower));
+    d_error = avg_k*error + avg_k*d_error;  // average error
 
     d_freq = d_freq + d_beta * d_error;
     d_phase = d_phase + d_freq + d_alpha * d_error;
index 09baf7fde88b65dd0de45d6689988d1877a3983f..178e18f3e8469313b50996a9b39d662ac4c1406c 100644 (file)
@@ -45,8 +45,12 @@ class gri_fft_complex;
  * (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 calculating the power in both the upper and lower bands and comparing them. The
- * difference in power between the filters is proportional to the frequency offset.
+ *
+ * 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
index dcc0017b3c16660fd7b238a2a106e76720d2b4ee..f0516f2fd9e808387f6b687e50556b7ccca12c0a 100644 (file)
@@ -30,6 +30,7 @@ grpython_PYTHON =                     \
        eng_notation.py                 \
        eng_option.py                   \
        modulation_utils.py             \
+       modulation_utils2.py            \
        ofdm_packet_utils.py            \
        packet_utils.py                 \
        gr_unittest.py                  \
index 68d68362363fb10a1c9c466969bf6fb01b0e9fc3..7b24fb69d75bed59643c8af4296fc7385fd65d29 100644 (file)
@@ -1,5 +1,5 @@
 #
-# Copyright 2005,2007,2009 Free Software Foundation, Inc.
+# Copyright 2005,2007,2009,2010 Free Software Foundation, Inc.
 # 
 # This file is part of GNU Radio
 # 
index 860015c3f02ab33621e576fd7b5aad9d2329741e..55e4890f309d274f3c5c5cb5f8194abb9e52cc20 100644 (file)
@@ -233,10 +233,10 @@ class dbpsk_demod(gr.hier_block2):
         arity = pow(2,self.bits_per_symbol())
 
         # Automatic gain control
-        scale = (1.0/16384.0)
-        self.pre_scaler = gr.multiply_const_cc(scale)   # scale the signal from full-range to +-1
-        #self.agc = gr.agc2_cc(0.6e-1, 1e-3, 1, 1, 100)
-        self.agc = gr.feedforward_agc_cc(16, 2.0)
+        #scale = (1.0/16384.0)
+        #self.pre_scaler = gr.multiply_const_cc(scale)   # scale the signal from full-range to +-1
+        self.agc = gr.agc2_cc(0.6e-1, 1e-3, 1, 1, 100)
+        #self.agc = gr.feedforward_agc_cc(16, 2.0)
 
         # RRC data filter
         ntaps = 11 * samples_per_symbol
@@ -288,7 +288,7 @@ class dbpsk_demod(gr.hier_block2):
             self._setup_logging()
 
         # Connect and Initialize base class
-        self.connect(self, self.pre_scaler, self.agc, self.rrc_filter, self.receiver,
+        self.connect(self, self.agc, self.rrc_filter, self.receiver,
                      self.diffdec, self.slicer, self.symbol_mapper, self.unpack, self)
 
     def samples_per_symbol(self):
index e9fb3df89874266518b2a7025fbc020a20362a39..d7bcf53907c9e619a9aa3147bb801a85bdfb8e41 100644 (file)
@@ -1,5 +1,5 @@
 #
-# Copyright 2005,2006,2007 Free Software Foundation, Inc.
+# Copyright 2009,2010 Free Software Foundation, Inc.
 # 
 # This file is part of GNU Radio
 # 
@@ -25,7 +25,7 @@
 differential BPSK modulation and demodulation.
 """
 
-from gnuradio import gr, gru, modulation_utils
+from gnuradio import gr, gru, modulation_utils2
 from math import pi, sqrt, ceil
 import psk
 import cmath
@@ -38,8 +38,8 @@ _def_gray_code = True
 _def_verbose = False
 _def_log = False
 
-_def_freq_alpha = 4e-3
-_def_costas_alpha = 0.1
+_def_freq_alpha = 0.010
+_def_phase_alpha = 0.1
 _def_timing_alpha = 0.100
 _def_timing_beta = 0.010
 _def_timing_max_dev = 1.5
@@ -83,7 +83,7 @@ class dbpsk2_mod(gr.hier_block2):
         self._excess_bw = excess_bw
         self._gray_code = gray_code
 
-        if not isinstance(self._samples_per_symbol, int) or self._samples_per_symbol < 2:
+        if self._samples_per_symbol < 2:
             raise TypeError, ("sbp must be an integer >= 2, is %d" % self._samples_per_symbol)
         
         arity = pow(2,self.bits_per_symbol())
@@ -103,7 +103,7 @@ class dbpsk2_mod(gr.hier_block2):
 
         # pulse shaping filter
         nfilts = 32
-        ntaps = nfilts * 11 * self._samples_per_symbol      # make nfilts filters of ntaps each
+        ntaps = nfilts * 11 * int(self._samples_per_symbol)    # make nfilts filters of ntaps each
         self.rrc_taps = gr.firdes.root_raised_cosine(
             nfilts,          # gain
             nfilts,          # sampling rate based on 32 filters in resampler
@@ -145,7 +145,7 @@ class dbpsk2_mod(gr.hier_block2):
         """
         Given command line options, create dictionary suitable for passing to __init__
         """
-        return modulation_utils.extract_kwargs_from_options(dbpsk2_mod.__init__,
+        return modulation_utils2.extract_kwargs_from_options(dbpsk2_mod.__init__,
                                                             ('self',), options)
     extract_kwargs_from_options=staticmethod(extract_kwargs_from_options)
 
@@ -182,7 +182,7 @@ class dbpsk2_demod(gr.hier_block2):
                  samples_per_symbol=_def_samples_per_symbol,
                  excess_bw=_def_excess_bw,
                  freq_alpha=_def_freq_alpha,
-                 costas_alpha=_def_costas_alpha,
+                 phase_alpha=_def_phase_alpha,
                  timing_alpha=_def_timing_alpha,
                  timing_max_dev=_def_timing_max_dev,
                  gray_code=_def_gray_code,
@@ -201,8 +201,8 @@ class dbpsk2_demod(gr.hier_block2):
        @type excess_bw: float
         @param freq_alpha: loop filter gain for frequency recovery
         @type freq_alpha: float
-        @param costas_alpha: loop filter gain for phase/fine frequency recovery
-        @type costas_alpha: float
+        @param phase_alpha: loop filter gain for phase/fine frequency recovery
+        @type phase_alpha: float
         @param timing_alpha: loop alpha gain for timing recovery
         @type timing_alpha: float
         @param timing_max: timing loop maximum rate deviations
@@ -226,8 +226,8 @@ class dbpsk2_demod(gr.hier_block2):
         self._samples_per_symbol = samples_per_symbol
         self._excess_bw = excess_bw
         self._freq_alpha = freq_alpha
-        self._freq_beta = 0.25*self._freq_alpha**2
-        self._costas_alpha = costas_alpha
+        self._freq_beta = 0.10*self._freq_alpha
+        self._phase_alpha = phase_alpha
         self._timing_alpha = timing_alpha
         self._timing_beta = _def_timing_beta
         self._timing_max_dev=timing_max_dev
@@ -259,13 +259,13 @@ class dbpsk2_demod(gr.hier_block2):
         self.time_recov.set_beta(self._timing_beta)
 
         # Perform phase / fine frequency correction
-        self._costas_beta  = 0.25 * self._costas_alpha * self._costas_alpha
+        self._phase_beta  = 0.25 * self._phase_alpha * self._phase_alpha
         # Allow a frequency swing of +/- half of the sample rate
         fmin = -0.5
         fmax = 0.5
         
-        self.phase_recov = gr.costas_loop_cc(self._costas_alpha,
-                                             self._costas_beta,
+        self.phase_recov = gr.costas_loop_cc(self._phase_alpha,
+                                             self._phase_beta,
                                              fmax, fmin, arity)
 
         # Do differential decoding based on phase change of symbols
@@ -308,29 +308,27 @@ class dbpsk2_demod(gr.hier_block2):
         print "bits per symbol:     %d"   % self.bits_per_symbol()
         print "Gray code:           %s"   % self._gray_code
         print "RRC roll-off factor: %.2f" % self._excess_bw
-        print "FLL gain:            %.2f" % self._freq_alpha
-        print "Costas Loop alpha:   %.2f" % self._costas_alpha
-        print "Costas Loop beta:    %.2f" % self._costas_beta
-        print "Timing alpha gain:   %.2f" % self._timing_alpha
-        print "Timing beta gain:    %.2f" % self._timing_beta
+        print "FLL gain:            %.2e" % self._freq_alpha
+        print "Timing alpha gain:   %.2e" % self._timing_alpha
+        print "Timing beta gain:    %.2e" % self._timing_beta
         print "Timing max dev:      %.2f" % self._timing_max_dev
+        print "Phase track alpha:   %.2e" % self._phase_alpha
+        print "Phase track beta:    %.2e" % self._phase_beta
 
     def _setup_logging(self):
         print "Modulation logging turned on."
-        self.connect(self.pre_scaler,
-                         gr.file_sink(gr.sizeof_gr_complex, "rx_prescaler.dat"))
         self.connect(self.agc,
                      gr.file_sink(gr.sizeof_gr_complex, "rx_agc.dat"))
-        self.connect(self.rrc_filter,
-                     gr.file_sink(gr.sizeof_gr_complex, "rx_rrc_filter.dat"))
-        self.connect(self.clock_recov,
-                     gr.file_sink(gr.sizeof_gr_complex, "rx_clock_recov.dat"))
+        self.connect(self.freq_recov,
+                     gr.file_sink(gr.sizeof_gr_complex, "rx_freq_recov.dat"))
         self.connect(self.time_recov,
                      gr.file_sink(gr.sizeof_gr_complex, "rx_time_recov.dat"))
+        self.connect(self.phase_recov,
+                     gr.file_sink(gr.sizeof_gr_complex, "rx_phase_recov.dat"))
         self.connect(self.diffdec,
                      gr.file_sink(gr.sizeof_gr_complex, "rx_diffdec.dat"))        
         self.connect(self.slicer,
-                    gr.file_sink(gr.sizeof_char, "rx_slicer.dat"))
+                     gr.file_sink(gr.sizeof_char, "rx_slicer.dat"))
         self.connect(self.symbol_mapper,
                      gr.file_sink(gr.sizeof_char, "rx_symbol_mapper.dat"))
         self.connect(self.unpack,
@@ -347,11 +345,11 @@ class dbpsk2_demod(gr.hier_block2):
                           help="disable gray coding on modulated bits (PSK)")
         parser.add_option("", "--freq-alpha", type="float", default=_def_freq_alpha,
                           help="set frequency lock loop alpha gain value [default=%default] (PSK)")
-        parser.add_option("", "--costas-alpha", type="float", default=None,
-                          help="set Costas loop alpha value [default=%default] (PSK)")
-        parser.add_option("", "--gain-alpha", type="float", default=_def_timing_alpha,
+        parser.add_option("", "--phase-alpha", type="float", default=_def_phase_alpha,
+                          help="set phase tracking loop alpha value [default=%default] (PSK)")
+        parser.add_option("", "--timing-alpha", type="float", default=_def_timing_alpha,
                           help="set timing symbol sync loop gain alpha value [default=%default] (GMSK/PSK)")
-        parser.add_option("", "--gain-beta", type="float", default=_def_timing_beta,
+        parser.add_option("", "--timing-beta", type="float", default=_def_timing_beta,
                           help="set timing symbol sync loop gain beta value [default=%default] (GMSK/PSK)")
         parser.add_option("", "--timing-max-dev", type="float", default=_def_timing_max_dev,
                           help="set timing symbol sync loop maximum deviation [default=%default] (GMSK/PSK)")
@@ -361,11 +359,11 @@ class dbpsk2_demod(gr.hier_block2):
         """
         Given command line options, create dictionary suitable for passing to __init__
         """
-        return modulation_utils.extract_kwargs_from_options(
+        return modulation_utils2.extract_kwargs_from_options(
                  dbpsk2_demod.__init__, ('self',), options)
     extract_kwargs_from_options=staticmethod(extract_kwargs_from_options)
 #
 # Add these to the mod/demod registry
 #
-modulation_utils.add_type_1_mod('dbpsk2', dbpsk2_mod)
-modulation_utils.add_type_1_demod('dbpsk2', dbpsk2_demod)
+modulation_utils2.add_type_1_mod('dbpsk2', dbpsk2_mod)
+modulation_utils2.add_type_1_demod('dbpsk2', dbpsk2_demod)
index 9fae6accac07c14cf5aff158d8b6f2dde0bbbd22..e1e627707becb0d7c6465b1a1b53acce7ebe13cb 100644 (file)
@@ -1,5 +1,5 @@
 #
-# Copyright 2005,2006,2007,2009 Free Software Foundation, Inc.
+# Copyright 2009,2010 Free Software Foundation, Inc.
 # 
 # This file is part of GNU Radio
 # 
@@ -25,7 +25,7 @@
 differential QPSK modulation and demodulation.
 """
 
-from gnuradio import gr, gru, modulation_utils
+from gnuradio import gr, gru, modulation_utils2
 from math import pi, sqrt
 import psk
 import cmath
@@ -38,8 +38,8 @@ _def_gray_code = True
 _def_verbose = False
 _def_log = False
 
-_def_freq_alpha = 4e-3
-_def_costas_alpha = 0.01
+_def_freq_alpha = 0.010
+_def_phase_alpha = 0.01
 _def_timing_alpha = 0.100
 _def_timing_beta = 0.010
 _def_timing_max_dev = 1.5
@@ -83,8 +83,8 @@ class dqpsk2_mod(gr.hier_block2):
         self._excess_bw = excess_bw
         self._gray_code = gray_code
 
-        if not isinstance(samples_per_symbol, int) or samples_per_symbol < 2:
-            raise TypeError, ("sbp must be an integer >= 2, is %d" % samples_per_symbol)
+        if samples_per_symbol < 2:
+            raise TypeError, ("sbp must be >= 2, is %f" % samples_per_symbol)
 
        ntaps = 11 * samples_per_symbol
  
@@ -107,7 +107,7 @@ class dqpsk2_mod(gr.hier_block2):
 
         # pulse shaping filter
         nfilts = 32
-        ntaps = nfilts * 11 * self._samples_per_symbol      # make nfilts filters of ntaps each
+        ntaps = 11 * int(nfilts * self._samples_per_symbol)  # make nfilts filters of ntaps each
         self.rrc_taps = gr.firdes.root_raised_cosine(
             nfilts,          # gain
             nfilts,          # sampling rate based on 32 filters in resampler
@@ -168,7 +168,7 @@ class dqpsk2_mod(gr.hier_block2):
         """
         Given command line options, create dictionary suitable for passing to __init__
         """
-        return modulation_utils.extract_kwargs_from_options(dqpsk2_mod.__init__,
+        return modulation_utils2.extract_kwargs_from_options(dqpsk2_mod.__init__,
                                                             ('self',), options)
     extract_kwargs_from_options=staticmethod(extract_kwargs_from_options)
 
@@ -185,7 +185,7 @@ class dqpsk2_demod(gr.hier_block2):
                  samples_per_symbol=_def_samples_per_symbol,
                  excess_bw=_def_excess_bw,
                  freq_alpha=_def_freq_alpha,
-                 costas_alpha=_def_costas_alpha,
+                 phase_alpha=_def_phase_alpha,
                  timing_alpha=_def_timing_alpha,
                  timing_max_dev=_def_timing_max_dev,
                  gray_code=_def_gray_code,
@@ -204,8 +204,8 @@ class dqpsk2_demod(gr.hier_block2):
        @type excess_bw: float
         @param freq_alpha: loop filter gain for frequency recovery
         @type freq_alpha: float
-        @param costas_alpha: loop filter gain
-        @type costas_alphas: float
+        @param phase_alpha: loop filter gain
+        @type phase_alphas: float
         @param timing_alpha: timing loop alpha gain
         @type timing_alpha: float
         @param timing_max: timing loop maximum rate deviations
@@ -230,7 +230,7 @@ class dqpsk2_demod(gr.hier_block2):
         self._excess_bw = excess_bw
         self._freq_alpha = freq_alpha
         self._freq_beta = 0.25*self._freq_alpha**2
-        self._costas_alpha = costas_alpha
+        self._phase_alpha = phase_alpha
         self._timing_alpha = timing_alpha
         self._timing_beta = _def_timing_beta
         self._timing_max_dev=timing_max_dev
@@ -264,13 +264,13 @@ class dqpsk2_demod(gr.hier_block2):
         
 
         # Perform phase / fine frequency correction
-        self._costas_beta  = 0.25 * self._costas_alpha * self._costas_alpha
+        self._phase_beta  = 0.25 * self._phase_alpha * self._phase_alpha
         # Allow a frequency swing of +/- half of the sample rate
         fmin = -0.5
         fmax = 0.5
 
-        self.phase_recov = gr.costas_loop_cc(self._costas_alpha,
-                                             self._costas_beta,
+        self.phase_recov = gr.costas_loop_cc(self._phase_alpha,
+                                             self._phase_beta,
                                              fmax, fmin, arity)
 
 
@@ -315,24 +315,22 @@ class dqpsk2_demod(gr.hier_block2):
         print "Gray code:           %s"   % self._gray_code
         print "RRC roll-off factor: %.2f" % self._excess_bw
         print "FLL gain:            %.2f" % self._freq_alpha
-        print "Costas Loop alpha:   %.2e" % self._costas_alpha
-        print "Costas Loop beta:    %.2e" % self._costas_beta
         print "Timing alpha gain:   %.2f" % self._timing_alpha
         print "Timing beta gain:    %.2f" % self._timing_beta
         print "Timing max dev:      %.2f" % self._timing_max_dev
+        print "Phase track alpha:   %.2e" % self._phase_alpha
+        print "Phase track beta:    %.2e" % self._phase_beta
 
     def _setup_logging(self):
         print "Modulation logging turned on."
-        self.connect(self.pre_scaler,
-                     gr.file_sink(gr.sizeof_gr_complex, "rx_prescaler.dat"))
         self.connect(self.agc,
                      gr.file_sink(gr.sizeof_gr_complex, "rx_agc.dat"))
-        self.connect(self.rrc_filter,
-                     gr.file_sink(gr.sizeof_gr_complex, "rx_rrc_filter.dat"))
-        self.connect(self.clock_recov,
-                     gr.file_sink(gr.sizeof_gr_complex, "rx_clock_recov.dat"))
+        self.connect(self.freq_recov,
+                     gr.file_sink(gr.sizeof_gr_complex, "rx_freq_recov.dat"))
         self.connect(self.time_recov,
                      gr.file_sink(gr.sizeof_gr_complex, "rx_time_recov.dat"))
+        self.connect(self.phase_recov,
+                     gr.file_sink(gr.sizeof_gr_complex, "rx_phase_recov.dat"))
         self.connect(self.diffdec,
                      gr.file_sink(gr.sizeof_gr_complex, "rx_diffdec.dat"))        
         self.connect(self.slicer,
@@ -344,7 +342,7 @@ class dqpsk2_demod(gr.hier_block2):
 
     def add_options(parser):
         """
-        Adds modulation-specific options to the standard parser
+        Adds DQPSK demodulation-specific options to the standard parser
         """
         parser.add_option("", "--excess-bw", type="float", default=_def_excess_bw,
                           help="set RRC excess bandwith factor [default=%default] (PSK)")
@@ -353,11 +351,11 @@ class dqpsk2_demod(gr.hier_block2):
                           help="disable gray coding on modulated bits (PSK)")
         parser.add_option("", "--freq-alpha", type="float", default=_def_freq_alpha,
                           help="set frequency lock loop alpha gain value [default=%default] (PSK)")
-        parser.add_option("", "--costas-alpha", type="float", default=_def_costas_alpha,
-                          help="set Costas loop alpha value [default=%default] (PSK)")
-        parser.add_option("", "--gain-alpha", type="float", default=_def_timing_alpha,
+        parser.add_option("", "--phase-alpha", type="float", default=_def_phase_alpha,
+                          help="set phase tracking loop alpha value [default=%default] (PSK)")
+        parser.add_option("", "--timing-alpha", type="float", default=_def_timing_alpha,
                           help="set timing symbol sync loop gain alpha value [default=%default] (GMSK/PSK)")
-        parser.add_option("", "--gain-beta", type="float", default=_def_timing_beta,
+        parser.add_option("", "--timing-beta", type="float", default=_def_timing_beta,
                           help="set timing symbol sync loop gain beta value [default=%default] (GMSK/PSK)")
         parser.add_option("", "--timing-max-dev", type="float", default=_def_timing_max_dev,
                           help="set timing symbol sync loop maximum deviation [default=%default] (GMSK/PSK)")
@@ -367,7 +365,7 @@ class dqpsk2_demod(gr.hier_block2):
         """
         Given command line options, create dictionary suitable for passing to __init__
         """
-        return modulation_utils.extract_kwargs_from_options(
+        return modulation_utils2.extract_kwargs_from_options(
             dqpsk2_demod.__init__, ('self',), options)
     extract_kwargs_from_options=staticmethod(extract_kwargs_from_options)
 
@@ -375,5 +373,5 @@ class dqpsk2_demod(gr.hier_block2):
 #
 # Add these to the mod/demod registry
 #
-modulation_utils.add_type_1_mod('dqpsk2', dqpsk2_mod)
-modulation_utils.add_type_1_demod('dqpsk2', dqpsk2_demod)
+modulation_utils2.add_type_1_mod('dqpsk2', dqpsk2_mod)
+modulation_utils2.add_type_1_demod('dqpsk2', dqpsk2_demod)
diff --git a/gnuradio-core/src/python/gnuradio/modulation_utils2.py b/gnuradio-core/src/python/gnuradio/modulation_utils2.py
new file mode 100644 (file)
index 0000000..c5dba3e
--- /dev/null
@@ -0,0 +1,81 @@
+#
+# Copyright 2010 Free Software Foundation, Inc.
+# 
+# This file is part of GNU Radio
+# 
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+# 
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+
+"""
+Miscellaneous utilities for managing mods and demods, as well as other items
+useful in dealing with generalized handling of different modulations and demods.
+"""
+
+import inspect
+
+
+# Type 1 modulators accept a stream of bytes on their input and produce complex baseband output
+_type_1_modulators = {}
+
+def type_1_mods():
+    return _type_1_modulators
+
+def add_type_1_mod(name, mod_class):
+    _type_1_modulators[name] = mod_class
+
+
+# Type 1 demodulators accept complex baseband input and produce a stream of bits, packed
+# 1 bit / byte as their output.  Their output is completely unambiguous.  There is no need
+# to resolve phase or polarity ambiguities.
+_type_1_demodulators = {}
+
+def type_1_demods():
+    return _type_1_demodulators
+
+def add_type_1_demod(name, demod_class):
+    _type_1_demodulators[name] = demod_class
+
+
+def extract_kwargs_from_options(function, excluded_args, options):
+    """
+    Given a function, a list of excluded arguments and the result of
+    parsing command line options, create a dictionary of key word
+    arguments suitable for passing to the function.  The dictionary
+    will be populated with key/value pairs where the keys are those
+    that are common to the function's argument list (minus the
+    excluded_args) and the attributes in options.  The values are the
+    corresponding values from options unless that value is None.
+    In that case, the corresponding dictionary entry is not populated.
+
+    (This allows different modulations that have the same parameter
+    names, but different default values to coexist.  The downside is
+    that --help in the option parser will list the default as None,
+    but in that case the default provided in the __init__ argument
+    list will be used since there is no kwargs entry.)
+
+    @param function: the function whose parameter list will be examined
+    @param excluded_args: function arguments that are NOT to be added to the dictionary
+    @type excluded_args: sequence of strings
+    @param options: result of command argument parsing
+    @type options: optparse.Values
+    """
+    # Try this in C++ ;)
+    args, varargs, varkw, defaults = inspect.getargspec(function)
+    d = {}
+    for kw in [a for a in args if a not in excluded_args]:
+        if hasattr(options, kw):
+            if getattr(options, kw) is not None:
+                d[kw] = getattr(options, kw)
+    return d
index 1417c17fa5b1d731a70bd07571040b66b710d5ed..e36b05413e1137b0a814eedd8dae635210d9336c 100644 (file)
@@ -143,7 +143,7 @@ def make_packet(payload, samples_per_symbol, bits_per_symbol,
                        (payload_with_crc), '\x55'))
 
     if pad_for_usrp:
-        pkt = pkt + (_npadding_bytes(len(pkt), samples_per_symbol, bits_per_symbol) * '\x55')
+        pkt = pkt + (_npadding_bytes(len(pkt), int(samples_per_symbol), bits_per_symbol) * '\x55')
 
     #print "make_packet: len(pkt) =", len(pkt)
     return pkt
index 37ee8123eb084e212510c5768769e79584ba61a3..36037febb0b6c3156343a0869422ae85a7bed224 100644 (file)
@@ -1,6 +1,6 @@
 <?xml version='1.0' encoding='ASCII'?>
 <flow_graph>
-  <timestamp>Fri Jan 29 18:10:00 2010</timestamp>
+  <timestamp>Sat Mar  6 17:17:12 2010</timestamp>
   <block>
     <key>options</key>
     <param>
     </param>
   </block>
   <block>
-    <key>variable_slider</key>
+    <key>root_raised_cosine_filter</key>
     <param>
       <key>id</key>
-      <value>alpha</value>
+      <value>root_raised_cosine_filter_0</value>
     </param>
     <param>
       <key>_enabled</key>
       <value>True</value>
     </param>
     <param>
-      <key>label</key>
-      <value>Freq Alpha</value>
-    </param>
-    <param>
-      <key>value</key>
-      <value>0</value>
+      <key>type</key>
+      <value>interp_fir_filter_ccf</value>
     </param>
     <param>
-      <key>min</key>
-      <value>0</value>
+      <key>decim</key>
+      <value>1</value>
     </param>
     <param>
-      <key>max</key>
-      <value>0.001</value>
+      <key>interp</key>
+      <value>spb_gen</value>
     </param>
     <param>
-      <key>num_steps</key>
-      <value>1000</value>
+      <key>gain</key>
+      <value>2*spb_gen</value>
     </param>
     <param>
-      <key>style</key>
-      <value>wx.SL_HORIZONTAL</value>
+      <key>samp_rate</key>
+      <value>1.0</value>
     </param>
     <param>
-      <key>converver</key>
-      <value>float_converter</value>
+      <key>sym_rate</key>
+      <value>1./spb_gen</value>
     </param>
     <param>
-      <key>grid_pos</key>
-      <value></value>
+      <key>alpha</key>
+      <value>rolloff</value>
     </param>
     <param>
-      <key>notebook</key>
-      <value></value>
+      <key>ntaps</key>
+      <value>44</value>
     </param>
     <param>
       <key>_coordinate</key>
-      <value>(552, 4)</value>
+      <value>(978, 157)</value>
     </param>
     <param>
       <key>_rotation</key>
     </param>
   </block>
   <block>
-    <key>variable_slider</key>
+    <key>gr_fll_band_edge_cc</key>
     <param>
       <key>id</key>
-      <value>beta</value>
+      <value>gr_fll_band_edge_cc_0</value>
     </param>
     <param>
       <key>_enabled</key>
       <value>True</value>
     </param>
     <param>
-      <key>label</key>
-      <value>Freq Beta</value>
-    </param>
-    <param>
-      <key>value</key>
-      <value>0</value>
-    </param>
-    <param>
-      <key>min</key>
-      <value>0.0</value>
-    </param>
-    <param>
-      <key>max</key>
-      <value>0.0001</value>
+      <key>type</key>
+      <value>cc</value>
     </param>
     <param>
-      <key>num_steps</key>
-      <value>1000</value>
+      <key>samps_per_sym</key>
+      <value>spb_gen</value>
     </param>
     <param>
-      <key>style</key>
-      <value>wx.SL_HORIZONTAL</value>
+      <key>rolloff</key>
+      <value>rolloff</value>
     </param>
     <param>
-      <key>converver</key>
-      <value>float_converter</value>
+      <key>filter_size</key>
+      <value>44</value>
     </param>
     <param>
-      <key>grid_pos</key>
-      <value></value>
+      <key>alpha</key>
+      <value>alpha</value>
     </param>
     <param>
-      <key>notebook</key>
-      <value></value>
+      <key>beta</key>
+      <value>beta</value>
     </param>
     <param>
       <key>_coordinate</key>
-      <value>(668, 5)</value>
+      <value>(874, 664)</value>
     </param>
     <param>
       <key>_rotation</key>
-      <value>180</value>
+      <value>0</value>
     </param>
   </block>
   <block>
-    <key>root_raised_cosine_filter</key>
+    <key>gr_channel_model</key>
     <param>
       <key>id</key>
-      <value>root_raised_cosine_filter_0</value>
+      <value>gr_channel_model_0</value>
     </param>
     <param>
       <key>_enabled</key>
       <value>True</value>
     </param>
     <param>
-      <key>type</key>
-      <value>interp_fir_filter_ccf</value>
-    </param>
-    <param>
-      <key>decim</key>
-      <value>1</value>
-    </param>
-    <param>
-      <key>interp</key>
-      <value>spb_gen</value>
+      <key>noise_voltage</key>
+      <value>noise_amp</value>
     </param>
     <param>
-      <key>gain</key>
-      <value>2*spb_gen</value>
+      <key>freq_offset</key>
+      <value>freq_offset</value>
     </param>
     <param>
-      <key>samp_rate</key>
+      <key>epsilon</key>
       <value>1.0</value>
     </param>
     <param>
-      <key>sym_rate</key>
-      <value>1./spb_gen</value>
-    </param>
-    <param>
-      <key>alpha</key>
-      <value>rolloff</value>
+      <key>taps</key>
+      <value>1.0</value>
     </param>
     <param>
-      <key>ntaps</key>
-      <value>44</value>
+      <key>seed</key>
+      <value>42</value>
     </param>
     <param>
       <key>_coordinate</key>
-      <value>(978, 157)</value>
+      <value>(618, 376)</value>
     </param>
     <param>
       <key>_rotation</key>
     </param>
   </block>
   <block>
-    <key>gr_fll_band_edge_cc</key>
+    <key>variable_slider</key>
     <param>
       <key>id</key>
-      <value>gr_fll_band_edge_cc_0</value>
+      <value>beta</value>
     </param>
     <param>
       <key>_enabled</key>
       <value>True</value>
     </param>
     <param>
-      <key>type</key>
-      <value>cc</value>
+      <key>label</key>
+      <value>Freq Beta</value>
     </param>
     <param>
-      <key>samps_per_sym</key>
-      <value>spb_gen</value>
+      <key>value</key>
+      <value>0</value>
     </param>
     <param>
-      <key>rolloff</key>
-      <value>rolloff</value>
+      <key>min</key>
+      <value>0.0</value>
     </param>
     <param>
-      <key>filter_size</key>
-      <value>44</value>
+      <key>max</key>
+      <value>0.01</value>
     </param>
     <param>
-      <key>alpha</key>
-      <value>alpha</value>
+      <key>num_steps</key>
+      <value>1000</value>
     </param>
     <param>
-      <key>beta</key>
-      <value>beta</value>
+      <key>style</key>
+      <value>wx.SL_HORIZONTAL</value>
+    </param>
+    <param>
+      <key>converver</key>
+      <value>float_converter</value>
+    </param>
+    <param>
+      <key>grid_pos</key>
+      <value></value>
+    </param>
+    <param>
+      <key>notebook</key>
+      <value></value>
     </param>
     <param>
       <key>_coordinate</key>
-      <value>(874, 664)</value>
+      <value>(668, 5)</value>
     </param>
     <param>
       <key>_rotation</key>
-      <value>0</value>
+      <value>180</value>
     </param>
   </block>
   <block>
-    <key>gr_channel_model</key>
+    <key>variable_slider</key>
     <param>
       <key>id</key>
-      <value>gr_channel_model_0</value>
+      <value>alpha</value>
     </param>
     <param>
       <key>_enabled</key>
       <value>True</value>
     </param>
     <param>
-      <key>noise_voltage</key>
-      <value>noise_amp</value>
+      <key>label</key>
+      <value>Freq Alpha</value>
     </param>
     <param>
-      <key>freq_offset</key>
-      <value>freq_offset</value>
+      <key>value</key>
+      <value>0</value>
     </param>
     <param>
-      <key>epsilon</key>
-      <value>1.0</value>
+      <key>min</key>
+      <value>0</value>
     </param>
     <param>
-      <key>taps</key>
-      <value>1.0</value>
+      <key>max</key>
+      <value>0.1</value>
     </param>
     <param>
-      <key>seed</key>
-      <value>42</value>
+      <key>num_steps</key>
+      <value>1000</value>
+    </param>
+    <param>
+      <key>style</key>
+      <value>wx.SL_HORIZONTAL</value>
+    </param>
+    <param>
+      <key>converver</key>
+      <value>float_converter</value>
+    </param>
+    <param>
+      <key>grid_pos</key>
+      <value></value>
+    </param>
+    <param>
+      <key>notebook</key>
+      <value></value>
     </param>
     <param>
       <key>_coordinate</key>
-      <value>(618, 376)</value>
+      <value>(552, 4)</value>
     </param>
     <param>
       <key>_rotation</key>
index 80a7aef0c668c1a67ea67cc7dd1d67c9b48c5222..8571995a582f95bfc71339bc971b76171b78b133 100644 (file)
@@ -1,6 +1,6 @@
 <?xml version='1.0' encoding='ASCII'?>
 <flow_graph>
-  <timestamp>Mon Feb  1 18:58:32 2010</timestamp>
+  <timestamp>Sat Mar  6 17:17:22 2010</timestamp>
   <block>
     <key>options</key>
     <param>
       <value>0</value>
     </param>
   </block>
-  <block>
-    <key>variable_slider</key>
-    <param>
-      <key>id</key>
-      <value>freq_beta</value>
-    </param>
-    <param>
-      <key>_enabled</key>
-      <value>True</value>
-    </param>
-    <param>
-      <key>label</key>
-      <value>Freq Beta</value>
-    </param>
-    <param>
-      <key>value</key>
-      <value>0</value>
-    </param>
-    <param>
-      <key>min</key>
-      <value>0.0</value>
-    </param>
-    <param>
-      <key>max</key>
-      <value>0.0001</value>
-    </param>
-    <param>
-      <key>num_steps</key>
-      <value>1000</value>
-    </param>
-    <param>
-      <key>style</key>
-      <value>wx.SL_HORIZONTAL</value>
-    </param>
-    <param>
-      <key>converver</key>
-      <value>float_converter</value>
-    </param>
-    <param>
-      <key>grid_pos</key>
-      <value></value>
-    </param>
-    <param>
-      <key>notebook</key>
-      <value></value>
-    </param>
-    <param>
-      <key>_coordinate</key>
-      <value>(836, 9)</value>
-    </param>
-    <param>
-      <key>_rotation</key>
-      <value>180</value>
-    </param>
-  </block>
-  <block>
-    <key>variable_slider</key>
-    <param>
-      <key>id</key>
-      <value>freq_alpha</value>
-    </param>
-    <param>
-      <key>_enabled</key>
-      <value>True</value>
-    </param>
-    <param>
-      <key>label</key>
-      <value>Freq Alpha</value>
-    </param>
-    <param>
-      <key>value</key>
-      <value>0</value>
-    </param>
-    <param>
-      <key>min</key>
-      <value>0</value>
-    </param>
-    <param>
-      <key>max</key>
-      <value>0.001</value>
-    </param>
-    <param>
-      <key>num_steps</key>
-      <value>1000</value>
-    </param>
-    <param>
-      <key>style</key>
-      <value>wx.SL_HORIZONTAL</value>
-    </param>
-    <param>
-      <key>converver</key>
-      <value>float_converter</value>
-    </param>
-    <param>
-      <key>grid_pos</key>
-      <value></value>
-    </param>
-    <param>
-      <key>notebook</key>
-      <value></value>
-    </param>
-    <param>
-      <key>_coordinate</key>
-      <value>(734, 10)</value>
-    </param>
-    <param>
-      <key>_rotation</key>
-      <value>0</value>
-    </param>
-  </block>
   <block>
     <key>variable_slider</key>
     <param>
       <value>0</value>
     </param>
   </block>
+  <block>
+    <key>variable_slider</key>
+    <param>
+      <key>id</key>
+      <value>freq_alpha</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>label</key>
+      <value>Freq Alpha</value>
+    </param>
+    <param>
+      <key>value</key>
+      <value>0</value>
+    </param>
+    <param>
+      <key>min</key>
+      <value>0</value>
+    </param>
+    <param>
+      <key>max</key>
+      <value>0.1</value>
+    </param>
+    <param>
+      <key>num_steps</key>
+      <value>1000</value>
+    </param>
+    <param>
+      <key>style</key>
+      <value>wx.SL_HORIZONTAL</value>
+    </param>
+    <param>
+      <key>converver</key>
+      <value>float_converter</value>
+    </param>
+    <param>
+      <key>grid_pos</key>
+      <value></value>
+    </param>
+    <param>
+      <key>notebook</key>
+      <value></value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(734, 10)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>variable_slider</key>
+    <param>
+      <key>id</key>
+      <value>freq_beta</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>label</key>
+      <value>Freq Beta</value>
+    </param>
+    <param>
+      <key>value</key>
+      <value>0</value>
+    </param>
+    <param>
+      <key>min</key>
+      <value>0.0</value>
+    </param>
+    <param>
+      <key>max</key>
+      <value>0.01</value>
+    </param>
+    <param>
+      <key>num_steps</key>
+      <value>1000</value>
+    </param>
+    <param>
+      <key>style</key>
+      <value>wx.SL_HORIZONTAL</value>
+    </param>
+    <param>
+      <key>converver</key>
+      <value>float_converter</value>
+    </param>
+    <param>
+      <key>grid_pos</key>
+      <value></value>
+    </param>
+    <param>
+      <key>notebook</key>
+      <value></value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(836, 9)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>180</value>
+    </param>
+  </block>
   <connection>
     <source_block_id>random_source_x_0</source_block_id>
     <sink_block_id>gr_uchar_to_float_0</sink_block_id>
index 4cc4a7bee3698f1a14ae36706ce9c37307dd6ef7..47e4f20288a91e23ba5b57fbf7638b2dc217bc0f 100755 (executable)
@@ -44,6 +44,11 @@ class my_top_block(gr.top_block):
         noise_power = power_in_signal/SNR
         noise_voltage = math.sqrt(noise_power)
 
+        # With new interface, sps does not get set by default, but
+        # in the loopback, we don't recalculate it; so just force it here
+        if(options.samples_per_symbol == None):
+            options.samples_per_symbol = 2
+
         self.txpath = transmit_path(mod_class, options)
         self.throttle = gr.throttle(gr.sizeof_gr_complex, options.sample_rate)
         self.rxpath = receive_path(demod_class, rx_callback, options)
index 1cb95198e67d527c5cee6709dc2d35ab2b83e4c9..56c6c7f52e22f8dd2493c339938ff4641366cdbb 100755 (executable)
@@ -1,6 +1,26 @@
 #!/usr/bin/env python
-
-from gnuradio import gr, gru, modulation_utils
+#
+# Copyright 2010 Free Software Foundation, Inc.
+# 
+# This file is part of GNU Radio
+# 
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+# 
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING.  If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+# 
+
+from gnuradio import gr, gru, modulation_utils2
 from gnuradio import eng_notation
 from gnuradio.eng_option import eng_option
 from optparse import OptionParser
@@ -223,6 +243,11 @@ class my_top_block(gr.top_block):
 
         self._noise_voltage = self.get_noise_voltage(self._snr_dB)
 
+        # With new interface, sps does not get set by default, but
+        # in the loopback, we don't recalculate it; so just force it here
+        if(options.samples_per_symbol == None):
+            options.samples_per_symbol = 2
+
         self.txpath = transmit_path(mod_class, options)
         self.throttle = gr.throttle(gr.sizeof_gr_complex, self.sample_rate())
         self.rxpath = receive_path(demod_class, rx_callback, options)
@@ -269,6 +294,7 @@ class my_top_block(gr.top_block):
                 self.phase_recov = self.rxpath.packet_receiver._demodulator.phase_recov
                 self.time_recov = self.rxpath.packet_receiver._demodulator.time_recov
                 self.freq_recov.set_alpha(self._gain_freq)
+                self.freq_recov.set_beta(self._gain_freq/10.0)
                 self.phase_recov.set_alpha(self._gain_phase)
                 self.phase_recov.set_beta(0.25*self._gain_phase*self._gain_phase)
                 self.time_recov.set_alpha(self._gain_clock)
@@ -367,6 +393,7 @@ class my_top_block(gr.top_block):
         self._gain_freq = gain_freq
         #self._gain_freq_beta = .25 * self._gain_freq * self._gain_freq
         self.rxpath.packet_receiver._demodulator.freq_recov.set_alpha(self._gain_freq)
+        self.rxpath.packet_receiver._demodulator.freq_recov.set_beta(self._gain_freq/10.0)
         #self.rxpath.packet_receiver._demodulator.freq_recov.set_beta(self._gain_fre_beta)
 
 
@@ -431,15 +458,15 @@ def main():
     def send_pkt(payload='', eof=False):
         return tb.txpath.send_pkt(payload, eof)
 
-    mods = modulation_utils.type_1_mods()
-    demods = modulation_utils.type_1_demods()
+    mods = modulation_utils2.type_1_mods()
+    demods = modulation_utils2.type_1_demods()
 
     parser = OptionParser(option_class=eng_option, conflict_handler="resolve")
     expert_grp = parser.add_option_group("Expert")
     channel_grp = parser.add_option_group("Channel")
 
     parser.add_option("-m", "--modulation", type="choice", choices=mods.keys(),
-                      default='dbpsk',
+                      default='dbpsk2',
                       help="Select modulation from: %s [default=%%default]"
                             % (', '.join(mods.keys()),))
 
index cabbecb6ffa6d428b82eeededdf7d6ec8614fc55..0c37f4c6a8d00d4447614b200c94d2d5d2733607 100755 (executable)
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 #
-# Copyright 2005,2006,2007,2009 Free Software Foundation, Inc.
+# Copyright 2010 Free Software Foundation, Inc.
 # 
 # This file is part of GNU Radio
 # 
@@ -20,7 +20,7 @@
 # Boston, MA 02110-1301, USA.
 # 
 
-from gnuradio import gr, gru, modulation_utils
+from gnuradio import gr, gru, modulation_utils2
 from gnuradio import usrp
 from gnuradio import eng_notation
 from gnuradio.eng_option import eng_option
@@ -33,7 +33,7 @@ import sys
 
 # from current dir
 from receive_path import receive_path
-from pick_bitrate import pick_rx_bitrate
+from pick_bitrate2 import pick_rx_bitrate
 
 try:
     from gnuradio.qtgui import qtgui
@@ -219,7 +219,7 @@ class my_top_block(gr.top_block):
 
         # FIXME: do better exposure to lower issues for control
         self._gain_clock = self.rxpath.packet_receiver._demodulator._timing_alpha
-        self._gain_phase = self.rxpath.packet_receiver._demodulator._costas_alpha
+        self._gain_phase = self.rxpath.packet_receiver._demodulator._phase_alpha
         self._gain_freq  = self.rxpath.packet_receiver._demodulator._freq_alpha
 
         self.connect(self.u, self.rxpath)
@@ -242,8 +242,8 @@ class my_top_block(gr.top_block):
             
             # Connect to the QT sinks
             # FIXME: make better exposure to receiver from rxpath
-            #self.receiver = self.rxpath.packet_receiver._demodulator.phase_recov
-            self.receiver = self.rxpath.packet_receiver._demodulator.freq_recov
+            self.receiver = self.rxpath.packet_receiver._demodulator.phase_recov
+            #self.receiver = self.rxpath.packet_receiver._demodulator.freq_recov
             self.connect(self.u, self.snk_rxin)
             self.connect(self.receiver, self.snk_rx)
             
@@ -267,9 +267,9 @@ class my_top_block(gr.top_block):
         self.u.set_decim(self._decim)
 
         (self._bitrate, self._samples_per_symbol, self._decim) = \
-                        pick_rx_bitrate(self._bitrate, self._demod_class.bits_per_symbol(), \
-                                        self._samples_per_symbol, self._decim, adc_rate,  \
-                                        self.u.get_decim_rates())
+                        pick_rx_bitrate(options.bitrate, self._demod_class.bits_per_symbol(), \
+                                        options.samples_per_symbol, options.decim, \
+                                        adc_rate, self.u.get_decim_rates())
 
         self.u.set_decim(self._decim)
         self.set_auto_tr(True)                 # enable Auto Transmit/Receive switching
@@ -353,6 +353,7 @@ class my_top_block(gr.top_block):
         self._gain_freq = gain_freq
         #self._gain_freq_beta = .25 * self._gain_freq * self._gain_freq
         self.rxpath.packet_receiver._demodulator.freq_recov.set_alpha(self._gain_freq)
+        self.rxpath.packet_receiver._demodulator.freq_recov.set_beta(self._gain_freq/10.0)
         #self.rxpath.packet_receiver._demodulator.freq_recov.set_beta(self._gain_fre_beta)
 
 
@@ -423,14 +424,14 @@ def main():
                 ok, pktno, n_rcvd, n_right)
 
 
-    demods = modulation_utils.type_1_demods()
+    demods = modulation_utils2.type_1_demods()
 
     # Create Options Parser:
     parser = OptionParser (option_class=eng_option, conflict_handler="resolve")
     expert_grp = parser.add_option_group("Expert")
 
     parser.add_option("-m", "--modulation", type="choice", choices=demods.keys(), 
-                      default='dbpsk',
+                      default='dbpsk2',
                       help="Select modulation from: %s [default=%%default]"
                             % (', '.join(demods.keys()),))
 
diff --git a/gnuradio-examples/python/digital/benchmark_rx2.py b/gnuradio-examples/python/digital/benchmark_rx2.py
new file mode 100755 (executable)
index 0000000..fe422be
--- /dev/null
@@ -0,0 +1,114 @@
+#!/usr/bin/env python
+#
+# Copyright 2010 Free Software Foundation, Inc.
+# 
+# This file is part of GNU Radio
+# 
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+# 
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING.  If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+# 
+
+from gnuradio import gr, gru, modulation_utils2
+from gnuradio import usrp
+from gnuradio import eng_notation
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+
+import random
+import struct
+import sys
+
+# from current dir
+import usrp_receive_path2
+
+#import os
+#print os.getpid()
+#raw_input('Attach and press enter: ')
+
+class my_top_block(gr.top_block):
+    def __init__(self, demodulator, rx_callback, options):
+        gr.top_block.__init__(self)
+
+        # Set up receive path
+        self.rxpath = usrp_receive_path2.usrp_receive_path(demodulator, rx_callback, options) 
+
+        self.connect(self.rxpath)
+
+# /////////////////////////////////////////////////////////////////////////////
+#                                   main
+# /////////////////////////////////////////////////////////////////////////////
+
+global n_rcvd, n_right
+
+def main():
+    global n_rcvd, n_right
+
+    n_rcvd = 0
+    n_right = 0
+    
+    def rx_callback(ok, payload):
+        global n_rcvd, n_right
+        (pktno,) = struct.unpack('!H', payload[0:2])
+        n_rcvd += 1
+        if ok:
+            n_right += 1
+
+        print "ok = %5s  pktno = %4d  n_rcvd = %4d  n_right = %4d" % (
+            ok, pktno, n_rcvd, n_right)
+
+
+    demods = modulation_utils2.type_1_demods()
+
+    # Create Options Parser:
+    parser = OptionParser (option_class=eng_option, conflict_handler="resolve")
+    expert_grp = parser.add_option_group("Expert")
+
+    parser.add_option("-m", "--modulation", type="choice", choices=demods.keys(), 
+                      default='dbpsk2',
+                      help="Select modulation from: %s [default=%%default]"
+                            % (', '.join(demods.keys()),))
+
+    usrp_receive_path2.add_options(parser, expert_grp)
+
+    for mod in demods.values():
+        mod.add_options(expert_grp)
+
+    (options, args) = parser.parse_args ()
+
+    if len(args) != 0:
+        parser.print_help(sys.stderr)
+        sys.exit(1)
+
+    if options.rx_freq is None:
+        sys.stderr.write("You must specify -f FREQ or --freq FREQ\n")
+        parser.print_help(sys.stderr)
+        sys.exit(1)
+
+
+    # build the graph
+    tb = my_top_block(demods[options.modulation], rx_callback, options)
+
+    r = gr.enable_realtime_scheduling()
+    if r != gr.RT_OK:
+        print "Warning: Failed to enable realtime scheduling."
+
+    tb.start()        # start flow graph
+    tb.wait()         # wait for it to finish
+
+if __name__ == '__main__':
+    try:
+        main()
+    except KeyboardInterrupt:
+        pass
diff --git a/gnuradio-examples/python/digital/benchmark_tx2.py b/gnuradio-examples/python/digital/benchmark_tx2.py
new file mode 100755 (executable)
index 0000000..6093dba
--- /dev/null
@@ -0,0 +1,135 @@
+#!/usr/bin/env python
+#
+# Copyright 2010 Free Software Foundation, Inc.
+# 
+# This file is part of GNU Radio
+# 
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+# 
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING.  If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+# 
+
+from gnuradio import gr, gru, modulation_utils2
+from gnuradio import usrp
+from gnuradio import eng_notation
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+
+import random, time, struct, sys
+
+# from current dir
+import usrp_transmit_path2
+
+#import os 
+#print os.getpid()
+#raw_input('Attach and press enter')
+
+class my_top_block(gr.top_block):
+    def __init__(self, modulator, options):
+        gr.top_block.__init__(self)
+
+        self.txpath = usrp_transmit_path2.usrp_transmit_path(modulator, options)
+
+        self.connect(self.txpath)
+
+# /////////////////////////////////////////////////////////////////////////////
+#                                   main
+# /////////////////////////////////////////////////////////////////////////////
+
+def main():
+
+    def send_pkt(payload='', eof=False):
+        return tb.txpath.send_pkt(payload, eof)
+
+    def rx_callback(ok, payload):
+        print "ok = %r, payload = '%s'" % (ok, payload)
+
+    mods = modulation_utils2.type_1_mods()
+
+    parser = OptionParser(option_class=eng_option, conflict_handler="resolve")
+    expert_grp = parser.add_option_group("Expert")
+
+    parser.add_option("-m", "--modulation", type="choice", choices=mods.keys(),
+                      default='dbpsk2',
+                      help="Select modulation from: %s [default=%%default]"
+                            % (', '.join(mods.keys()),))
+
+    parser.add_option("-s", "--size", type="eng_float", default=1500,
+                      help="set packet size [default=%default]")
+    parser.add_option("-M", "--megabytes", type="eng_float", default=1.0,
+                      help="set megabytes to transmit [default=%default]")
+    parser.add_option("","--discontinuous", action="store_true", default=False,
+                      help="enable discontinous transmission (bursts of 5 packets)")
+    parser.add_option("","--from-file", default=None,
+                      help="use file for packet contents")
+
+    usrp_transmit_path2.add_options(parser, expert_grp)
+
+    for mod in mods.values():
+        mod.add_options(expert_grp)
+
+    (options, args) = parser.parse_args ()
+
+    if len(args) != 0:
+        parser.print_help()
+        sys.exit(1)
+
+    if options.tx_freq is None:
+        sys.stderr.write("You must specify -f FREQ or --freq FREQ\n")
+        parser.print_help(sys.stderr)
+        sys.exit(1)
+
+    if options.from_file is not None:
+        source_file = open(options.from_file, 'r')
+
+    # build the graph
+    tb = my_top_block(mods[options.modulation], options)
+
+    r = gr.enable_realtime_scheduling()
+    if r != gr.RT_OK:
+        print "Warning: failed to enable realtime scheduling"
+
+    tb.start()                       # start flow graph
+        
+    # generate and send packets
+    nbytes = int(1e6 * options.megabytes)
+    n = 0
+    pktno = 0
+    pkt_size = int(options.size)
+
+    while n < nbytes:
+        if options.from_file is None:
+            data = (pkt_size - 2) * chr(pktno & 0xff) 
+        else:
+            data = source_file.read(pkt_size - 2)
+            if data == '':
+                break;
+
+        payload = struct.pack('!H', pktno & 0xffff) + data
+        send_pkt(payload)
+        n += len(payload)
+        sys.stderr.write('.')
+        if options.discontinuous and pktno % 5 == 4:
+            time.sleep(1)
+        pktno += 1
+        
+    send_pkt(eof=True)
+
+    tb.wait()                       # wait for it to finish
+
+if __name__ == '__main__':
+    try:
+        main()
+    except KeyboardInterrupt:
+        pass
diff --git a/gnuradio-examples/python/digital/pick_bitrate2.py b/gnuradio-examples/python/digital/pick_bitrate2.py
new file mode 100644 (file)
index 0000000..9253956
--- /dev/null
@@ -0,0 +1,154 @@
+#
+# Copyright 2010 Free Software Foundation, Inc.
+# 
+# This file is part of GNU Radio
+# 
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+# 
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING.  If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+# 
+
+from gnuradio import eng_notation
+
+_default_bitrate = 500e3
+_sps_min = 2
+_sps_max = 100
+
+def _pick_bitrate(bitrate, bits_per_symbol, samples_per_symbol,
+                  xrate, converter_rate, xrates):
+    """
+    @returns tuple (bitrate, samples_per_symbol, interp_rate_or_decim_rate)
+    """
+
+    if not isinstance(bits_per_symbol, int) or bits_per_symbol < 1:
+        raise ValueError, "bits_per_symbol must be an int >= 1"
+
+    converter_rate = float(converter_rate)
+    bits_per_symbol = float(bits_per_symbol)
+
+    # completely determined; if bitrate is specified, this overwrites it
+    if (samples_per_symbol is not None) and (xrate is not None):
+        bitrate = converter_rate / bits_per_symbol / xrate / samples_per_symbol
+
+    # If only SPS is given
+    if (bitrate is None) and (samples_per_symbol is not None) and (xrate is None):
+        xrate = max(xrates)
+        bitrate = converter_rate / bits_per_symbol / xrate / samples_per_symbol
+        
+    # If only xrate is given, just set SPS to 2 and calculate bitrate
+    if (bitrate is None) and (samples_per_symbol is None) and (xrate is not None):
+        samples_per_symbol = 2.0
+        bitrate = converter_rate / bits_per_symbol / xrate / samples_per_symbol
+
+    # If no parameters are give, use the default bit rate
+    if (bitrate is None) and (samples_per_symbol is None) and (xrate is None):
+        bitrate = _default_bitrate
+
+    # If only bitrate is specified, return max xrate and appropriate
+    # samples per symbol (minimum of 2.0) to reach bit rate
+    if (samples_per_symbol is None) and (xrate is None):
+        xrates.sort()
+        for i in xrange(len(xrates)):
+            if((converter_rate / bits_per_symbol / xrates[i]) >= 2*bitrate):
+                rate = xrates[i]
+            else:
+                break
+
+        try:
+            xrate = rate
+        except UnboundLocalError:
+            raise ValueError("Requested bitrate out of bounds")
+            
+        samples_per_symbol = converter_rate / bits_per_symbol / rate / bitrate
+        bitrate = converter_rate / bits_per_symbol / xrate / samples_per_symbol
+
+    # If bitrate and xrate are specified
+    if(samples_per_symbol is None):
+        samples_per_symbol = converter_rate / xrate / bits_per_symbol / bitrate
+
+    # If bitrate and SPS are specified
+    if(xrate is None):
+        xrate = converter_rate / samples_per_symbol / bits_per_symbol / bitrate
+        if((xrate in xrates) == False):
+            # Find the closest avaiable rate larger than the calculated one
+            xrates.sort()
+            for x in xrates:
+                if(x > xrate):
+                    xrate = x
+                    break
+            if(xrate > max(xrates)):
+                xrate = max(xrates)
+            
+            bitrate = converter_rate / bits_per_symbol / xrate / samples_per_symbol
+            print "Could not find suitable rate for specified SPS and Bitrate"
+            print "Using rate = %d for bitrate of %sbps" % \
+                  (xrate, (eng_notation.num_to_str(bitrate)))
+
+    if((xrate in xrates) == False):
+        raise ValueError(("Invalid rate (rate = %d)" % xrate))
+    if((samples_per_symbol < _sps_min) or (samples_per_symbol > _sps_max)):
+        raise ValueError(("Invalid samples per symbol (sps = %.2f). Must be in [%.0f, %.0f]." \
+                          % (samples_per_symbol, _sps_min, _sps_max)))
+        
+    return (bitrate, samples_per_symbol, int(xrate))
+
+
+def pick_tx_bitrate(bitrate, bits_per_symbol, samples_per_symbol,
+                    interp_rate, converter_rate, possible_interps):
+    """
+    Given the 4 input parameters, return at configuration that matches
+
+    @param bitrate: desired bitrate or None
+    @type bitrate: number or None
+    @param bits_per_symbol: E.g., BPSK -> 1, QPSK -> 2, 8-PSK -> 3
+    @type bits_per_symbol: integer >= 1
+    @param samples_per_symbol: samples/baud (aka samples/symbol)
+    @type samples_per_symbol: number or None
+    @param interp_rate: USRP interpolation factor
+    @type interp_rate: integer or None
+    @param converter_rate: converter sample rate in Hz
+    @type converter_rate: number
+    @param possible_interps: a list of possible rates
+    @type possible_interps: a list of integers
+
+    @returns tuple (bitrate, samples_per_symbol, interp_rate)
+    """
+
+    return _pick_bitrate(bitrate, bits_per_symbol, samples_per_symbol,
+                         interp_rate, converter_rate, possible_interps)
+
+
+def pick_rx_bitrate(bitrate, bits_per_symbol, samples_per_symbol,
+                    decim_rate, converter_rate, possible_decims):
+    """
+    Given the 4 input parameters, return at configuration that matches
+
+    @param bitrate: desired bitrate or None
+    @type bitrate: number or None
+    @param bits_per_symbol: E.g., BPSK -> 1, QPSK -> 2, 8-PSK -> 3
+    @type bits_per_symbol: integer >= 1
+    @param samples_per_symbol: samples/baud (aka samples/symbol)
+    @type samples_per_symbol: number or None
+    @param decim_rate: USRP decimation factor
+    @type decim_rate: integer or None
+    @param converter_rate: converter sample rate in Hz
+    @type converter_rate: number
+    @param possible_decims: a list of possible rates
+    @type possible_decims: a list of integers
+
+    @returns tuple (bitrate, samples_per_symbol, decim_rate)
+    """
+
+    return _pick_bitrate(bitrate, bits_per_symbol, samples_per_symbol,
+                         decim_rate, converter_rate, possible_decims)
index c229aa9e4784c9f6d848d893b0d42c520d52d87c..0024d6941f714778d61c43b040a2aeb575c95816 100644 (file)
@@ -119,7 +119,7 @@ class receive_path(gr.hier_block2):
             normal.add_option("-r", "--bitrate", type="eng_float", default=100e3,
                               help="specify bitrate [default=%default].")
         normal.add_option("-v", "--verbose", action="store_true", default=False)
-        expert.add_option("-S", "--samples-per-symbol", type="int", default=2,
+        expert.add_option("-S", "--samples-per-symbol", type="float", default=None,
                           help="set samples/symbol [default=%default]")
         expert.add_option("", "--log", action="store_true", default=False,
                           help="Log all parts of flow graph to files (CAUTION: lots of data)")
@@ -135,4 +135,4 @@ class receive_path(gr.hier_block2):
         print "\nReceive Path:"
         print "modulation:      %s"    % (self._demod_class.__name__)
         print "bitrate:         %sb/s" % (eng_notation.num_to_str(self._bitrate))
-        print "samples/symbol:  %3d"   % (self._samples_per_symbol)
+        print "samples/symbol:  %.4f"   % (self._samples_per_symbol)
index 9badcdc0840499d081bc0355c99e401cb2c45da2..86ebf75c3e87b70482f5a110b7dc664450ee16f3 100644 (file)
@@ -99,7 +99,7 @@ class transmit_path(gr.hier_block2):
                           help="set transmitter digital amplitude: 0 <= AMPL < 1 [default=%default]")
         normal.add_option("-v", "--verbose", action="store_true", default=False)
 
-        expert.add_option("-S", "--samples-per-symbol", type="int", default=2,
+        expert.add_option("-S", "--samples-per-symbol", type="float", default=None,
                           help="set samples/symbol [default=%default]")
         expert.add_option("", "--log", action="store_true", default=False,
                           help="Log all parts of flow graph to file (CAUTION: lots of data)")
@@ -114,5 +114,5 @@ class transmit_path(gr.hier_block2):
         print "Tx amplitude     %s"    % (self._tx_amplitude)
         print "modulation:      %s"    % (self._modulator_class.__name__)
         print "bitrate:         %sb/s" % (eng_notation.num_to_str(self._bitrate))
-        print "samples/symbol:  %3d"   % (self._samples_per_symbol)
+        print "samples/symbol:  %.4f"    % (self._samples_per_symbol)
         
index 517825cc1b53881bed8a1b78f700185f05fcb161..a8f16e28a9f5b884369f5c1731778c5a0abb2d42 100644 (file)
@@ -59,37 +59,35 @@ class usrp_receive_path(gr.hier_block2):
         if options.rx_freq is None:
             sys.stderr.write("-f FREQ or --freq FREQ or --rx-freq FREQ must be specified\n")
             raise SystemExit
-        rx_path = receive_path.receive_path(demod_class, rx_callback, options)
-        for attr in dir(rx_path): #forward the methods
-            if not attr.startswith('_') and not hasattr(self, attr):
-                setattr(self, attr, getattr(rx_path, attr))
 
         #setup usrp
         self._demod_class = demod_class
         self._setup_usrp_source(options)
 
-        # Set up resampler based on rate determined by _setup_usrp_source
-        rs_taps = gr.firdes.low_pass_2(32, 32, 0.45, 0.1, 60)
-        self.resampler = gr.pfb_arb_resampler_ccf(self.rs_rate, rs_taps)
+        rx_path = receive_path.receive_path(demod_class, rx_callback, options)
+        for attr in dir(rx_path): #forward the methods
+            if not attr.startswith('_') and not hasattr(self, attr):
+                setattr(self, attr, getattr(rx_path, attr))
 
         #connect
-        self.connect(self.u, self.resampler, rx_path)
+        self.connect(self.u, rx_path)
 
     def _setup_usrp_source(self, options):
         self.u = usrp_options.create_usrp_source(options)
         adc_rate = self.u.adc_rate()
         self.rs_rate = options.bitrate
-        if options.verbose:
-            print 'USRP Source:', self.u
+
         (self._bitrate, self._samples_per_symbol, self._decim) = \
                         pick_rx_bitrate(options.bitrate, self._demod_class.bits_per_symbol(), \
-                                        options.samples_per_symbol, options.decim, adc_rate,  \
-                                        self.u.get_decim_rates())
+                                        options.samples_per_symbol, options.decim,
+                                        adc_rate, self.u.get_decim_rates())
 
-        # Calculate resampler rate based on requested and actual rates
-        self.rs_rate = 1.0 /(self._bitrate / self.rs_rate)
-        
-        print "Resampling by %f to get bitrate of %ssps" % ( self.rs_rate, eng_notation.num_to_str(self._bitrate/self.rs_rate))
+        if options.verbose:
+            print 'USRP Source:', self.u
+            print 'Decimation: ', self._decim
+
+        options.samples_per_symbol = self._samples_per_symbol
+        options.decim = self._decim
         
         self.u.set_decim(self._decim)
 
diff --git a/gnuradio-examples/python/digital/usrp_receive_path2.py b/gnuradio-examples/python/digital/usrp_receive_path2.py
new file mode 100644 (file)
index 0000000..d200172
--- /dev/null
@@ -0,0 +1,96 @@
+#
+# Copyright 2010 Free Software Foundation, Inc.
+# 
+# This file is part of GNU Radio
+# 
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+# 
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING.  If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+# 
+
+from gnuradio import gr
+from gnuradio import usrp_options
+import receive_path
+from pick_bitrate2 import pick_rx_bitrate
+from gnuradio import eng_notation
+
+def add_freq_option(parser):
+    """
+    Hackery that has the -f / --freq option set both tx_freq and rx_freq
+    """
+    def freq_callback(option, opt_str, value, parser):
+        parser.values.rx_freq = value
+        parser.values.tx_freq = value
+
+    if not parser.has_option('--freq'):
+        parser.add_option('-f', '--freq', type="eng_float",
+                          action="callback", callback=freq_callback,
+                          help="set Tx and/or Rx frequency to FREQ [default=%default]",
+                          metavar="FREQ")
+
+def add_options(parser, expert):
+    add_freq_option(parser)
+    usrp_options.add_rx_options(parser)
+    receive_path.receive_path.add_options(parser, expert)
+    expert.add_option("", "--rx-freq", type="eng_float", default=None,
+                          help="set Rx frequency to FREQ [default=%default]", metavar="FREQ")
+    parser.add_option("-v", "--verbose", action="store_true", default=False)
+
+class usrp_receive_path(gr.hier_block2):
+
+    def __init__(self, demod_class, rx_callback, options):
+        '''
+        See below for what options should hold
+        '''
+        gr.hier_block2.__init__(self, "usrp_receive_path",
+                gr.io_signature(0, 0, 0),                    # Input signature
+                gr.io_signature(0, 0, 0)) # Output signature
+        if options.rx_freq is None:
+            sys.stderr.write("-f FREQ or --freq FREQ or --rx-freq FREQ must be specified\n")
+            raise SystemExit
+
+        #setup usrp
+        self._demod_class = demod_class
+        self._setup_usrp_source(options)
+
+        rx_path = receive_path.receive_path(demod_class, rx_callback, options)
+        for attr in dir(rx_path): #forward the methods
+            if not attr.startswith('_') and not hasattr(self, attr):
+                setattr(self, attr, getattr(rx_path, attr))
+
+        #connect
+        self.connect(self.u, rx_path)
+
+    def _setup_usrp_source(self, options):
+        self.u = usrp_options.create_usrp_source(options)
+        adc_rate = self.u.adc_rate()
+        self.rs_rate = options.bitrate
+
+        (self._bitrate, self._samples_per_symbol, self._decim) = \
+                        pick_rx_bitrate(options.bitrate, self._demod_class.bits_per_symbol(), \
+                                        options.samples_per_symbol, options.decim,
+                                        adc_rate, self.u.get_decim_rates())
+
+        if options.verbose:
+            print 'USRP Source:', self.u
+            print 'Decimation: ', self._decim
+
+        options.samples_per_symbol = self._samples_per_symbol
+        options.decim = self._decim
+        
+        self.u.set_decim(self._decim)
+
+        if not self.u.set_center_freq(options.rx_freq):
+            print "Failed to set Rx frequency to %s" % (eng_notation.num_to_str(options.rx_freq))
+            raise ValueError, eng_notation.num_to_str(options.rx_freq)
index ee63dcd2b7e2d35a07194ef94fe81840c8269179..f0f467599a6f6e78b0d4dfce46cce6d1facda01d 100644 (file)
@@ -58,21 +58,18 @@ class usrp_transmit_path(gr.hier_block2):
         if options.tx_freq is None:
             sys.stderr.write("-f FREQ or --freq FREQ or --tx-freq FREQ must be specified\n")
             raise SystemExit
-        tx_path = transmit_path.transmit_path(modulator_class, options)
-        for attr in dir(tx_path): #forward the methods
-            if not attr.startswith('_') and not hasattr(self, attr):
-                setattr(self, attr, getattr(tx_path, attr))
 
         #setup usrp
         self._modulator_class = modulator_class
         self._setup_usrp_sink(options)
 
-        # Set up resampler based on rate determined by _setup_usrp_sink
-        rs_taps = gr.firdes.low_pass_2(32, 32, 0.45, 0.1, 60)
-        self.resampler = gr.pfb_arb_resampler_ccf(self.rs_rate, rs_taps)
+        tx_path = transmit_path.transmit_path(modulator_class, options)
+        for attr in dir(tx_path): #forward the methods
+            if not attr.startswith('_') and not hasattr(self, attr):
+                setattr(self, attr, getattr(tx_path, attr))
 
         #connect
-        self.connect(tx_path, self.resampler, self.u)
+        self.connect(tx_path, self.u)
         
     def _setup_usrp_sink(self, options):
         """
@@ -82,17 +79,20 @@ class usrp_transmit_path(gr.hier_block2):
         self.u = usrp_options.create_usrp_sink(options)
         dac_rate = self.u.dac_rate()
         self.rs_rate = options.bitrate    # Store requested bit rate
-        if options.verbose:
-            print 'USRP Sink:', self.u
+            
         (self._bitrate, self._samples_per_symbol, self._interp) = \
-                        pick_tx_bitrate(options.bitrate, self._modulator_class.bits_per_symbol(), \
-                                        options.samples_per_symbol, options.interp, dac_rate, \
-                                        self.u.get_interp_rates())
+                        pick_tx_bitrate(options.bitrate, self._modulator_class.bits_per_symbol(),
+                                        options.samples_per_symbol, options.interp,
+                                        dac_rate, self.u.get_interp_rates())
 
-        # Calculate resampler rate based on requested and actual rates
-        self.rs_rate = self._bitrate / self.rs_rate
-        print "Resampling by %f to get bitrate of %ssps" % (self.rs_rate, eng_notation.num_to_str(self._bitrate/self.rs_rate))
+        options.interp = self._interp
+        options.samples_per_symbol = self._samples_per_symbol
+        options.bitrate = self._bitrate
 
+        if options.verbose:
+            print 'USRP Sink:', self.u
+            print "Interpolation Rate: ", self._interp
+        
         self.u.set_interp(self._interp)
         self.u.set_auto_tr(True)
 
diff --git a/gnuradio-examples/python/digital/usrp_transmit_path2.py b/gnuradio-examples/python/digital/usrp_transmit_path2.py
new file mode 100644 (file)
index 0000000..54930e5
--- /dev/null
@@ -0,0 +1,101 @@
+#
+# Copyright 2010 Free Software Foundation, Inc.
+# 
+# This file is part of GNU Radio
+# 
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+# 
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING.  If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+# 
+
+from gnuradio import gr
+from gnuradio import usrp_options
+import transmit_path
+from pick_bitrate2 import pick_tx_bitrate
+from gnuradio import eng_notation
+
+def add_freq_option(parser):
+    """
+    Hackery that has the -f / --freq option set both tx_freq and rx_freq
+    """
+    def freq_callback(option, opt_str, value, parser):
+        parser.values.rx_freq = value
+        parser.values.tx_freq = value
+
+    if not parser.has_option('--freq'):
+        parser.add_option('-f', '--freq', type="eng_float",
+                          action="callback", callback=freq_callback,
+                          help="set Tx and/or Rx frequency to FREQ [default=%default]",
+                          metavar="FREQ")
+
+def add_options(parser, expert):
+    add_freq_option(parser)
+    usrp_options.add_tx_options(parser)
+    transmit_path.transmit_path.add_options(parser, expert)
+    expert.add_option("", "--tx-freq", type="eng_float", default=None,
+                          help="set transmit frequency to FREQ [default=%default]", metavar="FREQ")
+    parser.add_option("-v", "--verbose", action="store_true", default=False)
+
+class usrp_transmit_path(gr.hier_block2):
+    def __init__(self, modulator_class, options):
+        '''
+        See below for what options should hold
+        '''
+        gr.hier_block2.__init__(self, "usrp_transmit_path",
+                gr.io_signature(0, 0, 0),                    # Input signature
+                gr.io_signature(0, 0, 0)) # Output signature
+        if options.tx_freq is None:
+            sys.stderr.write("-f FREQ or --freq FREQ or --tx-freq FREQ must be specified\n")
+            raise SystemExit
+
+        #setup usrp
+        self._modulator_class = modulator_class
+        self._setup_usrp_sink(options)
+
+        tx_path = transmit_path.transmit_path(modulator_class, options)
+        for attr in dir(tx_path): #forward the methods
+            if not attr.startswith('_') and not hasattr(self, attr):
+                setattr(self, attr, getattr(tx_path, attr))
+
+        #connect
+        self.connect(tx_path, self.u)
+        
+    def _setup_usrp_sink(self, options):
+        """
+        Creates a USRP sink, determines the settings for best bitrate,
+        and attaches to the transmitter's subdevice.
+        """
+        self.u = usrp_options.create_usrp_sink(options)
+        dac_rate = self.u.dac_rate()
+        self.rs_rate = options.bitrate    # Store requested bit rate
+            
+        (self._bitrate, self._samples_per_symbol, self._interp) = \
+                        pick_tx_bitrate(options.bitrate, self._modulator_class.bits_per_symbol(),
+                                        options.samples_per_symbol, options.interp,
+                                        dac_rate, self.u.get_interp_rates())
+
+        options.interp = self._interp
+        options.samples_per_symbol = self._samples_per_symbol
+        options.bitrate = self._bitrate
+
+        if options.verbose:
+            print 'USRP Sink:', self.u
+            print "Interpolation Rate: ", self._interp
+        
+        self.u.set_interp(self._interp)
+        self.u.set_auto_tr(True)
+
+        if not self.u.set_center_freq(options.tx_freq):
+            print "Failed to set Rx frequency to %s" % (eng_notation.num_to_str(options.tx_freq))
+            raise ValueError, eng_notation.num_to_str(options.tx_freq)
index 2ef49558905d5b1f9b0609fae5f87c54ab27716b..a315e166bb9a28b312b28a153f2870336ebff84d 100644 (file)
@@ -1,3 +1 @@
-from gpio_swig import *
-
 fpga_filename = 'std_2rxint_2tx_dig.rbf'
index c81bc780dcf4efc2ed61a369ef0a562baa745439..e628d6b1606f2fb2cb9d62bcc5d52ea302f641db 100644 (file)
@@ -1,6 +1,6 @@
 # -*- Makefile -*-
 #
-# Copyright 2004,2006,2009 Free Software Foundation, Inc.
+# Copyright 2004,2006,2009,2010 Free Software Foundation, Inc.
 # 
 # This file is part of GNU Radio
 # 
@@ -20,6 +20,9 @@
 # Boston, MA 02110-1301, USA.
 # 
 
+# The name of this "out-of-tree" module
+modname = howto
+
 # these flags are used when compiling non-SWIG-wrapper files
 # when going in to non-SWIG libraries
 AM_CXXFLAGS = @autoconf_default_CXXFLAGS@
@@ -34,21 +37,22 @@ AM_CPPFLAGS = \
 # these are used by both SWIG and CXX
 STD_DEFINES_AND_INCLUDES = \
        $(DEFINES) \
+       -I$(abs_top_srcdir)/include \
        -I$(GNURADIO_CORE_INCLUDEDIR) \
        -I$(GNURADIO_CORE_INCLUDEDIR)/swig
 
 # includes
-grincludedir = $(includedir)/gnuradio
+modincludedir = $(includedir)/$(modname)
 
 # swig includes 
-swigincludedir = $(grincludedir)/swig
+swigincludedir = $(modincludedir)/swig
 
 # Install this stuff in the appropriate subdirectory
 # This usually ends up at:
-#   ${prefix}/lib/python${python_version}/site-packages/gnuradio
+#   ${prefix}/lib/python${python_version}/site-packages/$(modname)
 
-grpythondir = $(pythondir)/gnuradio
-grpyexecdir = $(pyexecdir)/gnuradio
+modpythondir = $(pythondir)/$(modname)
+modpyexecdir = $(pyexecdir)/$(modname)
 
 # Data directory for grc block wrappers
 grc_blocksdir = $(prefix)/share/gnuradio/grc/blocks
index c15a8172144f2ca15b629b3de98cc3d1c43f8c68..686117f83ce017081898fde40b0a77257f818b07 100644 (file)
 ## Default install locations for these files:
 ##
 ## Default location for the Python directory is:
-##  ${prefix}/lib/python${python_version}/site-packages/[category]/@NAME@
+##  ${prefix}/lib/python${python_version}/site-packages/@NAME@
 ## Default location for the Python exec directory is:
-##  ${exec_prefix}/lib/python${python_version}/site-packages/[category]/@NAME@
+##  ${exec_prefix}/lib/python${python_version}/site-packages/@NAME@
 ##
 ## The following can be overloaded to change the install location, but
 ## this has to be done in the including Makefile.am -before-
 ## Makefile.swig is included.
 
-@NAME@_pythondir_category ?= gnuradio/@NAME@
-@NAME@_pylibdir_category ?= $(@NAME@_pythondir_category)
-@NAME@_pythondir = $(pythondir)/$(@NAME@_pythondir_category)
-@NAME@_pylibdir = $(pyexecdir)/$(@NAME@_pylibdir_category)
+@NAME@_pythondir = $(pythondir)/@NAME@
+@NAME@_pylibdir = $(pyexecdir)/@NAME@
 
 ## SWIG headers are always installed into the same directory.
 
@@ -72,7 +70,7 @@ MOSTLYCLEANFILES += $(DEPDIR)/*.S*
 ## .h file is sometimes built, but not always ... so that one has to
 ## be added manually by the including Makefile.am .
 
-swig_built_sources += @NAME@.py @NAME@.cc
+swig_built_sources += @NAME@_swig.py @NAME@_swig.cc
 
 ## Various SWIG variables.  These can be overloaded in the including
 ## Makefile.am by setting the variable value there, then including
@@ -83,31 +81,31 @@ swig_built_sources += @NAME@.py @NAME@.cc
        $(@NAME@_swiginclude_headers)
 
 @NAME@_pylib_LTLIBRARIES =             \
-       _@NAME@.la
+       _@NAME@_swig.la
 
-_@NAME@_la_SOURCES =                   \
-       @NAME@.cc                       \
+_@NAME@_swig_la_SOURCES =              \
+       @NAME@_swig.cc                  \
        $(@NAME@_la_swig_sources)
 
-_@NAME@_la_LIBADD =                    \
+_@NAME@_swig_la_LIBADD =               \
        $(STD_SWIG_LA_LIB_ADD)          \
        $(@NAME@_la_swig_libadd)
 
-_@NAME@_la_LDFLAGS =                   \
+_@NAME@_swig_la_LDFLAGS =              \
        $(STD_SWIG_LA_LD_FLAGS)         \
        $(@NAME@_la_swig_ldflags)
 
-_@NAME@_la_CXXFLAGS =                  \
+_@NAME@_swig_la_CXXFLAGS =             \
        $(STD_SWIG_CXX_FLAGS)           \
        $(@NAME@_la_swig_cxxflags)
 
 @NAME@_python_PYTHON =                 \
-       @NAME@.py                       \
+       @NAME@_swig.py                  \
        $(@NAME@_python)
 
 ## Entry rule for running SWIG
 
-@NAME@.h @NAME@.py @NAME@.cc: @NAME@.i
+@NAME@.h @NAME@_swig.py @NAME@_swig.cc: @NAME@.i
 ## This rule will get called only when MAKE decides that one of the
 ## targets needs to be created or re-created, because:
 ##
@@ -202,7 +200,7 @@ $(DEPDIR)/@NAME@-generate-stamp:
 ##
        if $(SWIG) $(STD_SWIG_PYTHON_ARGS) $(@NAME@_swig_args) \
                -MD -MF $(DEPDIR)/@NAME@.Std \
-               -module @NAME@ -o @NAME@.cc $(WHAT); then \
+               -module @NAME@_swig -o @NAME@_swig.cc $(WHAT); then \
            if test $(host_os) = mingw32; then \
                $(RM) $(DEPDIR)/@NAME@.Sd; \
                $(SED) 's,\\\\,/,g' < $(DEPDIR)/@NAME@.Std \
index 8d3d870d8426c5b93f19a661f5b5c5209e8d9db1..f14e28325d9cb7b7687befde7b9630ebca710305 100755 (executable)
@@ -5,9 +5,9 @@
 # Generated: Thu Nov 12 11:26:07 2009
 ##################################################
 
+import howto
 from gnuradio import eng_notation
 from gnuradio import gr
-from gnuradio import howto
 from gnuradio.eng_option import eng_option
 from gnuradio.gr import firdes
 from gnuradio.wxgui import scopesink2
index 2b46106e819f64cbade9f2298e8c05f49cdad992..c58ef00478ccb3a132728ade67510f46c498d3bc 100644 (file)
@@ -3,7 +3,7 @@
   <name>Square2</name>
   <key>howto_square2_ff</key>
   <category>HOWTO</category>
-  <import>from gnuradio import howto</import>
+  <import>import howto</import>
   <make>howto.square2_ff()</make>
 
   <sink>
index ed318bfc6e6e830f2f7a63418698969143cda004..34a0b0a3f25aea18b6cee16af01cbc81ec246adb 100644 (file)
@@ -3,7 +3,7 @@
   <name>Square</name>
   <key>howto_square_ff</key>
   <category>HOWTO</category>
-  <import>from gnuradio import howto</import>
+  <import>import howto</import>
   <make>howto.square_ff()</make>
 
   <sink>
index 336cb8a203e3caf5b6ad0f73b0f79d86b2a203f8..2e76ee453c085228e3fac456fda95f2ee774568a 100644 (file)
@@ -1,5 +1,5 @@
 #
-# Copyright 2004,2005,2006,2008,2009 Free Software Foundation, Inc.
+# Copyright 2004,2005,2006,2008,2009,2010 Free Software Foundation, Inc.
 # 
 # This file is part of GNU Radio
 # 
@@ -28,21 +28,21 @@ TESTS = test_all
 # howto C++ library: libgnuradio-howto.so
 # ----------------------------------------------------------------
 
-# C/C++ headers get installed in ${prefix}/include/gnuradio
-grinclude_HEADERS =            \
-       howto_square_ff.h       \
+# C/C++ headers get installed in ${prefix}/include/$(modname)
+modinclude_HEADERS = \
+       howto_square_ff.h \
        howto_square2_ff.h
 
 lib_LTLIBRARIES = libgnuradio-howto.la
 
-libgnuradio_howto_la_SOURCES =         \
-       howto_square_ff.cc      \
+libgnuradio_howto_la_SOURCES = \
+       howto_square_ff.cc \
        howto_square2_ff.cc
 
-libgnuradio_howto_la_LIBADD =  \
+libgnuradio_howto_la_LIBADD = \
        $(GNURADIO_CORE_LA)
 
-libgnuradio_howto_la_LDFLAGS = \
+libgnuradio_howto_la_LDFLAGS = \
        $(NO_UNDEFINED)
 
 # ----------------------------------------------------------------
@@ -51,23 +51,23 @@ libgnuradio_howto_la_LDFLAGS =      \
 
 noinst_LTLIBRARIES = libgnuradio-howto-qa.la
 
-libgnuradio_howto_qa_la_SOURCES =      \
-       qa_howto.cc                     \
-       qa_howto_square_ff.cc           \
+libgnuradio_howto_qa_la_SOURCES = \
+       qa_howto.cc \
+       qa_howto_square_ff.cc \
        qa_howto_square2_ff.cc
 
 libgnuradio_howto_qa_la_LDFLAGS = $(NO_UNDEFINED) -version-info 0:0:0
 
-libgnuradio_howto_qa_la_LIBADD =       \
-       libgnuradio-howto.la            \
+libgnuradio_howto_qa_la_LIBADD = \
+       libgnuradio-howto.la \
        $(CPPUNIT_LIBS)
 
 # ----------------------------------------------------------------
 # headers that don't get installed
 # ----------------------------------------------------------------
-noinst_HEADERS =               \
-       qa_howto.h              \
-       qa_howto_square_ff.h    \
+noinst_HEADERS = \
+       qa_howto.h \
+       qa_howto_square_ff.h \
        qa_howto_square2_ff.h
 
 # ----------------------------------------------------------------
index 4ef5fc964d276fac3c858ab26dedf4d92878a9d2..ae36ea665f0588390c58f076a10d7cef80f23f64 100644 (file)
@@ -1,5 +1,5 @@
 #
-# Copyright 2004 Free Software Foundation, Inc.
+# Copyright 2004,2010 Free Software Foundation, Inc.
 # 
 # This file is part of GNU Radio
 # 
 
 include $(top_srcdir)/Makefile.common
 
-ourpythondir = $(grpythondir)/howto
-
 EXTRA_DIST = run_tests.in
 TESTS = run_tests
 
-ourpython_PYTHON = \
+modpython_PYTHON = \
        __init__.py
 
 noinst_PYTHON = \
index fc40109d0568e3cc061bdc334e8e7ed28fbd2423..4737ad619ebeded36144607b85c22b63f9b7abaa 100644 (file)
@@ -1,5 +1,5 @@
 #
-# Copyright 2004,2005,2006,2008,2009 Free Software Foundation, Inc.
+# Copyright 2004,2005,2006,2008,2009,2010 Free Software Foundation, Inc.
 # 
 # This file is part of GNU Radio
 # 
@@ -27,14 +27,13 @@ if PYTHON
 ###################################
 # SWIG Python interface and library
 
-TOP_SWIG_IFILES =              \
+TOP_SWIG_IFILES = \
        howto.i
 
 # Install so that they end up available as:
-#   import gnuradio.howto
+#   import howto
 # This ends up at:
-#   ${prefix}/lib/python${python_version}/site-packages/gnuradio
-howto_pythondir_category = gnuradio/howto
+#   ${prefix}/lib/python${python_version}/site-packages/$(modname)
 
 howto_la_swig_libadd =         \
        $(top_builddir)/lib/libgnuradio-howto.la
@@ -48,7 +47,7 @@ BUILT_SOURCES = $(swig_built_sources)
 no_dist_files = $(swig_built_sources)
 
 # additional SWIG files to be installed
-howto_swiginclude_headers =    \
+howto_swiginclude_headers = \
        howto_square_ff.i \
        howto_square2_ff.i
 
index c62e5aa3e0a1beb9de01c71b5c61172a2bf06118..6c6e6629054f186954a4fb1f1bd0c91ba977f6ba 100644 (file)
 ## Default install locations for these files:
 ##
 ## Default location for the Python directory is:
-##  ${prefix}/lib/python${python_version}/site-packages/[category]/howto
+##  ${prefix}/lib/python${python_version}/site-packages/howto
 ## Default location for the Python exec directory is:
-##  ${exec_prefix}/lib/python${python_version}/site-packages/[category]/howto
+##  ${exec_prefix}/lib/python${python_version}/site-packages/howto
 ##
 ## The following can be overloaded to change the install location, but
 ## this has to be done in the including Makefile.am -before-
 ## Makefile.swig is included.
 
-howto_pythondir_category ?= gnuradio/howto
-howto_pylibdir_category ?= $(howto_pythondir_category)
-howto_pythondir = $(pythondir)/$(howto_pythondir_category)
-howto_pylibdir = $(pyexecdir)/$(howto_pylibdir_category)
+howto_pythondir = $(pythondir)/howto
+howto_pylibdir = $(pyexecdir)/howto
 
 ## SWIG headers are always installed into the same directory.
 
@@ -79,7 +77,7 @@ swig_built_sources += howto_swig.py howto_swig.cc
 ## Makefile.swig .
 
 howto_swiginclude_HEADERS =            \
-       howto.i                         \
+       howto.i                 \
        $(howto_swiginclude_headers)
 
 howto_pylib_LTLIBRARIES =              \
@@ -89,7 +87,7 @@ _howto_swig_la_SOURCES =              \
        howto_swig.cc                   \
        $(howto_la_swig_sources)
 
-_howto_swig_la_LIBADD =                        \
+_howto_swig_la_LIBADD =                \
        $(STD_SWIG_LA_LIB_ADD)          \
        $(howto_la_swig_libadd)
 
index fb21e4f449b8eb817a34c792209f1bc2da1029bc..9c4e222c810d52ac44c7ec4512b3685dd1f39e98 100644 (file)
@@ -35,6 +35,7 @@ ourpython_PYTHON = \
     pyqt_filter.py
 
 bin_SCRIPTS = \
+    create-gnuradio-out-of-tree-project \
     gr_plot_char.py \
     gr_plot_const.py \
     gr_plot_fft.py \
diff --git a/gr-utils/src/python/create-gnuradio-out-of-tree-project b/gr-utils/src/python/create-gnuradio-out-of-tree-project
new file mode 100755 (executable)
index 0000000..1f512b2
--- /dev/null
@@ -0,0 +1,69 @@
+#!/usr/bin/env python
+
+from optparse import OptionParser
+import os
+import re
+import sys
+import subprocess
+
+tarball_url="http://gnuradio.org/releases/gnuradio/gr-howto-write-a-block-3.3git-651-g642252d8.tar.gz"
+
+def open_tarball(tarball_name=None):
+    """Return a readable fileobject that references the tarball.
+    If tarball_name is None, download from the net
+    """
+    if tarball_name:
+        return open(tarball_name, 'r')
+    p = subprocess.Popen(["wget", "-O", "-", tarball_url],
+                         close_fds=True, stdout=subprocess.PIPE)
+    return p.stdout
+
+def extract_and_rename_files(tarball, module_name):
+    #  Requires GNU tar.
+    tar_cmd = 'tar xz --strip-components=1 --transform="s/howto/%s/g"' % (module_name,)
+    p = subprocess.Popen(tar_cmd, shell=True, stdin=tarball, close_fds=True)
+    sts = os.waitpid(p.pid, 0)
+    return sts == 0
+
+def main():
+    usage = "%prog: [options] new_module_name"
+    description="Create a prototype 'out of tree' GNU Radio project"
+    parser = OptionParser(usage=usage, description=description)
+    parser.add_option("-T", "--tarball", type="string", default=None,
+                      help="path to gr-howto-build-a-block gzipped tarball [default=<get from web>]")
+    (options, args) = parser.parse_args()
+    if len(args) != 1:
+        parser.print_help()
+        raise SystemExit,2
+    module_name = args[0]
+    if not re.match(r'[_a-z][_a-z0-9]*$', module_name):
+        sys.stderr.write("module_name '%s' may only contain [a-z0-9_]\n" % (module_name))
+        raise SystemExit, 1
+
+    # Ensure there's no file or directory called <module_name>
+    if os.path.exists(module_name):
+        sys.stderr.write("A file or directory named '%s' already exists\n" % (module_name,))
+        raise SystemExit, 1
+
+    os.mkdir(module_name)
+    os.chdir(module_name)
+
+    ok = extract_and_rename_files(open_tarball(options.tarball), module_name)
+
+    # rename file contents
+    upper_module_name = module_name.upper()
+    sed_cmd = 'sed -i -e "s/howto/%s/g" -e "s/HOWTO/%s/g"' % (module_name,
+                                                                 upper_module_name)
+    os.system('find . -type f -print0 | xargs -0 ' + sed_cmd)
+
+    sys.stdout.write("""
+Project '%s' is now ready to build.
+
+  $ ./bootstrap
+  $ ./configure --prefix=/home/[user]/install
+  $ (make && make check && make install) 2>&1 | tee make.log
+
+""" % (module_name,))
+
+if __name__ == '__main__':
+    main()
index b70468ed03f44ba481d0a7f1e88e621fe02b445c..790df7c3fa6c282c353e698c883e77d45a01ee63 100644 (file)
@@ -1,5 +1,5 @@
 """
-Copyright 2007, 2008, 2009 Free Software Foundation, Inc.
+Copyright 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 This file is part of GNU Radio
 
 GNU Radio Companion is free software; you can redistribute it and/or
@@ -82,19 +82,21 @@ class DrawingArea(gtk.DrawingArea):
                Forward button click information to the flow graph.
                """
                self.ctrl_mask = event.state & gtk.gdk.CONTROL_MASK
-               self._flow_graph.handle_mouse_button_press(
-                       left_click=(event.button == 1),
+               if event.button == 1: self._flow_graph.handle_mouse_selector_press(
                        double_click=(event.type == gtk.gdk._2BUTTON_PRESS),
                        coordinate=(event.x, event.y),
                )
+               if event.button == 3: self._flow_graph.handle_mouse_context_press(
+                       coordinate=(event.x, event.y),
+                       event=event,
+               )
 
        def _handle_mouse_button_release(self, widget, event):
                """
                Forward button release information to the flow graph.
                """
                self.ctrl_mask = event.state & gtk.gdk.CONTROL_MASK
-               self._flow_graph.handle_mouse_button_release(
-                       left_click=(event.button == 1),
+               if event.button == 1: self._flow_graph.handle_mouse_selector_release(
                        coordinate=(event.x, event.y),
                )
 
index 5adecccc13a063e756825b37ed24e5652da318f0..897145a1dba7dc503c643875980bf77129b6e952 100644 (file)
@@ -1,5 +1,5 @@
 """
-Copyright 2007, 2008, 2009 Free Software Foundation, Inc.
+Copyright 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 This file is part of GNU Radio
 
 GNU Radio Companion is free software; you can redistribute it and/or
@@ -51,6 +51,19 @@ class FlowGraph(Element):
                #selected ports
                self._old_selected_port = None
                self._new_selected_port = None
+               #context menu
+               self._context_menu = gtk.Menu()
+               for action in [
+                       Actions.BLOCK_CUT,
+                       Actions.BLOCK_COPY,
+                       Actions.BLOCK_PASTE,
+                       Actions.ELEMENT_DELETE,
+                       Actions.BLOCK_ROTATE_CCW,
+                       Actions.BLOCK_ROTATE_CW,
+                       Actions.BLOCK_ENABLE,
+                       Actions.BLOCK_DISABLE,
+                       Actions.BLOCK_PARAM_MODIFY,
+               ]: self._context_menu.append(action.create_menu_item())
 
        ###########################################################################
        # Access Drawing Area
@@ -425,14 +438,27 @@ class FlowGraph(Element):
        ##########################################################################
        ## Event Handlers
        ##########################################################################
-       def handle_mouse_button_press(self, left_click, double_click, coordinate):
+       def handle_mouse_context_press(self, coordinate, event):
                """
-               A mouse button is pressed, only respond to left clicks.
+               The context mouse button was pressed:
+               If no elements were selected, perform re-selection at this coordinate.
+               Then, show the context menu at the mouse click location.
+               """
+               selections = self.what_is_selected(coordinate)
+               if not set(selections).intersection(self.get_selected_elements()):
+                       self.set_coordinate(coordinate)
+                       self.mouse_pressed = True
+                       self.update_selected_elements()
+                       self.mouse_pressed = False
+               self._context_menu.popup(None, None, None, event.button, event.time)
+
+       def handle_mouse_selector_press(self, double_click, coordinate):
+               """
+               The selector mouse button was pressed:
                Find the selected element. Attempt a new connection if possible.
                Open the block params window on a double click.
                Update the selection state of the flow graph.
                """
-               if not left_click: return
                self.press_coor = coordinate
                self.set_coordinate(coordinate)
                self.time = 0
@@ -444,11 +470,12 @@ class FlowGraph(Element):
                        self.mouse_pressed = False
                        Actions.BLOCK_PARAM_MODIFY()
 
-       def handle_mouse_button_release(self, left_click, coordinate):
+       def handle_mouse_selector_release(self, coordinate):
                """
-               A mouse button is released, record the state.
+               The selector mouse button was released:
+               Update the state, handle motion (dragging).
+               And update the selected flowgraph elements.
                """
-               if not left_click: return
                self.set_coordinate(coordinate)
                self.time = 0
                self.mouse_pressed = False
index 3188aad1d5db76176e453c2ccda0674ea19e8b28..c371b023b539b79ec257133efe28bb36b6e837c5 100644 (file)
@@ -1,6 +1,6 @@
 /* -*- c++ -*- */
 /*
- * Copyright 2006,2009 Free Software Foundation, Inc.
+ * Copyright 2006,2009,2010 Free Software Foundation, Inc.
  * 
  * This file is part of GNU Radio
  * 
@@ -465,23 +465,30 @@ std::complex<double> *pmt_c64vector_writable_elements(pmt_t v, size_t &len); //<
 /*
  * ------------------------------------------------------------------------
  *        Dictionary (a.k.a associative array, hash, map)
+ *
+ * This is a functional data structure that is persistent.  Updating a
+ * functional data structure does not destroy the existing version, but
+ * rather creates a new version that coexists with the old.
  * ------------------------------------------------------------------------
  */
 
 //! Return true if \p obj is a dictionary
-bool pmt_is_dict(pmt_t obj);
+bool pmt_is_dict(const pmt_t &obj);
 
-//! make an empty dictionary
+//! Make an empty dictionary
 pmt_t pmt_make_dict();
 
-//! dict[key] = value
-void  pmt_dict_set(pmt_t dict, pmt_t key, pmt_t value);
+//! Return a new dictionary with \p key associated with \p value.
+pmt_t pmt_dict_add(const pmt_t &dict, const pmt_t &key, const pmt_t &value);
+
+//! Return a new dictionary with \p key removed.
+pmt_t pmt_dict_delete(const pmt_t &dict, const pmt_t &key);
 
 //! Return true if \p key exists in \p dict
-bool  pmt_dict_has_key(pmt_t dict, pmt_t key);
+bool  pmt_dict_has_key(const pmt_t &dict, const pmt_t &key);
 
 //! If \p key exists in \p dict, return associated value; otherwise return \p not_found.
-pmt_t pmt_dict_ref(pmt_t dict, pmt_t key, pmt_t not_found);
+pmt_t pmt_dict_ref(const pmt_t &dict, const pmt_t &key, const pmt_t &not_found);
 
 //! Return list of (key . value) pairs
 pmt_t pmt_dict_items(pmt_t dict);
index e50e218380311560a0e91249ac9a9e5c017a2cb0..aa1688d24a8b69f18fda47fb9393e3cb5b43f8a8 100644 (file)
@@ -1,6 +1,6 @@
 /* -*- c++ -*- */
 /*
- * Copyright 2006,2009 Free Software Foundation, Inc.
+ * Copyright 2006,2009,2010 Free Software Foundation, Inc.
  * 
  * This file is part of GNU Radio
  * 
@@ -141,12 +141,6 @@ _uniform_vector(pmt_t x)
   return dynamic_cast<pmt_uniform_vector*>(x.get());
 }
 
-static pmt_dict *
-_dict(pmt_t x)
-{
-  return dynamic_cast<pmt_dict*>(x.get());
-}
-
 static pmt_any *
 _any(pmt_t x)
 {
@@ -728,124 +722,91 @@ pmt_uniform_vector_writable_elements(pmt_t vector, size_t &len)
 //                            Dictionaries
 ////////////////////////////////////////////////////////////////////////////
 
-pmt_dict::pmt_dict()
-  : d_alist(PMT_NIL)
-{
-}
-
-void
-pmt_dict::set(pmt_t key, pmt_t value)
-{
-  pmt_t        p = pmt_assv(key, d_alist);     // look for (key . value) pair
-  if (pmt_is_pair(p)){                 // found existing pair...
-    pmt_set_cdr(p, value);             // overrwrite cdr with new value
-  }
-  else {                               // not in the dict
-    d_alist = pmt_cons(pmt_cons(key, value), d_alist); // add new (key . value) pair
-  }
-}
-
-pmt_t
-pmt_dict::ref(pmt_t key, pmt_t not_found) const
-{
-  pmt_t        p = pmt_assv(key, d_alist);     // look for (key . value) pair
-  if (pmt_is_pair(p))
-    return pmt_cdr(p);
-  else
-    return not_found;
-}
+/*
+ * This is an a-list implementation.
+ *
+ * When we need better performance for large dictionaries, consider implementing
+ * persistent Red-Black trees as described in "Purely Functional Data Structures", 
+ * Chris Okasaki, 1998, section 3.3.
+ */
 
 bool
-pmt_dict::has_key(pmt_t key) const
+pmt_is_dict(const pmt_t &obj)
 {
-  return pmt_is_pair(pmt_assv(key, d_alist));
+  return pmt_is_null(obj) || pmt_is_pair(obj);
 }
 
 pmt_t
-pmt_dict::items() const
+pmt_make_dict()
 {
-  return d_alist;
+  return PMT_NIL;
 }
 
 pmt_t
-pmt_dict::keys() const
+pmt_dict_add(const pmt_t &dict, const pmt_t &key, const pmt_t &value)
 {
-  return pmt_map(pmt_car, d_alist);
-}
+  if (pmt_is_null(dict))
+    return pmt_acons(key, value, PMT_NIL);
 
-pmt_t
-pmt_dict::values() const
-{
-  return pmt_map(pmt_cdr, d_alist);
-}
+  if (pmt_dict_has_key(dict, key))
+    return pmt_acons(key, value, pmt_dict_delete(dict, key));
 
-bool
-pmt_is_dict(pmt_t obj)
-{
-  return obj->is_dict();
+  return pmt_acons(key, value, dict);
 }
 
 pmt_t
-pmt_make_dict()
+pmt_dict_delete(const pmt_t &dict, const pmt_t &key)
 {
-  return pmt_t(new pmt_dict());
+  if (pmt_is_null(dict))
+    return dict;
+
+  if (pmt_eqv(pmt_caar(dict), key))
+    return pmt_cdr(dict);
+  
+  return pmt_cons(pmt_car(dict), pmt_dict_delete(pmt_cdr(dict), key));
 }
 
-void
-pmt_dict_set(pmt_t dict, pmt_t key, pmt_t value)
+pmt_t
+pmt_dict_ref(const pmt_t &dict, const pmt_t &key, const pmt_t &not_found)
 {
-  pmt_dict* d = _dict(dict);
-  if (!d)
-    throw pmt_wrong_type("pmt_dict_set", dict);
-
-  d->set(key, value);
+  pmt_t        p = pmt_assv(key, dict);        // look for (key . value) pair
+  if (pmt_is_pair(p))
+    return pmt_cdr(p);
+  else
+    return not_found;
 }
 
 bool
-pmt_dict_has_key(pmt_t dict, pmt_t key)
+pmt_dict_has_key(const pmt_t &dict, const pmt_t &key)
 {
-  pmt_dict* d = _dict(dict);
-  if (!d)
-    throw pmt_wrong_type("pmt_dict_has_key", dict);
-
-  return d->has_key(key);
-}
-
-pmt_t
-pmt_dict_ref(pmt_t dict, pmt_t key, pmt_t not_found)
-{
-  pmt_dict* d = _dict(dict);
-  if (!d)
-    throw pmt_wrong_type("pmt_dict_ref", dict);
-
-  return d->ref(key, not_found);
+  return pmt_is_pair(pmt_assv(key, dict));
 }
 
 pmt_t
 pmt_dict_items(pmt_t dict)
 {
-  if (!dict->is_dict())
-    throw pmt_wrong_type("pmt_dict_items", dict);
+  if (!pmt_is_dict(dict))
+    throw pmt_wrong_type("pmt_dict_values", dict);
 
-  return _dict(dict)->items();
+  return dict;         // equivalent to dict in the a-list case
 }
 
 pmt_t
 pmt_dict_keys(pmt_t dict)
 {
-  if (!dict->is_dict())
+  if (!pmt_is_dict(dict))
     throw pmt_wrong_type("pmt_dict_keys", dict);
 
-  return _dict(dict)->keys();
+  return pmt_map(pmt_car, dict);
 }
 
 pmt_t
 pmt_dict_values(pmt_t dict)
 {
-  if (!dict->is_dict())
-    throw pmt_wrong_type("pmt_dict_values", dict);
+  if (!pmt_is_dict(dict))
+    throw pmt_wrong_type("pmt_dict_keys", dict);
 
-  return _dict(dict)->values();
+  return pmt_map(pmt_cdr, dict);
 }
 
 ////////////////////////////////////////////////////////////////////////////
@@ -977,6 +938,24 @@ pmt_eqv(const pmt_t& x, const pmt_t& y)
   return false;
 }
 
+bool
+pmt_eqv_raw(pmt_base *x, pmt_base *y)
+{
+  if (x == y)
+    return true;
+
+  if (x->is_integer() && y->is_integer())
+    return _integer(x)->value() == _integer(y)->value();
+
+  if (x->is_real() && y->is_real())
+    return _real(x)->value() == _real(y)->value();
+
+  if (x->is_complex() && y->is_complex())
+    return _complex(x)->value() == _complex(y)->value();
+
+  return false;
+}
+
 bool
 pmt_equal(const pmt_t& x, const pmt_t& y)
 {
@@ -1082,6 +1061,35 @@ pmt_assq(pmt_t obj, pmt_t alist)
   return PMT_F;
 }
 
+/*
+ * This avoids a bunch of shared_pointer reference count manipulation.
+ */
+pmt_t
+pmt_assv_raw(pmt_base *obj, pmt_base *alist)
+{
+  while (alist->is_pair()){
+    pmt_base *p = ((pmt_pair *)alist)->d_car.get();
+    if (!p->is_pair())         // malformed alist
+      return PMT_F;
+
+    if (pmt_eqv_raw(obj, ((pmt_pair *)p)->d_car.get()))
+      return ((pmt_pair *)alist)->d_car;
+
+    alist = (((pmt_pair *)alist)->d_cdr).get();
+  }
+  return PMT_F;
+}
+
+#if 1
+
+pmt_t
+pmt_assv(pmt_t obj, pmt_t alist)
+{
+  return pmt_assv_raw(obj.get(), alist.get());
+}
+
+#else
+
 pmt_t
 pmt_assv(pmt_t obj, pmt_t alist)
 {
@@ -1098,6 +1106,9 @@ pmt_assv(pmt_t obj, pmt_t alist)
   return PMT_F;
 }
 
+#endif
+
+
 pmt_t
 pmt_assoc(pmt_t obj, pmt_t alist)
 {
@@ -1322,7 +1333,6 @@ pmt_dump_sizeof()
   printf("sizeof(pmt_null)           = %3zd\n", sizeof(pmt_null));
   printf("sizeof(pmt_pair)           = %3zd\n", sizeof(pmt_pair));
   printf("sizeof(pmt_vector)         = %3zd\n", sizeof(pmt_vector));
-  printf("sizeof(pmt_dict)           = %3zd\n", sizeof(pmt_dict));
   printf("sizeof(pmt_uniform_vector) = %3zd\n", sizeof(pmt_uniform_vector));
 }
 
index 7581845f825df373a65951c7d8241e8b60e1f5f9..50683ffb525365ec10d6d39debe350be27d4c59b 100644 (file)
@@ -1,6 +1,6 @@
 /* -*- c++ -*- */
 /*
- * Copyright 2006,2009 Free Software Foundation, Inc.
+ * Copyright 2006,2009,2010 Free Software Foundation, Inc.
  * 
  * This file is part of GNU Radio
  * 
@@ -107,9 +107,9 @@ public:
 
 class pmt_integer : public pmt_base
 {
+public:
   long         d_value;
 
-public:
   pmt_integer(long value);
   //~pmt_integer(){}
 
@@ -120,9 +120,9 @@ public:
 
 class pmt_real : public pmt_base
 {
+public:
   double       d_value;
 
-public:
   pmt_real(double value);
   //~pmt_real(){}
 
@@ -133,9 +133,9 @@ public:
 
 class pmt_complex : public pmt_base
 {
+public:
   std::complex<double> d_value;
 
-public:
   pmt_complex(std::complex<double> value);
   //~pmt_complex(){}
 
@@ -155,10 +155,10 @@ public:
 
 class pmt_pair : public pmt_base
 {
+public:
   pmt_t                d_car;
   pmt_t                d_cdr;
 
-public:
   pmt_pair(const pmt_t& car, const pmt_t& cdr);
   //~pmt_pair(){};
 
@@ -203,23 +203,6 @@ public:
   void _set(size_t k, pmt_t v) { d_v[k] = v; }
 };
 
-class pmt_dict : public pmt_base
-{
-  pmt_t                d_alist;        // list of (key . value) pairs
-
-public:
-  pmt_dict();
-  //~pmt_dict();
-
-  bool  is_dict() const { return true; }
-  void  set(pmt_t key, pmt_t value);
-  pmt_t ref(pmt_t key, pmt_t default_value) const;
-  bool  has_key(pmt_t key) const;
-  pmt_t items() const;
-  pmt_t keys() const;
-  pmt_t values() const;
-};
-
 class pmt_any : public pmt_base
 {
   boost::any   d_any;
index 59d9e14d30a7e257b07e6975a08c490e7cf41c34..f2414c72cdc18528b9c3aebcf63298822473c573 100644 (file)
@@ -1,6 +1,6 @@
 /* -*- c++ -*- */
 /*
- * Copyright 2006,2009 Free Software Foundation, Inc.
+ * Copyright 2006,2009,2010 Free Software Foundation, Inc.
  * 
  * This file is part of GNU Radio
  * 
@@ -36,14 +36,14 @@ qa_pmt_prims::test_symbols()
   CPPUNIT_ASSERT(!pmt_is_symbol(PMT_F));
   CPPUNIT_ASSERT_THROW(pmt_symbol_to_string(PMT_F), pmt_wrong_type);
 
-  pmt_t sym1 = pmt_string_to_symbol("test");
+  pmt_t sym1 = mp("test");
   CPPUNIT_ASSERT(pmt_is_symbol(sym1));
   CPPUNIT_ASSERT_EQUAL(std::string("test"), pmt_symbol_to_string(sym1));
   CPPUNIT_ASSERT(pmt_is_true(sym1));
   CPPUNIT_ASSERT(!pmt_is_false(sym1));
 
-  pmt_t sym2 = pmt_string_to_symbol("foo");
-  pmt_t sym3 = pmt_string_to_symbol("test");
+  pmt_t sym2 = mp("foo");
+  pmt_t sym3 = mp("test");
   CPPUNIT_ASSERT_EQUAL(sym1, sym3);
   CPPUNIT_ASSERT(sym1 != sym2);
   CPPUNIT_ASSERT(sym1 == sym3);
@@ -56,7 +56,7 @@ qa_pmt_prims::test_symbols()
   for (int i = 0; i < N; i++){
     char buf[100];
     snprintf(buf, sizeof(buf), "test-%d", i);
-    v1[i] = pmt_string_to_symbol(buf);
+    v1[i] = mp(buf);
   }
 
   // confirm that they are all unique
@@ -68,7 +68,7 @@ qa_pmt_prims::test_symbols()
   for (int i = 0; i < N; i++){
     char buf[100];
     snprintf(buf, sizeof(buf), "test-%d", i);
-    v2[i] = pmt_string_to_symbol(buf);
+    v2[i] = mp(buf);
   }
 
   // confirm that we get the same ones back
@@ -79,7 +79,7 @@ qa_pmt_prims::test_symbols()
 void
 qa_pmt_prims::test_booleans()
 {
-  pmt_t sym = pmt_string_to_symbol("test");
+  pmt_t sym = mp("test");
   CPPUNIT_ASSERT(pmt_is_bool(PMT_T));
   CPPUNIT_ASSERT(pmt_is_bool(PMT_F));
   CPPUNIT_ASSERT(!pmt_is_bool(sym));
@@ -137,9 +137,9 @@ qa_pmt_prims::test_pairs()
 {
   CPPUNIT_ASSERT(pmt_is_null(PMT_NIL));
   CPPUNIT_ASSERT(!pmt_is_pair(PMT_NIL));
-  pmt_t s1 = pmt_string_to_symbol("s1");
-  pmt_t s2 = pmt_string_to_symbol("s2");
-  pmt_t s3 = pmt_string_to_symbol("s3");
+  pmt_t s1 = mp("s1");
+  pmt_t s2 = mp("s2");
+  pmt_t s3 = mp("s3");
 
 
   CPPUNIT_ASSERT_EQUAL((size_t)0, pmt_length(PMT_NIL));
@@ -174,9 +174,9 @@ qa_pmt_prims::test_vectors()
   static const size_t N = 3;
   pmt_t v1 = pmt_make_vector(N, PMT_NIL);
   CPPUNIT_ASSERT_EQUAL(N, pmt_length(v1));
-  pmt_t s0 = pmt_string_to_symbol("s0");
-  pmt_t s1 = pmt_string_to_symbol("s1");
-  pmt_t s2 = pmt_string_to_symbol("s2");
+  pmt_t s0 = mp("s0");
+  pmt_t s1 = mp("s1");
+  pmt_t s2 = mp("s2");
 
   pmt_vector_set(v1, 0, s0);
   pmt_vector_set(v1, 1, s1);
@@ -213,7 +213,7 @@ qa_pmt_prims::test_tuples()
   for (size_t i = 0; i < 10; i++){
     std::ostringstream os;
     os << "s" << i;
-    s[i] = pmt_string_to_symbol(os.str());
+    s[i] = mp(os.str());
     pmt_vector_set(v, i, s[i]);
   }
 
@@ -282,9 +282,9 @@ qa_pmt_prims::test_tuples()
 void
 qa_pmt_prims::test_equivalence()
 {
-  pmt_t s0 = pmt_string_to_symbol("s0");
-  pmt_t s1 = pmt_string_to_symbol("s1");
-  pmt_t s2 = pmt_string_to_symbol("s2");
+  pmt_t s0 = mp("s0");
+  pmt_t s1 = mp("s1");
+  pmt_t s2 = mp("s2");
   pmt_t list0 = pmt_cons(s0, pmt_cons(s1, pmt_cons(s2, PMT_NIL)));
   pmt_t list1 = pmt_cons(s0, pmt_cons(s1, pmt_cons(s2, PMT_NIL)));
   pmt_t i0 = pmt_from_long(42);
@@ -324,13 +324,13 @@ qa_pmt_prims::test_equivalence()
 void
 qa_pmt_prims::test_misc()
 {
-  pmt_t k0 = pmt_string_to_symbol("k0");
-  pmt_t k1 = pmt_string_to_symbol("k1");
-  pmt_t k2 = pmt_string_to_symbol("k2");
-  pmt_t k3 = pmt_string_to_symbol("k3");
-  pmt_t v0 = pmt_string_to_symbol("v0");
-  pmt_t v1 = pmt_string_to_symbol("v1");
-  pmt_t v2 = pmt_string_to_symbol("v2");
+  pmt_t k0 = mp("k0");
+  pmt_t k1 = mp("k1");
+  pmt_t k2 = mp("k2");
+  pmt_t k3 = mp("k3");
+  pmt_t v0 = mp("v0");
+  pmt_t v1 = mp("v1");
+  pmt_t v2 = mp("v2");
   pmt_t p0 = pmt_cons(k0, v0);
   pmt_t p1 = pmt_cons(k1, v1);
   pmt_t p2 = pmt_cons(k2, v2);
@@ -351,29 +351,31 @@ qa_pmt_prims::test_dict()
   pmt_t dict = pmt_make_dict();
   CPPUNIT_ASSERT(pmt_is_dict(dict));
 
-  pmt_t k0 = pmt_string_to_symbol("k0");
-  pmt_t k1 = pmt_string_to_symbol("k1");
-  pmt_t k2 = pmt_string_to_symbol("k2");
-  pmt_t k3 = pmt_string_to_symbol("k3");
-  pmt_t v0 = pmt_string_to_symbol("v0");
-  pmt_t v1 = pmt_string_to_symbol("v1");
-  pmt_t v2 = pmt_string_to_symbol("v2");
-  pmt_t v3 = pmt_string_to_symbol("v3");
+  pmt_t k0 = mp("k0");
+  pmt_t k1 = mp("k1");
+  pmt_t k2 = mp("k2");
+  pmt_t k3 = mp("k3");
+  pmt_t v0 = mp("v0");
+  pmt_t v1 = mp("v1");
+  pmt_t v2 = mp("v2");
+  pmt_t v3 = mp("v3");
   pmt_t not_found = pmt_cons(PMT_NIL, PMT_NIL);
   
   CPPUNIT_ASSERT(!pmt_dict_has_key(dict, k0));
-  pmt_dict_set(dict, k0, v0);
+  dict = pmt_dict_add(dict, k0, v0);
   CPPUNIT_ASSERT(pmt_dict_has_key(dict, k0));
   CPPUNIT_ASSERT(pmt_eqv(pmt_dict_ref(dict, k0, not_found), v0));
   CPPUNIT_ASSERT(pmt_eqv(pmt_dict_ref(dict, k1, not_found), not_found));
-  pmt_dict_set(dict, k1, v1);
-  pmt_dict_set(dict, k2, v2);
+  dict = pmt_dict_add(dict, k1, v1);
+  dict = pmt_dict_add(dict, k2, v2);
   CPPUNIT_ASSERT(pmt_eqv(pmt_dict_ref(dict, k1, not_found), v1));
-  pmt_dict_set(dict, k1, v3);
+  dict = pmt_dict_add(dict, k1, v3);
   CPPUNIT_ASSERT(pmt_eqv(pmt_dict_ref(dict, k1, not_found), v3));
 
-  pmt_t keys = pmt_cons(k2, pmt_cons(k1, pmt_cons(k0, PMT_NIL)));
-  pmt_t vals = pmt_cons(v2, pmt_cons(v3, pmt_cons(v0, PMT_NIL)));
+  pmt_t keys = pmt_list3(k1, k2, k0);
+  pmt_t vals = pmt_list3(v3, v2, v0);
+  //std::cout << "pmt_dict_keys:   " << pmt_dict_keys(dict) << std::endl;
+  //std::cout << "pmt_dict_values: " << pmt_dict_values(dict) << std::endl;
   CPPUNIT_ASSERT(pmt_equal(keys, pmt_dict_keys(dict)));
   CPPUNIT_ASSERT(pmt_equal(vals, pmt_dict_values(dict)));
 }
@@ -381,10 +383,10 @@ qa_pmt_prims::test_dict()
 void
 qa_pmt_prims::test_io()
 {
-  pmt_t k0 = pmt_string_to_symbol("k0");
-  pmt_t k1 = pmt_string_to_symbol("k1");
-  pmt_t k2 = pmt_string_to_symbol("k2");
-  pmt_t k3 = pmt_string_to_symbol("k3");
+  pmt_t k0 = mp("k0");
+  pmt_t k1 = mp("k1");
+  pmt_t k2 = mp("k2");
+  pmt_t k3 = mp("k3");
 
   CPPUNIT_ASSERT_EQUAL(std::string("k0"), pmt_write_string(k0));
 }
@@ -392,10 +394,10 @@ qa_pmt_prims::test_io()
 void
 qa_pmt_prims::test_lists()
 {
-  pmt_t s0 = pmt_intern("s0");
-  pmt_t s1 = pmt_intern("s1");
-  pmt_t s2 = pmt_intern("s2");
-  pmt_t s3 = pmt_intern("s3");
+  pmt_t s0 = mp("s0");
+  pmt_t s1 = mp("s1");
+  pmt_t s2 = mp("s2");
+  pmt_t s3 = mp("s3");
 
   pmt_t l1 = pmt_list4(s0, s1, s2, s3);
   pmt_t l2 = pmt_list3(s0, s1, s2);
@@ -466,7 +468,7 @@ qa_pmt_msg_accepter_nop::~qa_pmt_msg_accepter_nop(){}
 void
 qa_pmt_prims::test_msg_accepter()
 {
-  pmt_t sym = pmt_intern("my-symbol");
+  pmt_t sym = mp("my-symbol");
 
   boost::any a0;
   a0 = std::string("Hello!");
@@ -493,16 +495,16 @@ void
 qa_pmt_prims::test_serialize()
 {
   std::stringbuf sb;           // fake channel
-  pmt_t a = pmt_intern("a");
-  pmt_t b = pmt_intern("b");
-  pmt_t c = pmt_intern("c");
+  pmt_t a = mp("a");
+  pmt_t b = mp("b");
+  pmt_t c = mp("c");
 
   sb.str("");                  // reset channel to empty
 
   // write stuff to channel
 
   pmt_serialize(PMT_NIL, sb);
-  pmt_serialize(pmt_intern("foobarvia"), sb);
+  pmt_serialize(mp("foobarvia"), sb);
   pmt_serialize(pmt_from_long(123456789), sb);
   pmt_serialize(pmt_from_long(-123456789), sb);
   pmt_serialize(pmt_cons(PMT_NIL, PMT_NIL), sb);
@@ -517,7 +519,7 @@ qa_pmt_prims::test_serialize()
   // read it back
 
   CPPUNIT_ASSERT(pmt_equal(pmt_deserialize(sb), PMT_NIL));
-  CPPUNIT_ASSERT(pmt_equal(pmt_deserialize(sb), pmt_intern("foobarvia")));
+  CPPUNIT_ASSERT(pmt_equal(pmt_deserialize(sb), mp("foobarvia")));
   CPPUNIT_ASSERT(pmt_equal(pmt_deserialize(sb), pmt_from_long(123456789)));
   CPPUNIT_ASSERT(pmt_equal(pmt_deserialize(sb), pmt_from_long(-123456789)));
   CPPUNIT_ASSERT(pmt_equal(pmt_deserialize(sb), pmt_cons(PMT_NIL, PMT_NIL)));
@@ -540,9 +542,9 @@ qa_pmt_prims::test_serialize()
 void
 qa_pmt_prims::test_sets()
 {
-  pmt_t s1 = pmt_intern("s1");
-  pmt_t s2 = pmt_intern("s2");
-  pmt_t s3 = pmt_intern("s3");
+  pmt_t s1 = mp("s1");
+  pmt_t s2 = mp("s2");
+  pmt_t s3 = mp("s3");
 
   pmt_t l1 = pmt_list1(s1);
   pmt_t l2 = pmt_list2(s2,s3);