function [ber]=MLSE(snr,C,N);

L=length(C)-1; 
sig=10^(-snr/20);
 
 st=sign(randn(N,1));
 st=[-ones(L,1);st;-ones(L,1)]; % prepend and append 0 -> -1 

 y = conv(C,st);

 y=y(L:length(y));

% Add noise

 y=y+sig*randn(size(y));
 
% VA-based MLSD

 met=ones(2^L,1)*Inf;
 met(1)=0;            % Algorithm initialized to all zero state
 survivor=zeros(2^L,N);
 l21=2^(L-1); 
 B=3*L;   % max survivor length

 dec_path=zeros(1,N-B+1);
 table=flipud(base2([0:2^L-1])); % base2 converts decimal to binary.

for n=1:B
   
    met_temp=zeros(2^L,1);   
    surv_temp=zeros(2^L,n);

 for state=0:2^L-1    

   % state actually indexes the destination nodes of the trellis section,
   % prev_states are the two source nodes leading to state

   sn = floor(state/l21);
   prev_states = [2*rem(state,l21) 2*rem(state,l21)+1];
   
    st_hat=2*[sn sn; table(:,prev_states + 1)]-1;
    yr=[y(n) y(n)];
    met1=(yr-[C]*st_hat).^2;

 
   [met_temp(state+1),ind] = min(met(prev_states+1)+met1');   

   surv_temp(state+1,:)=[survivor(prev_states(ind)+1,1:n-1) sn]; 

 end;

  survivor(:,1:n)=surv_temp;
  met=met_temp;
  
end;

for n=B+1:N

    met_temp=zeros(2^L,1);   
    surv_temp=zeros(2^L,B);
    dec_path(n-B) = survivor(find(met==min(met)),1);
    
 for state=0:2^L-1    

   sn = floor(state/l21);
   prev_states = [2*rem(state,l21) 2*rem(state,l21)+1];
   
   st_hat=2*[sn sn; table(:,prev_states + 1)]-1; 
   yr=[y(n) y(n)];
   met1=(yr-[C]*st_hat).^2;

   [met_temp(state+1),ind] = min(met(prev_states+1)+met1');   
   surv_temp(state+1,:)=[survivor(prev_states(ind)+1,2:B) sn]; 
   
 end;

  survivor=surv_temp;
  met=met_temp;
  
end;

st1=(1+st(L:N+L-1))'/2;
ber=sum(abs(dec_path(1:N-B)-st1(1:N-B)))/(N-B);








