New MPI mitigation schemes // Duobinary // Start of FTN schemes
This commit is contained in:
211
Classes/04_DSP/Equalizer/FFE_FFDCAVG.m
Normal file
211
Classes/04_DSP/Equalizer/FFE_FFDCAVG.m
Normal file
@@ -0,0 +1,211 @@
|
||||
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),112);
|
||||
dc_err = zeros(numel(obj.constellation),1);
|
||||
dc_sto = NaN(numel(obj.constellation),N);
|
||||
|
||||
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
|
||||
always_correct_decision = 0;
|
||||
if always_correct_decision
|
||||
[~,symbol_idx] = min(abs(d(symbol) - obj.constellation)); % decision for closest constellation point
|
||||
else
|
||||
[~,symbol_idx] = min(abs(y(symbol) - obj.constellation)); % decision for closest constellation point
|
||||
end
|
||||
d_hat(symbol,1) = obj.constellation(symbol_idx);
|
||||
end
|
||||
|
||||
err(symbol) = y(symbol) - d_hat(symbol); % Instantaneous error
|
||||
|
||||
if 1
|
||||
%use buffer for dc-error
|
||||
err_buffer(symbol_idx,1) = err(symbol);
|
||||
err_buffer(symbol_idx,:) = circshift(err_buffer(symbol_idx,:),1);
|
||||
dc_sto(symbol_idx,symbol) = obj.mu_buff*mean(err_buffer(symbol_idx,:));
|
||||
y(symbol) = y(symbol) - obj.mu_buff * mean(err_buffer(symbol_idx,:));
|
||||
else
|
||||
%or use 1+alpha*D as adaptive error
|
||||
dc_err(symbol_idx) = dc_err(symbol_idx) + obj.mu_buff * err(symbol);
|
||||
dc_sto(symbol_idx,symbol) = dc_err(symbol_idx);
|
||||
y(symbol) = y(symbol) - dc_err(symbol_idx);
|
||||
end
|
||||
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user