function decoded_seq=vit_decoder(G,K,detected,opmode,hard_or_soft)
% performs the Viterbi algorithm on detected to get the decoded_seq
% G: N x LK Generator polynomial matrix
% K: Number of encoder input bits
%Copyleft: Won Y. Yang, wyyang53@hanmail.net, CAU for academic use only
detected = detected(:).';
if nargin<5|hard_or_soft(1)=='h', detected=(detected>0.5); end
[N,LK]=size(G);
if rem(LK,K)~=0, error('Column size of G must be a multiple of K'); end
tmp= rem(length(detected),N);
if tmp>0, detected=[detected zeros(1,N-tmp)]; end
b=LK-K; % Number of bits representing the state
no_of_states=2^b; N_msgsymbol=length(detected)/N;
for m=1:no_of_states
for n=1:N_msgsymbol+1
states(m,n)=0; % inactive in the trellis
p_state(m,n)=0; n_state(m,n)=0; input(m,n)=0;
end
end
states(1,1)=1; % make the initial state active
cost(1,1)=0; K2=2^K;
for n=1:N_msgsymbol
y=detected((n-1)*N+1:n*N); % Received sequence
n1=n+1;
for m=1:no_of_states
if states(m,n)==1 % active
xb=deci2bin1(m-1,b);
for m0=1:K2
u=deci2bin1(m0-1,K);
[nxb(m0,:),yb(m0,:)]=state_eq(xb,u,G);
nxm0=bin2deci(nxb(m0,:))+1;
states(nxm0,n1)=1;
dif=sum(abs(y-yb(m0,:)));
d(m0)=cost(m,n)+dif;
if p_state(nxm0,n1)==0 % Unchecked state node?
cost(nxm0,n1)=d(m0);
p_state(nxm0,n1)=m; input(nxm0,n1)=m0-1;
else
[cost(nxm0,n1),i]=min([d(m0) cost(nxm0,n1)]);
if i==1, p_state(nxm0,n1)=m; input(nxm0,n1)=m0-1; end
end
end
end
end
end
decoded_seq=[];
if nargin>3 & ~strncmp(opmode,'term',4)
[min_dist,m]=min(cost(:,n1)); % Trace back from best-metric state
else m=1; % Trace back from the all-0 state
end
for n=n1:-1:2
decoded_seq= [deci2bin1(input(m,n),K) decoded_seq];
m=p_state(m,n);
end
function y=deci2bin1(x,l)
% Converts a given decimal number x into a binary number of l bits
if x==0, y=0;
else y=[];
while x>=1, y=[rem(x,2) y]; x=floor(x/2); end
end
if nargin>1, y=[zeros(size(x,1),l-size(y,2)) y]; end
function [nxb,yb]=state_eq(xb,u,G)
% To be used as a subroutine for conv_encoder()
K=length(u); LK=size(G,2); L1K=LK-K;
if isempty(xb), xb=zeros(1,L1K);
else
N=length(xb); %(L-1)K
if L1K~=N, error('Incompatible Dimension in state_eq()'); end
end
A=[zeros(K,L1K); eye(L1K-K) zeros(L1K-K,K)];
B=[eye(K); zeros(L1K-K,K)];
C=G(:,K+1:end); D=G(:,1:K);
nxb=rem(A*xb'+B*u',2)';
yb=rem(C*xb'+D*u',2)';