%% LDPC Processing for DL-SCH and UL-SCH
%
% This example highlights the low-density parity-check (LDPC) coding chain
% for the 5G NR downlink and uplink shared transport channels (DL-SCH and 
% UL-SCH).

%   Copyright 2018-2019 The MathWorks, Inc.

%% Shared Channel Parameters
%
% The example uses the DL-SCH to describe the processing, which also
% applies to the UL-SCH.
%
% Select parameters for a transport block transmitted on the downlink
% shared (DL-SCH) channel.

rng(210);              % Set RNG state for repeatability

A = 10000;             % Transport block length, positive integer
rate = 449/1024;       % Target code rate, 0<R<1
rv = 0;                % Redundancy version, 0-3
modulation = 'QPSK';   % Modulation scheme, QPSK, 16QAM, 64QAM, 256QAM
nlayers = 1;           % Number of layers, 1-4 for a transport block

%%
% Based on the selected transport block length and target coding rate,
% DL-SCH coding parameters are determined using the
% <docid:5g_ref#mw_function_nrDLSCHInfo nrDLSCHInfo> function.

% DL-SCH coding parameters
cbsInfo = nrDLSCHInfo(A,rate);
disp('DL-SCH coding parameters')
disp(cbsInfo)

%%
% DL-SCH supports multi-codeword transmission (i.e. two transport blocks)
% while UL-SCH supports only a single codeword. UL-SCH also supports
% pi/2-BPSK modulation in addition to those listed above for DL-SCH.

%% Transport Block Processing using LDPC Coding
%
% Data delivered from the MAC layer to the physical layer is termed as a
% transport block. For the downlink shared channel (DL-SCH), a transport
% block goes through the processing stages of:
%
% * CRC attachment, 
% * Code block segmentation and code block CRC attachment, 
% * Channel coding using LDPC, 
% * Rate matching and code block concatenation
%
% before being passed on to the physical downlink shared channel (PDSCH)
% for scrambling, modulation, layer mapping and resource/antenna mapping.
% Each of these stages is performed by a function as shown next.

% Random transport block data generation
in = randi([0 1],A,1,'int8');

% Transport block CRC attachment 
tbIn = nrCRCEncode(in,cbsInfo.CRC);

% Code block segmentation and CRC attachment
cbsIn = nrCodeBlockSegmentLDPC(tbIn,cbsInfo.BGN);

% LDPC encoding
enc = nrLDPCEncode(cbsIn,cbsInfo.BGN);

% Rate matching and code block concatenation
outlen = ceil(A/rate);
chIn = nrRateMatchLDPC(enc,outlen,rv,modulation,nlayers);

%%
% The output number of bits from the rate matching and code block
% concatenation process must match the bit capacity of the PDSCH, based on
% the available resources. In this example, as the PDSCH is not modeled,
% this is set to achieve the target code rate based on the transport block
% size previously selected.
%
% Similar processing applies for the UL-SCH, where the physical uplink
% shared channel (PUSCH) is the recipient of the UL-SCH codeword. The
% following schematics depict the processing for the two channels.
%
% <<../nr5gSCH.png>>
%
% Refer to <docid:5g_ref#mw_sysobj_nrDLSCH nrDLSCH> and
% <docid:5g_ref#mw_sysobj_nrULSCH nrULSCH> System objects that encapsulate
% the processing per transport block, with additional support for
% retransmissions.

%% Channel
%
% A simple bipolar channel with no noise is used for this example.
% With the full PDSCH or PUSCH processing, one can consider fading
% channels, AWGN and other RF impairments as well.

chOut = double(1-2*(chIn));

%% Receive Processing using LDPC Decoding
%
% The receive end processing for the DL-SCH channel comprises of
% the corresponding dual operations to the transmit end that include
%
% * Rate recovery 
% * LDPC decoding
% * Code block desegmentation and CRC decoding
% * Transport block CRC decoding
%
% Each of these stages is performed by a function as shown next.

% Rate recovery
raterec = nrRateRecoverLDPC(chOut,A,rate,rv,modulation,nlayers);

% LDPC decoding
decBits = nrLDPCDecode(raterec,cbsInfo.BGN,25);

% Code block desegmentation and CRC decoding
[blk,blkErr] = nrCodeBlockDesegmentLDPC(decBits,cbsInfo.BGN,A+cbsInfo.L);

disp(['CRC error per code-block: [' num2str(blkErr) ']'])

% Transport block CRC decoding
[out,tbErr] = nrCRCDecode(blk,cbsInfo.CRC);

disp(['Transport block CRC error: ' num2str(tbErr)])
disp(['Recovered transport block with no error: ' num2str(isequal(out,in))])

%%
% As the displays indicate, there are no CRC errors at both the code-block
% and transport block levels. This leads to the transport block being
% recovered and decoded with no errors, as expected, for a noiseless
% channel.
%
% Refer to <docid:5g_ref#mw_sysobj_nrDLSCHDecoder nrDLSCHDecoder> and
% <docid:5g_ref#mw_sysobj_nrULSCHDecoder nrULSCHDecoder> System objects
% that encapsulate the receive processing per codeword, with additional
% soft-combining of retransmissions for improved performance.
