function hamming_demo

% 	decoder = 'Hard';
% 	decoder = 'Soft';
	decoder = 'SISO';
	
	% parametro del codice
	NmK = 3;
	N = 2^NmK-1;
	K = N-NmK;
	
	temp = de2bi(0:2^NmK-1);
	P = temp(sum(temp,2)>=2,:);
	G=[eye(K),P];
	
	% tabelle delle parole informative e di codice
	d_tab = de2bi(0:2^K-1);
	c_tab = mod(d_tab*G,2);
	
	% rapporto segnale rumore
	SNR_dB = 5;
	sigma_w = sqrt(10^(-SNR_dB/10));
	
	n_err = 0;
	n_loop = 0;
	n_ev = 0;
	n_ev_target = 300;
	while n_ev < n_ev_target
		
		% sorgente
		d = d_tab(ceil(2^K*rand),:);
		
		% codifica
		c = mod(d*G,2);
		
		% mapping BPSK
		v = 1-2*c;
		
		% canale AWGN
		w = sigma_w*randn(1,N);
		r = v+w;

		switch decoder
			case 'Hard'
				
				% decisioni all'uscita del canale
				b = r<0;
				
				% calcola le distanze di Hamming
				dH = sum(mod(c_tab+repmat(b,2^K,1),2),2);
				
				% decisioni MV (Hard)
				[val,pos]=min(dH);
				d_est = d_tab(pos,:);
	
			case 'Soft'
				
				% calcola le distanze euclidee
				d2=sum(abs(repmat(r,2^K,1)-(1-2*c_tab)).^2,2);
				
				% decisioni MV (Soft)
				[val,pos]=min(d2);
				d_est = d_tab(pos,:);
				
			case 'SISO'
				
				% demapping LLR
				Lc = 2*r/sigma_w^2;
				
				% Hamming SISO
				Ld_a = zeros(1,K);
				Ld = hamming_siso(Ld_a,Lc,d_tab,c_tab);
				%Ld_e = Ld-Ld_a;
				
				% decisioni Hard
				d_est = Ld<0;
		end
		
		n_loop = n_loop + 1;
		err = sum(mod(d+d_est,2));
		n_err = n_err + err;
		if err
			n_ev = n_ev + 1;
		end
	end
	fprintf('SNR = %gdB - ER: %g (%d/%d) - BER: %g (%d/%d)\n',...
		SNR_dB,n_ev/n_loop,n_ev,n_loop,...
		n_err/(n_loop*K),n_err,n_loop*K);
	
end

% function Ld = hamming_siso(Ld_a,Lc,d_tab,c_tab)
% 	
% 	% implementare il calcolo degli LLR :)
% 	
% 	K = log2(size(d_tab,1));
% 	Ld = Ld_a + Lc(1:K);
% 
% end
function Ld = hamming_siso(Ld_a,Lc,d_tab,c_tab)
	
	% implementare il calcolo degli LLR :)
	% fatto :)
	
	K = size(Ld_a,2);
	Ld = zeros(1,K);
	for bit = 1:K
		numeratore = 0;
		denominatore = 0;
		for i = 1:2^K
			if d_tab(i,bit) == 0
				numeratore = numeratore + exp((Lc*(0.5-c_tab(i,:))') + (Ld_a*(0.5-d_tab(i,:))'));
			elseif d_tab(i,bit) == 1
				denominatore = denominatore + exp((Lc*(0.5-c_tab(i,:))') + (Ld_a*(0.5-d_tab(i,:))'));
			end
		end
		Ld(bit) = log(numeratore/denominatore);
	end
end
