Commit 89c3cadc authored by Ben Wojtowicz's avatar Ben Wojtowicz

Added SIB1 encoding/decoding, fixed channel estimator

parent 777a4500
......@@ -25,6 +25,7 @@
% Notes: None
% Rev History: Ben Wojtowicz 11/22/2011 Created
% Ben Wojtowicz 01/29/2012 Fixed license statement
% Ben Wojtowicz 02/19/2012 Added newline to EOF
%
function [dec] = cmn_bin2dec(array, num_bits)
[num_array, junk] = size(array);
......@@ -35,4 +36,4 @@ function [dec] = cmn_bin2dec(array, num_bits)
dec(n) = dec(n) + array(n,num_bits-m)*2^m;
endfor
endfor
endfunction
\ No newline at end of file
endfunction
......@@ -25,6 +25,7 @@
% Notes: None
% Rev History: Ben Wojtowicz 11/22/2011 Created
% Ben Wojtowicz 01/29/2012 Fixed license statement
% Ben Wojtowicz 02/19/2012 Fixed mod(num_bits,3)==0 bug
%
function [array] = cmn_oct2bin(oct, num_bits)
[junk, num_oct] = size(oct);
......@@ -40,8 +41,10 @@ function [array] = cmn_oct2bin(oct, num_bits)
idx = idx - 3;
endfor
% Convert non-whole digits
dig = mod(tmp, 10);
array(n, 1:idx) = cmn_dec2bin(dig, mod(num_bits, 3));
if(mod(num_bits, 3) != 0)
% Convert non-whole digits
dig = mod(tmp, 10);
array(n, 1:idx) = cmn_dec2bin(dig, mod(num_bits, 3));
endif
endfor
endfunction
......@@ -25,9 +25,10 @@
% array in octal
% Outputs: out - Ouput bit array
% Spec: N/A
% Notes: Currently only supports hard bits
% Notes: N/A
% Rev History: Ben Wojtowicz 11/22/2011 Created
% Ben Wojtowicz 01/29/2012 Fixed license statement
% Ben Wojtowicz 02/19/2012 Added soft bit decoding
%
function [out] = cmn_viterbi_decode(in, k, r, g)
......@@ -82,23 +83,33 @@ function [out] = cmn_viterbi_decode(in, k, r, g)
path_metric = zeros(num_states, (length(in)/r)+10);
for(n=0:(length(in)/r)-1)
br_metric = zeros(num_states, 2);
p_metric = zeros(num_states, 2);
w_metric = zeros(num_states, 2);
for(m=0:num_states-1)
% Calculate the accumulated branch metrics for each state
for(o=0:1)
prev_state = mod(bitshift(m, 1) + o, num_states);
br_metric(m+1,o+1) = br_metric(m+1,o+1) + path_metric(prev_state+1,n+1);
st_arr = cmn_dec2bin(st_output(m+1,o+1), r);
prev_state = mod(bitshift(m, 1) + o, num_states);
p_metric(m+1,o+1) = path_metric(prev_state+1,n+1);
st_arr = cmn_dec2bin(st_output(m+1,o+1), r);
for(p=0:r-1)
br_metric(m+1,o+1) = br_metric(m+1,o+1) + mod(st_arr(p+1)+in(n*r+p+1), 2);
if(in(n*r+p+1) >= 0)
in_bit = 0;
else
in_bit = 1;
endif
br_metric(m+1,o+1) = br_metric(m+1,o+1) + mod(st_arr(p+1)+in_bit, 2);
w_metric(m+1,o+1) = w_metric(m+1,o+1) + abs(in(n*r+p+1));
endfor
endfor
% Keep the smallest branch metric as the path metric
if(br_metric(m+1,1) > br_metric(m+1,2))
path_metric_new(m+1) = br_metric(m+1,2);
% Keep the smallest branch metric as the path metric, weight the branch metric
tmp1 = br_metric(m+1,1) + p_metric(m+1,1);
tmp2 = br_metric(m+1,2) + p_metric(m+1,2);
if(tmp1 > tmp2)
path_metric_new(m+1) = p_metric(m+1,2) + w_metric(m+1,2)*br_metric(m+1,2);
else
path_metric_new(m+1) = br_metric(m+1,1);
path_metric_new(m+1) = p_metric(m+1,1) + w_metric(m+1,1)*br_metric(m+1,1);
endif
endfor
path_metric(:,n+2) = path_metric_new';
......
......@@ -14,20 +14,20 @@
% You should have received a copy of the GNU Affero General Public License
% along with this program. If not, see <http://www.gnu.org/licenses/>.
%
% Function: lte_mib_pack
% Description: Packs all of the fields into the Master
% Information Block
% Inputs: bw - System bandwidth (in number of RBs)
% phich_dur - PHICH Duration (normal or extended)
% phich_res - Number of PHICH groups (1/6, 1/2, 1, 2)
% sfn - System frame number
% Outputs: mib - Packed master information block
% Spec: 3GPP TS 36.331 section 6.2.2 v10.0.0
% Function: lte_bcch_bch_msg_pack
% Description: Packs all of the fields into the BCCH BCH message
% Inputs: bw - System bandwidth (in number of RBs)
% phich_dur - PHICH Duration (normal or extended)
% phich_res - Number of PHICH groups (1/6, 1/2, 1, 2)
% sfn - System frame number
% Outputs: bcch_bch_msg - Packed BCCH BCH message
% Spec: 3GPP TS 36.331 section 6.2.1 and 6.2.2 v10.0.0
% Notes: None
% Rev History: Ben Wojtowicz 10/30/2011 Created
% Ben Wojtowicz 01/29/2012 Fixed license statement
% Ben Wojtowicz 02/19/2012 Changed function name to match spec
%
function [mib] = lte_mib_pack(bw, phich_dur, phich_res, sfn)
function [bcch_bch_msg] = lte_bcch_bch_msg_pack(bw, phich_dur, phich_res, sfn)
% Check bandwidth
if(bw == 6)
act_bw = [0,0,0];
......@@ -43,18 +43,18 @@ function [mib] = lte_mib_pack(bw, phich_dur, phich_res, sfn)
act_bw = [1,0,1];
else
printf("ERROR: Invalid bw (%u)\n", bw);
mib = 0;
bcch_bch_msg = 0;
return;
endif
% Check phich_dur
if(phich_dur(1) == "n")
if(phich_dur == "normal")
act_phich_dur = 0;
elseif(phich_dur(1) == "e")
elseif(phich_dur == "extended")
act_phich_dur = 1;
else
printf("ERROR: Invalid phich_dur (%s)\n", phich_dur);
mib = 0;
bcch_bch_msg = 0;
return;
endif
......@@ -69,7 +69,7 @@ function [mib] = lte_mib_pack(bw, phich_dur, phich_res, sfn)
act_phich_res = [1,1];
else
printf("ERROR: Invalid phich_res (%f)\n", phich_res);
mib = 0;
bcch_bch_msg = 0;
return;
endif
......@@ -82,10 +82,10 @@ function [mib] = lte_mib_pack(bw, phich_dur, phich_res, sfn)
endfor
else
printf("ERROR: Invalid sfn (%u)\n", sfn);
mib = 0;
bcch_bch_msg = 0;
return;
endif
% Pack MIB
mib = [act_bw, act_phich_dur, act_phich_res, act_sfn, zeros(1,10)];
endfunction
\ No newline at end of file
% Pack the BCCH BCH message
bcch_bch_msg = [act_bw, act_phich_dur, act_phich_res, act_sfn, zeros(1,10)];
endfunction
......@@ -14,23 +14,23 @@
% You should have received a copy of the GNU Affero General Public License
% along with this program. If not, see <http://www.gnu.org/licenses/>.
%
% Function: lte_mib_unpack
% Description: Unpacks all of the fiels from the Master
% Information Block
% Inputs: bw - System bandwidth (in number of RBs)
% phich_dur - PHICH Duration (normal or extended)
% phich_res - Number of PHICH groups (1/6, 1/2, 1, 2)
% sfn - System frame number
% Outputs: mib - Packed master information block
% Spec: 3GPP TS 36.331 section 6.2.2 v10.0.0
% Function: lte_bcch_bch_msg_unpack
% Description: Unpacks all of the fields from the BCCH BCH message
% Inputs: bcch_bch_msg - Packed BCCH BCH message
% Outputs: bw - System bandwidth (in number of RBs)
% phich_dur - PHICH Duration (normal or extended)
% phich_res - Number of PHICH groups (1/6, 1/2, 1, 2)
% sfn - System frame number
% Spec: 3GPP TS 36.331 section 6.2.1 and 6.2.2 v10.0.0
% Notes: None
% Rev History: Ben Wojtowicz 10/30/2011 Created
% Ben Wojtowicz 01/29/2012 Fixed license statement
% Ben Wojtowicz 02/19/2012 Changed function name to match spec
%
function [bw, phich_dur, phich_res, sfn] = lte_mib_unpack(mib)
% Check mib
if(length(mib) ~= 24)
printf("ERROR: Invalid mib (length is %u, should be 24)\n", length(mib));
function [bw, phich_dur, phich_res, sfn] = lte_bcch_bch_msg_unpack(bcch_bch_msg)
% Check bcch_bch_msg
if(length(bcch_bch_msg) ~= 24)
printf("ERROR: Invalid bcch_bch_msg (length is %u, should be 24)\n", length(bcch_bch_msg));
bw = 0;
phich_dur = 0;
phich_res = 0;
......@@ -38,11 +38,11 @@ function [bw, phich_dur, phich_res, sfn] = lte_mib_unpack(mib)
return;
endif
% Unpack MIB
act_bw = mib(1:3);
act_phich_dur = mib(4);
act_phich_res = mib(5:6);
act_sfn = mib(7:14);
% Unpack the BCCH BCH message
act_bw = bcch_bch_msg(1:3);
act_phich_dur = bcch_bch_msg(4);
act_phich_res = bcch_bch_msg(5:6);
act_sfn = bcch_bch_msg(7:14);
% Construct bandwidth
act_bw = 4*act_bw(1) + 2*act_bw(2) + act_bw(3);
......@@ -87,4 +87,4 @@ function [bw, phich_dur, phich_res, sfn] = lte_mib_unpack(mib)
for(n=0:7)
sfn = sfn + act_sfn(n+1)*2^(9-n);
endfor
endfunction
\ No newline at end of file
endfunction
%
% Copyright 2012 Ben Wojtowicz
%
% This program is free software: you can redistribute it and/or modify
% it under the terms of the GNU Affero General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% This program is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
% GNU Affero General Public License for more details.
%
% You should have received a copy of the GNU Affero General Public License
% along with this program. If not, see <http://www.gnu.org/licenses/>.
%
% Function: lte_bcch_dlsch_msg_pack
% Description: Packs all of the fields into the BCCH DLSCH message
% Inputs: sib_num - SIB number
% sib - SIB message
% Outputs: bcch_dlsch_msg - Packed BCCH DLSCH message
% Spec: 3GPP TS 36.331 section 6.2.1 and 6.2.2 v10.0.0
% Notes: Currently only supports SIB1
% Rev History: Ben Wojtowicz 1/22/2012 Created
%
function [bcch_dlsch_msg] = lte_bcch_dlsch_msg_pack(sib_num, sib)
% Check sib_num
if(sib_num == 1)
ext_bit = 0;
sib_choice_bit = 1;
bcch_dlsch_msg = [ext_bit, sib_choice_bit, sib];
else
printf("ERROR: Invalid sib_num %u\n", sib_num);
bcch_dlsch_msg = 0;
return;
endif
endfunction
%
% Copyright 2012 Ben Wojtowicz
%
% This program is free software: you can redistribute it and/or modify
% it under the terms of the GNU Affero General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% This program is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
% GNU Affero General Public License for more details.
%
% You should have received a copy of the GNU Affero General Public License
% along with this program. If not, see <http://www.gnu.org/licenses/>.
%
% Function: lte_bcch_dlsch_msg_unpack
% Description: Unpacks all of the fields from the BCCH DLSCH message
% Inputs: bcch_dlsch_msg - Packed BCCH DLSCH message
% Outputs: sib_num - SIB number
% sib - SIB message
% Spec: 3GPP TS 36.331 section 6.2.1 and 6.2.2 v10.0.0
% Notes: Currently only supports SIB1
% Rev History: Ben Wojtowicz 1/22/2012 Created
%
function [sib_num, sib] = lte_bcch_dlsch_msg_unpack(bcch_dlsch_msg)
% Initialize the message index
idx = 0;
% Skip the extension bit
idx = idx + 1;
% Extract the sib1_choice_bit
sib1_choice_bit = bcch_dlsch_msg(idx+1);
idx = idx + 1;
% Determine if SIB1 or another SIB was received
if(sib1_choice_bit == 1)
% SIB 1 was received
sib_num = 1;
sib = bcch_dlsch_msg(idx+1:end);
else
printf("ERROR: Invalid BCCH DLSCH message\n");
sib_num = 0;
sib = 0;
endif
endfunction
......@@ -24,22 +24,14 @@
% Notes: None
% Rev History: Ben Wojtowicz 11/12/2011 Created
% Ben Wojtowicz 01/29/2012 Fixed license statement
% Ben Wojtowicz 02/19/2012 Commonized rate unmatcher and
% removed conversion to hard bits
%
function [mib, N_ant] = lte_bch_channel_decode(bch_bits)
% Rate match to get the d_bits
d_bits = lte_rate_unmatch(bch_bits);
% Rate unmatch to get the d_bits
d_bits = lte_rate_unmatch_conv(bch_bits, 40);
d_bits = reshape(d_bits, 1, []);
% Convert from soft NRZ to hard bits for viterbi decoder
for(n=1:length(d_bits))
if(d_bits(n) > 0)
d_bits(n) = 0;
else
d_bits(n) = 1;
endif
endfor
% Viterbi decode the d_bits to get the c_bits
c_bits = cmn_viterbi_decode(d_bits, 7, 3, [133, 171, 165]);
......@@ -79,116 +71,3 @@ function [mib, N_ant] = lte_bch_channel_decode(bch_bits)
mib = 0;
endif
endfunction
function [d_bits] = lte_rate_unmatch(e_bits)
% In order to undo bit collection, selection and transmission, a dummy block must be
% sub-block interleaved to determine where NULL bits are to be inserted
% Sub block interleaving
% Step 1: Assign C_cc_sb to 32
C_cc_sb = 32;
% Step 2: Determine the number of rows
R_cc_sb = 0;
d_bits_len = 40; % FIXME This is specific for BCH
while(d_bits_len > (C_cc_sb*R_cc_sb))
R_cc_sb = R_cc_sb + 1;
endwhile
% Inter-column permutation values
ic_perm = [1, 17, 9, 25, 5, 21, 13, 29, 3, 19, 11, 27, 7, 23, 15, 31, 0, 16, 8, 24, 4, 20, 12, 28, 2, 18, 10, 26, 6, 22, 14, 30] + 1;
% Steps 3, 4, and 5
for(x=0:3-1)
% Step 3: Pack data into matrix and pad with dummy (NULL==10000 for this routine)
if(d_bits_len < (C_cc_sb*R_cc_sb))
N_dummy = C_cc_sb*R_cc_sb - d_bits_len;
else
N_dummy = 0;
endif
tmp = [10000*ones(1, N_dummy), zeros(1,d_bits_len)];
idx = 0;
for(n=0:R_cc_sb-1)
for(m=0:C_cc_sb-1)
sb_mat(n+1,m+1) = tmp(idx+1);
idx = idx + 1;
endfor
endfor
% Step 4: Inter-column permutation
for(n=0:R_cc_sb-1)
for(m=0:C_cc_sb-1)
sb_perm_mat(n+1,m+1) = sb_mat(n+1,ic_perm(m+1));
endfor
endfor
% Step 5: Read out the bits
idx = 0;
for(m=0:C_cc_sb-1)
for(n=0:R_cc_sb-1)
v(x+1,idx+1) = sb_perm_mat(n+1,m+1);
idx = idx + 1;
endfor
endfor
endfor
% Undo bit collection, selection, and transmission by recreating the circular buffer
K_pi = R_cc_sb*C_cc_sb;
K_w = 3*K_pi;
w_dum = [v(1,:), v(2,:), v(3,:)];
w = 10000*ones(1,K_w);
E = 1920;
k_idx = 0;
j_idx = 0;
while(k_idx < E)
if(w_dum(mod(j_idx, K_w)+1) != 10000)
% FIXME: soft combine the inputs
if(w(mod(j_idx, K_w)+1) == 10000)
w(mod(j_idx, K_w)+1) = e_bits(k_idx+1);
% elseif(e_bits(k_idx+1) != 10000)
% w(mod(j_idx, K_w)+1) = w(mod(j_idx, K_w)+1) + e_bits(k_idx+1);
endif
k_idx = k_idx + 1;
endif
j_idx = j_idx + 1;
endwhile
% Recreate sub-block interleaver output
v(1,:) = w(1:K_pi);
v(2,:) = w(K_pi+1:2*K_pi);
v(3,:) = w(2*K_pi+1:end);
% Sub block deinterleaving
% Steps 5, 4, and 3
for(x=0:3-1)
% Step 5: Load the permuted matrix
idx = 0;
for(m=0:C_cc_sb-1)
for(n=0:R_cc_sb-1)
sb_perm_mat(n+1,m+1) = v(x+1,idx+1);
idx = idx + 1;
endfor
endfor
% Step 4: Undo permutation
for(n=0:R_cc_sb-1)
for(m=0:C_cc_sb-1)
sb_mat(n+1,ic_perm(m+1)) = sb_perm_mat(n+1,m+1);
endfor
endfor
% Step 3: Unpack the data and remove dummy
if(d_bits_len < (C_cc_sb*R_cc_sb))
N_dummy = C_cc_sb*R_cc_sb - d_bits_len;
else
N_dummy = 0;
endif
idx = 0;
for(n=0:R_cc_sb-1)
for(m=0:C_cc_sb-1)
tmp(idx+1) = sb_mat(n+1,m+1);
idx = idx + 1;
endfor
endfor
d_bits(x+1,:) = tmp(N_dummy+1:end);
endfor
endfunction
......@@ -24,6 +24,7 @@
% Notes: None
% Rev History: Ben Wojtowicz 10/30/2011 Created
% Ben Wojtowicz 01/29/2012 Fixed license statement
% Ben Wojtowicz 02/19/2012 Commonized rate matcher
%
function [bch_bits] = lte_bch_channel_encode(mib, N_ant)
% Check mib
......@@ -65,76 +66,8 @@ function [bch_bits] = lte_bch_channel_encode(mib, N_ant)
d_bits = reshape(d_bits, 3, []);
% Determine e_bits
e_bits = lte_rate_match(d_bits);
e_bits = lte_rate_match_conv(d_bits, 1920);
% Return the e_bits
bch_bits = e_bits;
endfunction
function [e_bits] = lte_rate_match(d_bits)
[this_is_three, d_bits_len] = size(d_bits);
% Sub block interleaving
% Step 1: Assign C_cc_sb to 32
C_cc_sb = 32;
% Step 2: Determine the number of rows
R_cc_sb = 0;
while(d_bits_len > (C_cc_sb*R_cc_sb))
R_cc_sb = R_cc_sb + 1;
endwhile
% Inter-column permutation values
ic_perm = [1, 17, 9, 25, 5, 21, 13, 29, 3, 19, 11, 27, 7, 23, 15, 31, 0, 16, 8, 24, 4, 20, 12, 28, 2, 18, 10, 26, 6, 22, 14, 30] + 1;
% Steps 3, 4, and 5
for(x=0:this_is_three-1)
% Step 3: Pack data into matrix and pad with dummy (NULL==10000 for this routine)
if(d_bits_len < (C_cc_sb*R_cc_sb))
N_dummy = C_cc_sb*R_cc_sb - d_bits_len;
else
N_dummy = 0;
endif
tmp = [10000*ones(1, N_dummy), d_bits(x+1,:)];
idx = 0;
for(n=0:R_cc_sb-1)
for(m=0:C_cc_sb-1)
sb_mat(n+1,m+1) = tmp(idx+1);
idx = idx + 1;
endfor
endfor
% Step 4: Inter-column permutation
for(n=0:R_cc_sb-1)
for(m=0:C_cc_sb-1)
sb_perm_mat(n+1,m+1) = sb_mat(n+1,ic_perm(m+1));
endfor
endfor
% Step 5: Read out the bits
idx = 0;
for(m=0:C_cc_sb-1)
for(n=0:R_cc_sb-1)
v(x+1,idx+1) = sb_perm_mat(n+1,m+1);
idx = idx + 1;
endfor
endfor
endfor
K_pi = R_cc_sb*C_cc_sb;
% Bit collection, selection and transmission
% Create circular buffer and define E, the number of output bits
w = [v(1,:), v(2,:), v(3,:)];
K_w = 3*K_pi;
E = 1920;
% Create output
k_idx = 0;
j_idx = 0;
while(k_idx < E)
if(w(mod(j_idx, K_w)+1) ~= 10000)
e_bits(k_idx+1) = w(mod(j_idx, K_w)+1);
k_idx = k_idx + 1;
endif
j_idx = j_idx + 1;
endwhile
endfunction
\ No newline at end of file
......@@ -24,8 +24,18 @@
% Notes: None
% Rev History: Ben Wojtowicz 12/26/2011 Created
% Ben Wojtowicz 01/29/2012 Fixed license statement
% Ben Wojtowicz 02/19/2012 Added conversion to hard bits
%
function [cfi] = lte_cfi_channel_decode(cfi_bits)
% Convert from soft NRZ to hard bits
for(n=1:length(cfi_bits))
if(cfi_bits(n) >= 0)
cfi_bits(n) = 0;
else
cfi_bits(n) = 1;
endif
endfor
% Calculate the number of bit errors for each CFI
cfi_bits_1 = [0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1];
cfi_bits_2 = [1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0];
......
%
% Copyright 2012 Ben Wojtowicz
%
% This program is free software: you can redistribute it and/or modify
% it under the terms of the GNU Affero General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% This program is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
% GNU Affero General Public License for more details.
%
% You should have received a copy of the GNU Affero General Public License
% along with this program. If not, see <http://www.gnu.org/licenses/>.
%
% Function: lte_code_block_concatenation
% Description: Performs code block concatenation for turbo coded channels
% Inputs: in_bits - Code block bits to be concatenated
% Outputs: out_bits - Code block concatenated bits
% Spec: 3GPP TS 36.212 section 5.1.5 v10.1.0
% Notes: None
% Rev History: Ben Wojtowicz 01/09/2012 Created
%
function [out_bits] = lte_code_block_concatenation(in_bits)
[C, in_bits_len] = size(in_bits);
% Concatenate code blocks
k_idx = 0;
r_idx = 0;
while(r_idx < C)
j_idx = 0;
while(j_idx < in_bits_len)
out_bits(k_idx+1) = in_bits(r_idx+1,j_idx+1);
k_idx = k_idx + 1;
j_idx = j_idx + 1;
endwhile
r_idx = r_idx + 1;
endwhile
endfunction
%
% Copyright 2012 Ben Wojtowicz
%
% This program is free software: you can redistribute it and/or modify
% it under the terms of the GNU Affero General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% This program is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
% GNU Affero General Public License for more details.
%
% You should have received a copy of the GNU Affero General Public License
% along with this program. If not, see <http://www.gnu.org/licenses/>.
%
% Function: lte_code_block_deconcatenation
% Description: Undoes code block concatenation for turbo coded channels
% Inputs: in_bits - Code block bits to be deconcatenated
% tbs - Transport block size for the channel
% Outputs: out_bits - Code block deconcatenated bits
% Spec: 3GPP TS 36.212 section 5.1.5 v10.1.0
% Notes: None
% Rev History: Ben Wojtowicz 01/10/2012 Created
%
function [out_bits] = lte_code_block_deconcatenation(in_bits, tbs)
% Define K table 36.212 Table 5.1.3-3 v10.1.0
k_table = [40,48,56,64,72,80,88,96,104,112,120,128,136,144,152,160,168,176,184,192,200,208,216,224,232,240,248,256,264,272,280,288,296,304,312,320,328,336,344,352,360,368,376,384,392,400,408,416,424,432,440,448,456,464,472,480,488,496,504,512,528,544,560,576,592,608,624,640,656,672,688,704,720,736,752,768,784,800,816,832,848,864,880,896,912,928,944,960,976,992,1008,1024,1056,1088,1120,1152,1184,1216,1248,1280,1312,1344,1376,1408,1440,1472,1504,1536,1568,1600,1632,1664,1696,1728,1760,1792,1824,1856,1888,1920,1952,1984,2016,2048,2112,2176,2240,2304,2368,2432,2496,2560,2624,2688,2752,2816,2880,2944,3008,3072,3136,3200,3264,3328,3392,3456,3520,3584,3648,3712,3776,3840,3904,3968,4032,4096,4160,4224,4288,4352,4416,4480,4544,4608,4672,4736,4800,4864,4928,4992,5056,5120,5184,5248,5312,5376,5440,5504,5568,5632,5696,5760,5824,5888,5952,6016,6080,6144];
% Determine L, C, B', K+, C+, K-, and C- 36.212 section 5.1.2 v10.1.0
Z = 6144;
if(tbs <= Z)
L = 0;
C = 1;
B_prime = length(in_bits);
for(n=0:length(k_table)-1)
if(C*k_table(n+1) >= B_prime)
K_plus = k_table(n+1);
break;
endif
endfor
K_minus = 0;
C_plus = 1;
C_minus = 0;
else
B = tbs + 24;
L = 24;
C = ceil(B/(Z-L));
B_prime = B + C*L;
for(n=0:length(k_table)-1)
if(C*k_table(n+1) >= B_prime)
K_plus = k_table(n+1);
break;
endif
endfor
for(n=length(k_table)-1:-1:0)
if(k_table(n+1) < K_plus)
K_minus = k_table(n+1);
break;
endif
endfor
K_delta = K_plus - K_minus;
C_minus = floor((C*K_plus - B_prime)/K_delta);
C_plus = C - C_minus;
endif
out_s.num_cb = C;
out_bits_len = length(in_bits)/C;
% Deconcatenate code blocks
k_idx = 0;
r_idx = 0;
while(r_idx < C)
j_idx = 0;
while(j_idx < out_bits_len)
out_bits(r_idx+1,j_idx+1) = in_bits(k_idx+1);
k_idx = k_idx + 1;
j_idx = j_idx + 1;
endwhile
r_idx = r_idx + 1;
endwhile
endfunction
%
% Copyright 2012 Ben Wojtowicz
%
% This program is free software: you can redistribute it and/or modify
% it under the terms of the GNU Affero General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% This program is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the