1 /* -*- c++ -*- */
2 /*
3  * Copyright 2012,2018 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 
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27 
28 #include "vector_insert_impl.h"
29 #include <gnuradio/block.h>
30 #include <gnuradio/io_signature.h>
31 #include <stdio.h>
32 #include <algorithm>
33 #include <stdexcept>
34 
35 namespace gr {
36 namespace blocks {
37 
38 template <class T>
39 typename vector_insert<T>::sptr
make(const std::vector<T> & data,int periodicity,int offset)40 vector_insert<T>::make(const std::vector<T>& data, int periodicity, int offset)
41 {
42     return gnuradio::get_initial_sptr(
43         new vector_insert_impl<T>(data, periodicity, offset));
44 }
45 
46 template <class T>
vector_insert_impl(const std::vector<T> & data,int periodicity,int offset)47 vector_insert_impl<T>::vector_insert_impl(const std::vector<T>& data,
48                                           int periodicity,
49                                           int offset)
50     : block("vector_insert",
51             io_signature::make(1, 1, sizeof(T)),
52             io_signature::make(1, 1, sizeof(T))),
53       d_data(data),
54       d_offset(offset),
55       d_periodicity(periodicity)
56 {
57     this->set_tag_propagation_policy(gr::block::TPP_DONT); // handle tags manually
58     // some sanity checks
59     assert(offset < periodicity);
60     assert(offset >= 0);
61     assert((size_t)periodicity > data.size());
62 }
63 
64 template <class T>
~vector_insert_impl()65 vector_insert_impl<T>::~vector_insert_impl()
66 {
67 }
68 
69 template <class T>
general_work(int noutput_items,gr_vector_int & ninput_items,gr_vector_const_void_star & input_items,gr_vector_void_star & output_items)70 int vector_insert_impl<T>::general_work(int noutput_items,
71                                         gr_vector_int& ninput_items,
72                                         gr_vector_const_void_star& input_items,
73                                         gr_vector_void_star& output_items)
74 {
75     T* out = (T*)output_items[0];
76     const T* in = (const T*)input_items[0];
77 
78     int ii(0), oo(0);
79 
80     while ((oo < noutput_items) && (ii < ninput_items[0])) {
81         // printf("oo = %d, ii = %d, d_offset = %d, noutput_items = %d, ninput_items[0] =
82         // %d", oo, ii, d_offset, noutput_items, ninput_items[0]); printf(", d_periodicity
83         // = %d\n", d_periodicity);
84 
85         if (d_offset >= ((int)d_data.size())) { // if we are in the copy region
86             int max_copy = std::min(std::min(noutput_items - oo, ninput_items[0] - ii),
87                                     d_periodicity - d_offset);
88             std::vector<tag_t> tags;
89             this->get_tags_in_range(
90                 tags, 0, this->nitems_read(0) + ii, this->nitems_read(0) + max_copy + ii);
91             for (unsigned i = 0; i < tags.size(); i++) {
92                 // printf("copy tag from in@%d to out@%d\n", int(tags[i].offset),
93                 // int(nitems_written(0) + oo + (tags[i].offset-nitems_read(0)-ii)));
94                 this->add_item_tag(0,
95                                    this->nitems_written(0) + oo +
96                                        (tags[i].offset - this->nitems_read(0) - ii),
97                                    tags[i].key,
98                                    tags[i].value,
99                                    tags[i].srcid);
100             }
101             // printf("copy %d from input\n", max_copy);
102             memcpy(&out[oo], &in[ii], sizeof(T) * max_copy);
103             // printf(" * memcpy returned.\n");
104             ii += max_copy;
105             oo += max_copy;
106             d_offset = (d_offset + max_copy) % d_periodicity;
107         } else { // if we are in the insertion region
108             int max_copy = std::min(noutput_items - oo, ((int)d_data.size()) - d_offset);
109             // printf("copy %d from d_data[%d] to out[%d]\n", max_copy, d_offset, oo);
110             memcpy(&out[oo], &d_data[d_offset], sizeof(T) * max_copy);
111             // printf(" * memcpy returned.\n");
112             oo += max_copy;
113             d_offset = (d_offset + max_copy) % d_periodicity;
114             // printf(" ## (inelse) oo = %d, d_offset = %d\n", oo, d_offset);
115         }
116 
117         // printf(" # exit else, on to next loop.\n");
118     }
119     // printf(" # got out of loop\n");
120 
121     // printf("consume = %d, produce = %d\n", ii, oo);
122     this->consume_each(ii);
123     return oo;
124 }
125 
126 template class vector_insert<std::uint8_t>;
127 template class vector_insert<std::int16_t>;
128 template class vector_insert<std::int32_t>;
129 template class vector_insert<float>;
130 template class vector_insert<gr_complex>;
131 } /* namespace blocks */
132 } /* namespace gr */
133