FFE / MPI algorithm
This commit is contained in:
@@ -47,6 +47,7 @@ classdef FFE < handle
|
|||||||
optmize_mus = 0;
|
optmize_mus = 0;
|
||||||
mu_optimization
|
mu_optimization
|
||||||
mu_optimization_iter = 0;
|
mu_optimization_iter = 0;
|
||||||
|
mu_optimization_len
|
||||||
end
|
end
|
||||||
|
|
||||||
methods
|
methods
|
||||||
@@ -64,13 +65,14 @@ classdef FFE < handle
|
|||||||
options.dd_mode = 1;
|
options.dd_mode = 1;
|
||||||
options.mu_dd = 1e-5;
|
options.mu_dd = 1e-5;
|
||||||
options.epochs_dd = 5;
|
options.epochs_dd = 5;
|
||||||
options.dd_len_fraction = 0.25;
|
options.dd_len_fraction = 1;
|
||||||
options.mu_dc = 0;
|
options.mu_dc = 0;
|
||||||
|
|
||||||
options.decide = false;
|
options.decide = false;
|
||||||
|
|
||||||
options.save_debug = 0;
|
options.save_debug = 0;
|
||||||
options.optmize_mus = 0;
|
options.optmize_mus = 0;
|
||||||
|
options.mu_optimization_len = 2^15;
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -116,10 +118,10 @@ classdef FFE < handle
|
|||||||
training = 0;
|
training = 0;
|
||||||
showviz = 0;
|
showviz = 0;
|
||||||
if obj.dd_mode
|
if obj.dd_mode
|
||||||
n_dd = obj.ddLength(n);
|
[signal,decision] = obj.equalize(X.signal, D.signal,obj.mu_dd,obj.epochs_dd,n,training,showviz);
|
||||||
obj.equalize(X.signal, D.signal,obj.mu_dd,obj.epochs_dd,n_dd,training,showviz);
|
else
|
||||||
|
[signal,decision] = obj.equalize(X.signal, D.signal,0,1,n,training,showviz);
|
||||||
end
|
end
|
||||||
[signal,decision]=obj.applyCurrentTaps(X.signal,n);
|
|
||||||
|
|
||||||
% Output Signal
|
% Output Signal
|
||||||
if obj.decide
|
if obj.decide
|
||||||
@@ -175,6 +177,7 @@ classdef FFE < handle
|
|||||||
|
|
||||||
for epoch = 1 : epochs
|
for epoch = 1 : epochs
|
||||||
symbol = 0;
|
symbol = 0;
|
||||||
|
% obj.e_dc = 0;
|
||||||
for sample = 1 : obj.sps : N
|
for sample = 1 : obj.sps : N
|
||||||
|
|
||||||
symbol = symbol+1;
|
symbol = symbol+1;
|
||||||
@@ -269,17 +272,6 @@ classdef FFE < handle
|
|||||||
|
|
||||||
end
|
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)
|
function N_dd = ddLength(obj,N)
|
||||||
if isempty(obj.dd_len_fraction) || obj.dd_len_fraction <= 0 || obj.dd_len_fraction >= 1
|
if isempty(obj.dd_len_fraction) || obj.dd_len_fraction <= 0 || obj.dd_len_fraction >= 1
|
||||||
N_dd = N;
|
N_dd = N;
|
||||||
@@ -292,6 +284,8 @@ classdef FFE < handle
|
|||||||
end
|
end
|
||||||
|
|
||||||
function optimizeMus(obj,x,d)
|
function optimizeMus(obj,x,d)
|
||||||
|
[x_opt,d_opt,N_opt] = obj.optimizationSignals(x,d);
|
||||||
|
|
||||||
switch obj.adaption_technique
|
switch obj.adaption_technique
|
||||||
case adaption_method.lms
|
case adaption_method.lms
|
||||||
mu_range = [1e-5, 1e-2];
|
mu_range = [1e-5, 1e-2];
|
||||||
@@ -312,7 +306,8 @@ classdef FFE < handle
|
|||||||
vars = [vars, optimizableVariable("mu_dc",mu_dc_range,"Transform","log")];
|
vars = [vars, optimizableVariable("mu_dc",mu_dc_range,"Transform","log")];
|
||||||
end
|
end
|
||||||
obj.mu_optimization_iter = 0;
|
obj.mu_optimization_iter = 0;
|
||||||
obj.mu_optimization = bayesopt(@(p)obj.muObjective(p,x,d),vars, ...
|
fprintf("FFE mu opt uses %d samples / %d symbols\n",N_opt,numel(d_opt));
|
||||||
|
obj.mu_optimization = bayesopt(@(p)obj.muObjective(p,x_opt,d_opt),vars, ...
|
||||||
"MaxObjectiveEvaluations",20, ...
|
"MaxObjectiveEvaluations",20, ...
|
||||||
"AcquisitionFunctionName","expected-improvement-plus", ...
|
"AcquisitionFunctionName","expected-improvement-plus", ...
|
||||||
"IsObjectiveDeterministic",false, ...
|
"IsObjectiveDeterministic",false, ...
|
||||||
@@ -325,58 +320,84 @@ classdef FFE < handle
|
|||||||
if optimize_mu_dc
|
if optimize_mu_dc
|
||||||
obj.mu_dc = obj.mu_optimization.XAtMinObjective.mu_dc;
|
obj.mu_dc = obj.mu_optimization.XAtMinObjective.mu_dc;
|
||||||
end
|
end
|
||||||
objective_db = 10*log10(obj.mu_optimization.MinObjective);
|
|
||||||
if obj.dd_mode && optimize_mu_dc
|
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", ...
|
fprintf("\nFFE mu opt done: mu_tr=%9.3e, mu_dd=%9.3e, mu_dc=%9.3e, BER=%9.3e\n", ...
|
||||||
obj.mu_tr,obj.mu_dd,obj.mu_dc,obj.mu_optimization.MinObjective,objective_db);
|
obj.mu_tr,obj.mu_dd,obj.mu_dc,obj.mu_optimization.MinObjective);
|
||||||
elseif obj.dd_mode
|
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", ...
|
fprintf("\nFFE mu opt done: mu_tr=%9.3e, mu_dd=%9.3e, BER=%9.3e\n", ...
|
||||||
obj.mu_tr,obj.mu_dd,obj.mu_optimization.MinObjective,objective_db);
|
obj.mu_tr,obj.mu_dd,obj.mu_optimization.MinObjective);
|
||||||
elseif optimize_mu_dc
|
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", ...
|
fprintf("\nFFE mu opt done: mu_tr=%9.3e, mu_dc=%9.3e, BER=%9.3e\n", ...
|
||||||
obj.mu_tr,obj.mu_dc,obj.mu_optimization.MinObjective,objective_db);
|
obj.mu_tr,obj.mu_dc,obj.mu_optimization.MinObjective);
|
||||||
else
|
else
|
||||||
fprintf("\nFFE mu opt done: mu_tr=%9.3e, MSE=%9.3e, MSE_dB=%7.2f dB\n", ...
|
fprintf("\nFFE mu opt done: mu_tr=%9.3e, BER=%9.3e\n", ...
|
||||||
obj.mu_tr,obj.mu_optimization.MinObjective,objective_db);
|
obj.mu_tr,obj.mu_optimization.MinObjective);
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function objective_db = muObjective(obj,params,x,d)
|
function [x_opt,d_opt,N_opt] = optimizationSignals(obj,x,d)
|
||||||
|
N_available = min(numel(x),numel(d) * obj.sps);
|
||||||
|
|
||||||
|
if isempty(obj.mu_optimization_len) || obj.mu_optimization_len <= 0 || isinf(obj.mu_optimization_len)
|
||||||
|
N_opt = N_available;
|
||||||
|
else
|
||||||
|
N_opt = min(N_available,max(obj.len_tr,obj.mu_optimization_len));
|
||||||
|
end
|
||||||
|
|
||||||
|
N_opt = obj.sps * floor(N_opt / obj.sps);
|
||||||
|
N_opt = max(obj.sps,N_opt);
|
||||||
|
|
||||||
|
n_symbols = N_opt / obj.sps;
|
||||||
|
x_opt = x(1:N_opt);
|
||||||
|
d_opt = d(1:n_symbols);
|
||||||
|
end
|
||||||
|
|
||||||
|
function objective = muObjective(obj,params,x,d)
|
||||||
old_debug = obj.save_debug;
|
old_debug = obj.save_debug;
|
||||||
old_mu_dc = obj.mu_dc;
|
old_mu_dc = obj.mu_dc;
|
||||||
obj.save_debug = 1;
|
obj.save_debug = 0;
|
||||||
if isprop(params,"mu_dc")
|
has_mu_dc = any(strcmp(params.Properties.VariableNames,"mu_dc"));
|
||||||
|
if has_mu_dc
|
||||||
obj.mu_dc = params.mu_dc;
|
obj.mu_dc = params.mu_dc;
|
||||||
end
|
end
|
||||||
obj.e = zeros(obj.order,1);
|
obj.e = zeros(obj.order,1);
|
||||||
obj.e_dc = 0;
|
obj.e_dc = 0;
|
||||||
obj.P = (1/0.05) * eye(obj.order);
|
obj.P = (1/0.05) * eye(obj.order);
|
||||||
obj.debug_struct = struct();
|
obj.debug_struct = struct();
|
||||||
obj.equalize(x,d,params.mu_tr,obj.epochs_tr,obj.len_tr,1,0);
|
N_tr = min(obj.len_tr,numel(x));
|
||||||
|
[signal,~] = obj.equalize(x,d,params.mu_tr,obj.epochs_tr,N_tr,1,0);
|
||||||
if obj.dd_mode
|
if obj.dd_mode
|
||||||
obj.equalize(x,d,params.mu_dd,obj.epochs_dd,obj.ddLength(numel(x)),0,0);
|
[signal,~] = obj.equalize(x,d,params.mu_dd,obj.epochs_dd,numel(x),0,0);
|
||||||
objective = mean(obj.debug_struct.error(end,:),"omitnan");
|
|
||||||
else
|
|
||||||
objective = mean(obj.debug_struct.error_tr(end,:),"omitnan");
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
M = numel(unique(d));
|
||||||
|
mapper = PAMmapper(M,0);
|
||||||
|
eq_signal_sd = Signal(signal);
|
||||||
|
eq_signal_hd = mapper.quantize(eq_signal_sd);
|
||||||
|
tx_symbols = Signal(d);
|
||||||
|
rx_bits = mapper.demap(eq_signal_hd);
|
||||||
|
tx_bits = mapper.demap(tx_symbols);
|
||||||
|
[~,errors,ber,~] = calc_ber(rx_bits.signal,tx_bits.signal, ...
|
||||||
|
"skip_front",10, ...
|
||||||
|
"skip_end",10, ...
|
||||||
|
"returnErrorLocation",1);
|
||||||
|
objective = ber;
|
||||||
if ~isfinite(objective)
|
if ~isfinite(objective)
|
||||||
objective = inf;
|
objective = inf;
|
||||||
end
|
end
|
||||||
objective_db = 10*log10(objective);
|
|
||||||
obj.mu_optimization_iter = obj.mu_optimization_iter + 1;
|
obj.mu_optimization_iter = obj.mu_optimization_iter + 1;
|
||||||
optimize_mu_dc = isprop(params,"mu_dc");
|
if obj.dd_mode && has_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, BER=%9.3e, errors=%d", ...
|
||||||
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,ber,errors);
|
||||||
obj.mu_optimization_iter,params.mu_tr,params.mu_dd,params.mu_dc,objective,objective_db);
|
|
||||||
elseif obj.dd_mode
|
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", ...
|
fprintf("\rFFE mu opt %02d: mu_tr=%9.3e, mu_dd=%9.3e, BER=%9.3e, errors=%d", ...
|
||||||
obj.mu_optimization_iter,params.mu_tr,params.mu_dd,objective,objective_db);
|
obj.mu_optimization_iter,params.mu_tr,params.mu_dd,ber,errors);
|
||||||
elseif optimize_mu_dc
|
elseif has_mu_dc
|
||||||
fprintf("\rFFE mu opt %02d: mu_tr=%9.3e, mu_dc=%9.3e, MSE=%9.3e, MSE_dB=%7.2f dB", ...
|
fprintf("\rFFE mu opt %02d: mu_tr=%9.3e, mu_dc=%9.3e, BER=%9.3e, errors=%d", ...
|
||||||
obj.mu_optimization_iter,params.mu_tr,params.mu_dc,objective,objective_db);
|
obj.mu_optimization_iter,params.mu_tr,params.mu_dc,ber,errors);
|
||||||
else
|
else
|
||||||
fprintf("\rFFE mu opt %02d: mu_tr=%9.3e, MSE=%9.3e, MSE_dB=%7.2f dB", ...
|
fprintf("\rFFE mu opt %02d: mu_tr=%9.3e, BER=%9.3e, errors=%d", ...
|
||||||
obj.mu_optimization_iter,params.mu_tr,objective,objective_db);
|
obj.mu_optimization_iter,params.mu_tr,ber,errors);
|
||||||
end
|
end
|
||||||
obj.save_debug = old_debug;
|
obj.save_debug = old_debug;
|
||||||
obj.mu_dc = old_mu_dc;
|
obj.mu_dc = old_mu_dc;
|
||||||
|
|||||||
@@ -21,18 +21,18 @@ function output = mpi_recipe_dev(Scpe_sig_raw, Symbols, Tx_bits, options)
|
|||||||
"debug_plots", options.debug_plots);
|
"debug_plots", options.debug_plots);
|
||||||
|
|
||||||
|
|
||||||
mu_dc = 0.005;%1e-5;
|
mu_dc = 0;%1e-5;
|
||||||
|
|
||||||
eq_settings = { ...
|
eq_settings = { ...
|
||||||
"epochs_tr", 5, ...
|
"epochs_tr", 5, ...
|
||||||
"epochs_dd", 3, ...
|
"epochs_dd", 5, ...
|
||||||
"len_tr", 4096*2, ...
|
"len_tr", 4096*2, ...
|
||||||
"mu_dd",3.005e-03, ...
|
"mu_dd",0.02, ...
|
||||||
"mu_tr",1.063e-01, ...
|
"mu_tr",0.2, ...
|
||||||
"order", 25, ...
|
"order", 25, ...
|
||||||
"sps", 2, ...
|
"sps", 2, ...
|
||||||
"decide", 0, ...
|
"decide", 0, ...
|
||||||
"optmize_mus", 0, ...
|
"optmize_mus", 1, ...
|
||||||
"dd_mode", 1, ...
|
"dd_mode", 1, ...
|
||||||
"adaption_technique", "nlms", ...
|
"adaption_technique", "nlms", ...
|
||||||
"mu_dc", mu_dc};
|
"mu_dc", mu_dc};
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ dsp_options.recipe = @mpi_recipe_dev;
|
|||||||
dsp_options.append_to_db = false;
|
dsp_options.append_to_db = false;
|
||||||
dsp_options.start_occurence = 1;
|
dsp_options.start_occurence = 1;
|
||||||
dsp_options.max_occurences = 10;
|
dsp_options.max_occurences = 10;
|
||||||
dsp_options.debug_plots = false;
|
dsp_options.debug_plots = true;
|
||||||
|
|
||||||
dsp_options.database_type = "mysql";
|
dsp_options.database_type = "mysql";
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user