% BiDFE fading channel simulations

% Initialization
rand('seed',0);
chan_num=500;   
% Number of blocks
N=1000;           % block length
Lf=16;            % Number of feedfroward taps
Lb=8;             % Number of feedback taps
P=1;              % Fractional sampling factor
terrain=2; % Power profile terrain "urban"
SNR_min=2;SNR_max=14;SNR_step=1;
N_avg=5;%moving average window on each side

tic
snr=SNR_min:SNR_step:SNR_max;

for chan=1:chan_num,    
chan

%generate channel
[C]=generate_channels(terrain,0.125,1);%real, baud-spaced
C=C./sqrt(C*C');%'
C_est=C;
Lc=length(C);
[junk,Lbad]=max(abs(C));

% Generate Source Sequence
symb=pam(N,2,1);
symb_up=zeros(1,P*N-P+1);
symb_up(1:P:P*N-P+1)=symb;

% Transmit through channel
tx_seq=conv(symb_up,C); %rx_seq without noise

for snr_index=1:length(snr)

sig=10^(-snr(snr_index)/20);
[f_opt,b_opt,delay,mmse]=dfe_tap_estimator(C,Lf,Lb,10^(-snr(snr_index)/10),P,0);
[f_opt_tr,b_opt_tr,delay_tr,mmse_tr]=dfe_tap_estimator(fliplr(C),Lf,Lb,10^(-snr(snr_index)/10),P,0);
[mmse_div,rho,alpha]=trdfe_mse(C,f_opt,b_opt,delay,f_opt_tr,b_opt_tr,delay_tr,10^(-snr(snr_index)/10));

%Received sequence
rec_seq=tx_seq+noise(length(tx_seq),snr(snr_index),1);

% Feedforward filtering
rec_seq1=conv(rec_seq,transpose(f_opt));
r=rec_seq1(delay:P:end); % downsampled signal

% Feedback filtering

% Ideal feedback
symb_hat_ideal(1:Lb)=symb(1:Lb);
for k=Lb+1:N
y(k)=r(k)-symb(k-1:-1:k-Lb)*b_opt;
symb_hat_ideal(k)=pamdet(y(k),2,1);
end;

% Hard Decision feedback
symb_hat(1:Lb)=symb(1:Lb);
for k=Lb+1:N
y(k)=r(k)-symb_hat(k-1:-1:k-Lb)*b_opt;
symb_hat(k)=pamdet(y(k),2,1);
end;

% Soft Decision feedback
symb_hat_soft(1:Lb)=symb(1:Lb);
for k=Lb+1:N
y_soft(k)=r(k)-symb_hat_soft(k-1:-1:k-Lb)*b_opt;
%symb_hat_soft(k)=tanh(y_soft(k)/sqrt(mmse));
symb_hat_soft(k)=tanh(y_soft(k)/sig);
end;

% Time reversed decision feedback

% Feedforward filtering
rec_seq_tr=fliplr(rec_seq);
rec_seq1_tr=conv(rec_seq_tr,transpose(f_opt_tr));
r_tr=rec_seq1_tr(delay_tr:P:end); % downsampled signal

% Feedback filtering

% Ideal feedback
symb_tr=fliplr(symb);
symb_hat_ideal_tr(1:Lb)=symb_tr(1:Lb);
for k=Lb+1:N
y_tr(k)=r_tr(k)-symb_tr(k-1:-1:k-Lb)*b_opt_tr;
symb_hat_ideal_tr(k)=pamdet(y_tr(k),2,1);
end;

% Hard Decision feedback
symb_hat_tr(1:Lb)=symb_tr(1:Lb);
for k=Lb+1:N
y_tr(k)=r_tr(k)-symb_hat_tr(k-1:-1:k-Lb)*b_opt_tr;
symb_hat_tr(k)=pamdet(y_tr(k),2,1);
end;

% Soft Decision feedback
symb_hat_soft_tr(1:Lb)=symb_tr(1:Lb);
for k=Lb+1:N
y_soft_tr(k)=r_tr(k)-symb_hat_soft_tr(k-1:-1:k-Lb)*b_opt_tr;
%symb_hat_soft_tr(k)=tanh(y_soft_tr(k)/sqrt(mmse_tr));
symb_hat_soft_tr(k)=tanh(y_soft_tr(k)/sig);
end;

% linear combining for hard DFE(Add & detect)
symb_hat_bidfe(1:Lb)=symb(1:Lb);
symb_hat_bidfe(N-Lb+1:N)=symb(N-Lb+1:N);
symb_hat_bidfe(Lb+1:N-Lb)=pamdet(alpha*y(Lb+1:N-Lb)+(1-alpha)*fliplr(y_tr(Lb+1:N-Lb)),2,1);

% linear combining for soft DFE(Add & detect)
symb_hat_bidfe_soft(1:Lb)=symb(1:Lb);
symb_hat_bidfe_soft(N-Lb+1:N)=symb(N-Lb+1:N);
symb_hat_bidfe_soft(Lb+1:N-Lb)=pamdet(alpha*y_soft(Lb+1:N-Lb)+(1-alpha)*fliplr(y_soft_tr(Lb+1:N-Lb)),2,1);

%%%%% Reconstruction of received Sequence (for BAD)
% Note: r_hat should be compared with rec_seq and not r.
% Currently, will work only for baud-spaced. 

r_hat=conv(symb_hat,C_est);
r_hat_tr=conv(fliplr(symb_hat_tr),C_est);
r_diff=(r_hat-rec_seq).^2;
r_diff_tr=(r_hat_tr-rec_seq).^2;

symb_bad(1:N_avg)=symb_hat(1:N_avg);
symb_bad(N:-1:N_avg+1)=symb_hat_tr(1:N-N_avg);

%Arbitration

for k=N_avg+1+Lbad:N-N_avg+Lbad,
if (sum(r_diff(k-N_avg:1:k+N_avg)) < sum(r_diff_tr(k-N_avg:1:k+N_avg))) 
symb_bad(k-Lbad)=symb_hat(k-Lbad);
end;
end;

%%%%%%%%End Reconstruction& arbitration (BAD)

% Performance measures

ser_ideal(chan,snr_index)=symberror(symb,symb_hat_ideal);
ser(chan,snr_index)=symberror(symb,symb_hat);
ser_soft(chan,snr_index)=symberror(symb,sign(symb_hat_soft));
ser_ideal_tr(chan,snr_index)=symberror(symb_tr,symb_hat_ideal_tr);
ser_tr(chan,snr_index)=symberror(symb_tr,symb_hat_tr);
ser_soft_tr(chan,snr_index)=symberror(symb_tr,sign(symb_hat_soft_tr));
ser_bidfe(chan,snr_index)=symberror(symb,symb_hat_bidfe);
ser_bidfe_soft(chan,snr_index)=symberror(symb,symb_hat_bidfe_soft);
ser_bad(chan,snr_index)=symberror(symb,symb_bad);

end;
end;

SER_ideal=mean(ser_ideal);
SER=mean(ser);
SER_soft=mean(ser_soft);
SER_ideal_tr=mean(ser_ideal_tr);
SER_tr=mean(ser_tr);
SER_soft_tr=mean(ser_soft_tr);
SER_bidfe=mean(ser_bidfe);
SER_bidfe_soft=mean(ser_bidfe_soft);
SER_bad=mean(ser_bad);

set(0,'DefaultAxesFontSize',18);
set(0,'DefaultTextFontSize',18);
set(0,'DefaultTextFontName','times');
set(0,'DefaultAxesFontName','times');

figure(2);
%pl1=semilogy(snr,SER_ideal,'r-o','LineWidth',2);
hold on;
pl2=semilogy(snr,SER,'b-.','LineWidth',2);
%pl3=semilogy(snr,SER_soft,'m-*','LineWidth',2);
pl4=semilogy(snr,SER_bidfe,'k-^','LineWidth',2);
pl5=semilogy(snr,SER_bidfe_soft,'g--','LineWidth',2);
pl6=semilogy(snr,SER_bad,'c-s','LineWidth',2);
xlabel('SNR  in  dB','FontSize',18);
ylabel('Symbol  Error  Rate','FontSize',18);
legend([pl2,pl4,pl5,pl6],'Normal mode DFE','LC-BiDFE: Hard','LC-BiDFE: Soft','BAD');
grid;

save result_bidfe_fading1 chan_num snr SER_ideal SER SER_soft SER_tr SER_soft_tr SER_bad SER_bidfe SER_bidfe_soft SER_ideal_tr C Lf Lb P N Lbad C_est N_avg ser ser_ideal ser_tr ser_ideal_tr ser_soft ser_soft_tr ser_bidfe ser_bidfe_soft ser_bad;

toc







