From a91da3b97c35e6fd750c18f7d7fda4191afebc2d Mon Sep 17 00:00:00 2001 From: Silas Oettinghaus Date: Fri, 22 May 2026 15:28:37 +0200 Subject: [PATCH] FFE with DC tap. But RLS does not work anymore --- Classes/04_DSP/Equalizer/FFE.m | 92 ++++++++++++++++++++++++++++++---- 1 file changed, 82 insertions(+), 10 deletions(-) diff --git a/Classes/04_DSP/Equalizer/FFE.m b/Classes/04_DSP/Equalizer/FFE.m index 849539e..f3f822d 100644 --- a/Classes/04_DSP/Equalizer/FFE.m +++ b/Classes/04_DSP/Equalizer/FFE.m @@ -25,6 +25,9 @@ classdef FFE < handle dd_mode % 1 or 0 to set DD-mode on or off mu_dd %weight update in dd mode epochs_dd + dd_len_fraction + mu_dc + e_dc P % covariance matrix of rls @@ -55,6 +58,8 @@ classdef FFE < handle options.dd_mode = 1; options.mu_dd = 1e-5; options.epochs_dd = 5; + options.dd_len_fraction = 0.25; + options.mu_dc = 0; options.decide = false; @@ -69,6 +74,7 @@ classdef FFE < handle end obj.e = zeros(obj.order,1); + obj.e_dc = 0; obj.error = 0; end @@ -80,6 +86,7 @@ classdef FFE < handle X = X.normalize("mode","rms"); obj.constellation = unique(D.signal); + obj.e_dc = 0; delta = 0.05; @@ -88,6 +95,7 @@ classdef FFE < handle if obj.optmize_mus obj.optimizeMus(X.signal,D.signal); obj.e = zeros(obj.order,1); + obj.e_dc = 0; obj.P = (1/delta) * eye(obj.order); end @@ -101,7 +109,11 @@ classdef FFE < handle n = X.length; training = 0; showviz = 0; - [signal,decision]=obj.equalize(X.signal, D.signal,obj.mu_dd,obj.epochs_dd,n,training,showviz); + if obj.dd_mode + n_dd = obj.ddLength(n); + obj.equalize(X.signal, D.signal,obj.mu_dd,obj.epochs_dd,n_dd,training,showviz); + end + [signal,decision]=obj.applyCurrentTaps(X.signal,n); % Output Signal if obj.decide @@ -163,7 +175,7 @@ classdef FFE < handle U = x(obj.order+sample-1:-1:sample); - y(symbol,1) = (obj.e.*mask).' * U; % Calculating output of LMS __ * | + y(symbol,1) = obj.e_dc + (obj.e.*mask).' * U; % Calculating output of LMS __ * | if training d_hat(symbol,1) = d(symbol); @@ -217,6 +229,10 @@ classdef FFE < handle end + + if obj.mu_dc ~= 0 + obj.e_dc = obj.e_dc + obj.mu_dc * err(symbol); + end end @@ -247,6 +263,28 @@ classdef FFE < handle end + function [y,d_hat] = applyCurrentTaps(obj,x,N) + x = [zeros(floor(obj.order/2),1); x; zeros(obj.order,1)]; + for sample = 1 : obj.sps : N + symbol = (sample - 1) / obj.sps + 1; + U = x(obj.order+sample-1:-1:sample); + y(symbol,1) = obj.e_dc + obj.e.' * U; + [~,symbol_idx] = min(abs(y(symbol) - obj.constellation)); + d_hat(symbol,1) = obj.constellation(symbol_idx); + end + end + + function N_dd = ddLength(obj,N) + if isempty(obj.dd_len_fraction) || obj.dd_len_fraction <= 0 || obj.dd_len_fraction >= 1 + N_dd = N; + return + end + + N_dd = floor(N * obj.dd_len_fraction); + N_dd = max(obj.sps,N_dd); + N_dd = min(N,N_dd); + end + function optimizeMus(obj,x,d) switch obj.adaption_technique case adaption_method.lms @@ -256,12 +294,17 @@ classdef FFE < handle case adaption_method.rls mu_range = [0.98, 0.99999]; end + mu_dc_range = [1e-5, 1e-1]; mu_tr_var = optimizableVariable("mu_tr",mu_range,"Transform","log"); vars = mu_tr_var; if obj.dd_mode vars = [vars, optimizableVariable("mu_dd",mu_range,"Transform","log")]; end + optimize_mu_dc = obj.mu_dc ~= 0; + if optimize_mu_dc + vars = [vars, optimizableVariable("mu_dc",mu_dc_range,"Transform","log")]; + end obj.mu_optimization_iter = 0; obj.mu_optimization = bayesopt(@(p)obj.muObjective(p,x,d),vars, ... "MaxObjectiveEvaluations",10, ... @@ -273,19 +316,39 @@ classdef FFE < handle if obj.dd_mode obj.mu_dd = obj.mu_optimization.XAtMinObjective.mu_dd; end - fprintf("\nFFE mu opt done: mu_tr=%9.3e, mu_dd=%9.3e, metric=%9.3e\n", ... - obj.mu_tr,obj.mu_dd,obj.mu_optimization.MinObjective); + if optimize_mu_dc + obj.mu_dc = obj.mu_optimization.XAtMinObjective.mu_dc; + end + objective_db = 10*log10(obj.mu_optimization.MinObjective); + if obj.dd_mode && optimize_mu_dc + fprintf("\nFFE mu opt done: mu_tr=%9.3e, mu_dd=%9.3e, mu_dc=%9.3e, MSE=%9.3e, MSE_dB=%7.2f dB\n", ... + obj.mu_tr,obj.mu_dd,obj.mu_dc,obj.mu_optimization.MinObjective,objective_db); + elseif obj.dd_mode + fprintf("\nFFE mu opt done: mu_tr=%9.3e, mu_dd=%9.3e, MSE=%9.3e, MSE_dB=%7.2f dB\n", ... + obj.mu_tr,obj.mu_dd,obj.mu_optimization.MinObjective,objective_db); + elseif optimize_mu_dc + fprintf("\nFFE mu opt done: mu_tr=%9.3e, mu_dc=%9.3e, MSE=%9.3e, MSE_dB=%7.2f dB\n", ... + obj.mu_tr,obj.mu_dc,obj.mu_optimization.MinObjective,objective_db); + else + fprintf("\nFFE mu opt done: mu_tr=%9.3e, MSE=%9.3e, MSE_dB=%7.2f dB\n", ... + obj.mu_tr,obj.mu_optimization.MinObjective,objective_db); + end end function objective = muObjective(obj,params,x,d) old_debug = obj.save_debug; + old_mu_dc = obj.mu_dc; obj.save_debug = 1; + if isprop(params,"mu_dc") + obj.mu_dc = params.mu_dc; + end obj.e = zeros(obj.order,1); + obj.e_dc = 0; obj.P = (1/0.05) * eye(obj.order); obj.debug_struct = struct(); obj.equalize(x,d,params.mu_tr,obj.epochs_tr,obj.len_tr,1,0); if obj.dd_mode - obj.equalize(x,d,params.mu_dd,obj.epochs_dd,numel(x),0,0); + obj.equalize(x,d,params.mu_dd,obj.epochs_dd,obj.ddLength(numel(x)),0,0); objective = mean(obj.debug_struct.error(end,:),"omitnan"); else objective = mean(obj.debug_struct.error_tr(end,:),"omitnan"); @@ -293,15 +356,24 @@ classdef FFE < handle if ~isfinite(objective) objective = inf; end + objective_db = 10*log10(objective); obj.mu_optimization_iter = obj.mu_optimization_iter + 1; - if obj.dd_mode - fprintf("\rFFE mu opt %02d: mu_tr=%9.3e, mu_dd=%9.3e, metric=%9.3e", ... - obj.mu_optimization_iter,params.mu_tr,params.mu_dd,objective); + optimize_mu_dc = isprop(params,"mu_dc"); + if obj.dd_mode && optimize_mu_dc + fprintf("\rFFE mu opt %02d: mu_tr=%9.3e, mu_dd=%9.3e, mu_dc=%9.3e, MSE=%9.3e, MSE_dB=%7.2f dB", ... + obj.mu_optimization_iter,params.mu_tr,params.mu_dd,params.mu_dc,objective,objective_db); + elseif obj.dd_mode + fprintf("\rFFE mu opt %02d: mu_tr=%9.3e, mu_dd=%9.3e, MSE=%9.3e, MSE_dB=%7.2f dB", ... + obj.mu_optimization_iter,params.mu_tr,params.mu_dd,objective,objective_db); + elseif optimize_mu_dc + fprintf("\rFFE mu opt %02d: mu_tr=%9.3e, mu_dc=%9.3e, MSE=%9.3e, MSE_dB=%7.2f dB", ... + obj.mu_optimization_iter,params.mu_tr,params.mu_dc,objective,objective_db); else - fprintf("\rFFE mu opt %02d: mu_tr=%9.3e, metric=%9.3e", ... - obj.mu_optimization_iter,params.mu_tr,objective); + fprintf("\rFFE mu opt %02d: mu_tr=%9.3e, MSE=%9.3e, MSE_dB=%7.2f dB", ... + obj.mu_optimization_iter,params.mu_tr,objective,objective_db); end obj.save_debug = old_debug; + obj.mu_dc = old_mu_dc; end end end