EQ Structures for MPI mitigation

This commit is contained in:
Silas
2024-08-15 09:40:59 +02:00
parent 34f9149346
commit 23f386da77
13 changed files with 880 additions and 135 deletions

View File

@@ -0,0 +1,179 @@
classdef FFE_DCremoval < handle
% Implementation of plain and simple FFE.
% 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);
properties
sps % usually 2
order
e
error
len_tr
mu_tr
epochs_tr
mu_dd
epochs_dd
mu_dc
constellation
decide
end
methods
function obj = FFE_DCremoval(options)
arguments(Input)
options.sps = 2;
options.order = 15;
options.len_tr = 4096;
options.mu_tr = 0;
options.epochs_tr = 5;
options.mu_dd = 1e-5;
options.epochs_dd = 5;
options.mu_dc = 0.05;
options.decide = false;
end
fn = fieldnames(options);
for n = 1:numel(fn)
obj.(fn{n}) = options.(fn{n});
end
obj.e = zeros(obj.order,1);
obj.error = 0;
end
function [X] = process(obj, X, D)
% actual processing of the signal (steps 1. - 3.)
% 1 normalize RMS
X = X.normalize("mode","rms");
obj.constellation = unique(D.signal);
% Training Mode
training = 1;
showviz = 0;
obj.equalize(X.signal, D.signal,obj.mu_tr,obj.epochs_tr,obj.len_tr,training,showviz);
% Decision Directed Mode
N = X.length;
training = 0;
showviz = 0;
[signal,decision]=obj.equalize(X.signal, D.signal,obj.mu_dd,obj.epochs_dd,N,training,showviz);
% Output Signal
if obj.decide
X.signal = decision;
else
X.signal = signal;
end
X.fs = D.fs; %change sampling frequency of outgoing signal from fdac e.g. 2 sps to symbol spaced = fsym
lbdesc = [num2str(obj.order),' tap FFE'];
X = X.logbookentry(lbdesc); % append to logbook
end
function [y,d_hat] = equalize(obj,x,d,mio,epochs,N,training,showviz)
arguments
obj
x
d
mio
epochs
N
training
showviz
end
x = [zeros(floor(obj.order/2),1); x; zeros(obj.order,1)];
if showviz
f = figure(111);
subplot(2,2,1:2);
hold on
a = scatter(1:numel(x),x,1,'.');
a2 = scatter(1,1,1,'.');
a3 = scatter(1,1,2,'.');
a4 = xline(1);
ylim([-3 3])
xlim([0 length(x)]);
% subplot(2,2,3)
% dplot = x(1:1+500);
% b = scatter(1:numel(dplot),dplot,5,'x');
% xline(1)
% xline(obj.order)
% ylim([-3 3])
% xlim([0 500]);
subplot(2,2,3:4)
c = stem(obj.e);
ylim([-1 1])
drawnow
end
err = 0;
e_dc = 0;
for epoch = 1 : epochs
symbol = 0;
for sample = 1 : obj.sps : N
symbol = symbol+1;
U = x(obj.order+sample-1:-1:sample);
y(symbol,1) = e_dc + obj.e.' * U; % Calculating output of LMS __ * |
if training
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);
end
err(symbol) = y(symbol) - d_hat(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
end
if mod(sample,100) == 1 && showviz
a2.XData = 1:2*numel(y);
a2.YData = repelem(y, 2);
a3.XData = 1:2*numel(d_hat);
a3.YData = repelem(d_hat, 2);
a4.Value = sample;
% b.YData = x(symbol:symbol+500);
c.YData = obj.e;
drawnow;
end
e_dc = e_dc - obj.mu_dc * err(symbol);
obj.error(epoch,symbol) = err(symbol) * err(symbol)'; % Instantaneous square error
end
end
end
end
end

View File

@@ -0,0 +1,193 @@
classdef FFE_FFDCAVG < handle
% Implementation of plain and simple FFE.
% 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);
properties
sps % usually 2
order
e
error
len_tr
mu_tr
epochs_tr
mu_dd
epochs_dd
mu_buff
constellation
decide
end
methods
function obj = FFE_FFDCAVG(options)
arguments(Input)
options.sps = 2;
options.order = 15;
options.len_tr = 4096;
options.mu_tr = 0;
options.epochs_tr = 5;
options.mu_dd = 1e-5;
options.epochs_dd = 5;
options.mu_buff = 0;
options.decide = false;
end
fn = fieldnames(options);
for n = 1:numel(fn)
obj.(fn{n}) = options.(fn{n});
end
obj.e = zeros(obj.order,1);
obj.error = 0;
end
function [X] = process(obj, X, D)
% actual processing of the signal (steps 1. - 3.)
% 1 normalize RMS
X = X.normalize("mode","rms");
obj.constellation = unique(D.signal);
% Training Mode
training = 1;
showviz = 0;
obj.equalize(X.signal, D.signal,obj.mu_tr,obj.epochs_tr,obj.len_tr,training,showviz);
% Decision Directed Mode
N = X.length;
training = 0;
showviz = 0;
[signal,decision]=obj.equalize(X.signal, D.signal,obj.mu_dd,obj.epochs_dd,N,training,showviz);
% Output Signal
if obj.decide
X.signal = decision;
else
X.signal = signal;
end
X.fs = D.fs; %change sampling frequency of outgoing signal from fdac e.g. 2 sps to symbol spaced = fsym
lbdesc = [num2str(obj.order),' tap FFE'];
X = X.logbookentry(lbdesc); % append to logbook
end
function [y,d_hat] = equalize(obj,x,d,mio,epochs,N,training,showviz)
arguments
obj
x
d
mio
epochs
N
training
showviz
end
x = [zeros(floor(obj.order/2),1); x; zeros(obj.order,1)];
if showviz
f = figure(111);
subplot(2,2,1:2);
hold on
a = scatter(1:numel(x),x,1,'.');
a2 = scatter(1,1,1,'.');
a3 = scatter(1,1,2,'.');
a4 = xline(1);
ylim([-3 3])
xlim([0 length(x)]);
% subplot(2,2,3)
% dplot = x(1:1+500);
% b = scatter(1:numel(dplot),dplot,5,'x');
% xline(1)
% xline(obj.order)
% ylim([-3 3])
% xlim([0 500]);
subplot(2,2,3:4)
c = stem(obj.e);
ylim([-1 1])
drawnow
end
for epoch = 1 : epochs
symbol = 0;
err_buffer = zeros(numel(obj.constellation),50);
for sample = 1 : obj.sps : N
symbol = symbol+1;
U = x(obj.order+sample-1:-1:sample);
y(symbol,1) = obj.e.' * U; % Calculating output of LMS __ * |
if training
[~,symbol_idx] = min(abs(d(symbol) - obj.constellation)); % decision for closest constellation point
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);
end
err(symbol) = y(symbol) - d_hat(symbol); % Instantaneous error
err_buffer(symbol_idx,1) = err(symbol);
err_buffer(symbol_idx,:) = circshift(err_buffer(symbol_idx,:),1);
y(symbol) = y(symbol) - obj.mu_buff*mean(err_buffer(symbol_idx,:));
if training
[~,symbol_idx] = min(abs(d(symbol) - obj.constellation)); % decision for closest constellation point
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);
end
err(symbol) = y(symbol) - d_hat(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
end
if mod(sample,100) == 1 && showviz
a2.XData = 1:2*numel(y);
a2.YData = repelem(y, 2);
a3.XData = 1:2*numel(d_hat);
a3.YData = repelem(d_hat, 2);
a4.Value = sample;
% b.YData = x(symbol:symbol+500);
c.YData = obj.e;
drawnow;
end
obj.error(epoch,symbol) = err(symbol) * err(symbol)'; % Instantaneous square error
end
end
end
end
end

View File

@@ -0,0 +1,149 @@
classdef FFE_adaptive_decision < handle
% Implementation of plain and simple FFE.
% 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);
properties
sps % usually 2
order
e
error
len_tr
mu_tr
epochs_tr
mu_dd
epochs_dd
buffer_length
constellation
decide
end
methods
function obj = FFE_adaptive_decision(options)
arguments(Input)
options.sps = 2;
options.order = 15;
options.len_tr = 4096;
options.mu_tr = 0;
options.epochs_tr = 5;
options.mu_dd = 1e-5;
options.epochs_dd = 5;
options.buffer_length = 100;
options.decide = false;
end
fn = fieldnames(options);
for n = 1:numel(fn)
obj.(fn{n}) = options.(fn{n});
end
obj.e = zeros(obj.order,1);
obj.error = 0;
end
function [X] = process(obj, X, D)
% actual processing of the signal (steps 1. - 3.)
% 1 normalize RMS
X = X.normalize("mode","rms");
obj.constellation = unique(D.signal);
% Training Mode
training = 1;
showviz = 0;
obj.equalize(X.signal, D.signal,obj.mu_tr,obj.epochs_tr,obj.len_tr,training,showviz);
% Decision Directed Mode
N = X.length;
training = 0;
showviz = 0;
[signal,decision]=obj.equalize(X.signal, D.signal,obj.mu_dd,obj.epochs_dd,N,training,showviz);
% Output Signal
if obj.decide
X.signal = decision;
else
X.signal = signal;
end
X.fs = D.fs; %change sampling frequency of outgoing signal from fdac e.g. 2 sps to symbol spaced = fsym
lbdesc = [num2str(obj.order),' tap FFE'];
X = X.logbookentry(lbdesc); % append to logbook
end
function [y,d_hat] = equalize(obj,x,d,mio,epochs,N,training,showviz)
arguments
obj
x
d
mio
epochs
N
training
showviz
end
x = [zeros(floor(obj.order/2),1); x; zeros(obj.order,1)];
for epoch = 1 : epochs
symbol = 0;
% y_buffer = zeros(numel(obj.constellation),500);
y_buffer = repmat(obj.constellation,1,obj.buffer_length);
for sample = 1 : obj.sps : N
symbol = symbol+1;
U = x(obj.order+sample-1:-1:sample);
y(symbol,1) = obj.e.' * U; % Calculating output of LMS __ * |
if training
[~,symbol_idx] = min(abs(d(symbol) - obj.constellation)); % decision for closest constellation point
d_hat(symbol,1) = d(symbol);
else
y_buffer(y_buffer==0) = NaN;
adap_constellation = mean(y_buffer,2,"omitnan");
[~,symbol_idx] = min(abs(y(symbol) - adap_constellation)); % decision for closest constellation point
d_hat(symbol,1) = obj.constellation(symbol_idx);
end
y_buffer(symbol_idx,1) = y(symbol);
y_buffer(symbol_idx,:) = circshift(y_buffer(symbol_idx,:),1);
err(symbol) = y(symbol) - d_hat(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
end
obj.error(epoch,symbol) = err(symbol) * err(symbol)'; % Instantaneous square error
end
end
end
end
end