diff options
Diffstat (limited to 'gr-blocks/lib')
26 files changed, 2220 insertions, 1 deletions
diff --git a/gr-blocks/lib/CMakeLists.txt b/gr-blocks/lib/CMakeLists.txt index ee4658ae34..b0f3ef15cd 100644 --- a/gr-blocks/lib/CMakeLists.txt +++ b/gr-blocks/lib/CMakeLists.txt @@ -114,6 +114,9 @@ expand_cc_h_impl(sub_XX ss ii ff cc) expand_cc_h_impl(xor_XX bb ss ii) expand_cc_h_impl(packed_to_unpacked_XX bb ss ii) expand_cc_h_impl(unpacked_to_packed_XX bb ss ii) +expand_cc_h_impl(vector_insert_X b s i f c) +expand_cc_h_impl(vector_sink_X b s i f c) +expand_cc_h_impl(vector_source_X b s i f c) ######################################################################## # Setup the include and linker paths @@ -142,6 +145,9 @@ list(APPEND gr_blocks_sources fxpt.cc wavfile.cc add_ff_impl.cc + annotator_1to1_impl.cc + annotator_alltoall_impl.cc + annotator_raw_impl.cc bin_statistics_f_impl.cc burst_tagger_impl.cc char_to_float_impl.cc @@ -154,8 +160,10 @@ list(APPEND gr_blocks_sources complex_to_mag_squared_impl.cc complex_to_arg_impl.cc conjugate_cc_impl.cc + copy_impl.cc deinterleave_impl.cc delay_impl.cc + endian_swap_impl.cc file_descriptor_sink_impl.cc file_descriptor_source_impl.cc file_sink_impl.cc @@ -169,6 +177,7 @@ list(APPEND gr_blocks_sources float_to_short_impl.cc float_array_to_uchar.cc float_to_uchar_impl.cc + head_impl.cc int_to_float_impl.cc interleave_impl.cc interleaved_short_array_to_complex.cc @@ -200,6 +209,7 @@ list(APPEND gr_blocks_sources rms_ff_impl.cc short_to_char_impl.cc short_to_float_impl.cc + skiphead_impl.cc socket_pdu_impl.cc stream_mux_impl.cc stream_pdu_base.cc @@ -262,15 +272,19 @@ GR_LIBRARY_FOO(gnuradio-blocks RUNTIME_COMPONENT "blocks_runtime" DEVEL_COMPONEN if(ENABLE_TESTING) include(GrTest) - include_directories(${CPPUNIT_INCLUDE_DIRS}) + include_directories( + ${GR_FILTER_INCLUDE_DIRS} + ${CPPUNIT_INCLUDE_DIRS}) link_directories(${CPPUNIT_LIBRARY_DIRS}) list(APPEND test_gr_blocks_sources ${CMAKE_CURRENT_SOURCE_DIR}/test_gr_blocks.cc ${CMAKE_CURRENT_SOURCE_DIR}/qa_blocks.cc + ${CMAKE_CURRENT_SOURCE_DIR}/qa_block_tags.cc ${CMAKE_CURRENT_SOURCE_DIR}/qa_fxpt.cc ${CMAKE_CURRENT_SOURCE_DIR}/qa_fxpt_nco.cc ${CMAKE_CURRENT_SOURCE_DIR}/qa_fxpt_vco.cc + ${CMAKE_CURRENT_SOURCE_DIR}/qa_rotator.cc ) add_executable(test-gr-blocks ${test_gr_blocks_sources}) @@ -281,6 +295,7 @@ if(ENABLE_TESTING) test-gr-blocks gnuradio-core gnuradio-blocks + gnuradio-filter ${Boost_LIBRARIES} ${CPPUNIT_LIBRARIES} ) diff --git a/gr-blocks/lib/annotator_1to1_impl.cc b/gr-blocks/lib/annotator_1to1_impl.cc new file mode 100644 index 0000000000..d3f4758684 --- /dev/null +++ b/gr-blocks/lib/annotator_1to1_impl.cc @@ -0,0 +1,113 @@ +/* -*- c++ -*- */ +/* + * Copyright 2010,2013 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 "annotator_1to1_impl.h" +#include <gr_io_signature.h> +#include <string.h> +#include <iostream> +#include <iomanip> + +namespace gr { + namespace blocks { + + annotator_1to1::sptr + annotator_1to1::make(int when, size_t sizeof_stream_item) + { + return gnuradio::get_initial_sptr + (new annotator_1to1_impl(when, sizeof_stream_item)); + } + + annotator_1to1_impl::annotator_1to1_impl(int when, size_t sizeof_stream_item) + : gr_sync_block("annotator_1to1", + gr_make_io_signature(1, -1, sizeof_stream_item), + gr_make_io_signature(1, -1, sizeof_stream_item)), + d_itemsize(sizeof_stream_item), d_when((uint64_t)when) + { + set_tag_propagation_policy(TPP_ONE_TO_ONE); + + d_tag_counter = 0; + set_relative_rate(1.0); + } + + annotator_1to1_impl::~annotator_1to1_impl() + { + } + + int + annotator_1to1_impl::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + const float *in = (const float*)input_items[0]; + float *out = (float*)output_items[0]; + + std::stringstream str; + str << name() << unique_id(); + + uint64_t abs_N = 0; + int ninputs = input_items.size(); + for(int i = 0; i < ninputs; i++) { + abs_N = nitems_read(i); + + std::vector<gr_tag_t> all_tags; + get_tags_in_range(all_tags, i, abs_N, abs_N + noutput_items); + + std::vector<gr_tag_t>::iterator itr; + for(itr = all_tags.begin(); itr != all_tags.end(); itr++) { + d_stored_tags.push_back(*itr); + } + } + + // Storing the current noutput_items as the value to the "noutput_items" key + pmt::pmt_t srcid = pmt::pmt_string_to_symbol(str.str()); + pmt::pmt_t key = pmt::pmt_string_to_symbol("seq"); + + // Work does nothing to the data stream; just copy all inputs to outputs + // Adds a new tag when the number of items read is a multiple of d_when + abs_N = nitems_read(0); + int noutputs = output_items.size(); + for(int j = 0; j < noutput_items; j++) { + // the min() is a hack to make sure this doesn't segfault if + // there are a different number of ins and outs. This is + // specifically designed to test the 1-to-1 propagation policy. + for(int i = 0; i < std::min(noutputs, ninputs); i++) { + if(abs_N % d_when == 0) { + pmt::pmt_t value = pmt::pmt_from_uint64(d_tag_counter++); + add_item_tag(i, abs_N, key, value, srcid); + } + + in = (const float*)input_items[i]; + out = (float*)output_items[i]; + out[j] = in[j]; + } + abs_N++; + } + + return noutput_items; + } + + } /* namespace blocks */ +} /* namespace gr */ diff --git a/gr-blocks/lib/annotator_1to1_impl.h b/gr-blocks/lib/annotator_1to1_impl.h new file mode 100644 index 0000000000..3306602e2c --- /dev/null +++ b/gr-blocks/lib/annotator_1to1_impl.h @@ -0,0 +1,56 @@ +/* -*- c++ -*- */ +/* + * Copyright 2010,2013 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_ANNOTATOR_1TO1_IMPL_H +#define INCLUDED_GR_ANNOTATOR_1TO1_IMPL_H + +#include <blocks/annotator_1to1.h> + +namespace gr { + namespace blocks { + + class annotator_1to1_impl : public annotator_1to1 + { + private: + size_t d_itemsize; + uint64_t d_when; + uint64_t d_tag_counter; + std::vector<gr_tag_t> d_stored_tags; + + public: + annotator_1to1_impl(int when, size_t sizeof_stream_item); + ~annotator_1to1_impl(); + + std::vector<gr_tag_t> data() const + { + return d_stored_tags; + } + + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } /* namespace blocks */ +} /* namespace gr */ + +#endif /* INCLUDED_GR_ANNOTATOR_1TO1_IMPL_H */ diff --git a/gr-blocks/lib/annotator_alltoall_impl.cc b/gr-blocks/lib/annotator_alltoall_impl.cc new file mode 100644 index 0000000000..5af1a9c18e --- /dev/null +++ b/gr-blocks/lib/annotator_alltoall_impl.cc @@ -0,0 +1,117 @@ +/* -*- c++ -*- */ +/* + * Copyright 2010,2013 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 "annotator_alltoall_impl.h" +#include <gr_io_signature.h> +#include <string.h> +#include <iostream> +#include <iomanip> + +namespace gr { + namespace blocks { + + annotator_alltoall::sptr + annotator_alltoall::make(int when, size_t sizeof_stream_item) + { + return gnuradio::get_initial_sptr + (new annotator_alltoall_impl(when, sizeof_stream_item)); + } + + annotator_alltoall_impl::annotator_alltoall_impl(int when, + size_t sizeof_stream_item) + : gr_sync_block("annotator_alltoall", + gr_make_io_signature(1, -1, sizeof_stream_item), + gr_make_io_signature(1, -1, sizeof_stream_item)), + d_itemsize(sizeof_stream_item), d_when((uint64_t)when) + { + set_tag_propagation_policy(TPP_ALL_TO_ALL); + + d_tag_counter = 0; + } + + annotator_alltoall_impl::~annotator_alltoall_impl() + { + } + + int + annotator_alltoall_impl::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + const float *in = (const float*)input_items[0]; + float *out = (float*)output_items[0]; + + std::stringstream str; + str << name() << unique_id(); + + uint64_t abs_N = 0, end_N; + int ninputs = input_items.size(); + for(int i = 0; i < ninputs; i++) { + abs_N = nitems_read(i); + end_N = abs_N + (uint64_t)(noutput_items); + + std::vector<gr_tag_t> all_tags; + get_tags_in_range(all_tags, i, abs_N, end_N); + + std::vector<gr_tag_t>::iterator itr; + for(itr = all_tags.begin(); itr != all_tags.end(); itr++) { + d_stored_tags.push_back(*itr); + } + } + + // Source ID and key for any tag that might get applied from this block + pmt::pmt_t srcid = pmt::pmt_string_to_symbol(str.str()); + pmt::pmt_t key = pmt::pmt_string_to_symbol("seq"); + + // Work does nothing to the data stream; just copy all inputs to + // outputs Adds a new tag when the number of items read is a + // multiple of d_when + abs_N = nitems_written(0); + int noutputs = output_items.size(); + + for(int j = 0; j < noutput_items; j++) { + for(int i = 0; i < noutputs; i++) { + if(abs_N % d_when == 0) { + pmt::pmt_t value = pmt::pmt_from_uint64(d_tag_counter++); + add_item_tag(i, abs_N, key, value, srcid); + } + + // Sum all of the inputs together for each output. Just 'cause. + out = (float*)output_items[i]; + out[j] = 0; + for(int ins = 0; ins < ninputs; ins++) { + in = (const float*)input_items[ins]; + out[j] += in[j]; + } + } + abs_N++; + } + + return noutput_items; + } + + } /* namespace blocks */ +} /* namespace gr */ diff --git a/gr-blocks/lib/annotator_alltoall_impl.h b/gr-blocks/lib/annotator_alltoall_impl.h new file mode 100644 index 0000000000..24c21948bc --- /dev/null +++ b/gr-blocks/lib/annotator_alltoall_impl.h @@ -0,0 +1,56 @@ +/* -*- c++ -*- */ +/* + * Copyright 2010,2013 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_ANNOTATOR_ALLTOALL_IMPL_H +#define INCLUDED_GR_ANNOTATOR_ALLTOALL_IMPL_H + +#include <blocks/annotator_alltoall.h> + +namespace gr { + namespace blocks { + + class annotator_alltoall_impl : public annotator_alltoall + { + private: + size_t d_itemsize; + uint64_t d_when; + uint64_t d_tag_counter; + std::vector<gr_tag_t> d_stored_tags; + + public: + annotator_alltoall_impl(int when, size_t sizeof_stream_item); + ~annotator_alltoall_impl(); + + std::vector<gr_tag_t> data() const + { + return d_stored_tags; + } + + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } /* namespace blocks */ +} /* namespace gr */ + +#endif /* INCLUDED_GR_ANNOTATOR_ALLTOALL_IMPL_H */ diff --git a/gr-blocks/lib/annotator_raw_impl.cc b/gr-blocks/lib/annotator_raw_impl.cc new file mode 100644 index 0000000000..1b92523089 --- /dev/null +++ b/gr-blocks/lib/annotator_raw_impl.cc @@ -0,0 +1,112 @@ +/* -*- c++ -*- */ +/* + * Copyright 2010,2013 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 "annotator_raw_impl.h" +#include <gr_io_signature.h> +#include <string.h> +#include <iostream> +#include <iomanip> +#include <stdexcept> + +using namespace pmt; + +namespace gr { + namespace blocks { + + annotator_raw::sptr + annotator_raw::make(size_t sizeof_stream_item) + { + return gnuradio::get_initial_sptr + (new annotator_raw_impl(sizeof_stream_item)); + } + + annotator_raw_impl::annotator_raw_impl(size_t sizeof_stream_item) + : gr_sync_block("annotator_raw", + gr_make_io_signature(1, 1, sizeof_stream_item), + gr_make_io_signature(1, 1, sizeof_stream_item)), + d_itemsize(sizeof_stream_item) + { + set_tag_propagation_policy(TPP_ONE_TO_ONE); + set_relative_rate(1.0); + } + + void annotator_raw_impl::add_tag(uint64_t offset, pmt_t key, pmt_t val) + { + gruel::scoped_lock l(d_mutex); + + gr_tag_t tag; + tag.srcid = pmt::pmt_intern(name()); + tag.key = key; + tag.value = val; + tag.offset = offset; + + // add our new tag + d_queued_tags.push_back(tag); + // make sure our tags are in offset order + std::sort(d_queued_tags.begin(), d_queued_tags.end(), + gr_tag_t::offset_compare); + // make sure we are not adding an item in the past! + if(tag.offset > nitems_read(0)) { + throw std::runtime_error("annotator_raw::add_tag: item added too far in the past\n."); + } + } + + annotator_raw_impl::~annotator_raw_impl() + { + } + + int + annotator_raw_impl::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + gruel::scoped_lock l(d_mutex); + + const char *in = (const char*)input_items[0]; + char *out = (char*)output_items[0]; + + uint64_t start_N = nitems_read(0); + uint64_t end_N = start_N + (uint64_t)(noutput_items); + + // locate queued tags that fall in this range and insert them when appropriate + std::vector<gr_tag_t>::iterator i = d_queued_tags.begin(); + while( i != d_queued_tags.end() ) { + if( (*i).offset >= start_N && (*i).offset < end_N) { + add_item_tag(0, (*i).offset,(*i).key, (*i).value, (*i).srcid); + i = d_queued_tags.erase(i); + } + else { + break; + } + } + + // copy data across + memcpy(out, in, noutput_items*d_itemsize); + return noutput_items; + } + + } /* namespace blocks */ +} /* namespace gr */ diff --git a/gr-blocks/lib/annotator_raw_impl.h b/gr-blocks/lib/annotator_raw_impl.h new file mode 100644 index 0000000000..2e349bfe33 --- /dev/null +++ b/gr-blocks/lib/annotator_raw_impl.h @@ -0,0 +1,54 @@ +/* -*- c++ -*- */ +/* + * Copyright 2010,2013 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_ANNOTATOR_RAW_IMPL_H +#define INCLUDED_GR_ANNOTATOR_RAW_IMPL_H + +#include <blocks/annotator_raw.h> +#include <gruel/thread.h> + +namespace gr { + namespace blocks { + + class annotator_raw_impl : public annotator_raw + { + private: + size_t d_itemsize; + std::vector<gr_tag_t> d_queued_tags; + gruel::mutex d_mutex; + + public: + annotator_raw_impl(size_t sizeof_stream_item); + ~annotator_raw_impl(); + + // insert a tag to be added + void add_tag(uint64_t offset, pmt::pmt_t key, pmt::pmt_t val); + + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } /* namespace blocks */ +} /* namespace gr */ + +#endif /* INCLUDED_GR_ANNOTATOR_RAW_IMPL_H */ diff --git a/gr-blocks/lib/copy_impl.cc b/gr-blocks/lib/copy_impl.cc new file mode 100644 index 0000000000..f489b03c0c --- /dev/null +++ b/gr-blocks/lib/copy_impl.cc @@ -0,0 +1,82 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006,2009,2013 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 "copy_impl.h" +#include <gr_io_signature.h> +#include <string.h> + +namespace gr { + namespace blocks { + + copy::sptr + copy::make(size_t itemsize) + { + return gnuradio::get_initial_sptr + (new copy_impl(itemsize)); + } + + copy_impl::copy_impl(size_t itemsize) + : gr_block("copy", + gr_make_io_signature(1, 1, itemsize), + gr_make_io_signature(1, 1, itemsize)), + d_itemsize(itemsize), + d_enabled(true) + { + } + + copy_impl::~copy_impl() + { + } + + bool + copy_impl::check_topology(int ninputs, int noutputs) + { + return ninputs == noutputs; + } + + int + copy_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]; + + int n = std::min<int>(ninput_items[0], noutput_items); + int j = 0; + + if(d_enabled) { + memcpy(out, in, n*d_itemsize); + j = n; + } + + consume_each(n); + return j; + } + + } /* namespace blocks */ +} /* namespace gr */ diff --git a/gr-blocks/lib/copy_impl.h b/gr-blocks/lib/copy_impl.h new file mode 100644 index 0000000000..f462ffebdc --- /dev/null +++ b/gr-blocks/lib/copy_impl.h @@ -0,0 +1,55 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006,2009,2013 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_COPY_IMPL_H +#define INCLUDED_GR_COPY_IMPL_H + +#include <blocks/copy.h> + +namespace gr { + namespace blocks { + + class copy_impl : public copy + { + private: + size_t d_itemsize; + bool d_enabled; + + public: + copy_impl(size_t itemsize); + ~copy_impl(); + + bool check_topology(int ninputs, int noutputs); + + void set_enabled(bool enable) { d_enabled = enable; } + bool enabled() const { return d_enabled;} + + 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_COPY_IMPL_H */ diff --git a/gr-blocks/lib/endian_swap_impl.cc b/gr-blocks/lib/endian_swap_impl.cc new file mode 100644 index 0000000000..7e67c30147 --- /dev/null +++ b/gr-blocks/lib/endian_swap_impl.cc @@ -0,0 +1,110 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2010,2012,2013 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 "endian_swap_impl.h" +#include <gr_io_signature.h> +#include <volk/volk.h> + +namespace gr { + namespace blocks { + + endian_swap::sptr + endian_swap::make(size_t item_size_bytes) + { + return gnuradio::get_initial_sptr + (new endian_swap_impl(item_size_bytes)); + } + + endian_swap_impl::endian_swap_impl (size_t item_size_bytes) + : gr_sync_block("endian_swap_impl", + gr_make_io_signature(1, 1, item_size_bytes), + gr_make_io_signature(1, 1, item_size_bytes)) + { + const int alignment_multiple = volk_get_alignment(); + set_alignment(std::max(1, alignment_multiple)); + } + + endian_swap_impl::~endian_swap_impl() + { + } + + int + endian_swap_impl::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + const char *in = (const char*)input_items[0]; + char *out = (char*)output_items[0]; + + int nbytes(output_signature()->sizeof_stream_item(0)); + if(is_unaligned()) { + switch(nbytes){ + case 1: + memcpy(out,in,noutput_items); + break; + case 2: + memcpy(out,in,2*noutput_items); + volk_16u_byteswap_u((uint16_t*)out,noutput_items); + break; + case 4: + memcpy(out,in,4*noutput_items); + volk_32u_byteswap_u((uint32_t*)out,noutput_items); + break; + case 8: + memcpy(out,in,8*noutput_items); + volk_64u_byteswap_u((uint64_t*)out,noutput_items); + break; + default: + throw std::runtime_error("itemsize is not valid for endian_swap!"); + } + } + else { + switch(nbytes) { + case 1: + memcpy(out,in,noutput_items); + break; + case 2: + memcpy(out,in,2*noutput_items); + volk_16u_byteswap_a((uint16_t*)out,noutput_items); + break; + case 4: + memcpy(out,in,4*noutput_items); + volk_32u_byteswap_a((uint32_t*)out,noutput_items); + break; + case 8: + memcpy(out,in,8*noutput_items); + volk_64u_byteswap_a((uint64_t*)out,noutput_items); + break; + default: + throw std::runtime_error("itemsize is not valid for endian_swap!"); + } + } + + return noutput_items; + } + + } /* namespace blocks */ +} /* namespace gr */ diff --git a/gr-blocks/lib/endian_swap_impl.h b/gr-blocks/lib/endian_swap_impl.h new file mode 100644 index 0000000000..517df44f17 --- /dev/null +++ b/gr-blocks/lib/endian_swap_impl.h @@ -0,0 +1,48 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2012,2013 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_ENDIAN_SWAP_IMPL_H +#define INCLUDED_GR_ENDIAN_SWAP_IMPL_H + +#include <blocks/endian_swap.h> + +namespace gr { + namespace blocks { + + class endian_swap_impl : public endian_swap + { + private: + size_t item_size_bytes; + + public: + endian_swap_impl(size_t item_size_bytes); + ~endian_swap_impl(); + + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } /* namespace blocks */ +} /* namespace gr */ + +#endif /* INCLUDED_GR_ENDIAN_SWAP_IMPL_H */ diff --git a/gr-blocks/lib/head_impl.cc b/gr-blocks/lib/head_impl.cc new file mode 100644 index 0000000000..7dfa36607c --- /dev/null +++ b/gr-blocks/lib/head_impl.cc @@ -0,0 +1,75 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2009,2013 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 "head_impl.h" +#include <gr_io_signature.h> +#include <string.h> + +namespace gr { + namespace blocks { + + head::sptr + head::make(size_t sizeof_stream_item, uint64_t nitems) + { + return gnuradio::get_initial_sptr + (new head_impl(sizeof_stream_item, nitems)); + } + + head_impl::head_impl(size_t sizeof_stream_item, uint64_t nitems) + : gr_sync_block("head", + gr_make_io_signature(1, 1, sizeof_stream_item), + gr_make_io_signature(1, 1, sizeof_stream_item)), + d_nitems(nitems), d_ncopied_items(0) + { + } + + head_impl::~head_impl() + { + } + + int + head_impl::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + if(d_ncopied_items >= d_nitems) + return -1; // Done! + + unsigned n = std::min(d_nitems - d_ncopied_items, + (uint64_t)noutput_items); + + if(n == 0) + return 0; + + memcpy(output_items[0], input_items[0], + n * input_signature()->sizeof_stream_item (0)); + d_ncopied_items += n; + + return n; + } + + } /* namespace blocks */ +} /* namespace gr */ diff --git a/gr-blocks/lib/head_impl.h b/gr-blocks/lib/head_impl.h new file mode 100644 index 0000000000..a56acfbb27 --- /dev/null +++ b/gr-blocks/lib/head_impl.h @@ -0,0 +1,52 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2009,2012,2013 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_HEAD_IMPL_H +#define INCLUDED_GR_HEAD_IMPL_H + +#include <blocks/head.h> + +namespace gr { + namespace blocks { + + class head_impl : public head + { + private: + uint64_t d_nitems; + uint64_t d_ncopied_items; + + public: + head_impl(size_t sizeof_stream_item, uint64_t nitems); + ~head_impl(); + + void reset() { d_ncopied_items = 0; } + void set_length(int nitems) { d_nitems = nitems; } + + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } /* namespace blocks */ +} /* namespace gr */ + +#endif /* INCLUDED_GR_HEAD_IMPL_H */ diff --git a/gr-blocks/lib/qa_block_tags.cc b/gr-blocks/lib/qa_block_tags.cc new file mode 100644 index 0000000000..93edc4695a --- /dev/null +++ b/gr-blocks/lib/qa_block_tags.cc @@ -0,0 +1,451 @@ +/* -*- c++ -*- */ +/* + * Copyright 2010,2013 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 <qa_block_tags.h> +#include <gr_block.h> +#include <gr_top_block.h> +#include <gr_null_source.h> +#include <gr_null_sink.h> +#include <gr_head.h> +#include <blocks/annotator_alltoall.h> +#include <blocks/annotator_1to1.h> +#include <gr_keep_one_in_n.h> +#include <filter/firdes.h> +#include <gr_tags.h> + + +// ---------------------------------------------------------------- + +using namespace pmt; + +// set to 1 to turn on debug output +// The debug output fully checks that the tags seen are what are expected. While +// this behavior currently works with our implementation, there is no guarentee +// that the tags will be coming in this specific order, so it's dangerous to +// rely on this as a test of the tag system working. We would really want to +// tags we know we should see and then test that they all occur once, but in no +// particular order. +#define QA_TAGS_DEBUG 0 + +void +qa_block_tags::t0() +{ + unsigned int N = 1000; + gr_top_block_sptr tb = gr_make_top_block("top"); + gr_block_sptr src (gr_make_null_source(sizeof(int))); + gr_block_sptr head (gr_make_head(sizeof(int), N)); + gr_block_sptr snk (gr_make_null_sink(sizeof(int))); + + tb->connect(src, 0, head, 0); + tb->connect(head, 0, snk, 0); + + //CPPUNIT_ASSERT_THROW(src->nitems_read(0), std::runtime_error); + //CPPUNIT_ASSERT_THROW(src->nitems_written(0), std::runtime_error); + CPPUNIT_ASSERT_EQUAL(src->nitems_read(0), (uint64_t)0); + CPPUNIT_ASSERT_EQUAL(src->nitems_written(0), (uint64_t)0); + + tb->run(); + + CPPUNIT_ASSERT_THROW(src->nitems_read(0), std::invalid_argument); + CPPUNIT_ASSERT(src->nitems_written(0) >= N); + CPPUNIT_ASSERT_EQUAL(snk->nitems_read(0), (uint64_t)1000); + CPPUNIT_ASSERT_THROW(snk->nitems_written(0), std::invalid_argument); +} + + +void +qa_block_tags::t1() +{ + int N = 40000; + gr_top_block_sptr tb = gr_make_top_block("top"); + gr_block_sptr src (gr_make_null_source(sizeof(int))); + gr_block_sptr head (gr_make_head(sizeof(int), N)); + gr::blocks::annotator_alltoall::sptr ann0(gr::blocks::annotator_alltoall::make(10000, sizeof(int))); + gr::blocks::annotator_alltoall::sptr ann1(gr::blocks::annotator_alltoall::make(10000, sizeof(int))); + gr::blocks::annotator_alltoall::sptr ann2(gr::blocks::annotator_alltoall::make(10000, sizeof(int))); + gr::blocks::annotator_alltoall::sptr ann3(gr::blocks::annotator_alltoall::make(10000, sizeof(int))); + gr::blocks::annotator_alltoall::sptr ann4(gr::blocks::annotator_alltoall::make(10000, sizeof(int))); + gr_block_sptr snk0 (gr_make_null_sink(sizeof(int))); + gr_block_sptr snk1 (gr_make_null_sink(sizeof(int))); + + tb->connect(src, 0, head, 0); + tb->connect(head, 0, ann0, 0); + + tb->connect(ann0, 0, ann1, 0); + tb->connect(ann0, 1, ann2, 0); + tb->connect(ann1, 0, ann3, 0); + tb->connect(ann2, 0, ann4, 0); + + tb->connect(ann3, 0, snk0, 0); + tb->connect(ann4, 0, snk1, 0); + + tb->run(); + + std::vector<gr_tag_t> tags0 = ann0->data(); + std::vector<gr_tag_t> tags3 = ann3->data(); + std::vector<gr_tag_t> tags4 = ann4->data(); + + // The first annotator does not receive any tags from the null sink upstream + CPPUNIT_ASSERT_EQUAL(tags0.size(), (size_t)0); + CPPUNIT_ASSERT_EQUAL(tags3.size(), (size_t)8); + CPPUNIT_ASSERT_EQUAL(tags4.size(), (size_t)8); + +#if QA_TAGS_DEBUG + // Kludge together the tags that we know should result from the above graph + std::stringstream str0, str1, str2; + str0 << ann0->name() << ann0->unique_id(); + str1 << ann1->name() << ann1->unique_id(); + str2 << ann2->name() << ann2->unique_id(); + + pmt_t expected_tags3[8]; + expected_tags3[0] = mp(pmt_from_uint64(0), mp(str1.str()), mp("seq"), mp(0)); + expected_tags3[1] = mp(pmt_from_uint64(0), mp(str0.str()), mp("seq"), mp(0)); + expected_tags3[2] = mp(pmt_from_uint64(10000), mp(str1.str()), mp("seq"), mp(1)); + expected_tags3[3] = mp(pmt_from_uint64(10000), mp(str0.str()), mp("seq"), mp(2)); + expected_tags3[4] = mp(pmt_from_uint64(20000), mp(str1.str()), mp("seq"), mp(2)); + expected_tags3[5] = mp(pmt_from_uint64(20000), mp(str0.str()), mp("seq"), mp(4)); + expected_tags3[6] = mp(pmt_from_uint64(30000), mp(str1.str()), mp("seq"), mp(3)); + expected_tags3[7] = mp(pmt_from_uint64(30000), mp(str0.str()), mp("seq"), mp(6)); + + pmt_t expected_tags4[8]; + expected_tags4[0] = mp(pmt_from_uint64(0), mp(str2.str()), mp("seq"), mp(0)); + expected_tags4[1] = mp(pmt_from_uint64(0), mp(str0.str()), mp("seq"), mp(1)); + expected_tags4[2] = mp(pmt_from_uint64(10000), mp(str2.str()), mp("seq"), mp(1)); + expected_tags4[3] = mp(pmt_from_uint64(10000), mp(str0.str()), mp("seq"), mp(3)); + expected_tags4[4] = mp(pmt_from_uint64(20000), mp(str2.str()), mp("seq"), mp(2)); + expected_tags4[5] = mp(pmt_from_uint64(20000), mp(str0.str()), mp("seq"), mp(5)); + expected_tags4[6] = mp(pmt_from_uint64(30000), mp(str2.str()), mp("seq"), mp(3)); + expected_tags4[7] = mp(pmt_from_uint64(30000), mp(str0.str()), mp("seq"), mp(7)); + + std::cout << std::endl << "qa_block_tags::t1" << std::endl; + + // For annotator 3, we know it gets tags from ann0 and ann1, test this + for(size_t i = 0; i < tags3.size(); i++) { + std::cout << "tags3[" << i << "] = " << tags3[i] << "\t\t" << expected_tags3[i] << std::endl; + CPPUNIT_ASSERT_EQUAL(pmt_write_string(tags3[i]), pmt_write_string(expected_tags3[i])); + } + + // For annotator 4, we know it gets tags from ann0 and ann2, test this + std::cout << std::endl; + for(size_t i = 0; i < tags4.size(); i++) { + std::cout << "tags4[" << i << "] = " << tags4[i] << "\t\t" << expected_tags4[i] << std::endl; + CPPUNIT_ASSERT_EQUAL(pmt_write_string(tags4[i]), pmt_write_string(expected_tags4[i])); + } +#endif +} + +void +qa_block_tags::t2 () +{ + int N = 40000; + gr_top_block_sptr tb = gr_make_top_block("top"); + gr_block_sptr src (gr_make_null_source(sizeof(int))); + gr_block_sptr head (gr_make_head(sizeof(int), N)); + gr::blocks::annotator_alltoall::sptr ann0(gr::blocks::annotator_alltoall::make(10000, sizeof(int))); + gr::blocks::annotator_alltoall::sptr ann1(gr::blocks::annotator_alltoall::make(10000, sizeof(int))); + gr::blocks::annotator_alltoall::sptr ann2(gr::blocks::annotator_alltoall::make(10000, sizeof(int))); + gr::blocks::annotator_alltoall::sptr ann3(gr::blocks::annotator_alltoall::make(10000, sizeof(int))); + gr::blocks::annotator_alltoall::sptr ann4(gr::blocks::annotator_alltoall::make(10000, sizeof(int))); + gr_block_sptr snk0 (gr_make_null_sink(sizeof(int))); + gr_block_sptr snk1 (gr_make_null_sink(sizeof(int))); + gr_block_sptr snk2 (gr_make_null_sink(sizeof(int))); + + tb->connect(src, 0, head, 0); + tb->connect(head, 0, ann0, 0); + + tb->connect(ann0, 0, ann1, 0); + tb->connect(ann0, 1, ann1, 1); + tb->connect(ann1, 0, ann2, 0); + tb->connect(ann1, 1, ann3, 0); + tb->connect(ann1, 2, ann4, 0); + + tb->connect(ann2, 0, snk0, 0); + tb->connect(ann3, 0, snk1, 0); + tb->connect(ann4, 0, snk2, 0); + + tb->run(); + + std::vector<gr_tag_t> tags0 = ann0->data(); + std::vector<gr_tag_t> tags1 = ann1->data(); + std::vector<gr_tag_t> tags2 = ann2->data(); + std::vector<gr_tag_t> tags3 = ann4->data(); + std::vector<gr_tag_t> tags4 = ann4->data(); + + // The first annotator does not receive any tags from the null sink upstream + CPPUNIT_ASSERT_EQUAL(tags0.size(), (size_t)0); + CPPUNIT_ASSERT_EQUAL(tags1.size(), (size_t)8); + + // Make sure the rest all have 12 tags + CPPUNIT_ASSERT_EQUAL(tags2.size(), (size_t)12); + CPPUNIT_ASSERT_EQUAL(tags3.size(), (size_t)12); + CPPUNIT_ASSERT_EQUAL(tags4.size(), (size_t)12); + + +#if QA_TAGS_DEBUG + // Kludge together the tags that we know should result from the above graph + std::stringstream str0, str1; + str0 << ann0->name() << ann0->unique_id(); + str1 << ann1->name() << ann1->unique_id(); + + pmt_t expected_tags2[12]; + expected_tags2[0] = mp(pmt_from_uint64(0), mp(str1.str()), mp("seq"), mp(0)); + expected_tags2[1] = mp(pmt_from_uint64(0), mp(str0.str()), mp("seq"), mp(0)); + expected_tags2[2] = mp(pmt_from_uint64(0), mp(str0.str()), mp("seq"), mp(1)); + expected_tags2[3] = mp(pmt_from_uint64(10000), mp(str1.str()), mp("seq"), mp(3)); + expected_tags2[4] = mp(pmt_from_uint64(10000), mp(str0.str()), mp("seq"), mp(2)); + expected_tags2[5] = mp(pmt_from_uint64(10000), mp(str0.str()), mp("seq"), mp(3)); + expected_tags2[6] = mp(pmt_from_uint64(20000), mp(str1.str()), mp("seq"), mp(6)); + expected_tags2[7] = mp(pmt_from_uint64(20000), mp(str0.str()), mp("seq"), mp(4)); + expected_tags2[8] = mp(pmt_from_uint64(20000), mp(str0.str()), mp("seq"), mp(5)); + expected_tags2[9] = mp(pmt_from_uint64(30000), mp(str1.str()), mp("seq"), mp(9)); + expected_tags2[10] = mp(pmt_from_uint64(30000), mp(str0.str()), mp("seq"), mp(6)); + expected_tags2[11] = mp(pmt_from_uint64(30000), mp(str0.str()), mp("seq"), mp(7)); + + pmt_t expected_tags4[12]; + expected_tags4[0] = mp(pmt_from_uint64(0), mp(str1.str()), mp("seq"), mp(2)); + expected_tags4[1] = mp(pmt_from_uint64(0), mp(str0.str()), mp("seq"), mp(0)); + expected_tags4[2] = mp(pmt_from_uint64(0), mp(str0.str()), mp("seq"), mp(1)); + expected_tags4[3] = mp(pmt_from_uint64(10000), mp(str1.str()), mp("seq"), mp(5)); + expected_tags4[4] = mp(pmt_from_uint64(10000), mp(str0.str()), mp("seq"), mp(2)); + expected_tags4[5] = mp(pmt_from_uint64(10000), mp(str0.str()), mp("seq"), mp(3)); + expected_tags4[6] = mp(pmt_from_uint64(20000), mp(str1.str()), mp("seq"), mp(8)); + expected_tags4[7] = mp(pmt_from_uint64(20000), mp(str0.str()), mp("seq"), mp(4)); + expected_tags4[8] = mp(pmt_from_uint64(20000), mp(str0.str()), mp("seq"), mp(5)); + expected_tags4[9] = mp(pmt_from_uint64(30000), mp(str1.str()), mp("seq"), mp(11)); + expected_tags4[10] = mp(pmt_from_uint64(30000), mp(str0.str()), mp("seq"), mp(6)); + expected_tags4[11] = mp(pmt_from_uint64(30000), mp(str0.str()), mp("seq"), mp(7)); + + std::cout << std::endl << "qa_block_tags::t2" << std::endl; + + // For annotator[2-4], we know it gets tags from ann0 and ann1 + // but the tags from the different outputs of ann1 are different for each. + // Just testing ann2 and ann4; if they are correct it would be + // inconceivable for ann3 to have it wrong. + for(size_t i = 0; i < tags2.size(); i++) { + std::cout << "tags2[" << i << "] = " << tags2[i] << "\t\t" << expected_tags2[i] << std::endl; + CPPUNIT_ASSERT_EQUAL(pmt_write_string(tags2[i]), pmt_write_string(expected_tags2[i])); + } + + std::cout << std::endl; + for(size_t i = 0; i < tags4.size(); i++) { + std::cout << "tags2[" << i << "] = " << tags4[i] << "\t\t" << expected_tags4[i] << std::endl; + CPPUNIT_ASSERT_EQUAL(pmt_write_string(tags4[i]), pmt_write_string(expected_tags4[i])); + } +#endif +} + + +void +qa_block_tags::t3() +{ + int N = 40000; + gr_top_block_sptr tb = gr_make_top_block("top"); + gr_block_sptr src (gr_make_null_source(sizeof(int))); + gr_block_sptr head (gr_make_head(sizeof(int), N)); + gr::blocks::annotator_1to1::sptr ann0 (gr::blocks::annotator_1to1::make(10000, sizeof(int))); + gr::blocks::annotator_alltoall::sptr ann1 (gr::blocks::annotator_alltoall::make(10000, sizeof(int))); + gr::blocks::annotator_alltoall::sptr ann2 (gr::blocks::annotator_alltoall::make(10000, sizeof(int))); + gr::blocks::annotator_1to1::sptr ann3 (gr::blocks::annotator_1to1::make(10000, sizeof(int))); + gr::blocks::annotator_1to1::sptr ann4 (gr::blocks::annotator_1to1::make(10000, sizeof(int))); + gr_block_sptr snk0 (gr_make_null_sink(sizeof(int))); + gr_block_sptr snk1 (gr_make_null_sink(sizeof(int))); + + tb->connect(src, 0, head, 0); + tb->connect(head, 0, ann0, 0); + tb->connect(head, 0, ann0, 1); + + tb->connect(ann0, 0, ann1, 0); + tb->connect(ann0, 1, ann2, 0); + tb->connect(ann1, 0, ann3, 0); + tb->connect(ann2, 0, ann4, 0); + + tb->connect(ann3, 0, snk0, 0); + tb->connect(ann4, 0, snk1, 0); + + tb->run(); + + + std::vector<gr_tag_t> tags0 = ann0->data(); + std::vector<gr_tag_t> tags3 = ann3->data(); + std::vector<gr_tag_t> tags4 = ann4->data(); + + // The first annotator does not receive any tags from the null sink upstream + CPPUNIT_ASSERT_EQUAL(tags0.size(), (size_t)0); + CPPUNIT_ASSERT_EQUAL(tags3.size(), (size_t)8); + CPPUNIT_ASSERT_EQUAL(tags4.size(), (size_t)8); + +#if QA_TAGS_DEBUG + // Kludge together the tags that we know should result from the above graph + std::stringstream str0, str1, str2; + str0 << ann0->name() << ann0->unique_id(); + str1 << ann1->name() << ann1->unique_id(); + str2 << ann2->name() << ann2->unique_id(); + + pmt_t expected_tags3[8]; + expected_tags3[0] = mp(pmt_from_uint64(0), mp(str1.str()), mp("seq"), mp(0)); + expected_tags3[1] = mp(pmt_from_uint64(0), mp(str0.str()), mp("seq"), mp(0)); + expected_tags3[2] = mp(pmt_from_uint64(10000), mp(str1.str()), mp("seq"), mp(1)); + expected_tags3[3] = mp(pmt_from_uint64(10000), mp(str0.str()), mp("seq"), mp(2)); + expected_tags3[4] = mp(pmt_from_uint64(20000), mp(str1.str()), mp("seq"), mp(2)); + expected_tags3[5] = mp(pmt_from_uint64(20000), mp(str0.str()), mp("seq"), mp(4)); + expected_tags3[6] = mp(pmt_from_uint64(30000), mp(str1.str()), mp("seq"), mp(3)); + expected_tags3[7] = mp(pmt_from_uint64(30000), mp(str0.str()), mp("seq"), mp(6)); + + pmt_t expected_tags4[8]; + expected_tags4[0] = mp(pmt_from_uint64(0), mp(str2.str()), mp("seq"), mp(0)); + expected_tags4[1] = mp(pmt_from_uint64(0), mp(str0.str()), mp("seq"), mp(1)); + expected_tags4[2] = mp(pmt_from_uint64(10000), mp(str2.str()), mp("seq"), mp(1)); + expected_tags4[3] = mp(pmt_from_uint64(10000), mp(str0.str()), mp("seq"), mp(3)); + expected_tags4[4] = mp(pmt_from_uint64(20000), mp(str2.str()), mp("seq"), mp(2)); + expected_tags4[5] = mp(pmt_from_uint64(20000), mp(str0.str()), mp("seq"), mp(5)); + expected_tags4[6] = mp(pmt_from_uint64(30000), mp(str2.str()), mp("seq"), mp(3)); + expected_tags4[7] = mp(pmt_from_uint64(30000), mp(str0.str()), mp("seq"), mp(7)); + + std::cout << std::endl << "qa_block_tags::t3" << std::endl; + + // For annotator 3, we know it gets tags from ann0 and ann1, test this + for(size_t i = 0; i < tags3.size(); i++) { + std::cout << "tags3[" << i << "] = " << tags3[i] << "\t\t" << expected_tags3[i] << std::endl; + CPPUNIT_ASSERT_EQUAL(pmt_write_string(tags3[i]), pmt_write_string(expected_tags3[i])); + } + + // For annotator 4, we know it gets tags from ann0 and ann2, test this + std::cout << std::endl; + for(size_t i = 0; i < tags4.size(); i++) { + std::cout << "tags4[" << i << "] = " << tags4[i] << "\t\t" << expected_tags4[i] << std::endl; + CPPUNIT_ASSERT_EQUAL(pmt_write_string(tags4[i]), pmt_write_string(expected_tags4[i])); + } +#endif +} + + +void +qa_block_tags::t4() +{ + int N = 40000; + gr_top_block_sptr tb = gr_make_top_block("top"); + gr_block_sptr src (gr_make_null_source(sizeof(int))); + gr_block_sptr head (gr_make_head(sizeof(int), N)); + gr::blocks::annotator_1to1::sptr ann0(gr::blocks::annotator_1to1::make(10000, sizeof(int))); + gr::blocks::annotator_1to1::sptr ann1(gr::blocks::annotator_1to1::make(10000, sizeof(int))); + gr::blocks::annotator_1to1::sptr ann2(gr::blocks::annotator_1to1::make(10000, sizeof(int))); + gr_block_sptr snk0 (gr_make_null_sink(sizeof(int))); + gr_block_sptr snk1 (gr_make_null_sink(sizeof(int))); + + // using 1-to-1 tag propagation without having equal number of + // ins and outs. Make sure this works; will just exit run early. + tb->connect(src, 0, head, 0); + tb->connect(head, 0, ann0, 0); + tb->connect(ann0, 0, ann1, 0); + tb->connect(ann0, 1, ann2, 0); + tb->connect(ann1, 0, snk0, 0); + tb->connect(ann2, 0, snk1, 0); + + std::cerr << std::endl + << "NOTE: This is supposed to produce an error from gr_block_executor" + << std::endl; + tb->run(); +} + + +void +qa_block_tags::t5() +{ + int N = 40000; + gr_top_block_sptr tb = gr_make_top_block("top"); + gr_block_sptr src (gr_make_null_source(sizeof(float))); + gr_block_sptr head (gr_make_head(sizeof(float), N)); + gr::blocks::annotator_alltoall::sptr ann0(gr::blocks::annotator_alltoall::make(10000, sizeof(float))); + gr::blocks::annotator_alltoall::sptr ann1(gr::blocks::annotator_alltoall::make(10000, sizeof(float))); + gr::blocks::annotator_alltoall::sptr ann2(gr::blocks::annotator_alltoall::make(1000, sizeof(float))); + gr_block_sptr snk0 (gr_make_null_sink(sizeof(float))); + + // Rate change blocks + gr_keep_one_in_n_sptr dec10 (gr_make_keep_one_in_n(sizeof(float), 10)); + + tb->connect(src, 0, head, 0); + tb->connect(head, 0, ann0, 0); + tb->connect(ann0, 0, ann1, 0); + tb->connect(ann1, 0, dec10, 0); + tb->connect(dec10, 0, ann2, 0); + tb->connect(ann2, 0, snk0, 0); + + tb->run(); + + std::vector<gr_tag_t> tags0 = ann0->data(); + std::vector<gr_tag_t> tags1 = ann1->data(); + std::vector<gr_tag_t> tags2 = ann2->data(); + + // The first annotator does not receive any tags from the null sink upstream + CPPUNIT_ASSERT_EQUAL(tags0.size(), (size_t)0); + CPPUNIT_ASSERT_EQUAL(tags1.size(), (size_t)4); + CPPUNIT_ASSERT_EQUAL(tags2.size(), (size_t)8); + + +#if QA_TAGS_DEBUG + // Kludge together the tags that we know should result from the above graph + std::stringstream str0, str1, str2; + str0 << ann0->name() << ann0->unique_id(); + str1 << ann1->name() << ann1->unique_id(); + str2 << ann2->name() << ann2->unique_id(); + + pmt_t expected_tags1[5]; + expected_tags1[0] = mp(pmt_from_uint64(0), mp(str0.str()), mp("seq"), mp(0)); + expected_tags1[1] = mp(pmt_from_uint64(10000), mp(str0.str()), mp("seq"), mp(1)); + expected_tags1[2] = mp(pmt_from_uint64(20000), mp(str0.str()), mp("seq"), mp(2)); + expected_tags1[3] = mp(pmt_from_uint64(30000), mp(str0.str()), mp("seq"), mp(3)); + + pmt_t expected_tags2[10]; + expected_tags2[0] = mp(pmt_from_uint64(0), mp(str1.str()), mp("seq"), mp(0)); + expected_tags2[1] = mp(pmt_from_uint64(0), mp(str0.str()), mp("seq"), mp(0)); + expected_tags2[2] = mp(pmt_from_uint64(1000), mp(str1.str()), mp("seq"), mp(1)); + expected_tags2[3] = mp(pmt_from_uint64(1000), mp(str0.str()), mp("seq"), mp(1)); + expected_tags2[4] = mp(pmt_from_uint64(2000), mp(str1.str()), mp("seq"), mp(2)); + expected_tags2[5] = mp(pmt_from_uint64(2000), mp(str0.str()), mp("seq"), mp(2)); + expected_tags2[6] = mp(pmt_from_uint64(3000), mp(str1.str()), mp("seq"), mp(3)); + expected_tags2[7] = mp(pmt_from_uint64(3000), mp(str0.str()), mp("seq"), mp(3)); + expected_tags2[8] = mp(pmt_from_uint64(4000), mp(str1.str()), mp("seq"), mp(4)); + expected_tags2[9] = mp(pmt_from_uint64(4000), mp(str0.str()), mp("seq"), mp(4)); + + std::cout << std::endl << "qa_block_tags::t5" << std::endl; + + // annotator 1 gets tags from annotator 0 + std::cout << "tags1.size(): " << tags1.size() << std::endl; + for(size_t i = 0; i < tags1.size(); i++) { + std::cout << "tags1[" << i << "] = " << tags1[i] << "\t\t" << expected_tags1[i] << std::endl; + CPPUNIT_ASSERT_EQUAL(pmt_write_string(tags1[i]), pmt_write_string(expected_tags1[i])); + } + + // annotator 2 gets tags from annotators 0 and 1 + std::cout << std::endl; + std::cout << "tags2.size(): " << tags2.size() << std::endl; + for(size_t i = 0; i < tags2.size(); i++) { + std::cout << "tags2[" << i << "] = " << tags2[i] << "\t\t" << expected_tags2[i] << std::endl; + CPPUNIT_ASSERT_EQUAL(pmt_write_string(tags2[i]), pmt_write_string(expected_tags2[i])); + } +#endif +} + diff --git a/gr-blocks/lib/qa_block_tags.h b/gr-blocks/lib/qa_block_tags.h new file mode 100644 index 0000000000..83bebe23f6 --- /dev/null +++ b/gr-blocks/lib/qa_block_tags.h @@ -0,0 +1,50 @@ +/* -*- c++ -*- */ +/* + * Copyright 2010,2013 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_QA_BLOCK_TAGS_H +#define INCLUDED_QA_BLOCK_TAGS_H + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/TestCase.h> +#include <stdexcept> + +class qa_block_tags : public CppUnit::TestCase +{ + CPPUNIT_TEST_SUITE(qa_block_tags); + CPPUNIT_TEST(t0); + CPPUNIT_TEST(t1); + CPPUNIT_TEST(t2); + CPPUNIT_TEST(t3); + CPPUNIT_TEST(t4); + CPPUNIT_TEST(t5); + CPPUNIT_TEST_SUITE_END(); + + private: + void t0(); + void t1(); + void t2(); + void t3(); + void t4(); + void t5(); +}; + +#endif /* INCLUDED_QA_BLOCK_TAGS_H */ diff --git a/gr-blocks/lib/qa_blocks.cc b/gr-blocks/lib/qa_blocks.cc index fbae11d264..ebf5d3c349 100644 --- a/gr-blocks/lib/qa_blocks.cc +++ b/gr-blocks/lib/qa_blocks.cc @@ -26,18 +26,22 @@ */ #include <qa_blocks.h> +#include <qa_block_tags.h> #include <qa_fxpt.h> #include <qa_fxpt_nco.h> #include <qa_fxpt_vco.h> +#include <qa_rotator.h> CppUnit::TestSuite * qa_gr_blocks::suite() { CppUnit::TestSuite *s = new CppUnit::TestSuite("gr-blocks"); + s->addTest(qa_block_tags::suite()); s->addTest(qa_fxpt::suite()); s->addTest(qa_fxpt_nco::suite()); s->addTest(qa_fxpt_vco::suite()); + s->addTest(qa_rotator::suite()); return s; } diff --git a/gr-blocks/lib/qa_rotator.cc b/gr-blocks/lib/qa_rotator.cc new file mode 100644 index 0000000000..86bbdd5282 --- /dev/null +++ b/gr-blocks/lib/qa_rotator.cc @@ -0,0 +1,75 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002,2013 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 <gruel/attributes.h> +#include <cppunit/TestAssert.h> +#include <qa_rotator.h> +#include <blocks/rotator.h> +#include <stdio.h> +#include <cmath> +#include <gr_expj.h> + +// error vector magnitude +__GR_ATTR_UNUSED static float +error_vector_mag(gr_complex a, gr_complex b) +{ + return abs(a-b); +} + +void +qa_rotator::t1() +{ + static const unsigned int N = 100000; + + gr::blocks::rotator r; + + double phase_incr = 2*M_PI / 1003; + double phase = 0; + + // Old code: We increment then return the rotated value, thus we + // need to start one tick back r.set_phase(gr_complex(1,0) * + // conj(gr_expj(phase_incr))); + + r.set_phase(gr_complex(1,0)); + r.set_phase_incr(gr_expj(phase_incr)); + + for(unsigned i = 0; i < N; i++) { + gr_complex expected = gr_expj(phase); + gr_complex actual = r.rotate(gr_complex(1, 0)); + +#if 0 + float evm = error_vector_mag(expected, actual); + printf("[%6d] expected: (%8.6f, %8.6f) actual: (%8.6f, %8.6f) evm: %8.6f\n", + i, expected.real(), expected.imag(), actual.real(), actual.imag(), evm); +#endif + + CPPUNIT_ASSERT_COMPLEXES_EQUAL(expected, actual, 0.0001); + + phase += phase_incr; + if(phase >= 2*M_PI) + phase -= 2*M_PI; + } +} diff --git a/gr-blocks/lib/qa_rotator.h b/gr-blocks/lib/qa_rotator.h new file mode 100644 index 0000000000..575ea506c7 --- /dev/null +++ b/gr-blocks/lib/qa_rotator.h @@ -0,0 +1,39 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008,2013 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 _QA_GR_ROTATOR_H_ +#define _QA_GR_ROTATOR_H_ + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/TestCase.h> + +class qa_rotator : public CppUnit::TestCase +{ + CPPUNIT_TEST_SUITE(qa_rotator); + CPPUNIT_TEST(t1); + CPPUNIT_TEST_SUITE_END(); + + private: + void t1(); +}; + +#endif /* _QA_GR_ROTATOR_H_ */ diff --git a/gr-blocks/lib/skiphead_impl.cc b/gr-blocks/lib/skiphead_impl.cc new file mode 100644 index 0000000000..feb39eb8f4 --- /dev/null +++ b/gr-blocks/lib/skiphead_impl.cc @@ -0,0 +1,93 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,2007,2010,2013 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 "skiphead_impl.h" +#include <gr_io_signature.h> +#include <string.h> + +namespace gr { + namespace blocks { + + skiphead::sptr + skiphead::make(size_t itemsize, uint64_t nitems_to_skip) + { + return gnuradio::get_initial_sptr + (new skiphead_impl(itemsize, nitems_to_skip)); + } + + skiphead_impl::skiphead_impl(size_t itemsize, uint64_t nitems_to_skip) + : gr_block("skiphead", + gr_make_io_signature(1, 1, itemsize), + gr_make_io_signature(1, 1, itemsize)), + d_nitems_to_skip(nitems_to_skip), d_nitems(0) + { + } + + skiphead_impl::~skiphead_impl() + { + } + + int + skiphead_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 char *in = (const char*)input_items[0]; + char *out = (char*)output_items[0]; + + int ninput_items = std::min(ninput_items_[0], noutput_items); + int ii = 0; // input index + + while (ii < ninput_items) { + uint64_t ni_total = ii + d_nitems; // total items processed so far + if(ni_total < d_nitems_to_skip) { // need to skip some more + + int n_to_skip = (int)std::min(d_nitems_to_skip - ni_total, + (uint64_t)(ninput_items - ii)); + ii += n_to_skip; + } + + else { // nothing left to skip. copy away + int n_to_copy = ninput_items - ii; + if(n_to_copy > 0) { + size_t itemsize = output_signature()->sizeof_stream_item(0); + memcpy(out, in + (ii*itemsize), n_to_copy*itemsize); + } + + d_nitems += ninput_items; + consume_each(ninput_items); + return n_to_copy; + } + } + + d_nitems += ninput_items; + consume_each(ninput_items); + return 0; + } + + } /* namespace blocks */ +} /* namespace gr */ diff --git a/gr-blocks/lib/skiphead_impl.h b/gr-blocks/lib/skiphead_impl.h new file mode 100644 index 0000000000..d8e0870cb1 --- /dev/null +++ b/gr-blocks/lib/skiphead_impl.h @@ -0,0 +1,50 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,2013 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_SKIPHEAD_IMPL_H +#define INCLUDED_GR_SKIPHEAD_IMPL_H + +#include <blocks/skiphead.h> + +namespace gr { + namespace blocks { + + class skiphead_impl : public skiphead + { + private: + uint64_t d_nitems_to_skip; + uint64_t d_nitems; // total items seen + + public: + skiphead_impl(size_t itemsize, uint64_t nitems_to_skip); + ~skiphead_impl(); + + 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_SKIPHEAD_IMPL_H */ diff --git a/gr-blocks/lib/vector_insert_X_impl.cc.t b/gr-blocks/lib/vector_insert_X_impl.cc.t new file mode 100644 index 0000000000..adf31fe05a --- /dev/null +++ b/gr-blocks/lib/vector_insert_X_impl.cc.t @@ -0,0 +1,109 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 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. + */ + +// @WARNING@ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <@NAME_IMPL@.h> +#include <algorithm> +#include <gr_io_signature.h> +#include <stdexcept> +#include <stdio.h> + +namespace gr { + namespace blocks { + + @NAME@::sptr + @NAME@::make(const std::vector<@TYPE@> &data, int periodicity, int offset) + { + return gnuradio::get_initial_sptr + (new @NAME_IMPL@(data, periodicity, offset)); + } + + @NAME_IMPL@::@NAME_IMPL@(const std::vector<@TYPE@> &data, + int periodicity, int offset) + : gr_block("@BASE_NAME@", + gr_make_io_signature(1, 1, sizeof(@TYPE@)), + gr_make_io_signature(1, 1, sizeof(@TYPE@))), + d_data(data), + d_offset(offset), + d_periodicity(periodicity) + { + //printf("INITIAL: periodicity = %d, offset = %d\n", periodicity, offset); + // some sanity checks + assert(offset < periodicity); + assert(offset >= 0); + assert((size_t)periodicity > data.size()); + } + + @NAME_IMPL@::~@NAME_IMPL@() + {} + + int + @NAME_IMPL@::general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + @TYPE@ *out = (@TYPE@ *)output_items[0]; + const @TYPE@ *in = (const @TYPE@ *)input_items[0]; + + int ii(0), oo(0); + + while((oo < noutput_items) && (ii < ninput_items[0])) { + //printf("oo = %d, ii = %d, d_offset = %d, noutput_items = %d, ninput_items[0] = %d", oo, ii, d_offset, noutput_items, ninput_items[0]); + //printf(", d_periodicity = %d\n", d_periodicity); + + if(d_offset >= ((int)d_data.size())) { // if we are in the copy region + int max_copy = std::min(std::min(noutput_items - oo, ninput_items[0] - ii), + d_periodicity - d_offset); + //printf("copy %d from input\n", max_copy); + memcpy( &out[oo], &in[ii], sizeof(@TYPE@)*max_copy ); + //printf(" * memcpy returned.\n"); + ii += max_copy; + oo += max_copy; + d_offset = (d_offset + max_copy)%d_periodicity; + } + else { // if we are in the insertion region + int max_copy = std::min(noutput_items - oo, ((int)d_data.size()) - d_offset); + //printf("copy %d from d_data[%d] to out[%d]\n", max_copy, d_offset, oo); + memcpy(&out[oo], &d_data[d_offset], sizeof(@TYPE@)*max_copy); + //printf(" * memcpy returned.\n"); + oo += max_copy; + d_offset = (d_offset + max_copy)%d_periodicity; + //printf(" ## (inelse) oo = %d, d_offset = %d\n", oo, d_offset); + } + + //printf(" # exit else, on to next loop.\n"); + } + //printf(" # got out of loop\n"); + + //printf("consume = %d, produce = %d\n", ii, oo); + consume_each(ii); + return oo; + } + + } /* namespace blocks */ +} /* namespace gr */ diff --git a/gr-blocks/lib/vector_insert_X_impl.h.t b/gr-blocks/lib/vector_insert_X_impl.h.t new file mode 100644 index 0000000000..f447ef1e80 --- /dev/null +++ b/gr-blocks/lib/vector_insert_X_impl.h.t @@ -0,0 +1,58 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012,2013 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. + */ + +// @WARNING@ + +#ifndef @GUARD_NAME_IMPL@ +#define @GUARD_NAME_IMPL@ + +#include <blocks/@NAME@.h> + +namespace gr { + namespace blocks { + + class @NAME_IMPL@ : public @NAME@ + { + private: + std::vector<@TYPE@> d_data; + int d_offset; + int d_periodicity; + + public: + @NAME_IMPL@(const std::vector<@TYPE@> &data, + int periodicity, int offset); + ~@NAME_IMPL@(); + + void rewind() { d_offset=0; } + void set_data(const std::vector<@TYPE@> &data) { + d_data = data; rewind(); } + + 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 /* @GUARD_NAME_IMPL@ */ diff --git a/gr-blocks/lib/vector_sink_X_impl.cc.t b/gr-blocks/lib/vector_sink_X_impl.cc.t new file mode 100644 index 0000000000..3be2861025 --- /dev/null +++ b/gr-blocks/lib/vector_sink_X_impl.cc.t @@ -0,0 +1,83 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2008,2010,2013 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. + */ + +// @WARNING@ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <@NAME_IMPL@.h> +#include <gr_io_signature.h> +#include <algorithm> +#include <iostream> + +namespace gr { + namespace blocks { + + @NAME@::sptr + @BASE_NAME@::make(int vlen) + { + return gnuradio::get_initial_sptr + (new @NAME_IMPL@(vlen)); + } + + @NAME_IMPL@::@NAME_IMPL@(int vlen) + : gr_sync_block("@NAME@", + gr_make_io_signature(1, 1, sizeof(@TYPE@) * vlen), + gr_make_io_signature(0, 0, 0)), + d_vlen(vlen) + { + } + + @NAME_IMPL@::~@NAME_IMPL@() + {} + + std::vector<@TYPE@> + @NAME_IMPL@::data() const + { + return d_data; + } + + std::vector<gr_tag_t> + @NAME_IMPL@::tags() const + { + return d_tags; + } + + int + @NAME_IMPL@::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + @TYPE@ *iptr = (@TYPE@*)input_items[0]; + + for(int i = 0; i < noutput_items * d_vlen; i++) + d_data.push_back (iptr[i]); + std::vector<gr_tag_t> tags; + get_tags_in_range(tags, 0, nitems_read(0), nitems_read(0) + noutput_items); + d_tags.insert(d_tags.end(), tags.begin(), tags.end()); + return noutput_items; + } + + } /* namespace blocks */ +} /* namespace gr */ diff --git a/gr-blocks/lib/vector_sink_X_impl.h.t b/gr-blocks/lib/vector_sink_X_impl.h.t new file mode 100644 index 0000000000..60d21e0c8c --- /dev/null +++ b/gr-blocks/lib/vector_sink_X_impl.h.t @@ -0,0 +1,56 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2008,2009,2013 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. + */ + +// @WARNING@ + +#ifndef @GUARD_NAME_IMPL@ +#define @GUARD_NAME_IMPL@ + +#include <blocks/@NAME@.h> + +namespace gr { + namespace blocks { + + class @NAME_IMPL@ : public @NAME@ + { + private: + std::vector<@TYPE@> d_data; + std::vector<gr_tag_t> d_tags; + int d_vlen; + + public: + @NAME_IMPL@(int vlen); + ~@NAME_IMPL@(); + + void reset() { d_data.clear(); } + std::vector<@TYPE@> data() const; + std::vector<gr_tag_t> tags() const; + + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } /* namespace blocks */ +} /* namespace gr */ + +#endif /* @GUARD_NAME_IMPL@ */ diff --git a/gr-blocks/lib/vector_source_X_impl.cc.t b/gr-blocks/lib/vector_source_X_impl.cc.t new file mode 100644 index 0000000000..9c1c63a213 --- /dev/null +++ b/gr-blocks/lib/vector_source_X_impl.cc.t @@ -0,0 +1,144 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2008,2010,2013 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. + */ + +// @WARNING@ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <@NAME_IMPL@.h> +#include <algorithm> +#include <gr_io_signature.h> +#include <stdexcept> + +namespace gr { + namespace blocks { + + @NAME@::sptr + @NAME@::make(const std::vector<@TYPE@> &data, + bool repeat, int vlen, + const std::vector<gr_tag_t> &tags) + { + return gnuradio::get_initial_sptr + (new @NAME_IMPL@(data, repeat, vlen, tags)); + } + + @NAME_IMPL@::@NAME_IMPL@(const std::vector<@TYPE@> &data, + bool repeat, int vlen, + const std::vector<gr_tag_t> &tags) + : gr_sync_block("@BASE_NAME@", + gr_make_io_signature(0, 0, 0), + gr_make_io_signature(1, 1, sizeof(@TYPE@) * vlen)), + d_data(data), + d_repeat(repeat), + d_offset(0), + d_vlen(vlen), + d_tags(tags), + d_tagpos(0) + { + if(tags.size() == 0) { + d_settags = 0; + } + else { + d_settags = 1; + set_output_multiple(data.size() / vlen); + } + if((data.size() % vlen) != 0) + throw std::invalid_argument("data length must be a multiple of vlen"); + } + + @NAME_IMPL@::~@NAME_IMPL@() + {} + + void + @NAME_IMPL@::set_data (const std::vector<@TYPE@> &data, + const std::vector<gr_tag_t> &tags) + { + d_data = data; + d_tags = tags; + rewind(); + if(tags.size() == 0) { + d_settags = false; + } + else { + d_settags = true; + } + } + + int + @NAME_IMPL@::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + @TYPE@ *optr = (@TYPE@ *) output_items[0]; + + if(d_repeat) { + unsigned int size = d_data.size (); + unsigned int offset = d_offset; + if(size == 0) + return -1; + + if(d_settags) { + int n_outputitems_per_vector = d_data.size() / d_vlen; + for(int i = 0; i < noutput_items; i += n_outputitems_per_vector) { + // FIXME do proper vector copy + memcpy((void *) optr, (const void*)&d_data[0], size*sizeof (@TYPE@)); + optr += size; + for(unsigned t = 0; t < d_tags.size(); t++) { + add_item_tag(0, nitems_written(0)+i+d_tags[t].offset, + d_tags[t].key, d_tags[t].value); + } + } + } + else { + for(int i = 0; i < noutput_items*d_vlen; i++) { + optr[i] = d_data[offset++]; + if(offset >= size) { + offset = 0; + } + } + } + + d_offset = offset; + return noutput_items; + } + else { + if(d_offset >= d_data.size ()) + return -1; // Done! + + unsigned n = std::min((unsigned)d_data.size() - d_offset, + (unsigned)noutput_items*d_vlen); + for(unsigned i = 0; i < n; i++) { + optr[i] = d_data[d_offset + i]; + } + for(unsigned t = 0; t < d_tags.size(); t++) { + if((d_tags[t].offset >= d_offset) && (d_tags[t].offset < d_offset+n)) + add_item_tag(0, d_tags[t].offset, d_tags[t].key, d_tags[t].value); + } + d_offset += n; + return n/d_vlen; + } + } + + } /* namespace blocks */ +} /* namespace gr */ diff --git a/gr-blocks/lib/vector_source_X_impl.h.t b/gr-blocks/lib/vector_source_X_impl.h.t new file mode 100644 index 0000000000..78ec52bacf --- /dev/null +++ b/gr-blocks/lib/vector_source_X_impl.h.t @@ -0,0 +1,62 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2008,2012-2013 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. + */ + +// @WARNING@ + +#ifndef @GUARD_NAME_IMPL@ +#define @GUARD_NAME_IMPL@ + +#include <blocks/@NAME@.h> + +namespace gr { + namespace blocks { + + class @NAME_IMPL@ : public @NAME@ + { + private: + std::vector<@TYPE@> d_data; + bool d_repeat; + unsigned int d_offset; + int d_vlen; + bool d_settags; + std::vector<gr_tag_t> d_tags; + unsigned int d_tagpos; + + public: + @NAME_IMPL@(const std::vector<@TYPE@> &data, + bool repeat, int vlen, + const std::vector<gr_tag_t> &tags); + ~@NAME_IMPL@(); + + void rewind() { d_offset=0; } + void set_data(const std::vector<@TYPE@> &data, + const std::vector<gr_tag_t> &tags); + + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } /* namespace blocks */ +} /* namespace gr */ + +#endif /* @GUARD_NAME_IMPL@ */ |