1 /* -*- c++ -*- */
2 /*
3 * Copyright 2007,2010,2012-2013 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 "delay_impl.h"
28 #include <gnuradio/io_signature.h>
29 #include <string.h>
30
31 namespace gr {
32 namespace blocks {
33
make(size_t itemsize,int delay)34 delay::sptr delay::make(size_t itemsize, int delay)
35 {
36 return gnuradio::get_initial_sptr(new delay_impl(itemsize, delay));
37 }
38
delay_impl(size_t itemsize,int delay)39 delay_impl::delay_impl(size_t itemsize, int delay)
40 : block("delay",
41 io_signature::make(1, -1, itemsize),
42 io_signature::make(1, -1, itemsize)),
43 d_itemsize(itemsize)
44 {
45 if (delay < 0) {
46 throw std::runtime_error("delay: Cannot initialize block with a delay < 0.");
47 }
48 set_dly(delay);
49 d_delta = 0;
50 }
51
~delay_impl()52 delay_impl::~delay_impl() {}
53
forecast(int noutput_items,gr_vector_int & ninput_items_required)54 void delay_impl::forecast(int noutput_items, gr_vector_int& ninput_items_required)
55 {
56 // make sure all inputs have noutput_items available
57 unsigned ninputs = ninput_items_required.size();
58 for (unsigned i = 0; i < ninputs; i++)
59 ninput_items_required[i] = noutput_items;
60 }
61
set_dly(int d)62 void delay_impl::set_dly(int d)
63 {
64 // only set a new delta if there is a change in the delay; this
65 // protects from quickly-repeated calls to this function that
66 // would end with d_delta=0.
67 if (d != dly()) {
68 gr::thread::scoped_lock l(d_mutex_delay);
69 int old = dly();
70 set_history(d + 1);
71 declare_sample_delay(history() - 1);
72 d_delta += dly() - old;
73 }
74 }
75
general_work(int noutput_items,gr_vector_int & ninput_items,gr_vector_const_void_star & input_items,gr_vector_void_star & output_items)76 int delay_impl::general_work(int noutput_items,
77 gr_vector_int& ninput_items,
78 gr_vector_const_void_star& input_items,
79 gr_vector_void_star& output_items)
80 {
81 gr::thread::scoped_lock l(d_mutex_delay);
82 assert(input_items.size() == output_items.size());
83
84 const char* iptr;
85 char* optr;
86 int cons, ret;
87
88 // No change in delay; just memcpy ins to outs
89 if (d_delta == 0) {
90 for (size_t i = 0; i < input_items.size(); i++) {
91 iptr = (const char*)input_items[i];
92 optr = (char*)output_items[i];
93 std::memcpy(optr, iptr, noutput_items * d_itemsize);
94 }
95 cons = noutput_items;
96 ret = noutput_items;
97 }
98
99 // Skip over d_delta items on the input
100 else if (d_delta < 0) {
101 int n_to_copy, n_adj;
102 int delta = -d_delta;
103 n_to_copy = std::max(0, noutput_items - delta);
104 n_adj = std::min(delta, noutput_items);
105 for (size_t i = 0; i < input_items.size(); i++) {
106 iptr = (const char*)input_items[i];
107 optr = (char*)output_items[i];
108 std::memcpy(optr, iptr + delta * d_itemsize, n_to_copy * d_itemsize);
109 }
110 cons = noutput_items;
111 ret = n_to_copy;
112 delta -= n_adj;
113 d_delta = -delta;
114 }
115
116 // produce but not consume (inserts zeros)
117 else { // d_delta > 0
118 int n_from_input, n_padding;
119 n_from_input = std::max(0, noutput_items - d_delta);
120 n_padding = std::min(d_delta, noutput_items);
121 for (size_t i = 0; i < input_items.size(); i++) {
122 iptr = (const char*)input_items[i];
123 optr = (char*)output_items[i];
124 std::memset(optr, 0, n_padding * d_itemsize);
125 std::memcpy(optr, iptr, n_from_input * d_itemsize);
126 }
127 cons = n_from_input;
128 ret = noutput_items;
129 d_delta -= n_padding;
130 }
131
132 consume_each(cons);
133 return ret;
134 }
135
136 } /* namespace blocks */
137 } /* namespace gr */
138