% project_conv.m
% Simulate a wireless channel using 8PSK modulation
% .. and convolutional channel coding.
% Find BER for various Eb/No
%
% D.Bozarth 03-25-08 SSU Engineering Science
% adapted from project 2, CES 544 of 03-31-07
%
convFlg         = 1;    % 0 => no channel coding, 1 => use channel coding             
graphBiasFlg    = 1;    % 0 => Allow (#bit errors) == 0.
                        % 1 => Ensure min (#bit errors) == 1.
%
bsz = 486;      % length of binary sequence (one frame)
                % Note: For depth-2 convolution and 8PSK modulation,
                % .. bsz must be a multiple of 6.
Es  = 1;        % energy per symbol
Rs  = 24e3;     % symbol rate, baud
fD  = 200;      % max Doppler frequency, Hz
ni  = 1000;     % number of iterations used to determine BER
n   = 4;        % number of encoder states          = 2 ^ (output bit length)
p   = 2;        % number of distinct code inputs    = 2 ^ (input  bit length)
%
EbN = [0  5 10 15 20 25]; % bit energy per noise, dB
ben = [0  0  0  0  0  0]; % counted Bit Errors
ber = [0  0  0  0  0  0]; % calculated Bit Error Rates

format short e;

if convFlg
    in_trels = ...
'1 1, 0 0, 0 0; 1 2, 1 0, 1 1; 2 3, 0 0, 1 0; 2 4, 1 0, 0 1; 3 1, 0 0, 1 1; 3 2, 1 0, 0 0; 4 3, 0 0, 0 1; 4 4, 1 0, 1 0';
    [trels_edges] = make_trellis(in_trels, n, p);
end

t1 = cputime;
for i = 1:size(ber, 2)
    be      = 0;        % number of bit errors detected
    EbNo    = EbN(i);   % bit energy to noise floor

    for j = 1:ni
        % Generate a random binary sequence.
        Bt  = zeros(1, bsz);
        Bt0 = zeros(1, bsz);
        
        for k = 1:bsz ; Bt(k) = (rand(1, 1) > 0.5); end
        
        if convFlg % Apply channel encoding.
            Bt0 = Bt;
            Bt  = conv_encode(trels_edges, n, p, Bt, bsz);
        end        

        % Transmit & receive the frame.
        Br = frameLink_8PSK( Bt, Es, Rs, fD, EbNo );

        if convFlg % Apply channel decoding.
            % Convert received bits to complex symbols (to match trellis syntax).
            sz      = bsz * log2(n);
            csqc    = bin2_to_cpx(Br, sz);

            % Find the set of max-likelihood valid binary sequences.
            fun             = @conv_decode_metric;  % the metric function
            [mlseqs, cost]  = viterbi_decode(trels_edges, n, p, csqc, bsz, fun);
            % mlseqs is nominally complex, but here it's purely real & binary.

            Br = mlseqs(1, :); % Any solution will do.
            Bt = Bt0;
        end
        
        % Compare with original sequence and find errors. 
        dif = abs(Bt - Br);
        be  = be + sum(dif);
    end

    if (graphBiasFlg == 1)
        if be == 0; be = 1; end
    end
    
    ben(i) = be;
    ber(i) = be ./ (bsz * ni);
end
t2 = cputime;
elapsed = t2 - t1

ben
ber
%semilogy(EbN, ber);
%
% End script
