diff options
author | Clayton Smith <argilo@gmail.com> | 2018-10-01 20:29:26 -0400 |
---|---|---|
committer | Marcus Müller <marcus@hostalia.de> | 2018-11-02 00:12:34 +0100 |
commit | 5b401b6500d381d69b3bc56feb1e6ad001218039 (patch) | |
tree | 7cf95738b5565d642f18ebc3d0ab628bc6d952f7 | |
parent | 4cbe4ba15def9e0c40e6ea628df58ee55868307a (diff) |
Allow the full range of offsets.
-rw-r--r-- | gr-blocks/grc/blocks_keep_m_in_n.block.yml | 2 | ||||
-rw-r--r-- | gr-blocks/lib/keep_m_in_n_impl.cc | 21 | ||||
-rw-r--r-- | gr-blocks/python/blocks/qa_keep_m_in_n.py | 79 |
3 files changed, 80 insertions, 22 deletions
diff --git a/gr-blocks/grc/blocks_keep_m_in_n.block.yml b/gr-blocks/grc/blocks_keep_m_in_n.block.yml index 451899eae0..96cf25dde9 100644 --- a/gr-blocks/grc/blocks_keep_m_in_n.block.yml +++ b/gr-blocks/grc/blocks_keep_m_in_n.block.yml @@ -37,6 +37,8 @@ asserts: - ${ n > 0 } - ${ m > 0 } - ${ m <= n } +- ${ offset >= 0 } +- ${ offset < n } templates: imports: from gnuradio import blocks diff --git a/gr-blocks/lib/keep_m_in_n_impl.cc b/gr-blocks/lib/keep_m_in_n_impl.cc index 4784d3c1a2..2c67af9c34 100644 --- a/gr-blocks/lib/keep_m_in_n_impl.cc +++ b/gr-blocks/lib/keep_m_in_n_impl.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2012 Free Software Foundation, Inc. + * Copyright 2012,2018 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -59,9 +59,14 @@ namespace gr { std::string s = boost::str(boost::format("keep_m_in_n: m (%1%) <= n %2%") % d_m % d_n); throw std::runtime_error(s); } - if(d_offset > (d_n - d_m)) { - std::string s = boost::str(boost::format("keep_m_in_n: offset (%1%) <= n (%2%) - m (%3%)") \ - % d_offset % d_n % d_m); + if(d_offset < 0) { + std::string s = boost::str(boost::format("keep_m_in_n: offset (%1%) must be >= 0") \ + % d_offset); + throw std::runtime_error(s); + } + if(d_offset >= d_n) { + std::string s = boost::str(boost::format("keep_m_in_n: offset (%1%) < n (%2%)") \ + % d_offset % d_n); throw std::runtime_error(s); } @@ -107,13 +112,19 @@ namespace gr { // iterate over data blocks of size {n, input : m, output} int blks = std::min(noutput_items/d_m, ninput_items[0]/d_n); + int excess = (d_offset + d_m - d_n) * d_itemsize; for(int i=0; i<blks; i++) { // set up copy pointers const uint8_t* iptr = &in[(i*d_n + d_offset)*d_itemsize]; uint8_t* optr = &out[i*d_m*d_itemsize]; // perform copy - memcpy( optr, iptr, d_m*d_itemsize ); + if(excess <= 0) { + memcpy( optr, iptr, d_m*d_itemsize ); + } else { + memcpy( optr, &in[i*d_n*d_itemsize], excess); + memcpy( optr + excess, iptr, d_m*d_itemsize - excess); + } } consume_each(blks*d_n); diff --git a/gr-blocks/python/blocks/qa_keep_m_in_n.py b/gr-blocks/python/blocks/qa_keep_m_in_n.py index 30a15d9ded..14d7863bbd 100644 --- a/gr-blocks/python/blocks/qa_keep_m_in_n.py +++ b/gr-blocks/python/blocks/qa_keep_m_in_n.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2008,2010,2012,2013 Free Software Foundation, Inc. +# Copyright 2008,2010,2012,2013,2018 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -25,6 +25,7 @@ from gnuradio import gr, gr_unittest, blocks import sys import random + class test_keep_m_in_n(gr_unittest.TestCase): def setUp(self): @@ -34,25 +35,69 @@ class test_keep_m_in_n(gr_unittest.TestCase): pass def test_001(self): - self.maxDiff = None; + self.maxDiff = None tb = gr.top_block() - src = blocks.vector_source_b( list(range(0,100)) ) + src = blocks.vector_source_c(list(range(0, 100))) # itemsize, M, N, offset - km2 = blocks.keep_m_in_n( 1, 1, 2, 0 ); - km3 = blocks.keep_m_in_n( 1, 1, 3, 1 ); - km7 = blocks.keep_m_in_n( 1, 1, 7, 2 ); - snk2 = blocks.vector_sink_b(); - snk3 = blocks.vector_sink_b(); - snk7 = blocks.vector_sink_b(); - tb.connect(src,km2,snk2); - tb.connect(src,km3,snk3); - tb.connect(src,km7,snk7); - tb.run(); - - self.assertEqual(list(range(0,100,2)), list(snk2.data())); - self.assertEqual(list(range(1,100,3)), list(snk3.data())); - self.assertEqual(list(range(2,100,7)), list(snk7.data())); + km2 = blocks.keep_m_in_n(8, 1, 2, 0) + km3 = blocks.keep_m_in_n(8, 1, 3, 1) + km7 = blocks.keep_m_in_n(8, 1, 7, 2) + snk2 = blocks.vector_sink_c() + snk3 = blocks.vector_sink_c() + snk7 = blocks.vector_sink_c() + tb.connect(src, km2, snk2) + tb.connect(src, km3, snk3) + tb.connect(src, km7, snk7) + tb.run() + + self.assertEqual(list(range(0, 100, 2)), list(snk2.data())) + self.assertEqual(list(range(1, 100, 3)), list(snk3.data())) + self.assertEqual(list(range(2, 100, 7)), list(snk7.data())) + + def test_002(self): + self.maxDiff = None + tb = gr.top_block() + src = blocks.vector_source_f(list(range(0, 100))) + + km = [] + snk = [] + for i in range(5): + km.append(blocks.keep_m_in_n(4, 3, 5, i)) + snk.append(blocks.vector_sink_f()) + tb.connect(src, km[i], snk[i]) + tb.run() + + for i in range(5): + self.assertEqual( + sorted( + list(range(i, 100, 5)) + + list(range((i+1) % 5, 100, 5)) + + list(range((i+2) % 5, 100, 5)) + ), + list(snk[i].data()) + ) + + def test_003(self): + with self.assertRaises(RuntimeError) as cm: + blocks.keep_m_in_n(8, 0, 5, 0) + self.assertEqual(str(cm.exception), 'keep_m_in_n: m=0 but must be > 0') + + with self.assertRaises(RuntimeError) as cm: + blocks.keep_m_in_n(8, 5, 0, 0) + self.assertEqual(str(cm.exception), 'keep_m_in_n: n=0 but must be > 0') + + with self.assertRaises(RuntimeError) as cm: + blocks.keep_m_in_n(8, 6, 5, 0) + self.assertEqual(str(cm.exception), 'keep_m_in_n: m (6) <= n 5') + + with self.assertRaises(RuntimeError) as cm: + blocks.keep_m_in_n(8, 2, 5, -1) + self.assertEqual(str(cm.exception), 'keep_m_in_n: offset (-1) must be >= 0') + + with self.assertRaises(RuntimeError) as cm: + blocks.keep_m_in_n(8, 2, 5, 5) + self.assertEqual(str(cm.exception), 'keep_m_in_n: offset (5) < n (5)') if __name__ == '__main__': |