%% sim_main_single.m
% file with main simulation loops (no parallel processing)


for i_snr = 1:length(SNR) % smycka SNR
    calc_round = calc_round+1;
    disp([' SNR = ',num2str(SNR(i_snr)),' dB | ',num2str(i_snr),'/',num2str(length(SNR)),' SNR values | ',num2str(calc_round),'/',num2str(length(SNR)*length(SpatialStreams)*length(MCSvec)),' of total calculation']);
    
    
    for i_loop = 1:N_frames; % vnitrni smycka - pocet behu
        if mod(i_loop,1000) == 0
            disp(['Part ',num2str(i_loop/1000),'/',num2str(N_frames/1000)]);
        end
        
%         switch mode
%             case g
%                 
%             case n
%                 
%             case ac
        txObj = WIFI_TX(wifi_params,txObj,i_mcs); % perform transmitter operations
        
        wifi_params.general.newNsym = txObj.output.newNsym;
%         
%             otherwise
%                 
%         end
        LENGTH;
        size(txObj.output.x_s);
        wifi_y_tx = txObj.output.x_s;
        save(['WIFI_',wifi_standard,'_LENGTH_',num2str(LENGTH),'.mat'],'wifi_y_tx')
        
        clear wifi_y_tx
        
        % sigma_v = 10^(-EbNo/20);
        
        % upconverter option %% NENI POTREBA -> dodelat pozdeji, viz
        % load_wifi_params.m, radek ~90
        %         txObj = WIFI_upconverter(txObj, wifi_params, agOut, agParams, useGPU);
        %         plotSpectrum(txObj.output.txUpSignal,txObj.output.genie.fs);
        % or usrp
        
        %% interferring signal
        % load - nahrat signal LTE dle parametru (BW = 1.4 -- 20 MHz)
        
        %% channel model and noise
        %         %% Prevzorkovani rusiveho signalu (LTE) a jeho upkonverze - NENI POTREBA, viz vyse
        %         if ((i_snr == 1) && (i_loop == 1))
        %             K = gcd(agParams.Fs,wifi_params.Fs);
        %             L = wifi_params.Fs/K;
        %             M = agParams.Fs/K;
        %             agOut.y_tx = resample(agOut.y_tx,L,M);
        %
        %             [agOut] = LTE_upconverter(agOut, agParams, wifi_params, useGPU, txObj);
        %             save('InterfSignalTemp.mat','agOut');
        %             %             pwelch(agOut.txUpSignal)
        %         else
        %             load('InterfSignalTemp.mat');
        %         end
        %
        %         P_LTE = (norm(agOut.txUpSignal)^2)/(length(agOut.txUpSignal));
        %         P_WiFi = (norm(txObj.output.txUpSignal)^2)/(length(txObj.output.txUpSignal));
        %
        %         W_WiFi = 1;
        %         W_LTE = ((10^(-(SNR(i_snr))/10))/W_WiFi);
        %         txObj.output.txUpSignal = W_LTE*agOut.txUpSignal+W_WiFi*txObj.output.txUpSignal;
        % %         plotSpectrum(txObj.output.txUpSignal,txObj.output.genie.fs)
        
        addSomeNoise = wifi_params.general.addSomeNoise;    %testing with or without noise, false is not made yet

        
        channelNoiseIn = txObj.output.x_s;
       switch addSomeNoise
          case 'fad'
            channelObj = channel(wifi_params,txObj.nTXant,rxObj.nRXant); % mozna presunout mimo tuto smycku - parametry kanalu jsou znamy jiz pred simulaci
        %   channelObj.H = squeeze(channelObj.H);
        %   for i_channel = 1:wifi_params.general.n_users(1,2)
        %   channelFadOut = zeros(size(channelObj.h,4),length(channelNoiseIn));
        %   H_completPath = zeros(size(channelObj.h,4),size(channelObj.h,3));
