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); eq_settings = { ... "epochs_tr", 5, ... "epochs_dd", 5, ... "len_tr", 4096, ... "mu_tr",0.04, ... "mu_dd",0.012, ... "mu_dc", 0.012, ... "adaptive_dc_enabled", 0, ... "order", 25, ... "sps", 2, ... "decide", 0, ... "optmize_mus", 0, ... "dd_mode", 1, ... "adaption_technique", "nlms", ... "plot_mu_optimization", options.debug_plots,... "save_debug",true}; eq_ffe = FFE(eq_settings{:}); showLevelScatter(Scpe_sig_raw, Symbols, ... "fsym", options.fsym, ... "fignum", 400, ... "normalize", true); % Scpe_sig_raw.spectrum("normalizeTo0dB",1,"fft_length",4096*4,"fignum",401); %options.dataTable.sir; %% 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"); mu_dc_eff_s = movmean(dbg.mu_dc_eff(:),smooth_len,"omitnan"); e_dc_eff_s = movmean(dbg.e_dc_eff(:),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(mu_dc_eff_s,"DisplayName","mu DC - either fixed or adaptive"); e_dc_scale = max(abs(e_dc_eff_s),[],"omitnan") + eps; plot(-1.*e_dc_eff_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 = -e_dc_eff_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