Merge branch 'grc' from http://gnuradio.org/git/jblum.git into master
authorJohnathan Corgan <jcorgan@corganenterprises.com>
Fri, 4 Sep 2009 22:47:49 +0000 (15:47 -0700)
committerJohnathan Corgan <jcorgan@corganenterprises.com>
Fri, 4 Sep 2009 22:47:49 +0000 (15:47 -0700)
  we dont use test() -> remove it
  Made the window for the pass band filters integers (take firdes.WIN_XXX).
  Evaluation fix in param.to_code().
  Removed the flagging api and usage from the base classes.
  added ref scale param to fft and waterfall
  Switched the python classes to inherit from the base and gui classes.
  port and param types from an overloaded method
  todo
  Replaced TYPES in Port and Param with types parameter.
  made is_virtual_xxx a block level function, used by port and param classes
  added stream id type and checking in evaluate
  avoid loops
  Recursive resolution of virtual sources.
  added virtual source and added stream ids, logic to clone in port
  added rewrite methods to element to separate from validation logic
  Added virtual sink and logic to clone port.
  removed repurposing of pads
  Work on command line options for generated code.
  renamed the colors dialog to types
  use pkgpythondir
  ...

48 files changed:
config/gr_fortran.m4
configure.ac
gnuradio-core/src/lib/filter/Makefile.am
gnuradio-core/src/lib/filter/filter.i
gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.cc [new file with mode: 0644]
gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.h [new file with mode: 0644]
gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.i [new file with mode: 0644]
gnuradio-core/src/lib/general/gr_constants.cc.in
gnuradio-core/src/lib/general/gr_constants.h
gnuradio-core/src/lib/general/gr_constants.i
gnuradio-core/src/lib/gnuradio-config-info.cc
gnuradio-core/src/python/gnuradio/blks2impl/logpwrfft.py
gr-vrt/src/vrt_quadradio_source_32fc.cc
gr-vrt/src/vrt_quadradio_source_32fc.h
gr-wxgui/src/python/common.py
gr-wxgui/src/python/fft_window.py
gr-wxgui/src/python/plotter/waterfall_plotter.py
gr-wxgui/src/python/scopesink_gl.py
gr-wxgui/src/python/waterfall_window.py
grc/blocks/usrp2_sink_xxxx.xml
grc/blocks/usrp2_source_xxxx.xml
grc/blocks/usrp_dual_sink_x.xml
grc/blocks/usrp_dual_source_x.xml
grc/blocks/usrp_simple_sink_x.xml
grc/blocks/usrp_simple_source_x.xml
grc/grc_gnuradio/usrp/dual_usrp.py
grc/grc_gnuradio/usrp/simple_usrp.py
gruel/src/include/gruel/Makefile.am
gruel/src/include/gruel/msg_accepter.h
gruel/src/include/gruel/msg_passing.h [new file with mode: 0644]
gruel/src/include/gruel/pmt.h
gruel/src/include/gruel/pmt_sugar.h [new file with mode: 0644]
gruel/src/include/gruel/send.h [deleted file]
gruel/src/lib/Makefile.am
gruel/src/lib/pmt/Makefile.am
gruel/src/lib/pmt/pmt.cc
gruel/src/lib/pmt/qa_pmt_prims.cc
gruel/src/lib/pmt/qa_pmt_prims.h
gruel/src/lib/pmt/test_pmt.cc [deleted file]
gruel/src/lib/test_gruel.cc [new file with mode: 0644]
usrp/host/lib/db_flexrf.cc
usrp2/firmware/lib/db_rfx.c
usrp2/host/lib/control.cc
usrp2/host/lib/control.h
usrp2/host/lib/usrp2_impl.cc
usrp2/host/lib/usrp2_impl.h
vrt/include/vrt/quadradio.h
vrt/lib/quadradio.cc

index b5b0470f45c2ce78cb525490bf56d32b0548f140..a558b2f7e3f00eaecddd39bc5248a0ece883c543 100644 (file)
@@ -28,5 +28,6 @@ AC_DEFUN([GR_FORTRAN],[
     then
         AC_PROG_F77
         AC_F77_LIBRARY_LDFLAGS
+       AC_PROG_CC dnl bux fix to restore $ac_ext
     fi
 ])
index 1764b46abe2abad7cb054ca2a6abae3d1771a465..2bb37935e9a4cb1ef10b664c6a1463f13368a064 100644 (file)
@@ -286,9 +286,6 @@ dnl AX_BOOST_TEST_EXEC_MONITOR
 dnl AX_BOOST_UNIT_TEST_FRAMEWORK
 dnl AX_BOOST_WSERIALIZATION
 
-
-dnl If this is being done from a subversion tree, create variables
-GR_SUBVERSION
 BUILD_DATE=`date -R -u`
 AC_SUBST(BUILD_DATE)
 
index 838f69b92d39163d50c70719e664bef960121eb3..d5afd571bac31bd10aba7d3f30858bae6a9b130f 100644 (file)
@@ -205,7 +205,8 @@ libfilter_la_common_SOURCES =               \
        gr_pfb_channelizer_ccf.cc       \
        gr_pfb_decimator_ccf.cc         \
        gr_pfb_interpolator_ccf.cc      \
-       gr_pfb_arb_resampler_ccf.cc
+       gr_pfb_arb_resampler_ccf.cc     \
+       gr_pfb_clock_sync_ccf.cc
 
 libfilter_qa_la_common_SOURCES =       \
        qa_filter.cc                    \
@@ -284,7 +285,8 @@ grinclude_HEADERS =                         \
        gr_pfb_channelizer_ccf.h        \
        gr_pfb_decimator_ccf.h          \
        gr_pfb_interpolator_ccf.h       \
-       gr_pfb_arb_resampler_ccf.h
+       gr_pfb_arb_resampler_ccf.h      \
+       gr_pfb_clock_sync_ccf.h
 
 noinst_HEADERS =                       \
        assembly.h                      \
@@ -339,6 +341,7 @@ swiginclude_HEADERS =                       \
        gr_pfb_decimator_ccf.i          \
        gr_pfb_interpolator_ccf.i       \
        gr_pfb_arb_resampler_ccf.i      \
+       gr_pfb_clock_sync_ccf.i         \
        $(GENERATED_I)
 endif
 
index 16b8005be5072b272895588a96d31591fc7c1e58..91f55c5142610326c137b57510a13490ce7d7141 100644 (file)
@@ -36,6 +36,7 @@
 #include <gr_pfb_decimator_ccf.h>
 #include <gr_pfb_interpolator_ccf.h>
 #include <gr_pfb_arb_resampler_ccf.h>
+#include <gr_pfb_clock_sync_ccf.h>
 %}
 
 %include "gr_iir_filter_ffd.i"
@@ -56,5 +57,6 @@
 %include "gr_pfb_decimator_ccf.i"
 %include "gr_pfb_interpolator_ccf.i"
 %include "gr_pfb_arb_resampler_ccf.i"
+%include "gr_pfb_clock_sync_ccf.i"
 
 %include "filter_generated.i"
