/* -*- c++ -*- */ /* * Copyright 2004,2010,2012,2018 Free Software Foundation, Inc. * * This file is part of GNU Radio * * SPDX-License-Identifier: GPL-3.0-or-later * */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "chunks_to_symbols_impl.h" #include <gnuradio/io_signature.h> #include <pmt/pmt.h> #include <cassert> namespace gr { namespace digital { void set_vector_from_pmt(std::vector<gr_complex>& symbol_table, const pmt::pmt_t& symbol_table_pmt) { size_t length; const gr_complex* elements = pmt::c32vector_elements(symbol_table_pmt, length); symbol_table.assign(elements, elements + length); } void set_vector_from_pmt(std::vector<float>& symbol_table, const pmt::pmt_t& symbol_table_pmt) { size_t length; const float* elements = pmt::f32vector_elements(symbol_table_pmt, length); symbol_table.assign(elements, elements + length); } template <class IN_T, class OUT_T> typename chunks_to_symbols<IN_T, OUT_T>::sptr chunks_to_symbols<IN_T, OUT_T>::make(const std::vector<OUT_T>& symbol_table, const unsigned int D) { return gnuradio::make_block_sptr<chunks_to_symbols_impl<IN_T, OUT_T>>(symbol_table, D); } template <class IN_T, class OUT_T> chunks_to_symbols_impl<IN_T, OUT_T>::chunks_to_symbols_impl( const std::vector<OUT_T>& symbol_table, const unsigned int D) : sync_interpolator("chunks_to_symbols", io_signature::make(1, -1, sizeof(IN_T)), io_signature::make(1, -1, sizeof(OUT_T)), D), d_D(D), d_symbol_table(symbol_table), symbol_table_key(pmt::mp("set_symbol_table")) { this->message_port_register_in(symbol_table_key); this->set_msg_handler(symbol_table_key, [this](const pmt::pmt_t& msg) { this->handle_set_symbol_table(msg); }); } template <class IN_T, class OUT_T> chunks_to_symbols_impl<IN_T, OUT_T>::~chunks_to_symbols_impl() { } template <class IN_T, class OUT_T> void chunks_to_symbols_impl<IN_T, OUT_T>::handle_set_symbol_table( const pmt::pmt_t& symbol_table_pmt) { set_vector_from_pmt(d_symbol_table, symbol_table_pmt); } template <class IN_T, class OUT_T> void chunks_to_symbols_impl<IN_T, OUT_T>::set_symbol_table( const std::vector<OUT_T>& symbol_table) { gr::thread::scoped_lock lock(this->d_setlock); d_symbol_table = symbol_table; } template <class IN_T, class OUT_T> int chunks_to_symbols_impl<IN_T, OUT_T>::work(int noutput_items, gr_vector_const_void_star& input_items, gr_vector_void_star& output_items) { gr::thread::scoped_lock lock(this->d_setlock); auto nstreams = input_items.size(); for (unsigned int m = 0; m < nstreams; m++) { const auto* in = reinterpret_cast<const IN_T*>(input_items[m]); // NB: The compiler can't know whether all specializations of `chunks_to_symbol` // are subclasses of gr::block. Hence the "this->" hoop we have to jump through to // access members of parent classes. size_t in_count = this->nitems_read(m); auto out = reinterpret_cast<OUT_T*>(output_items[m]); std::vector<tag_t> tags; this->get_tags_in_range( tags, m, this->nitems_read(m), this->nitems_read(m) + noutput_items / d_D); // per tag: all the samples leading up to this tag can be handled straightforward // with the current settings if (d_D == 1) { for (const auto& tag : tags) { for (; in_count < tag.offset; ++in_count) { auto key = static_cast<unsigned int>(*in); *out = d_symbol_table[key]; ++out; ++in; } if (tag.key == symbol_table_key) { handle_set_symbol_table(tag.value); } } // after the last tag, continue working on the remaining items for (; in < reinterpret_cast<const IN_T*>(input_items[m]) + noutput_items; ++in) { auto key = static_cast<unsigned int>(*in); *out = d_symbol_table[key]; ++out; } } else { // the multi-dimensional case for (const auto& tag : tags) { for (; in_count < tag.offset; ++in_count) { auto key = static_cast<unsigned int>(*in) * d_D; for (unsigned int idx = 0; idx < d_D; ++idx) { *out = d_symbol_table[key + idx]; ++out; } ++in; } if (tag.key == symbol_table_key) { handle_set_symbol_table(tag.value); } } // after the last tag, continue working on the remaining items for (; in < reinterpret_cast<const IN_T*>(input_items[m]) + noutput_items; ++in) { auto key = static_cast<unsigned int>(*in) * d_D; for (unsigned int idx = 0; idx < d_D; ++idx) { *out = d_symbol_table[key + idx]; ++out; } } } } return noutput_items; } template class chunks_to_symbols<std::uint8_t, float>; template class chunks_to_symbols<std::uint8_t, gr_complex>; template class chunks_to_symbols<std::int16_t, float>; template class chunks_to_symbols<std::int16_t, gr_complex>; template class chunks_to_symbols<std::int32_t, float>; template class chunks_to_symbols<std::int32_t, gr_complex>; } /* namespace digital */ } /* namespace gr */