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