diff --git a/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.cc b/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.cc
new file mode 100644 (file)
index 0000000..91cbf74
--- /dev/null
@@ -0,0 +1,258 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2009 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 <cstdio>
+#include <cmath>
+
+#include <gr_pfb_clock_sync_ccf.h>
+#include <gr_fir_ccf.h>
+#include <gr_fir_util.h>
+#include <gr_io_signature.h>
+#include <gr_math.h>
+
+gr_pfb_clock_sync_ccf_sptr gr_make_pfb_clock_sync_ccf (float sps, float gain,
+                                                      const std::vector<float> &taps,
+                                                      unsigned int filter_size,
+                                                      float init_phase)
+{
+  return gr_pfb_clock_sync_ccf_sptr (new gr_pfb_clock_sync_ccf (sps, gain, taps,
+                                                               filter_size,
+                                                               init_phase));
+}
+
+
+gr_pfb_clock_sync_ccf::gr_pfb_clock_sync_ccf (float sps, float gain,
+                                             const std::vector<float> &taps,
+                                             unsigned int filter_size,
+                                             float init_phase)
+  : gr_block ("pfb_clock_sync_ccf",
+             gr_make_io_signature (1, 1, sizeof(gr_complex)),
+             gr_make_io_signature2 (2, 2, sizeof(gr_complex), sizeof(float))),
+    d_updated (false), d_sps(sps), d_alpha(gain)
+{
+  d_nfilters = filter_size;
+
+  // Store the last filter between calls to work
+  // The accumulator keeps track of overflow to increment the stride correctly.
+  // set it here to the fractional difference based on the initial phaes
+  // assert(init_phase <= 2*M_PI);
+  float x = init_phase / (2*M_PI); //normalize initial phase
+  d_acc = x*(d_nfilters-1);
+  d_last_filter = (int)floor(d_acc);
+  d_acc = fmodf(d_acc, 1);
+  d_start_count = 0;
+  
+
+  d_filters = std::vector<gr_fir_ccf*>(d_nfilters);
+  d_diff_filters = std::vector<gr_fir_ccf*>(d_nfilters);
+
+  // Create an FIR filter for each channel and zero out the taps
+  std::vector<float> vtaps(0, d_nfilters);
+  for(unsigned int i = 0; i < d_nfilters; i++) {
+    d_filters[i] = gr_fir_util::create_gr_fir_ccf(vtaps);
+    d_diff_filters[i] = gr_fir_util::create_gr_fir_ccf(vtaps);
+  }
+
+  // Now, actually set the filters' taps
+  std::vector<float> dtaps;
+  create_diff_taps(taps, dtaps);
+  set_taps(taps, d_taps, d_filters);
+  set_taps(dtaps, d_dtaps, d_diff_filters);
+}
+
+gr_pfb_clock_sync_ccf::~gr_pfb_clock_sync_ccf ()
+{
+  for(unsigned int i = 0; i < d_nfilters; i++) {
+    delete d_filters[i];
+  }
+}
+
+void
+gr_pfb_clock_sync_ccf::set_taps (const std::vector<float> &newtaps,
+                                std::vector< std::vector<float> > &ourtaps,
+                                std::vector<gr_fir_ccf*> &ourfilter)
+{
+  unsigned int i,j;
+
+  unsigned int ntaps = newtaps.size();
+  d_taps_per_filter = (unsigned int)ceil((double)ntaps/(double)d_nfilters);
+
+  // Create d_numchan vectors to store each channel's taps
+  ourtaps.resize(d_nfilters);
+  
+  // Make a vector of the taps plus fill it out with 0's to fill
+  // each polyphase filter with exactly d_taps_per_filter
+  std::vector<float> tmp_taps;
+  tmp_taps = newtaps;
+  while((float)(tmp_taps.size()) < d_nfilters*d_taps_per_filter) {
+    tmp_taps.push_back(0.0);
+  }
+  
+  // Partition the filter
+  for(i = 0; i < d_nfilters; i++) {
+    // Each channel uses all d_taps_per_filter with 0's if not enough taps to fill out
+    ourtaps[i] = std::vector<float>(d_taps_per_filter, 0);
+    for(j = 0; j < d_taps_per_filter; j++) {
+      ourtaps[i][j] = tmp_taps[i + j*d_nfilters];  // add taps to channels in reverse order
+    }
+    
+    // Build a filter for each channel and add it's taps to it
+    ourfilter[i]->set_taps(ourtaps[i]);
+  }
+
+  // Set the history to ensure enough input items for each filter
+  set_history (d_taps_per_filter + d_sps);
+
+  d_updated = true;
+}
+
+void
+gr_pfb_clock_sync_ccf::create_diff_taps(const std::vector<float> &newtaps,
+                                       std::vector<float> &difftaps)
+{
+  difftaps.clear();
+  difftaps.push_back(0); //newtaps[0]);
+  for(unsigned int i = 1; i < newtaps.size()-1; i++) {
+    difftaps.push_back(newtaps[i+1] - newtaps[i-1]);
+  }
+  difftaps.push_back(0);//-newtaps[newtaps.size()-1]);
+}
+
+void
+gr_pfb_clock_sync_ccf::print_taps()
+{
+  unsigned int i, j;
+  for(i = 0; i < d_nfilters; i++) {
+    printf("filter[%d]: [%.4e, ", i, d_taps[i][0]);
+    for(j = 1; j < d_taps_per_filter-1; j++) {
+      printf("%.4e,", d_taps[i][j]);
+    }
+    printf("%.4e]\n", d_taps[i][j]);
+  }
+}
+
+void
+gr_pfb_clock_sync_ccf::print_diff_taps()
+{
+  unsigned int i, j;
+  for(i = 0; i < d_nfilters; i++) {
+    printf("filter[%d]: [%.4e, ", i, d_dtaps[i][0]);
+    for(j = 1; j < d_taps_per_filter-1; j++) {
+      printf("%.4e,", d_dtaps[i][j]);
+    }
+    printf("%.4e]\n", d_dtaps[i][j]);
+  }
+}
+
+
+std::vector<float>
+gr_pfb_clock_sync_ccf::channel_taps(int channel)
+{
+  std::vector<float> taps;
+  unsigned int i;
+  for(i = 0; i < d_taps_per_filter; i++) {
+    taps.push_back(d_taps[channel][i]);
+  }
+  return taps;
+}
+
+std::vector<float>
+gr_pfb_clock_sync_ccf::diff_channel_taps(int channel)
+{
+  std::vector<float> taps;
+  unsigned int i;
+  for(i = 0; i < d_taps_per_filter; i++) {
+    taps.push_back(d_dtaps[channel][i]);
+  }
+  return taps;
+}
+
+
+int
+gr_pfb_clock_sync_ccf::general_work (int noutput_items,
+                                    gr_vector_int &ninput_items,
+                                    gr_vector_const_void_star &input_items,
+                                    gr_vector_void_star &output_items)
+{
+  gr_complex *in = (gr_complex *) input_items[0];
+  gr_complex *out = (gr_complex *) output_items[0];
+  float *err = (float *) output_items[1];
+  
+  if (d_updated) {
+    d_updated = false;
+    return 0;               // history requirements may have changed.
+  }
+
+  // We need this many to process one output
+  int nrequired = ninput_items[0] - d_taps_per_filter;
+
+  int i = 0, count = d_start_count;
+  float error = 0;
+
+  // produce output as long as we can and there are enough input samples
+  while((i < noutput_items) && (count < nrequired)) {
+    out[i] = d_filters[d_last_filter]->filter(&in[count]);
+    error =  (out[i] * d_diff_filters[d_last_filter]->filter(&in[count])).real();
+    err[i] = error;
+
+    d_acc += d_alpha*error;
+    gr_branchless_clip(d_acc, 1);
+
+    int newfilter;
+    newfilter = (int)((float)d_last_filter + d_acc);
+    if(newfilter != (int)d_last_filter)
+      d_acc = 0.5;
+
+    if(newfilter >= (int)d_nfilters) {
+      d_last_filter = newfilter - d_nfilters;
+      count++;
+    }
+    else if(newfilter < 0) {
+      d_last_filter = d_nfilters + newfilter;
+      count--;
+    }
+    else {
+      d_last_filter = newfilter;
+    }
+
+    i++;
+    count += d_sps;
+  }
+
+  // Set the start index at the next entrance to the work function
+  // if we stop because we run out of input items, jump ahead in the
+  // next call to work. Otherwise, we can start at zero.
+  if(count > nrequired) {
+    d_start_count = count - (nrequired);
+    consume_each(ninput_items[0]-d_taps_per_filter);
+  }
+  else {
+    d_start_count = 0;
+    consume_each(count);
+  }
+  
+  return i;
+}
diff --git a/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.h b/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.h
new file mode 100644 (file)
index 0000000..1a04e55
--- /dev/null
@@ -0,0 +1,106 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2009 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_GR_PFB_CLOCK_SYNC_CCF_H
+#define        INCLUDED_GR_PFB_CLOCK_SYNC_CCF_H
+
+#include <gr_block.h>
+
+class gr_pfb_clock_sync_ccf;
+typedef boost::shared_ptr<gr_pfb_clock_sync_ccf> gr_pfb_clock_sync_ccf_sptr;
+gr_pfb_clock_sync_ccf_sptr gr_make_pfb_clock_sync_ccf (float sps, float gain,
+                                                          const std::vector<float> &taps,
+                                                          unsigned int filter_size=32,
+                                                          float init_phase=0);
+
+class gr_fir_ccf;
+
+/*!
+ * \class gr_pfb_clock_sync_ccf
+ *
+ * \brief Timing synchronizer using polyphase filterbanks
+ *
+ * \ingroup filter_blk
+ * 
+ */
+
+class gr_pfb_clock_sync_ccf : public gr_block
+{
+ private:
+  /*!
+   * Build the polyphase filterbank timing synchronizer.
+   */
+  friend gr_pfb_clock_sync_ccf_sptr gr_make_pfb_clock_sync_ccf (float sps, float gain,
+                                                               const std::vector<float> &taps,
+                                                               unsigned int filter_size,
+                                                               float init_phase);
+
+  bool                    d_updated;
+  unsigned int             d_sps;
+  float                    d_alpha;
+  unsigned int             d_nfilters;
+  std::vector<gr_fir_ccf*> d_filters;
+  std::vector<gr_fir_ccf*> d_diff_filters;
+  std::vector< std::vector<float> > d_taps;
+  std::vector< std::vector<float> > d_dtaps;
+  float                    d_acc;
+  unsigned int             d_last_filter;
+  unsigned int             d_start_count;
+  unsigned int             d_taps_per_filter;
+
+  /*!
+   * Build the polyphase filterbank timing synchronizer.
+   */
+  gr_pfb_clock_sync_ccf (float sps, float gain,
+                        const std::vector<float> &taps,
+                        unsigned int filter_size,
+                        float init_phase);
+  
+  void create_diff_taps(const std::vector<float> &newtaps,
+                       std::vector<float> &difftaps);
+
+public:
+  ~gr_pfb_clock_sync_ccf ();
+  
+  /*!
+   * Resets the filterbank's filter taps with the new prototype filter
+   */
+  void set_taps (const std::vector<float> &taps,
+                std::vector< std::vector<float> > &ourtaps,
+                std::vector<gr_fir_ccf*> &ourfilter);
+  std::vector<float> channel_taps(int channel);
+  std::vector<float> diff_channel_taps(int channel);
+
+  /*!
+   * Print all of the filterbank taps to screen.
+   */
+  void print_taps();
+  void print_diff_taps();
+  
+  int general_work (int noutput_items,
+                   gr_vector_int &ninput_items,
+                   gr_vector_const_void_star &input_items,
+                   gr_vector_void_star &output_items);
+};
+
+#endif
diff --git a/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.i b/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.i
new file mode 100644 (file)
index 0000000..729d4a1
--- /dev/null
@@ -0,0 +1,49 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2009 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.
+ */
+
+GR_SWIG_BLOCK_MAGIC(gr,pfb_clock_sync_ccf);
+
+gr_pfb_clock_sync_ccf_sptr gr_make_pfb_clock_sync_ccf (float sps, float gain,
+                                                      const std::vector<float> &taps,
+                                                      unsigned int filter_size=32,
+                                                      float init_phase=0);
+
+class gr_pfb_clock_sync_ccf : public gr_block
+{
+ private:
+  gr_pfb_clock_sync_ccf (float sps, float gain,
+                        const std::vector<float> &taps,
+                        unsigned int filter_size,
+                        float init_phase);
+
+ public:
+  ~gr_pfb_clock_sync_ccf ();
+
+  void set_taps (const std::vector<float> &taps,
+                std::vector< std::vector<float> > &ourtaps,
+                std::vector<gr_fir_ccf*> &ourfilter);
+
+  std::vector<float> channel_taps(int channel);
+  std::vector<float> diff_channel_taps(int channel);
+  void print_taps();
+  void print_diff_taps();
+};
index efb0f1c776695e7ef259ec2b8c7e0322fdbedba8..71a47eb5102450aeb6bb79dd9f49ecc00cbebe49 100644 (file)
@@ -50,18 +50,6 @@ gr_build_date()
   return "@BUILD_DATE@";
 }
 
-const std::string
-gr_svn_date()
-{
-  return "@SVNDATE@";
-}
-
-const std::string
-gr_svn_version()
-{
-  return "@SVNVERSION@";
-}
-
 const std::string
 gr_version()
 {
index e44890be0176061810972004b2a7a7d26e1c264c..449d41c174c1461414f4444908d006c8cb5d921c 100644 (file)
@@ -44,16 +44,6 @@ const std::string gr_prefsdir();
  */
 const std::string gr_build_date();
 
-/*!
- * \brief return repository date as set when 'bootstrap' is run
- */
-const std::string gr_svn_date();
-
-/*!
- * \brief return repository version as set when 'bootstrap' is run
- */
-const std::string gr_svn_version();
-
 /*!
  * \brief return version string defined in configure.ac
  */
index 156af4a3655fbae0a15382d349d434e2b3fcf50e..a5aef14925da5e1103c2296c23eb2ef4f6732e58 100644 (file)
@@ -4,14 +4,10 @@
 %rename(sysconfdir) gr_sysconfdir;
 %rename(prefsdir) gr_prefsdir;
 %rename(build_date) gr_build_date;
-%rename(svn_date) gr_svn_date;
-%rename(svn_version) gr_svn_version;
 %rename(version) gr_version;
 
 const std::string gr_prefix();
 const std::string gr_sysconfdir();
 const std::string gr_prefsdir();
 const std::string gr_build_date();
-const std::string gr_svn_date();
-const std::string gr_svn_version();
 const std::string gr_version();
index df78ea2ddf9bea047de6d65e86520d92fd31a242..6fa53b87762954b8bfe8aa55d0366c92a7ffb57f 100644 (file)
@@ -43,8 +43,6 @@ main(int argc, char **argv)
     ("prefsdir", "print gnuradio preferences directory")
     ("builddate", "print gnuradio build date (RFC2822 format)")
     ("version,v", "print gnuradio version")
-    ("svnversion", "print SVN repository version (SVN format)")
-    ("svndate", "print SVN repository date")
     ;
 
   po::store(po::parse_command_line(argc, argv, desc), vm);
@@ -70,11 +68,5 @@ main(int argc, char **argv)
   if (vm.count("version"))
     std::cout << gr_version() << std::endl;
 
-  if (vm.count("svnversion"))
-    std::cout << gr_svn_version() << std::endl;
-
-  if (vm.count("svndate"))
-    std::cout << gr_svn_date() << std::endl;
-
   return 0;
 }
index cf8eb1be78597fae71ed617307ddf4e707e0e7f4..7ef40be40a92bb4f55a872e05802e95fd2b3f0c2 100644 (file)
@@ -55,9 +55,9 @@ class _logpwrfft_base(gr.hier_block2):
         c2mag = gr.complex_to_mag(fft_size)
         self._avg = gr.single_pole_iir_filter_ff(1.0, fft_size)
         self._log = gr.nlog10_ff(20, fft_size,
-                                 -10*math.log10(fft_size)              # Adjust for number of bins
+                                 -20*math.log10(fft_size)              # Adjust for number of bins
                                  -10*math.log10(window_power/fft_size) # Adjust for windowing loss
-                                 -20*math.log10(ref_scale/2))          # Adjust for reference scale
+                                 -20*math.log10(ref_scale/2)+3.0)      # Adjust for reference scale
         self.connect(self, self._sd, fft, c2mag, self._avg, self._log, self)
 
         self._average = average
index 0321062aa93e015ae60118570719c4aed8aea5b3..0aac86991f074edc216b47a8452059d20cafc435 100644 (file)
@@ -86,9 +86,15 @@ vrt_quadradio_source_32fc::set_center_freq(double target_freq)
 }
 
 bool 
-vrt_quadradio_source_32fc::set_band_select(const std::string &band)
+vrt_quadradio_source_32fc::set_band_select(int band)
 {
-  return d_qr->set_band_select(band);
+  return d_qr->set_band_select(static_cast<vrt_band_sel_t>(band));
+}
+
+int 
+vrt_quadradio_source_32fc::get_band_select(void)
+{
+  return static_cast<int>(d_qr->get_band_select());
 }
 
 //void 
@@ -210,3 +216,7 @@ vrt_quadradio_source_32fc::set_beamforming(std::vector<gr_complex> gains){
  return d_qr->set_beamforming(gains_ints);
 }
 
+bool
+vrt_quadradio_source_32fc::set_cal_enb(bool enb){
+  return d_qr->set_cal_enb(enb);
+}
index 6ad63f7be46784f99aae3e54d52ca461c7e1206d..6193efa102bde88943b1833a36c3f9fa62e35c2e 100644 (file)
@@ -68,9 +68,9 @@ public:
 
   /*!
    * \brief Set the band select dboard bits.
-   * \param band "A", "B", "C", "D"
    */
