1% ldpc.m
2%
3% David Rowe 2013
4% Octave functions to help us use the CML LDPC code.
5%
6% Installing CML library
7% ----------------------
8%
9% $ sudo apt-get install liboctave-dev
10% $ wget http://www.iterativesolutions.com/user/image/cml.1.10.zip
11% $ unzip cml.1.10.zip
12% $ patch -p0 < ~/codec2/octave/cml.patch
13% $ cd cml/source
14% $ octave --no-gui
15% octave:> make
16% (you'll see a few warnings but hopefully no errors)
17%
18% Optionally set an environment variable for CML_PATH in your shell or
19% in your codec2/octave/.octaverc file
20
211;
22
23function init_cml()
24  currentdir = pwd;
25
26  path_to_cml = getenv("CML_PATH");
27
28  if exist(path_to_cml, 'dir') == 7
29    cd(path_to_cml)
30    CmlStartup
31    cd(currentdir);
32  else
33    printf("\n---------------------------------------------------\n");
34    printf("Can't start CML in path: %s\n", path_to_cml);
35    printf("See CML_PATH instructions at top of this script (ldpc.m)\n");
36    printf("-----------------------------------------------------\n\n");
37    assert(0);
38  end
39end
40
41% init using built in WiMax or DVSB2 code
42
43function code_param = ldpc_init_builtin(code, rate, framesize, modulation, mod_order, mapping, constellation)
44    if strcmp(code,'wimax')
45      [code_param.H_rows, code_param.H_cols, code_param.P_matrix] = InitializeWiMaxLDPC( rate, framesize,  0 );
46    end
47    if strcmp(code,'dvbs2')
48      [code_param.H_rows, code_param.H_cols, code_param.P_matrix] = InitializeDVBS2( rate, framesize);
49    end
50    if nargin == 7
51      code_param.S_matrix = constellation;
52    else
53      if length(mapping) == 0
54        code_param.S_matrix = CreateConstellation( modulation, mod_order);
55      else
56        code_param.S_matrix = CreateConstellation( modulation, mod_order, mapping );
57      end
58    end
59    code_param.bits_per_symbol = log2(mod_order);
60
61    code_param.ldpc_data_bits_per_frame = length(code_param.H_cols) - length(code_param.P_matrix);
62    code_param.ldpc_parity_bits_per_frame = framesize - code_param.ldpc_data_bits_per_frame;
63    code_param.ldpc_coded_bits_per_frame = framesize;
64
65    code_param.data_bits_per_frame  = code_param.ldpc_data_bits_per_frame;
66    code_param.coded_bits_per_frame = code_param.ldpc_coded_bits_per_frame;
67    code_param.coded_syms_per_frame = code_param.coded_bits_per_frame/code_param.bits_per_symbol;
68endfunction
69
70
71% init using user supplied code
72
73function [code_param framesize rate] = ldpc_init_user(HRA, modulation, mod_order, mapping, constellation)
74    [Nr Nc] = size(HRA);
75    rate = (Nc-Nr)/Nc;
76    framesize = Nc;
77    [H_rows, H_cols] = Mat2Hrows(HRA);
78    code_param.H_rows = H_rows;
79    code_param.H_cols = H_cols;
80    code_param.P_matrix = [];
81    if nargin == 5
82      code_param.S_matrix = constellation;
83    else
84      if length(mapping) == 0
85        code_param.S_matrix = CreateConstellation( modulation, mod_order);
86      else
87        code_param.S_matrix = CreateConstellation( modulation, mod_order, mapping );
88      end
89    end
90    code_param.bits_per_symbol = log2(mod_order);
91
92    code_param.ldpc_data_bits_per_frame = length(code_param.H_cols) - length(code_param.P_matrix);
93    code_param.ldpc_parity_bits_per_frame = framesize - code_param.ldpc_data_bits_per_frame;
94    code_param.ldpc_coded_bits_per_frame = framesize;
95
96    % these variables support underfilling frame
97    code_param.data_bits_per_frame  = code_param.ldpc_data_bits_per_frame;
98    code_param.coded_bits_per_frame = code_param.ldpc_coded_bits_per_frame;
99    code_param.coded_syms_per_frame = code_param.coded_bits_per_frame/code_param.bits_per_symbol;
100endfunction
101
102
103function [codeword s] = ldpc_enc(data, code_param)
104    codeword = LdpcEncode( data, code_param.H_rows, code_param.P_matrix );
105    s = Modulate( codeword, code_param.S_matrix );
106endfunction
107
108
109function [detected_data paritychecks] = ldpc_dec(code_param, max_iterations, demod_type, decoder_type, r, EsNo, fading)
110    symbol_likelihood = Demod2D( r, code_param.S_matrix, EsNo, fading);
111
112    % initialize the extrinsic decoder input
113
114    input_somap_c = zeros(1, code_param.ldpc_coded_bits_per_frame );
115    bit_likelihood = Somap( symbol_likelihood, demod_type, input_somap_c );
116
117    input_decoder_c = bit_likelihood(1:code_param.ldpc_coded_bits_per_frame);
118
119    [x_hat paritychecks] = MpDecode( -input_decoder_c, code_param.H_rows, code_param.H_cols, ...
120                              max_iterations, decoder_type, 1, 1);
121    [mx mx_ind] = max(paritychecks);
122    detected_data = x_hat(mx_ind,:);
123endfunction
124
125
126% Packs a binary array into an array of 8 bit bytes, MSB first
127
128function packed = packmsb(unpacked)
129    packed = zeros(1,floor(length(unpacked)+7)/8);
130    bit = 7; byte = 1;
131    for i=1:length(unpacked)
132        packed(byte) = bitor(packed(byte), bitshift(unpacked(i),bit));
133        bit--;
134        if (bit < 0)
135            bit = 7;
136            byte++;
137        end
138    end
139endfunction
140
141
142% unpacks an array of 8 bit bytes into a binary array of unpacked bits, MSB first
143
144function unpacked = unpackmsb(packed)
145    bit = 7; byte = 1;
146    for i=1:length(packed)*8
147        unpacked(i) = bitand(bitshift(packed(byte), -bit), 1);
148        bit--;
149        if (bit < 0)
150            bit = 7;
151            byte++;
152        end
153    end
154endfunction
155
156
157% symbol interleaver that acts on bits 2 at a time
158
159function y = interleave_bits(interleaver, x)
160    y =  zeros(1,length(x));
161    for i = 1:length(interleaver)
162        dst = interleaver(i);
163        y(2*(dst-1)+1:2*dst) = x(2*(i-1)+1:2*(i));
164    end
165endfunction
166
167% symbol de-interleaver
168
169function x = deinterleave_symbols(interleaver, y)
170    for i = 1:length(interleaver)
171        x(i) = y(interleaver(i));
172    end
173endfunction
174