diff options
-rw-r--r-- | gr-blocks/grc/blocks_repack_bits_bb.xml | 27 | ||||
-rw-r--r-- | gr-blocks/include/gnuradio/blocks/repack_bits_bb.h | 6 | ||||
-rw-r--r-- | gr-blocks/lib/repack_bits_bb_impl.cc | 115 | ||||
-rw-r--r-- | gr-blocks/lib/repack_bits_bb_impl.h | 5 | ||||
-rwxr-xr-x | gr-blocks/python/blocks/qa_repack_bits_bb.py | 53 |
5 files changed, 164 insertions, 42 deletions
diff --git a/gr-blocks/grc/blocks_repack_bits_bb.xml b/gr-blocks/grc/blocks_repack_bits_bb.xml index 4ad5ec631b..7931132540 100644 --- a/gr-blocks/grc/blocks_repack_bits_bb.xml +++ b/gr-blocks/grc/blocks_repack_bits_bb.xml @@ -2,30 +2,36 @@ <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> + <make>blocks.repack_bits_bb($k, $l, $len_tag_key, $align_output, $endianness)</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> + <hide>part</hide> </param> + <param> <name>Packet Alignment</name> <key>align_output</key> <value>False</value> <type>enum</type> + <hide>part</hide> <option> <name>Output</name> <key>True</key> @@ -35,10 +41,29 @@ <key>False</key> </option> </param> + + + <param> + <name>Endianness</name> + <key>endianness</key> + <value>gr.GR_LSB_FIRST</value> + <type>int</type> + <hide>part</hide> + <option> + <name>MSB</name> + <key>gr.GR_MSB_FIRST</key> + </option> + <option> + <name>LSB</name> + <key>gr.GR_LSB_FIRST</key> + </option> + </param> + <sink> <name>in</name> <type>byte</type> </sink> + <source> <name>out</name> <type>byte</type> diff --git a/gr-blocks/include/gnuradio/blocks/repack_bits_bb.h b/gr-blocks/include/gnuradio/blocks/repack_bits_bb.h index e094e6815a..83bd771e0b 100644 --- a/gr-blocks/include/gnuradio/blocks/repack_bits_bb.h +++ b/gr-blocks/include/gnuradio/blocks/repack_bits_bb.h @@ -25,6 +25,7 @@ #include <gnuradio/blocks/api.h> #include <gnuradio/tagged_stream_block.h> +#include <gnuradio/endianness.h> namespace gr { namespace blocks { @@ -75,12 +76,13 @@ namespace gr { * \param tsb_tag_key If not empty, this is the key for the length tag. * \param align_output If tsb_tag_key is given, this controls if the input * or the output is aligned. + * \param endianness The endianness of the output data stream (LSB or MSB). */ - static sptr make(int k, int l=8, const std::string &tsb_tag_key="", bool align_output=false); + static sptr make(int k, int l=8, const std::string &tsb_tag_key="", + bool align_output=false, endianness_t endianness=GR_LSB_FIRST); }; } // namespace blocks } // namespace gr #endif /* INCLUDED_BLOCKS_REPACK_BITS_BB_H */ - diff --git a/gr-blocks/lib/repack_bits_bb_impl.cc b/gr-blocks/lib/repack_bits_bb_impl.cc index af83187e92..de61bf414f 100644 --- a/gr-blocks/lib/repack_bits_bb_impl.cc +++ b/gr-blocks/lib/repack_bits_bb_impl.cc @@ -31,20 +31,25 @@ 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) + repack_bits_bb::make(int k, int l, const std::string &len_tag_key, + bool align_output, endianness_t endianness) { - return gnuradio::get_initial_sptr (new repack_bits_bb_impl(k, l, len_tag_key, align_output)); + return gnuradio::get_initial_sptr + (new repack_bits_bb_impl(k, l, len_tag_key, + align_output, endianness)); } - repack_bits_bb_impl::repack_bits_bb_impl(int k, int l, const std::string &len_tag_key, bool align_output) + repack_bits_bb_impl::repack_bits_bb_impl(int k, int l, const std::string &len_tag_key, + bool align_output, endianness_t endianness) : tagged_stream_block("repack_bits_bb", - io_signature::make(1, 1, sizeof (char)), - io_signature::make(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) + io_signature::make(1, 1, sizeof(char)), + io_signature::make(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), + d_endianness(endianness) { 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]"); @@ -88,31 +93,70 @@ namespace gr { 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); + switch(d_endianness) { + case GR_LSB_FIRST: + 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); + } + break; + + + case GR_MSB_FIRST: + 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_k - 1 - d_in_index)) & 0x01) << (d_l - 1 - 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); + } + break; + + default: + throw std::runtime_error("repack_bits_bb: unrecognized endianness value."); } return n_written; @@ -120,4 +164,3 @@ namespace gr { } /* namespace blocks */ } /* namespace gr */ - diff --git a/gr-blocks/lib/repack_bits_bb_impl.h b/gr-blocks/lib/repack_bits_bb_impl.h index ffb8349d35..8c57c74c23 100644 --- a/gr-blocks/lib/repack_bits_bb_impl.h +++ b/gr-blocks/lib/repack_bits_bb_impl.h @@ -37,12 +37,14 @@ namespace gr { 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 + endianness_t d_endianness; 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 k, int l, const std::string &len_tag_key, + bool align_output, endianness_t endianness=GR_LSB_FIRST); ~repack_bits_bb_impl(); int work(int noutput_items, @@ -55,4 +57,3 @@ namespace gr { } // namespace gr #endif /* INCLUDED_BLOCKS_REPACK_BITS_BB_IMPL_H */ - diff --git a/gr-blocks/python/blocks/qa_repack_bits_bb.py b/gr-blocks/python/blocks/qa_repack_bits_bb.py index 10880b196a..50e1506196 100755 --- a/gr-blocks/python/blocks/qa_repack_bits_bb.py +++ b/gr-blocks/python/blocks/qa_repack_bits_bb.py @@ -46,6 +46,19 @@ class qa_repack_bits_bb (gr_unittest.TestCase): self.tb.run () self.assertEqual(sink.data(), expected_data) + def test_001_simple_msb (self): + """ Very simple test, 2 bits -> 1 with MSB set """ + src_data = (0b11, 0b01, 0b10) + expected_data = (0b1, 0b1, 0b0, 0b1, 0b1, 0b0) + k = 2 + l = 1 + src = blocks.vector_source_b(src_data, False, 1) + repack = blocks.repack_bits_bb(k, l, "", False, gr.GR_MSB_FIRST) + sink = blocks.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) @@ -59,6 +72,32 @@ class qa_repack_bits_bb (gr_unittest.TestCase): 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 = blocks.vector_source_b(src_data, False, 1) + repack = blocks.repack_bits_bb(k, l) + sink = blocks.vector_sink_b() + self.tb.connect(src, repack, sink) + self.tb.run () + self.assertEqual(sink.data(), expected_data) + + def test_002_three_msb (self): + """ 8 -> 3 """ + src_data = (0b11111101, 0b11111111, 0b11111111) + expected_data = (0b111,) + (0b111,) + (0b011,) + (0b111,) * 5 + k = 8 + l = 3 + src = blocks.vector_source_b(src_data, False, 1) + repack = blocks.repack_bits_bb(k, l, "", False, gr.GR_MSB_FIRST) + sink = blocks.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)]) @@ -72,6 +111,19 @@ class qa_repack_bits_bb (gr_unittest.TestCase): self.tb.run () self.assertEqual(sink.data(), src_data) + def test_003_lots_of_bytes_msb (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 = blocks.vector_source_b(src_data, False, 1) + repack1 = blocks.repack_bits_bb(8, 3, "", False, gr.GR_MSB_FIRST) + repack2 = blocks.repack_bits_bb(3, 5, "", False, gr.GR_MSB_FIRST) + repack3 = blocks.repack_bits_bb(5, 7, "", False, gr.GR_MSB_FIRST) + repack4 = blocks.repack_bits_bb(7, 8, "", False, gr.GR_MSB_FIRST) + sink = blocks.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) @@ -112,4 +164,3 @@ class qa_repack_bits_bb (gr_unittest.TestCase): if __name__ == '__main__': gr_unittest.run(qa_repack_bits_bb, "qa_repack_bits_bb.xml") - |