-  bool set_band_select(const std::string &band);
+  bool set_band_select(int band);
+  int get_band_select(void);
 
   /*!
    * \brief Turn the 10 dB attenuation on/off.
@@ -109,6 +109,7 @@ public:
   bool set_lo_freq(double freq);
   bool set_cal_freq(double freq);
   bool set_beamforming(std::vector<gr_complex> gains);
+  bool set_cal_enb(bool enb);
 };
 
 
index d555a1f055a9c3b824e2b71cb0c793c0ec562fcb..9c97ce1ecad898a32e1871f9445c42713db7fd9e 100644 (file)
@@ -137,6 +137,25 @@ def get_min_max(samples):
        scale_factor = 3
        mean = numpy.average(samples)
        rms = numpy.max([scale_factor*((numpy.sum((samples-mean)**2)/len(samples))**.5), .1])
-       min = mean - rms
-       max = mean + rms
-       return min, max
+       min_val = mean - rms
+       max_val = mean + rms
+       return min_val, max_val
+
+def get_min_max_fft(fft_samps):
+       """
+       Get the minimum and maximum bounds for an array of fft samples.
+       @param samples the array of real values
+       @return a tuple of min, max
+       """
+       #get the peak level (max of the samples)
+       peak_level = numpy.max(fft_samps)
+       #separate noise samples
+       noise_samps = numpy.sort(fft_samps)[:len(fft_samps)/2]
+       #get the noise floor
+       noise_floor = numpy.average(noise_samps)
+       #get the noise deviation
+       noise_dev = numpy.std(noise_samps)
+       #determine the maximum and minimum levels
+       max_level = peak_level
+       min_level = noise_floor - abs(2*noise_dev)
+       return min_level, max_level
index 926812d8cedcc0b30375a4a898b762fb9e10e34f..e025c28dd71872679776064878c26be1970a03e7 100644 (file)
@@ -254,17 +254,11 @@ class fft_window(wx.Panel, pubsub.pubsub):
                Set the dynamic range and reference level.
                """
                if not len(self.samples): return
-               #get the peak level (max of the samples)
-               peak_level = numpy.max(self.samples)
-               #get the noise floor (averge the smallest samples)
-               noise_floor = numpy.average(numpy.sort(self.samples)[:len(self.samples)/4])
-               #padding
-               noise_floor -= abs(noise_floor)*.5
-               peak_level += abs(peak_level)*.1
-               #set the reference level to a multiple of y divs
-               self[REF_LEVEL_KEY] = self[Y_DIVS_KEY]*math.ceil(peak_level/self[Y_DIVS_KEY])
+               min_level, max_level = common.get_min_max_fft(self.samples)
                #set the range to a clean number of the dynamic range
-               self[Y_PER_DIV_KEY] = common.get_clean_num((peak_level - noise_floor)/self[Y_DIVS_KEY])
+               self[Y_PER_DIV_KEY] = common.get_clean_num(1+(max_level - min_level)/self[Y_DIVS_KEY])
+               #set the reference level to a multiple of y per div
+               self[REF_LEVEL_KEY] = self[Y_PER_DIV_KEY]*round(.5+max_level/self[Y_PER_DIV_KEY])
 
        def _reset_peak_vals(self, *args): self.peak_vals = EMPTY_TRACE
 
index 2e0669961badf81da5e6494186746600bc47145a..d32b0ca0a631f07935c78654d70337bbf4e02328 100644 (file)
@@ -209,7 +209,7 @@ class waterfall_plotter(grid_plotter_base):
                self._pointer = 0
                if self._num_lines and self._fft_size:
                        GL.glBindTexture(GL.GL_TEXTURE_2D, self._waterfall_texture)
-                       data = numpy.zeros(self._num_lines*self._fft_size*4, numpy.uint8).tostring()
+                       data = numpy.zeros(self._num_lines*ceil_log2(self._fft_size)*4, numpy.uint8).tostring()
                        GL.glTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_RGBA, ceil_log2(self._fft_size), self._num_lines, 0, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, data)
                self._resize_texture_flag = False
 
index b4ae0f3391df3a86b51e5b20dbcd7a746a05ba6e..a5e3ca3ce32fc7f9c40fd305d5c7fd4bd2d709e5 100644 (file)
@@ -50,7 +50,7 @@ class ac_couple_block(gr.hier_block2):
                self.connect(self, lpf, mute, (sub, 1))
                #subscribe
                controller.subscribe(ac_couple_key, lambda x: mute.set_mute(not x))
-               controller.subscribe(sample_rate_key, lambda x: lpf.set_taps(2.0/x))
+               controller.subscribe(sample_rate_key, lambda x: lpf.set_taps(0.05))
                #initialize
                controller[ac_couple_key] = ac_couple
                controller[sample_rate_key] = controller[sample_rate_key]
index c00992e14fee13598112a12beeb8411852daaa60..28e67a83006aa6af3123107fe4d3f79db06062d6 100644 (file)
@@ -237,16 +237,10 @@ class waterfall_window(wx.Panel, pubsub.pubsub):
                Does not affect the current data in the waterfall.
                """
                if not len(self.samples): return
-               #get the peak level (max of the samples)
-               peak_level = numpy.max(self.samples)
-               #get the noise floor (averge the smallest samples)
-               noise_floor = numpy.average(numpy.sort(self.samples)[:len(self.samples)/4])
-               #padding
-               noise_floor -= abs(noise_floor)*.5
-               peak_level += abs(peak_level)*.1
+               min_level, max_level = common.get_min_max_fft(self.samples)
                #set the range and level
-               self[REF_LEVEL_KEY] = peak_level
-               self[DYNAMIC_RANGE_KEY] = peak_level - noise_floor
+               self[REF_LEVEL_KEY] = max_level
+               self[DYNAMIC_RANGE_KEY] = max_level - min_level
 
        def handle_msg(self, msg):
                """
index 639f96cf48bffd08bfcb4aeda0c09f46c0975fca..f2ee4d151f8b9834cc60d7a1691b1458ee8cf7c8 100644 (file)
@@ -2,6 +2,7 @@
 <!--
 ###################################################
 ##USRP2 Sink
+##  Note: the center freq must be set after the lo offset
 ###################################################
  -->
 <block>
@@ -16,14 +17,16 @@ usrp2.sink_$(type.fcn)($interface)
 usrp2.sink_$(type.fcn)($interface, $mac_addr)
 #end if
 self.$(id).set_interp($interpolation)
-self.$(id).set_center_freq($frequency)
-self.$(id).set_gain($gain)
 #if $lo_offset() != float('inf')
 self.$(id).set_lo_offset($lo_offset)
-#end if</make>
-       <callback>set_lo_offset($lo_offset)</callback>
+#end if
+self.$(id).set_center_freq($frequency)
+self.$(id).set_gain($gain)</make>
        <callback>set_interp($interpolation)</callback>
-       <callback>set_center_freq($frequency)</callback>
+       <callback>#if $lo_offset() != float('inf')
+self.$(id).set_lo_offset($lo_offset)
+#end if
+self.$(id).set_center_freq($frequency)</callback>
        <callback>set_gain($gain)</callback>
        <param>
                <name>Output Type</name>
index 6c776d0ad37deaa54f32b3d7b570eb717a0caf37..02046e609a37b1f4ae2310e5362f0139e88d0db4 100644 (file)
@@ -2,6 +2,7 @@
 <!--
 ###################################################
 ##USRP2 Source
+##  Note: the center freq must be set after the lo offset
 ###################################################
  -->
 <block>
@@ -16,14 +17,16 @@ usrp2.source_$(type.fcn)($interface)
 usrp2.source_$(type.fcn)($interface, $mac_addr)
 #end if
 self.$(id).set_decim($decimation)
-self.$(id).set_center_freq($frequency)
-self.$(id).set_gain($gain)
 #if $lo_offset() != float('inf')
 self.$(id).set_lo_offset($lo_offset)
-#end if</make>
-       <callback>set_lo_offset($lo_offset)</callback>
+#end if
+self.$(id).set_center_freq($frequency)
+self.$(id).set_gain($gain)</make>
        <callback>set_decim($decimation)</callback>
-       <callback>set_center_freq($frequency)</callback>
+       <callback>#if $lo_offset() != float('inf')
+self.$(id).set_lo_offset($lo_offset)
+#end if
+self.$(id).set_center_freq($frequency)</callback>
        <callback>set_gain($gain)</callback>
        <param>
                <name>Output Type</name>
index 8f418becdba36e2db73eb4eded6e5827a62ceadd..4539b62f9527f1ef552022baa0f02a7c1e8d4a7b 100644 (file)
        <import>from grc_gnuradio import usrp as grc_usrp</import>
        <make>grc_usrp.dual_sink_$(type.fcn)(which=$which)
 self.$(id).set_interp_rate($interpolation)
-self.$(id).set_frequency_a($frequency_a, verbose=True)
-self.$(id).set_frequency_b($frequency_b, verbose=True)
-self.$(id).set_gain_a($gain_a)
-self.$(id).set_gain_b($gain_b)
+self.$(id).set_frequency_a($frequency_a, verbose=True#slurp
 #if $lo_offset_a() != float('inf')
-self.$(id).set_lo_offset_a($lo_offset_a)
+, lo_offset=$lo_offset_a#slurp
 #end if
+)
+self.$(id).set_frequency_b($frequency_b, verbose=True#slurp
 #if $lo_offset_b() != float('inf')
-self.$(id).set_lo_offset_b($lo_offset_b)
+, lo_offset=$lo_offset_b#slurp
 #end if
+)
+self.$(id).set_gain_a($gain_a)
+self.$(id).set_gain_b($gain_b)
 ##################################################
 ## Flex RF A
 ##################################################
@@ -39,8 +41,16 @@ self.$(id).set_enable_b(True)
 self.$(id).set_auto_tr_b(True)
 #end if</make>
        <callback>set_interp_rate($interpolation)</callback>
-       <callback>set_frequency_a($frequency_a)</callback>
-       <callback>set_frequency_b($frequency_b)</callback>
+       <callback>set_frequency_a($frequency_a#slurp
+#if $lo_offset_a() != float('inf')
+, lo_offset=$lo_offset_a#slurp
+#end if
+)</callback>
+       <callback>set_frequency_b($frequency_b#slurp
+#if $lo_offset_b() != float('inf')
+, lo_offset=$lo_offset_b#slurp
+#end if
+)</callback>
        <callback>set_gain_a($gain_a)</callback>
        <callback>set_gain_b($gain_b)</callback>
        <param>
index 740895d424697b8712c86c74a0ebba30cdb65f15..ad9a860ac3afd94ee2ca3424d61f335c47c24751 100644 (file)
 self.$(id).set_format(width=$format.width, shift=$format.shift)
 #end if
 self.$(id).set_decim_rate($decimation)
-self.$(id).set_frequency_a($frequency_a, verbose=True)
-self.$(id).set_frequency_b($frequency_b, verbose=True)
-self.$(id).set_gain_a($gain_a)
-self.$(id).set_gain_b($gain_b)
+self.$(id).set_frequency_a($frequency_a, verbose=True#slurp
 #if $lo_offset_a() != float('inf')
-self.$(id).set_lo_offset_a($lo_offset_a)
+, lo_offset=$lo_offset_a#slurp
 #end if
+)
+self.$(id).set_frequency_b($frequency_b, verbose=True#slurp
 #if $lo_offset_b() != float('inf')
-self.$(id).set_lo_offset_b($lo_offset_b)
-#end if</make>
+, lo_offset=$lo_offset_b#slurp
+#end if
+)
+self.$(id).set_gain_a($gain_a)
+self.$(id).set_gain_b($gain_b)</make>
        <callback>set_decim_rate($decimation)</callback>
-       <callback>set_frequency_a($frequency_a)</callback>
-       <callback>set_frequency_b($frequency_b)</callback>
+       <callback>set_frequency_a($frequency_a#slurp
+#if $lo_offset_a() != float('inf')
+, lo_offset=$lo_offset_a#slurp
+#end if
+)</callback>
+       <callback>set_frequency_b($frequency_b#slurp
+#if $lo_offset_b() != float('inf')
+, lo_offset=$lo_offset_b#slurp
+#end if
+)</callback>
        <callback>set_gain_a($gain_a)</callback>
        <callback>set_gain_b($gain_b)</callback>
        <param>
index f3ccf1263c5671dfdb1da27ac3114f7eb1418dbf..b52cd4880913a2357c57227255e75bc1cc75c70e 100644 (file)
        <import>from grc_gnuradio import usrp as grc_usrp</import>
        <make>grc_usrp.simple_sink_$(type.fcn)(which=$which, side=$side)
 self.$(id).set_interp_rate($interpolation)
-self.$(id).set_frequency($frequency, verbose=True)
+self.$(id).set_frequency($frequency, verbose=True#slurp
+#if $lo_offset() != float('inf')
+, lo_offset=$lo_offset#slurp
+#end if
+)
 self.$(id).set_gain($gain)
 #if $transmit.tx_enb
 self.$(id).set_enable(True)
 #end if
 #if $transmit.auto_tr
 self.$(id).set_auto_tr(True)
-#end if
-#if $lo_offset() != float('inf')
-self.$(id).set_lo_offset($lo_offset)
 #end if</make>
-       <callback>set_lo_offset($lo_offset)</callback>
        <callback>set_interp_rate($interpolation)</callback>
-       <callback>set_frequency($frequency)</callback>
+       <callback>set_frequency($frequency#slurp
+#if $lo_offset() != float('inf')
+, lo_offset=$lo_offset#slurp
+#end if
+)</callback>
        <callback>set_gain($gain)</callback>
        <param>
                <name>Input Type</name>
index 1a777bd6302c7cf017703ce06556150a4e19e461..7fcc7a22cf37eeff7d924a95694c109718ba971b 100644 (file)
 self.$(id).set_format(width=$format.width, shift=$format.shift)
 #end if
 self.$(id).set_decim_rate($decimation)
-self.$(id).set_frequency($frequency, verbose=True)
-self.$(id).set_gain($gain)
+self.$(id).set_frequency($frequency, verbose=True#slurp
 #if $lo_offset() != float('inf')
-self.$(id).set_lo_offset($lo_offset)
-#end if</make>
-       <callback>set_lo_offset($lo_offset)</callback>
+, lo_offset=$lo_offset#slurp
+#end if
+)
+self.$(id).set_gain($gain)</make>
        <callback>set_decim_rate($decimation)</callback>
-       <callback>set_frequency($frequency)</callback>
+       <callback>set_frequency($frequency#slurp
+#if $lo_offset() != float('inf')
+, lo_offset=$lo_offset#slurp
+#end if
+)</callback>
        <callback>set_gain($gain)</callback>
        <param>
                <name>Output Type</name>
index 1ecf7c47fe4e980d2eba74d25f0ca5538236fc21..3692e17602148c9d674e648eb7a1a157f86e93a2 100644 (file)
@@ -53,22 +53,22 @@ class _dual_source(gr.hier_block2):
                for i in range(2): self.connect((deinter, i), (self, i))
 
        def set_decim_rate(self, decim): self._get_u().set_decim_rate(int(decim))
-       def set_frequency_a(self, frequency, verbose=False):
+       def set_frequency_a(self, frequency, verbose=False, lo_offset=None):
+               if lo_offset is not None: self._subdev_a.set_lo_offset(lo_offset)
                self._set_frequency(
                        chan=0, #ddc0
                        subdev=self._subdev_a,
                        frequency=frequency,
                        verbose=verbose,
                )
-       def set_frequency_b(self, frequency, verbose=False):
+       def set_frequency_b(self, frequency, verbose=False, lo_offset=None):
+               if lo_offset is not None: self._subdev_b.set_lo_offset(lo_offset)
                self._set_frequency(
                        chan=1, #ddc1
                        subdev=self._subdev_b,
                        frequency=frequency,
                        verbose=verbose,
                )
-       def set_lo_offset_a(self, lo_offset): self._subdev_a.set_lo_offset(lo_offset)
-       def set_lo_offset_b(self, lo_offset): self._subdev_b.set_lo_offset(lo_offset)
        def set_gain_a(self, gain): self._subdev_a.set_gain(gain)
        def set_gain_b(self, gain): self._subdev_b.set_gain(gain)
 
@@ -105,22 +105,22 @@ class _dual_sink(gr.hier_block2):
                for i in range(2): self.connect((self, i), (inter, i))
 
        def set_interp_rate(self, interp): self._get_u().set_interp_rate(int(interp))
-       def set_frequency_a(self, frequency, verbose=False):
+       def set_frequency_a(self, frequency, verbose=False, lo_offset=None):
+               if lo_offset is not None: self._subdev_a.set_lo_offset(lo_offset)
                self._set_frequency(
                        chan=self._subdev_a.which(),
                        subdev=self._subdev_a,
                        frequency=frequency,
                        verbose=verbose,
                )
-       def set_frequency_b(self, frequency, verbose=False):
+       def set_frequency_b(self, frequency, verbose=False, lo_offset=None):
+               if lo_offset is not None: self._subdev_b.set_lo_offset(lo_offset)
                self._set_frequency(
                        chan=self._subdev_b.which(),
                        subdev=self._subdev_b,
                        frequency=frequency,
                        verbose=verbose,
                )
-       def set_lo_offset_a(self, lo_offset): self._subdev_a.set_lo_offset(lo_offset)
-       def set_lo_offset_b(self, lo_offset): self._subdev_b.set_lo_offset(lo_offset)
        def set_gain_a(self, gain): self._subdev_a.set_gain(gain)
        def set_gain_b(self, gain): self._subdev_b.set_gain(gain)
        def set_enable_a(self, enable): self._subdev_a.set_enable(enable)
index 9065c7fe93ed2decbba24ee49484807b52b8acd1..fc4c75bf0618598dab80b60fc0df990a7e623c92 100644 (file)
@@ -56,8 +56,8 @@ class _simple_source(gr.hier_block2):
                self._get_u().set_decim_rate(int(decim))
                if self._no_hb: #set the BW to half the sample rate
                        self._subdev.set_bw(self._get_u().converter_rate()/decim/2)
-       def set_lo_offset(self, lo_offset): self._subdev.set_lo_offset(lo_offset)
-       def set_frequency(self, frequency, verbose=False):
+       def set_frequency(self, frequency, verbose=False, lo_offset=None):
+               if lo_offset is not None: self._subdev.set_lo_offset(lo_offset)
                self._set_frequency(
                        chan=0, #ddc0
                        subdev=self._subdev,
@@ -96,14 +96,14 @@ class _simple_sink(gr.hier_block2):
                self.connect(self, self._get_u())
 
        def set_interp_rate(self, interp): self._get_u().set_interp_rate(int(interp))
-       def set_frequency(self, frequency, verbose=False):
+       def set_frequency(self, frequency, verbose=False, lo_offset=None):
+               if lo_offset is not None: self._subdev.set_lo_offset(lo_offset)
                self._set_frequency(
                        chan=self._subdev.which(),
                        subdev=self._subdev,
                        frequency=frequency,
                        verbose=verbose,
                )
-       def set_lo_offset(self, lo_offset): self._subdev.set_lo_offset(lo_offset)
        def set_gain(self, gain): self._subdev.set_gain(gain)
        def set_enable(self, enable): self._subdev.set_enable(enable)
        def set_auto_tr(self, auto_tr): self._subdev.set_auto_tr(auto_tr)
index 9f50cb619f3e391cfa406d8a1611c4a2ae3d5790..67dd129955c5f7695d438fedfa6a30fb25c9a778 100644 (file)
@@ -31,11 +31,12 @@ gruelinclude_HEADERS = \
        msg_accepter.h \
        msg_accepter_msgq.h \
        msg_queue.h \
+       msg_passing.h \
        pmt.h \
        pmt_pool.h \
        pmt_serial_tags.h \
+       pmt_sugar.h \
        realtime.h \
-       send.h \
        sys_pri.h \
        thread_body_wrapper.h \
        thread_group.h \
index 3afd6dde08fb4616354c6af017fc8968e8246277..70ac846f53d643496319d7d8989d4c5c4870735d 100644 (file)
@@ -22,6 +22,7 @@
 #define INCLUDED_GRUEL_MSG_ACCEPTER_H
 
 #include <gruel/pmt.h>
+#include <boost/shared_ptr.hpp>
 
 namespace gruel {
 
@@ -44,6 +45,8 @@ namespace gruel {
     virtual void post(pmt::pmt_t msg) = 0;
   };
 
+  typedef boost::shared_ptr<msg_accepter> msg_accepter_sptr;
+
 } /* namespace gruel */
 
 #endif /* INCLUDED_GRUEL_MSG_ACCEPTER_H */
