function output = mpi_recipe_dev(Scpe_sig_raw, Symbols, Tx_bits, options) %mpi_recipe_dev Minimal example recipe for the DSP job framework. % This recipe intentionally performs only light preprocessing and records % summary values. It demonstrates the recipe interface without running a % full equalizer chain. 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 Scpe_sig = preprocessSignal(Scpe_sig_raw, Symbols, options.fsym, ... "mode", "auto", ... "debug_plots", options.debug_plots); output = struct(); eq_core_settings = { ... "sps", 2, ... "order", 25, ... "decide", 0, ... "adaption_technique", "nlms"}; eq_training_settings = { ... "len_tr", 4096, ... "epochs_tr", 5, ... "mu_tr", 0.04}; eq_dd_settings = { ... "dd_mode", 1, ... "epochs_dd", 5, ... "mu_dd", 0.012}; eq_a1_settings = { ... "dc_smoothing_a1", 0, ... "dc_avg_bufferlength_a1", 0}; eq_a2_settings = { ... "dc_smoothing_a2", 0, ... "dc_level_avg_bufferlength_a2", 0, ... "dc_level_weights_a2", [0.692 0.979 0.98 0.138]}; eq_dc_tracking_settings = { ... "dc_tracking_mu", 0.05, ... "dc_tracking_adaptive_enabled", 0, ... "dc_tracking_buffer_len", 1024}; eq_ffe_update_settings = { ... "ffe_update_buffer_len", 1}; eq_optimizer_settings = { ... "optmize_mus", 0, ... "plot_mu_optimization", options.debug_plots, ... "optimize_dc_tracking_params", 1, ... "optimize_a2_level_weights", 0, ... "a2_level_weight_optimization_len", 2^15, ... "a2_level_weight_optimization_max_evals", 30, ... "a2_level_weight_max", 1}; eq_debug_settings = { ... "save_debug", true}; eq_settings = [ ... eq_core_settings, ... eq_training_settings, ... eq_dd_settings, ... eq_a1_settings, ... eq_a2_settings, ... eq_dc_tracking_settings, ... eq_ffe_update_settings, ... eq_optimizer_settings, ... eq_debug_settings]; eq_ffe = FFE(eq_settings{:}); showLevelScatter(Scpe_sig_raw, Symbols, ... "fsym", options.fsym, ... "fignum", 400, ... "normalize", true); %% NORMAL FFE if 1 [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",sprintf('Normal FFE; SIR %d dB',options.dataTable.sir)); output.ffe_package = ffe_results; [~, avg_for_lvl] = showLevelScatter(equalized_signal, Symbols, ... "fsym", options.fsym, ... "fignum", 401, ... "normalize", true); output.ffe_debug = struct(); dbg = eq_ffe.debug_struct; smooth_len = 501; output.ffe_debug.smoothing_window = smooth_len; error_first_s = movmean(dbg.error_first_epoch(:),smooth_len,"omitnan"); error_last_s = movmean(dbg.error(:),smooth_len,"omitnan"); dc_tracking_mu_eff_s = movmean(dbg.dc_tracking_mu_eff(:),smooth_len,"omitnan"); dc_tracking_est_s = movmean(dbg.dc_tracking_est(:),smooth_len,"omitnan"); figure(460); clf; tiledlayout(2,1,"TileSpacing","compact","Padding","compact"); nexttile; semilogy(error_first_s + eps,"DisplayName","first epoch"); hold on; semilogy(error_last_s + eps,"DisplayName","last epoch"); grid on; ylabel("error"); title("FFE debug error"); legend("Location","best"); nexttile;hold on % plot(eq_sig_mov,"DisplayName","err dc eff"); plot(dc_tracking_mu_eff_s,"DisplayName","mu DC - either fixed or adaptive"); e_dc_scale = max(abs(dc_tracking_est_s),[],"omitnan") + eps; plot(-1.*dc_tracking_est_s./e_dc_scale,"DisplayName","Inverted DC-tracking; Value that is subtracted during EQ"); avg_lvl_dc=mean(avg_for_lvl,1,"omitnan"); plot(avg_lvl_dc./0.01,"DisplayName","Smoothed EQ output signal; calc'd by showLevelScatter"); grid on; xlabel("Symbol"); ylabel("mu dc eff"); title("Effective adaptive DC step"); legend inv_dc_track = -dc_tracking_est_s(:); avg_lvl_dc = avg_lvl_dc(:); xcorr_len = min(numel(inv_dc_track),numel(avg_lvl_dc)); inv_dc_xcorr = inv_dc_track(1:xcorr_len); avg_lvl_xcorr = avg_lvl_dc(1:xcorr_len); inv_dc_xcorr = fillmissing(inv_dc_xcorr,"linear","EndValues","nearest"); avg_lvl_xcorr = fillmissing(avg_lvl_xcorr,"linear","EndValues","nearest"); inv_dc_xcorr = inv_dc_xcorr - mean(inv_dc_xcorr,"omitnan"); avg_lvl_xcorr = avg_lvl_xcorr - mean(avg_lvl_xcorr,"omitnan"); [dc_level_xcorr,dc_level_lags] = xcorr(inv_dc_xcorr,avg_lvl_xcorr,"coeff"); [dc_level_corr,dc_level_idx] = max(dc_level_xcorr); dc_level_delay_symbols = dc_level_lags(dc_level_idx); output.ffe_debug.dc_level_delay_symbols = dc_level_delay_symbols; output.ffe_debug.dc_level_delay_corr = dc_level_corr; output.ffe_debug.dc_level_lags = dc_level_lags; output.ffe_debug.dc_level_xcorr = dc_level_xcorr; fprintf("FFE debug: xcorr(inv DC tracking, avg level) delay=%d symbols, corr=%6.3f\n", ... dc_level_delay_symbols,dc_level_corr); figure(461); clf; plot(dc_level_lags,dc_level_xcorr,"DisplayName","xcorr"); hold on; plot(dc_level_delay_symbols,dc_level_corr,"ro","DisplayName","max"); grid on; xlabel("Lag in symbols"); ylabel("Correlation coefficient"); title(sprintf("Delay estimate: %d symbols (corr %.3f)",dc_level_delay_symbols,dc_level_corr)); legend("Location","best"); end % % % %% MPI Reduction % if 1 % % % dc_buffer_len = 0; % % ffe_buffer_len = 0; % % smoothing_buffer_length = options.userParameters.smoothing_length; % % smoothing_buffer_update = 1; % % % eq_ffe_dcr = FFE_DCremoval_adaptive_mu(eq_settings{:}, ... % % "dc_buffer_len",dc_buffer_len, ... % % "ffe_buffer_len",ffe_buffer_len,... % % "smoothing_buffer_length",smoothing_buffer_length,... % % "smoothing_buffer_update",smoothing_buffer_update); % % eq_ = FFE_DCremoval("epochs_tr",5,"epochs_dd",3,"len_tr",4096*2,"mu_dd",... % 0.0002,"mu_tr",0,"order",25,"sps",2,"decide",0,... % "mu_dc",0.005,"dc_buffer_len",1); % % ffe_results_dcr = ffe(eq_, options.M, Scpe_sig, Symbols, Tx_bits, ... % "precode_mode", options.duob_mode, ... % 'showAnalysis', options.debug_plots, ... % "postFFE", [], ... % "eth_style_symbol_mapping", 0); % % ffe_results_dcr.metrics.print("description",'FFE DCR'); % output.ffe_dcr_package = ffe_results_dcr; % end end