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 #include <gnuradio/fec/decoder.h>
24 #include <gnuradio/fec/ldpc_decoder.h>
25 #include <gnuradio/fec/maxstar.h>
26 #include <math.h>
27 #include <stdio.h>
28 #include <string.h> // for memcpy
29 #include <volk/volk.h>
30 #include <boost/assign/list_of.hpp>
31 #include <algorithm> // for std::reverse
32 #include <sstream>
33 #include <vector>
34 
35 
36 namespace gr {
37 namespace fec {
38 
39 generic_decoder::sptr
make(std::string alist_file,float sigma,int max_iterations)40 ldpc_decoder::make(std::string alist_file, float sigma, int max_iterations)
41 {
42     return generic_decoder::sptr(new ldpc_decoder(alist_file, sigma, max_iterations));
43 }
44 
ldpc_decoder(std::string alist_file,float sigma,int max_iterations)45 ldpc_decoder::ldpc_decoder(std::string alist_file, float sigma, int max_iterations)
46     : generic_decoder("ldpc_decoder")
47 {
48     if (!boost::filesystem::exists(alist_file))
49         throw std::runtime_error("Bad AList file name!");
50 
51     d_list.read(alist_file.c_str());
52     d_code.set_alist(d_list);
53     d_spa.set_alist_sigma(d_list, sigma);
54 
55     d_rate =
56         static_cast<double>(d_code.dimension()) / static_cast<double>(d_code.get_N());
57     set_frame_size(d_code.dimension());
58 
59     d_spa.set_K(d_output_size);
60     d_spa.set_max_iterations(max_iterations);
61 }
62 
get_output_size()63 int ldpc_decoder::get_output_size() { return d_output_size; }
64 
get_input_size()65 int ldpc_decoder::get_input_size() { return d_input_size; }
66 
rate()67 double ldpc_decoder::rate() { return d_rate; }
68 
set_frame_size(unsigned int frame_size)69 bool ldpc_decoder::set_frame_size(unsigned int frame_size)
70 {
71     if (frame_size % d_code.dimension() != 0) {
72         GR_LOG_ERROR(d_logger,
73                      boost::format("Frame size (%1% bits) must be a "
74                                    "multiple of the information word "
75                                    "size of the LDPC matrix, %2%") %
76                          frame_size % (d_code.dimension()));
77         throw std::runtime_error("ldpc_decoder: cannot use frame size.");
78     }
79 
80     d_output_size = frame_size;
81     d_input_size = static_cast<int>(round(frame_size / d_rate));
82 
83     return true;
84 }
85 
generic_work(void * inBuffer,void * outBuffer)86 void ldpc_decoder::generic_work(void* inBuffer, void* outBuffer)
87 {
88     const float* in = (const float*)inBuffer;
89     unsigned char* out = (unsigned char*)outBuffer;
90 
91     int j = 0;
92     std::vector<float> rx(d_code.get_N());
93     for (int i = 0; i < d_input_size; i += d_code.get_N()) {
94         for (int k = 0; k < d_code.get_N(); k++) {
95             rx[k] = in[i + k] * (-1);
96         }
97 
98         int n_iterations = 0;
99         std::vector<char> estimate(d_spa.decode(rx, &n_iterations));
100         std::vector<char> data(d_code.get_systematic_bits(estimate));
101         memcpy(&out[j], &data[0], d_code.dimension());
102         d_iterations = n_iterations;
103 
104         j += d_code.dimension();
105     }
106 }
107 
get_input_item_size()108 int ldpc_decoder::get_input_item_size() { return sizeof(INPUT_DATATYPE); }
109 
get_output_item_size()110 int ldpc_decoder::get_output_item_size() { return sizeof(OUTPUT_DATATYPE); }
111 
get_history()112 int ldpc_decoder::get_history() { return 0; }
113 
get_shift()114 float ldpc_decoder::get_shift() { return 0.0; }
115 
get_conversion()116 const char* ldpc_decoder::get_conversion() { return "none"; }
117 
~ldpc_decoder()118 ldpc_decoder::~ldpc_decoder() {}
119 
120 } // namespace fec
121 } // namespace gr
122