% function [gn,En,bn,b_bar_check,margin]=DMTLCma(p,NoisePSD,Ex_bar,b_bar,N,gap)
%
% Levin Campello's Method for margin-adaptive DMT - UNEQUAL MOD, REAL BB ONLY
%
% p is the sampled pulse response (nu = length(p) - 1)
% NoisePSD is noise PSD on same scale as Ex_bar
% Ex_bar is the normalized energy
% N is the total number of real/complex subchannels, N>2
% gap is the gap in dB
% b_bar is the bit rate
%
% gn is channel gain
% En is the energy in the nth subchannel (PAM or QAM)
% bn is the bit in the nth subchannel (PAM or QAM)
% b_bar_check is the bit rate for checking - this should be equal to b_bar
% margin is the margin in dB
%
% The first bin and the last bin is PAM, the rest of them are QAM.

function [gn,En,bn,b_bar_check,margin]=DMTLCma(p,NoisePSD,Ex_bar,b_bar,N,gap)
Noise_var=NoisePSD;
gap=10^(gap/10);
nu=length(p)-1;

% initialization
En=zeros(1,N/2+1);
bn=zeros(1,N/2+1);
gn=zeros(1,N/2+1);
Hn = zeros(1,N/2+1);
decision_table=zeros(1,N/2+1);

% subchannel center frequencies
f=0:1/N:1/2;

% find Hn vector
for i=1:length(p)
	Hn=Hn+p(i)*exp(j*2*pi*f*(i-1)); 
end

% find gn vector
gn=abs(Hn).^2/Noise_var;

%debugging purpose
%plot(gn)

%%%%%%%%%%%%%%%%%%%%%%%
% Margin Adaptive LC %
%%%%%%%%%%%%%%%%%%%%%%%

%initialization

%used energy so far
E_so_far=0;
%decision table - QAM and PAM 
decision_table(2:N/2)=2*gap./gn(2:N/2);
% gap-formula based incremental energies
if gn(1) ~= 0
    decision_table(1)=3*gap/gn(1);
else
    decision_table(1)=inf;
end
if gn(N/2+1) ~=0
    decision_table(N/2+1)=3*gap/gn(N/2+1);
else
    decision_table(N/2+1)=inf;
end

%decision_table: debugging purpose

while(1)
    
    [y,index]=min(decision_table);
    E_so_far=E_so_far+y;
    
    if sum(bn) >= (N+nu)*b_bar
      
        break;
	
    else
      
        En(index)=En(index)+y;
        bn(index)=bn(index)+1;
	
	if (index ==1 | index == N/2+1)
	  decision_table(index)=4*decision_table(index);
	else
	  decision_table(index)=2*decision_table(index);
	end

    end
    
end

% calculate b_bar
b_bar_check=1/(N+nu)*(sum(bn));

% check margin
margin=10*log10(N*Ex_bar/sum(En));




    
        
        
