classdef FFE < 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 constellation decide end methods function obj = FFE(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.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,Noi] = 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 Noi = X; Noi = X - D; 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; 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 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 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 end obj.error(epoch,symbol) = err(symbol) * err(symbol)'; % Instantaneous square error end end end end end