% =========================================================
% This is a system test driver for PSK Detector : test_8psk.m
% Parameters: a real square matrix and 8-PSK constellation.
% =========================================================
% Test          :   S-02
% 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 50]; 
snr_length = length(SNRS);

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

% Constellation size
EightPSK = 8;
fprintf('+ Constellation size = %d\n', EightPSK);

% 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) / 1.5;

% Detected symbol accuracy
SYM_ACC = 1e-5;

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

% ---------------------- PSK Detector ----------------------
time_psk = zeros(1,snr_length);
max_time_psk = zeros(1,snr_length);
sym_errors_psk = zeros(1,snr_length);

% ----------------------------------------------------------
% Loop over all SNR levels 
for k = 1 : snr_length,
    % 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) + sqrt(-1)*randn(RX,TX) )/sqrt(2); 
        H = sqrt(rho/TX)*A;
        v = ( randn(RX,1) + sqrt(-1)*randn(RX,1) )/sqrt(2);   

        % 8-PSK-modulated data
        s_phase = floor(EightPSK * rand(TX,1)) * (2*pi/EightPSK);
        s = exp(sqrt(-1) * s_phase);
        
        % -----------------------------------------------------------------
        % Simulate channel
        % -----------------------------------------------------------------
        y = H * s + v; 
        
        % -----------------------------------------------------------------
        % Run PSK Detector
        % -----------------------------------------------------------------
        time_start = cputime;
        % Parameters EightPSK and PSK_NOISE_PARAM are set in the beginning of
        % the script
        [s_dec, f_psk] = psk_detector(H, y, EightPSK, 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;
        % Count number of symbol errors
        symbol_errors = sum(abs(s_phase - s_dec) > SYM_ACC); 
        sym_errors_psk(k) = sym_errors_psk(k) + symbol_errors;
    end
end

% Compute SER
ser_psk = sym_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
ser_psk
sym_errors_psk

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

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


