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