function [] = mimo_sim_fun( N_tx , Modulation , N_bits , Display_mode , ...
    Zf_en , Mmse_en , Ml_en , Sd_en , Zfpa2p2_en , Zfpa2p2EQU_en , ...
    FullAPP_en , Cap_en , Webdemo_en , Filename )
% mimo_sim_fun(4, 'QPSK', 1000, 2, 1,1,1,1,1,1,1, 1,0,'soft_mimo');
%% process input

if nargin < 1
    % use default values:
    N_tx        = 4;
    Modulation  = 'QPSK';
    Display_mode= 2;
    N_bits      = 10^3;
    Zf_en       = true;
    Mmse_en     = false;
    Ml_en       = false;
    Sd_en       = true;
    Zfpa2p2_en      = true;
    Zfpa2p2EQU_en   = false;
    FullAPP_en  = false;
    Cap_en      = true;
    Webdemo_en  = false;
    Filename    = 'mimo_eval';
end

rx_en_vec = [Zf_en; Mmse_en; Ml_en; Sd_en; ...
    Zfpa2p2_en; Zfpa2p2EQU_en; FullAPP_en];

SNR_dB_inc    =   2;
SNR_dB_min    = -10;
SNR_dB_max    =  40;
n_tx          = N_tx;
n_rx          = N_tx;

if strcmpi(Modulation,'QPSK')
    % bits per symbol: must be a positive real even scalar integer
    % 2 --> QPSK=4-QAM, 4 --> 16-QAM
    n_bps = 2;
elseif strcmpi(Modulation,'16QAM')
    n_bps = 4;
else
    n_bps = 2;
end

% process Outout mode
if Display_mode == 1
    ber_en = true;
    mut_en = false;
elseif Display_mode == 2
    ber_en = true;
    mut_en = true;
else
    ber_en = false;
    mut_en = true;
end

% disable to speed simulation up
check_parameters = true;

% load used files in folder
addpath(genpath([cd filesep 'soft_mimo_files']));

% define style
set(0, 'defaultlinelinewidth', 2);
set(0, 'defaultaxesfontsize', 8);
set(0, 'defaultaxesfontname', 'Helvetica');
set(0, 'defaulttextfontsize', 8);
set(0, 'defaulttextfontname', 'Helvetica');


is_cached = false;

try
    
    load([cd filesep 'soft_mimo_files' filesep 'soft_mimo_cached_results.mat']);
    
    % get cached struct c
    c = cache{n_tx,n_bps}; %#ok<USENS>
    
    % cut out desited rx alg
    c.results = c.results(logical(rx_en_vec));
    
    if ~any(isempty(c.results))
    
        is_cached = true;
    
    end
    
catch
    is_cached = false;
end

% update parameters
c.webdemo_en = Webdemo_en;
c.filename   = Filename;

c.ber_en = ber_en;
c.mut_en = mut_en;


if ~is_cached
    
    c = create_constraint_struct(n_tx, n_rx, n_bps, N_bits, SNR_dB_min, ...
        SNR_dB_max, SNR_dB_inc, ber_en, mut_en, Cap_en, ...
        Webdemo_en, Filename, check_parameters);
    
    %% run simulation
    
    c = m1_transmitter(c);
    c = m2_channel(c);
    
    % receivers:
    if Zf_en
        c = m3_rx_zf_08(c);
    end
    if Mmse_en
        c = m3_rx_mmse_08(c);
    end
    if Ml_en
        c = m3_rx_ml_09(c);
    end
    if Sd_en
        c = m3_rx_sphere_detector_hard_ZF_rad_08(c);
    end
    if Zfpa2p2_en
        % ZF frontend + per antenna APP (ZF + PA^2P^2)
        c = m3_rx_zf_pa_app_maxlog_09(c);
    end
    if Zfpa2p2EQU_en
        c = m3_rx_zf_pa_app_EQU_maxlog_09(c);
    end
    if FullAPP_en
        c = m3_rx_full_app_maxlog_09(c);
    end
    
    c = m4_calculate_channel_capacity_03(c);
    
end


%%
m5_visualization_05(c);

end