diff --git a/gruel/src/include/gruel/msg_passing.h b/gruel/src/include/gruel/msg_passing.h
new file mode 100644 (file)
index 0000000..ebbeca8
--- /dev/null
@@ -0,0 +1,111 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2009 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.
+ */
+#ifndef INCLUDED_GRUEL_MSG_PASSING_H
+#define INCLUDED_GRUEL_MSG_PASSING_H
+
+/*!
+ * \brief Include this header to use the message passing features
+ */
+
+#include <gruel/pmt.h>
+#include <gruel/msg_accepter.h>
+
+
+namespace gruel {
+
+  /*!
+   * \brief send message to msg_accepter
+   *
+   * \param accepter is the target of the send.
+   * \param msg is the message to send.  It's usually a pmt tuple.
+   *
+   * Sending a message is an asynchronous operation.  The \p send
+   * call will not wait for the message either to arrive at the
+   * destination or to be received.
+   *
+   * \returns msg
+   */
+  static inline pmt::pmt_t
+  send(msg_accepter_sptr accepter, const pmt::pmt_t &msg)
+  {
+    accepter->post(msg);
+    return msg;
+  }
+
+  /*!
+   * \brief send message to msg_accepter
+   *
+   * \param accepter is the target of the send.
+   * \param msg is the message to send.  It's usually a pmt tuple.
+   *
+   * Sending a message is an asynchronous operation.  The \p send
+   * call will not wait for the message either to arrive at the
+   * destination or to be received.
+   *
+   * \returns msg
+   */
+  static inline pmt::pmt_t
+  send(msg_accepter *accepter, const pmt::pmt_t &msg)
+  {
+    accepter->post(msg);
+    return msg;
+  }
+
+  /*!
+   * \brief send message to msg_accepter
+   *
+   * \param accepter is the target of the send.
+   * \param msg is the message to send.  It's usually a pmt tuple.
+   *
+   * Sending a message is an asynchronous operation.  The \p send
+   * call will not wait for the message either to arrive at the
+   * destination or to be received.
+   *
+   * \returns msg
+   */
+  static inline pmt::pmt_t
+  send(msg_accepter &accepter, const pmt::pmt_t &msg)
+  {
+    accepter.post(msg);
+    return msg;
+  }
+
+  /*!
+   * \brief send message to msg_accepter
+   *
+   * \param accepter is the target of the send.  precond: pmt_is_msg_accepter(accepter)
+   * \param msg is the message to send.  It's usually a pmt tuple.
+   *
+   * Sending a message is an asynchronous operation.  The \p send
+   * call will not wait for the message either to arrive at the
+   * destination or to be received.
+   *
+   * \returns msg
+   */
+  static inline pmt::pmt_t
+  send(pmt::pmt_t accepter, const pmt::pmt_t &msg)
+  {
+    return send(pmt_msg_accepter_ref(accepter), msg);
+  }
+
+} /* namespace gruel */
+
+#endif /* INCLUDED_GRUEL_MSG_PASSING_H */
index 2403593017f52ea79265e6a632f935d932465a28..3188aad1d5db76176e453c2ccda0674ea19e8b28 100644 (file)
@@ -24,6 +24,7 @@
 #define INCLUDED_PMT_H
 
 #include <boost/intrusive_ptr.hpp>
+#include <boost/shared_ptr.hpp>
 #include <boost/any.hpp>
 #include <complex>
 #include <string>
 #include <iosfwd>
 #include <stdexcept>
 
