1 /* -*- c++ -*- */
2 /*
3 * Copyright 2019 Free Software Foundation, Inc.
4 *
5 * This file is part of GNU Radio
6 *
7 * GNU Radio is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3, or (at your option)
10 * any later version.
11 *
12 * GNU Radio is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with GNU Radio; see the file COPYING. If not, write to
19 * the Free Software Foundation, Inc., 51 Franklin Street,
20 * Boston, MA 02110-1301, USA.
21 */
22
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 #include "selector_impl.h"
28 #include <gnuradio/io_signature.h>
29 #include <string.h>
30 #include <stdexcept>
31
32 namespace gr {
33 namespace blocks {
34
35 selector::sptr
make(size_t itemsize,unsigned int input_index,unsigned int output_index)36 selector::make(size_t itemsize, unsigned int input_index, unsigned int output_index)
37 {
38 return gnuradio::get_initial_sptr(
39 new selector_impl(itemsize, input_index, output_index));
40 }
41
selector_impl(size_t itemsize,unsigned int input_index,unsigned int output_index)42 selector_impl::selector_impl(size_t itemsize,
43 unsigned int input_index,
44 unsigned int output_index)
45 : block("selector",
46 io_signature::make(1, -1, itemsize),
47 io_signature::make(1, -1, itemsize)),
48 d_itemsize(itemsize),
49 d_enabled(true),
50 d_input_index(input_index),
51 d_output_index(output_index),
52 d_num_inputs(0),
53 d_num_outputs(0)
54 {
55 message_port_register_in(pmt::mp("en"));
56 set_msg_handler(pmt::mp("en"), [this](pmt::pmt_t msg) { this->handle_enable(msg); });
57
58 // TODO: add message ports for input_index and output_index
59 }
60
~selector_impl()61 selector_impl::~selector_impl() {}
62
set_input_index(unsigned int input_index)63 void selector_impl::set_input_index(unsigned int input_index)
64 {
65 gr::thread::scoped_lock l(d_mutex);
66 if (input_index < d_num_inputs)
67 d_input_index = input_index;
68 else
69 throw std::out_of_range("input_index must be < ninputs");
70 }
71
set_output_index(unsigned int output_index)72 void selector_impl::set_output_index(unsigned int output_index)
73 {
74 gr::thread::scoped_lock l(d_mutex);
75 if (output_index < d_num_outputs)
76 d_output_index = output_index;
77 else
78 throw std::out_of_range("output_index must be < noutputs");
79 }
80
handle_enable(pmt::pmt_t msg)81 void selector_impl::handle_enable(pmt::pmt_t msg)
82 {
83 if (pmt::is_bool(msg)) {
84 bool en = pmt::to_bool(msg);
85 gr::thread::scoped_lock l(d_mutex);
86 d_enabled = en;
87 } else {
88 GR_LOG_WARN(d_logger,
89 "handle_enable: Non-PMT type received, expecting Boolean PMT");
90 }
91 }
92
forecast(int noutput_items,gr_vector_int & ninput_items_required)93 void selector_impl::forecast(int noutput_items, gr_vector_int& ninput_items_required)
94 {
95 unsigned ninputs = ninput_items_required.size();
96 for (unsigned i = 0; i < ninputs; i++) {
97 ninput_items_required[i] = 0;
98 }
99 ninput_items_required[d_input_index] = noutput_items;
100 }
101
check_topology(int ninputs,int noutputs)102 bool selector_impl::check_topology(int ninputs, int noutputs)
103 {
104 if ((int)d_input_index < ninputs && (int)d_output_index < noutputs) {
105 d_num_inputs = (unsigned int)ninputs;
106 d_num_outputs = (unsigned int)noutputs;
107 return true;
108 } else {
109 GR_LOG_WARN(d_logger,
110 "check_topology: Input or Output index greater than number of ports");
111 return false;
112 }
113 }
114
general_work(int noutput_items,gr_vector_int & ninput_items,gr_vector_const_void_star & input_items,gr_vector_void_star & output_items)115 int selector_impl::general_work(int noutput_items,
116 gr_vector_int& ninput_items,
117 gr_vector_const_void_star& input_items,
118 gr_vector_void_star& output_items)
119 {
120 const uint8_t** in = (const uint8_t**)&input_items[0];
121 uint8_t** out = (uint8_t**)&output_items[0];
122
123 gr::thread::scoped_lock l(d_mutex);
124 if (d_enabled) {
125 std::copy(in[d_input_index],
126 in[d_input_index] + noutput_items * d_itemsize,
127 out[d_output_index]);
128 produce(d_output_index, noutput_items);
129 }
130
131 consume_each(noutput_items);
132 return WORK_CALLED_PRODUCE;
133 }
134
setup_rpc()135 void selector_impl::setup_rpc()
136 {
137 #ifdef GR_CTRLPORT
138 add_rpc_variable(rpcbasic_sptr(new rpcbasic_register_handler<selector>(
139 alias(), "en", "", "Enable", RPC_PRIVLVL_MIN, DISPNULL)));
140 #endif /* GR_CTRLPORT */
141 }
142
143 } /* namespace blocks */
144 } /* namespace gr */
145