1 /* -*- c++ -*- */
2 /*
3  * Copyright 2015 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 <gnuradio/fec/polar_common.h>
28 #include <gnuradio/io_signature.h>
29 #include <volk/volk.h>
30 
31 #include <gnuradio/blocks/pack_k_bits.h>
32 #include <gnuradio/blocks/unpack_k_bits.h>
33 
34 #include <cmath>
35 #include <iostream>
36 #include <stdexcept>
37 #include <vector>
38 
39 namespace gr {
40 namespace fec {
41 namespace code {
42 
polar_common(int block_size,int num_info_bits,std::vector<int> frozen_bit_positions,std::vector<char> frozen_bit_values)43 polar_common::polar_common(int block_size,
44                            int num_info_bits,
45                            std::vector<int> frozen_bit_positions,
46                            std::vector<char> frozen_bit_values)
47     : d_frozen_bit_positions(frozen_bit_positions),
48       d_frozen_bit_values(frozen_bit_values),
49       d_block_size(block_size),
50       d_block_power((int)log2(float(block_size))),
51       d_num_info_bits(num_info_bits)
52 {
53     if (pow(2, d_block_power) != d_block_size) {
54         throw std::runtime_error("block_size MUST be a power of 2!");
55     }
56 
57     unsigned int num_frozen_bits = d_block_size - d_num_info_bits;
58     if (num_frozen_bits != d_frozen_bit_positions.size()) {
59         throw std::runtime_error(
60             "number of frozen bit positions must equal block_size - num_info_bits");
61     }
62 
63     // According to papers frozen bits default to '0'.
64     while (d_frozen_bit_values.size() < num_frozen_bits) {
65         d_frozen_bit_values.push_back(0);
66     }
67     initialize_info_bit_position_vector();
68     setup_volk_vectors();
69     setup_info_bit_positions_reversed();
70 
71     d_unpacker = new gr::blocks::kernel::unpack_k_bits(8);
72 }
73 
initialize_info_bit_position_vector()74 void polar_common::initialize_info_bit_position_vector()
75 {
76     int num_frozen_bit = 0;
77     int frozen_pos = d_frozen_bit_positions.at(num_frozen_bit);
78     for (int i = 0; i < d_block_size; i++) {
79         if (i != frozen_pos) {
80             d_info_bit_positions.push_back((int)i);
81         } else {
82             num_frozen_bit++;
83             num_frozen_bit =
84                 std::min(num_frozen_bit, (int)(d_frozen_bit_positions.size() - 1));
85             frozen_pos = d_frozen_bit_positions.at(num_frozen_bit);
86         }
87     }
88 
89     if ((int)d_info_bit_positions.size() != num_info_bits()) {
90         throw std::runtime_error(
91             "polar_common: number of info bit positions MUST equal num_info_bits (K)!");
92     }
93 }
94 
setup_info_bit_positions_reversed()95 void polar_common::setup_info_bit_positions_reversed()
96 {
97     for (unsigned int i = 0; i < d_info_bit_positions.size(); i++) {
98         d_info_bit_positions_reversed.push_back(
99             (int)bit_reverse((long)d_info_bit_positions.at(i), block_power()));
100     }
101 
102     if ((int)d_info_bit_positions_reversed.size() != num_info_bits()) {
103         throw std::runtime_error(
104             "polar_encoder: number of info bit positions MUST equal num_info_bits (K)!");
105     }
106 }
107 
setup_volk_vectors()108 void polar_common::setup_volk_vectors()
109 {
110     int nfrozen = block_size() - num_info_bits();
111     d_volk_temp = (unsigned char*)volk_malloc(sizeof(unsigned char) * block_size(),
112                                               volk_get_alignment());
113     d_volk_frozen_bit_mask = (unsigned char*)volk_malloc(
114         sizeof(unsigned char) * block_size(), volk_get_alignment());
115     d_volk_frozen_bits = (unsigned char*)volk_malloc(sizeof(unsigned char) * nfrozen,
116                                                      volk_get_alignment());
117     std::copy(d_frozen_bit_values.begin(), d_frozen_bit_values.end(), d_volk_frozen_bits);
118     std::fill(
119         d_volk_frozen_bits + d_frozen_bit_values.size(), d_volk_frozen_bits + nfrozen, 0);
120 
121     unsigned int nfbit = 0;
122     for (int i = 0; i < block_size(); i++) {
123         unsigned char m = 0x00;
124         if (nfbit < d_frozen_bit_positions.size() && d_frozen_bit_positions[nfbit] == i) {
125             m = 0xFF;
126             nfbit++;
127         }
128         d_volk_frozen_bit_mask[i] = m;
129     }
130 }
131 
volk_encode(unsigned char * out_buf,const unsigned char * in_buf)132 void polar_common::volk_encode(unsigned char* out_buf, const unsigned char* in_buf)
133 {
134     volk_8u_x3_encodepolar_8u_x2(out_buf,
135                                  d_volk_temp,
136                                  d_volk_frozen_bit_mask,
137                                  d_volk_frozen_bits,
138                                  in_buf,
139                                  block_size());
140 }
141 
volk_encode_block(unsigned char * out_buf,unsigned char * in_buf)142 void polar_common::volk_encode_block(unsigned char* out_buf, unsigned char* in_buf)
143 {
144     volk_8u_x2_encodeframepolar_8u(out_buf, in_buf, block_size());
145 }
146 
~polar_common()147 polar_common::~polar_common()
148 {
149     delete d_unpacker;
150 
151     volk_free(d_volk_temp);
152     volk_free(d_volk_frozen_bit_mask);
153     volk_free(d_volk_frozen_bits);
154 }
155 
bit_reverse(long value,int active_bits) const156 long polar_common::bit_reverse(long value, int active_bits) const
157 {
158     long r = 0;
159     for (int i = 0; i < active_bits; i++) {
160         r <<= 1;
161         r |= value & 1;
162         value >>= 1;
163     }
164     return r;
165 }
166 
print_packed_bit_array(const unsigned char * printed_array,const int num_bytes) const167 void polar_common::print_packed_bit_array(const unsigned char* printed_array,
168                                           const int num_bytes) const
169 {
170     int num_bits = num_bytes << 3;
171     unsigned char* temp = new unsigned char[num_bits];
172     d_unpacker->unpack(temp, printed_array, num_bytes);
173 
174     std::cout << "[";
175     for (int i = 0; i < num_bits; i++) {
176         std::cout << (int)*(temp + i) << " ";
177     }
178     std::cout << "]" << std::endl;
179 
180     delete[] temp;
181 }
182 
print_unpacked_bit_array(const unsigned char * bits,const unsigned int num_bytes) const183 void polar_common::print_unpacked_bit_array(const unsigned char* bits,
184                                             const unsigned int num_bytes) const
185 {
186     std::cout << "( ";
187     for (unsigned int i = 0; i < num_bytes; i++) {
188         std::cout << (int)*bits++ << ", ";
189     }
190     std::cout << ")" << std::endl;
191 }
192 
193 } /* namespace code */
194 } /* namespace fec */
195 } /* namespace gr */
196