%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% .m script of web demo "Peeling Decoder for Graph Based Codes" 
% Written for GNU Octave
% 
% INSTITUTE OF TELECOMMUNICATIONS  
% University of Stuttgart 
% www.inue-uni-stuttgart.de 
% author: Ahmed Elkelesh   
% date: 09.11.2014   
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function tanner(v,c,Hid,hr,uploadfile,filename)
% The first function to be called in this slide 
% v,c,Hid,hr,uploadfile: parameters passed by the user from the webdemo page 
fh = figure(1);
set(fh, "visible", "off");
% Defining the Parity Check Matrix H
if hr ==1
try
		H = load(uploadfile);
catch
		tanner(v,c,Hid,0,uploadfile, filename);
end 
else
if Hid==1
    % H for a Hamming code (n=7, k=4)
    H=[1,0,1,1,1,0,0;1,1,1,0,0,1,0;0,1,1,1,0,0,1;];
end
if Hid==2
    % H for a Hamming code (n=15, k=11)
    H=[0,0,0,0,0,0,0,1,1,1,1,1,1,1,1;0,0,0,1,1,1,1,0,0,0,0,1,1,1,1;0,1,1,0,0,1,1,0,0,1,1,0,0,1,1;1,0,1,0,1,0,1,0,1,0,1,0,1,0,1;];
end
if Hid==3
    % H for a regular LDPC code (v=3, c=4, n=12, k=3)
    H=[1,0,0,0,0,1,0,1,0,1,0,0;1,0,0,1,1,0,0,0,0,0,1,0;0,1,0,0,1,0,1,0,1,0,0,0;0,0,1,0,0,1,0,0,0,0,1,1;0,0,1,0,0,0,1,1,0,0,0,1;0,1,0,0,1,0,0,0,1,0,1,0;1,0,0,1,0,0,1,0,0,1,0,0;0,1,0,0,0,1,0,1,0,1,0,0;0,0,1,1,0,0,0,0,1,0,0,1;];
end
if Hid==4
    % H for a regular LDPC code (v=3, c=6, n=20, k=10)
    H=[0,0,0,0,1,0,0,0,1,1,1,0,0,0,0,1,0,0,0,1;0,0,0,0,0,0,1,1,0,0,1,1,0,1,0,1,0,0,0,0;0,1,1,0,0,0,1,0,0,0,0,0,0,0,0,1,0,1,0,1;0,0,0,0,0,1,0,1,0,1,0,0,0,0,0,0,1,1,1,0;1,1,0,0,1,0,0,0,0,0,0,0,1,0,0,0,1,0,1,0;0,0,0,0,0,0,1,0,0,0,1,1,0,1,1,0,0,0,0,1;0,0,0,1,1,1,0,1,0,0,0,0,1,0,1,0,0,0,0,0;1,0,1,0,0,0,0,0,1,0,0,0,1,1,1,0,0,0,0,0;1,1,1,1,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0;0,0,0,1,0,1,0,0,1,0,0,1,0,0,0,0,0,1,1,0;];
end
if Hid==5
    % H for a regular LDPC code with the given degree profiles by the user
    H = generateH(v,c);
end
end
draw_part_graph_1(H);
print(filename, "-dpng","-S640,480", "-r0");  
end

function draw_part_graph_1 (H)
% This function draws the Bipartite graph (Tanner graph) of a code with a certain H matrix
% The input to the function is:
% H: The parity check matrix of the code under consideration
varnodes = 1:size(H,2);
varnodepos = 1:1:numel(varnodes);
hh=plot(varnodepos, zeros(size(varnodepos)),'r'); % Plotting the circles representing the variable nodes
set(hh,'marker','.','markersize',40)
xlim([0 numel(varnodes)+1]);
hold all;
% find connected check nodes
vnidx=1;
multcn = [];
for vn = varnodes
    cns{vnidx} = find(H(:,vn));
    multcn = [multcn; cns{vnidx}];
    vnidx=vnidx+1;
end
allcn = unique(multcn);
cnpos = [1:1:numel(allcn)] + 0.5*(numel(varnodes)-numel(allcn));
ss=plot(cnpos, 2*ones(size(cnpos)),'m'); % Plotting the circles representing the check nodes
set(ss,'marker','.','markersize',40);
vnidx=1;
for vn = varnodes
    for k=1:numel(cns{vnidx})
        cnk = allcn == cns{vnidx}(k);
        line([varnodepos(vnidx) cnpos(cnk)],[0 2],'LineWidth',2); % Plotting the edges between variable nodes and check nodes according to the input H
    end
    vnidx = vnidx+1;
end
hold off;
set(gca,'XTick',[]);
set(gca,'YTick',[]);
set(gca,'Box','off');
title('Check Nodes','fontsize',18);
xlabel('Variable Nodes','fontsize',16);
end

function [ H ] = generateH( v,c )
% This function generates the parity check matrix H of a regular LDPC code
% using the Gallager's method described in slide 3 with the following inputs:
% v: the variable node degree
% c: the check node degree
H1=zeros(2*v,2*c);
H_temp=zeros(2,2*c);
H_temp(1,1:c)=1;
H_temp(2,c+1:end)=1;
H1(1:2,1:2*c)=H_temp;
for i=2:v 
a=randperm(2*c);
H2=H_temp(:,a);
H1(2*i-1:2*i,:)=H2;
end
H=H1;
end