%            channelObj.x_h_fadding = conv(txObj.output.x_s,channelObj.h,'same');
            
        
        for i_channelPath = 1:wifi_params.general.N_sts
            channelObj.x_h_fadding(i_channelPath,:) = conv(txObj.output.x_s(i_channelPath,:),channelObj.h(:,:,i_channelPath,i_channelPath));
        end
        
        
            n = 10^(-SNR(i_snr)/20)*((randn(size(channelObj.x_h_fadding))+1j*(randn(size(channelObj.x_h_fadding))))/sqrt(2));
            v = sqrt(wifi_params.mapping.n_fft/wifi_params.mapping.n_tot) * n;
                       
            channelFad = channelObj.x_h_fadding + v;
            
            channelObj.x_hn = channelFad ;
            channelObj.SNR = SNR(i_snr);               
                
            case 'fadTest'
            H_completPath = 1/sqrt(2)*[randn(size(channelNoiseIn,1),size(channelNoiseIn,2)) + j*randn(size(channelNoiseIn,1),size(channelNoiseIn,2))];
%            H_completPath = H_completPath + h_path;
%            test_path = eye(size(channelObj.h,3),size(channelObj.h,4)).';

            n = 10^(-SNR(i_snr)/20)*((randn(size(channelNoiseIn))+1j*(randn(size(channelNoiseIn))))/sqrt(2));
            v = sqrt(wifi_params.mapping.n_fft/wifi_params.mapping.n_tot) * n;
            channelNoiseIn = channelNoiseIn;
            
            channelFad = (H_completPath.*channelNoiseIn) + v;
%            channelFadOut = channelFadOut + channelFad;
            

                channelObj.x_h = channelFad ;
                channelObj.SNR = SNR(i_snr);
                channelObj.h_completPath = H_completPath;
                %         channelObj.x_h = conv(txObj.output.txUpSignal,channelObj.h);

    %        end

            % noise
%             n = 10^(-SNR(i_snr)/20)*((randn(size(channelObj.x_h))+1j*(randn(size(channelObj.x_h))))/sqrt(2));
%             v = sqrt(wifi_params.mapping.n_fft/wifi_params.mapping.n_tot) * n;
% 
%             % awgn or fading channel + white noise
             channelObj.x_hn = channelObj.x_h;
            
        case 'mimo'
            
            numTxMIMO = wifi_params.general.n_users(1,2);         % Number of transmit antennas
            numRxMIMO = wifi_params.general.n_users(1,3);         % Number of receive antennas
            RsMIMO = 40000;        % Sampling rate (Hz)
            tauMIMO = [0 2e-6];    % Path delays (sec)
            pdbMIMO = [0 -10];     % Average path gains (dB)
            maxDoppMIMO = 30;      % Maximum Doppler shift (Hz)

            hChan = comm.MIMOChannel(...
                'SampleRate',RsMIMO,...
                'PathDelays',tauMIMO,...
                'AveragePathGains',pdbMIMO,...
                'MaximumDopplerShift',maxDoppMIMO,...
                'SpatialCorrelation',false,...
                'NumTransmitAntennas',numTxMIMO,...
                'NumReceiveAntennas',numRxMIMO,...
                'PathGainsOutputPort',true);
            
            [chanOut, pathGains] = step(hChan, txObj.output.x_s.');
            n = 10^(-SNR(i_snr)/20)*((randn(size(chanOut.'))+1j*(randn(size(chanOut.'))))/sqrt(2));
            v = sqrt(wifi_params.mapping.n_fft/wifi_params.mapping.n_tot) * n;

            % awgn or fading channel + white noise
            chanOut = chanOut.';
            channelObj.x_hn = chanOut+v;
            channelObj.pathGains = pathGains;
            
        case 'awgn'

            n = 10^(-SNR(i_snr)/20)*((randn(size(txObj.output.x_s))+1j*(randn(size(txObj.output.x_s))))/sqrt(2));
            v = sqrt(wifi_params.mapping.n_fft/wifi_params.mapping.n_tot) * n;

            % awgn or fading channel + white noise
            
            channelObj.x_hn = txObj.output.x_s+v;
%            channelObj.pathGains = pathGains;

        end
            
        %% downconverter option -> NENI POTREBA, viz vyse
        % or usrp
        
        %         [ChanMod_output, txObj] = WIFI_downconverter(channelObj.x_hn, txObj, wifi_params, useGPU);
        
        % receiver
        
        %         rxObj = WIFI_RX(wifi_params,rxObj,channelObj, ChanMod_output);
        rxObj = WIFI_RX(wifi_params,rxObj,channelObj, channelObj.x_hn,i_mcs);
        results = result_calculation(results,txObj,rxObj,i_snr,i_loop,N_frames);
    end % inner loop
    % results evaluation % using OOP
end % outer loop