diff --git a/.gitignore b/.gitignore index 59a9775..fa14071 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ *.m~ .DS_Store *.bak +*.asv diff --git a/NRDemodulator.m b/NRDemodulator.m index c80c9d4..d1b325d 100644 --- a/NRDemodulator.m +++ b/NRDemodulator.m @@ -29,15 +29,17 @@ end function ModulationOrder = get.ModulationOrder(obj) - if strcmp(obj.Modulation, 'BPSK') + Modulation_ = obj.Modulation; + + if strcmp(Modulation_, 'BPSK') ModulationOrder = 2; - elseif strcmp(obj.Modulation, 'QPSK') + elseif strcmp(Modulation_, 'QPSK') ModulationOrder = 4; - elseif strcmp(obj.Modulation, '16QAM') + elseif strcmp(Modulation_, '16QAM') ModulationOrder = 16; - elseif strcmp(obj.Modulation, '64QAM') + elseif strcmp(Modulation_, '64QAM') ModulationOrder = 64; - elseif strcmp(obj.Modulation, '256QAM') + elseif strcmp(Modulation_, '256QAM') ModulationOrder = 256; else error('ldpc_3gpp_matlab:UnsupportedParameters','Unsupported modulation'); @@ -45,15 +47,17 @@ end function Q_m = get.Q_m(obj) - if strcmp(obj.Modulation, 'BPSK') + Modulation_ = obj.Modulation; + + if strcmp(Modulation_, 'BPSK') Q_m = 1; - elseif strcmp(obj.Modulation, 'QPSK') + elseif strcmp(Modulation_, 'QPSK') Q_m = 2; - elseif strcmp(obj.Modulation, '16QAM') + elseif strcmp(Modulation_, '16QAM') Q_m = 4; - elseif strcmp(obj.Modulation, '64QAM') + elseif strcmp(Modulation_, '64QAM') Q_m = 6; - elseif strcmp(obj.Modulation, '256QAM') + elseif strcmp(Modulation_, '256QAM') Q_m = 8; else error('ldpc_3gpp_matlab:UnsupportedParameters','Unsupported modulation'); @@ -66,15 +70,17 @@ methods(Access = protected) function setupImpl(obj) - if strcmp(obj.Modulation, 'BPSK') + Modulation_ = obj.Modulation; + + if strcmp(Modulation_, 'BPSK') obj.hMod = comm.PSKDemodulator('ModulationOrder',2,'PhaseOffset',pi/4,'BitOutput',true,'DecisionMethod',obj.DecisionMethod,'Variance',obj.Variance); - elseif strcmp(obj.Modulation, 'QPSK') + elseif strcmp(Modulation_, 'QPSK') obj.hMod = comm.PSKDemodulator('ModulationOrder',4,'PhaseOffset',pi/4,'BitOutput',true,'DecisionMethod',obj.DecisionMethod,'Variance',obj.Variance,'SymbolMapping','Custom','CustomSymbolMapping',[0 2 3 1]); - elseif strcmp(obj.Modulation, '16QAM') + elseif strcmp(Modulation_, '16QAM') obj.hMod = comm.RectangularQAMDemodulator('ModulationOrder',16,'BitOutput',true,'NormalizationMethod','Average power','DecisionMethod',obj.DecisionMethod,'Variance',obj.Variance,'SymbolMapping','Custom','CustomSymbolMapping',[11,10,14,15,9,8,12,13,1,0,4,5,3,2,6,7]); - elseif strcmp(obj.Modulation, '64QAM') + elseif strcmp(Modulation_, '64QAM') obj.hMod = comm.RectangularQAMDemodulator('ModulationOrder',64,'BitOutput',true,'NormalizationMethod','Average power','DecisionMethod',obj.DecisionMethod,'Variance',obj.Variance,'SymbolMapping','Custom','CustomSymbolMapping',[47,46,42,43,59,58,62,63,45,44,40,41,57,56,60,61,37,36,32,33,49,48,52,53,39,38,34,35,51,50,54,55,7,6,2,3,19,18,22,23,5,4,0,1,17,16,20,21,13,12,8,9,25,24,28,29,15,14,10,11,27,26,30,31]); - elseif strcmp(obj.Modulation, '256QAM') + elseif strcmp(Modulation_, '256QAM') obj.hMod = comm.RectangularQAMDemodulator('ModulationOrder',256,'BitOutput',true,'NormalizationMethod','Average power','DecisionMethod',obj.DecisionMethod,'Variance',obj.Variance,'SymbolMapping','Custom','CustomSymbolMapping',[191,190,186,187,171,170,174,175,239,238,234,235,251,250,254,255,189,188,184,185,169,168,172,173,237,236,232,233,249,248,252,253,181,180,176,177,161,160,164,165,229,228,224,225,241,240,244,245,183,182,178,179,163,162,166,167,231,230,226,227,243,242,246,247,151,150,146,147,131,130,134,135,199,198,194,195,211,210,214,215,149,148,144,145,129,128,132,133,197,196,192,193,209,208,212,213,157,156,152,153,137,136,140,141,205,204,200,201,217,216,220,221,159,158,154,155,139,138,142,143,207,206,202,203,219,218,222,223,31,30,26,27,11,10,14,15,79,78,74,75,91,90,94,95,29,28,24,25,9,8,12,13,77,76,72,73,89,88,92,93,21,20,16,17,1,0,4,5,69,68,64,65,81,80,84,85,23,22,18,19,3,2,6,7,71,70,66,67,83,82,86,87,55,54,50,51,35,34,38,39,103,102,98,99,115,114,118,119,53,52,48,49,33,32,36,37,101,100,96,97,113,112,116,117,61,60,56,57,41,40,44,45,109,108,104,105,121,120,124,125,63,62,58,59,43,42,46,47,111,110,106,107,123,122,126,127]); else error('ldpc_3gpp_matlab:UnsupportedParameters','Unsupported modulation'); diff --git a/NRLDPC.m b/NRLDPC.m index 6b2fe3b..865a8c8 100644 --- a/NRLDPC.m +++ b/NRLDPC.m @@ -319,9 +319,11 @@ % K_cb is calculated in Section 5.2.2 of TS38.212 function K_cb = get.K_cb(obj) - if obj.BG == 1 + BG_ = obj.BG; + + if BG_ == 1 K_cb = 8448; - elseif obj.BG == 2 + elseif BG_ == 2 K_cb = 3840; else error('ldpc_3gpp_matlab:UnsupportedParameters','BG must be 1 or 2'); @@ -330,10 +332,14 @@ % C is calculated in Section 5.2.2 of TS38.212 function C = get.C(obj) - if obj.B <= obj.K_cb + B_ = obj.B; + K_cb_ = obj.K_cb; + code_block_L_ = obj.code_block_L; + + if B_ <= K_cb_ C = 1; else - C = ceil(obj.B/(obj.K_cb-obj.code_block_L)); + C = ceil(B_/(K_cb_-code_block_L_)); end end @@ -358,10 +364,15 @@ % B_prime is calculated in Section 5.2.2 of TS38.212 function B_prime = get.B_prime(obj) - if obj.B <= obj.K_cb - B_prime = obj.B; + B_ = obj.B; + K_cb_ = obj.K_cb; + C_ = obj.C; + code_block_L_ = obj.code_block_L; + + if B_ <= K_cb_ + B_prime = B_; else - B_prime = obj.B + obj.C*obj.code_block_L; + B_prime = B_ + C_*code_block_L_; end end @@ -372,16 +383,19 @@ % The calculation of K_b is given in Section 5.2.2 of TS38.212. function K_b = get.K_b(obj) - if obj.BG == 1 + BG_ = obj.BG; + K_prime_ = obj.K_prime; + + if BG_ == 1 K_b = 22; - elseif obj.BG == 2 + elseif BG_ == 2 % TS38.212 uses B rather than K_prime for the comparisons % below, but both ways give the same answer in all cases - if obj.K_prime > 640 + if K_prime_ > 640 K_b = 10; - elseif obj.K_prime > 560 + elseif K_prime_ > 560 K_b = 9; - elseif obj.K_prime > 192 + elseif K_prime_ > 192 K_b = 8; else K_b = 6; @@ -398,10 +412,13 @@ % The calculation of K is given in Section 5.2.2 of TS38.212. function K = get.K(obj) - if obj.BG == 1 - K = obj.Z_c*22; - elseif obj.BG == 2 - K = obj.Z_c*10; + BG_ = obj.BG; + Z_c_ = obj.Z_c; + + if BG_ == 1 + K = Z_c_*22; + elseif BG_ == 2 + K = Z_c_*10; else error('ldpc_3gpp_matlab:UnsupportedParameters','Valid values of BG are 1 and 2.'); end @@ -424,10 +441,13 @@ % The calculation of N is given in Section 5.3.2 of TS38.212. function N = get.N(obj) - if obj.BG == 1 - N = obj.Z_c*66; - elseif obj.BG == 2 - N = obj.Z_c*50; + BG_ = obj.BG; + Z_c_ = obj.Z_c; + + if BG_ == 1 + N = Z_c_*66; + elseif BG_ == 2 + N = Z_c_*50; else error('ldpc_3gpp_matlab:UnsupportedParameters','Valid values of BG are 1 and 2.'); end @@ -449,8 +469,11 @@ end function CBGTI_flags = get.CBGTI_flags(obj) - CBGTI_flags = ones(1,obj.C); - CBGTI_flags(obj.CBGTI(obj.CBGTI 0 + if code_block_L_ > 0 obj.hCBCRCDetector = comm.CRCDetector('Polynomial',obj.code_block_CRC_polynomial); end - % try - % obj.hLDPCDecoder = comm.gpu.LDPCDecoder('ParityCheckMatrix',obj.H,'MaximumIterationCount',obj.iterations,'IterationTerminationCondition','Parity check satisfied'); - % catch - obj.hLDPCDecoder = comm.LDPCDecoder('ParityCheckMatrix',obj.H,'MaximumIterationCount',obj.iterations,'IterationTerminationCondition','Parity check satisfied'); - % end - obj.d_tilde_buffer = cell(obj.C,1); - for r=0:obj.C-1 - obj.d_tilde_buffer{r+1} = zeros(obj.N_cb,1); +% try +% obj.hLDPCDecoder = comm.gpu.LDPCDecoder('ParityCheckMatrix',obj.H,'MaximumIterationCount',obj.iterations,'IterationTerminationCondition','Parity check satisfied'); +% catch + obj.hLDPCDecoder = comm.LDPCDecoder('ParityCheckMatrix',obj.H,'MaximumIterationCount',obj.iterations,'IterationTerminationCondition','Parity check satisfied'); +% end + d_tilde_buffer_ = cell(C_,1); + for r=0:C_-1 + d_tilde_buffer_{r+1} = zeros(N_cb_,1); end + obj.d_tilde_buffer = d_tilde_buffer_; - obj.b_hat_buffer = zeros(obj.B,1); - obj.code_block_CRC_passed = zeros(obj.C,1); + obj.b_hat_buffer = zeros(B_,1); + obj.code_block_CRC_passed = zeros(C_,1); end @@ -135,21 +141,25 @@ function setupImpl(obj) % Implements Section 5.5 of TS38.212 function f_tilde = code_block_concatenation(obj, g_tilde) - if size(g_tilde,1) ~= obj.G || size(g_tilde,2) ~= 1 + G_ = obj.G; + C_ = obj.C; + E_r_ = obj.E_r; + + if size(g_tilde,1) ~= G_ || size(g_tilde,2) ~= 1 error('ldpc_3gpp_matlab:Error','g_tilde should be a column vector of length G.'); end - f_tilde = cell(obj.C,1); - for r = 0:obj.C-1 - f_tilde{r+1} = zeros(obj.E_r(r+1), 1); + f_tilde = cell(C_,1); + for r = 0:C_-1 + f_tilde{r+1} = zeros(E_r_(r+1), 1); end k = 0; r = 0; - while r < obj.C + while r < C_ j = 0; - while j < obj.E_r(r+1) + while j < E_r_(r+1) f_tilde{r+1}(j+1) = g_tilde(k+1); k = k + 1; j = j + 1; @@ -160,23 +170,27 @@ function setupImpl(obj) % Implements Section 5.4.2.2 of TS38.212 function e_tilde = bit_interleaving(obj, f_tilde) - if size(f_tilde,1) ~= obj.C || size(f_tilde,2) ~= 1 + C_ = obj.C; + E_r_ = obj.E_r; + Q_m_ = obj.Q_m; + + if size(f_tilde,1) ~= C_ || size(f_tilde,2) ~= 1 error('ldpc_3gpp_matlab:Error','f_tilde should be a column cell array of length C.'); end - e_tilde = cell(obj.C,1); + e_tilde = cell(C_,1); - for r = 0:obj.C-1 + for r = 0:C_-1 - if size(f_tilde{r+1},1) ~= obj.E_r(r+1) || size(f_tilde{r+1},2) ~= 1 + if size(f_tilde{r+1},1) ~= E_r_(r+1) || size(f_tilde{r+1},2) ~= 1 error('ldpc_3gpp_matlab:Error','f_tilde{r+1} should be a column vector of length E_r(r+1).'); end - e_tilde{r+1} = zeros(obj.E_r(r+1),1); + e_tilde{r+1} = zeros(E_r_(r+1),1); - for j = 0:obj.E_r(r+1)/obj.Q_m-1 - for i = 0:obj.Q_m-1 - e_tilde{r+1}(i*obj.E_r(r+1)/obj.Q_m+j+1) = f_tilde{r+1}(i+j*obj.Q_m+1); + for j = 0:E_r_(r+1)/Q_m_-1 + for i = 0:Q_m_-1 + e_tilde{r+1}(i*E_r_(r+1)/Q_m_+j+1) = f_tilde{r+1}(i+j*Q_m_+1); end end end @@ -184,52 +198,69 @@ function setupImpl(obj) % Implements Section 5.4.2.1 of TS38.212 function d_tilde = bit_selection(obj, e_tilde) - if size(e_tilde,1) ~= obj.C || size(e_tilde,2) ~= 1 + C_ = obj.C; + E_r_ = obj.E_r; + N_ = obj.N; + K_prime_ = obj.K_prime; + Z_c_ = obj.Z_c; + K_ = obj.K; + k_0_ = obj.k_0; + N_cb_ = obj.N_cb; + I_HARQ_ = obj.I_HARQ; + d_tilde_buffer_ = obj.d_tilde_buffer; + + if size(e_tilde,1) ~= C_ || size(e_tilde,2) ~= 1 error('ldpc_3gpp_matlab:Error','e_tilde should be a column cell array of length C.'); end - d_tilde = cell(obj.C,1); + d_tilde = cell(C_,1); - for r=0:obj.C-1 - if size(e_tilde{r+1},1) ~= obj.E_r(r+1) || size(e_tilde{r+1},2) ~= 1 + for r=0:C_-1 + if size(e_tilde{r+1},1) ~= E_r_(r+1) || size(e_tilde{r+1},2) ~= 1 error('ldpc_3gpp_matlab:Error','e_tilde{r+1} should be a column vector of length E_r(r+1).'); end - d_tilde{r+1} = zeros(obj.N,1); - d_tilde{r+1}(max(obj.K_prime-2*obj.Z_c+1,1):obj.K-2*obj.Z_c) = NaN; + d_tilde{r+1} = zeros(N_,1); + d_tilde{r+1}(max(K_prime_-2*Z_c_+1,1):K_-2*Z_c_) = NaN; k = 0; j = 0; - while k < obj.E_r(r+1) - if ~isnan(d_tilde{r+1}(mod(obj.k_0 + j, obj.N_cb)+1)) - d_tilde{r+1}(mod(obj.k_0 + j, obj.N_cb)+1) = d_tilde{r+1}(mod(obj.k_0 + j, obj.N_cb)+1) + e_tilde{r+1}(k+1); + while k < E_r_(r+1) + if ~isnan(d_tilde{r+1}(mod(k_0_ + j, N_cb_)+1)) + d_tilde{r+1}(mod(k_0_ + j, N_cb_)+1) = d_tilde{r+1}(mod(k_0_ + j, N_cb_)+1) + e_tilde{r+1}(k+1); k = k+1; end j = j+1; end - if obj.I_HARQ ~= 0 - d_tilde{r+1}(1:obj.N_cb) = d_tilde{r+1}(1:obj.N_cb) + obj.d_tilde_buffer{r+1}; - obj.d_tilde_buffer{r+1} = d_tilde{r+1}(1:obj.N_cb); + if I_HARQ_ ~= 0 + d_tilde{r+1}(1:N_cb_) = d_tilde{r+1}(1:N_cb_) + d_tilde_buffer_{r+1}; + d_tilde_buffer_{r+1} = d_tilde{r+1}(1:N_cb_); end end + obj.d_tilde_buffer = d_tilde_buffer_; end % Implements Section 5.3.2 of TS38.212 function c_hat = LDPC_coding(obj, d_tilde) - if size(d_tilde,1) ~= obj.C || size(d_tilde,2) ~= 1 + C_ = obj.C; + N_ = obj.N; + Z_c_ = obj.Z_c; + K_ = obj.K; + + if size(d_tilde,1) ~= C_ || size(d_tilde,2) ~= 1 error('ldpc_3gpp_matlab:Error','d_tilde should be a column cell array of length C.'); end - c_hat = cell(obj.C,1); + c_hat = cell(C_,1); - for r=0:obj.C-1 - if size(d_tilde{r+1},1) ~= obj.N || size(d_tilde{r+1},2) ~= 1 + for r=0:C_-1 + if size(d_tilde{r+1},1) ~= N_ || size(d_tilde{r+1},2) ~= 1 error('ldpc_3gpp_matlab:Error','d_tilde{r+1} should be a column vector of length N.'); end - cw_tilde = [zeros(2*obj.Z_c,1); d_tilde{r+1}]; - c_tilde = cw_tilde(1:obj.K); + cw_tilde = [zeros(2*Z_c_,1); d_tilde{r+1}]; + c_tilde = cw_tilde(1:K_); cw_tilde(isnan(cw_tilde)) = inf; c_hat{r+1} = double(step(obj.hLDPCDecoder, cw_tilde)); c_hat{r+1}(isnan(c_tilde)) = NaN; @@ -238,68 +269,90 @@ function setupImpl(obj) % Implements Section 5.2.2 of TS38.212 function b_hat = code_block_segmentation(obj, c_hat) - if size(c_hat,1) ~= obj.C || size(c_hat,2) ~= 1 + C_ = obj.C; + I_HARQ_ = obj.I_HARQ; + b_hat_buffer_ = obj.b_hat_buffer; + B_ = obj.B; + K_ = obj.K; + K_prime_ = obj.K_prime; + code_block_L_ = obj.code_block_L; + CBGTI_flags_ = obj.CBGTI_flags; + code_block_CRC_passed_ = obj.code_block_CRC_passed; + + if size(c_hat,1) ~= C_ || size(c_hat,2) ~= 1 error('ldpc_3gpp_matlab:Error','c_hat should be a column cell array of length C.'); end - if obj.I_HARQ ~= 0 - b_hat = obj.b_hat_buffer; + if I_HARQ_ ~= 0 + b_hat = b_hat_buffer_; else - b_hat = zeros(obj.B,1); + b_hat = zeros(B_,1); end s = 0; - for r = 0:obj.C-1 - if size(c_hat{r+1},1) ~= obj.K || size(c_hat,2) ~= 1 + for r = 0:C_-1 + if size(c_hat{r+1},1) ~= K_ || size(c_hat,2) ~= 1 error('ldpc_3gpp_matlab:Error','c_hat should be a column vector of length K.'); end code_block_CRC_failed = false; - if obj.C > 1 - [~,code_block_CRC_failed] = step(obj.hCBCRCDetector,c_hat{r+1}(1:obj.K_prime)); + if C_ > 1 + [~,code_block_CRC_failed] = step(obj.hCBCRCDetector,c_hat{r+1}(1:K_prime_)); end - for k = 0:obj.K_prime-obj.code_block_L-1 - if ~code_block_CRC_failed && obj.CBGTI_flags(r+1) == 1 + for k = 0:K_prime_-code_block_L_-1 + if ~code_block_CRC_failed && CBGTI_flags_(r+1) == 1 b_hat(s+1) = c_hat{r+1}(k+1); - obj.code_block_CRC_passed(r+1) = 1; + code_block_CRC_passed_(r+1) = 1; end s = s + 1; end end - if obj.I_HARQ ~= 0 - obj.b_hat_buffer = b_hat; + if I_HARQ_ ~= 0 + b_hat_buffer_ = b_hat; end + + obj.code_block_CRC_passed = code_block_CRC_passed_; + obj.b_hat_buffer = b_hat_buffer_; end % Implements Section 5.1 of TS38.212 function a_hat = crc_calculation(obj, b_hat) - if size(b_hat,1) ~= obj.B || size(b_hat,2) ~= 1 + B_ = obj.B; + A_ = obj.A; + code_block_CRC_passed_ = obj.code_block_CRC_passed; + + if size(b_hat,1) ~= B_ || size(b_hat,2) ~= 1 error('ldpc_3gpp_matlab:Error','b_hat should be a column vector of length B.'); end - a_hat = zeros(obj.A,1); + a_hat = zeros(A_,1); - for k = 0:obj.A-1 + for k = 0:A_-1 a_hat(k+1) = b_hat(k+1); end [~,transport_block_CRC_failed] = step(obj.hTBCRCDetector,b_hat); - if transport_block_CRC_failed || any(~obj.code_block_CRC_passed) + if transport_block_CRC_failed || any(~code_block_CRC_passed_) a_hat = []; end end function resetImpl(obj) - obj.d_tilde_buffer = cell(obj.C,1); - for r=0:obj.C-1 - obj.d_tilde_buffer{r+1} = zeros(obj.N_cb,1); + C_ = obj.C; + B_ = obj.B; + N_cb_ = obj.N_cb; + + d_tilde_buffer_ = cell(C_,1); + for r=0:C_-1 + d_tilde_buffer_{r+1} = zeros(N_cb_,1); end + obj.d_tilde_buffer = d_tilde_buffer_; - obj.b_hat_buffer = zeros(obj.B,1); - obj.code_block_CRC_passed = zeros(obj.C,1); + obj.b_hat_buffer = zeros(B_,1); + obj.code_block_CRC_passed = zeros(C_,1); end end diff --git a/NRLDPCEncoder.m b/NRLDPCEncoder.m index cf836a1..bd1a12b 100644 --- a/NRLDPCEncoder.m +++ b/NRLDPCEncoder.m @@ -68,47 +68,56 @@ function setupImpl(obj) % Implements Section 5.3.2 of TS38.212 function b = crc_calculation(obj, a) - if size(a,1) ~= obj.A || size(a,2) ~= 1 + A_ = obj.A; + B_ = obj.B; + + if size(a,1) ~= A_ || size(a,2) ~= 1 error('ldpc_3gpp_matlab:Error','a should be a column vector of length A.'); end - b = zeros(obj.B,1); + b = zeros(B_,1); ap = step(obj.hTBCRCGenerator, a); - p = ap(obj.A+1:obj.B); + p = ap(A_+1:B_); - for k = 0:obj.A-1 + for k = 0:A_-1 b(k+1) = a(k+1); end - for k = obj.A:obj.B-1 - b(k+1) = p(k-obj.A+1); + for k = A_:B_-1 + b(k+1) = p(k-A_+1); end end % Implements Section 5.2.2 of TS38.212 function c = code_block_segmentation(obj, b) - if size(b,1) ~= obj.B || size(b,2) ~= 1 + B_ = obj.B; + C_ = obj.C; + K_ = obj.K; + K_prime_ = obj.K_prime; + code_block_L_ = obj.code_block_L; + + if size(b,1) ~= B_ || size(b,2) ~= 1 error('ldpc_3gpp_matlab:Error','b should be a column vector of length B.'); end - c = cell(obj.C,1); + c = cell(C_,1); s = 0; - for r = 0:obj.C-1 - c{r+1} = zeros(obj.K,1); + for r = 0:C_-1 + c{r+1} = zeros(K_,1); - for k = 0:obj.K_prime-obj.code_block_L-1 + for k = 0:K_prime_-code_block_L_-1 c{r+1}(k+1) = b(s+1); s = s + 1; end - if obj.C > 1 - cp = step(obj.hCBCRCGenerator, c{r+1}(1:obj.K_prime-obj.code_block_L)); - p = cp(obj.K_prime-obj.code_block_L+1:obj.K_prime); - for k = obj.K_prime-obj.code_block_L:obj.K_prime-1 - c{r+1}(k+1) = p(k+obj.code_block_L-obj.K_prime+1); + if C_ > 1 + cp = step(obj.hCBCRCGenerator, c{r+1}(1:K_prime_-code_block_L_)); + p = cp(K_prime_-code_block_L_+1:K_prime_); + for k = K_prime_-code_block_L_:K_prime_-1 + c{r+1}(k+1) = p(k+code_block_L_-K_prime_+1); end end - for k = obj.K_prime:obj.K-1 + for k = K_prime_:K_-1 c{r+1}(k+1) = NaN; end end @@ -116,59 +125,70 @@ function setupImpl(obj) % Implements Section 5.3.2 of TS38.212 function d = LDPC_coding(obj, c) - if size(c,1) ~= obj.C || size(c,2) ~= 1 + C_ = obj.C; + K_ = obj.K; + N_ = obj.N; + Z_c_ = obj.Z_c; + + if size(c,1) ~= C_ || size(c,2) ~= 1 error('ldpc_3gpp_matlab:Error','c should be a column cell array of length C.'); end - d = cell(obj.C,1); + d = cell(C_,1); - for r = 0:obj.C-1 - if size(c{r+1},1) ~= obj.K || size(c{r+1},2) ~= 1 + for r = 0:C_-1 + if size(c{r+1},1) ~= K_ || size(c{r+1},2) ~= 1 error('ldpc_3gpp_matlab:Error','c{r+1} should be a column vector of length K.'); end - d{r+1} = zeros(obj.N,1); + d{r+1} = zeros(N_,1); % Not sure about what to do if there are NaNs within the first - % 2*obj.Z_c elements of c. The following code (adapted from + % 2*Z_c elements of c. The following code (adapted from % TS38.212) does not set these to 0. - for k = 2*obj.Z_c:obj.K-1 + for k = 2*Z_c_:K_-1 if ~isnan(c{r+1}(k+1)) - d{r+1}(k-2*obj.Z_c+1) = c{r+1}(k+1); + d{r+1}(k-2*Z_c_+1) = c{r+1}(k+1); else c{r+1}(k+1) = 0; - d{r+1}(k-2*obj.Z_c+1) = NaN; + d{r+1}(k-2*Z_c_+1) = NaN; end end cw = step(obj.hLDPCEncoder, c{r+1}); - w = cw(obj.K+1:obj.N+2*obj.Z_c); + w = cw(K_+1:N_+2*Z_c_); - for k = obj.K:obj.N+2*obj.Z_c-1 - d{r+1}(k-2*obj.Z_c+1) = w(k-obj.K+1); + for k = K_:N_+2*Z_c_-1 + d{r+1}(k-2*Z_c_+1) = w(k-K_+1); end end end % Implements Section 5.4.2.1 of TS38.212 function e = bit_selection(obj, d) - if size(d,1) ~= obj.C || size(d,2) ~= 1 + C_ = obj.C; + N_ = obj.N; + E_r_ = obj.E_r; + k_0_ = obj.k_0; + N_cb_ = obj.N_cb; + + if size(d,1) ~= C_ || size(d,2) ~= 1 error('ldpc_3gpp_matlab:Error','d should be a column cell array of length C.'); end - e=cell(obj.C,1); + e=cell(C_,1); - for r = 0:obj.C-1 - if size(d{r+1},1) ~= obj.N || size(d{r+1},2) ~= 1 + for r = 0:C_-1 + if size(d{r+1},1) ~= N_ || size(d{r+1},2) ~= 1 error('ldpc_3gpp_matlab:Error','d{r+1} should be a column vector of length N.'); end - e{r+1} = zeros(obj.E_r(r+1),1); + e{r+1} = zeros(E_r_(r+1),1); k = 0; j = 0; - while k < obj.E_r(r+1) - if ~isnan(d{r+1}(mod(obj.k_0 + j, obj.N_cb)+1)) - e{r+1}(k+1) = d{r+1}(mod(obj.k_0 + j, obj.N_cb)+1); + while k < E_r_(r+1) + if ~isnan(d{r+1}(mod(k_0_ + j, N_cb_)+1)) + e{r+1}(k+1) = d{r+1}(mod(k_0_ + j, N_cb_)+1); k = k+1; end j = j+1; @@ -178,23 +198,27 @@ function setupImpl(obj) % Implements Section 5.4.2.2 of TS38.212 function f = bit_interleaving(obj, e) - if size(e,1) ~= obj.C || size(e,2) ~= 1 + C_ = obj.C; + E_r_ = obj.E_r; + Q_m_ = obj.Q_m; + + if size(e,1) ~= C_ || size(e,2) ~= 1 error('ldpc_3gpp_matlab:Error','e should be a column cell array of length C.'); end - f = cell(obj.C,1); + f = cell(C_,1); - for r = 0:obj.C-1 + for r = 0:C_-1 - if size(e{r+1},1) ~= obj.E_r(r+1) || size(e{r+1},2) ~= 1 + if size(e{r+1},1) ~= E_r_(r+1) || size(e{r+1},2) ~= 1 error('ldpc_3gpp_matlab:Error','e{r+1} should be a column vector of length E_r(r+1).'); end - f{r+1} = zeros(obj.E_r(r+1),1); + f{r+1} = zeros(E_r_(r+1),1); - for j = 0:obj.E_r(r+1)/obj.Q_m-1 - for i = 0:obj.Q_m-1 - f{r+1}(i+j*obj.Q_m+1) = e{r+1}(i*obj.E_r(r+1)/obj.Q_m+j+1); + for j = 0:E_r_(r+1)/Q_m_-1 + for i = 0:Q_m_-1 + f{r+1}(i+j*Q_m_+1) = e{r+1}(i*E_r_(r+1)/Q_m_+j+1); end end end @@ -202,23 +226,27 @@ function setupImpl(obj) % Implements Section 5.5 of TS38.212 function g = code_block_concatenation(obj, f) - if size(f,1) ~= obj.C || size(f,2) ~= 1 + C_ = obj.C; + E_r_ = obj.E_r; + G_ = obj.G; + + if size(f,1) ~= C_ || size(f,2) ~= 1 error('ldpc_3gpp_matlab:Error','f should be a column cell array of length C.'); end - for r = 0:obj.C-1 - if size(f{r+1},1) ~= obj.E_r(r+1) || size(f{r+1},2) ~= 1 + for r = 0:C_-1 + if size(f{r+1},1) ~= E_r_(r+1) || size(f{r+1},2) ~= 1 error('ldpc_3gpp_matlab:Error','f{r+1} should be a column vector of length E_r(r+1).'); end end - g = zeros(obj.G,1); + g = zeros(G_,1); k = 0; r = 0; - while r < obj.C + while r < C_ j = 0; - while j < obj.E_r(r+1) + while j < E_r_(r+1) g(k+1) = f{r+1}(j+1); k = k + 1; j = j + 1; diff --git a/NRModulator.m b/NRModulator.m index 0300c63..ae6107f 100644 --- a/NRModulator.m +++ b/NRModulator.m @@ -27,15 +27,17 @@ end function ModulationOrder = get.ModulationOrder(obj) - if strcmp(obj.Modulation, 'BPSK') + Modulation_ = obj.Modulation; + + if strcmp(Modulation_, 'BPSK') ModulationOrder = 2; - elseif strcmp(obj.Modulation, 'QPSK') + elseif strcmp(Modulation_, 'QPSK') ModulationOrder = 4; - elseif strcmp(obj.Modulation, '16QAM') + elseif strcmp(Modulation_, '16QAM') ModulationOrder = 16; - elseif strcmp(obj.Modulation, '64QAM') + elseif strcmp(Modulation_, '64QAM') ModulationOrder = 64; - elseif strcmp(obj.Modulation, '256QAM') + elseif strcmp(Modulation_, '256QAM') ModulationOrder = 256; else error('ldpc_3gpp_matlab:UnsupportedParameters','Unsupported modulation'); @@ -43,15 +45,17 @@ end function Q_m = get.Q_m(obj) - if strcmp(obj.Modulation, 'BPSK') + Modulation_ = obj.Modulation; + + if strcmp(Modulation_, 'BPSK') Q_m = 1; - elseif strcmp(obj.Modulation, 'QPSK') + elseif strcmp(Modulation_, 'QPSK') Q_m = 2; - elseif strcmp(obj.Modulation, '16QAM') + elseif strcmp(Modulation_, '16QAM') Q_m = 4; - elseif strcmp(obj.Modulation, '64QAM') + elseif strcmp(Modulation_, '64QAM') Q_m = 6; - elseif strcmp(obj.Modulation, '256QAM') + elseif strcmp(Modulation_, '256QAM') Q_m = 8; else error('ldpc_3gpp_matlab:UnsupportedParameters','Unsupported modulation'); @@ -63,15 +67,17 @@ methods(Access = protected) function setupImpl(obj) - if strcmp(obj.Modulation, 'BPSK') + Modulation_ = obj.Modulation; + + if strcmp(Modulation_, 'BPSK') obj.hMod = comm.PSKModulator('ModulationOrder',2,'PhaseOffset',pi/4,'BitInput',true); - elseif strcmp(obj.Modulation, 'QPSK') + elseif strcmp(Modulation_, 'QPSK') obj.hMod = comm.PSKModulator('ModulationOrder',4,'PhaseOffset',pi/4,'BitInput',true,'SymbolMapping','Custom','CustomSymbolMapping',[0 2 3 1]); - elseif strcmp(obj.Modulation, '16QAM') + elseif strcmp(Modulation_, '16QAM') obj.hMod = comm.RectangularQAMModulator('ModulationOrder',16,'BitInput',true,'NormalizationMethod','Average power','SymbolMapping','Custom','CustomSymbolMapping',[11,10,14,15,9,8,12,13,1,0,4,5,3,2,6,7]); - elseif strcmp(obj.Modulation, '64QAM') + elseif strcmp(Modulation_, '64QAM') obj.hMod = comm.RectangularQAMModulator('ModulationOrder',64,'BitInput',true,'NormalizationMethod','Average power','SymbolMapping','Custom','CustomSymbolMapping',[47,46,42,43,59,58,62,63,45,44,40,41,57,56,60,61,37,36,32,33,49,48,52,53,39,38,34,35,51,50,54,55,7,6,2,3,19,18,22,23,5,4,0,1,17,16,20,21,13,12,8,9,25,24,28,29,15,14,10,11,27,26,30,31]); - elseif strcmp(obj.Modulation, '256QAM') + elseif strcmp(Modulation_, '256QAM') obj.hMod = comm.RectangularQAMModulator('ModulationOrder',256,'BitInput',true,'NormalizationMethod','Average power','SymbolMapping','Custom','CustomSymbolMapping',[191,190,186,187,171,170,174,175,239,238,234,235,251,250,254,255,189,188,184,185,169,168,172,173,237,236,232,233,249,248,252,253,181,180,176,177,161,160,164,165,229,228,224,225,241,240,244,245,183,182,178,179,163,162,166,167,231,230,226,227,243,242,246,247,151,150,146,147,131,130,134,135,199,198,194,195,211,210,214,215,149,148,144,145,129,128,132,133,197,196,192,193,209,208,212,213,157,156,152,153,137,136,140,141,205,204,200,201,217,216,220,221,159,158,154,155,139,138,142,143,207,206,202,203,219,218,222,223,31,30,26,27,11,10,14,15,79,78,74,75,91,90,94,95,29,28,24,25,9,8,12,13,77,76,72,73,89,88,92,93,21,20,16,17,1,0,4,5,69,68,64,65,81,80,84,85,23,22,18,19,3,2,6,7,71,70,66,67,83,82,86,87,55,54,50,51,35,34,38,39,103,102,98,99,115,114,118,119,53,52,48,49,33,32,36,37,101,100,96,97,113,112,116,117,61,60,56,57,41,40,44,45,109,108,104,105,121,120,124,125,63,62,58,59,43,42,46,47,111,110,106,107,123,122,126,127]); else error('ldpc_3gpp_matlab:UnsupportedParameters','Unsupported modulation');