summaryrefslogtreecommitdiff
path: root/gnuradio-core/src
diff options
context:
space:
mode:
authorEric Blossom2010-12-06 23:16:25 -0800
committerEric Blossom2010-12-06 23:16:25 -0800
commit55685f7a8ac97186de05a9e806824fa48e327d47 (patch)
treeadfb51f196eeff692182ff6e8fad2b2b5ac8713d /gnuradio-core/src
parent59a1eeb1b18483ec716afde24df3f0593ed5085c (diff)
parente13783aeb84a2c3656c3344a8d52fa2c9ee38a00 (diff)
downloadgnuradio-55685f7a8ac97186de05a9e806824fa48e327d47.tar.gz
gnuradio-55685f7a8ac97186de05a9e806824fa48e327d47.tar.bz2
gnuradio-55685f7a8ac97186de05a9e806824fa48e327d47.zip
Merge branch 'next' into guile-next
* next: (116 commits) Adding new example script for using the new PFB arbitrary resampler interface. One resampler takes user-generated taps and another resampler just takes the resampling rate. Both input and output signals are plotted. Modifying blsk2 wrapper for PFB arbitrary resampler to allow the user to just specify the requested resampling rate without providing their own filter taps. uhd: reverting tag changes on uhd single usrp source, there seems to be issues with the work() logic uhd: removed default value chan=0 in the cc files WITH_INCLUDES _must_ be last uhd: replaced CFLAGS with CPPFLAGS variable, and fixed swig args FIXME uhd: default channel params to zero for single source and sink blocks Revert "Removed usrp2-firmware from being automatically built." Remove generated file from repo Removed usrp2-firmware from being automatically built. uhd: added libdir to UHD CFLAGS (shared by lib and swig) Swapping out preset keys until I work out some of their issues. Modifying QA tests for the sample tags. By default, it only checks the sizes of the tags since order is not specified or guarenteed. Block is a gr_block, so this sets its relative rate. Was required for using in the QA of the sample tags code. Removing global pmt constants. Were causing segfaults during make check. Must fix this later. Fixing up the UHD sample tag example to take command line options. Swapping order of testing rrate. Changing propagation policy enum type name and making a few other minor edits. Changing API for gr_skiphead to use uint64_t for the offset instead of size_t (still unsigned). Fixes issue #304. Adding typedef for uint64_t and int64_t so we can use them through SWIG. ... Passes make distcheck.
Diffstat (limited to 'gnuradio-core/src')
-rw-r--r--gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_ccf.cc11
-rw-r--r--gnuradio-core/src/lib/filter/gr_pfb_interpolator_ccf.cc2
-rw-r--r--gnuradio-core/src/lib/filter/gr_sincos.c4
-rw-r--r--gnuradio-core/src/lib/filter/gr_single_pole_iir.h6
-rw-r--r--gnuradio-core/src/lib/general/Makefile.am15
-rw-r--r--gnuradio-core/src/lib/general/general.i6
-rw-r--r--gnuradio-core/src/lib/general/gr_annotator_1to1.cc107
-rw-r--r--gnuradio-core/src/lib/general/gr_annotator_1to1.h74
-rw-r--r--gnuradio-core/src/lib/general/gr_annotator_1to1.i36
-rw-r--r--gnuradio-core/src/lib/general/gr_annotator_alltoall.cc110
-rw-r--r--gnuradio-core/src/lib/general/gr_annotator_alltoall.h75
-rw-r--r--gnuradio-core/src/lib/general/gr_annotator_alltoall.i36
-rw-r--r--gnuradio-core/src/lib/general/gr_burst_tagger.cc83
-rw-r--r--gnuradio-core/src/lib/general/gr_burst_tagger.h56
-rw-r--r--gnuradio-core/src/lib/general/gr_burst_tagger.i31
-rw-r--r--gnuradio-core/src/lib/general/gr_circular_file.cc7
-rw-r--r--gnuradio-core/src/lib/general/gr_float_to_complex.cc4
-rw-r--r--gnuradio-core/src/lib/general/gr_keep_one_in_n.cc5
-rw-r--r--gnuradio-core/src/lib/general/gr_skiphead.cc8
-rw-r--r--gnuradio-core/src/lib/general/gr_skiphead.h10
-rw-r--r--gnuradio-core/src/lib/general/gr_skiphead.i8
-rw-r--r--gnuradio-core/src/lib/gengen/gr_add_XX.cc.t2
-rw-r--r--gnuradio-core/src/lib/gengen/gr_divide_XX.cc.t4
-rw-r--r--gnuradio-core/src/lib/gengen/gr_multiply_XX.cc.t2
-rw-r--r--gnuradio-core/src/lib/gengen/gr_sub_XX.cc.t4
-rw-r--r--gnuradio-core/src/lib/io/Makefile.am9
-rw-r--r--gnuradio-core/src/lib/io/gr_tagged_file_sink.cc212
-rw-r--r--gnuradio-core/src/lib/io/gr_tagged_file_sink.h70
-rw-r--r--gnuradio-core/src/lib/io/gr_tagged_file_sink.i35
-rw-r--r--gnuradio-core/src/lib/io/io.i3
-rw-r--r--gnuradio-core/src/lib/runtime/Makefile.am8
-rw-r--r--gnuradio-core/src/lib/runtime/gr_block.cc68
-rw-r--r--gnuradio-core/src/lib/runtime/gr_block.h85
-rw-r--r--gnuradio-core/src/lib/runtime/gr_block.i3
-rw-r--r--gnuradio-core/src/lib/runtime/gr_block_detail.cc92
-rw-r--r--gnuradio-core/src/lib/runtime/gr_block_detail.h73
-rw-r--r--gnuradio-core/src/lib/runtime/gr_block_executor.cc87
-rw-r--r--gnuradio-core/src/lib/runtime/gr_block_executor.h3
-rw-r--r--gnuradio-core/src/lib/runtime/gr_buffer.cc71
-rw-r--r--gnuradio-core/src/lib/runtime/gr_buffer.h50
-rw-r--r--gnuradio-core/src/lib/runtime/gr_flat_flowgraph.cc7
-rw-r--r--gnuradio-core/src/lib/runtime/gr_preferences.cc24
-rw-r--r--gnuradio-core/src/lib/runtime/gr_tag_info.cc38
-rw-r--r--gnuradio-core/src/lib/runtime/gr_tag_info.h87
-rw-r--r--gnuradio-core/src/lib/runtime/qa_block_tags.cc450
-rw-r--r--gnuradio-core/src/lib/runtime/qa_block_tags.h52
-rw-r--r--gnuradio-core/src/lib/runtime/qa_runtime.cc2
-rw-r--r--gnuradio-core/src/lib/swig/gnuradio.i2
-rw-r--r--gnuradio-core/src/python/gnuradio/blks2impl/pfb_arb_resampler.py11
49 files changed, 2174 insertions, 74 deletions
diff --git a/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_ccf.cc b/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_ccf.cc
index 399632003..59b76a6f0 100644
--- a/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_ccf.cc
+++ b/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_ccf.cc
@@ -71,7 +71,7 @@ gr_pfb_arb_resampler_ccf::gr_pfb_arb_resampler_ccf (float rate,
// Create an FIR filter for each channel and zero out the taps
std::vector<float> vtaps(0, d_int_rate);
- for(int i = 0; i < d_int_rate; i++) {
+ for(unsigned int i = 0; i < d_int_rate; i++) {
d_filters[i] = gr_fir_util::create_gr_fir_ccf(vtaps);
d_diff_filters[i] = gr_fir_util::create_gr_fir_ccf(vtaps);
}
@@ -97,8 +97,6 @@ gr_pfb_arb_resampler_ccf::create_taps (const std::vector<float> &newtaps,
std::vector< std::vector<float> > &ourtaps,
std::vector<gr_fir_ccf*> &ourfilter)
{
- int i,j;
-
unsigned int ntaps = newtaps.size();
d_taps_per_filter = (unsigned int)ceil((double)ntaps/(double)d_int_rate);
@@ -114,10 +112,10 @@ gr_pfb_arb_resampler_ccf::create_taps (const std::vector<float> &newtaps,
}
// Partition the filter
- for(i = 0; i < d_int_rate; i++) {
+ for(unsigned int i = 0; i < d_int_rate; i++) {
// Each channel uses all d_taps_per_filter with 0's if not enough taps to fill out
ourtaps[d_int_rate-1-i] = std::vector<float>(d_taps_per_filter, 0);
- for(j = 0; j < d_taps_per_filter; j++) {
+ for(unsigned int j = 0; j < d_taps_per_filter; j++) {
ourtaps[d_int_rate - 1 - i][j] = tmp_taps[i + j*d_int_rate];
}
@@ -173,7 +171,8 @@ gr_pfb_arb_resampler_ccf::general_work (int noutput_items,
return 0; // history requirements may have changed.
}
- int i = 0, j, count = d_start_index;
+ int i = 0, count = d_start_index;
+ unsigned int j;
gr_complex o0, o1;
// Restore the last filter position
diff --git a/gnuradio-core/src/lib/filter/gr_pfb_interpolator_ccf.cc b/gnuradio-core/src/lib/filter/gr_pfb_interpolator_ccf.cc
index 8a0ad1c4c..e20bc38bb 100644
--- a/gnuradio-core/src/lib/filter/gr_pfb_interpolator_ccf.cc
+++ b/gnuradio-core/src/lib/filter/gr_pfb_interpolator_ccf.cc
@@ -132,7 +132,7 @@ gr_pfb_interpolator_ccf::work (int noutput_items,
int i = 0, count = 0;
while(i < noutput_items) {
- for(int j = 0; j < d_rate; j++) {
+ for(unsigned int j = 0; j < d_rate; j++) {
out[i] = d_filters[j]->filter(&in[count]);
i++;
}
diff --git a/gnuradio-core/src/lib/filter/gr_sincos.c b/gnuradio-core/src/lib/filter/gr_sincos.c
index 240a84852..57b26b22f 100644
--- a/gnuradio-core/src/lib/filter/gr_sincos.c
+++ b/gnuradio-core/src/lib/filter/gr_sincos.c
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2004 Free Software Foundation, Inc.
+ * Copyright 2004,2010 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -24,7 +24,9 @@
#include "config.h"
#endif
+#ifndef _GNU_SOURCE
#define _GNU_SOURCE // ask for GNU extensions if available
+#endif
#include <gr_sincos.h>
#include <math.h>
diff --git a/gnuradio-core/src/lib/filter/gr_single_pole_iir.h b/gnuradio-core/src/lib/filter/gr_single_pole_iir.h
index bd59e53ac..da919b35c 100644
--- a/gnuradio-core/src/lib/filter/gr_single_pole_iir.h
+++ b/gnuradio-core/src/lib/filter/gr_single_pole_iir.h
@@ -71,12 +71,12 @@ public:
d_prev_output = 0;
}
- tap_type prev_output () { return d_prev_output; }
+ o_type prev_output () { return d_prev_output; }
protected:
tap_type d_alpha;
tap_type d_one_minus_alpha;
- tap_type d_prev_output;
+ o_type d_prev_output;
};
@@ -87,7 +87,7 @@ template<class o_type, class i_type, class tap_type>
o_type
gr_single_pole_iir<o_type, i_type, tap_type>::filter (const i_type input)
{
- tap_type output;
+ o_type output;
output = d_alpha * input + d_one_minus_alpha * d_prev_output;
d_prev_output = output;
diff --git a/gnuradio-core/src/lib/general/Makefile.am b/gnuradio-core/src/lib/general/Makefile.am
index b25326deb..c6440506d 100644
--- a/gnuradio-core/src/lib/general/Makefile.am
+++ b/gnuradio-core/src/lib/general/Makefile.am
@@ -176,7 +176,10 @@ libgeneral_la_SOURCES = \
gr_descrambler_bb.cc \
gr_scrambler_bb.cc \
gr_probe_mpsk_snr_c.cc \
- gr_probe_density_b.cc
+ gr_probe_density_b.cc \
+ gr_annotator_alltoall.cc \
+ gr_annotator_1to1.cc \
+ gr_burst_tagger.cc
libgeneral_qa_la_SOURCES = \
qa_general.cc \
@@ -346,7 +349,10 @@ grinclude_HEADERS = \
gr_descrambler_bb.h \
gr_scrambler_bb.h \
gr_probe_mpsk_snr_c.h \
- gr_probe_density_b.h
+ gr_probe_density_b.h \
+ gr_annotator_alltoall.h \
+ gr_annotator_1to1.h \
+ gr_burst_tagger.h
noinst_HEADERS = \
qa_general.h \
@@ -487,5 +493,8 @@ swiginclude_HEADERS = \
gr_descrambler_bb.i \
gr_scrambler_bb.i \
gr_probe_mpsk_snr_c.i \
- gr_probe_density_b.i
+ gr_probe_density_b.i \
+ gr_annotator_alltoall.i \
+ gr_annotator_1to1.i \
+ gr_burst_tagger.i
endif
diff --git a/gnuradio-core/src/lib/general/general.i b/gnuradio-core/src/lib/general/general.i
index 2c86a6240..fb9c4c0f2 100644
--- a/gnuradio-core/src/lib/general/general.i
+++ b/gnuradio-core/src/lib/general/general.i
@@ -142,6 +142,9 @@
#include <gr_fll_band_edge_cc.h>
#include <gr_additive_scrambler_bb.h>
#include <complex_vec_test.h>
+#include <gr_annotator_alltoall.h>
+#include <gr_annotator_1to1.h>
+#include <gr_burst_tagger.h>
%}
%include "gr_nop.i"
@@ -264,3 +267,6 @@
%include "gr_fll_band_edge_cc.i"
%include "gr_additive_scrambler_bb.i"
%include "complex_vec_test.i"
+%include "gr_annotator_alltoall.i"
+%include "gr_annotator_1to1.i"
+%include "gr_burst_tagger.i"
diff --git a/gnuradio-core/src/lib/general/gr_annotator_1to1.cc b/gnuradio-core/src/lib/general/gr_annotator_1to1.cc
new file mode 100644
index 000000000..511b356e5
--- /dev/null
+++ b/gnuradio-core/src/lib/general/gr_annotator_1to1.cc
@@ -0,0 +1,107 @@
+/* -*- 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 <gr_annotator_1to1.h>
+#include <gr_io_signature.h>
+#include <string.h>
+#include <iostream>
+#include <iomanip>
+
+gr_annotator_1to1_sptr
+gr_make_annotator_1to1 (int when, size_t sizeof_stream_item)
+{
+ return gnuradio::get_initial_sptr (new gr_annotator_1to1
+ (when, sizeof_stream_item));
+}
+
+gr_annotator_1to1::gr_annotator_1to1 (int when, size_t sizeof_stream_item)
+ : gr_sync_block ("annotator_1to1",
+ gr_make_io_signature (1, -1, sizeof_stream_item),
+ gr_make_io_signature (1, -1, sizeof_stream_item)),
+ d_itemsize(sizeof_stream_item), d_when((uint64_t)when)
+{
+ set_tag_propagation_policy(TPP_ONE_TO_ONE);
+
+ d_tag_counter = 0;
+ set_relative_rate(1.0);
+}
+
+gr_annotator_1to1::~gr_annotator_1to1 ()
+{
+}
+
+int
+gr_annotator_1to1::work (int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+{
+ const float *in = (const float*)input_items[0];
+ float *out = (float*)output_items[0];
+
+ std::stringstream str;
+ str << name() << unique_id();
+
+ uint64_t abs_N = 0;
+ int ninputs = input_items.size();
+ for(int i = 0; i < ninputs; i++) {
+ abs_N = nitems_read(i);
+
+ std::vector<pmt::pmt_t> all_tags;
+ get_tags_in_range(all_tags, i, abs_N, abs_N + noutput_items);
+
+ std::vector<pmt::pmt_t>::iterator itr;
+ for(itr = all_tags.begin(); itr != all_tags.end(); itr++) {
+ d_stored_tags.push_back(*itr);
+ }
+ }
+
+ // Storing the current noutput_items as the value to the "noutput_items" key
+ pmt::pmt_t srcid = pmt::pmt_string_to_symbol(str.str());
+ pmt::pmt_t key = pmt::pmt_string_to_symbol("seq");
+
+ // Work does nothing to the data stream; just copy all inputs to outputs
+ // Adds a new tag when the number of items read is a multiple of d_when
+ abs_N = nitems_read(0);
+ int noutputs = output_items.size();
+ for(int j = 0; j < noutput_items; j++) {
+ // the min() is a hack to make sure this doesn't segfault if there are a
+ // different number of ins and outs. This is specifically designed to test
+ // the 1-to-1 propagation policy.
+ for(int i = 0; i < std::min(noutputs, ninputs); i++) {
+ if(abs_N % d_when == 0) {
+ pmt::pmt_t value = pmt::pmt_from_uint64(d_tag_counter++);
+ add_item_tag(i, abs_N, key, value, srcid);
+ }
+
+ in = (const float*)input_items[i];
+ out = (float*)output_items[i];
+ out[j] = in[j];
+ }
+ abs_N++;
+ }
+
+ return noutput_items;
+}
diff --git a/gnuradio-core/src/lib/general/gr_annotator_1to1.h b/gnuradio-core/src/lib/general/gr_annotator_1to1.h
new file mode 100644
index 000000000..4abc5b051
--- /dev/null
+++ b/gnuradio-core/src/lib/general/gr_annotator_1to1.h
@@ -0,0 +1,74 @@
+/* -*- 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_GR_ANNOTATOR_1TO1_H
+#define INCLUDED_GR_ANNOTATOR_1TO1_H
+
+#include <gr_sync_block.h>
+
+class gr_annotator_1to1;
+typedef boost::shared_ptr<gr_annotator_1to1> gr_annotator_1to1_sptr;
+
+// public constructor
+gr_annotator_1to1_sptr
+gr_make_annotator_1to1 (int when, size_t sizeof_stream_item);
+
+/*!
+ * \brief 1-to-1 stream annotator testing block. FOR TESTING PURPOSES ONLY.
+ *
+ * This block creates tags to be sent downstream every 10,000 items it sees. The
+ * tags contain the name and ID of the instantiated block, use "seq" as a key,
+ * and have a counter that increments by 1 for every tag produced that is used
+ * as the tag's value. The tags are propagated using the 1-to-1 policy.
+ *
+ * It also stores a copy of all tags it sees flow past it. These tags can be
+ * recalled externally with the data() member.
+ *
+ * This block is only meant for testing and showing how to use the tags.
+ */
+class gr_annotator_1to1 : public gr_sync_block
+{
+ public:
+ ~gr_annotator_1to1 ();
+ int work (int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+
+ std::vector<pmt::pmt_t> data() const
+ {
+ return d_stored_tags;
+ }
+
+protected:
+ gr_annotator_1to1 (int when, size_t sizeof_stream_item);
+
+ private:
+ size_t d_itemsize;
+ uint64_t d_when;
+ uint64_t d_tag_counter;
+ std::vector<pmt::pmt_t> d_stored_tags;
+
+ friend gr_annotator_1to1_sptr
+ gr_make_annotator_1to1 (int when, size_t sizeof_stream_item);
+};
+
+#endif
diff --git a/gnuradio-core/src/lib/general/gr_annotator_1to1.i b/gnuradio-core/src/lib/general/gr_annotator_1to1.i
new file mode 100644
index 000000000..f29ecbf53
--- /dev/null
+++ b/gnuradio-core/src/lib/general/gr_annotator_1to1.i
@@ -0,0 +1,36 @@
+/* -*- 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.
+ */
+
+GR_SWIG_BLOCK_MAGIC(gr,annotator_1to1);
+
+gr_annotator_1to1_sptr gr_make_annotator_1to1 (int when,
+ size_t sizeof_stream_item);
+
+class gr_annotator_1to1 : public gr_sync_block
+{
+public:
+ std::vector<pmt::pmt_t> data() const;
+
+private:
+ gr_annotator_1to1 (int when, size_t sizeof_stream_item);
+};
+
diff --git a/gnuradio-core/src/lib/general/gr_annotator_alltoall.cc b/gnuradio-core/src/lib/general/gr_annotator_alltoall.cc
new file mode 100644
index 000000000..344fd088b
--- /dev/null
+++ b/gnuradio-core/src/lib/general/gr_annotator_alltoall.cc
@@ -0,0 +1,110 @@
+/* -*- 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 <gr_annotator_alltoall.h>
+#include <gr_io_signature.h>
+#include <string.h>
+#include <iostream>
+#include <iomanip>
+
+gr_annotator_alltoall_sptr
+gr_make_annotator_alltoall (int when, size_t sizeof_stream_item)
+{
+ return gnuradio::get_initial_sptr (new gr_annotator_alltoall
+ (when, sizeof_stream_item));
+}
+
+gr_annotator_alltoall::gr_annotator_alltoall (int when,
+ size_t sizeof_stream_item)
+ : gr_sync_block ("annotator_alltoall",
+ gr_make_io_signature (1, -1, sizeof_stream_item),
+ gr_make_io_signature (1, -1, sizeof_stream_item)),
+ d_itemsize(sizeof_stream_item), d_when((uint64_t)when)
+{
+ set_tag_propagation_policy(TPP_ALL_TO_ALL);
+
+ d_tag_counter = 0;
+}
+
+gr_annotator_alltoall::~gr_annotator_alltoall ()
+{
+}
+
+int
+gr_annotator_alltoall::work (int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+{
+ const float *in = (const float *) input_items[0];
+ float *out = (float *) output_items[0];
+
+ std::stringstream str;
+ str << name() << unique_id();
+
+ uint64_t abs_N = 0, end_N;
+ int ninputs = input_items.size();
+ for(int i = 0; i < ninputs; i++) {
+ abs_N = nitems_read(i);
+ end_N = abs_N + (uint64_t)(noutput_items);
+
+ std::vector<pmt::pmt_t> all_tags;
+ get_tags_in_range(all_tags, i, abs_N, end_N);
+
+ std::vector<pmt::pmt_t>::iterator itr;
+ for(itr = all_tags.begin(); itr != all_tags.end(); itr++) {
+ d_stored_tags.push_back(*itr);
+ }
+ }
+
+ // Source ID and key for any tag that might get applied from this block
+ pmt::pmt_t srcid = pmt::pmt_string_to_symbol(str.str());
+ pmt::pmt_t key = pmt::pmt_string_to_symbol("seq");
+
+ // Work does nothing to the data stream; just copy all inputs to outputs
+ // Adds a new tag when the number of items read is a multiple of d_when
+ abs_N = nitems_written(0);
+ int noutputs = output_items.size();
+
+ for(int j = 0; j < noutput_items; j++) {
+ for(int i = 0; i < noutputs; i++) {
+ if(abs_N % d_when == 0) {
+ pmt::pmt_t value = pmt::pmt_from_uint64(d_tag_counter++);
+ add_item_tag(i, abs_N, key, value, srcid);
+ }
+
+ // Sum all of the inputs together for each output. Just 'cause.
+ out = (float*)output_items[i];
+ out[j] = 0;
+ for(int ins = 0; ins < ninputs; ins++) {
+ in = (const float*)input_items[ins];
+ out[j] += in[j];
+ }
+ }
+ abs_N++;
+ }
+
+ return noutput_items;
+}
diff --git a/gnuradio-core/src/lib/general/gr_annotator_alltoall.h b/gnuradio-core/src/lib/general/gr_annotator_alltoall.h
new file mode 100644
index 000000000..e1e51ebf3
--- /dev/null
+++ b/gnuradio-core/src/lib/general/gr_annotator_alltoall.h
@@ -0,0 +1,75 @@
+/* -*- 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_GR_ANNOTATOR_ALLTOALL_H
+#define INCLUDED_GR_ANNOTATOR_ALLTOALL_H
+
+#include <gr_sync_block.h>
+
+class gr_annotator_alltoall;
+typedef boost::shared_ptr<gr_annotator_alltoall> gr_annotator_alltoall_sptr;
+
+// public constructor
+gr_annotator_alltoall_sptr
+gr_make_annotator_alltoall (int when, size_t sizeof_stream_item);
+
+/*!
+ * \brief All-to-all stream annotator testing block. FOR TESTING PURPOSES ONLY.
+ *
+ * This block creates tags to be sent downstream every 10,000 items it sees. The
+ * tags contain the name and ID of the instantiated block, use "seq" as a key,
+ * and have a counter that increments by 1 for every tag produced that is used
+ * as the tag's value. The tags are propagated using the all-to-all policy.
+ *
+ * It also stores a copy of all tags it sees flow past it. These tags can be
+ * recalled externally with the data() member.
+ *
+ * This block is only meant for testing and showing how to use the tags.
+ */
+class gr_annotator_alltoall : public gr_sync_block
+{
+ public:
+ ~gr_annotator_alltoall ();
+
+ int work (int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+
+ std::vector<pmt::pmt_t> data() const
+ {
+ return d_stored_tags;
+ }
+
+protected:
+ gr_annotator_alltoall (int when, size_t sizeof_stream_item);
+
+ private:
+ size_t d_itemsize;
+ uint64_t d_when;
+ uint64_t d_tag_counter;
+ std::vector<pmt::pmt_t> d_stored_tags;
+
+ friend gr_annotator_alltoall_sptr
+ gr_make_annotator_alltoall (int when, size_t sizeof_stream_item);
+};
+
+#endif
diff --git a/gnuradio-core/src/lib/general/gr_annotator_alltoall.i b/gnuradio-core/src/lib/general/gr_annotator_alltoall.i
new file mode 100644
index 000000000..f9bf6dd9a
--- /dev/null
+++ b/gnuradio-core/src/lib/general/gr_annotator_alltoall.i
@@ -0,0 +1,36 @@
+/* -*- 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.
+ */
+
+GR_SWIG_BLOCK_MAGIC(gr,annotator_alltoall);
+
+gr_annotator_alltoall_sptr gr_make_annotator_alltoall (int when,
+ size_t sizeof_stream_item);
+
+class gr_annotator_alltoall : public gr_sync_block
+{
+public:
+ std::vector<pmt::pmt_t> data() const;
+
+private:
+ gr_annotator_alltoall (int when, size_t sizeof_stream_item);
+};
+
diff --git a/gnuradio-core/src/lib/general/gr_burst_tagger.cc b/gnuradio-core/src/lib/general/gr_burst_tagger.cc
new file mode 100644
index 000000000..4b3847b08
--- /dev/null
+++ b/gnuradio-core/src/lib/general/gr_burst_tagger.cc
@@ -0,0 +1,83 @@
+/* -*- 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 <gr_burst_tagger.h>
+#include <gr_io_signature.h>
+#include <string.h>
+
+gr_burst_tagger_sptr
+gr_make_burst_tagger(size_t itemsize)
+{
+ return gnuradio::get_initial_sptr(new gr_burst_tagger(itemsize));
+}
+
+gr_burst_tagger::gr_burst_tagger(size_t itemsize)
+ : gr_sync_block ("burst_tagger",
+ gr_make_io_signature2 (2, 2, itemsize, sizeof(short)),
+ gr_make_io_signature (1, 1, itemsize)),
+ d_itemsize(itemsize), d_state(false)
+{
+ std::stringstream str;
+ str << name() << unique_id();
+
+ d_key = pmt::pmt_string_to_symbol("burst");
+ d_id = pmt::pmt_string_to_symbol(str.str());
+}
+
+gr_burst_tagger::~gr_burst_tagger()
+{
+}
+
+int
+gr_burst_tagger::work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+{
+ const char *signal = (const char*)input_items[0];
+ const short *trigger = (const short*)input_items[1];
+ char *out = (char*)output_items[0];
+
+ memcpy(out, signal, noutput_items * d_itemsize);
+
+ for(int i = 0; i < noutput_items; i++) {
+ if(trigger[i] > 0) {
+ if(d_state == false) {
+ d_state = true;
+ pmt::pmt_t value = pmt::PMT_T;
+ add_item_tag(0, nitems_written(0)+i, d_key, value, d_id);
+ }
+ }
+ else {
+ if(d_state == true) {
+ d_state = false;
+ pmt::pmt_t value = pmt::PMT_F;
+ add_item_tag(0, nitems_written(0)+i, d_key, value, d_id);
+ }
+ }
+ }
+
+ return noutput_items;
+}
diff --git a/gnuradio-core/src/lib/general/gr_burst_tagger.h b/gnuradio-core/src/lib/general/gr_burst_tagger.h
new file mode 100644
index 000000000..8f814bea0
--- /dev/null
+++ b/gnuradio-core/src/lib/general/gr_burst_tagger.h
@@ -0,0 +1,56 @@
+/* -*- 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_GR_BURST_TAGGER_H
+#define INCLUDED_GR_BURST_TAGGER_H
+
+#include <gr_sync_block.h>
+
+class gr_burst_tagger;
+typedef boost::shared_ptr<gr_burst_tagger> gr_burst_tagger_sptr;
+
+gr_burst_tagger_sptr gr_make_burst_tagger(size_t itemsize);
+
+/*!
+ * \brief output[i] = input[i]
+ * \ingroup misc_blk
+ *
+ */
+class gr_burst_tagger : public gr_sync_block
+{
+ size_t d_itemsize;
+ bool d_state;
+ pmt::pmt_t d_key;
+ pmt::pmt_t d_id;
+
+ friend gr_burst_tagger_sptr gr_make_burst_tagger(size_t itemsize);
+ gr_burst_tagger(size_t itemsize);
+
+ public:
+ ~gr_burst_tagger();
+
+ int work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+};
+
+#endif
diff --git a/gnuradio-core/src/lib/general/gr_burst_tagger.i b/gnuradio-core/src/lib/general/gr_burst_tagger.i
new file mode 100644
index 000000000..ebf1eea8c
--- /dev/null
+++ b/gnuradio-core/src/lib/general/gr_burst_tagger.i
@@ -0,0 +1,31 @@
+/* -*- 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.
+ */
+
+GR_SWIG_BLOCK_MAGIC(gr,burst_tagger)
+
+gr_burst_tagger_sptr gr_make_burst_tagger(size_t itemsize);
+
+class gr_burst_tagger : public gr_sync_block
+{
+ private:
+ gr_burst_tagger(size_t itemsize);
+};
diff --git a/gnuradio-core/src/lib/general/gr_circular_file.cc b/gnuradio-core/src/lib/general/gr_circular_file.cc
index 468b49a10..c9222597a 100644
--- a/gnuradio-core/src/lib/general/gr_circular_file.cc
+++ b/gnuradio-core/src/lib/general/gr_circular_file.cc
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2002 Free Software Foundation, Inc.
+ * Copyright 2002,2010 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -66,7 +66,10 @@ gr_circular_file::gr_circular_file (const char *filename,
exit (1);
}
#ifdef HAVE_MMAP /* FIXME */
- ftruncate (d_fd, size + HEADER_SIZE);
+ if(ftruncate (d_fd, size + HEADER_SIZE) != 0) {
+ perror (filename);
+ exit (1);
+ }
#endif
}
else {
diff --git a/gnuradio-core/src/lib/general/gr_float_to_complex.cc b/gnuradio-core/src/lib/general/gr_float_to_complex.cc
index 89ef18869..a392abd06 100644
--- a/gnuradio-core/src/lib/general/gr_float_to_complex.cc
+++ b/gnuradio-core/src/lib/general/gr_float_to_complex.cc
@@ -52,12 +52,12 @@ gr_float_to_complex::work (int noutput_items,
switch (input_items.size ()){
case 1:
- for (int j = 0; j < noutput_items*d_vlen; j++)
+ for (size_t j = 0; j < noutput_items*d_vlen; j++)
out[j] = gr_complex (r[j], 0);
break;
case 2:
- for (int j = 0; j < noutput_items*d_vlen; j++)
+ for (size_t j = 0; j < noutput_items*d_vlen; j++)
out[j] = gr_complex (r[j], i[j]);
break;
diff --git a/gnuradio-core/src/lib/general/gr_keep_one_in_n.cc b/gnuradio-core/src/lib/general/gr_keep_one_in_n.cc
index c07e177fe..85495e277 100644
--- a/gnuradio-core/src/lib/general/gr_keep_one_in_n.cc
+++ b/gnuradio-core/src/lib/general/gr_keep_one_in_n.cc
@@ -38,8 +38,9 @@ gr_keep_one_in_n::gr_keep_one_in_n (size_t item_size, int n)
: gr_block ("keep_one_in_n",
gr_make_io_signature (1, 1, item_size),
gr_make_io_signature (1, 1, item_size)),
- d_n (n), d_count(n)
+ d_count(n)
{
+ set_n(n);
}
void
@@ -50,6 +51,8 @@ gr_keep_one_in_n::set_n(int n)
d_n = n;
d_count = n;
+
+ set_relative_rate(1.0 / (float)n);
}
int
diff --git a/gnuradio-core/src/lib/general/gr_skiphead.cc b/gnuradio-core/src/lib/general/gr_skiphead.cc
index ea7e9405f..1670eb7cf 100644
--- a/gnuradio-core/src/lib/general/gr_skiphead.cc
+++ b/gnuradio-core/src/lib/general/gr_skiphead.cc
@@ -27,7 +27,7 @@
#include <gr_io_signature.h>
#include <string.h>
-gr_skiphead::gr_skiphead (size_t itemsize, size_t nitems_to_skip)
+gr_skiphead::gr_skiphead (size_t itemsize, uint64_t nitems_to_skip)
: gr_block ("skiphead",
gr_make_io_signature(1, 1, itemsize),
gr_make_io_signature(1, 1, itemsize)),
@@ -36,7 +36,7 @@ gr_skiphead::gr_skiphead (size_t itemsize, size_t nitems_to_skip)
}
gr_skiphead_sptr
-gr_make_skiphead (size_t itemsize, size_t nitems_to_skip)
+gr_make_skiphead (size_t itemsize, uint64_t nitems_to_skip)
{
return gnuradio::get_initial_sptr(new gr_skiphead (itemsize, nitems_to_skip));
}
@@ -55,11 +55,11 @@ gr_skiphead::general_work(int noutput_items,
while (ii < ninput_items){
- long long ni_total = ii + d_nitems; // total items processed so far
+ uint64_t ni_total = ii + d_nitems; // total items processed so far
if (ni_total < d_nitems_to_skip){ // need to skip some more
int n_to_skip = (int) std::min(d_nitems_to_skip - ni_total,
- (long long)(ninput_items - ii));
+ (uint64_t)(ninput_items - ii));
ii += n_to_skip;
}
diff --git a/gnuradio-core/src/lib/general/gr_skiphead.h b/gnuradio-core/src/lib/general/gr_skiphead.h
index 965feff9b..933c126e3 100644
--- a/gnuradio-core/src/lib/general/gr_skiphead.h
+++ b/gnuradio-core/src/lib/general/gr_skiphead.h
@@ -39,11 +39,11 @@ typedef boost::shared_ptr<gr_skiphead> gr_skiphead_sptr;
class gr_skiphead : public gr_block
{
- friend gr_skiphead_sptr gr_make_skiphead (size_t itemsize, size_t nitems_to_skip);
- gr_skiphead (size_t itemsize, size_t nitems_to_skip);
+ friend gr_skiphead_sptr gr_make_skiphead (size_t itemsize, uint64_t nitems_to_skip);
+ gr_skiphead (size_t itemsize, uint64_t nitems_to_skip);
- long long d_nitems_to_skip;
- long long d_nitems; // total items seen
+ uint64_t d_nitems_to_skip;
+ uint64_t d_nitems; // total items seen
public:
@@ -54,7 +54,7 @@ class gr_skiphead : public gr_block
};
gr_skiphead_sptr
-gr_make_skiphead (size_t itemsize, size_t nitems_to_skip);
+gr_make_skiphead (size_t itemsize, uint64_t nitems_to_skip);
#endif /* INCLUDED_GR_SKIPHEAD_H */
diff --git a/gnuradio-core/src/lib/general/gr_skiphead.i b/gnuradio-core/src/lib/general/gr_skiphead.i
index 52c0808f0..45cbd0437 100644
--- a/gnuradio-core/src/lib/general/gr_skiphead.i
+++ b/gnuradio-core/src/lib/general/gr_skiphead.i
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2005,2007 Free Software Foundation, Inc.
+ * Copyright 2005,2007,2010 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -22,9 +22,9 @@
GR_SWIG_BLOCK_MAGIC(gr,skiphead);
-gr_skiphead_sptr gr_make_skiphead (size_t itemsize, size_t nitems_to_skip);
+gr_skiphead_sptr gr_make_skiphead (size_t itemsize, uint64_t nitems_to_skip);
class gr_skiphead : public gr_block {
- friend gr_skiphead_sptr gr_make_skiphead (size_t itemsize, size_t nitems_to_skip);
- gr_skiphead (size_t itemsize, size_t nitems_to_skip);
+ friend gr_skiphead_sptr gr_make_skiphead (size_t itemsize, uint64_t nitems_to_skip);
+ gr_skiphead (size_t itemsize, uint64_t nitems_to_skip);
};
diff --git a/gnuradio-core/src/lib/gengen/gr_add_XX.cc.t b/gnuradio-core/src/lib/gengen/gr_add_XX.cc.t
index 58a25325a..0e8b23ee1 100644
--- a/gnuradio-core/src/lib/gengen/gr_add_XX.cc.t
+++ b/gnuradio-core/src/lib/gengen/gr_add_XX.cc.t
@@ -52,7 +52,7 @@ int
int ninputs = input_items.size ();
- for (int i = 0; i < noutput_items*d_vlen; i++){
+ for (size_t i = 0; i < noutput_items*d_vlen; i++){
@I_TYPE@ acc = ((@I_TYPE@ *) input_items[0])[i];
for (int j = 1; j < ninputs; j++)
acc += ((@I_TYPE@ *) input_items[j])[i];
diff --git a/gnuradio-core/src/lib/gengen/gr_divide_XX.cc.t b/gnuradio-core/src/lib/gengen/gr_divide_XX.cc.t
index 1200145fa..ea245b57b 100644
--- a/gnuradio-core/src/lib/gengen/gr_divide_XX.cc.t
+++ b/gnuradio-core/src/lib/gengen/gr_divide_XX.cc.t
@@ -53,13 +53,13 @@ int
int ninputs = input_items.size ();
if (ninputs == 1){ // compute reciprocal
- for (int i = 0; i < noutput_items*d_vlen; i++)
+ for (size_t i = 0; i < noutput_items*d_vlen; i++)
*optr++ = (@O_TYPE@) ((@O_TYPE@) 1 /
((@I_TYPE@ *) input_items[0])[i]);
}
else {
- for (int i = 0; i < noutput_items*d_vlen; i++){
+ for (size_t i = 0; i < noutput_items*d_vlen; i++){
@I_TYPE@ acc = ((@I_TYPE@ *) input_items[0])[i];
for (int j = 1; j < ninputs; j++)
acc /= ((@I_TYPE@ *) input_items[j])[i];
diff --git a/gnuradio-core/src/lib/gengen/gr_multiply_XX.cc.t b/gnuradio-core/src/lib/gengen/gr_multiply_XX.cc.t
index 13ec0c8b3..5d270c763 100644
--- a/gnuradio-core/src/lib/gengen/gr_multiply_XX.cc.t
+++ b/gnuradio-core/src/lib/gengen/gr_multiply_XX.cc.t
@@ -52,7 +52,7 @@ int
int ninputs = input_items.size ();
- for (int i = 0; i < noutput_items*d_vlen; i++){
+ for (size_t i = 0; i < noutput_items*d_vlen; i++){
@I_TYPE@ acc = ((@I_TYPE@ *) input_items[0])[i];
for (int j = 1; j < ninputs; j++)
acc *= ((@I_TYPE@ *) input_items[j])[i];
diff --git a/gnuradio-core/src/lib/gengen/gr_sub_XX.cc.t b/gnuradio-core/src/lib/gengen/gr_sub_XX.cc.t
index f0ed75217..1dcdf81ad 100644
--- a/gnuradio-core/src/lib/gengen/gr_sub_XX.cc.t
+++ b/gnuradio-core/src/lib/gengen/gr_sub_XX.cc.t
@@ -53,12 +53,12 @@ int
int ninputs = input_items.size ();
if (ninputs == 1){ // negate
- for (int i = 0; i < noutput_items*d_vlen; i++)
+ for (size_t i = 0; i < noutput_items*d_vlen; i++)
*optr++ = (@O_TYPE@) -((@I_TYPE@ *) input_items[0])[i];
}
else {
- for (int i = 0; i < noutput_items*d_vlen; i++){
+ for (size_t i = 0; i < noutput_items*d_vlen; i++){
@I_TYPE@ acc = ((@I_TYPE@ *) input_items[0])[i];
for (int j = 1; j < ninputs; j++)
acc -= ((@I_TYPE@ *) input_items[j])[i];
diff --git a/gnuradio-core/src/lib/io/Makefile.am b/gnuradio-core/src/lib/io/Makefile.am
index c52554645..8ce740afd 100644
--- a/gnuradio-core/src/lib/io/Makefile.am
+++ b/gnuradio-core/src/lib/io/Makefile.am
@@ -56,7 +56,8 @@ libio_la_SOURCES = \
gr_udp_source.cc \
gr_wavfile_sink.cc \
gr_wavfile_source.cc \
- gri_wavfile.cc
+ gri_wavfile.cc \
+ gr_tagged_file_sink.cc
grinclude_HEADERS = \
gr_file_sink.h \
@@ -89,7 +90,8 @@ grinclude_HEADERS = \
gr_udp_source.h \
gr_wavfile_source.h \
gr_wavfile_sink.h \
- gri_wavfile.h
+ gri_wavfile.h \
+ gr_tagged_file_sink.h
if PYTHON
swiginclude_HEADERS = \
@@ -111,5 +113,6 @@ swiginclude_HEADERS = \
gr_udp_sink.i \
gr_udp_source.i \
gr_wavfile_source.i \
- gr_wavfile_sink.i
+ gr_wavfile_sink.i \
+ gr_tagged_file_sink.i
endif
diff --git a/gnuradio-core/src/lib/io/gr_tagged_file_sink.cc b/gnuradio-core/src/lib/io/gr_tagged_file_sink.cc
new file mode 100644
index 000000000..c76ede542
--- /dev/null
+++ b/gnuradio-core/src/lib/io/gr_tagged_file_sink.cc
@@ -0,0 +1,212 @@
+/* -*- 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 <gr_tagged_file_sink.h>
+#include <gr_io_signature.h>
+#include <cstdio>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdexcept>
+#include <iostream>
+#include <gr_tag_info.h>
+
+#ifdef O_BINARY
+#define OUR_O_BINARY O_BINARY
+#else
+#define OUR_O_BINARY 0
+#endif
+
+// should be handled via configure
+#ifdef O_LARGEFILE
+#define OUR_O_LARGEFILE O_LARGEFILE
+#else
+#define OUR_O_LARGEFILE 0
+#endif
+
+
+gr_tagged_file_sink::gr_tagged_file_sink (size_t itemsize, double samp_rate)
+ : gr_sync_block ("tagged_file_sink",
+ gr_make_io_signature (1, 1, itemsize),
+ gr_make_io_signature (0, 0, 0)),
+ d_itemsize (itemsize), d_n(0), d_sample_rate(samp_rate)
+{
+ d_state = NOT_IN_BURST;
+ d_last_N = 0;
+ d_timeval = 0;
+}
+
+gr_tagged_file_sink_sptr
+gr_make_tagged_file_sink (size_t itemsize, double samp_rate)
+{
+ return gnuradio::get_initial_sptr(new gr_tagged_file_sink (itemsize, samp_rate));
+}
+
+gr_tagged_file_sink::~gr_tagged_file_sink ()
+{
+}
+
+int
+gr_tagged_file_sink::work (int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+{
+ char *inbuf = (char *) input_items[0];
+
+ uint64_t start_N = nitems_read(0);
+ uint64_t end_N = start_N + (uint64_t)(noutput_items);
+ pmt::pmt_t bkey = pmt::pmt_string_to_symbol("burst");
+ //pmt::pmt_t tkey = pmt::pmt_string_to_symbol("time"); // use gr_tags::key_time
+
+ std::vector<pmt::pmt_t> all_tags;
+ get_tags_in_range(all_tags, 0, start_N, end_N);
+
+ std::sort(all_tags.begin(), all_tags.end(), gr_tags::nitems_compare);
+
+ std::vector<pmt::pmt_t>::iterator vitr = all_tags.begin();
+
+ int idx = 0, idx_stop = 0;
+ while(idx < noutput_items) {
+ if(d_state == NOT_IN_BURST) {
+ while(vitr != all_tags.end()) {
+ if((pmt::pmt_eqv(gr_tags::get_key(*vitr), bkey)) &&
+ pmt::pmt_is_true(gr_tags::get_value(*vitr))) {
+
+ uint64_t N = gr_tags::get_nitems(*vitr);
+ idx = (int)(N - start_N);
+
+ //std::cout << std::endl << "Found start of burst: "
+ // << idx << ", " << N << std::endl;
+
+ // Find time burst occurred by getting latest time tag and extrapolating
+ // to new time based on sample rate of this block.
+ std::vector<pmt::pmt_t> time_tags;
+ //get_tags_in_range(time_tags, 0, d_last_N, N, gr_tags::key_time);
+ get_tags_in_range(time_tags, 0, d_last_N, N,
+ pmt::pmt_string_to_symbol("time"));
+ if(time_tags.size() > 0) {
+ pmt::pmt_t tag = time_tags[time_tags.size()-1];
+
+ uint64_t time_nitems = gr_tags::get_nitems(tag);
+
+ // Get time based on last time tag from USRP
+ pmt::pmt_t time = gr_tags::get_value(tag);
+ int tsecs = pmt::pmt_to_long(pmt::pmt_tuple_ref(time, 0));
+ double tfrac = pmt::pmt_to_double(pmt::pmt_tuple_ref(time, 1));
+
+ // Get new time from last time tag + difference in time to when
+ // burst tag occured based on the sample rate
+ double delta = (double)(N - time_nitems) / d_sample_rate;
+ d_timeval = (double)tsecs + tfrac + delta;
+
+ //std::cout.setf(std::ios::fixed, std::ios::floatfield);
+ //std::cout.precision(8);
+ //std::cout << "Time found: " << (double)tsecs + tfrac << std::endl;
+ //std::cout << " time: " << d_timeval << std::endl;
+ //std::cout << " time at N = " << time_nitems << " burst N = " << N << std::endl;
+ }
+ else {
+ // if no time tag, use last seen tag and update time based on
+ // sample rate of the block
+ d_timeval += (double)(N - d_last_N) / d_sample_rate;
+ //std::cout << "Time not found" << std::endl;
+ //std::cout << " time: " << d_timeval << std::endl;
+ }
+ d_last_N = N;
+
+ std::stringstream filename;
+ filename.setf(std::ios::fixed, std::ios::floatfield);
+ filename.precision(8);
+ filename << "file" << d_n << "_" << d_timeval << ".dat";
+ d_n++;
+
+ int fd;
+ if ((fd = ::open (filename.str().c_str(),
+ O_WRONLY|O_CREAT|O_TRUNC|OUR_O_LARGEFILE|OUR_O_BINARY,
+ 0664)) < 0){
+ perror (filename.str().c_str());
+ return -1;
+ }
+
+ // FIXME:
+ //if ((d_handle = fdopen (fd, d_is_binary ? "wb" : "w")) == NULL){
+ if ((d_handle = fdopen (fd, "wb")) == NULL){
+ perror (filename.str().c_str());
+ ::close(fd); // don't leak file descriptor if fdopen fails.
+ }
+
+ //std::cout << "Created new file: " << filename.str() << std::endl;
+
+ d_state = IN_BURST;
+ break;
+ }
+
+ vitr++;
+ }
+ if(d_state == NOT_IN_BURST)
+ return noutput_items;
+ }
+ else { // In burst
+ while(vitr != all_tags.end()) {
+ if((pmt::pmt_eqv(gr_tags::get_key(*vitr), bkey)) &&
+ pmt::pmt_is_false(gr_tags::get_value(*vitr))) {
+ uint64_t N = gr_tags::get_nitems(*vitr);
+ idx_stop = (int)N - start_N;
+
+ //std::cout << "Found end of burst: "
+ // << idx_stop << ", " << N << std::endl;
+
+ int count = fwrite (&inbuf[d_itemsize*idx], d_itemsize, idx_stop-idx, d_handle);
+ if (count == 0) {
+ if(ferror(d_handle)) {
+ perror("gr_tagged_file_sink: error writing file");
+ }
+ }
+ idx = idx_stop;
+ d_state = NOT_IN_BURST;
+ vitr++;
+ fclose(d_handle);
+ break;
+ }
+ else {
+ vitr++;
+ }
+ }
+ if(d_state == IN_BURST) {
+ int count = fwrite (&inbuf[idx], d_itemsize, noutput_items-idx, d_handle);
+ if (count == 0) {
+ if(ferror(d_handle)) {
+ perror("gr_tagged_file_sink: error writing file");
+ }
+ }
+ idx = noutput_items;
+ }
+ }
+ }
+
+ return noutput_items;
+}
diff --git a/gnuradio-core/src/lib/io/gr_tagged_file_sink.h b/gnuradio-core/src/lib/io/gr_tagged_file_sink.h
new file mode 100644
index 000000000..956340f8d
--- /dev/null
+++ b/gnuradio-core/src/lib/io/gr_tagged_file_sink.h
@@ -0,0 +1,70 @@
+/* -*- 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_GR_TAGGED_FILE_SINK_H
+#define INCLUDED_GR_TAGGED_FILE_SINK_H
+
+#include <gr_sync_block.h>
+
+class gr_tagged_file_sink;
+typedef boost::shared_ptr<gr_tagged_file_sink> gr_tagged_file_sink_sptr;
+
+gr_tagged_file_sink_sptr gr_make_tagged_file_sink (size_t itemsize,
+ double samp_rate);
+
+/*!
+ * \brief Write stream to file descriptor.
+ * \ingroup sink_blk
+ */
+
+class gr_tagged_file_sink : public gr_sync_block
+{
+ friend gr_tagged_file_sink_sptr gr_make_tagged_file_sink (size_t itemsize,
+ double samp_rate);
+
+ private:
+ enum {
+ NOT_IN_BURST = 0,
+ IN_BURST
+ };
+
+ size_t d_itemsize;
+ int d_state;
+ FILE *d_handle;
+ int d_n;
+ double d_sample_rate;
+ uint64_t d_last_N;
+ double d_timeval;
+
+ protected:
+ gr_tagged_file_sink (size_t itemsize, double samp_rate);
+
+ public:
+ ~gr_tagged_file_sink ();
+
+ int work (int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+};
+
+
+#endif /* INCLUDED_GR_TAGGED_FILE_SINK_H */
diff --git a/gnuradio-core/src/lib/io/gr_tagged_file_sink.i b/gnuradio-core/src/lib/io/gr_tagged_file_sink.i
new file mode 100644
index 000000000..1408adfc1
--- /dev/null
+++ b/gnuradio-core/src/lib/io/gr_tagged_file_sink.i
@@ -0,0 +1,35 @@
+/* -*- 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.
+ */
+
+GR_SWIG_BLOCK_MAGIC(gr,tagged_file_sink)
+
+gr_tagged_file_sink_sptr
+gr_make_tagged_file_sink (size_t itemsize, double samp_rate);
+
+class gr_tagged_file_sink : public gr_sync_block
+{
+ protected:
+ gr_tagged_file_sink (size_t itemsize, double samp_rate);
+
+ public:
+ ~gr_tagged_file_sink ();
+};
diff --git a/gnuradio-core/src/lib/io/io.i b/gnuradio-core/src/lib/io/io.i
index 3538942ca..365577cd4 100644
--- a/gnuradio-core/src/lib/io/io.i
+++ b/gnuradio-core/src/lib/io/io.i
@@ -43,7 +43,7 @@
#include <gr_udp_source.h>
#include <gr_wavfile_sink.h>
#include <gr_wavfile_source.h>
-
+#include <gr_tagged_file_sink.h>
%}
%include "gr_file_sink_base.i"
@@ -64,4 +64,5 @@
%include "gr_udp_source.i"
%include "gr_wavfile_sink.i"
%include "gr_wavfile_source.i"
+%include "gr_tagged_file_sink.i"
diff --git a/gnuradio-core/src/lib/runtime/Makefile.am b/gnuradio-core/src/lib/runtime/Makefile.am
index f67e8843d..dd9a8ea64 100644
--- a/gnuradio-core/src/lib/runtime/Makefile.am
+++ b/gnuradio-core/src/lib/runtime/Makefile.am
@@ -68,7 +68,8 @@ libruntime_la_SOURCES = \
gr_vmcircbuf_mmap_tmpfile.cc \
gr_vmcircbuf_createfilemapping.cc \
gr_vmcircbuf_sysv_shm.cc \
- gr_select_handler.cc
+ gr_select_handler.cc \
+ gr_tag_info.cc
libruntime_qa_la_SOURCES = \
qa_gr_block.cc \
@@ -79,6 +80,7 @@ libruntime_qa_la_SOURCES = \
qa_gr_top_block.cc \
qa_gr_io_signature.cc \
qa_gr_vmcircbuf.cc \
+ qa_block_tags.cc \
qa_runtime.cc
grinclude_HEADERS = \
@@ -121,7 +123,8 @@ grinclude_HEADERS = \
gr_tmp_path.h \
gr_types.h \
gr_unittests.h \
- gr_vmcircbuf.h
+ gr_vmcircbuf.h \
+ gr_tag_info.h
noinst_HEADERS = \
gr_vmcircbuf_mmap_shm_open.h \
@@ -136,6 +139,7 @@ noinst_HEADERS = \
qa_gr_io_signature.h \
qa_gr_top_block.h \
qa_gr_vmcircbuf.h \
+ qa_block_tags.h \
qa_runtime.h
if PYTHON
diff --git a/gnuradio-core/src/lib/runtime/gr_block.cc b/gnuradio-core/src/lib/runtime/gr_block.cc
index 8915f3360..81a55af9d 100644
--- a/gnuradio-core/src/lib/runtime/gr_block.cc
+++ b/gnuradio-core/src/lib/runtime/gr_block.cc
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2004,2009 Free Software Foundation, Inc.
+ * Copyright 2004,2009,2010 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -36,7 +36,8 @@ gr_block::gr_block (const std::string &name,
d_output_multiple (1),
d_relative_rate (1.0),
d_history(1),
- d_fixed_rate(false)
+ d_fixed_rate(false),
+ d_tag_propagation_policy(TPP_ALL_TO_ALL)
{
}
@@ -117,6 +118,69 @@ gr_block::fixed_rate_noutput_to_ninput(int noutput)
throw std::runtime_error("Unimplemented");
}
+uint64_t
+gr_block::nitems_read(unsigned int which_input)
+{
+ if(d_detail) {
+ return d_detail->nitems_read(which_input);
+ }
+ else {
+ //throw std::runtime_error("No block_detail associated with block yet");
+ return 0;
+ }
+}
+
+uint64_t
+gr_block::nitems_written(unsigned int which_output)
+{
+ if(d_detail) {
+ return d_detail->nitems_written(which_output);
+ }
+ else {
+ //throw std::runtime_error("No block_detail associated with block yet");
+ return 0;
+ }
+}
+
+void
+gr_block::add_item_tag(unsigned int which_output,
+ uint64_t offset,
+ const pmt::pmt_t &key,
+ const pmt::pmt_t &value,
+ const pmt::pmt_t &srcid)
+{
+ d_detail->add_item_tag(which_output, offset, key, value, srcid);
+}
+
+void
+gr_block::get_tags_in_range(std::vector<pmt::pmt_t> &v,
+ unsigned int which_output,
+ uint64_t start, uint64_t end)
+{
+ d_detail->get_tags_in_range(v, which_output, start, end);
+}
+
+void
+gr_block::get_tags_in_range(std::vector<pmt::pmt_t> &v,
+ unsigned int which_output,
+ uint64_t start, uint64_t end,
+ const pmt::pmt_t &key)
+{
+ d_detail->get_tags_in_range(v, which_output, start, end, key);
+}
+
+gr_block::tag_propagation_policy_t
+gr_block::tag_propagation_policy()
+{
+ return d_tag_propagation_policy;
+}
+
+void
+gr_block::set_tag_propagation_policy(tag_propagation_policy_t p)
+{
+ d_tag_propagation_policy = p;
+}
+
std::ostream&
operator << (std::ostream& os, const gr_block *m)
{
diff --git a/gnuradio-core/src/lib/runtime/gr_block.h b/gnuradio-core/src/lib/runtime/gr_block.h
index b6f724dde..ad7fa9555 100644
--- a/gnuradio-core/src/lib/runtime/gr_block.h
+++ b/gnuradio-core/src/lib/runtime/gr_block.h
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2004,2007,2009 Free Software Foundation, Inc.
+ * Copyright 2004,2007,2009,2010 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -63,6 +63,12 @@ class gr_block : public gr_basic_block {
WORK_DONE = -1
};
+ enum tag_propagation_policy_t {
+ TPP_DONT = 0,
+ TPP_ALL_TO_ALL = 1,
+ TPP_ONE_TO_ONE = 2
+ };
+
virtual ~gr_block ();
/*!
@@ -198,6 +204,26 @@ class gr_block : public gr_basic_block {
*/
virtual int fixed_rate_noutput_to_ninput(int noutput);
+ /*!
+ * \brief Return the number of items read on input stream which_input
+ */
+ uint64_t nitems_read(unsigned int which_input);
+
+ /*!
+ * \brief Return the number of items written on output stream which_output
+ */
+ uint64_t nitems_written(unsigned int which_output);
+
+ /*!
+ * \brief Asks for the policy used by the scheduler to moved tags downstream.
+ */
+ tag_propagation_policy_t tag_propagation_policy();
+
+ /*!
+ * \brief Set the policy by the scheduler to determine how tags are moved downstream.
+ */
+ void set_tag_propagation_policy(tag_propagation_policy_t p);
+
// ----------------------------------------------------------------------------
private:
@@ -207,6 +233,7 @@ class gr_block : public gr_basic_block {
gr_block_detail_sptr d_detail; // implementation details
unsigned d_history;
bool d_fixed_rate;
+ tag_propagation_policy_t d_tag_propagation_policy; // policy for moving tags downstream
protected:
@@ -216,6 +243,62 @@ class gr_block : public gr_basic_block {
void set_fixed_rate(bool fixed_rate){ d_fixed_rate = fixed_rate; }
+
+ /*!
+ * \brief Adds a new tag onto the given output buffer.
+ *
+ * \param which_output an integer of which output stream to attach the tag
+ * \param abs_offset a uint64 number of the absolute item number
+ * assicated with the tag. Can get from nitems_written.
+ * \param key the tag key as a PMT symbol
+ * \param value any PMT holding any value for the given key
+ * \param srcid optional source ID specifier; defaults to PMT_F
+ */
+ void add_item_tag(unsigned int which_output,
+ uint64_t abs_offset,
+ const pmt::pmt_t &key,
+ const pmt::pmt_t &value,
+ const pmt::pmt_t &srcid=pmt::PMT_F);
+
+ /*!
+ * \brief Given a [start,end), returns a vector of all tags in the range.
+ *
+ * Range of counts is from start to end-1.
+ *
+ * Tags are tuples of:
+ * (item count, source id, key, value)
+ *
+ * \param v a vector reference to return tags into
+ * \param which_input an integer of which input stream to pull from
+ * \param abs_start a uint64 count of the start of the range of interest
+ * \param abs_end a uint64 count of the end of the range of interest
+ */
+ void get_tags_in_range(std::vector<pmt::pmt_t> &v,
+ unsigned int which_input,
+ uint64_t abs_start,
+ uint64_t abs_end);
+
+ /*!
+ * \brief Given a [start,end), returns a vector of all tags in the range
+ * with a given key.
+ *
+ * Range of counts is from start to end-1.
+ *
+ * Tags are tuples of:
+ * (item count, source id, key, value)
+ *
+ * \param v a vector reference to return tags into
+ * \param which_input an integer of which input stream to pull from
+ * \param abs_start a uint64 count of the start of the range of interest
+ * \param abs_end a uint64 count of the end of the range of interest
+ * \param key a PMT symbol key to filter only tags of this key
+ */
+ void get_tags_in_range(std::vector<pmt::pmt_t> &v,
+ unsigned int which_input,
+ uint64_t abs_start,
+ uint64_t abs_end,
+ const pmt::pmt_t &key);
+
// These are really only for internal use, but leaving them public avoids
// having to work up an ever-varying list of friends
diff --git a/gnuradio-core/src/lib/runtime/gr_block.i b/gnuradio-core/src/lib/runtime/gr_block.i
index f4ee43477..bb0c5f221 100644
--- a/gnuradio-core/src/lib/runtime/gr_block.i
+++ b/gnuradio-core/src/lib/runtime/gr_block.i
@@ -49,6 +49,9 @@ class gr_block : public gr_basic_block {
bool start();
bool stop();
+ uint64_t nitems_read(unsigned int which_input);
+ uint64_t nitems_written(unsigned int which_output);
+
// internal use
gr_block_detail_sptr detail () const { return d_detail; }
void set_detail (gr_block_detail_sptr detail) { d_detail = detail; }
diff --git a/gnuradio-core/src/lib/runtime/gr_block_detail.cc b/gnuradio-core/src/lib/runtime/gr_block_detail.cc
index 38d4a13ca..a360240c0 100644
--- a/gnuradio-core/src/lib/runtime/gr_block_detail.cc
+++ b/gnuradio-core/src/lib/runtime/gr_block_detail.cc
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2004,2009 Free Software Foundation, Inc.
+ * Copyright 2004,2009,2010 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -27,6 +27,8 @@
#include <gr_block_detail.h>
#include <gr_buffer.h>
+using namespace pmt;
+
static long s_ncurrently_allocated = 0;
long
@@ -88,16 +90,20 @@ gr_block_detail::set_done (bool done)
void
gr_block_detail::consume (int which_input, int how_many_items)
{
- if (how_many_items > 0)
+ if (how_many_items > 0) {
input (which_input)->update_read_pointer (how_many_items);
+ }
}
+
void
gr_block_detail::consume_each (int how_many_items)
{
- if (how_many_items > 0)
- for (int i = 0; i < ninputs (); i++)
+ if (how_many_items > 0) {
+ for (int i = 0; i < ninputs (); i++) {
d_input[i]->update_read_pointer (how_many_items);
+ }
+ }
}
void
@@ -112,16 +118,88 @@ gr_block_detail::produce (int which_output, int how_many_items)
void
gr_block_detail::produce_each (int how_many_items)
{
- if (how_many_items > 0){
- for (int i = 0; i < noutputs (); i++)
+ if (how_many_items > 0) {
+ for (int i = 0; i < noutputs (); i++) {
d_output[i]->update_write_pointer (how_many_items);
+ }
d_produce_or |= how_many_items;
}
}
void
-gr_block_detail::_post(pmt::pmt_t msg)
+gr_block_detail::_post(pmt_t msg)
{
d_tpb.insert_tail(msg);
}
+
+uint64_t
+gr_block_detail::nitems_read(unsigned int which_input)
+{
+ if(which_input >= d_ninputs)
+ throw std::invalid_argument ("gr_block_detail::n_input_items");
+ return d_input[which_input]->nitems_read();
+}
+
+uint64_t
+gr_block_detail::nitems_written(unsigned int which_output)
+{
+ if(which_output >= d_noutputs)
+ throw std::invalid_argument ("gr_block_detail::n_output_items");
+ return d_output[which_output]->nitems_written();
+}
+
+void
+gr_block_detail::add_item_tag(unsigned int which_output,
+ uint64_t abs_offset,
+ const pmt_t &key,
+ const pmt_t &value,
+ const pmt_t &srcid)
+{
+ if(!pmt_is_symbol(key)) {
+ throw pmt_wrong_type("gr_block_detail::add_item_tag key", key);
+ }
+ else {
+ // build tag tuple
+ pmt_t nitem = pmt_from_uint64(abs_offset);
+ pmt_t tuple = pmt_make_tuple(nitem, srcid, key, value);
+
+ // Add tag to gr_buffer's deque tags
+ d_output[which_output]->add_item_tag(tuple);
+ }
+}
+
+void
+gr_block_detail::get_tags_in_range(std::vector<pmt::pmt_t> &v,
+ unsigned int which_input,
+ uint64_t abs_start,
+ uint64_t abs_end)
+{
+ // get from gr_buffer_reader's deque of tags
+ d_input[which_input]->get_tags_in_range(v, abs_start, abs_end);
+}
+
+void
+gr_block_detail::get_tags_in_range(std::vector<pmt_t> &v,
+ unsigned int which_input,
+ uint64_t abs_start,
+ uint64_t abs_end,
+ const pmt_t &key)
+{
+ std::vector<pmt_t> found_items;
+
+ v.resize(0);
+
+ // get from gr_buffer_reader's deque of tags
+ d_input[which_input]->get_tags_in_range(found_items, abs_start, abs_end);
+
+ // Filter further by key name
+ pmt_t itemkey;
+ std::vector<pmt_t>::iterator itr;
+ for(itr = found_items.begin(); itr != found_items.end(); itr++) {
+ itemkey = pmt_tuple_ref(*itr, 2);
+ if(pmt_eqv(key, itemkey)) {
+ v.push_back(*itr);
+ }
+ }
+}
diff --git a/gnuradio-core/src/lib/runtime/gr_block_detail.h b/gnuradio-core/src/lib/runtime/gr_block_detail.h
index c5787a5ad..d7ec3b136 100644
--- a/gnuradio-core/src/lib/runtime/gr_block_detail.h
+++ b/gnuradio-core/src/lib/runtime/gr_block_detail.h
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2004,2009 Free Software Foundation, Inc.
+ * Copyright 2004,2009,2010 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -25,6 +25,7 @@
#include <gr_runtime_types.h>
#include <gr_tpb_detail.h>
+#include <gr_tag_info.h>
#include <stdexcept>
/*!
@@ -88,6 +89,75 @@ class gr_block_detail {
*/
void _post(pmt::pmt_t msg);
+ // Return the number of items read on input stream which_input
+ uint64_t nitems_read(unsigned int which_input);
+
+ // Return the number of items written on output stream which_output
+ uint64_t nitems_written(unsigned int which_output);
+
+
+ /*!
+ * \brief Adds a new tag to the given output stream.
+ *
+ * This takes the input parameters and builds a PMT tuple
+ * from it. It then calls gr_buffer::add_item_tag(pmt::pmt_t t),
+ * which appends the tag onto its deque.
+ *
+ * \param which_output an integer of which output stream to attach the tag
+ * \param abs_offset a uint64 number of the absolute item number
+ * assicated with the tag. Can get from nitems_written.
+ * \param key the tag key as a PMT symbol
+ * \param value any PMT holding any value for the given key
+ * \param srcid a PMT source ID specifier
+ */
+ void add_item_tag(unsigned int which_output,
+ uint64_t abs_offset,
+ const pmt::pmt_t &key,
+ const pmt::pmt_t &value,
+ const pmt::pmt_t &srcid);
+
+ /*!
+ * \brief Given a [start,end), returns a vector of all tags in the range.
+ *
+ * Pass-through function to gr_buffer_reader to get a vector of tags
+ * in given range. Range of counts is from start to end-1.
+ *
+ * Tags are tuples of:
+ * (item count, source id, key, value)
+ *
+ * \param v a vector reference to return tags into
+ * \param which_input an integer of which input stream to pull from
+ * \param abs_start a uint64 count of the start of the range of interest
+ * \param abs_end a uint64 count of the end of the range of interest
+ */
+ void get_tags_in_range(std::vector<pmt::pmt_t> &v,
+ unsigned int which_input,
+ uint64_t abs_start,
+ uint64_t abs_end);
+
+ /*!
+ * \brief Given a [start,end), returns a vector of all tags in the range
+ * with a given key.
+ *
+ * Calls get_tags_in_range(which_input, abs_start, abs_end) to get a vector of
+ * tags from the buffers. This function then provides a secondary filter to
+ * the tags to extract only tags with the given 'key'.
+ *
+ * Tags are tuples of:
+ * (item count, source id, key, value)
+ *
+ * \param v a vector reference to return tags into
+ * \param which_input an integer of which input stream to pull from
+ * \param abs_start a uint64 count of the start of the range of interest
+ * \param abs_end a uint64 count of the end of the range of interest
+ * \param key a PMT symbol to select only tags of this key
+ */
+ void get_tags_in_range(std::vector<pmt::pmt_t> &v,
+ unsigned int which_input,
+ uint64_t abs_start,
+ uint64_t abs_end,
+ const pmt::pmt_t &key);
+
gr_tpb_detail d_tpb; // used by thread-per-block scheduler
int d_produce_or;
@@ -100,7 +170,6 @@ class gr_block_detail {
std::vector<gr_buffer_sptr> d_output;
bool d_done;
-
gr_block_detail (unsigned int ninputs, unsigned int noutputs);
friend class gr_tpb_detail;
diff --git a/gnuradio-core/src/lib/runtime/gr_block_executor.cc b/gnuradio-core/src/lib/runtime/gr_block_executor.cc
index 2c21a0b0f..112150235 100644
--- a/gnuradio-core/src/lib/runtime/gr_block_executor.cc
+++ b/gnuradio-core/src/lib/runtime/gr_block_executor.cc
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2004,2008,2009 Free Software Foundation, Inc.
+ * Copyright 2004,2008,2009,2010 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -87,7 +87,80 @@ min_available_space (gr_block_detail *d, int output_multiple)
return min_space;
}
+static bool
+propagate_tags(gr_block::tag_propagation_policy_t policy, gr_block_detail *d,
+ const std::vector<uint64_t> &start_nitems_read, double rrate,
+ std::vector<pmt::pmt_t> &rtags)
+{
+ // Move tags downstream
+ // if a sink, we don't need to move downstream;
+ // and do not bother if block uses TAGS_NONE attribute
+ if(d->sink_p()) {
+ return true;
+ }
+ switch(policy) {
+ case gr_block::TPP_DONT:
+ return true;
+ break;
+ case gr_block::TPP_ALL_TO_ALL:
+ // every tag on every input propogates to everyone downstream
+ for(int i = 0; i < d->ninputs(); i++) {
+ d->get_tags_in_range(rtags, i, start_nitems_read[i],
+ d->nitems_read(i));
+
+ std::vector<pmt::pmt_t>::iterator t;
+ if(rrate == 1.0) {
+ for(t = rtags.begin(); t != rtags.end(); t++) {
+ for(int o = 0; o < d->noutputs(); o++)
+ d->output(o)->add_item_tag(*t);
+ }
+ }
+ else {
+ for(t = rtags.begin(); t != rtags.end(); t++) {
+ uint64_t newcount = pmt::pmt_to_uint64(pmt::pmt_tuple_ref(*t, 0));
+ pmt::pmt_t newtup = pmt::mp(pmt::pmt_from_uint64(newcount * rrate),
+ pmt::pmt_tuple_ref(*t, 1),
+ pmt::pmt_tuple_ref(*t, 2),
+ pmt::pmt_tuple_ref(*t, 3));
+
+ for(int o = 0; o < d->noutputs(); o++)
+ d->output(o)->add_item_tag(newtup);
+ }
+ }
+ }
+ break;
+ case gr_block::TPP_ONE_TO_ONE:
+ // tags from input i only go to output i
+ // this requires d->ninputs() == d->noutputs; this is checked when this
+ // type of tag-propagation system is selected in gr_block_detail
+ if(d->ninputs() == d->noutputs()) {
+ for(int i = 0; i < d->ninputs(); i++) {
+ d->get_tags_in_range(rtags, i, start_nitems_read[i],
+ d->nitems_read(i));
+
+ std::vector<pmt::pmt_t>::iterator t;
+ for(t = rtags.begin(); t != rtags.end(); t++) {
+ uint64_t newcount = pmt::pmt_to_uint64(pmt::pmt_tuple_ref(*t, 0));
+ pmt::pmt_t newtup = pmt::mp(pmt::pmt_from_uint64(newcount * rrate),
+ pmt::pmt_tuple_ref(*t, 1),
+ pmt::pmt_tuple_ref(*t, 2),
+ pmt::pmt_tuple_ref(*t, 3));
+ d->output(i)->add_item_tag(newtup);
+ }
+ }
+ }
+ else {
+ std::cerr << "Error: gr_block_executor: propagation_policy 'ONE-TO-ONE' requires ninputs == noutputs" << std::endl;
+ return false;
+ }
+
+ break;
+ default:
+ return true;
+ }
+ return true;
+}
gr_block_executor::gr_block_executor (gr_block_sptr block)
: d_block(block), d_log(0)
@@ -134,6 +207,7 @@ gr_block_executor::run_one_iteration()
d_input_items.resize (0);
d_input_done.resize(0);
d_output_items.resize (d->noutputs ());
+ d_start_nitems_read.resize(0);
// determine the minimum available output space
noutput_items = min_available_space (d, m->output_multiple ());
@@ -155,6 +229,7 @@ gr_block_executor::run_one_iteration()
d_input_items.resize (d->ninputs ());
d_input_done.resize(d->ninputs());
d_output_items.resize (0);
+ d_start_nitems_read.resize(d->ninputs());
LOG(*d_log << " sink\n");
max_items_avail = 0;
@@ -198,6 +273,7 @@ gr_block_executor::run_one_iteration()
d_input_items.resize (d->ninputs ());
d_input_done.resize(d->ninputs());
d_output_items.resize (d->noutputs ());
+ d_start_nitems_read.resize(d->ninputs());
max_items_avail = 0;
for (int i = 0; i < d->ninputs (); i++){
@@ -294,12 +370,21 @@ gr_block_executor::run_one_iteration()
for (int i = 0; i < d->noutputs (); i++)
d_output_items[i] = d->output(i)->write_pointer();
+ // determine where to start looking for new tags
+ for (int i = 0; i < d->ninputs(); i++)
+ d_start_nitems_read[i] = d->nitems_read(i);
+
// Do the actual work of the block
int n = m->general_work (noutput_items, d_ninput_items,
d_input_items, d_output_items);
LOG(*d_log << " general_work: noutput_items = " << noutput_items
<< " result = " << n << std::endl);
+ if(!propagate_tags(m->tag_propagation_policy(), d,
+ d_start_nitems_read, m->relative_rate(),
+ d_returned_tags))
+ goto were_done;
+
if (n == gr_block::WORK_DONE)
goto were_done;
diff --git a/gnuradio-core/src/lib/runtime/gr_block_executor.h b/gnuradio-core/src/lib/runtime/gr_block_executor.h
index 41b5ede7c..77ace5522 100644
--- a/gnuradio-core/src/lib/runtime/gr_block_executor.h
+++ b/gnuradio-core/src/lib/runtime/gr_block_executor.h
@@ -25,6 +25,7 @@
#include <gr_runtime_types.h>
#include <fstream>
+#include <gruel/pmt.h>
//class gr_block_executor;
//typedef boost::shared_ptr<gr_block_executor> gr_block_executor_sptr;
@@ -47,6 +48,8 @@ protected:
gr_vector_const_void_star d_input_items;
std::vector<bool> d_input_done;
gr_vector_void_star d_output_items;
+ std::vector<uint64_t> d_start_nitems_read; //stores where tag counts are before work
+ std::vector<pmt::pmt_t> d_returned_tags;
public:
gr_block_executor(gr_block_sptr block);
diff --git a/gnuradio-core/src/lib/runtime/gr_buffer.cc b/gnuradio-core/src/lib/runtime/gr_buffer.cc
index db2db5d6d..0b2eb52a0 100644
--- a/gnuradio-core/src/lib/runtime/gr_buffer.cc
+++ b/gnuradio-core/src/lib/runtime/gr_buffer.cc
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2004,2009 Free Software Foundation, Inc.
+ * Copyright 2004,2009,2010 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -80,7 +80,7 @@ minimum_buffer_items (long type_size, long page_size)
gr_buffer::gr_buffer (int nitems, size_t sizeof_item, gr_block_sptr link)
: d_base (0), d_bufsize (0), d_vmcircbuf (0),
d_sizeof_item (sizeof_item), d_link(link),
- d_write_index (0), d_done (false)
+ d_write_index (0), d_abs_write_offset(0), d_done (false)
{
if (!allocate_buffer (nitems, sizeof_item))
throw std::bad_alloc ();
@@ -156,8 +156,13 @@ gr_buffer::space_available ()
// Find out the maximum amount of data available to our readers
int most_data = d_readers[0]->items_available ();
- for (unsigned int i = 1; i < d_readers.size (); i++)
+ uint64_t min_items_read = d_readers[0]->nitems_read();
+ for (size_t i = 1; i < d_readers.size (); i++) {
most_data = std::max (most_data, d_readers[i]->items_available ());
+ min_items_read = std::min(min_items_read, d_readers[i]->nitems_read());
+ }
+
+ prune_tags(min_items_read);
// The -1 ensures that the case d_write_index == d_read_index is
// unambiguous. It indicates that there is no data for the reader
@@ -177,6 +182,7 @@ gr_buffer::update_write_pointer (int nitems)
{
gruel::scoped_lock guard(*mutex());
d_write_index = index_add (d_write_index, nitems);
+ d_abs_write_offset += nitems;
}
void
@@ -215,6 +221,40 @@ gr_buffer::drop_reader (gr_buffer_reader *reader)
d_readers.erase (result);
}
+void
+gr_buffer::add_item_tag(const pmt::pmt_t &tag)
+{
+ gruel::scoped_lock guard(*mutex());
+ d_item_tags.push_back(tag);
+}
+
+void
+gr_buffer::prune_tags(uint64_t max_time)
+{
+ /* NOTE: this function _should_ lock the mutex before editing
+ d_item_tags. In practice, this function is only called at
+ runtime by min_available_space in gr_block_executor.cc,
+ which locks the mutex itself.
+
+ If this function is used elsewhere, remember to lock the
+ buffer's mutex al la the scoped_lock line below.
+ */
+ //gruel::scoped_lock guard(*mutex());
+
+ int n = 0;
+ uint64_t item_time;
+ std::deque<pmt::pmt_t>::iterator itr = d_item_tags.begin();
+
+ while(itr != d_item_tags.end()) {
+ item_time = pmt::pmt_to_uint64(pmt::pmt_tuple_ref(*itr, 0));
+ if(item_time < max_time) {
+ d_item_tags.pop_front();
+ n++;
+ }
+ itr++;
+ }
+}
+
long
gr_buffer_ncurrently_allocated ()
{
@@ -225,7 +265,7 @@ gr_buffer_ncurrently_allocated ()
gr_buffer_reader::gr_buffer_reader(gr_buffer_sptr buffer, unsigned int read_index,
gr_block_sptr link)
- : d_buffer(buffer), d_read_index(read_index), d_link(link)
+ : d_buffer(buffer), d_read_index(read_index), d_abs_read_offset(0), d_link(link)
{
s_buffer_reader_count++;
}
@@ -253,6 +293,29 @@ gr_buffer_reader::update_read_pointer (int nitems)
{
gruel::scoped_lock guard(*mutex());
d_read_index = d_buffer->index_add (d_read_index, nitems);
+ d_abs_read_offset += nitems;
+}
+
+void
+gr_buffer_reader::get_tags_in_range(std::vector<pmt::pmt_t> &v,
+ uint64_t abs_start,
+ uint64_t abs_end)
+{
+ gruel::scoped_lock guard(*mutex());
+
+ v.resize(0);
+ std::deque<pmt::pmt_t>::iterator itr = d_buffer->get_tags_begin();
+
+ uint64_t item_time;
+ while(itr != d_buffer->get_tags_end()) {
+ item_time = pmt::pmt_to_uint64(pmt::pmt_tuple_ref(*itr, 0));
+
+ if((item_time >= abs_start) && (item_time <= abs_end)) {
+ v.push_back(*itr);
+ }
+
+ itr++;
+ }
}
long
diff --git a/gnuradio-core/src/lib/runtime/gr_buffer.h b/gnuradio-core/src/lib/runtime/gr_buffer.h
index 207bfe7c5..fe0e7585d 100644
--- a/gnuradio-core/src/lib/runtime/gr_buffer.h
+++ b/gnuradio-core/src/lib/runtime/gr_buffer.h
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2004,2009 Free Software Foundation, Inc.
+ * Copyright 2004,2009,2010 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -26,6 +26,7 @@
#include <gr_runtime_types.h>
#include <boost/weak_ptr.hpp>
#include <gruel/thread.h>
+#include <gruel/pmt.h>
class gr_vmcircbuf;
@@ -88,6 +89,26 @@ class gr_buffer {
gruel::mutex *mutex() { return &d_mutex; }
+ uint64_t nitems_written() { return d_abs_write_offset; }
+
+
+ /*!
+ * \brief Adds a new tag to the buffer.
+ *
+ * \param tag a PMT tuple containing the new tag
+ */
+ void add_item_tag(const pmt::pmt_t &tag);
+
+ /*!
+ * \brief Removes all tags before \p max_time from buffer
+ *
+ * \param max_time the time (item number) to trim up until.
+ */
+ void prune_tags(uint64_t max_time);
+
+ std::deque<pmt::pmt_t>::iterator get_tags_begin() { return d_item_tags.begin(); }
+ std::deque<pmt::pmt_t>::iterator get_tags_end() { return d_item_tags.end(); }
+
// -------------------------------------------------------------------------
private:
@@ -106,11 +127,15 @@ class gr_buffer {
boost::weak_ptr<gr_block> d_link; // block that writes to this buffer
//
- // The mutex protects d_write_index, d_done and the d_read_index's in the buffer readers.
+ // The mutex protects d_write_index, d_abs_write_offset, d_done, d_item_tags
+ // and the d_read_index's and d_abs_read_offset's in the buffer readers.
//
gruel::mutex d_mutex;
unsigned int d_write_index; // in items [0,d_bufsize)
+ uint64_t d_abs_write_offset; // num items written since the start
bool d_done;
+ std::deque<pmt::pmt_t> d_item_tags;
+
unsigned
index_add (unsigned a, unsigned b)
@@ -220,11 +245,31 @@ class gr_buffer_reader {
gruel::mutex *mutex() { return d_buffer->mutex(); }
+ uint64_t nitems_read() { return d_abs_read_offset; }
+
/*!
* \brief Return the block that reads via this reader.
+ *
*/
gr_block_sptr link() { return gr_block_sptr(d_link); }
+
+ /*!
+ * \brief Given a [start,end), returns a vector all tags in the range.
+ *
+ * Get a vector of tags in given range. Range of counts is from start to end-1.
+ *
+ * Tags are tuples of:
+ * (item count, source id, key, value)
+ *
+ * \param v a vector reference to return tags into
+ * \param abs_start a uint64 count of the start of the range of interest
+ * \param abs_end a uint64 count of the end of the range of interest
+ */
+ void get_tags_in_range(std::vector<pmt::pmt_t> &v,
+ uint64_t abs_start,
+ uint64_t abs_end);
+
// -------------------------------------------------------------------------
private:
@@ -236,6 +281,7 @@ class gr_buffer_reader {
gr_buffer_sptr d_buffer;
unsigned int d_read_index; // in items [0,d->buffer.d_bufsize)
+ uint64_t d_abs_read_offset; // num items seen since the start
boost::weak_ptr<gr_block> d_link; // block that reads via this buffer reader
//! constructor is private. Use gr_buffer::add_reader to create instances
diff --git a/gnuradio-core/src/lib/runtime/gr_flat_flowgraph.cc b/gnuradio-core/src/lib/runtime/gr_flat_flowgraph.cc
index 031eb6dfd..5d1057e0f 100644
--- a/gnuradio-core/src/lib/runtime/gr_flat_flowgraph.cc
+++ b/gnuradio-core/src/lib/runtime/gr_flat_flowgraph.cc
@@ -264,16 +264,13 @@ void gr_flat_flowgraph::dump()
int no = detail->noutputs();
for (int i = 0; i < no; i++) {
gr_buffer_sptr buffer = detail->output(i);
- std::cout << " output " << i << ": " << buffer
- << " space=" << buffer->space_available() << std::endl;
+ std::cout << " output " << i << ": " << buffer << std::endl;
}
for (int i = 0; i < ni; i++) {
gr_buffer_reader_sptr reader = detail->input(i);
std::cout << " reader " << i << ": " << reader
- << " reading from buffer=" << reader->buffer()
- << " avail=" << reader->items_available() << " items"
- << std::endl;
+ << " reading from buffer=" << reader->buffer() << std::endl;
}
}
diff --git a/gnuradio-core/src/lib/runtime/gr_preferences.cc b/gnuradio-core/src/lib/runtime/gr_preferences.cc
index e0be2db62..5f7412248 100644
--- a/gnuradio-core/src/lib/runtime/gr_preferences.cc
+++ b/gnuradio-core/src/lib/runtime/gr_preferences.cc
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2003 Free Software Foundation, Inc.
+ * Copyright 2003,2010 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -77,11 +77,20 @@ gr_preferences::get (const char *key)
static char buf[1024];
FILE *fp = fopen (pathname (key), "r");
- if (fp == 0)
+ if (fp == 0) {
+ perror (pathname (key));
return 0;
+ }
memset (buf, 0, sizeof (buf));
- fread (buf, 1, sizeof (buf) - 1, fp);
+ size_t ret = fread (buf, 1, sizeof (buf) - 1, fp);
+ if(ret == 0) {
+ if(ferror(fp) != 0) {
+ perror (pathname (key));
+ fclose (fp);
+ return 0;
+ }
+ }
fclose (fp);
return buf;
}
@@ -97,6 +106,13 @@ gr_preferences::set (const char *key, const char *value)
return;
}
- fwrite (value, 1, strlen (value), fp);
+ size_t ret = fwrite (value, 1, strlen (value), fp);
+ if(ret == 0) {
+ if(ferror(fp) != 0) {
+ perror (pathname (key));
+ fclose (fp);
+ return;
+ }
+ }
fclose (fp);
};
diff --git a/gnuradio-core/src/lib/runtime/gr_tag_info.cc b/gnuradio-core/src/lib/runtime/gr_tag_info.cc
new file mode 100644
index 000000000..f15329f9b
--- /dev/null
+++ b/gnuradio-core/src/lib/runtime/gr_tag_info.cc
@@ -0,0 +1,38 @@
+/* -*- 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 <gr_tag_info.h>
+#include <gruel/pmt.h>
+
+namespace gr_tags {
+/*
+ const pmt::pmt_t key_time = pmt::pmt_string_to_symbol("time");
+ const pmt::pmt_t key_sample_rate = pmt::pmt_string_to_symbol("sample_rate");
+ const pmt::pmt_t key_frequency = pmt::pmt_string_to_symbol("frequency");
+ const pmt::pmt_t key_rssi = pmt::pmt_string_to_symbol("rssi");
+ const pmt::pmt_t key_rx_gain = pmt::pmt_string_to_symbol("gain");
+*/
+}
diff --git a/gnuradio-core/src/lib/runtime/gr_tag_info.h b/gnuradio-core/src/lib/runtime/gr_tag_info.h
new file mode 100644
index 000000000..5a1e1555a
--- /dev/null
+++ b/gnuradio-core/src/lib/runtime/gr_tag_info.h
@@ -0,0 +1,87 @@
+/* -*- 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_GR_TAG_INFO_H
+#define INCLUDED_GR_TAG_INFO_H
+
+#include <gruel/pmt.h>
+
+namespace gr_tags {
+
+ enum {
+ TAG_NITEM_REF = 0,
+ TAG_SRCID_REF,
+ TAG_KEY_REF,
+ TAG_VALUE_REF
+ };
+
+ /*
+ extern const pmt::pmt_t key_time;
+ extern const pmt::pmt_t key_sample_rate;
+ extern const pmt::pmt_t key_frequency;
+ extern const pmt::pmt_t key_rssi;
+ extern const pmt::pmt_t key_gain;
+ */
+
+ /*!
+ * \brief Returns the item \p tag occurred at (as a uint64_t)
+ */
+ static inline uint64_t
+ get_nitems(const pmt::pmt_t &tag) {
+ return pmt::pmt_to_uint64(pmt::pmt_tuple_ref(tag, TAG_NITEM_REF));
+ }
+
+ /*!
+ * \brief Returns the source ID of \p tag (as a PMT)
+ */
+ static inline pmt::pmt_t
+ get_srcid(const pmt::pmt_t &tag) {
+ return pmt::pmt_tuple_ref(tag, TAG_SRCID_REF);
+ }
+
+ /*!
+ * \brief Returns the key of \p tag (as a PMT symbol)
+ */
+ static inline pmt::pmt_t
+ get_key(const pmt::pmt_t &tag) {
+ return pmt::pmt_tuple_ref(tag, TAG_KEY_REF);
+ }
+
+ /*!
+ * \brief Returns the value of \p tag (as a PMT)
+ */
+ static inline pmt::pmt_t
+ get_value(const pmt::pmt_t &tag) {
+ return pmt::pmt_tuple_ref(tag, TAG_VALUE_REF);
+ }
+
+ /*!
+ * \brief Comparison function to test which tag, \p x or \p y, came first in time
+ */
+ static inline bool
+ nitems_compare(pmt::pmt_t x, pmt::pmt_t y) {
+ return get_nitems(x) < get_nitems(y);
+ }
+
+}; /* namespace tags */
+
+#endif /* GR_TAG_INFO */
diff --git a/gnuradio-core/src/lib/runtime/qa_block_tags.cc b/gnuradio-core/src/lib/runtime/qa_block_tags.cc
new file mode 100644
index 000000000..07ce5c276
--- /dev/null
+++ b/gnuradio-core/src/lib/runtime/qa_block_tags.cc
@@ -0,0 +1,450 @@
+/* -*- 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 <qa_block_tags.h>
+#include <gr_block.h>
+#include <gr_top_block.h>
+#include <gr_null_source.h>
+#include <gr_null_sink.h>
+#include <gr_head.h>
+#include <gr_annotator_alltoall.h>
+#include <gr_annotator_1to1.h>
+#include <gr_keep_one_in_n.h>
+#include <gr_firdes.h>
+#include <gruel/pmt.h>
+
+
+// ----------------------------------------------------------------
+
+using namespace pmt;
+
+// set to 1 to turn on debug output
+// The debug output fully checks that the tags seen are what are expected. While
+// this behavior currently works with our implementation, there is no guarentee
+// that the tags will be coming in this specific order, so it's dangerous to
+// rely on this as a test of the tag system working. We would really want to
+// tags we know we should see and then test that they all occur once, but in no
+// particular order.
+#define QA_TAGS_DEBUG 0
+
+void
+qa_block_tags::t0 ()
+{
+ unsigned int N = 1000;
+ gr_top_block_sptr tb = gr_make_top_block("top");
+ gr_block_sptr src (gr_make_null_source(sizeof(int)));
+ gr_block_sptr head (gr_make_head(sizeof(int), N));
+ gr_block_sptr snk (gr_make_null_sink(sizeof(int)));
+
+ tb->connect(src, 0, head, 0);
+ tb->connect(head, 0, snk, 0);
+
+ //CPPUNIT_ASSERT_THROW(src->nitems_read(0), std::runtime_error);
+ //CPPUNIT_ASSERT_THROW(src->nitems_written(0), std::runtime_error);
+ CPPUNIT_ASSERT_EQUAL(src->nitems_read(0), (uint64_t)0);
+ CPPUNIT_ASSERT_EQUAL(src->nitems_written(0), (uint64_t)0);
+
+ tb->run();
+
+ CPPUNIT_ASSERT_THROW(src->nitems_read(0), std::invalid_argument);
+ CPPUNIT_ASSERT(src->nitems_written(0) >= N);
+ CPPUNIT_ASSERT_EQUAL(snk->nitems_read(0), (uint64_t)1000);
+ CPPUNIT_ASSERT_THROW(snk->nitems_written(0), std::invalid_argument);
+}
+
+
+void
+qa_block_tags::t1 ()
+{
+ int N = 40000;
+ gr_top_block_sptr tb = gr_make_top_block("top");
+ gr_block_sptr src (gr_make_null_source(sizeof(int)));
+ gr_block_sptr head (gr_make_head(sizeof(int), N));
+ gr_annotator_alltoall_sptr ann0 (gr_make_annotator_alltoall(10000, sizeof(int)));
+ gr_annotator_alltoall_sptr ann1 (gr_make_annotator_alltoall(10000, sizeof(int)));
+ gr_annotator_alltoall_sptr ann2 (gr_make_annotator_alltoall(10000, sizeof(int)));
+ gr_annotator_alltoall_sptr ann3 (gr_make_annotator_alltoall(10000, sizeof(int)));
+ gr_annotator_alltoall_sptr ann4 (gr_make_annotator_alltoall(10000, sizeof(int)));
+ gr_block_sptr snk0 (gr_make_null_sink(sizeof(int)));
+ gr_block_sptr snk1 (gr_make_null_sink(sizeof(int)));
+
+ tb->connect(src, 0, head, 0);
+ tb->connect(head, 0, ann0, 0);
+
+ tb->connect(ann0, 0, ann1, 0);
+ tb->connect(ann0, 1, ann2, 0);
+ tb->connect(ann1, 0, ann3, 0);
+ tb->connect(ann2, 0, ann4, 0);
+
+ tb->connect(ann3, 0, snk0, 0);
+ tb->connect(ann4, 0, snk1, 0);
+
+ tb->run();
+
+ std::vector<pmt::pmt_t> tags0 = ann0->data();
+ std::vector<pmt::pmt_t> tags3 = ann3->data();
+ std::vector<pmt::pmt_t> tags4 = ann4->data();
+
+ // The first annotator does not receive any tags from the null sink upstream
+ CPPUNIT_ASSERT_EQUAL(tags0.size(), (size_t)0);
+ CPPUNIT_ASSERT_EQUAL(tags3.size(), (size_t)8);
+ CPPUNIT_ASSERT_EQUAL(tags4.size(), (size_t)8);
+
+#if QA_TAGS_DEBUG
+ // Kludge together the tags that we know should result from the above graph
+ std::stringstream str0, str1, str2;
+ str0 << ann0->name() << ann0->unique_id();
+ str1 << ann1->name() << ann1->unique_id();
+ str2 << ann2->name() << ann2->unique_id();
+
+ pmt_t expected_tags3[8];
+ expected_tags3[0] = mp(pmt_from_uint64(0), mp(str1.str()), mp("seq"), mp(0));
+ expected_tags3[1] = mp(pmt_from_uint64(0), mp(str0.str()), mp("seq"), mp(0));
+ expected_tags3[2] = mp(pmt_from_uint64(10000), mp(str1.str()), mp("seq"), mp(1));
+ expected_tags3[3] = mp(pmt_from_uint64(10000), mp(str0.str()), mp("seq"), mp(2));
+ expected_tags3[4] = mp(pmt_from_uint64(20000), mp(str1.str()), mp("seq"), mp(2));
+ expected_tags3[5] = mp(pmt_from_uint64(20000), mp(str0.str()), mp("seq"), mp(4));
+ expected_tags3[6] = mp(pmt_from_uint64(30000), mp(str1.str()), mp("seq"), mp(3));
+ expected_tags3[7] = mp(pmt_from_uint64(30000), mp(str0.str()), mp("seq"), mp(6));
+
+ pmt_t expected_tags4[8];
+ expected_tags4[0] = mp(pmt_from_uint64(0), mp(str2.str()), mp("seq"), mp(0));
+ expected_tags4[1] = mp(pmt_from_uint64(0), mp(str0.str()), mp("seq"), mp(1));
+ expected_tags4[2] = mp(pmt_from_uint64(10000), mp(str2.str()), mp("seq"), mp(1));
+ expected_tags4[3] = mp(pmt_from_uint64(10000), mp(str0.str()), mp("seq"), mp(3));
+ expected_tags4[4] = mp(pmt_from_uint64(20000), mp(str2.str()), mp("seq"), mp(2));
+ expected_tags4[5] = mp(pmt_from_uint64(20000), mp(str0.str()), mp("seq"), mp(5));
+ expected_tags4[6] = mp(pmt_from_uint64(30000), mp(str2.str()), mp("seq"), mp(3));
+ expected_tags4[7] = mp(pmt_from_uint64(30000), mp(str0.str()), mp("seq"), mp(7));
+
+ std::cout << std::endl << "qa_block_tags::t1" << std::endl;
+
+ // For annotator 3, we know it gets tags from ann0 and ann1, test this
+ for(size_t i = 0; i < tags3.size(); i++) {
+ std::cout << "tags3[" << i << "] = " << tags3[i] << "\t\t" << expected_tags3[i] << std::endl;
+ CPPUNIT_ASSERT_EQUAL(pmt_write_string(tags3[i]), pmt_write_string(expected_tags3[i]));
+ }
+
+ // For annotator 4, we know it gets tags from ann0 and ann2, test this
+ std::cout << std::endl;
+ for(size_t i = 0; i < tags4.size(); i++) {
+ std::cout << "tags4[" << i << "] = " << tags4[i] << "\t\t" << expected_tags4[i] << std::endl;
+ CPPUNIT_ASSERT_EQUAL(pmt_write_string(tags4[i]), pmt_write_string(expected_tags4[i]));
+ }
+#endif
+}
+
+void
+qa_block_tags::t2 ()
+{
+ int N = 40000;
+ gr_top_block_sptr tb = gr_make_top_block("top");
+ gr_block_sptr src (gr_make_null_source(sizeof(int)));
+ gr_block_sptr head (gr_make_head(sizeof(int), N));
+ gr_annotator_alltoall_sptr ann0 (gr_make_annotator_alltoall(10000, sizeof(int)));
+ gr_annotator_alltoall_sptr ann1 (gr_make_annotator_alltoall(10000, sizeof(int)));
+ gr_annotator_alltoall_sptr ann2 (gr_make_annotator_alltoall(10000, sizeof(int)));
+ gr_annotator_alltoall_sptr ann3 (gr_make_annotator_alltoall(10000, sizeof(int)));
+ gr_annotator_alltoall_sptr ann4 (gr_make_annotator_alltoall(10000, sizeof(int)));
+ gr_block_sptr snk0 (gr_make_null_sink(sizeof(int)));
+ gr_block_sptr snk1 (gr_make_null_sink(sizeof(int)));
+ gr_block_sptr snk2 (gr_make_null_sink(sizeof(int)));
+
+ tb->connect(src, 0, head, 0);
+ tb->connect(head, 0, ann0, 0);
+
+ tb->connect(ann0, 0, ann1, 0);
+ tb->connect(ann0, 1, ann1, 1);
+ tb->connect(ann1, 0, ann2, 0);
+ tb->connect(ann1, 1, ann3, 0);
+ tb->connect(ann1, 2, ann4, 0);
+
+ tb->connect(ann2, 0, snk0, 0);
+ tb->connect(ann3, 0, snk1, 0);
+ tb->connect(ann4, 0, snk2, 0);
+
+ tb->run();
+
+ std::vector<pmt::pmt_t> tags0 = ann0->data();
+ std::vector<pmt::pmt_t> tags1 = ann1->data();
+ std::vector<pmt::pmt_t> tags2 = ann2->data();
+ std::vector<pmt::pmt_t> tags3 = ann4->data();
+ std::vector<pmt::pmt_t> tags4 = ann4->data();
+
+ // The first annotator does not receive any tags from the null sink upstream
+ CPPUNIT_ASSERT_EQUAL(tags0.size(), (size_t)0);
+ CPPUNIT_ASSERT_EQUAL(tags1.size(), (size_t)8);
+
+ // Make sure the rest all have 12 tags
+ CPPUNIT_ASSERT_EQUAL(tags2.size(), (size_t)12);
+ CPPUNIT_ASSERT_EQUAL(tags3.size(), (size_t)12);
+ CPPUNIT_ASSERT_EQUAL(tags4.size(), (size_t)12);
+
+
+#if QA_TAGS_DEBUG
+ // Kludge together the tags that we know should result from the above graph
+ std::stringstream str0, str1;
+ str0 << ann0->name() << ann0->unique_id();
+ str1 << ann1->name() << ann1->unique_id();
+
+ pmt_t expected_tags2[12];
+ expected_tags2[0] = mp(pmt_from_uint64(0), mp(str1.str()), mp("seq"), mp(0));
+ expected_tags2[1] = mp(pmt_from_uint64(0), mp(str0.str()), mp("seq"), mp(0));
+ expected_tags2[2] = mp(pmt_from_uint64(0), mp(str0.str()), mp("seq"), mp(1));
+ expected_tags2[3] = mp(pmt_from_uint64(10000), mp(str1.str()), mp("seq"), mp(3));
+ expected_tags2[4] = mp(pmt_from_uint64(10000), mp(str0.str()), mp("seq"), mp(2));
+ expected_tags2[5] = mp(pmt_from_uint64(10000), mp(str0.str()), mp("seq"), mp(3));
+ expected_tags2[6] = mp(pmt_from_uint64(20000), mp(str1.str()), mp("seq"), mp(6));
+ expected_tags2[7] = mp(pmt_from_uint64(20000), mp(str0.str()), mp("seq"), mp(4));
+ expected_tags2[8] = mp(pmt_from_uint64(20000), mp(str0.str()), mp("seq"), mp(5));
+ expected_tags2[9] = mp(pmt_from_uint64(30000), mp(str1.str()), mp("seq"), mp(9));
+ expected_tags2[10] = mp(pmt_from_uint64(30000), mp(str0.str()), mp("seq"), mp(6));
+ expected_tags2[11] = mp(pmt_from_uint64(30000), mp(str0.str()), mp("seq"), mp(7));
+
+ pmt_t expected_tags4[12];
+ expected_tags4[0] = mp(pmt_from_uint64(0), mp(str1.str()), mp("seq"), mp(2));
+ expected_tags4[1] = mp(pmt_from_uint64(0), mp(str0.str()), mp("seq"), mp(0));
+ expected_tags4[2] = mp(pmt_from_uint64(0), mp(str0.str()), mp("seq"), mp(1));
+ expected_tags4[3] = mp(pmt_from_uint64(10000), mp(str1.str()), mp("seq"), mp(5));
+ expected_tags4[4] = mp(pmt_from_uint64(10000), mp(str0.str()), mp("seq"), mp(2));
+ expected_tags4[5] = mp(pmt_from_uint64(10000), mp(str0.str()), mp("seq"), mp(3));
+ expected_tags4[6] = mp(pmt_from_uint64(20000), mp(str1.str()), mp("seq"), mp(8));
+ expected_tags4[7] = mp(pmt_from_uint64(20000), mp(str0.str()), mp("seq"), mp(4));
+ expected_tags4[8] = mp(pmt_from_uint64(20000), mp(str0.str()), mp("seq"), mp(5));
+ expected_tags4[9] = mp(pmt_from_uint64(30000), mp(str1.str()), mp("seq"), mp(11));
+ expected_tags4[10] = mp(pmt_from_uint64(30000), mp(str0.str()), mp("seq"), mp(6));
+ expected_tags4[11] = mp(pmt_from_uint64(30000), mp(str0.str()), mp("seq"), mp(7));
+
+ std::cout << std::endl << "qa_block_tags::t2" << std::endl;
+
+ // For annotator[2-4], we know it gets tags from ann0 and ann1
+ // but the tags from the different outputs of ann1 are different for each.
+ // Just testing ann2 and ann4; if they are correct it would be
+ // inconceivable for ann3 to have it wrong.
+ for(size_t i = 0; i < tags2.size(); i++) {
+ std::cout << "tags2[" << i << "] = " << tags2[i] << "\t\t" << expected_tags2[i] << std::endl;
+ CPPUNIT_ASSERT_EQUAL(pmt_write_string(tags2[i]), pmt_write_string(expected_tags2[i]));
+ }
+
+ std::cout << std::endl;
+ for(size_t i = 0; i < tags4.size(); i++) {
+ std::cout << "tags2[" << i << "] = " << tags4[i] << "\t\t" << expected_tags4[i] << std::endl;
+ CPPUNIT_ASSERT_EQUAL(pmt_write_string(tags4[i]), pmt_write_string(expected_tags4[i]));
+ }
+#endif
+}
+
+
+void
+qa_block_tags::t3 ()
+{
+ int N = 40000;
+ gr_top_block_sptr tb = gr_make_top_block("top");
+ gr_block_sptr src (gr_make_null_source(sizeof(int)));
+ gr_block_sptr head (gr_make_head(sizeof(int), N));
+ gr_annotator_1to1_sptr ann0 (gr_make_annotator_1to1(10000, sizeof(int)));
+ gr_annotator_alltoall_sptr ann1 (gr_make_annotator_alltoall(10000, sizeof(int)));
+ gr_annotator_alltoall_sptr ann2 (gr_make_annotator_alltoall(10000, sizeof(int)));
+ gr_annotator_1to1_sptr ann3 (gr_make_annotator_1to1(10000, sizeof(int)));
+ gr_annotator_1to1_sptr ann4 (gr_make_annotator_1to1(10000, sizeof(int)));
+ gr_block_sptr snk0 (gr_make_null_sink(sizeof(int)));
+ gr_block_sptr snk1 (gr_make_null_sink(sizeof(int)));
+
+ tb->connect(src, 0, head, 0);
+ tb->connect(head, 0, ann0, 0);
+ tb->connect(head, 0, ann0, 1);
+
+ tb->connect(ann0, 0, ann1, 0);
+ tb->connect(ann0, 1, ann2, 0);
+ tb->connect(ann1, 0, ann3, 0);
+ tb->connect(ann2, 0, ann4, 0);
+
+ tb->connect(ann3, 0, snk0, 0);
+ tb->connect(ann4, 0, snk1, 0);
+
+ tb->run();
+
+
+ std::vector<pmt::pmt_t> tags0 = ann0->data();
+ std::vector<pmt::pmt_t> tags3 = ann3->data();
+ std::vector<pmt::pmt_t> tags4 = ann4->data();
+
+ // The first annotator does not receive any tags from the null sink upstream
+ CPPUNIT_ASSERT_EQUAL(tags0.size(), (size_t)0);
+ CPPUNIT_ASSERT_EQUAL(tags3.size(), (size_t)8);
+ CPPUNIT_ASSERT_EQUAL(tags4.size(), (size_t)8);
+
+#if QA_TAGS_DEBUG
+ // Kludge together the tags that we know should result from the above graph
+ std::stringstream str0, str1, str2;
+ str0 << ann0->name() << ann0->unique_id();
+ str1 << ann1->name() << ann1->unique_id();
+ str2 << ann2->name() << ann2->unique_id();
+
+ pmt_t expected_tags3[8];
+ expected_tags3[0] = mp(pmt_from_uint64(0), mp(str1.str()), mp("seq"), mp(0));
+ expected_tags3[1] = mp(pmt_from_uint64(0), mp(str0.str()), mp("seq"), mp(0));
+ expected_tags3[2] = mp(pmt_from_uint64(10000), mp(str1.str()), mp("seq"), mp(1));
+ expected_tags3[3] = mp(pmt_from_uint64(10000), mp(str0.str()), mp("seq"), mp(2));
+ expected_tags3[4] = mp(pmt_from_uint64(20000), mp(str1.str()), mp("seq"), mp(2));
+ expected_tags3[5] = mp(pmt_from_uint64(20000), mp(str0.str()), mp("seq"), mp(4));
+ expected_tags3[6] = mp(pmt_from_uint64(30000), mp(str1.str()), mp("seq"), mp(3));
+ expected_tags3[7] = mp(pmt_from_uint64(30000), mp(str0.str()), mp("seq"), mp(6));
+
+ pmt_t expected_tags4[8];
+ expected_tags4[0] = mp(pmt_from_uint64(0), mp(str2.str()), mp("seq"), mp(0));
+ expected_tags4[1] = mp(pmt_from_uint64(0), mp(str0.str()), mp("seq"), mp(1));
+ expected_tags4[2] = mp(pmt_from_uint64(10000), mp(str2.str()), mp("seq"), mp(1));
+ expected_tags4[3] = mp(pmt_from_uint64(10000), mp(str0.str()), mp("seq"), mp(3));
+ expected_tags4[4] = mp(pmt_from_uint64(20000), mp(str2.str()), mp("seq"), mp(2));
+ expected_tags4[5] = mp(pmt_from_uint64(20000), mp(str0.str()), mp("seq"), mp(5));
+ expected_tags4[6] = mp(pmt_from_uint64(30000), mp(str2.str()), mp("seq"), mp(3));
+ expected_tags4[7] = mp(pmt_from_uint64(30000), mp(str0.str()), mp("seq"), mp(7));
+
+ std::cout << std::endl << "qa_block_tags::t3" << std::endl;
+
+ // For annotator 3, we know it gets tags from ann0 and ann1, test this
+ for(size_t i = 0; i < tags3.size(); i++) {
+ std::cout << "tags3[" << i << "] = " << tags3[i] << "\t\t" << expected_tags3[i] << std::endl;
+ CPPUNIT_ASSERT_EQUAL(pmt_write_string(tags3[i]), pmt_write_string(expected_tags3[i]));
+ }
+
+ // For annotator 4, we know it gets tags from ann0 and ann2, test this
+ std::cout << std::endl;
+ for(size_t i = 0; i < tags4.size(); i++) {
+ std::cout << "tags4[" << i << "] = " << tags4[i] << "\t\t" << expected_tags4[i] << std::endl;
+ CPPUNIT_ASSERT_EQUAL(pmt_write_string(tags4[i]), pmt_write_string(expected_tags4[i]));
+ }
+#endif
+}
+
+
+void
+qa_block_tags::t4 ()
+{
+ int N = 40000;
+ gr_top_block_sptr tb = gr_make_top_block("top");
+ gr_block_sptr src (gr_make_null_source(sizeof(int)));
+ gr_block_sptr head (gr_make_head(sizeof(int), N));
+ gr_annotator_1to1_sptr ann0 (gr_make_annotator_1to1(10000, sizeof(int)));
+ gr_annotator_1to1_sptr ann1 (gr_make_annotator_1to1(10000, sizeof(int)));
+ gr_annotator_1to1_sptr ann2 (gr_make_annotator_1to1(10000, sizeof(int)));
+ gr_block_sptr snk0 (gr_make_null_sink(sizeof(int)));
+ gr_block_sptr snk1 (gr_make_null_sink(sizeof(int)));
+
+ // using 1-to-1 tag propagation without having equal number of
+ // ins and outs. Make sure this works; will just exit run early.
+ tb->connect(src, 0, head, 0);
+ tb->connect(head, 0, ann0, 0);
+ tb->connect(ann0, 0, ann1, 0);
+ tb->connect(ann0, 1, ann2, 0);
+ tb->connect(ann1, 0, snk0, 0);
+ tb->connect(ann2, 0, snk1, 0);
+
+ std::cerr << std::endl
+ << "NOTE: This is supposed to produce an error from gr_block_executor"
+ << std::endl;
+ tb->run();
+}
+
+
+void
+qa_block_tags::t5 ()
+{
+ int N = 40000;
+ gr_top_block_sptr tb = gr_make_top_block("top");
+ gr_block_sptr src (gr_make_null_source(sizeof(float)));
+ gr_block_sptr head (gr_make_head(sizeof(float), N));
+ gr_annotator_alltoall_sptr ann0 (gr_make_annotator_alltoall(10000, sizeof(float)));
+ gr_annotator_alltoall_sptr ann1 (gr_make_annotator_alltoall(10000, sizeof(float)));
+ gr_annotator_alltoall_sptr ann2 (gr_make_annotator_alltoall(1000, sizeof(float)));
+ gr_block_sptr snk0 (gr_make_null_sink(sizeof(float)));
+
+ // Rate change blocks
+ gr_keep_one_in_n_sptr dec10 (gr_make_keep_one_in_n(sizeof(float), 10));
+
+ tb->connect(src, 0, head, 0);
+ tb->connect(head, 0, ann0, 0);
+ tb->connect(ann0, 0, ann1, 0);
+ tb->connect(ann1, 0, dec10, 0);
+ tb->connect(dec10, 0, ann2, 0);
+ tb->connect(ann2, 0, snk0, 0);
+
+ tb->run();
+
+ std::vector<pmt::pmt_t> tags0 = ann0->data();
+ std::vector<pmt::pmt_t> tags1 = ann1->data();
+ std::vector<pmt::pmt_t> tags2 = ann2->data();
+
+ // The first annotator does not receive any tags from the null sink upstream
+ CPPUNIT_ASSERT_EQUAL(tags0.size(), (size_t)0);
+ CPPUNIT_ASSERT_EQUAL(tags1.size(), (size_t)4);
+ CPPUNIT_ASSERT_EQUAL(tags2.size(), (size_t)8);
+
+
+#if QA_TAGS_DEBUG
+ // Kludge together the tags that we know should result from the above graph
+ std::stringstream str0, str1, str2;
+ str0 << ann0->name() << ann0->unique_id();
+ str1 << ann1->name() << ann1->unique_id();
+ str2 << ann2->name() << ann2->unique_id();
+
+ pmt_t expected_tags1[5];
+ expected_tags1[0] = mp(pmt_from_uint64(0), mp(str0.str()), mp("seq"), mp(0));
+ expected_tags1[1] = mp(pmt_from_uint64(10000), mp(str0.str()), mp("seq"), mp(1));
+ expected_tags1[2] = mp(pmt_from_uint64(20000), mp(str0.str()), mp("seq"), mp(2));
+ expected_tags1[3] = mp(pmt_from_uint64(30000), mp(str0.str()), mp("seq"), mp(3));
+
+ pmt_t expected_tags2[10];
+ expected_tags2[0] = mp(pmt_from_uint64(0), mp(str1.str()), mp("seq"), mp(0));
+ expected_tags2[1] = mp(pmt_from_uint64(0), mp(str0.str()), mp("seq"), mp(0));
+ expected_tags2[2] = mp(pmt_from_uint64(1000), mp(str1.str()), mp("seq"), mp(1));
+ expected_tags2[3] = mp(pmt_from_uint64(1000), mp(str0.str()), mp("seq"), mp(1));
+ expected_tags2[4] = mp(pmt_from_uint64(2000), mp(str1.str()), mp("seq"), mp(2));
+ expected_tags2[5] = mp(pmt_from_uint64(2000), mp(str0.str()), mp("seq"), mp(2));
+ expected_tags2[6] = mp(pmt_from_uint64(3000), mp(str1.str()), mp("seq"), mp(3));
+ expected_tags2[7] = mp(pmt_from_uint64(3000), mp(str0.str()), mp("seq"), mp(3));
+ expected_tags2[8] = mp(pmt_from_uint64(4000), mp(str1.str()), mp("seq"), mp(4));
+ expected_tags2[9] = mp(pmt_from_uint64(4000), mp(str0.str()), mp("seq"), mp(4));
+
+ std::cout << std::endl << "qa_block_tags::t5" << std::endl;
+
+ // annotator 1 gets tags from annotator 0
+ std::cout << "tags1.size(): " << tags1.size() << std::endl;
+ for(size_t i = 0; i < tags1.size(); i++) {
+ std::cout << "tags1[" << i << "] = " << tags1[i] << "\t\t" << expected_tags1[i] << std::endl;
+ CPPUNIT_ASSERT_EQUAL(pmt_write_string(tags1[i]), pmt_write_string(expected_tags1[i]));
+ }
+
+ // annotator 2 gets tags from annotators 0 and 1
+ std::cout << std::endl;
+ std::cout << "tags2.size(): " << tags2.size() << std::endl;
+ for(size_t i = 0; i < tags2.size(); i++) {
+ std::cout << "tags2[" << i << "] = " << tags2[i] << "\t\t" << expected_tags2[i] << std::endl;
+ CPPUNIT_ASSERT_EQUAL(pmt_write_string(tags2[i]), pmt_write_string(expected_tags2[i]));
+ }
+#endif
+}
+
diff --git a/gnuradio-core/src/lib/runtime/qa_block_tags.h b/gnuradio-core/src/lib/runtime/qa_block_tags.h
new file mode 100644
index 000000000..b0d211390
--- /dev/null
+++ b/gnuradio-core/src/lib/runtime/qa_block_tags.h
@@ -0,0 +1,52 @@
+/* -*- 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_QA_BLOCK_TAGS_H
+#define INCLUDED_QA_BLOCK_TAGS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/TestCase.h>
+#include <stdexcept>
+
+class qa_block_tags : public CppUnit::TestCase {
+
+ CPPUNIT_TEST_SUITE (qa_block_tags);
+ CPPUNIT_TEST (t0);
+ CPPUNIT_TEST (t1);
+ CPPUNIT_TEST (t2);
+ CPPUNIT_TEST (t3);
+ CPPUNIT_TEST (t4);
+ CPPUNIT_TEST (t5);
+ CPPUNIT_TEST_SUITE_END ();
+
+ private:
+ void t0 ();
+ void t1 ();
+ void t2 ();
+ void t3 ();
+ void t4 ();
+ void t5 ();
+
+};
+
+
+#endif /* INCLUDED_QA_BLOCK_TAGS_H */
diff --git a/gnuradio-core/src/lib/runtime/qa_runtime.cc b/gnuradio-core/src/lib/runtime/qa_runtime.cc
index 31e3a82d6..967d4bfa8 100644
--- a/gnuradio-core/src/lib/runtime/qa_runtime.cc
+++ b/gnuradio-core/src/lib/runtime/qa_runtime.cc
@@ -38,6 +38,7 @@
#include <qa_gr_hier_block2.h>
#include <qa_gr_hier_block2_derived.h>
#include <qa_gr_buffer.h>
+#include <qa_block_tags.h>
CppUnit::TestSuite *
qa_runtime::suite ()
@@ -52,6 +53,7 @@ qa_runtime::suite ()
s->addTest (qa_gr_hier_block2::suite ());
s->addTest (qa_gr_hier_block2_derived::suite ());
s->addTest (qa_gr_buffer::suite ());
+ s->addTest (qa_block_tags::suite ());
return s;
}
diff --git a/gnuradio-core/src/lib/swig/gnuradio.i b/gnuradio-core/src/lib/swig/gnuradio.i
index 47fd4e330..1601cca12 100644
--- a/gnuradio-core/src/lib/swig/gnuradio.i
+++ b/gnuradio-core/src/lib/swig/gnuradio.i
@@ -60,6 +60,8 @@
typedef std::complex<float> gr_complex;
typedef std::complex<double> gr_complexd;
+typedef unsigned long long uint64_t;
+typedef long long int64_t;
// instantiate the required template specializations
diff --git a/gnuradio-core/src/python/gnuradio/blks2impl/pfb_arb_resampler.py b/gnuradio-core/src/python/gnuradio/blks2impl/pfb_arb_resampler.py
index e40d9636a..cd9289fa5 100644
--- a/gnuradio-core/src/python/gnuradio/blks2impl/pfb_arb_resampler.py
+++ b/gnuradio-core/src/python/gnuradio/blks2impl/pfb_arb_resampler.py
@@ -31,15 +31,22 @@ class pfb_arb_resampler_ccf(gr.hier_block2):
streams. This block is provided to be consistent with the interface to the
other PFB block.
'''
- def __init__(self, rate, taps, flt_size=32):
+ def __init__(self, rate, taps=None, flt_size=32, atten=80):
gr.hier_block2.__init__(self, "pfb_arb_resampler_ccf",
gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature
gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature
self._rate = rate
- self._taps = taps
self._size = flt_size
+ if taps is not None:
+ self._taps = taps
+ else:
+ # Create a filter that covers the full bandwidth of the input signal
+ bw = 0.5
+ tb = 0.1
+ self._taps = gr.firdes.low_pass_2(self._size, self._size, bw, tb, atten)
+
self.pfb = gr.pfb_arb_resampler_ccf(self._rate, self._taps, self._size)
self.connect(self, self.pfb)