+namespace gruel {
+  class msg_accepter;
+};
+
 /*!
  * This file defines a polymorphic type and the operations on it.
  *
@@ -299,6 +304,33 @@ void pmt_vector_set(pmt_t vector, size_t k, pmt_t obj);
 //! Store \p fill in every position of \p vector
 void pmt_vector_fill(pmt_t vector, pmt_t fill);
 
+/*
+ * ------------------------------------------------------------------------
+ *                   Binary Large Objects (BLOBs)
+ *
+ * Handy for passing around uninterpreted chunks of memory.
+ * ------------------------------------------------------------------------
+ */
+
+//! Return true if \p x is a blob, othewise false.
+bool pmt_is_blob(pmt_t x);
+
+/*!
+ * \brief Make a blob given a pointer and length in bytes
+ *
+ * \param buf is the pointer to data to use to create blob
+ * \param len is the size of the data in bytes.
+ *
+ * The data is copied into the blob.
+ */
+pmt_t pmt_make_blob(const void *buf, size_t len);
+
+//! Return a pointer to the blob's data
+const void *pmt_blob_data(pmt_t blob);
+
+//! Return the blob's length in bytes
+size_t pmt_blob_length(pmt_t blob);
+
 /*!
  * <pre>
  * ------------------------------------------------------------------------
@@ -482,6 +514,20 @@ boost::any pmt_any_ref(pmt_t obj);
 void pmt_any_set(pmt_t obj, const boost::any &any);
 
 
+/*
+ * ------------------------------------------------------------------------
+ *    msg_accepter -- pmt representation of gruel::msg_accepter
+ * ------------------------------------------------------------------------
+ */
+//! Return true if \p obj is a msg_accepter
+bool pmt_is_msg_accepter(const pmt_t &obj);
+
+//! make a msg_accepter
+pmt_t pmt_make_msg_accepter(boost::shared_ptr<gruel::msg_accepter> ma);
+
+//! Return underlying msg_accepter
+boost::shared_ptr<gruel::msg_accepter> pmt_msg_accepter_ref(const pmt_t &obj);
+
 /*
  * ------------------------------------------------------------------------
  *                       General functions
@@ -717,4 +763,7 @@ void pmt_dump_sizeof();     // debugging
 
 } /* namespace pmt */
 
+
+#include <gruel/pmt_sugar.h>
+
 #endif /* INCLUDED_PMT_H */
diff --git a/gruel/src/include/gruel/pmt_sugar.h b/gruel/src/include/gruel/pmt_sugar.h
new file mode 100644 (file)
index 0000000..92bcb5f
--- /dev/null
@@ -0,0 +1,165 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2009 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.
+ */
+#ifndef INCLUDED_GRUEL_PMT_SUGAR_H
+#define INCLUDED_GRUEL_PMT_SUGAR_H
+
+/*!
+ * This file is included by pmt.h and contains pseudo-constructor
+ * shorthand for making pmt objects
+ */
+
+namespace pmt {
+
+  //! Make pmt symbol
+  static inline pmt_t
+  mp(const std::string &s)
+  {
+    return pmt_string_to_symbol(s);
+  }
+
+  //! Make pmt symbol
+  static inline pmt_t
+  mp(const char *s)
+  {
+    return pmt_string_to_symbol(s);
+  }
+
+  //! Make pmt long
+  static inline pmt_t
+  mp(long x){
+    return pmt_from_long(x);
+  }
+
+  //! Make pmt long
+  static inline pmt_t
+  mp(int x){
+    return pmt_from_long(x);
+  }
+
+  //! Make pmt double
+  static inline pmt_t
+  mp(double x){
+    return pmt_from_double(x);
+  }
+  
+  //! Make pmt complex
+  static inline pmt_t
+  mp(std::complex<double> z)
+  {
+    return pmt_make_rectangular(z.real(), z.imag());
+  }
+
+  //! Make pmt complex
+  static inline pmt_t
+  mp(std::complex<float> z)
+  {
+    return pmt_make_rectangular(z.real(), z.imag());
+  }
+
+  //! Make pmt msg_accepter
+  static inline pmt_t
+  mp(boost::shared_ptr<gruel::msg_accepter> ma)
+  {
+    return pmt_make_msg_accepter(ma);
+  }
+
+  //! Make pmt Binary Large Object (BLOB)
+  static inline pmt_t
+  mp(const void *data, size_t len_in_bytes)
+  {
+    return pmt_make_blob(data, len_in_bytes);
+  }
+
+  //! Make tuple
+  static inline pmt_t
+  mp(const pmt_t &e0)
+  {
+    return pmt_make_tuple(e0);
+  }
+
+  //! Make tuple
+  static inline pmt_t
+  mp(const pmt_t &e0, const pmt_t &e1)
+  {
+    return pmt_make_tuple(e0, e1);
+  }
+
+  //! Make tuple
+  static inline pmt_t
+  mp(const pmt_t &e0, const pmt_t &e1, const pmt_t &e2)
+  {
+    return pmt_make_tuple(e0, e1, e2);
+  }
+
+  //! Make tuple
+  static inline pmt_t
+  mp(const pmt_t &e0, const pmt_t &e1, const pmt_t &e2, const pmt_t &e3)
+  {
+    return pmt_make_tuple(e0, e1, e2, e3);
+  }
+
+  //! Make tuple
+  static inline pmt_t
+  mp(const pmt_t &e0, const pmt_t &e1, const pmt_t &e2, const pmt_t &e3, const pmt_t &e4)
+  {
+    return pmt_make_tuple(e0, e1, e2, e3, e4);
+  }
+
+  //! Make tuple
+  static inline pmt_t
+  mp(const pmt_t &e0, const pmt_t &e1, const pmt_t &e2, const pmt_t &e3, const pmt_t &e4, const pmt_t &e5)
+  {
+    return pmt_make_tuple(e0, e1, e2, e3, e4, e5);
+  }
+
+  //! Make tuple
+  static inline pmt_t
+  mp(const pmt_t &e0, const pmt_t &e1, const pmt_t &e2, const pmt_t &e3, const pmt_t &e4, const pmt_t &e5, const pmt_t &e6)
+  {
+    return pmt_make_tuple(e0, e1, e2, e3, e4, e5, e6);
+  }
+
+  //! Make tuple
+  static inline pmt_t
+  mp(const pmt_t &e0, const pmt_t &e1, const pmt_t &e2, const pmt_t &e3, const pmt_t &e4, const pmt_t &e5, const pmt_t &e6, const pmt_t &e7)
+  {
+    return pmt_make_tuple(e0, e1, e2, e3, e4, e5, e6, e7);
+  }
+
+  //! Make tuple
+  static inline pmt_t
+  mp(const pmt_t &e0, const pmt_t &e1, const pmt_t &e2, const pmt_t &e3, const pmt_t &e4, const pmt_t &e5, const pmt_t &e6, const pmt_t &e7, const pmt_t &e8)
+  {
+    return pmt_make_tuple(e0, e1, e2, e3, e4, e5, e6, e7, e8);
+  }
+
+  //! Make tuple
+  static inline pmt_t
+  mp(const pmt_t &e0, const pmt_t &e1, const pmt_t &e2, const pmt_t &e3, const pmt_t &e4, const pmt_t &e5, const pmt_t &e6, const pmt_t &e7, const pmt_t &e8, const pmt_t &e9)
+  {
+    return pmt_make_tuple(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9);
+  }
+
+
+} /* namespace pmt */
+
+
+#endif /* INCLUDED_GRUEL_PMT_SUGAR_H */
diff --git a/gruel/src/include/gruel/send.h b/gruel/src/include/gruel/send.h
deleted file mode 100644 (file)
index 292017d..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2009 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.
- */
-#ifndef INCLUDED_GRUEL_SEND_H
-#define INCLUDED_GRUEL_SEND_H
-
-#include <gruel/msg_accepter.h>
-
-namespace gruel {
-
-
-  /*!
-   * \brief send \p msg to \p msg_accepter
-   *
-   * Sending a message is an asynchronous operation.  The \p send
-   * call will not wait for the message either to arrive at the
-   * destination or to be received.
-   *
-   * \returns msg
-   */
-  static inline pmt::pmt_t
-  send(msg_accepter &acc, pmt::pmt_t msg)
-  {
-    return acc.post(msg);
-  }
-
-
-
-} /* namespace gruel */
-
-
-#endif /* INCLUDED_SEND_H */
index 6dfb6787c804ad2f89aafff23c86d51a7488a1fc..9afa0d292f2df871f46af49174f53314d9efe50b 100644 (file)
@@ -25,6 +25,12 @@ SUBDIRS = pmt msg
 
 AM_CPPFLAGS = $(DEFINES) $(BOOST_CPPFLAGS) $(CPPUNIT_INCLUDES) $(GRUEL_INCLUDES) $(WITH_INCLUDES)
 
+
+TESTS = test_gruel
+
+noinst_PROGRAMS = test_gruel
+
+
 lib_LTLIBRARIES = libgruel.la
 
 # magic flags
@@ -47,3 +53,10 @@ libgruel_la_LIBADD =                         \
        $(PMT_LIB)                      \
        $(MSG_LIB)                      \
        -lstdc++
+
+
+# ----------------------------------------------------------------
+
+test_gruel_SOURCES = test_gruel.cc
+test_gruel_LDADD   = libgruel.la pmt/libpmt-qa.la
+
index 2b710a598f1550b15ad835afc5a51111c85f9fdd..8750cbdf8370788fdafbebbc6e9ef5d6efddd58e 100644 (file)
@@ -23,7 +23,6 @@ include $(top_srcdir)/Makefile.common
 
 AM_CPPFLAGS = $(DEFINES) $(BOOST_CPPFLAGS) $(CPPUNIT_INCLUDES) $(GRUEL_INCLUDES) $(WITH_INCLUDES)
 
-TESTS = test_pmt
 
 noinst_LTLIBRARIES = libpmt.la
 
@@ -90,14 +89,6 @@ libpmt_qa_la_LIBADD =                        \
        $(CPPUNIT_LIBS)                 \
        -lstdc++                        
 
-noinst_PROGRAMS        =                       \
-       test_pmt
-
-
-LIBPMTQA = libpmt-qa.la
-
-test_pmt_SOURCES = test_pmt.cc
-test_pmt_LDADD   = $(LIBPMTQA)
 
 # Do creation and inclusion of other Makefiles last
 
index f0e3c30a266f630a78252e0c4a2a35f2cfb7a918..e50e218380311560a0e91249ac9a9e5c017a2cb0 100644 (file)
@@ -26,8 +26,9 @@
 #include <vector>
 #include <gruel/pmt.h>
 #include "pmt_int.h"
-#include <stdio.h>
+#include <gruel/msg_accepter.h>
 #include <gruel/pmt_pool.h>
+#include <stdio.h>
 #include <string.h>
 
 namespace pmt {
@@ -881,6 +882,73 @@ pmt_any_set(pmt_t obj, const boost::any &any)
   _any(obj)->set(any);
 }
 
+////////////////////////////////////////////////////////////////////////////
+//               msg_accepter -- built from "any"
+////////////////////////////////////////////////////////////////////////////
+
+bool 
+pmt_is_msg_accepter(const pmt_t &obj)
+{
+  if (!pmt_is_any(obj))
+    return false;
+
+  boost::any r = pmt_any_ref(obj);
+  return boost::any_cast<gruel::msg_accepter_sptr>(&r) != 0;
+}
+
+//! make a msg_accepter
+pmt_t
+pmt_make_msg_accepter(gruel::msg_accepter_sptr ma)
+{
+  return pmt_make_any(ma);
+}
+
+//! Return underlying msg_accepter
+gruel::msg_accepter_sptr
+pmt_msg_accepter_ref(const pmt_t &obj)
+{
+  try {
+    return boost::any_cast<gruel::msg_accepter_sptr>(pmt_any_ref(obj));
+  }
+  catch (boost::bad_any_cast &e){
+    throw pmt_wrong_type("pmt_msg_accepter_ref", obj);
+  }
+}
+
+
+////////////////////////////////////////////////////////////////////////////
+//             Binary Large Object -- currently a u8vector
+////////////////////////////////////////////////////////////////////////////
+
+bool
+pmt_is_blob(pmt_t x)
+{
+  // return pmt_is_u8vector(x);
+  return pmt_is_uniform_vector(x);
+}
+
+pmt_t
+pmt_make_blob(const void *buf, size_t len_in_bytes)
+{
+  return pmt_init_u8vector(len_in_bytes, (const uint8_t *) buf);
+}
+
+const void *
+pmt_blob_data(pmt_t blob)
+{
+  size_t len;
+  return pmt_uniform_vector_elements(blob, len);
+}
+
+size_t
+pmt_blob_length(pmt_t blob)
+{
+  size_t len;
+  pmt_uniform_vector_elements(blob, len);
+  return len;
+}
+
+
 ////////////////////////////////////////////////////////////////////////////
 //                          General Functions
 ////////////////////////////////////////////////////////////////////////////
