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_encoder.h>
28 #include <gnuradio/io_signature.h>
29 #include <volk/volk.h>
30 #include <cmath>
31 #include <stdexcept>
32
33 #include <gnuradio/blocks/pack_k_bits.h>
34 #include <gnuradio/blocks/unpack_k_bits.h>
35
36 namespace gr {
37 namespace fec {
38 namespace code {
39
make(int block_size,int num_info_bits,std::vector<int> frozen_bit_positions,std::vector<char> frozen_bit_values,bool is_packed)40 generic_encoder::sptr polar_encoder::make(int block_size,
41 int num_info_bits,
42 std::vector<int> frozen_bit_positions,
43 std::vector<char> frozen_bit_values,
44 bool is_packed)
45 {
46 return generic_encoder::sptr(new polar_encoder(
47 block_size, num_info_bits, frozen_bit_positions, frozen_bit_values, is_packed));
48 }
49
polar_encoder(int block_size,int num_info_bits,std::vector<int> & frozen_bit_positions,std::vector<char> & frozen_bit_values,bool is_packed)50 polar_encoder::polar_encoder(int block_size,
51 int num_info_bits,
52 std::vector<int>& frozen_bit_positions,
53 std::vector<char>& frozen_bit_values,
54 bool is_packed)
55 : polar_common(block_size, num_info_bits, frozen_bit_positions, frozen_bit_values),
56 d_is_packed(is_packed)
57 {
58 setup_frozen_bit_inserter();
59 }
60
setup_frozen_bit_inserter()61 void polar_encoder::setup_frozen_bit_inserter()
62 {
63 d_frozen_bit_prototype =
64 (unsigned char*)volk_malloc(block_size() >> 3, volk_get_alignment());
65 memset(d_frozen_bit_prototype, 0, block_size() >> 3);
66
67 for (unsigned int i = 0; i < d_frozen_bit_positions.size(); i++) {
68 int rev_pos = (int)bit_reverse((long)d_frozen_bit_positions.at(i), block_power());
69 unsigned char frozen_bit = (unsigned char)d_frozen_bit_values.at(i);
70 insert_unpacked_bit_into_packed_array_at_position(
71 d_frozen_bit_prototype, frozen_bit, rev_pos);
72 }
73 }
74
~polar_encoder()75 polar_encoder::~polar_encoder() { volk_free(d_frozen_bit_prototype); }
76
generic_work(void * in_buffer,void * out_buffer)77 void polar_encoder::generic_work(void* in_buffer, void* out_buffer)
78 {
79 const unsigned char* in = (const unsigned char*)in_buffer;
80 unsigned char* out = (unsigned char*)out_buffer;
81
82 if (d_is_packed) {
83 insert_packed_frozen_bits_and_reverse(out, in);
84 encode_vector_packed(out);
85 } else {
86 volk_encode(out, in);
87 }
88 }
89
encode_vector_packed(unsigned char * target) const90 void polar_encoder::encode_vector_packed(unsigned char* target) const
91 {
92 encode_vector_packed_subbyte(target);
93 encode_vector_packed_interbyte(target);
94 }
95
encode_vector_packed_subbyte(unsigned char * target) const96 void polar_encoder::encode_vector_packed_subbyte(unsigned char* target) const
97 {
98 int num_bytes_per_block = block_size() >> 3;
99 while (num_bytes_per_block) {
100 encode_packed_byte(target);
101 ++target;
102 --num_bytes_per_block;
103 }
104 }
105
encode_packed_byte(unsigned char * target) const106 void polar_encoder::encode_packed_byte(unsigned char* target) const
107 {
108 // this method only produces correct results if block_size > 4.
109 // this is assumed to be the case.
110 *target ^= 0xaa & (*target << 1);
111 *target ^= 0xcc & (*target << 2);
112 *target ^= *target << 4;
113 }
114
encode_vector_packed_interbyte(unsigned char * target) const115 void polar_encoder::encode_vector_packed_interbyte(unsigned char* target) const
116 {
117 int branch_byte_size = 1;
118 unsigned char* pos;
119 int n_branches = block_size() >> 4;
120 int byte = 0;
121 for (int stage = 3; stage < block_power(); ++stage) {
122 pos = target;
123
124 for (int branch = 0; branch < n_branches; ++branch) {
125
126 byte = 0;
127 while (byte < branch_byte_size) {
128 *pos ^= *(pos + branch_byte_size);
129 ++pos;
130 ++byte;
131 }
132
133 pos += branch_byte_size;
134 }
135
136 n_branches >>= 1;
137 branch_byte_size <<= 1;
138 }
139 }
140
insert_packed_frozen_bits_and_reverse(unsigned char * target,const unsigned char * input) const141 void polar_encoder::insert_packed_frozen_bits_and_reverse(
142 unsigned char* target, const unsigned char* input) const
143 {
144 memcpy(target, d_frozen_bit_prototype, block_size() >> 3);
145 const int* info_bit_reversed_positions_ptr = &d_info_bit_positions_reversed[0];
146 int bit_num = 0;
147 unsigned char byte = *input;
148 int bit_pos;
149 while (bit_num < num_info_bits()) {
150 bit_pos = *info_bit_reversed_positions_ptr++;
151 insert_packet_bit_into_packed_array_at_position(
152 target, byte, bit_pos, bit_num % 8);
153 ++bit_num;
154 if (bit_num % 8 == 0) {
155 ++input;
156 byte = *input;
157 }
158 }
159 }
160
insert_unpacked_bit_into_packed_array_at_position(unsigned char * target,const unsigned char bit,const int pos) const161 void polar_encoder::insert_unpacked_bit_into_packed_array_at_position(
162 unsigned char* target, const unsigned char bit, const int pos) const
163 {
164 int byte_pos = pos >> 3;
165 int bit_pos = pos & 0x7;
166 *(target + byte_pos) ^= bit << (7 - bit_pos);
167 }
168
insert_packet_bit_into_packed_array_at_position(unsigned char * target,const unsigned char bit,const int target_pos,const int bit_pos) const169 void polar_encoder::insert_packet_bit_into_packed_array_at_position(
170 unsigned char* target,
171 const unsigned char bit,
172 const int target_pos,
173 const int bit_pos) const
174 {
175 insert_unpacked_bit_into_packed_array_at_position(
176 target, (bit >> (7 - bit_pos)) & 0x01, target_pos);
177 }
178
179 } /* namespace code */
180 } /* namespace fec */
181 } /* namespace gr */
182