www.gusucode.com > wlan工具箱matlab源码程序 > wlan/wlan/+wlan/+internal/ldpcDecodeCore.m
function [decoded, actualNumIter, finalParityChecks] = ldpcDecodeCore(LLR, rate, N_Iter, varargin) %LDPCDECODECORE LDPC decoder core % % decoded = ldpcDecodeCore(LLR, rate, N_Iter) decodes the % log-likelihood ratios LLR using a WLAN LDPC code at the specified rate % (rate). % % rate must be equal to '1/2', '2/3', '3/4', or '5/6'. % % N_Iter specifies the number of iterations. % % Each column of LLR specifies the log-likelihood ratios of a codeword. % The number of rows in LLR should be equal to one of the % three valid block lengths: 648, 1296, and 1944. % % See http://www.mathworks.com/help/comm/ref/ldpcdecoder.html for % the definition of log-likelihood ratios and details about the decoding % algorithm. % % By default, decoded are hard-decision outputs for the information bits % of the codewords and ldpcDecodeCore will perform exactly N_Iter % iterations. % % The following optional string inputs are accepted in varargin: % 'whole codeword' - If 'whole codeword' is provided, decoded contains % whole decoded codewords and the number of rows is % equal to the number of rows in LLR; otherwise, % decoded contains the information bits of the % codewords only and the number of rows is equal to % the number of information bits in one codeword. % 'soft decision' - If 'soft decision' is provided, each element in % decoded is a log-likelihood ratio for the % corresponding decoded bit and is of type double; % otherwise, each element is either 0 or 1 and % is of type int8. % 'early exit' - If 'early exit' is provided, after each iteration, % ldpcDecodeCore will determine independently for % each column of LLR if all parity checks are % satisfied, and will stop for column(s) with all % parity checks satisfied; otherwise, the function % will execute exactly N_Iter iterations. % % [decoded, actualNumIter, finalParityChecks] = ldpcDecodeCore(...) % provides optional outputs. % % actualNumIter is a row vector of positive integer(s) whose length is % equal to the number of columns of LLR. The i-th element corresponds % to the actual number of decoding iterations executed for the i-th % column of LLR. % % finalParityChecks is a matrix that holds the final parity checks. % The i-th column corresponds to the final parity checks for the i-th % codeword. The number of rows is equal to the number of parity-check % bits in a codeword. If all elements in finalParityChecks are zeros, % decoded corresponds to a valid codeword. % % See also ldpcEncodeCore, ldpcMatrix. % Copyright 2015-2016 The MathWorks, Inc. %#codegen % Persistent variables for pre-computed data structures for LDPC codes persistent d_1_2_648 % coding rate = 1/2, block length = 648 persistent d_1_2_1296 % coding rate = 1/2, block length = 1296 persistent d_1_2_1944 % coding rate = 1/2, block length = 1944 persistent d_2_3_648 % coding rate = 2/3, block length = 648 persistent d_2_3_1296 % coding rate = 2/3, block length = 1296 persistent d_2_3_1944 % coding rate = 2/3, block length = 1944 persistent d_3_4_648 % coding rate = 3/4, block length = 648 persistent d_3_4_1296 % coding rate = 3/4, block length = 1296 persistent d_3_4_1944 % coding rate = 3/4, block length = 1944 persistent d_5_6_648 % coding rate = 5/6, block length = 648 persistent d_5_6_1296 % coding rate = 5/6, block length = 1296 persistent d_5_6_1944 % coding rate = 5/6, block length = 1944 [blockLength, numCodewords] = size(LLR); % When an LDPC code is used for the first time, % load the corresponding pre-computed data structure and save it in a % persistent variable switch blockLength case 648 if strcmp(rate, '1/2') || isequal(rate, 1/2) infoLen = blockLength * 1/2; if isempty(d_1_2_648) H = wlan.internal.ldpcMatrix('1/2', blockLength); d_1_2_648 = ldpcinit(H); end [rows, cols, NGrp, grplist] = getldpcparams(d_1_2_648); elseif strcmp(rate, '2/3') || isequal(rate, 2/3) infoLen = blockLength * 2/3; if isempty(d_2_3_648) H = wlan.internal.ldpcMatrix('2/3', blockLength); d_2_3_648 = ldpcinit(H); end [rows, cols, NGrp, grplist] = getldpcparams(d_2_3_648); elseif strcmp(rate, '3/4') || isequal(rate, 3/4) infoLen = blockLength * 3/4; if isempty(d_3_4_648) H = wlan.internal.ldpcMatrix('3/4', blockLength); d_3_4_648 = ldpcinit(H); end [rows, cols, NGrp, grplist] = getldpcparams(d_3_4_648); else % case '5/6' infoLen = blockLength * 5/6; if isempty(d_5_6_648) H = wlan.internal.ldpcMatrix('5/6', blockLength); d_5_6_648 = ldpcinit(H); end [rows, cols, NGrp, grplist] = getldpcparams(d_5_6_648); end case 1296 if strcmp(rate, '1/2') || isequal(rate, 1/2) infoLen = blockLength * 1/2; if isempty(d_1_2_1296) H = wlan.internal.ldpcMatrix('1/2', blockLength); d_1_2_1296 = ldpcinit(H); end [rows, cols, NGrp, grplist] = getldpcparams(d_1_2_1296); elseif strcmp(rate, '2/3') || isequal(rate, 2/3) infoLen = blockLength * 2/3; if isempty(d_2_3_1296) H = wlan.internal.ldpcMatrix('2/3', blockLength); d_2_3_1296 = ldpcinit(H); end [rows, cols, NGrp, grplist] = getldpcparams(d_2_3_1296); elseif strcmp(rate, '3/4') || isequal(rate, 3/4) infoLen = blockLength * 3/4; if isempty(d_3_4_1296) H = wlan.internal.ldpcMatrix('3/4', blockLength); d_3_4_1296 = ldpcinit(H); end [rows, cols, NGrp, grplist] = getldpcparams(d_3_4_1296); else % case '5/6' infoLen = blockLength * 5/6; if isempty(d_5_6_1296) H = wlan.internal.ldpcMatrix('5/6', blockLength); d_5_6_1296 = ldpcinit(H); end [rows, cols, NGrp, grplist] = getldpcparams(d_5_6_1296); end otherwise % case 1944 if strcmp(rate, '1/2') || isequal(rate, 1/2) infoLen = blockLength * 1/2; if isempty(d_1_2_1944) H = wlan.internal.ldpcMatrix('1/2', blockLength); d_1_2_1944 = ldpcinit(H); end [rows, cols, NGrp, grplist] = getldpcparams(d_1_2_1944); elseif strcmp(rate, '2/3') || isequal(rate, 2/3) infoLen = blockLength * 2/3; if isempty(d_2_3_1944) H = wlan.internal.ldpcMatrix('2/3', blockLength); d_2_3_1944 = ldpcinit(H); end [rows, cols, NGrp, grplist] = getldpcparams(d_2_3_1944); elseif strcmp(rate, '3/4') || isequal(rate, 3/4) infoLen = blockLength * 3/4; if isempty(d_3_4_1944) H = wlan.internal.ldpcMatrix('3/4', blockLength); d_3_4_1944 = ldpcinit(H); end [rows, cols, NGrp, grplist] = getldpcparams(d_3_4_1944); else % case '5/6' infoLen = blockLength * 5/6; if isempty(d_5_6_1944) H = wlan.internal.ldpcMatrix('5/6', blockLength); d_5_6_1944 = ldpcinit(H); end [rows, cols, NGrp, grplist] = getldpcparams(d_5_6_1944); end end % Parse optional input arguments [outWholeCodeword, softDecision, earlyExit] = parseInputs(varargin{:}); % Initialize outputs LLR_out = coder.nullcopy(zeros(blockLength, numCodewords)); finalParityChecks = coder.nullcopy(zeros(blockLength-infoLen, numCodewords)); actualNumIter = coder.nullcopy(zeros(1, numCodewords)); % Decode if isempty(coder.target) % Simulation decoded = zeros(blockLength, numCodewords); compFinalParityChecks = (nargout == 3); numParityBits = blockLength - infoLen; rows = int32(rows-1); numRows= length(rows); numGrp = size(grplist,2); grplist = int32(grplist(:)); for cwIndx = 1:numCodewords % C implementation [decoded(:,cwIndx), ~, ~, ~, actualNumIter(cwIndx), ... finalParityChecks(:,cwIndx)] = mwcomm_ldpcdecode(LLR(:,cwIndx), ... N_Iter, blockLength, numParityBits, numRows, numGrp, grplist, ... rows, int8(~softDecision), int8(earlyExit), ... int8(compFinalParityChecks)); end % Format output if softDecision if ~outWholeCodeword decoded = decoded(1:infoLen, :); end else if outWholeCodeword decoded = int8(decoded); else decoded = int8(decoded(1:infoLen, :)); end end else % codegen % Initialize output to fix dimension and data type if softDecision if outWholeCodeword decoded = coder.nullcopy(zeros(blockLength, numCodewords)); else decoded = coder.nullcopy(zeros(infoLen, numCodewords)); end else if outWholeCodeword decoded = coder.nullcopy(zeros(blockLength, numCodewords,'int8')); else decoded = coder.nullcopy(zeros(infoLen, numCodewords,'int8')); end end % Parity-check matrix for computing final parity checks H = zeros(blockLength-infoLen, blockLength); for i = 1:length(rows) H(rows(i),cols(i)) = 1; end % The sum-product algorithm for cwIndx = 1:numCodewords % Key variables inside the for loop: % Lq, Lr, LLR_out Lq = LLR(cols, cwIndx); zeroLoc = zeros(size(Lq)); % Stores the location where Lq is zero numIter = 0; for iteration = 1:N_Iter numIter = numIter+1; Lq = tanh(Lq/2); prodLq = ones(infoLen,1); % Variables for handling Lq's that are equal to zero NumOfRowsWithZeroTanh = 0; ChangedZeroloc = 0; % Calculate the product of Lq's % May need to handle the situation when some values are zero for nn = 1:length(rows) if Lq(nn) ~= 0 prodLq(rows(nn)) = prodLq(rows(nn)) * Lq(nn); else % We must make sure that division by zero will not occur. % Moreover, we need to compute Lr correctly before % calculating LLR_out. % Strategy: % % Let j (column index) be fixed. % % If L(q_{ij}) = 0 for exactly one i (say i0), % then L(r_{ji}) = 0 for all i != i0, % and for i = i0, L(r_{ji}) will be computed correctly % if L(q_{ij}) is changed to any nonzero value. % % If L(q_{ij}) = 0 for two or more i's, % then L(r_{ji}) = 0 for all i. % First, change Lq to a nonzero value so that division % by zero will not occur. Lq(nn) = 1; % Check if this is the first zero for this particular j if zeroLoc(rows(nn)) == 0 % Yes, this is the first zero for this j. % For now, assume that there are no more zeros, % and store nn (which specifies i0), % so that we may set L(r_{ji}) = 0 for all i != i0. zeroLoc(rows(nn)) = nn; % Keep track of the number of rows we need to fix % For each j, NumOfRowsWithZeroTanh may be % increased once only, because zeroLoc(rows(nn)) is % no longer equal to 0. NumOfRowsWithZeroTanh = NumOfRowsWithZeroTanh + 1; % Make sure that zeroLoc will be cleared % for next iteration ChangedZeroloc = 1; % No need to do % prodLq(rows(nn)) = prodLq(rows(nn)) * Lq(nn); % because Lq(nn) has been changed to 1. else if zeroLoc(rows(nn)) > 0 % This is the second zero for this j. % Just set prodLq(rows(nn)) = 0 % to force all L(r_{ji}) to 0 for all i. prodLq(rows(nn)) = 0; % Set zeroLoc(rows(nn)) = -1 to record the fact % that there are two zeros already. zeroLoc(rows(nn)) = -1; % Keep track of the number of rows we need to fix NumOfRowsWithZeroTanh = NumOfRowsWithZeroTanh - 1; end end end end Lr = 2*atanh(prodLq(rows)./Lq); % atanh(x) approaches 19.07 as x approaches 1 % atanh(x) approaches -19.07 as x approaches -1 % Keep Lr finite to make subsequent summing operations meaningful Lr(Lr == Inf) = 2 * (19.07); Lr(Lr == -Inf) = 2 * (-19.07); % Fix those cases with a single zero if NumOfRowsWithZeroTanh > 0 for nn = 1:length(rows) if (zeroLoc(rows(nn)) > 0) && (zeroLoc(rows(nn)) ~= nn) Lr(nn) = 0; end end end if ChangedZeroloc zeroLoc(:) = 0; % Reset for next iteration end % Initial value of the sums LLR_out(:, cwIndx) = LLR(:, cwIndx); % Calculate the sums offset1 = 0; offset2 = 0; for g = 1:NGrp % Loop over all groups LLR_out(offset1+(1:grplist(1,g)), cwIndx) = ... LLR_out(offset1+(1:grplist(1,g)), cwIndx) + ... sum(reshape(Lr(offset2+(1:grplist(1,g)*grplist(2,g))), ... grplist(2,g), grplist(1,g)), 1)'; offset1 = offset1 + grplist(1,g); offset2 = offset2 + grplist(1,g)*grplist(2,g); end Lq = LLR_out(cols, cwIndx) - Lr; if earlyExit % Compute the parity checks to see if the decoder can stop early hardDecisions = double(LLR_out(:, cwIndx) <= 0); finalParityChecks(:, cwIndx) = mod(H*hardDecisions,2); if ~any(finalParityChecks(:, cwIndx)) break; end end end % If necessary, compute the final parity checks if ~earlyExit && (nargout == 3) hardDecisions = double(LLR_out(:, cwIndx) <= 0); finalParityChecks(:, cwIndx) = mod(H*hardDecisions,2); end actualNumIter(cwIndx) = numIter; end % Format output if softDecision if outWholeCodeword decoded(:) = LLR_out; else decoded(:) = LLR_out(1:infoLen,:); end else if outWholeCodeword decoded(:) = int8(LLR_out <= 0); else decoded(:) = int8(LLR_out(1:infoLen,:) <= 0); end end end function d = ldpcinit(H) [rows, cols] = find(H); j = [sum(H,1) -1]; x = find(j(2:end)-j(1:end-1)); y = j(x); dlist = reshape([filter([1 -1],1,x);y],1,[]); NGrp = length(dlist)/2; grplist = reshape(dlist, 2, []); d.rows = rows; % row indices of nonzero entry in H d.cols = cols; % column indices of nonzero entry in H d.NGrp = NGrp; % Number of groups in H d.grplist = grplist; % Each group has the same number of ones in each column function [rows, cols, NGrp, grplist] = getldpcparams(d) rows = d.rows; cols = d.cols; NGrp = d.NGrp; grplist = d.grplist; function [outWholeCodeword, softDecision, earlyExit] = parseInputs(varargin) outWholeCodeword = false; softDecision = false; earlyExit = false; for i = 1:(nargin) if strcmpi(varargin{i}, 'whole codeword') outWholeCodeword = true; elseif strcmpi(varargin{i}, 'soft decision') softDecision = true; elseif strcmpi(varargin{i}, 'early exit') earlyExit = true; end end