diff options
author | Josh Morman <jmorman@perspectalabs.com> | 2019-05-13 14:24:47 -0400 |
---|---|---|
committer | Martin Braun <martin.braun@ettus.com> | 2019-06-15 16:55:58 -0700 |
commit | 3ad584916c9fe2c1404dcd634d02eb85afd98337 (patch) | |
tree | 54480012d5a168bd3cf8d1db812d95b728d046f4 | |
parent | 25b01217d191a419ff686bd9c59a11f4a3b7437d (diff) |
blocks: replace blks2_selector with new implementation
blks2_selector was deprecated and finally removed
This block implements the same functionality but in a way more similar
to the Copy block
fixes #2460
-rw-r--r-- | gr-blocks/examples/selector.grc | 369 | ||||
-rw-r--r-- | gr-blocks/grc/blocks.tree.yml | 1 | ||||
-rw-r--r-- | gr-blocks/grc/blocks_selector.block.yml | 93 | ||||
-rw-r--r-- | gr-blocks/include/gnuradio/blocks/CMakeLists.txt | 1 | ||||
-rw-r--r-- | gr-blocks/include/gnuradio/blocks/selector.h | 65 | ||||
-rw-r--r-- | gr-blocks/lib/CMakeLists.txt | 1 | ||||
-rw-r--r-- | gr-blocks/lib/selector_impl.cc | 143 | ||||
-rw-r--r-- | gr-blocks/lib/selector_impl.h | 73 | ||||
-rw-r--r-- | gr-blocks/python/blocks/qa_selector.py | 223 | ||||
-rw-r--r-- | gr-blocks/swig/blocks_swig7.i | 3 |
10 files changed, 972 insertions, 0 deletions
diff --git a/gr-blocks/examples/selector.grc b/gr-blocks/examples/selector.grc new file mode 100644 index 0000000000..99cc7b91ef --- /dev/null +++ b/gr-blocks/examples/selector.grc @@ -0,0 +1,369 @@ +options: + parameters: + author: '' + category: '[GRC Hier Blocks]' + cmake_opt: '' + comment: '' + copyright: '' + description: '' + gen_cmake: 'On' + gen_linking: dynamic + generate_options: qt_gui + hier_block_src_path: '.:' + id: top_block + max_nouts: '0' + output_language: python + placement: (0,0) + qt_qss_theme: '' + realtime_scheduling: '' + run: 'True' + run_command: '{python} -u {filename}' + run_options: prompt + sizing_mode: fixed + thread_safe_setters: '' + title: top_block + window_size: '' + states: + coordinate: [8, 8] + rotation: 0 + state: enabled + +blocks: +- name: freq + id: variable_qtgui_range + parameters: + comment: '' + gui_hint: (2,0,1,2) + label: '' + min_len: '200' + orient: Qt.Horizontal + rangeType: float + start: '0' + step: '1' + stop: samp_rate/4 + value: '200' + widget: counter_slider + states: + coordinate: [448, 12.0] + rotation: 0 + state: true +- name: input_index + id: variable_qtgui_range + parameters: + comment: '' + gui_hint: (3,0,1,2) + label: '' + min_len: '200' + orient: Qt.Horizontal + rangeType: int + start: '0' + step: '1' + stop: '2' + value: '0' + widget: counter_slider + states: + coordinate: [584, 12.0] + rotation: 0 + state: true +- name: output_index + id: variable_qtgui_range + parameters: + comment: '' + gui_hint: (4,0,1,2) + label: '' + min_len: '200' + orient: Qt.Horizontal + rangeType: int + start: '0' + step: '1' + stop: '1' + value: '0' + widget: counter_slider + states: + coordinate: [696, 12.0] + rotation: 0 + state: true +- name: samp_rate + id: variable + parameters: + comment: '' + value: '32000' + states: + coordinate: [184, 12] + rotation: 0 + state: enabled +- name: analog_sig_source_x_0 + id: analog_sig_source_x + parameters: + affinity: '' + alias: '' + amp: '1' + comment: '' + freq: freq + maxoutbuf: '0' + minoutbuf: '0' + offset: '0' + samp_rate: samp_rate + type: complex + waveform: analog.GR_COS_WAVE + states: + coordinate: [280, 84.0] + rotation: 0 + state: true +- name: analog_sig_source_x_1 + id: analog_sig_source_x + parameters: + affinity: '' + alias: '' + amp: '1' + comment: '' + freq: freq + maxoutbuf: '0' + minoutbuf: '0' + offset: '0' + samp_rate: samp_rate + type: complex + waveform: analog.GR_TRI_WAVE + states: + coordinate: [280, 204.0] + rotation: 0 + state: true +- name: analog_sig_source_x_2 + id: analog_sig_source_x + parameters: + affinity: '' + alias: '' + amp: '1' + comment: '' + freq: freq + maxoutbuf: '0' + minoutbuf: '0' + offset: '0' + samp_rate: samp_rate + type: complex + waveform: analog.GR_SAW_WAVE + states: + coordinate: [280, 324.0] + rotation: 0 + state: true +- name: blocks_selector_0 + id: blocks_selector + parameters: + affinity: '' + alias: '' + comment: "The Selector block passes \nsamples from the input selected\n by input_index\ + \ to the output \nselected by output_index.\n\nOutputs != output_index \ndo\ + \ not produce samples\n\nWhen Enabled is set to Off, \nno output samples are\ + \ produced" + enabled: 'True' + input_index: input_index + maxoutbuf: '0' + minoutbuf: '0' + num_inputs: '3' + num_outputs: '2' + output_index: output_index + showports: 'True' + type: complex + vlen: '1' + states: + coordinate: [560, 196.0] + rotation: 0 + state: true +- name: qtgui_time_sink_x_0 + id: qtgui_time_sink_x + parameters: + affinity: '' + alias: '' + alpha1: '1.0' + alpha10: '1.0' + alpha2: '1.0' + alpha3: '1.0' + alpha4: '1.0' + alpha5: '1.0' + alpha6: '1.0' + alpha7: '1.0' + alpha8: '1.0' + alpha9: '1.0' + autoscale: 'False' + axislabels: 'True' + color1: blue + color10: blue + color2: green + color3: black + color4: cyan + color5: magenta + color6: yellow + color7: dark red + color8: dark green + color9: Dark Blue + comment: '' + ctrlpanel: 'False' + entags: 'True' + grid: 'False' + gui_hint: (0,0,1,1) + label1: Signal 1 + label10: Signal 10 + label2: Signal 2 + label3: Signal 3 + label4: Signal 4 + label5: Signal 5 + label6: Signal 6 + label7: Signal 7 + label8: Signal 8 + label9: Signal 9 + legend: 'True' + marker1: '1' + marker10: '1' + marker2: '1' + marker3: '1' + marker4: '1' + marker5: '1' + marker6: '1' + marker7: '1' + marker8: '1' + marker9: '1' + name: '"Output 0"' + nconnections: '1' + size: '1024' + srate: samp_rate + stemplot: 'False' + style1: '1' + style10: '1' + style2: '1' + style3: '1' + style4: '1' + style5: '1' + style6: '1' + style7: '1' + style8: '1' + style9: '1' + tr_chan: '0' + tr_delay: '0' + tr_level: '0.0' + tr_mode: qtgui.TRIG_MODE_FREE + tr_slope: qtgui.TRIG_SLOPE_POS + tr_tag: '""' + type: complex + update_time: '0.10' + width1: '1' + width10: '1' + width2: '1' + width3: '1' + width4: '1' + width5: '1' + width6: '1' + width7: '1' + width8: '1' + width9: '1' + ylabel: Amplitude + ymax: '1' + ymin: '-1' + yunit: '""' + states: + coordinate: [856, 108.0] + rotation: 0 + state: true +- name: qtgui_time_sink_x_1 + id: qtgui_time_sink_x + parameters: + affinity: '' + alias: '' + alpha1: '1.0' + alpha10: '1.0' + alpha2: '1.0' + alpha3: '1.0' + alpha4: '1.0' + alpha5: '1.0' + alpha6: '1.0' + alpha7: '1.0' + alpha8: '1.0' + alpha9: '1.0' + autoscale: 'False' + axislabels: 'True' + color1: blue + color10: blue + color2: green + color3: black + color4: cyan + color5: magenta + color6: yellow + color7: dark red + color8: dark green + color9: Dark Blue + comment: '' + ctrlpanel: 'False' + entags: 'True' + grid: 'True' + gui_hint: (0,1,1,1) + label1: Signal 1 + label10: Signal 10 + label2: Signal 2 + label3: Signal 3 + label4: Signal 4 + label5: Signal 5 + label6: Signal 6 + label7: Signal 7 + label8: Signal 8 + label9: Signal 9 + legend: 'True' + marker1: '1' + marker10: '1' + marker2: '1' + marker3: '1' + marker4: '1' + marker5: '1' + marker6: '1' + marker7: '1' + marker8: '1' + marker9: '1' + name: '"Output 1"' + nconnections: '1' + size: '1024' + srate: samp_rate + stemplot: 'False' + style1: '1' + style10: '1' + style2: '1' + style3: '1' + style4: '1' + style5: '1' + style6: '1' + style7: '1' + style8: '1' + style9: '1' + tr_chan: '0' + tr_delay: '0' + tr_level: '0.0' + tr_mode: qtgui.TRIG_MODE_FREE + tr_slope: qtgui.TRIG_SLOPE_POS + tr_tag: '""' + type: complex + update_time: '0.10' + width1: '1' + width10: '1' + width2: '1' + width3: '1' + width4: '1' + width5: '1' + width6: '1' + width7: '1' + width8: '1' + width9: '1' + ylabel: Amplitude + ymax: '1' + ymin: '-1' + yunit: '""' + states: + coordinate: [856, 252.0] + rotation: 0 + state: true + +connections: +- [analog_sig_source_x_0, '0', blocks_selector_0, '0'] +- [analog_sig_source_x_1, '0', blocks_selector_0, '1'] +- [analog_sig_source_x_2, '0', blocks_selector_0, '2'] +- [blocks_selector_0, '0', qtgui_time_sink_x_0, '0'] +- [blocks_selector_0, '1', qtgui_time_sink_x_1, '0'] + +metadata: + file_format: 1 diff --git a/gr-blocks/grc/blocks.tree.yml b/gr-blocks/grc/blocks.tree.yml index ebe509ddc4..40108372c2 100644 --- a/gr-blocks/grc/blocks.tree.yml +++ b/gr-blocks/grc/blocks.tree.yml @@ -94,6 +94,7 @@ - blocks_null_source - blocks_null_sink - blocks_copy + - blocks_selector - blocks_nop - xmlrpc_server - xmlrpc_client diff --git a/gr-blocks/grc/blocks_selector.block.yml b/gr-blocks/grc/blocks_selector.block.yml new file mode 100644 index 0000000000..5470c7d150 --- /dev/null +++ b/gr-blocks/grc/blocks_selector.block.yml @@ -0,0 +1,93 @@ +id: blocks_selector +label: Selector +flags: [ python, cpp ] + +parameters: +- id: type + label: Type + dtype: enum + options: [complex, float, int, short, byte] + option_attributes: + size: [gr.sizeof_gr_complex, gr.sizeof_float, gr.sizeof_int, gr.sizeof_short, + gr.sizeof_char] + hide: part +- id: enabled + label: Enabled + dtype: bool + default: 'True' + options: ['True', 'False'] + option_labels: [Enabled, Disabled] +- id: num_inputs + label: Number of Inputs + dtype: int + default: 2 +- id: num_outputs + label: Number of Outputs + dtype: int + default: 2 +- id: input_index + label: Input Index + dtype: int + default: 0 +- id: output_index + label: Output Index + dtype: int + default: 0 +- id: vlen + label: Vec Length + dtype: int + default: '1' + hide: ${ 'part' if vlen == 1 else 'none' } +- id: showports + label: Show Msg Ports + dtype: bool + default: 'True' + options: ['False', 'True'] + option_labels: ['Yes', 'No'] + hide: part + +inputs: +- domain: stream + dtype: ${ type } + vlen: ${ vlen } + multiplicity: ${ num_inputs } +- domain: message + id: en + optional: true + hide: ${ showports } + +outputs: +- domain: stream + dtype: ${ type } + vlen: ${ vlen } + multiplicity: ${ num_outputs } + +asserts: +- ${ vlen > 0 } + +templates: + imports: from gnuradio import blocks + make: |- + blocks.selector(${type.size}*${vlen},${input_index},${output_index}) + self.${id}.set_enabled(${enabled}) + callbacks: + - set_enabled(${enabled}) + - set_input_index(${input_index}) + - set_output_index(${output_index}) + +cpp_templates: + includes: ['#include <gnuradio/blocks/copy.h>'] + declarations: 'blocks::selector::sptr ${id};' + make: |- + this->${id} = blocks::selector::make(${type.size}*${vlen},${input_index},${output_index}); + self->${id}.set_enabled(${enabled}); + callbacks: + - set_enabled(${enabled}) + - set_input_index(${input_index}) + - set_output_index(${output_index}) + translations: + gr.sizeof_: 'sizeof(' + 'True': 'true' + 'False': 'false' + +file_format: 1 diff --git a/gr-blocks/include/gnuradio/blocks/CMakeLists.txt b/gr-blocks/include/gnuradio/blocks/CMakeLists.txt index 4ea763b105..04d7a81af9 100644 --- a/gr-blocks/include/gnuradio/blocks/CMakeLists.txt +++ b/gr-blocks/include/gnuradio/blocks/CMakeLists.txt @@ -51,6 +51,7 @@ install(FILES probe_signal_v.h rotator.h sample_and_hold.h + selector.h sub.h tsb_vector_sink.h unpack_k_bits.h diff --git a/gr-blocks/include/gnuradio/blocks/selector.h b/gr-blocks/include/gnuradio/blocks/selector.h new file mode 100644 index 0000000000..6d347a21a6 --- /dev/null +++ b/gr-blocks/include/gnuradio/blocks/selector.h @@ -0,0 +1,65 @@ +/* -*- c++ -*- */ +/* + * Copyright 2019 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_SELECTOR_H +#define INCLUDED_GR_SELECTOR_H + +#include <gnuradio/block.h> +#include <gnuradio/blocks/api.h> + +namespace gr { +namespace blocks { + +/*! + * \brief output[output_index][i] = input[input_index][i] + * \ingroup misc_blk + * + * \details + * Connect the sink at input index to the source at output index + * Samples from other input ports are consumed and dumped + * Other output ports produce no samples + * + */ +class BLOCKS_API selector : virtual public block +{ +public: + typedef boost::shared_ptr<selector> sptr; + + static sptr + make(size_t itemsize, unsigned int input_index, unsigned int output_index); + + // When enabled is set to false, no output samples are produced + // Otherwise samples are copied to the selected output port + virtual void set_enabled(bool enable) = 0; + virtual bool enabled() const = 0; + + virtual void set_input_index(unsigned int input_index) = 0; + virtual int input_index() const = 0; + + virtual void set_output_index(unsigned int output_index) = 0; + virtual int output_index() const = 0; +}; + +} /* namespace blocks */ +} /* namespace gr */ + +#endif /* INCLUDED_GR_SELECTOR_H */ diff --git a/gr-blocks/lib/CMakeLists.txt b/gr-blocks/lib/CMakeLists.txt index 7ee527d2fb..5ff174a8a8 100644 --- a/gr-blocks/lib/CMakeLists.txt +++ b/gr-blocks/lib/CMakeLists.txt @@ -46,6 +46,7 @@ add_library(gnuradio-blocks probe_signal_impl.cc probe_signal_v_impl.cc sample_and_hold_impl.cc + selector_impl.cc sub_impl.cc tsb_vector_sink_impl.cc unpacked_to_packed_impl.cc diff --git a/gr-blocks/lib/selector_impl.cc b/gr-blocks/lib/selector_impl.cc new file mode 100644 index 0000000000..dafb5f9096 --- /dev/null +++ b/gr-blocks/lib/selector_impl.cc @@ -0,0 +1,143 @@ +/* -*- c++ -*- */ +/* + * Copyright 2019 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 "selector_impl.h" +#include <gnuradio/io_signature.h> +#include <string.h> +#include <stdexcept> + +namespace gr { +namespace blocks { + +selector::sptr +selector::make(size_t itemsize, unsigned int input_index, unsigned int output_index) +{ + return gnuradio::get_initial_sptr( + new selector_impl(itemsize, input_index, output_index)); +} + +selector_impl::selector_impl(size_t itemsize, + unsigned int input_index, + unsigned int output_index) + : block("selector", + io_signature::make(1, -1, itemsize), + io_signature::make(1, -1, itemsize)), + d_itemsize(itemsize), + d_enabled(true), + d_input_index(input_index), + d_output_index(output_index), + d_num_inputs(0), + d_num_outputs(0) +{ + message_port_register_in(pmt::mp("en")); + set_msg_handler(pmt::mp("en"), [this](pmt::pmt_t msg) { this->handle_enable(msg); }); + + // TODO: add message ports for input_index and output_index +} + +selector_impl::~selector_impl() {} + +void selector_impl::set_input_index(unsigned int input_index) +{ + gr::thread::scoped_lock l(d_mutex); + if (input_index < d_num_inputs) + d_input_index = input_index; + else + throw std::out_of_range("input_index must be < ninputs"); +} + +void selector_impl::set_output_index(unsigned int output_index) +{ + gr::thread::scoped_lock l(d_mutex); + if (output_index < d_num_outputs) + d_output_index = output_index; + else + throw std::out_of_range("output_index must be < noutputs"); +} + +void selector_impl::handle_enable(pmt::pmt_t msg) +{ + if (pmt::is_bool(msg)) { + bool en = pmt::to_bool(msg); + gr::thread::scoped_lock l(d_mutex); + d_enabled = en; + } else { + GR_LOG_WARN(d_logger, + "handle_enable: Non-PMT type received, expecting Boolean PMT"); + } +} + +void selector_impl::forecast(int noutput_items, gr_vector_int& ninput_items_required) +{ + unsigned ninputs = ninput_items_required.size(); + for (unsigned i = 0; i < ninputs; i++) { + ninput_items_required[i] = noutput_items; + } +} + +bool selector_impl::check_topology(int ninputs, int noutputs) +{ + if ((int)d_input_index < ninputs && (int)d_output_index < noutputs) { + d_num_inputs = (unsigned int)ninputs; + d_num_outputs = (unsigned int)noutputs; + return true; + } else { + GR_LOG_WARN(d_logger, + "check_topology: Input or Output index greater than number of ports"); + return false; + } +} + +int selector_impl::general_work(int noutput_items, + gr_vector_int& ninput_items, + gr_vector_const_void_star& input_items, + gr_vector_void_star& output_items) +{ + const uint8_t** in = (const uint8_t**)&input_items[0]; + uint8_t** out = (uint8_t**)&output_items[0]; + + gr::thread::scoped_lock l(d_mutex); + if (d_enabled) { + std::copy(in[d_input_index], + in[d_input_index] + noutput_items * d_itemsize, + out[d_output_index]); + produce(d_output_index, noutput_items); + } + + consume_each(noutput_items); + return WORK_CALLED_PRODUCE; +} + +void selector_impl::setup_rpc() +{ +#ifdef GR_CTRLPORT + add_rpc_variable(rpcbasic_sptr(new rpcbasic_register_handler<selector>( + alias(), "en", "", "Enable", RPC_PRIVLVL_MIN, DISPNULL))); +#endif /* GR_CTRLPORT */ +} + +} /* namespace blocks */ +} /* namespace gr */ diff --git a/gr-blocks/lib/selector_impl.h b/gr-blocks/lib/selector_impl.h new file mode 100644 index 0000000000..e11068d805 --- /dev/null +++ b/gr-blocks/lib/selector_impl.h @@ -0,0 +1,73 @@ +/* -*- c++ -*- */ +/* + * Copyright 2019 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_SELECTOR_IMPL_H +#define INCLUDED_GR_SELECTOR_IMPL_H + +#include <gnuradio/blocks/selector.h> +#include <gnuradio/thread/thread.h> + +namespace gr { +namespace blocks { + +class selector_impl : public selector +{ +private: + size_t d_itemsize; + bool d_enabled; + unsigned int d_input_index, d_output_index; + unsigned int d_num_inputs, d_num_outputs; // keep track of the topology + + gr::thread::mutex d_mutex; + + +public: + selector_impl(size_t itemsize, unsigned int input_index, unsigned int output_index); + ~selector_impl(); + + void forecast(int noutput_items, gr_vector_int& ninput_items_required); + bool check_topology(int ninputs, int noutputs); + void setup_rpc(); + void handle_enable(pmt::pmt_t msg); + void set_enabled(bool enable) + { + gr::thread::scoped_lock l(d_mutex); + d_enabled = enable; + } + bool enabled() const { return d_enabled; } + + void set_input_index(unsigned int input_index); + int input_index() const { return d_input_index; } + + void set_output_index(unsigned int output_index); + int output_index() const { return d_output_index; } + + int general_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_GR_SELECTOR_IMPL_H */ diff --git a/gr-blocks/python/blocks/qa_selector.py b/gr-blocks/python/blocks/qa_selector.py new file mode 100644 index 0000000000..5bf01b593f --- /dev/null +++ b/gr-blocks/python/blocks/qa_selector.py @@ -0,0 +1,223 @@ +#!/usr/bin/env python +# +# Copyright 2019 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, blocks + + +class test_selector(gr_unittest.TestCase): + + def setUp(self): + self.tb = gr.top_block() + + def tearDown(self): + self.tb = None + + def test_select_same(self): + src_data = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10) + expected_result = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10) + expected_drop = () + + num_inputs = 4; num_outputs = 4 + input_index = 1; output_index = 2 + + op = blocks.selector(gr.sizeof_char, input_index, output_index) + + src = [] + dst = [] + for ii in range(num_inputs): + src.append( blocks.vector_source_b(src_data)) + self.tb.connect(src[ii], (op,ii)) + for jj in range(num_outputs): + dst.append(blocks.vector_sink_b()) + self.tb.connect((op,jj),dst[jj]) + + + self.tb.run() + + dst_data = dst[output_index].data() + + self.assertEqual(expected_result, dst_data) + + + def test_select_input(self): + + num_inputs = 4; num_outputs = 4 + input_index = 1; output_index = 2 + + op = blocks.selector(gr.sizeof_char, input_index, output_index) + + src = [] + dst = [] + for ii in range(num_inputs): + src_data = [ii+1]*10 + src.append( blocks.vector_source_b(src_data)) + self.tb.connect(src[ii], (op,ii)) + for jj in range(num_outputs): + dst.append(blocks.vector_sink_b()) + self.tb.connect((op,jj),dst[jj]) + + + self.tb.run() + + expected_result = [input_index+1]*10 + dst_data = list(dst[output_index].data()) + + self.assertEqual(expected_result, dst_data) + + def test_dump(self): + + num_inputs = 4; num_outputs = 4 + input_index = 1; output_index = 2 + output_not_selected = 3 + + op = blocks.selector(gr.sizeof_char, input_index, output_index) + + src = [] + dst = [] + for ii in range(num_inputs): + src_data = [ii+1]*10 + src.append( blocks.vector_source_b(src_data)) + self.tb.connect(src[ii], (op,ii)) + for jj in range(num_outputs): + dst.append(blocks.vector_sink_b()) + self.tb.connect((op,jj),dst[jj]) + + + self.tb.run() + + expected_result = [] + dst_data = list(dst[output_not_selected].data()) + + self.assertEqual(expected_result, dst_data) + + def test_not_enabled (self): + src_data = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10) + expected_result = () + + num_inputs = 4; num_outputs = 4 + input_index = 1; output_index = 2 + + op = blocks.selector(gr.sizeof_char, input_index, output_index) + op.set_enabled(False) + + src = [] + dst = [] + for ii in range(num_inputs): + src.append( blocks.vector_source_b(src_data)) + self.tb.connect(src[ii], (op,ii)) + for jj in range(num_outputs): + dst.append(blocks.vector_sink_b()) + self.tb.connect((op,jj),dst[jj]) + + + self.tb.run() + + dst_data = dst[output_index].data() + self.assertEqual(expected_result, dst_data) + + + # These tests cannot be run as set_index can only be called after check_topology is called + # def test_set_indices(self): + + # num_inputs = 4; num_outputs = 4 + # input_index = 1; output_index = 2 + + # op = blocks.selector(gr.sizeof_char, 0, 0) + + + # src = [] + # dst = [] + # for ii in range(num_inputs): + # src_data = [ii+1]*10 + # src.append( blocks.vector_source_b(src_data)) + # self.tb.connect(src[ii], (op,ii)) + # for jj in range(num_outputs): + # dst.append(blocks.vector_sink_b()) + # self.tb.connect((op,jj),dst[jj]) + + # op.set_input_index(input_index) + # op.set_output_index(output_index) + + # self.tb.run() + + # expected_result = [input_index+1]*10 + # dst_data = list(dst[output_index].data()) + + # self.assertEqual(expected_result, dst_data) + + # def test_dont_set_indices(self): + + # num_inputs = 4; num_outputs = 4 + # input_index = 1; output_index = 2 + + # op = blocks.selector(gr.sizeof_char, 0, 0) + # #op.set_input_index(input_index) + # #op.set_output_index(output_index) + + # src = [] + # dst = [] + # for ii in range(num_inputs): + # src_data = [ii+1]*10 + # src.append( blocks.vector_source_b(src_data)) + # self.tb.connect(src[ii], (op,ii)) + # for jj in range(num_outputs): + # dst.append(blocks.vector_sink_b()) + # self.tb.connect((op,jj),dst[jj]) + + + # self.tb.run() + + # expected_result = [input_index+1]*10 + # dst_data = list(dst[output_index].data()) + + # self.assertNotEqual(expected_result, dst_data) + + def test_float_vector(self): + + num_inputs = 4; num_outputs = 4 + input_index = 1; output_index = 2 + + veclen = 3 + + op = blocks.selector(gr.sizeof_float*veclen, input_index, output_index) + + src = [] + dst = [] + for ii in range(num_inputs): + src_data = [float(ii)+1]*10*veclen + src.append( blocks.vector_source_f(src_data, repeat=False, vlen=veclen)) + self.tb.connect(src[ii], (op,ii)) + for jj in range(num_outputs): + dst.append(blocks.vector_sink_f(vlen=veclen)) + self.tb.connect((op,jj),dst[jj]) + + + self.tb.run() + + expected_result = [float(input_index)+1]*10*veclen + dst_data = list(dst[output_index].data()) + + self.assertEqual(expected_result, dst_data) + +if __name__ == '__main__': + gr_unittest.run(test_selector) diff --git a/gr-blocks/swig/blocks_swig7.i b/gr-blocks/swig/blocks_swig7.i index 6314873b71..bb888dfbb2 100644 --- a/gr-blocks/swig/blocks_swig7.i +++ b/gr-blocks/swig/blocks_swig7.i @@ -34,6 +34,7 @@ #include "gnuradio/blocks/deinterleave.h" #include "gnuradio/blocks/divide.h" #include "gnuradio/blocks/exponentiate_const_cci.h" +#include "gnuradio/blocks/selector.h" #include "gnuradio/blocks/skiphead.h" #include "gnuradio/blocks/stream_mux.h" #include "gnuradio/blocks/stream_to_streams.h" @@ -50,6 +51,7 @@ %include "gnuradio/blocks/deinterleave.h" %include "gnuradio/blocks/divide.h" %include "gnuradio/blocks/exponentiate_const_cci.h" +%include "gnuradio/blocks/selector.h" %include "gnuradio/blocks/skiphead.h" %include "gnuradio/blocks/stream_mux.h" %include "gnuradio/blocks/stream_to_streams.h" @@ -68,6 +70,7 @@ GR_SWIG_BLOCK_MAGIC2_TMPL(blocks, divide_ss, divide<std::int16_t>); GR_SWIG_BLOCK_MAGIC2_TMPL(blocks, divide_ii, divide<std::int32_t>); GR_SWIG_BLOCK_MAGIC2_TMPL(blocks, divide_cc, divide<gr_complex>); GR_SWIG_BLOCK_MAGIC2(blocks, exponentiate_const_cci); +GR_SWIG_BLOCK_MAGIC2(blocks, selector); GR_SWIG_BLOCK_MAGIC2(blocks, skiphead); GR_SWIG_BLOCK_MAGIC2(blocks, stream_mux); GR_SWIG_BLOCK_MAGIC2(blocks, stream_to_streams); |