1 /* -*- c++ -*- */
2 /*
3 * Copyright 2013-2014 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 "depuncture_bb_impl.h"
28 #include <gnuradio/io_signature.h>
29 #include <pmt/pmt.h>
30 #include <stdio.h>
31 #include <volk/volk.h>
32 #include <boost/bind.hpp>
33 #include <string>
34
35 namespace gr {
36 namespace fec {
37
make(int puncsize,int puncpat,int delay,char symbol)38 depuncture_bb::sptr depuncture_bb::make(int puncsize, int puncpat, int delay, char symbol)
39 {
40 return gnuradio::get_initial_sptr(
41 new depuncture_bb_impl(puncsize, puncpat, delay, symbol));
42 }
43
depuncture_bb_impl(int puncsize,int puncpat,int delay,char symbol)44 depuncture_bb_impl::depuncture_bb_impl(int puncsize, int puncpat, int delay, char symbol)
45 : block("depuncture_bb",
46 io_signature::make(1, 1, sizeof(unsigned char)),
47 io_signature::make(1, 1, sizeof(unsigned char))),
48 d_puncsize(puncsize),
49 d_delay(delay),
50 d_sym(symbol)
51 {
52 // Create a mask of all 1's of puncsize length
53 int mask = 0;
54 for (int i = 0; i < d_puncsize; i++)
55 mask |= 1 << i;
56
57 // Rotate the pattern for the delay value; then mask it if there
58 // are any excess 1's in the pattern.
59 for (int i = 0; i < d_delay; ++i) {
60 puncpat = ((puncpat & 1) << (d_puncsize - 1)) + (puncpat >> 1);
61 }
62 d_puncpat = puncpat & mask;
63
64 // Calculate the number of holes in the pattern. The mask is all
65 // 1's given puncsize and puncpat is a pattern with >= puncsize
66 // 0's (masked to ensure this). The difference between the
67 // number of 1's in the mask and the puncpat is the number of
68 // holes.
69 uint32_t count_mask = 0, count_pat = 0;
70 volk_32u_popcnt(&count_mask, static_cast<uint32_t>(mask));
71 volk_32u_popcnt(&count_pat, static_cast<uint32_t>(d_puncpat));
72 d_puncholes = count_mask - count_pat;
73
74 set_fixed_rate(true);
75 set_relative_rate((uint64_t)d_puncsize, (uint64_t)(d_puncsize - d_puncholes));
76 set_output_multiple(d_puncsize);
77 // set_msg_handler(<portname>, [this](pmt::pmt_t msg) { this->catch_msg(msg); });
78 }
79
~depuncture_bb_impl()80 depuncture_bb_impl::~depuncture_bb_impl() {}
81
fixed_rate_ninput_to_noutput(int ninput)82 int depuncture_bb_impl::fixed_rate_ninput_to_noutput(int ninput)
83 {
84 return (int)(((d_puncsize / (double)(d_puncsize - d_puncholes)) * ninput) + .5);
85 }
86
fixed_rate_noutput_to_ninput(int noutput)87 int depuncture_bb_impl::fixed_rate_noutput_to_ninput(int noutput)
88 {
89 return (int)((((d_puncsize - d_puncholes) / (double)(d_puncsize)) * noutput) + .5);
90 }
91
forecast(int noutput_items,gr_vector_int & ninput_items_required)92 void depuncture_bb_impl::forecast(int noutput_items, gr_vector_int& ninput_items_required)
93 {
94 ninput_items_required[0] =
95 (int)((((d_puncsize - d_puncholes) / (double)(d_puncsize)) * noutput_items) + .5);
96 }
97
98 /*
99 void depuncture_bb_impl::catch_msg(pmt::pmt_t msg)
100 {
101 long mlong = pmt::pmt_to_long(msg);
102 for(int i = 0; i < mlong; ++i) {
103 d_puncholes = (d_puncholes >> 1) | ((d_puncholes & 1) << (d_puncsize - 1));
104 }
105 }
106 */
107
general_work(int noutput_items,gr_vector_int & ninput_items,gr_vector_const_void_star & input_items,gr_vector_void_star & output_items)108 int depuncture_bb_impl::general_work(int noutput_items,
109 gr_vector_int& ninput_items,
110 gr_vector_const_void_star& input_items,
111 gr_vector_void_star& output_items)
112 {
113 const uint8_t* in = (const uint8_t*)input_items[0];
114 uint8_t* out = (uint8_t*)output_items[0];
115
116 for (int i = 0, k = 0; i < noutput_items / output_multiple(); ++i) {
117 for (int j = 0; j < output_multiple(); ++j) {
118 out[i * output_multiple() + j] =
119 ((d_puncpat >> (d_puncsize - 1 - j)) & 1) ? in[k++] : d_sym;
120 }
121 }
122
123 /*
124 GR_LOG_DEBUG(d_debug_logger, ">>>>>> start");
125 for(int i = 0, k=0; i < noutput_items; ++i) {
126 if((d_puncpat >> (d_puncsize - 1 - (i % d_puncsize))) & 1) {
127 GR_LOG_DEBUG(d_debug_logger, boost::format("%1%...%2%") \
128 % out[i] % in[k++]);
129 }
130 else {
131 GR_LOG_DEBUG(d_debug_logger, boost::format("snit %1%") % out[i]);
132 }
133 }
134
135 GR_LOG_DEBUG(d_debug_logger, boost::format("comp: %1%, %2%\n") \
136 % noutput_items % ninput_items[0]);
137 GR_LOG_DEBUG(d_debug_logger, boost::format("consuming %1%") \
138 % ((int)(((1.0/relative_rate()) * noutput_items) + .5)));
139 */
140
141 consume_each((int)(((1.0 / relative_rate()) * noutput_items) + .5));
142 return noutput_items;
143 }
144
145 } /* namespace fec */
146 } /* namespace gr */
147