%% Decode Rate 3/4 LDPC Codewords
% Initialize parameters for the prototype matrix and block size to configure a rate 3/4 LDPC code specified in IEEE® 802.11. Create the parity-check matrix by using the ldpcQuasiCyclicMatrix function.

close all
clear all
P = [
    16 17 22 24  9  3 14 -1  4  2  7 -1 26 -1  2 -1 21 -1  1  0 -1 -1 -1 -1
    25 12 12  3  3 26  6 21 -1 15 22 -1 15 -1  4 -1 -1 16 -1  0  0 -1 -1 -1
    25 18 26 16 22 23  9 -1  0 -1  4 -1  4 -1  8 23 11 -1 -1 -1  0  0 -1 -1
     9  7  0  1 17 -1 -1  7  3 -1  3 23 -1 16 -1 -1 21 -1  0 -1 -1  0  0 -1
    24  5 26  7  1 -1 -1 15 24 15 -1  8 -1 13 -1 13 -1 11 -1 -1 -1 -1  0  0
     2  2 19 14 24  1 15 19 -1 21 -1  2 -1 24 -1  3 -1  2  1 -1 -1 -1 -1  0
    ];
blockSize = 54; % Change the block size to encode any size of data. E.g. This will encode 27*18 infomration bits with 162 parity bits. 
pcmatrix = ldpcQuasiCyclicMatrix(blockSize,P);

% Create LDPC encoder and decoder configuration objects, displaying their properties.

cfgLDPCEnc = ldpcEncoderConfig(pcmatrix);
cfgLDPCDec = ldpcDecoderConfig(pcmatrix);

% Transmit an LDPC-encoded, QPSK-modulated bit stream through an AWGN channel. Demodulate the signal, decode the received codewords, and then count bit errors. Use nested for loops to process multiple SNR settings and frames with and without LDPC forward error correction (FEC) coding of the transmitted data.

M = 64;
mu = log2(M);
maxnumiter = 1; % Increase the number of interations to improve the bit-error rate of coded bits. 
numframes = 100;

EbN0Vec = (0:1:18);
snr = EbN0Vec + 10*log10(mu);

ber = comm.ErrorRate;
ber2 = comm.ErrorRate;

for ii = 1:length(snr)
    for counter = 1:numframes
        data = randi([0 1],cfgLDPCEnc.NumInformationBits,1,'int8');
        % Transmit and receive with LDPC coding
        encodedData = ldpcEncode(data,cfgLDPCEnc);
        modSignal = qammod(encodedData, M, 'InputType', 'bit');
        %modSignal = pskmod(encodedData,M,InputType='bit');
        [rxsig, noisevar] = awgn(modSignal,snr(ii),'measured');
        demodSignal = qamdemod(rxsig, M, 'OutputType', 'approxllr', NoiseVariance=noisevar);
        %pskdemod(rxsig,M, OutputType='approxllr', NoiseVariance=noisevar);
        rxbits = ldpcDecode(demodSignal,cfgLDPCDec,maxnumiter);
        errStats = ber(data,rxbits);
        BerCoded(ii) = errStats(1);
     
        % Transmit and receive with no LDPC coding
        noCoding = qammod(data, M, 'InputType', 'bit');
        rxNoCoding = awgn(noCoding,snr(ii),'measured');
        rxBitsNoCoding = qamdemod(rxNoCoding, M, 'OutputType', 'bit');
        errStatsNoCoding = ber2(data,int8(rxBitsNoCoding));
        BerUncoded(ii)=errStatsNoCoding(1);
    end
        reset(ber);
    reset(ber2);
end
[berT,~] = berawgn(EbN0Vec,'qam',M,1);

semilogy(EbN0Vec,berT,'b');
hold
semilogy(EbN0Vec,berT,'b');
semilogy(EbN0Vec,BerCoded,'b:o');
semilogy(EbN0Vec,BerUncoded,'r');
title('Performance of Rate 3/4 LDPC in AWGN Chanells');
legend('Uncoded Theory','Coded Simulation','Location','Best');
xlabel('Eb/No (dB)'); ylabel('Bit Error Rate');
grid on