summaryrefslogtreecommitdiff
path: root/gr-blocks
diff options
context:
space:
mode:
Diffstat (limited to 'gr-blocks')
-rw-r--r--gr-blocks/CMakeLists.txt2
-rw-r--r--gr-blocks/grc/blocks_block_tree.xml1
-rw-r--r--gr-blocks/grc/blocks_repack_bits_bb.xml46
-rw-r--r--gr-blocks/include/blocks/CMakeLists.txt2
-rw-r--r--gr-blocks/include/blocks/repack_bits_bb.h65
-rw-r--r--gr-blocks/include/blocks/tagged_stream_mux.h61
-rw-r--r--gr-blocks/lib/CMakeLists.txt4
-rw-r--r--gr-blocks/lib/repack_bits_bb_impl.cc123
-rw-r--r--gr-blocks/lib/repack_bits_bb_impl.h58
-rw-r--r--gr-blocks/lib/tagged_stream_mux_impl.cc93
-rw-r--r--gr-blocks/lib/tagged_stream_mux_impl.h54
-rwxr-xr-xgr-blocks/python/qa_repack_bits_bb.py127
-rwxr-xr-xgr-blocks/python/qa_tagged_stream_mux.py111
-rw-r--r--gr-blocks/swig/blocks_swig.i6
14 files changed, 752 insertions, 1 deletions
diff --git a/gr-blocks/CMakeLists.txt b/gr-blocks/CMakeLists.txt
index e92e4c2808..c4821da2b8 100644
--- a/gr-blocks/CMakeLists.txt
+++ b/gr-blocks/CMakeLists.txt
@@ -34,6 +34,8 @@ GR_REGISTER_COMPONENT("gr-blocks" ENABLE_GR_BLOCKS
GR_SET_GLOBAL(GR_BLOCKS_INCLUDE_DIRS
${CMAKE_CURRENT_SOURCE_DIR}/lib
${CMAKE_CURRENT_SOURCE_DIR}/include
+ ${CMAKE_CURRENT_BINARY_DIR}/lib
+ ${CMAKE_CURRENT_BINARY_DIR}/include
)
########################################################################
diff --git a/gr-blocks/grc/blocks_block_tree.xml b/gr-blocks/grc/blocks_block_tree.xml
index 7b04737d4e..512252cda6 100644
--- a/gr-blocks/grc/blocks_block_tree.xml
+++ b/gr-blocks/grc/blocks_block_tree.xml
@@ -96,6 +96,7 @@
<block>blocks_int_to_float</block>
<block>blocks_interleaved_short_to_complex</block>
<block>blocks_short_to_char</block>
+ <block>blocks_repack_bits_bb</block>
<block>blocks_short_to_float</block>
<block>blocks_uchar_to_float</block>
</cat>
diff --git a/gr-blocks/grc/blocks_repack_bits_bb.xml b/gr-blocks/grc/blocks_repack_bits_bb.xml
new file mode 100644
index 0000000000..4ad5ec631b
--- /dev/null
+++ b/gr-blocks/grc/blocks_repack_bits_bb.xml
@@ -0,0 +1,46 @@
+<block>
+ <name>Repack Bits</name>
+ <key>blocks_repack_bits_bb</key>
+ <import>from gnuradio import blocks</import>
+ <make>blocks.repack_bits_bb($k, $l, $len_tag_key, $align_output)</make>
+ <param>
+ <name>Bits per input byte</name>
+ <key>k</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Bits per output byte</name>
+ <key>l</key>
+ <value>8</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Length Tag Key</name>
+ <key>len_tag_key</key>
+ <value>""</value>
+ <type>string</type>
+ </param>
+ <param>
+ <name>Packet Alignment</name>
+ <key>align_output</key>
+ <value>False</value>
+ <type>enum</type>
+ <option>
+ <name>Output</name>
+ <key>True</key>
+ </option>
+ <option>
+ <name>Input</name>
+ <key>False</key>
+ </option>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>byte</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>byte</type>
+ </source>
+</block>
diff --git a/gr-blocks/include/blocks/CMakeLists.txt b/gr-blocks/include/blocks/CMakeLists.txt
index c7b3cb918e..10e132ed92 100644
--- a/gr-blocks/include/blocks/CMakeLists.txt
+++ b/gr-blocks/include/blocks/CMakeLists.txt
@@ -155,6 +155,7 @@ install(FILES
peak_detector2_fb.h
probe_rate.h
regenerate_bb.h
+ repack_bits_bb.h
repeat.h
rms_cf.h
rms_ff.h
@@ -174,6 +175,7 @@ install(FILES
throttle.h
transcendental.h
tuntap_pdu.h
+ tagged_stream_mux.h
uchar_to_float.h
udp_sink.h
udp_source.h
diff --git a/gr-blocks/include/blocks/repack_bits_bb.h b/gr-blocks/include/blocks/repack_bits_bb.h
new file mode 100644
index 0000000000..9ade0a4353
--- /dev/null
+++ b/gr-blocks/include/blocks/repack_bits_bb.h
@@ -0,0 +1,65 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012 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_BLOCKS_REPACK_BITS_BB_H
+#define INCLUDED_BLOCKS_REPACK_BITS_BB_H
+
+#include <blocks/api.h>
+#include <gr_tagged_stream_block.h>
+
+namespace gr {
+ namespace blocks {
+
+ /*!
+ * \brief Pack \p k bits from the input stream onto \p k bits of the output stream.
+ * \ingroup blocks
+ *
+ * No bits are lost here; any value for k and l (within [1, 8]) is allowed.
+ * On every fresh input byte, it starts reading on the LSB, and starts copying
+ * to the LSB as well.
+ *
+ * If a packet length tag is given, this block assumes a tagged stream.
+ * In this case, the tag with the packet length is updated accordingly.
+ * Also, the number of input bits is padded with zeros if the number of input
+ * bits is not an integer multiple of \p l, or bits are truncated from the input
+ * if \p align_output is set to true.
+ */
+ class BLOCKS_API repack_bits_bb : virtual public gr_tagged_stream_block
+ {
+ public:
+ typedef boost::shared_ptr<repack_bits_bb> sptr;
+
+ /*!
+ * \param k Number of relevant bits on the input stream
+ * \param l Number of relevant bits on the output stream
+ * \param len_tag_key If not empty, this is the key for the length tag.
+ * \param align_output If len_tag_key is given, this controls if the input
+ * or the output is aligned.
+ */
+ static sptr make(int k, int l=8, const std::string &len_tag_key="", bool align_output=false);
+ };
+
+ } // namespace blocks
+} // namespace gr
+
+#endif /* INCLUDED_BLOCKS_REPACK_BITS_BB_H */
+
diff --git a/gr-blocks/include/blocks/tagged_stream_mux.h b/gr-blocks/include/blocks/tagged_stream_mux.h
new file mode 100644
index 0000000000..23e8a94403
--- /dev/null
+++ b/gr-blocks/include/blocks/tagged_stream_mux.h
@@ -0,0 +1,61 @@
+/* -*- c++ -*- */
+/* Copyright 2012 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_TAGGED_STREAM_MUX_H
+#define INCLUDED_TAGGED_STREAM_MUX_H
+
+#include <blocks/api.h>
+#include <gr_tagged_stream_block.h>
+
+namespace gr {
+ namespace blocks {
+
+ /*!
+ * \brief Combines tagged streams.
+ *
+ * \description
+ * Takes N streams as input. Each stream is tagged with packet lengths.
+ * Packets are output sequentially from each input stream.
+ *
+ * The output signal has a new length tag, which is the sum of all
+ * individual length tags.
+ *
+ * All other tags are propagated as expected, i.e. they stay associated
+ * with the same input item.
+ *
+ * \ingroup blocks
+ */
+ class BLOCKS_API tagged_stream_mux : virtual public gr_tagged_stream_block
+ {
+ public:
+ typedef boost::shared_ptr<tagged_stream_mux> sptr;
+
+ /* \param itemsize Items size (number of bytes per item)
+ * \param lengthtagname Length tag key
+ */
+ static sptr make(size_t itemsize, const std::string &lengthtagname);
+ };
+
+ } // namespace blocks
+} // namespace gr
+
+#endif /* INCLUDED_TAGGED_STREAM_MUX_H */
+
diff --git a/gr-blocks/lib/CMakeLists.txt b/gr-blocks/lib/CMakeLists.txt
index d64287c749..8fdaf8ecdd 100644
--- a/gr-blocks/lib/CMakeLists.txt
+++ b/gr-blocks/lib/CMakeLists.txt
@@ -214,6 +214,7 @@ list(APPEND gr_blocks_sources
transcendental_impl.cc
tcp_connection.cc
tuntap_pdu_impl.cc
+ tagged_stream_mux_impl.cc
uchar_array_to_float.cc
uchar_to_float_impl.cc
udp_sink_impl.cc
@@ -247,7 +248,8 @@ list(APPEND blocks_libs
${BLOCKS_LIBRARIES}
)
-add_library(gnuradio-blocks SHARED ${gr_blocks_sources})
+add_library(gnuradio-blocks SHARED ${gr_blocks_sources}
+ repack_bits_bb_impl.cc)
add_dependencies(gnuradio-blocks blocks_generated_includes)
target_link_libraries(gnuradio-blocks ${blocks_libs})
diff --git a/gr-blocks/lib/repack_bits_bb_impl.cc b/gr-blocks/lib/repack_bits_bb_impl.cc
new file mode 100644
index 0000000000..c7ed054c8a
--- /dev/null
+++ b/gr-blocks/lib/repack_bits_bb_impl.cc
@@ -0,0 +1,123 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012 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_io_signature.h>
+#include "repack_bits_bb_impl.h"
+
+namespace gr {
+ namespace blocks {
+
+ repack_bits_bb::sptr
+ repack_bits_bb::make(int k, int l, const std::string &len_tag_key, bool align_output)
+ {
+ return gnuradio::get_initial_sptr (new repack_bits_bb_impl(k, l, len_tag_key, align_output));
+ }
+
+ repack_bits_bb_impl::repack_bits_bb_impl(int k, int l, const std::string &len_tag_key, bool align_output)
+ : gr_tagged_stream_block("repack_bits_bb",
+ gr_make_io_signature(1, 1, sizeof (char)),
+ gr_make_io_signature(1, 1, sizeof (char)),
+ len_tag_key),
+ d_k(k), d_l(l),
+ d_packet_mode(!len_tag_key.empty()),
+ d_in_index(0), d_out_index(0),
+ d_align_output(align_output)
+ {
+ if (d_k > 8 || d_k < 1 || d_l > 8 || d_l < 1) {
+ throw std::invalid_argument("k and l must be in [1, 8]");
+ }
+
+ set_relative_rate((double) d_k / d_l);
+ }
+
+ repack_bits_bb_impl::~repack_bits_bb_impl()
+ {
+ }
+
+ int
+ repack_bits_bb_impl::calculate_output_stream_length(const gr_vector_int &ninput_items)
+ {
+ int n_out_bytes_required = (ninput_items[0] * d_k) / d_l;
+ if ((ninput_items[0] * d_k) % d_l && (!d_packet_mode || (d_packet_mode && !d_align_output))) {
+ n_out_bytes_required++;
+ }
+
+ return n_out_bytes_required;
+ }
+
+ int
+ repack_bits_bb_impl::work (int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ const unsigned char *in = (const unsigned char *) input_items[0];
+ unsigned char *out = (unsigned char *) output_items[0];
+ int bytes_to_write = noutput_items;
+
+ if (d_packet_mode) { // noutput_items could be larger than necessary
+ int bytes_to_read = ninput_items[0];
+ bytes_to_write = bytes_to_read * d_k / d_l;
+ if (!d_align_output && (((bytes_to_read * d_k) % d_l) != 0)) {
+ bytes_to_write++;
+ }
+ }
+
+ int n_read = 0;
+ int n_written = 0;
+ while(n_written < bytes_to_write && n_read < ninput_items[0]) {
+ if (d_out_index == 0) { // Starting a fresh byte
+ out[n_written] = 0;
+ }
+ out[n_written] |= ((in[n_read] >> d_in_index) & 0x01) << d_out_index;
+
+ d_in_index = (d_in_index + 1) % d_k;
+ d_out_index = (d_out_index + 1) % d_l;
+ if (d_in_index == 0) {
+ n_read++;
+ d_in_index = 0;
+ }
+ if (d_out_index == 0) {
+ n_written++;
+ d_out_index = 0;
+ }
+ }
+
+ if (d_packet_mode) {
+ if (d_out_index) {
+ n_written++;
+ d_out_index = 0;
+ }
+ } else {
+ consume_each(n_read);
+ }
+
+ return n_written;
+ }
+
+ } /* namespace blocks */
+} /* namespace gr */
+
diff --git a/gr-blocks/lib/repack_bits_bb_impl.h b/gr-blocks/lib/repack_bits_bb_impl.h
new file mode 100644
index 0000000000..bf39f8cb0f
--- /dev/null
+++ b/gr-blocks/lib/repack_bits_bb_impl.h
@@ -0,0 +1,58 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012 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_BLOCKS_REPACK_BITS_BB_IMPL_H
+#define INCLUDED_BLOCKS_REPACK_BITS_BB_IMPL_H
+
+#include <blocks/repack_bits_bb.h>
+
+namespace gr {
+ namespace blocks {
+
+ class repack_bits_bb_impl : public repack_bits_bb
+ {
+ private:
+ const int d_k; //! Bits on input stream
+ const int d_l; //! Bits on output stream
+ const bool d_packet_mode;
+ int d_in_index; // Current bit of input byte
+ int d_out_index; // Current bit of output byte
+ bool d_align_output; //! true if the output shall be aligned, false if the input shall be aligned
+
+ protected:
+ int calculate_output_stream_length(const gr_vector_int &ninput_items);
+
+ public:
+ repack_bits_bb_impl(int k, int l, const std::string &len_tag_key, bool align_output);
+ ~repack_bits_bb_impl();
+
+ int work(int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ };
+
+ } // namespace blocks
+} // namespace gr
+
+#endif /* INCLUDED_BLOCKS_REPACK_BITS_BB_IMPL_H */
+
diff --git a/gr-blocks/lib/tagged_stream_mux_impl.cc b/gr-blocks/lib/tagged_stream_mux_impl.cc
new file mode 100644
index 0000000000..59e36fa07e
--- /dev/null
+++ b/gr-blocks/lib/tagged_stream_mux_impl.cc
@@ -0,0 +1,93 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012 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_io_signature.h>
+#include "tagged_stream_mux_impl.h"
+
+namespace gr {
+ namespace blocks {
+
+ tagged_stream_mux::sptr
+ tagged_stream_mux::make(size_t itemsize, const std::string &lengthtagname)
+ {
+ return gnuradio::get_initial_sptr (new tagged_stream_mux_impl(itemsize, lengthtagname));
+ }
+
+ tagged_stream_mux_impl::tagged_stream_mux_impl(size_t itemsize, const std::string &lengthtagname)
+ : gr_tagged_stream_block("tagged_stream_mux",
+ gr_make_io_signature(1, -1, itemsize),
+ gr_make_io_signature(1, 1, itemsize),
+ lengthtagname),
+ d_itemsize(itemsize)
+ {
+ set_tag_propagation_policy(TPP_DONT);
+ }
+
+ tagged_stream_mux_impl::~tagged_stream_mux_impl()
+ {
+ }
+
+ int
+ tagged_stream_mux_impl::calculate_output_stream_length(const gr_vector_int &ninput_items)
+ {
+ int nout = 0;
+ for (unsigned i = 0; i < ninput_items.size(); i++) {
+ nout += ninput_items[i];
+ }
+ return nout;
+ }
+
+ int
+ tagged_stream_mux_impl::work (int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ unsigned char *out = (unsigned char *) output_items[0];
+ int n_produced = 0;
+
+ set_relative_rate(ninput_items.size());
+
+ for (unsigned int i = 0; i < input_items.size(); i++) {
+ const unsigned char *in = (const unsigned char *) input_items[i];
+
+ std::vector<gr_tag_t> tags;
+ get_tags_in_range(tags, i, nitems_read(i), nitems_read(i)+ninput_items[i]);
+ for (unsigned int j = 0; j < tags.size(); j++) {
+ const uint64_t offset = tags[j].offset - nitems_read(i) + nitems_written(0) + n_produced;
+ add_item_tag(0, offset, tags[j].key, tags[j].value);
+ }
+ memcpy((void *) out, (const void *) in, ninput_items[i] * d_itemsize);
+ out += ninput_items[i] * d_itemsize;
+ n_produced += ninput_items[i];
+ }
+
+ return n_produced;
+ }
+
+ } /* namespace blocks */
+} /* namespace gr */
+
diff --git a/gr-blocks/lib/tagged_stream_mux_impl.h b/gr-blocks/lib/tagged_stream_mux_impl.h
new file mode 100644
index 0000000000..19862e6868
--- /dev/null
+++ b/gr-blocks/lib/tagged_stream_mux_impl.h
@@ -0,0 +1,54 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012 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_TAGGED_STREAM_MUX_IMPL_H
+#define INCLUDED_TAGGED_STREAM_MUX_IMPL_H
+
+#include <vector>
+#include <blocks/tagged_stream_mux.h>
+
+namespace gr {
+ namespace blocks {
+
+ class tagged_stream_mux_impl : public tagged_stream_mux
+ {
+ private:
+ size_t d_itemsize;
+
+ protected:
+ int calculate_output_stream_length(const std::vector<int> &ninput_items);
+
+ public:
+ tagged_stream_mux_impl(size_t itemsize, const std::string &lengthtagname);
+ ~tagged_stream_mux_impl();
+
+ int work(int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ };
+
+ } // namespace blocks
+} // namespace gr
+
+#endif
+
diff --git a/gr-blocks/python/qa_repack_bits_bb.py b/gr-blocks/python/qa_repack_bits_bb.py
new file mode 100755
index 0000000000..b0c6480ec4
--- /dev/null
+++ b/gr-blocks/python/qa_repack_bits_bb.py
@@ -0,0 +1,127 @@
+#!/usr/bin/env python
+#
+# Copyright 2013 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.
+#
+
+import random
+from gnuradio import gr, gr_unittest
+from gruel import pmt
+import blocks_swig as blocks
+
+class qa_repack_bits_bb (gr_unittest.TestCase):
+
+ def setUp (self):
+ self.tb = gr.top_block ()
+
+ def tearDown (self):
+ self.tb = None
+
+ def test_001_simple (self):
+ """ Very simple test, 2 bits -> 1 """
+ src_data = (0b11, 0b01, 0b10)
+ expected_data = (0b1, 0b1, 0b1, 0b0, 0b0, 0b1)
+ k = 2
+ l = 1
+ src = gr.vector_source_b(src_data, False, 1)
+ repack = blocks.repack_bits_bb(k, l)
+ sink = gr.vector_sink_b()
+ self.tb.connect(src, repack, sink)
+ self.tb.run ()
+ self.assertEqual(sink.data(), expected_data)
+
+ def test_002_three (self):
+ """ 8 -> 3 """
+ src_data = (0b11111101, 0b11111111, 0b11111111)
+ expected_data = (0b101,) + (0b111,) * 7
+ k = 8
+ l = 3
+ src = gr.vector_source_b(src_data, False, 1)
+ repack = blocks.repack_bits_bb(k, l)
+ sink = gr.vector_sink_b()
+ self.tb.connect(src, repack, sink)
+ self.tb.run ()
+ self.assertEqual(sink.data(), expected_data)
+
+ def test_003_lots_of_bytes (self):
+ """ Lots and lots of bytes, multiple packer stages """
+ src_data = tuple([random.randint(0, 255) for x in range(3*5*7*8 * 10)])
+ src = gr.vector_source_b(src_data, False, 1)
+ repack1 = blocks.repack_bits_bb(8, 3)
+ repack2 = blocks.repack_bits_bb(3, 5)
+ repack3 = blocks.repack_bits_bb(5, 7)
+ repack4 = blocks.repack_bits_bb(7, 8)
+ sink = gr.vector_sink_b()
+ self.tb.connect(src, repack1, repack2, repack3, repack4, sink)
+ self.tb.run ()
+ self.assertEqual(sink.data(), src_data)
+
+ def test_004_three_with_tags (self):
+ """ 8 -> 3 """
+ src_data = (0b11111101, 0b11111111)
+ expected_data = (0b101,) + (0b111,) * 4 + (0b001,)
+ k = 8
+ l = 3
+ tag_name = "len"
+ tag = gr.gr_tag_t()
+ tag.offset = 0
+ tag.key = pmt.pmt_string_to_symbol(tag_name)
+ tag.value = pmt.pmt_from_long(len(src_data))
+ src = gr.vector_source_b(src_data, False, 1, (tag,))
+ repack = blocks.repack_bits_bb(k, l, tag_name)
+ sink = gr.vector_sink_b()
+ self.tb.connect(src, repack, sink)
+ self.tb.run ()
+ self.assertEqual(sink.data(), expected_data)
+ try:
+ out_tag = sink.tags()[0]
+ except:
+ self.assertFail()
+ self.assertEqual(out_tag.offset, 0)
+ self.assertEqual(pmt.pmt_symbol_to_string(out_tag.key), tag_name)
+ self.assertEqual(pmt.pmt_to_long(out_tag.value), len(expected_data))
+
+ def test_005_three_with_tags_trailing (self):
+ """ 3 -> 8, trailing bits """
+ src_data = (0b101,) + (0b111,) * 4 + (0b001,)
+ expected_data = (0b11111101, 0b11111111)
+ k = 3
+ l = 8
+ tag_name = "len"
+ tag = gr.gr_tag_t()
+ tag.offset = 0
+ tag.key = pmt.pmt_string_to_symbol(tag_name)
+ tag.value = pmt.pmt_from_long(len(src_data))
+ src = gr.vector_source_b(src_data, False, 1, (tag,))
+ repack = blocks.repack_bits_bb(k, l, tag_name, True)
+ sink = gr.vector_sink_b()
+ self.tb.connect(src, repack, sink)
+ self.tb.run ()
+ self.assertEqual(sink.data(), expected_data)
+ try:
+ out_tag = sink.tags()[0]
+ except:
+ self.assertFail()
+ self.assertEqual(out_tag.offset, 0)
+ self.assertEqual(pmt.pmt_symbol_to_string(out_tag.key), tag_name)
+ self.assertEqual(pmt.pmt_to_long(out_tag.value), len(expected_data))
+
+if __name__ == '__main__':
+ gr_unittest.run(qa_repack_bits_bb, "qa_repack_bits_bb.xml")
+
diff --git a/gr-blocks/python/qa_tagged_stream_mux.py b/gr-blocks/python/qa_tagged_stream_mux.py
new file mode 100755
index 0000000000..501c111a67
--- /dev/null
+++ b/gr-blocks/python/qa_tagged_stream_mux.py
@@ -0,0 +1,111 @@
+#!/usr/bin/env python
+#
+# Copyright 2013 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+from gnuradio import gr, gr_unittest
+from gruel import pmt
+import blocks_swig as blocks
+import numpy
+
+def make_len_tags(tupl, key):
+ tags = []
+ tag = gr.gr_tag_t()
+ tag.key = pmt.pmt_string_to_symbol(key)
+ n_read = 0
+ for element in tupl:
+ tag.offset = n_read
+ n_read += len(element)
+ tag.value = pmt.to_pmt(len(element))
+ tags.append(tag)
+ return tags
+
+def make_len_tag(offset, key, value):
+ tag = gr.gr_tag_t()
+ tag.offset = offset
+ tag.key = pmt.pmt_string_to_symbol(key)
+ tag.value = pmt.to_pmt(value)
+ return tag
+
+
+class qa_tagged_stream_mux (gr_unittest.TestCase):
+
+ def setUp(self):
+ self.tb = gr.top_block()
+
+ def tearDown(self):
+ self.tb = None
+
+ def test_1(self):
+ datas = (
+ 0, 1, 2, 5, 6, 10, 14, 15, 16,
+ 3, 4, 7, 8, 9, 11, 12, 13, 17
+ )
+ expected = tuple(range(18))
+
+ tagname = "packet_length"
+ len_tags_0 = (
+ make_len_tag(0, tagname, 3),
+ make_len_tag(3, tagname, 2),
+ make_len_tag(5, tagname, 1),
+ make_len_tag(6, tagname, 3)
+ )
+ len_tags_1 = (
+ make_len_tag(0, tagname, 2),
+ make_len_tag(2, tagname, 3),
+ make_len_tag(5, tagname, 3),
+ make_len_tag(8, tagname, 1)
+ )
+ test_tag_0 = gr.gr_tag_t()
+ test_tag_0.key = pmt.pmt_string_to_symbol('spam')
+ test_tag_0.offset = 4 # On the second '1'
+ test_tag_0.value = pmt.to_pmt(42)
+ test_tag_1 = gr.gr_tag_t()
+ test_tag_1.key = pmt.pmt_string_to_symbol('eggs')
+ test_tag_1.offset = 3 # On the first '3' of the 2nd stream
+ test_tag_1.value = pmt.to_pmt(23)
+
+ src0 = gr.vector_source_b(datas[0:9], False, 1, len_tags_0 + (test_tag_0,))
+ src1 = gr.vector_source_b(datas[9:], False, 1, len_tags_1 + (test_tag_1,))
+ tagged_stream_mux = blocks.tagged_stream_mux(gr.sizeof_char, tagname)
+ snk = gr.vector_sink_b()
+ self.tb.connect(src0, (tagged_stream_mux, 0))
+ self.tb.connect(src1, (tagged_stream_mux, 1))
+ self.tb.connect(tagged_stream_mux, snk)
+ self.tb.run()
+
+ self.assertEqual(expected, snk.data())
+
+ tags = [gr.tag_to_python(x) for x in snk.tags()]
+ tags = sorted([(x.offset, x.key, x.value) for x in tags])
+ tags_expected = [
+ (0, 'packet_length', 5),
+ (5, 'packet_length', 5),
+ (6, 'spam', 42),
+ (8, 'eggs', 23),
+ (10, 'packet_length', 4),
+ (14, 'packet_length', 4)
+ ]
+ self.assertEqual(tags, tags_expected)
+
+
+if __name__ == '__main__':
+ gr_unittest.run(qa_tagged_stream_mux, "qa_tagged_stream_mux.xml")
+
diff --git a/gr-blocks/swig/blocks_swig.i b/gr-blocks/swig/blocks_swig.i
index 646cdd1e9e..e5d091b9df 100644
--- a/gr-blocks/swig/blocks_swig.i
+++ b/gr-blocks/swig/blocks_swig.i
@@ -149,6 +149,7 @@
#include "blocks/or_ss.h"
#include "blocks/or_ii.h"
#include "blocks/regenerate_bb.h"
+#include "blocks/repack_bits_bb.h"
#include "blocks/repeat.h"
#include "blocks/rms_cf.h"
#include "blocks/rms_ff.h"
@@ -176,6 +177,7 @@
#include "blocks/throttle.h"
#include "blocks/transcendental.h"
#include "blocks/tuntap_pdu.h"
+#include "blocks/tagged_stream_mux.h"
#include "blocks/uchar_to_float.h"
#include "blocks/udp_sink.h"
#include "blocks/udp_source.h"
@@ -312,6 +314,7 @@
%include "blocks/peak_detector2_fb.h"
%include "blocks/probe_rate.h"
%include "blocks/regenerate_bb.h"
+%include "blocks/repack_bits_bb.h"
%include "blocks/repeat.h"
%include "blocks/rms_cf.h"
%include "blocks/rms_ff.h"
@@ -338,6 +341,7 @@
%include "blocks/throttle.h"
%include "blocks/transcendental.h"
%include "blocks/tuntap_pdu.h"
+%include "blocks/tagged_stream_mux.h"
%include "blocks/uchar_to_float.h"
%include "blocks/udp_sink.h"
%include "blocks/udp_source.h"
@@ -471,6 +475,7 @@ GR_SWIG_BLOCK_MAGIC2(blocks, probe_signal_vi);
GR_SWIG_BLOCK_MAGIC2(blocks, probe_signal_vf);
GR_SWIG_BLOCK_MAGIC2(blocks, probe_signal_vc);
GR_SWIG_BLOCK_MAGIC2(blocks, regenerate_bb);
+GR_SWIG_BLOCK_MAGIC2(blocks, repack_bits_bb);
GR_SWIG_BLOCK_MAGIC2(blocks, repeat);
GR_SWIG_BLOCK_MAGIC2(blocks, rms_cf);
GR_SWIG_BLOCK_MAGIC2(blocks, rms_ff);
@@ -498,6 +503,7 @@ GR_SWIG_BLOCK_MAGIC2(blocks, threshold_ff);
GR_SWIG_BLOCK_MAGIC2(blocks, throttle);
GR_SWIG_BLOCK_MAGIC2(blocks, transcendental);
GR_SWIG_BLOCK_MAGIC2(blocks, tuntap_pdu);
+GR_SWIG_BLOCK_MAGIC2(blocks, tagged_stream_mux);
GR_SWIG_BLOCK_MAGIC2(blocks, uchar_to_float);
GR_SWIG_BLOCK_MAGIC2(blocks, udp_sink);
GR_SWIG_BLOCK_MAGIC2(blocks, udp_source);