index 899674bbb18b4d2deaaff8cb60902c927b7a2f33..59d9e14d30a7e257b07e6975a08c490e7cf41c34 100644 (file)
@@ -22,8 +22,9 @@
 
 #include <qa_pmt_prims.h>
 #include <cppunit/TestAssert.h>
-#include <gruel/pmt.h>
-#include <stdio.h>
+#include <gruel/msg_passing.h>
+#include <cstdio>
+#include <cstring>
 #include <sstream>
 
 using namespace pmt;
@@ -453,6 +454,41 @@ qa_pmt_prims::test_any()
 
 // ------------------------------------------------------------------------
 
+class qa_pmt_msg_accepter_nop : public gruel::msg_accepter {
+public:
+  qa_pmt_msg_accepter_nop(){};
+  ~qa_pmt_msg_accepter_nop();
+  void post(pmt_t){};
+};
+
+qa_pmt_msg_accepter_nop::~qa_pmt_msg_accepter_nop(){}
+
+void
+qa_pmt_prims::test_msg_accepter()
+{
+  pmt_t sym = pmt_intern("my-symbol");
+
+  boost::any a0;
+  a0 = std::string("Hello!");
+  pmt_t p0 = pmt_make_any(a0);
+
+  gruel::msg_accepter_sptr ma0 = gruel::msg_accepter_sptr(new qa_pmt_msg_accepter_nop());
+  pmt_t p1 = pmt_make_msg_accepter(ma0);
+
+  CPPUNIT_ASSERT_EQUAL(ma0.get(), pmt_msg_accepter_ref(p1).get());
+
+  CPPUNIT_ASSERT_THROW(pmt_msg_accepter_ref(sym), pmt_wrong_type);
+  CPPUNIT_ASSERT_THROW(pmt_msg_accepter_ref(p0),  pmt_wrong_type);
+
+  // just confirm interfaces on send are OK
+  gruel::send(ma0.get(), sym);
+  gruel::send(ma0, sym);
+  gruel::send(p1, sym);
+
+}
+
+// ------------------------------------------------------------------------
+
 void
 qa_pmt_prims::test_serialize()
 {
@@ -522,3 +558,19 @@ qa_pmt_prims::test_sets()
   CPPUNIT_ASSERT(!pmt_subsetp(l3,l2));
 }
 
