% =============================================================
% This is a system test driver for PSK Detector : test_binary.m
% Parameters: a real square matrix and BPSK constellation.
% =============================================================
% Test          :   S-01
% Developed by  :   Nick (Mikalai) Kisialiou,
%                   Prof. Zhi-Quan Luo,
% Contacts      :   kisi0004@umn.edu, luozq@umn.edu
% =============================================================

fprintf('=====================================================\n');
fprintf('=           Test driver for PSK Detector            =\n');
fprintf('=====================================================\n');
fprintf('+ Starting simulations\n');

% Array of SNRs to simulate
SNRS = [6 10 20 30 40]; 
len = length(SNRS);

% Number of transmitters
TX = 60;
fprintf('+ TX = %d\n', TX);
% Number of receivers
RX = 60;
fprintf('+ RX = %d\n', RX);

% Constellation size
BPSK = 2;
fprintf('+ Constellation size = %d\n', BPSK);

% Detected symbol accuracy
SYM_ACC = 1e-5;

% PSK Detector parameters: 
% Speed-BER tradeoff : Please read help to select this parameter:
% CD to the directory with PSK Detector and type in matlab command line:
% >> help psk_detector
% The description of the detector provides recommended settings for
% PSK_NOISE_PARAM parameter:
PSK_NOISE_PARAM = chi2inv(.972,TX);

% Number of Monte-Carlo runs
NRUNS = 100;
fprintf('+ Number of runs per SNR level = %d\n', NRUNS);

% ---------------------- PSK Detector ----------------------
time_psk = zeros(1,len);
max_time_psk = zeros(1,len);
bit_errors_psk = zeros(1,len);

% ----------------------------------------------------------
% Loop over all SNR levels 
for k = 1 : len,
    % Pick the SNR level from the specified array
    rho = SNRS(k);
    fprintf('+ Running SNR = %f [dB]\n', 10*log10(rho));
    % Monte-Carlo simulation loop
    for i = 1 : NRUNS,
        % Generate random channel
        A = randn(RX,TX); 
        H = sqrt(rho/TX)*A;
        v = randn(RX,1); 
        
        % BPSK-modulated data
        s = 2*(randn(TX,1) > 0) - 1;
        
        % -----------------------------------------------------------------
        % Simulate channel
        % -----------------------------------------------------------------
        y = H * s + v;      
 
        % -----------------------------------------------------------------
        % Run PSK Detector
        % -----------------------------------------------------------------
        time_start = cputime;
        % Parameters BPSK and PSK_NOISE_PARAM are set in the beginning of the script
        [psk_phase_est, psk_obj] = psk_detector(H, y, BPSK, PSK_NOISE_PARAM);
        time_span = cputime - time_start;
        if (time_span > max_time_psk(k)),
            max_time_psk(k) = time_span;
        end
        time_psk(k) = time_psk(k) + time_span;
        % Convert detected phases to complex symbols
        psk_est = exp(sqrt(-1)*psk_phase_est);
        % Count number of bit errors
        bit_errors = sum(abs(s - psk_est) > SYM_ACC);
        bit_errors_psk(k) = bit_errors_psk(k) + bit_errors;
    end
end

% Compute BER
ber_psk = bit_errors_psk / (NRUNS * TX);
% Average time it took the detectors to run
time_psk = time_psk / NRUNS;

disp('============ PSK Detector statistics : =============');
time_psk
max_time_psk
bit_errors_psk
ber_psk

fprintf('+ Simulations complete\n');
fprintf('=====================================================\n');

% ==============================================================
% End of the test driver for PSK Detector
% ==============================================================


