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