Many changes towards simulation of JLT and once again the evaluation of the Highspeed data from Lab experiments 2024
This commit is contained in:
@@ -3,24 +3,34 @@ classdef FFE < handle
|
||||
% 1) Training mode (stable performance when you use NLMS)
|
||||
% 2) Decision directed mode
|
||||
|
||||
% Eq = FFE("epochs_tr",5,"epochs_dd",5,"len_tr",4096*2,"mu_dd",1e-4,"mu_tr",0,"order",25,"sps",2,"decide",0);
|
||||
%LMS: mu in order of 0.001 for acceptable convergence speed
|
||||
%NLMS: mu in order of 0.01 for acceptable convergence speed
|
||||
%RLS: mu is lambda -> 0.99 -> 1 (has a strong dependency on this! use a loop to find out best values)
|
||||
|
||||
% FFE("epochs_tr",5,"epochs_dd",2,"len_tr",2^13,"mu_dd",mu_dd,"mu_tr",mu_tr,"order",25,"sps",2,"decide",0, "adaption",adaption_method(adaption),"dd_mode",use_dd_mode);
|
||||
|
||||
properties
|
||||
sps % usually 2
|
||||
order
|
||||
e
|
||||
e_tr
|
||||
error
|
||||
debug_struct
|
||||
|
||||
len_tr
|
||||
mu_tr
|
||||
epochs_tr
|
||||
|
||||
mu_dd
|
||||
adaption_technique % nlms, lms, rls
|
||||
dd_mode % 1 or 0 to set DD-mode on or off
|
||||
mu_dd %weight update in dd mode
|
||||
epochs_dd
|
||||
|
||||
constellation
|
||||
P % covariance matrix of rls
|
||||
|
||||
decide
|
||||
constellation % symbol constellation
|
||||
|
||||
decide %wether to return the (hard) decisions or the result after FFE (soft)
|
||||
end
|
||||
|
||||
methods
|
||||
@@ -34,6 +44,8 @@ classdef FFE < handle
|
||||
options.mu_tr = 0;
|
||||
options.epochs_tr = 5;
|
||||
|
||||
options.adaption_technique adaption_method = adaption_method.lms;
|
||||
options.dd_mode = 1;
|
||||
options.mu_dd = 1e-5;
|
||||
options.epochs_dd = 5;
|
||||
|
||||
@@ -59,10 +71,15 @@ classdef FFE < handle
|
||||
|
||||
obj.constellation = unique(D.signal);
|
||||
|
||||
|
||||
delta = 0.05;
|
||||
obj.P = (1/delta) * eye(obj.order);
|
||||
|
||||
% Training Mode
|
||||
training = 1;
|
||||
showviz = 0;
|
||||
obj.equalize(X.signal, D.signal,obj.mu_tr,obj.epochs_tr,obj.len_tr,training,showviz);
|
||||
obj.e_tr = obj.e;
|
||||
|
||||
% Decision Directed Mode
|
||||
n = X.length;
|
||||
@@ -71,7 +88,7 @@ classdef FFE < handle
|
||||
[signal,decision]=obj.equalize(X.signal, D.signal,obj.mu_dd,obj.epochs_dd,n,training,showviz);
|
||||
|
||||
% Output Signal
|
||||
if obj.decide
|
||||
if obj.decide
|
||||
X.signal = decision;
|
||||
else
|
||||
X.signal = signal;
|
||||
@@ -83,24 +100,25 @@ classdef FFE < handle
|
||||
|
||||
Noi = X;
|
||||
Noi = X - D;
|
||||
|
||||
|
||||
|
||||
end
|
||||
|
||||
function [y,d_hat] = equalize(obj,x,d,mio,epochs,N,training,showviz)
|
||||
function [y,d_hat] = equalize(obj,x,d,mu,epochs,N,training,showviz)
|
||||
|
||||
arguments
|
||||
obj
|
||||
x
|
||||
d
|
||||
mio
|
||||
epochs
|
||||
N
|
||||
training
|
||||
obj
|
||||
x
|
||||
d
|
||||
mu
|
||||
epochs
|
||||
N
|
||||
training
|
||||
showviz
|
||||
end
|
||||
|
||||
x = [zeros(floor(obj.order/2),1); x; zeros(obj.order,1)];
|
||||
lambda = mu;
|
||||
|
||||
if training
|
||||
mask = ones(obj.order,1);
|
||||
@@ -111,8 +129,17 @@ classdef FFE < handle
|
||||
end
|
||||
|
||||
mask = ones(obj.order,1);
|
||||
maincursor_pos=ceil(length(obj.e)/2);
|
||||
always_ideal_decision = 0;
|
||||
save_debug = 1;
|
||||
grad =0;
|
||||
weight = 0;
|
||||
update = 0;
|
||||
|
||||
if mu == 0 || (~obj.dd_mode && ~training)
|
||||
epochs = 1;
|
||||
end
|
||||
|
||||
|
||||
for epoch = 1 : epochs
|
||||
symbol = 0;
|
||||
for sample = 1 : obj.sps : N
|
||||
@@ -124,30 +151,75 @@ classdef FFE < handle
|
||||
y(symbol,1) = (obj.e.*mask).' * U; % Calculating output of LMS __ * |
|
||||
|
||||
if training
|
||||
d_hat(symbol,1) = d(symbol);
|
||||
d_hat(symbol,1) = d(symbol);
|
||||
else
|
||||
[~,symbol_idx] = min(abs(y(symbol) - obj.constellation)); % decision for closest constellation point
|
||||
d_hat(symbol,1) = obj.constellation(symbol_idx);
|
||||
if ~always_ideal_decision
|
||||
[~,symbol_idx] = min(abs(y(symbol) - obj.constellation)); % decision for closest constellation point
|
||||
d_hat(symbol,1) = obj.constellation(symbol_idx);
|
||||
else
|
||||
d_hat(symbol,1) = d(symbol);
|
||||
end
|
||||
end
|
||||
|
||||
err(symbol) = y(symbol) - d_hat(symbol); % Instantaneous error
|
||||
% err(symbol) = y(symbol) - d_hat(symbol); % Instantaneous error
|
||||
err(symbol) = d_hat(symbol) - y(symbol); % Instantaneous error
|
||||
|
||||
true_err(symbol) = y(symbol) - d(symbol); % Instantaneous error
|
||||
|
||||
if mio ~= 0
|
||||
obj.e = obj.e - (mio * err(symbol) * U) ; % Weight update rule of LMS
|
||||
else
|
||||
normalizationfactor = (U.' * U);
|
||||
obj.e = obj.e - err(symbol) * U / normalizationfactor; % Weight update rule of NLMS
|
||||
if training || obj.dd_mode
|
||||
switch obj.adaption_technique
|
||||
|
||||
case adaption_method.lms
|
||||
|
||||
% mu used as update weight (suggestion: 0.001)
|
||||
weight = mu;
|
||||
grad = err(symbol) * U;
|
||||
update = grad * weight;
|
||||
obj.e = obj.e + update;
|
||||
|
||||
case adaption_method.nlms
|
||||
|
||||
% mu used as update weight (suggestion: 0.01-0.05; bit higher during tr)
|
||||
normU = ((U.'*U)) + eps;
|
||||
weight = mu / normU;
|
||||
grad = err(symbol) * U;
|
||||
update = grad * weight;
|
||||
obj.e = obj.e + update;
|
||||
|
||||
case adaption_method.rls
|
||||
|
||||
|
||||
% RLS‐Gain:
|
||||
denom = lambda + U.' * obj.P * U;
|
||||
k = (obj.P * U) / denom;
|
||||
|
||||
% Gewichtsupdate:
|
||||
update = k * err(symbol);
|
||||
obj.e = obj.e + update;
|
||||
|
||||
% P-Matrix‐Update:
|
||||
obj.P = (1/lambda) * (obj.P - k * (U.' * obj.P));
|
||||
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
obj.error(epoch,symbol) = err(symbol) * err(symbol)'; % Instantaneous square error
|
||||
|
||||
if save_debug
|
||||
obj.debug_struct.error(epoch,symbol) = err(symbol) * err(symbol)'; % Instantaneous square error
|
||||
if training
|
||||
obj.debug_struct.error_tr(epoch,symbol) = err(symbol) * err(symbol)'; % Instantaneous square error
|
||||
obj.debug_struct.update_tr(epoch,symbol) = update.'*update ./ rms(obj.e);
|
||||
end
|
||||
obj.debug_struct.main_cursor(epoch,symbol) = abs(obj.e(maincursor_pos));
|
||||
obj.debug_struct.mu_nlms(epoch,symbol) = weight;
|
||||
obj.debug_struct.update_gradient(epoch,symbol) = grad.'*grad;
|
||||
obj.debug_struct.update(epoch,symbol) = update.'*update ./ rms(obj.e);
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
Reference in New Issue
Block a user