+void
+qa_pmt_prims::test_sugar()
+{
+  CPPUNIT_ASSERT(pmt_is_symbol(mp("my-symbol")));
+  CPPUNIT_ASSERT_EQUAL((long) 10, pmt_to_long(mp(10)));
+  CPPUNIT_ASSERT_EQUAL((double) 1e6, pmt_to_double(mp(1e6)));
+  CPPUNIT_ASSERT_EQUAL(std::complex<double>(2, 3),
+                      pmt_to_complex(mp(std::complex<double>(2, 3))));
+
+  int buf[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+  pmt_t blob = mp(buf, sizeof(buf));
+  const void *data = pmt_blob_data(blob);
+  size_t nbytes = pmt_blob_length(blob);
+  CPPUNIT_ASSERT_EQUAL(sizeof(buf), nbytes);
+  CPPUNIT_ASSERT(memcmp(buf, data, nbytes) == 0);
+}
index 2fe473c43b5c81888f7124916c7ad6adc3401c7d..29ba02f11cb28bcf50d0e547a4d46c593be9047d 100644 (file)
@@ -40,10 +40,12 @@ class qa_pmt_prims : public CppUnit::TestCase {
   CPPUNIT_TEST(test_misc);
   CPPUNIT_TEST(test_dict);
   CPPUNIT_TEST(test_any);
+  CPPUNIT_TEST(test_msg_accepter);
   CPPUNIT_TEST(test_io);
   CPPUNIT_TEST(test_lists);
   CPPUNIT_TEST(test_serialize);
   CPPUNIT_TEST(test_sets);
+  CPPUNIT_TEST(test_sugar);
   CPPUNIT_TEST_SUITE_END();
 
  private:
@@ -59,10 +61,12 @@ class qa_pmt_prims : public CppUnit::TestCase {
   void test_misc();
   void test_dict();
   void test_any();
+  void test_msg_accepter();
   void test_io();
   void test_lists();
   void test_serialize();
   void test_sets();
+  void test_sugar();
 };
 
 #endif /* INCLUDED_QA_PMT_PRIMS_H */
diff --git a/gruel/src/lib/pmt/test_pmt.cc b/gruel/src/lib/pmt/test_pmt.cc
deleted file mode 100644 (file)
index 034785f..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2006 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.
- */
-
-#include <cppunit/TextTestRunner.h>
-#include <qa_pmt.h>
-
-int 
-main(int argc, char **argv)
-{
-  
-  CppUnit::TextTestRunner      runner;
-
-  runner.addTest(qa_pmt::suite ());
-  
-  bool was_successful = runner.run("", false);
-
-  return was_successful ? 0 : 1;
-}
diff --git a/gruel/src/lib/test_gruel.cc b/gruel/src/lib/test_gruel.cc
new file mode 100644 (file)
index 0000000..6693034
--- /dev/null
@@ -0,0 +1,37 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006,2009 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.
+ */
+
+#include <cppunit/TextTestRunner.h>
+#include "pmt/qa_pmt.h"
+
+int 
+main(int argc, char **argv)
+{
+  
+  CppUnit::TextTestRunner      runner;
+
+  runner.addTest(qa_pmt::suite ());
+  
+  bool was_successful = runner.run("", false);
+
+  return was_successful ? 0 : 1;
+}
index a8f4684b57244cf0d0ba9cd6cb4e7cba79fb20b2..2d2bfabbb262cb21b16cfd4b5dde51aa0db46e5d 100644 (file)
@@ -668,7 +668,7 @@ _2400_common::freq_min()
 double
 _2400_common::freq_max()
 {
-  return 2700e6;
+  return 2900e6;
 }
 
 //----------------------------------------------------------------------
@@ -700,7 +700,7 @@ _1200_common::freq_min()
 double 
 _1200_common::freq_max()
 {
-  return 1350e6;
+  return 1450e6;
 }
 
 //-------------------------------------------------------------------------
@@ -726,13 +726,13 @@ _1800_common::_1800_common()
 double 
 _1800_common::freq_min()
 {
-  return 1600e6;
+  return 1500e6;
 }
 
 double 
 _1800_common::freq_max()
 {
-  return 2000e6;
+  return 2100e6;
 }
 
 //-------------------------------------------------------------------------
@@ -758,13 +758,13 @@ _900_common::_900_common()
 double
 _900_common::freq_min()
 {
-  return 800e6;
+  return 750e6;
 }
 
 double
 _900_common::freq_max()
 {
-  return 1000e6;
+  return 1050e6;
 }
 
 //-------------------------------------------------------------------------
index 2f950016fb2304e3bef4ef5d779965cf38b2a497..ff12f9e32b1d02eb71612934cb71d96a58c2fff7 100644 (file)
@@ -200,8 +200,8 @@ struct db_rfx_900_rx db_rfx_900_rx = {
   .base.is_tx = false,
   .base.output_enables = 0x00E0,
   .base.used_pins = 0x00FF,
-  .base.freq_min = U2_DOUBLE_TO_FXPT_FREQ(800e6),
-  .base.freq_max = U2_DOUBLE_TO_FXPT_FREQ(1000e6),
+  .base.freq_min = U2_DOUBLE_TO_FXPT_FREQ(750e6),
+  .base.freq_max = U2_DOUBLE_TO_FXPT_FREQ(1050e6),
   .base.gain_min = U2_DOUBLE_TO_FXPT_GAIN(0),
   .base.gain_max = U2_DOUBLE_TO_FXPT_GAIN(70),
   .base.gain_step_size = U2_DOUBLE_TO_FXPT_GAIN(0.034),
@@ -231,8 +231,8 @@ struct db_rfx_900_tx db_rfx_900_tx = {
   .base.is_tx = true,
   .base.output_enables = 0x00E0,
   .base.used_pins = 0x00FF,
-  .base.freq_min = U2_DOUBLE_TO_FXPT_FREQ(800e6),
-  .base.freq_max = U2_DOUBLE_TO_FXPT_FREQ(1000e6),
+  .base.freq_min = U2_DOUBLE_TO_FXPT_FREQ(750e6),
+  .base.freq_max = U2_DOUBLE_TO_FXPT_FREQ(1050e6),
   //.base.gain_min = U2_DOUBLE_TO_FXPT_GAIN(xxx),
   //.base.gain_max = U2_DOUBLE_TO_FXPT_GAIN(xxx),
   //.base.gain_step_size = U2_DOUBLE_TO_FXPT_GAIN(xxx),
@@ -262,7 +262,7 @@ struct db_rfx_1200_rx db_rfx_1200_rx = {
   .base.output_enables = 0x00E0,
   .base.used_pins = 0x00FF,
   .base.freq_min = U2_DOUBLE_TO_FXPT_FREQ(1150e6),
-  .base.freq_max = U2_DOUBLE_TO_FXPT_FREQ(1350e6),
+  .base.freq_max = U2_DOUBLE_TO_FXPT_FREQ(1450e6),
   .base.gain_min = U2_DOUBLE_TO_FXPT_GAIN(0),
   .base.gain_max = U2_DOUBLE_TO_FXPT_GAIN(70),
   .base.gain_step_size = U2_DOUBLE_TO_FXPT_GAIN(0.034),
@@ -293,7 +293,7 @@ struct db_rfx_1200_tx db_rfx_1200_tx = {
   .base.output_enables = 0x00E0,
   .base.used_pins = 0x00FF,
   .base.freq_min = U2_DOUBLE_TO_FXPT_FREQ(1150e6),
-  .base.freq_max = U2_DOUBLE_TO_FXPT_FREQ(1350e6),
+  .base.freq_max = U2_DOUBLE_TO_FXPT_FREQ(1450e6),
   //.base.gain_min = U2_DOUBLE_TO_FXPT_GAIN(xxx),
   //.base.gain_max = U2_DOUBLE_TO_FXPT_GAIN(xxx),
   //.base.gain_step_size = U2_DOUBLE_TO_FXPT_GAIN(xxx),
@@ -322,8 +322,8 @@ struct db_rfx_1800_rx db_rfx_1800_rx = {
   .base.is_tx = false,
   .base.output_enables = 0x00E0,
   .base.used_pins = 0x00FF,
-  .base.freq_min = U2_DOUBLE_TO_FXPT_FREQ(1600e6),
-  .base.freq_max = U2_DOUBLE_TO_FXPT_FREQ(2000e6),
+  .base.freq_min = U2_DOUBLE_TO_FXPT_FREQ(1500e6),
+  .base.freq_max = U2_DOUBLE_TO_FXPT_FREQ(2100e6),
   .base.gain_min = U2_DOUBLE_TO_FXPT_GAIN(0),
   .base.gain_max = U2_DOUBLE_TO_FXPT_GAIN(70),
   .base.gain_step_size = U2_DOUBLE_TO_FXPT_GAIN(0.034),
@@ -353,8 +353,8 @@ struct db_rfx_1800_tx db_rfx_1800_tx = {
   .base.is_tx = true,
   .base.output_enables = 0x00E0,
   .base.used_pins = 0x00FF,
-  .base.freq_min = U2_DOUBLE_TO_FXPT_FREQ(1600e6),
-  .base.freq_max = U2_DOUBLE_TO_FXPT_FREQ(2000e6),
+  .base.freq_min = U2_DOUBLE_TO_FXPT_FREQ(1500e6),
+  .base.freq_max = U2_DOUBLE_TO_FXPT_FREQ(2100e6),
   //.base.gain_min = U2_DOUBLE_TO_FXPT_GAIN(xxx),
   //.base.gain_max = U2_DOUBLE_TO_FXPT_GAIN(xxx),
   //.base.gain_step_size = U2_DOUBLE_TO_FXPT_GAIN(xxx),
@@ -385,7 +385,7 @@ struct db_rfx_2400_rx db_rfx_2400_rx = {
   .base.output_enables = 0x00E0,
   .base.used_pins = 0x00FF,
   .base.freq_min = U2_DOUBLE_TO_FXPT_FREQ(2300e6),
-  .base.freq_max = U2_DOUBLE_TO_FXPT_FREQ(2700e6),
+  .base.freq_max = U2_DOUBLE_TO_FXPT_FREQ(2900e6),
   .base.gain_min = U2_DOUBLE_TO_FXPT_GAIN(0),
   .base.gain_max = U2_DOUBLE_TO_FXPT_GAIN(70),
   .base.gain_step_size = U2_DOUBLE_TO_FXPT_GAIN(0.034),
@@ -416,7 +416,7 @@ struct db_rfx_2400_tx db_rfx_2400_tx = {
   .base.output_enables = 0x00E0,
   .base.used_pins = 0x00FF,
   .base.freq_min = U2_DOUBLE_TO_FXPT_FREQ(2300e6),
-  .base.freq_max = U2_DOUBLE_TO_FXPT_FREQ(2700e6),
+  .base.freq_max = U2_DOUBLE_TO_FXPT_FREQ(2900e6),
   //.base.gain_min = U2_DOUBLE_TO_FXPT_GAIN(xxx),
   //.base.gain_max = U2_DOUBLE_TO_FXPT_GAIN(xxx),
   //.base.gain_step_size = U2_DOUBLE_TO_FXPT_GAIN(xxx),
index 4b8597c6003a15983d0c12fe3e28e18e68978ca5..bb71f79c27002bfadbecb305c0eae28a54495497 100644 (file)
 namespace usrp2 {
 
   pending_reply::pending_reply(unsigned int rid, void *buffer, size_t len)
-    : d_rid(rid), d_mutex(), d_cond(&d_mutex), d_buffer(buffer), d_len(len)
+    : d_rid(rid), d_buffer(buffer), d_len(len), d_mutex(), d_cond(&d_mutex),
+      d_complete(false)
   {
   }
 
   pending_reply::~pending_reply()
   {
-    signal(); // Needed?
+    notify_completion(); // Needed?
   }
 
   int
-  pending_reply::wait(double secs)
+  pending_reply::wait_for_completion(double secs)
   {
-    omni_mutex_lock l(d_mutex);
     omni_time abs_timeout = omni_time::time(omni_time(secs));
-    return d_cond.timedwait(abs_timeout.d_secs, abs_timeout.d_nsecs);
+    omni_mutex_lock l(d_mutex);
+    while (!d_complete){
+      int r = d_cond.timedwait(abs_timeout.d_secs, abs_timeout.d_nsecs);
+      if (r == 0)              // timed out
+       return 0;
+    }
+    return 1;
   }
 
   void
-  pending_reply::signal()
+  pending_reply::notify_completion()
   {
+    omni_mutex_lock l(d_mutex);
+    d_complete = true;
     d_cond.signal();
   }
   
index 9adc1618f8ce251b270374c4cde9ec5a5cf3cd1c..8769e4522f2e7dcfe38cba6170eef5065c0b1c36 100644 (file)
@@ -118,10 +118,13 @@ namespace usrp2 {
   {
   private:
     unsigned int    d_rid;
-    omni_mutex      d_mutex;
-    omni_condition  d_cond;
     void           *d_buffer;
     size_t         d_len;
+    
+    // d_mutex is used with d_cond and also protects d_complete
+    omni_mutex      d_mutex;
+    omni_condition  d_cond;
+    bool           d_complete;
 
   public:  
     /*!
@@ -140,12 +143,12 @@ namespace usrp2 {
      * Returns: 1 = ok, reply packet in buffer
      *          0 = timeout
      */
-    int wait(double secs);
+    int wait_for_completion(double secs);
 
     /*!
      * Allows creating thread to resume after copying reply into buffer
      */
-    void signal();
+    void notify_completion();
 
     /*!
      * Retrieve pending reply ID
index 1ecfd7348e65a5bf79b521591b69f49ff8e725fc..3d030432429c42d270743697840161552f4db43f 100644 (file)
@@ -133,7 +133,7 @@ namespace usrp2 {
       d_bg_running(false), d_rx_seqno(-1), d_tx_seqno(0), d_next_rid(0),
       d_num_rx_frames(0), d_num_rx_missing(0), d_num_rx_overruns(0), d_num_rx_bytes(0), 
       d_num_enqueued(0), d_enqueued_mutex(), d_bg_pending_cond(&d_enqueued_mutex),
-      d_channel_rings(NCHANS), d_tx_interp(0), d_rx_decim(0)
+      d_channel_rings(NCHANS), d_tx_interp(0), d_rx_decim(0), d_dont_enqueue(true)
   {
     if (!d_eth_buf->open(ifc, htons(U2_ETHERTYPE)))
       throw std::runtime_error("Unable to register USRP2 protocol");
@@ -298,22 +298,35 @@ namespace usrp2 {
     cmd->eop.len = sizeof(cmd->eop);
   }
 
+
+  bool
+  usrp2::impl::transmit_cmd(void *cmd_, size_t len_)
+  {
+    const void *cmd = cmd_;
+    int len = len_;
+    unsigned char tmp[64];
+
+    if (len_ < 64){            // pad to minimum ethernet frame size
+      memset(tmp, 0, sizeof(tmp));
+      memcpy(tmp, cmd_, len_);
+      cmd = tmp;
+      len = sizeof(tmp);
+    }
+
+    return d_eth_buf->tx_frame(cmd, len) == eth_buffer::EB_OK;
+  }
+
   bool
-  usrp2::impl::transmit_cmd(void *cmd, size_t len, pending_reply *p, double secs)
+  usrp2::impl::transmit_cmd_and_wait(void *cmd, size_t len, pending_reply *p, double secs)
   {
-    if (p)    
-      d_pending_replies[p->rid()] = p;
+    d_pending_replies[p->rid()] = p;
     
-    // Transmit command
-    if (d_eth_buf->tx_frame(cmd, len) != eth_buffer::EB_OK) {
+    if (!transmit_cmd(cmd, len)){
       d_pending_replies[p->rid()] = 0;
       return false;
     }
 
-    int res = 1;
-    if (p)
-      res = p->wait(secs);
-      
+    int res = p->wait_for_completion(secs);
     d_pending_replies[p->rid()] = 0;
     return res == 1;
   }
@@ -373,6 +386,10 @@ namespace usrp2 {
       return handle_control_packet(base, len);
     }
     else {                             // data packets
+
+      if (d_dont_enqueue)              // toss packet
+       return data_handler::RELEASE;
+
       return handle_data_packet(base, len);
     }
 
@@ -404,7 +421,7 @@ namespace usrp2 {
     
       // Copy reply into caller's buffer
       memcpy(rp->buffer(), p, std::min(oplen, buflen));
-      rp->signal();
+      rp->notify_completion();
       d_pending_replies[rid] = 0;
       return data_handler::RELEASE;
     }
@@ -485,7 +502,7 @@ namespace usrp2 {
     cmd.op.gain = htons(u2_double_to_fxpt_gain(gain));
     
     pending_reply p(cmd.op.rid, &reply, sizeof(reply));
-    if (!transmit_cmd(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
+    if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
       return false;
 
     bool success = (ntohx(reply.ok) == 1);
@@ -512,7 +529,7 @@ namespace usrp2 {
     cmd.eop.len = sizeof(cmd.eop);
     
     pending_reply p(cmd.op.rid, &reply, sizeof(reply));
-    if (!transmit_cmd(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
+    if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
       return false;
 
     bool success = (ntohx(reply.ok) == 1);
@@ -532,7 +549,7 @@ namespace usrp2 {
     cmd.op.freq_lo = htonl(u2_fxpt_freq_lo(fxpt));
     
     pending_reply p(cmd.op.rid, &reply, sizeof(reply));
-    if (!transmit_cmd(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
+    if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
       return false;
 
     bool success = (ntohx(reply.ok) == 1);
@@ -569,7 +586,7 @@ namespace usrp2 {
     cmd.op.decim = htonl(decimation_factor);
     
     pending_reply p(cmd.op.rid, &reply, sizeof(reply));
-    if (!transmit_cmd(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
+    if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
       return false;
 
     bool success = (ntohx(reply.ok) == 1);
@@ -589,7 +606,7 @@ namespace usrp2 {
     cmd.op.scale_iq = htonl(((scale_i & 0xffff) << 16) | (scale_q & 0xffff));
     
     pending_reply p(cmd.op.rid, &reply, sizeof(reply));
-    if (!transmit_cmd(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
+    if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
       return false;
 
     bool success = (ntohx(reply.ok) == 1);
@@ -634,14 +651,18 @@ namespace usrp2 {
       cmd.eop.opcode = OP_EOP;
       cmd.eop.len = sizeof(cmd.eop);
     
+      d_dont_enqueue = false;
       bool success = false;
       pending_reply p(cmd.op.rid, &reply, sizeof(reply));
-      success = transmit_cmd(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT);
+      success = transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT);
       success = success && (ntohx(reply.ok) == 1);
       
       if (success)
        d_channel_rings[channel] = ring_sptr(new ring(d_eth_buf->max_frames()));
+      else
+       d_dont_enqueue = true;
 
+      //fprintf(stderr, "usrp2::start_rx_streaming: success = %d\n", success);
       return success;
     }
   }
@@ -661,6 +682,9 @@ namespace usrp2 {
       return false;
     }
 
+    d_dont_enqueue = true;     // no new samples
+    flush_rx_samples(channel); // dump any we may already have
+
     op_stop_rx_cmd cmd;
     op_generic_t reply;
 
@@ -677,9 +701,10 @@ namespace usrp2 {
     
       bool success = false;
       pending_reply p(cmd.op.rid, &reply, sizeof(reply));
-      success = transmit_cmd(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT);
+      success = transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT);
       success = success && (ntohx(reply.ok) == 1);
       d_channel_rings[channel].reset();
+      //fprintf(stderr, "usrp2::stop_rx_streaming:  success = %d\n", success);
       return success;
     }
   }
@@ -732,6 +757,36 @@ namespace usrp2 {
     return true;
   }
 
+  bool
+  usrp2::impl::flush_rx_samples(unsigned int channel)
+  {
+    if (channel > MAX_CHAN) {
+      std::cerr << "usrp2: invalid channel (" << channel
+                << " )" << std::endl;
+      return false;
+    }
+
+    if (channel > 0) {
+      std::cerr << "usrp2: channel " << channel
+                << " not implemented" << std::endl;
+      return false;
+    }
+
+    ring_sptr rp = d_channel_rings[channel];
+    if (!rp){
+      return false;
+    }
+
+    // Iterate through frames and drop them
+    void *p;
+    size_t frame_len_in_bytes;
+    while (rp->dequeue(&p, &frame_len_in_bytes)) {
+      d_eth_buf->release_frame(p);
+      dec_enqueued();
+    }
+    return true;
+  }
+
   // ----------------------------------------------------------------
   //                           Transmit
   // ----------------------------------------------------------------
@@ -747,7 +802,7 @@ namespace usrp2 {
     cmd.op.gain = htons(u2_double_to_fxpt_gain(gain));
     
     pending_reply p(cmd.op.rid, &reply, sizeof(reply));
-    if (!transmit_cmd(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
+    if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
       return false;
 
     bool success = (ntohx(reply.ok) == 1);
@@ -774,7 +829,7 @@ namespace usrp2 {
     cmd.eop.len = sizeof(cmd.eop);
     
     pending_reply p(cmd.op.rid, &reply, sizeof(reply));
-    if (!transmit_cmd(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
+    if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
       return false;
 
     bool success = (ntohx(reply.ok) == 1);
@@ -794,7 +849,7 @@ namespace usrp2 {
     cmd.op.freq_lo = htonl(u2_fxpt_freq_lo(fxpt));
     
     pending_reply p(cmd.op.rid, &reply, sizeof(reply));
-    if (!transmit_cmd(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
+    if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
       return false;
 
     bool success = (ntohx(reply.ok) == 1);
@@ -831,7 +886,7 @@ namespace usrp2 {
     cmd.op.interp = htonl(interpolation_factor);
     
     pending_reply p(cmd.op.rid, &reply, sizeof(reply));
-    if (!transmit_cmd(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
+    if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
       return false;
 
     bool success = (ntohx(reply.ok) == 1);
@@ -882,7 +937,7 @@ namespace usrp2 {
     cmd.op.scale_iq = htonl(((scale_i & 0xffff) << 16) | (scale_q & 0xffff));
     
     pending_reply p(cmd.op.rid, &reply, sizeof(reply));
-    if (!transmit_cmd(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
+    if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
       return false;
 
     bool success = (ntohx(reply.ok) == 1);
@@ -1010,7 +1065,7 @@ namespace usrp2 {
     cmd.eop.len = sizeof(cmd.eop);
     
     pending_reply p(cmd.op.rid, &reply, sizeof(reply));
-    if (!transmit_cmd(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
+    if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
       return false;
 
     return ntohx(reply.ok) == 1;
@@ -1069,7 +1124,7 @@ namespace usrp2 {
       return false;
 
     pending_reply p(cmd.op.rid, &reply, sizeof(reply));
-    if (!transmit_cmd(&cmd, sizeof(cmd), &p, 4*DEF_CMD_TIMEOUT))
+    if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, 4*DEF_CMD_TIMEOUT))
       return false;
 
     bool success = (ntohx(reply.ok) == 1);
@@ -1108,7 +1163,7 @@ namespace usrp2 {
     cmd.eop.len = sizeof(cmd.eop);
     
     pending_reply p(cmd.op.rid, &reply, sizeof(reply));
-    if (!transmit_cmd(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
+    if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
       return false;
 
     bool success = (ntohx(reply.ok) == 1);
@@ -1135,7 +1190,7 @@ namespace usrp2 {
     cmd.eop.len = sizeof(cmd.eop);
     
     pending_reply p(cmd.op.rid, &reply, sizeof(reply));
-    if (!transmit_cmd(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
+    if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
       return false;
 
     return ntohx(reply.ok) == 1;
@@ -1157,7 +1212,7 @@ namespace usrp2 {
     cmd.eop.len = sizeof(cmd.eop);
     
     pending_reply p(cmd.op.rid, &reply, sizeof(reply));
-    if (!transmit_cmd(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
+    if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
       return false;
 
     return ntohx(reply.ok) == 1;
@@ -1197,7 +1252,7 @@ namespace usrp2 {
 
     reply = (op_generic_t *)malloc(rlen+bytes);
     pending_reply p(cmd.op.rid, reply, rlen+bytes);
-    if (transmit_cmd(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT)) {
+    if (transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT)) {
       uint32_t nwords = (reply->len-rlen)/sizeof(uint32_t);
       uint32_t *data = (uint32_t *)(reply+rlen/wlen);
       for (unsigned int i = 0; i < nwords; i++)
@@ -1264,7 +1319,7 @@ namespace usrp2 {
     bool ok = false;
     op_generic_t reply;
     pending_reply p(cmd->op.rid, &reply, sizeof(reply));
-    if (transmit_cmd(cmd, l, &p, DEF_CMD_TIMEOUT))
+    if (transmit_cmd_and_wait(cmd, l, &p, DEF_CMD_TIMEOUT))
       ok = (ntohx(reply.ok) == 1);
 
     free(cmd);
@@ -1286,7 +1341,7 @@ namespace usrp2 {
     cmd.eop.len = sizeof(cmd.eop);
     
     pending_reply p(cmd.op.rid, &reply, sizeof(reply));
-    if (!transmit_cmd(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
+    if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
       return false;
 
     bool success = (ntohx(reply.ok) == 1);
@@ -1315,7 +1370,7 @@ namespace usrp2 {
     cmd.eop.len = sizeof(cmd.eop);
     
     pending_reply p(cmd.op.rid, &reply, sizeof(reply));
-    if (!transmit_cmd(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
+    if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
       return false;
 
     bool success = (ntohx(reply.ok) == 1);
@@ -1348,7 +1403,7 @@ namespace usrp2 {
     cmd.eop.len = sizeof(cmd.eop);
     
     pending_reply p(cmd.op.rid, &reply, sizeof(reply));
-    if (!transmit_cmd(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
+    if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
       return false;
 
     bool success = (ntohx(reply.ok) == 1);
@@ -1377,7 +1432,7 @@ namespace usrp2 {
     cmd.eop.len = sizeof(cmd.eop);
     
     pending_reply p(cmd.op.rid, &reply, sizeof(reply));
-    if (!transmit_cmd(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
+    if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
       return false;
 
     bool success = (ntohx(reply.ok) == 1);
@@ -1406,7 +1461,7 @@ namespace usrp2 {
     cmd.eop.len = sizeof(cmd.eop);
     
     pending_reply p(cmd.op.rid, &reply, sizeof(reply));
-    if (!transmit_cmd(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
+    if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
       return false;
 
     bool success = (ntohx(reply.ok) == 1);
@@ -1443,7 +1498,7 @@ namespace usrp2 {
     cmd.eop.len = sizeof(cmd.eop);
     
     pending_reply p(cmd.op.rid, &reply, sizeof(reply));
-    if (!transmit_cmd(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
+    if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
       return false;
 
     bool success = (ntohx(reply.ok) == 1);
index ec96f3a7095d8692c0c9c8ec4ff73d33072d227c..ed71a6ba33903c09589b342ea75cdccb8c1fcf34 100644 (file)
@@ -87,6 +87,8 @@ namespace usrp2 {
     int                   d_tx_interp;         // shadow tx interp 
     int                   d_rx_decim;          // shadow rx decim
 
+    bool          d_dont_enqueue;
+
     void inc_enqueued() {
       omni_mutex_lock l(d_enqueued_mutex);
       d_num_enqueued++;
@@ -105,7 +107,8 @@ namespace usrp2 {
     void stop_bg();
     void init_config_rx_v2_cmd(op_config_rx_v2_cmd *cmd);
     void init_config_tx_v2_cmd(op_config_tx_v2_cmd *cmd);
-    bool transmit_cmd(void *cmd, size_t len, pending_reply *p, double secs=0.0);
+    bool transmit_cmd_and_wait(void *cmd, size_t len, pending_reply *p, double secs=0.0);
+    bool transmit_cmd(void *cmd, size_t len);
     virtual data_handler::result operator()(const void *base, size_t len);
     data_handler::result handle_control_packet(const void *base, size_t len);
     data_handler::result handle_data_packet(const void *base, size_t len);
@@ -141,6 +144,7 @@ namespace usrp2 {
     bool read_gpio(int bank, uint16_t *value);
     bool start_rx_streaming(unsigned int channel, unsigned int items_per_frame);
     bool rx_samples(unsigned int channel, rx_sample_handler *handler);
+    bool flush_rx_samples(unsigned int channel);
     bool stop_rx_streaming(unsigned int channel);
     unsigned int rx_overruns() const { return d_num_rx_overruns; }
     unsigned int rx_missing() const { return d_num_rx_missing; }
index 747ca8ef4745e3d4f6dd948ee6b6a64a91a768df..83323f09358b23ef97e940b972a30ab727c57b81 100644 (file)
@@ -38,6 +38,14 @@ typedef enum{
       
     } vrt_test_sig_t;
 
+typedef enum{
+    VRT_BAND_SEL_A='A',
+    VRT_BAND_SEL_B='B',
+    VRT_BAND_SEL_C='C',
+    VRT_BAND_SEL_D='D',  
+      
+    } vrt_band_sel_t;
+
 namespace vrt {
 
   /*
@@ -53,7 +61,7 @@ namespace vrt {
     int                   d_data_port;        // our data port number
     vrt::rx::sptr  d_rx;              // has-a rx
     
-    int                   d_band_select;              // band select setting
+    vrt_band_sel_t                d_band_select;              // band select setting
     int                   d_rx_antenna;               // antenna type rf/cal
     int                   d_attenuation0;             // attenuation setting
     int                   d_attenuation1;             // attenuation setting
@@ -92,7 +100,8 @@ namespace vrt {
 
     /* convenience methods that ultimately write the dboard pins */
     bool set_center_freq(double target_freq);
-    bool set_band_select(const std::string &band);
+    bool set_band_select(vrt_band_sel_t band);
+    vrt_band_sel_t get_band_select(void){return d_band_select;}
     //void set_10dB_atten(bool on);
     bool set_attenuation0(int attenuation);
     bool select_rx_antenna(const std::string &ant);
@@ -110,6 +119,7 @@ namespace vrt {
     bool set_lo_freq(double freq);
     bool set_cal_freq(double freq);
     bool set_beamforming(int32_t gains[8]);
+    bool set_cal_enb(bool enb);
     /*
      * The first parameter for these is a bitmask which indicates which
      * daughterboard or daughterboards to apply the operation to.
index ab5de89b8a2223712f7d38b4e2d5bff0e2d2db83..8cf542e0f3b5889f953b718d8a091cb3350769f0 100644 (file)
@@ -51,7 +51,7 @@ send_and_check(int fd, void *buf, size_t len)
 
 vrt::quadradio::quadradio(const std::string &ip, size_t rx_bufsize)
   : d_ctrl_fd(0), d_data_fd(0), d_data_port(0),
-  d_band_select(0), d_rx_antenna(0), d_attenuation0(0), d_attenuation1(0)//d_10dB_atten(true)
+  d_band_select(VRT_BAND_SEL_A), d_rx_antenna(0), d_attenuation0(0), d_attenuation1(0)//d_10dB_atten(true)
 {
   if (!open(ip.c_str()))
     throw std::runtime_error("vrt::quadradio: failed to open " + ip + "\n");
@@ -89,20 +89,16 @@ vrt::quadradio::stop_streaming()
 bool
 vrt::quadradio::set_center_freq(double target_freq){
     if (target_freq < 700e6) return false;
-    if (target_freq <= 1.0e9) return set_band_select("A");
-    if (target_freq <= 1.5e9) return set_band_select("B");
-    if (target_freq <= 2.2e9) return set_band_select("C");
-    if (target_freq <= 3.0e9) return set_band_select("D");
+    if (target_freq <= 1.0e9) return set_band_select(VRT_BAND_SEL_A);
+    if (target_freq <= 1.5e9) return set_band_select(VRT_BAND_SEL_B);
+    if (target_freq <= 2.2e9) return set_band_select(VRT_BAND_SEL_C);
+    if (target_freq <= 3.0e9) return set_band_select(VRT_BAND_SEL_D);
     return false;
 }
 
 bool
-vrt::quadradio::set_band_select(const std::string &band){
-    if (band == "A") d_band_select = 3;
-    else if (band == "B") d_band_select = 2;
-    else if (band == "C") d_band_select = 1;
-    else if (band == "D") d_band_select = 0;
-    else return false;
+vrt::quadradio::set_band_select(vrt_band_sel_t band){
+    d_band_select = band;
     update_dboard_pins();
     return true;
 }
@@ -149,11 +145,21 @@ static int reverse_bits(int input, int len){
 
 void
 vrt::quadradio::update_dboard_pins(void){
+    //convert the band ID to bits
+    int band_select;
+    switch (d_band_select){
+        case VRT_BAND_SEL_A: band_select = 3; break;
+        case VRT_BAND_SEL_B: band_select = 2; break;
+        case VRT_BAND_SEL_C: band_select = 1; break;
+        case VRT_BAND_SEL_D: band_select = 0; break;
+        default: band_select = 0;
+    }
+    //calculate the control bits
     int db_ctrl = \
-        ((reverse_bits(d_attenuation0, 5) & 0x1f) << 10) | \
+        ((reverse_bits(d_attenuation0, 5)  & 0x1f) << 10) | \
         ((reverse_bits(~d_attenuation1, 5) & 0x1f) << 03) | \
-        ((d_band_select                   & 0x03) << 01) | \
-        ((d_rx_antenna                    & 0x01) << 00);
+        ((band_select                      & 0x03) << 01) | \
+        ((d_rx_antenna                     & 0x01) << 00);
     set_dboard_pins(ALL_DBOARDS, db_ctrl);  // FIXME sets them all
 }
 
@@ -406,3 +412,13 @@ vrt::quadradio::set_beamforming(int32_t gains[8]){
   return send_and_check(d_ctrl_fd, cmd, sizeof(cmd));
 }
 
+bool
+vrt::quadradio::set_cal_enb(bool enb)
+{
+  uint32_t cmd[3];
+  cmd[0] = htonl(0);              // verb: set
+  cmd[1] = htonl(9);              // id: cal enb
+  cmd[2] = htonl(enb);
+
+  return send_and_check(d_ctrl_fd, cmd, sizeof(cmd));
+}