function output = mpi_recipe_dev(Scpe_sig_raw, Symbols, Tx_bits, options) %mpi_recipe_dev Minimal MPI equalizer comparison recipe. arguments Scpe_sig_raw Symbols Tx_bits options.fsym options.M options.duob_mode options.dataTable table options.userParameters struct = struct() options.debug_plots (1,1) logical = false end %% Execution toggles run_conventional_ffe = 1; run_a2_tracked_levels = 1; run_a2_residual = 1; run_a1 = 1; run_tracking_adaptive = 1; plot_output_signals = 0; %% Shared fixed EQ settings eq_sps = 2; eq_order = 50; eq_adaption = "nlms"; eq_len_tr = 4096; eq_epochs_tr = 5; eq_mu_tr = 0.04; eq_epochs_dd = 3; eq_save_debug = false; block_update = 1; if isfield(options.userParameters,"block_update") block_update = options.userParameters.block_update; end Scpe_sig = preprocessSignal(Scpe_sig_raw, Symbols, options.fsym, ... "mode", "auto", ... "debug_plots", options.debug_plots); output = struct(); %% if plot_output_signals showLevelScatter(Scpe_sig, Symbols, ... "fsym", options.fsym, ... "fignum", 400, ... "normalize", true); end %% Conventional FFE if run_conventional_ffe eq_ffe = FFE_plain( ... "sps", eq_sps, ... "order", eq_order, ... "decide", false, ... "adaption_technique", eq_adaption, ... "len_tr", eq_len_tr, ... "epochs_tr", eq_epochs_tr, ... "mu_tr", eq_mu_tr, ... "dd_mode", true, ... "epochs_dd", eq_epochs_dd, ... "mu_dd", 0.0012, ... "optmize_mus", false, ... "plot_mu_optimization", options.debug_plots, ... "save_debug", eq_save_debug); [ffe_results,equalized_signal] = runFfe(eq_ffe, "Conventional FFE", ... Scpe_sig, Symbols, Tx_bits, options); output.conventional_ffe = ffe_results; if plot_output_signals plotEqSignals(equalized_signal,Symbols,options,400,-1); end end %% A2 tracked-level decision if run_a2_tracked_levels eq_ffe = FFE_A2TrackedLevels( ... "sps", eq_sps, ... "order", eq_order, ... "decide", true, ... "adaption_technique", eq_adaption, ... "len_tr", eq_len_tr, ... "epochs_tr", eq_epochs_tr, ... "mu_tr", eq_mu_tr, ... "dd_mode", false, ... "epochs_dd", eq_epochs_dd, ... "mu_dd", 0.012, ... "dc_smoothing_a2", 1, ... "dc_level_avg_bufferlength_a2", 112, ... "dc_level_update_blocklength_a2", block_update, ... "dc_level_weights_a2", [1], ... "save_debug", eq_save_debug); [ffe_results,equalized_signal] = runFfe(eq_ffe, "A2 tracked levels", ... Scpe_sig, Symbols, Tx_bits, options); output.a2_adaptive_levels = ffe_results; if plot_output_signals plotEqSignals(equalized_signal,Symbols,options,410,-1); end end %% A2 residual correction if run_a2_residual eq_ffe = FFE_A2Residual( ... "sps", eq_sps, ... "order", eq_order, ... "decide", false, ... "adaption_technique", eq_adaption, ... "len_tr", eq_len_tr, ... "epochs_tr", eq_epochs_tr, ... "mu_tr", eq_mu_tr, ... "dd_mode", true, ... "epochs_dd", eq_epochs_dd, ... "mu_dd", 0.012, ... "dc_smoothing_a2", 1, ... "dc_level_avg_bufferlength_a2", 112, ... "dc_level_update_blocklength_a2", block_update, ... "dc_level_weights_a2", [0.6], ... "save_debug", eq_save_debug, "optmize_mus",0); [ffe_results,equalized_signal] = runFfe(eq_ffe, "A2 residual", ... Scpe_sig, Symbols, Tx_bits, options); output.a2_residual = ffe_results; if plot_output_signals plotEqSignals(equalized_signal,Symbols,options,420,-1); end end %% A1 moving-average input suppression if run_a1 eq_ffe = FFE_A1( ... "sps", eq_sps, ... "order", eq_order, ... "decide", false, ... "adaption_technique", eq_adaption, ... "len_tr", eq_len_tr, ... "epochs_tr", eq_epochs_tr, ... "mu_tr", eq_mu_tr, ... "dd_mode", false, ... "epochs_dd", eq_epochs_dd, ... "mu_dd", 0.012, ... "dc_smoothing_a1", 1, ... "dc_avg_bufferlength_a1", 2048, ... "dc_avg_update_blocklength_a1", block_update, ... "save_debug", eq_save_debug); [ffe_results,equalized_signal] = runFfe(eq_ffe, "A1", ... Scpe_sig, Symbols, Tx_bits, options); output.a1_ff_dc_avg = ffe_results; if plot_output_signals plotEqSignals(equalized_signal,Symbols,options,430,-1); end end %% DC tracking, adaptive/persistence path if run_tracking_adaptive eq_ffe = FFE_DCTracking( ... "sps", eq_sps, ... "order", eq_order, ... "decide", false, ... "adaption_technique", eq_adaption, ... "len_tr", eq_len_tr, ... "epochs_tr", eq_epochs_tr, ... "mu_tr", eq_mu_tr, ... "dd_mode", true, ... "epochs_dd", eq_epochs_dd, ... "mu_dd", 0.012, ... "dc_tracking_mu", 0.002, ... "dc_tracking_adaptive_enabled", true, ... "dc_tracking_persistence_gain", 0, ... "dc_tracking_buffer_len", block_update, ... "optmize_mus", false, ... "plot_mu_optimization", options.debug_plots, ... "save_debug", eq_save_debug); [ffe_results,equalized_signal] = runFfe(eq_ffe, "DC tracking adaptive", ... Scpe_sig, Symbols, Tx_bits, options); output.dc_tracking = ffe_results; if plot_output_signals plotEqSignals(equalized_signal,Symbols,options,450,-1); end end end function [ffe_results,equalized_signal] = runFfe(eq_ffe,description,Scpe_sig,Symbols,Tx_bits,options) [ffe_results,equalized_signal] = ffe(eq_ffe, options.M, Scpe_sig, Symbols, Tx_bits, ... "precode_mode", options.duob_mode, ... "showAnalysis", options.debug_plots, ... "postFFE", [], ... "eth_style_symbol_mapping", 0); ffe_results.metrics.print("description",resultDescription(description,options)); end function description = resultDescription(prefix,options) sir = options.dataTable.sir; if numel(sir) > 1 sir = sir(1); end description = sprintf('%s; SIR %g dB',prefix,sir); end function plotEqSignals(equalized_signal,Symbols,options,fignum,output_scale) showLevelScatter(equalized_signal .* output_scale, Symbols, ... "fsym", options.fsym, ... "fignum", fignum + 1, ... "normalize", true); end