%==========================================================================
% File: simu_SER_C4_parity_check.m
% =========================================================================
% Simulation performance C4-sequence with a single parity check for different 
% truncation lengths.
% Inputs:
%   x : spreading sequence
%   l : size of the truncated spreading sequence.
%   snr_tab : table that contains the snr value of interest for the
%             simulation.
% Output: SER : symbol error rate for each value of snr of snr_tab.
% 
% Note: the coefficients of the parity check are taken to optimize
% performance with a BPSK modulation. It may not be usefull in the case of 
% a C4 sequence, but, it is not armfull.
%
% Show the result usign: semilogy(snr_tab, SER);
%                        grid on;
%                        xlabel('snr (in dB)');
%                        ylabel('SER');
% =========================================================================
% Copyright: E. Boutillon, Université Bretagne Sud
% Date of creation:  07/07/2023
% Mdifications:      29/05/2026 (give more details + licence type in file 
%                                hearder).
% =========================================================================
% This code is distributed under a cecill B licence
% (https://cecill.info/licences/Licence_CeCILL-B_V1-en.html)
%==========================================================================
function [SER] = simu_SER_C4_parity_check(x, l, snr_tab)

[a b] = size(x);
q = length(x);
if a == 1
    x = [x x];
    for i = 1:q
        TCCSK(i,:) = x(i:i+l-1);
    end
else
    TCCSK = x;
end

SER = zeros(1,length(snr_tab));
last_nb_err = 100;
for ind_snr = 1:length(snr_tab)
    snr = snr_tab(ind_snr);
    sigma = sqrt(10^(-snr/10)/2);
    nb_err = 0;
    total = 0;    
    mult_32 = [1 (mod((2:64)+30, 63)+2)];
    mult_17 = [1 (mod((2:64)+15, 63)+2)];
    mult_19 = [1 (mod((2:64)+17, 63)+2)];
    while nb_err < 100 && total < 2*10^6 && last_nb_err > 40
        s_d = floor(rand(1,3)*q)+1;
        s(1) = mult_32(s_d(1));
        s(2) = mult_17(s_d(2));
        s(3) = mult_19(s_d(3));
        s(4) = bitxor(bitxor(s(1)-1,s(2)-1),s(3)-1)+1; 
        y = TCCSK(s, :) + sigma*(randn(4,l)+1i*randn(4,l));
        for i = 1:4
            LLR(:,i) = sum((y(i,:)- TCCSK).*conj(y(i,:) - TCCSK),2);
            [m(:,i) ind(:,i)] = min(LLR(:,i));
        end
        err = 0;
        do_break = 0;
        if sum( abs( ind -s))>0
            dist_genius = LLR(s(1),1) + LLR(s(2),2) + LLR(s(3),3) + LLR(s(4),4);
            for i = 1:4
                [LLR_s(:,i) ind_s(:,i)] = sort(LLR(:,i));
            end
            ind_1 = find( LLR_s(:,1)<dist_genius);
            for a = 1:length(ind_1) 
                da    = LLR_s(a,1);
                ind_2 = find( LLR_s(:,2)<dist_genius - da);
                for b = 1:length(ind_2)
                    db    = da + LLR_s(b,2);
                    ind_3 = find( LLR_s(:,3) < dist_genius - db);
                    for c = 1:length(ind_3)
                        dc = db + LLR_s(c,3);
                        d = bitxor(bitxor( mult_32(ind_s(a,1))-1, mult_17(ind_s(b,2))-1), mult_19(ind_s(c,3))-1)+1;
                        if dc + LLR(d,4) <= dist_genius
                            if d ~= s(4)
                                err = 1;
                            end
                            do_break = 1;
                            break
                        end
                    end
                    if do_break == 1
                        break;
                    end    
                end
                if do_break == 1
                    break;
                end
            end
        end
        total = total + 1;
        nb_err = nb_err + err;
    end
    last_nb_err = nb_err;
    if total > 0
        SER(ind_snr) = nb_err/total;
    else
        SER(ind_snr) = 0
    end
    disp(sprintf('SNR = %2.2f, l = %d, nb_err = %d, total = %d', snr, l, nb_err, total));
end
%semilogy(snr_tab, SER)
%grid on
%xlabel('$E_b/N_0$ (in dB)', 'interpreter','latex');
%ylabel('SER', 'interpreter','latex');

        
        


