Many changes here and there. I lost track... :-(
Current work is on MLSE and SD Decoding etc. MLSE is currently not 100% working, the scalings are maybe off?!
This commit is contained in:
@@ -269,6 +269,7 @@ classdef Signal
|
|||||||
SignalPower = [obj.power];
|
SignalPower = [obj.power];
|
||||||
Nase = [0];
|
Nase = [0];
|
||||||
SignalCopy = obj.signal;
|
SignalCopy = obj.signal;
|
||||||
|
SignalCopy = [];
|
||||||
ModifierName = class(CallingModifier);
|
ModifierName = class(CallingModifier);
|
||||||
|
|
||||||
|
|
||||||
@@ -365,7 +366,7 @@ classdef Signal
|
|||||||
if options.normalizeTo0dB
|
if options.normalizeTo0dB
|
||||||
p_lin = p_lin./ max(p_lin);
|
p_lin = p_lin./ max(p_lin);
|
||||||
p_dbm = 10*log10(p_lin); % normalized to 0 dB
|
p_dbm = 10*log10(p_lin); % normalized to 0 dB
|
||||||
ylab = "normalized to 0 dB";
|
ylab = "Normalized PSD";
|
||||||
else
|
else
|
||||||
p_dbm = 10*log10(p_lin);
|
p_dbm = 10*log10(p_lin);
|
||||||
ylab = "Power (dB/Hz)";
|
ylab = "Power (dB/Hz)";
|
||||||
@@ -395,7 +396,7 @@ classdef Signal
|
|||||||
if options.normalizeToNyquist == 0
|
if options.normalizeToNyquist == 0
|
||||||
xlabel("Frequency in GHz");
|
xlabel("Frequency in GHz");
|
||||||
edgetick = 2^(nextpow2(obj.fs*1e-9));
|
edgetick = 2^(nextpow2(obj.fs*1e-9));
|
||||||
xticks(-edgetick:16:edgetick);
|
xticks(-edgetick:32:edgetick);
|
||||||
xlim([100*round(min(w)/100,1)-10, 100*round(max(w)/100,1)+10])
|
xlim([100*round(min(w)/100,1)-10, 100*round(max(w)/100,1)+10])
|
||||||
xlim([-128 128]);%256GSa/s
|
xlim([-128 128]);%256GSa/s
|
||||||
else
|
else
|
||||||
@@ -406,13 +407,20 @@ classdef Signal
|
|||||||
ylabel(ylab);
|
ylabel(ylab);
|
||||||
|
|
||||||
try
|
try
|
||||||
ylim([max(min(floor(min(p_dbm))-3, ax.YLim(1)),-40), min(max(ceil(max(p_dbm))+3, ax.YLim(2)),10)]);
|
ylim([max(min(floor(min(p_dbm))-3, ax.YLim(1)),-40), min(max(ceil(max(p_dbm))+3, ax.YLim(2)),10)]);
|
||||||
catch
|
catch
|
||||||
ylim([floor(min(p_dbm))-3, ceil(max(p_dbm))+3]);
|
ylim([floor(min(p_dbm))-3, ceil(max(p_dbm))+3]);
|
||||||
end
|
end
|
||||||
ylim([floor(min(p_dbm))-3, ceil(max(p_dbm))+3]);
|
|
||||||
|
if options.normalizeTo0dB
|
||||||
|
% ylim([-40, 3]);
|
||||||
|
ylim([floor(min(p_dbm))-3, ceil(max(p_dbm))+3]);
|
||||||
|
else
|
||||||
|
ylim([floor(min(p_dbm))-3, ceil(max(p_dbm))+3]);
|
||||||
|
end
|
||||||
|
|
||||||
yticks(-200:10:10);
|
yticks(-200:10:10);
|
||||||
grid on; grid minor;
|
grid on;% grid minor;
|
||||||
legend
|
legend
|
||||||
% legend('Interpreter','none');
|
% legend('Interpreter','none');
|
||||||
|
|
||||||
@@ -912,8 +920,8 @@ classdef Signal
|
|||||||
elseif mode == 1
|
elseif mode == 1
|
||||||
% generate eye diagram using histogram
|
% generate eye diagram using histogram
|
||||||
|
|
||||||
maxA = max(sig(100:end-100))*2;
|
maxA = max(sig(100:end-100))*1.3;
|
||||||
minA = min(sig(100:end-100))*2;
|
minA = min(sig(100:end-100))*1.3;
|
||||||
|
|
||||||
% maxA = 0.0015;
|
% maxA = 0.0015;
|
||||||
% minA = 0;
|
% minA = 0;
|
||||||
@@ -927,7 +935,7 @@ classdef Signal
|
|||||||
hist_data(:,n)=flip(nn.'); %without flip, the eye is upside down :-(
|
hist_data(:,n)=flip(nn.'); %without flip, the eye is upside down :-(
|
||||||
end
|
end
|
||||||
|
|
||||||
ax = gca;
|
|
||||||
|
|
||||||
plot_data = 20*log10(hist_data);
|
plot_data = 20*log10(hist_data);
|
||||||
plot_data(plot_data==-Inf) = 0;
|
plot_data(plot_data==-Inf) = 0;
|
||||||
@@ -944,27 +952,29 @@ classdef Signal
|
|||||||
if isa(obj,'Opticalsignal')
|
if isa(obj,'Opticalsignal')
|
||||||
title(['Optical Eye ',options.displayname])
|
title(['Optical Eye ',options.displayname])
|
||||||
ylabel("Power in mW");
|
ylabel("Power in mW");
|
||||||
y_tickstring = string(linspace(maxA.*1e3,minA.*1e3,16));
|
y_tickstring = string(linspace(maxA.*1e3,minA.*1e3,6));
|
||||||
min_ = min(abs(obj.signal(100:end-100)).^2);
|
min_ = min(abs(obj.signal(100:end-100)).^2);
|
||||||
max_ = abs(max(obj.signal(100:end-100)).^2);
|
max_ = abs(max(obj.signal(100:end-100)).^2);
|
||||||
elseif isa(obj,'Electricalsignal')
|
elseif isa(obj,'Electricalsignal')
|
||||||
title(['Electrical Eye ',options.displayname])
|
title(['Electrical Eye ',options.displayname])
|
||||||
ylabel("Voltage in V");
|
ylabel("Voltage in V");
|
||||||
y_tickstring = string(linspace(maxA,minA,16));
|
y_tickstring = string(linspace(maxA,minA,6));
|
||||||
min_ = min(obj.signal(100:end-100));
|
min_ = min(obj.signal(100:end-100));
|
||||||
max_ = abs(max(obj.signal(100:end-100)));
|
max_ = abs(max(obj.signal(100:end-100)));
|
||||||
else
|
else
|
||||||
title(['Digital Eye ',options.displayname])
|
title(['Digital Eye ',options.displayname])
|
||||||
ylabel("Digital Signal Amplitude");
|
ylabel("Digital Signal Amplitude");
|
||||||
y_tickstring = string(linspace(maxA,minA,16));
|
y_tickstring = string(linspace(maxA,minA,6));
|
||||||
min_ = min(obj.signal(100:end-100));
|
min_ = min(obj.signal(100:end-100));
|
||||||
max_ = abs(max(obj.signal(100:end-100)));
|
max_ = abs(max(obj.signal(100:end-100)));
|
||||||
end
|
end
|
||||||
xlabel('Time in ps')
|
xlabel('Time in ps')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
% add information
|
% add information
|
||||||
|
|
||||||
if 0
|
if 1
|
||||||
|
|
||||||
pwr_dbm = round(obj.power,3);
|
pwr_dbm = round(obj.power,3);
|
||||||
pwr_lin = obj.power("unit",power_notation.W);
|
pwr_lin = obj.power("unit",power_notation.W);
|
||||||
@@ -1073,13 +1083,15 @@ classdef Signal
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
yticks(linspace(0,histpoints,16));
|
yticks(linspace(0,histpoints,6));
|
||||||
y_tickstring = sprintfc('%.2f', y_tickstring);
|
y_tickstring = sprintfc('%.2f', y_tickstring);
|
||||||
yticklabels(y_tickstring);
|
yticklabels(y_tickstring);
|
||||||
|
|
||||||
xticks(linspace(0,histpoints_horizontal,8))
|
xticks(linspace(0,histpoints_horizontal,6))
|
||||||
x_tickstring = sprintfc('%.2f', linspace(0, 2/fsym, 8) .* 1e12);
|
x_tickstring = sprintfc('%.2f', linspace(0, 2/fsym, 8) .* 1e12);
|
||||||
xticklabels(x_tickstring);
|
xticklabels(x_tickstring);
|
||||||
|
|
||||||
|
grid off
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ classdef M8199B < AWG
|
|||||||
|
|
||||||
fdac = 256e9;
|
fdac = 256e9;
|
||||||
|
|
||||||
Lp_awg = Filter('filtdegree',4,"f_cutoff",75e9,"fs",fdac*options.kover,"filterType",filtertypes.butterworth,"active",true);
|
Lp_awg = Filter('filtdegree',3,"f_cutoff",75e9,"fs",fdac*options.kover,"filterType",filtertypes.gaussian,"active",true);
|
||||||
|
|
||||||
obj = obj@AWG("fdac",fdac,"dac_min",dac_min,"dac_max",dac_max,"lpf_active",1,"H_lpf",Lp_awg,"kover",options.kover,...
|
obj = obj@AWG("fdac",fdac,"dac_min",dac_min,"dac_max",dac_max,"lpf_active",1,"H_lpf",Lp_awg,"kover",options.kover,...
|
||||||
"bit_resolution",5.5,"normalize2dac",1,"upsampling_method","samplehold");
|
"bit_resolution",5.5,"normalize2dac",1,"upsampling_method","samplehold");
|
||||||
|
|||||||
@@ -136,6 +136,13 @@ classdef PAMsource
|
|||||||
|
|
||||||
%%%%%% Duobinary %%%%%%%%%%%
|
%%%%%% Duobinary %%%%%%%%%%%
|
||||||
|
|
||||||
|
if obj.db_precode
|
||||||
|
obj.duobinary_mode = db_mode.db_precoded;
|
||||||
|
end
|
||||||
|
if obj.db_encode
|
||||||
|
obj.duobinary_mode = db_mode.db_encoded;
|
||||||
|
end
|
||||||
|
|
||||||
switch obj.duobinary_mode
|
switch obj.duobinary_mode
|
||||||
|
|
||||||
case db_mode.no_db
|
case db_mode.no_db
|
||||||
|
|||||||
@@ -1,189 +1,171 @@
|
|||||||
classdef Fiber
|
classdef Fiber
|
||||||
%FIBER Summary of this class goes here
|
% Fiber: Simulate optical fiber signal propagation using
|
||||||
% Detailed explanation goes here
|
% the split-step Fourier method (SSFM).
|
||||||
|
|
||||||
properties
|
properties
|
||||||
|
% Simulation sampling frequency [Hz]
|
||||||
fsimu
|
fsimu
|
||||||
|
% Fiber length [m]
|
||||||
fiber_length
|
fiber_length
|
||||||
|
% Attenuation coefficient [dB/km]
|
||||||
alpha
|
alpha
|
||||||
|
% Dispersion parameter D [s/m^2]
|
||||||
D
|
D
|
||||||
|
% Dispersion slope [s/m^3]
|
||||||
Dslope
|
Dslope
|
||||||
|
% Reference wavelength [m]
|
||||||
lambda0
|
lambda0
|
||||||
|
% Nonlinear coefficient [1/(W·m)]
|
||||||
gamma
|
gamma
|
||||||
|
% Maximum allowed nonlinear phase change per step [rad]
|
||||||
dphimax
|
dphimax
|
||||||
|
|
||||||
|
% Derived parameters:
|
||||||
|
% Second-order dispersion coefficient β2 [s^2/m]
|
||||||
b2
|
b2
|
||||||
|
% Third-order dispersion coefficient β3 [s^3/m]
|
||||||
b3
|
b3
|
||||||
|
% Linear attenuation constant [1/m]
|
||||||
alpha_lin
|
alpha_lin
|
||||||
|
% Frequency-domain linear operator per unit length
|
||||||
linstep
|
linstep
|
||||||
end
|
end
|
||||||
|
|
||||||
methods
|
methods
|
||||||
function obj = Fiber(options)
|
function obj = Fiber(options)
|
||||||
%FIBER Construct an instance of this class
|
% Constructor: initialize fiber physical and simulation parameters.
|
||||||
% Detailed explanation goes here
|
|
||||||
arguments
|
arguments
|
||||||
options.fsimu
|
options.fsimu % Sampling frequency [Hz]
|
||||||
options.fiber_length = 0
|
options.fiber_length = 0 % Fiber length [km]
|
||||||
options.alpha = 0.2
|
options.alpha = 0.2 % Attenuation [dB/km]
|
||||||
options.D = 17
|
options.D = 17 % Dispersion D parameter [ps/(nm·km)]
|
||||||
options.Dslope = 0.06
|
options.Dslope = 0.06 % Dispersion slope [ps/(nm^2·km)]
|
||||||
options.lambda0 = 1550
|
options.lambda0 = 1550 % Reference wavelength [nm]
|
||||||
options.gamma = 0
|
options.gamma = 0 % Nonlinear coefficient [1/(W·km)]
|
||||||
options.dphimax = 5e-3
|
options.dphimax = 5e-3 % Max phase step [rad]
|
||||||
end
|
end
|
||||||
|
|
||||||
obj.fsimu = options.fsimu;
|
% Assign inputs to object properties, converting units to SI.
|
||||||
obj.fiber_length = options.fiber_length*1000; %km
|
obj.fsimu = options.fsimu;
|
||||||
obj.alpha = options.alpha;
|
obj.fiber_length = options.fiber_length * 1e3; % km → m
|
||||||
obj.D = options.D*1e-6;
|
obj.alpha = options.alpha;
|
||||||
obj.Dslope = options.Dslope*1e3;
|
obj.D = options.D * 1e-6; % ps/(nm·km) → s/(m·m)
|
||||||
obj.lambda0 = options.lambda0*1e-9;
|
obj.Dslope = options.Dslope * 1e3; % ps/(nm^2·km) → s/m^2
|
||||||
obj.gamma = options.gamma;
|
obj.lambda0 = options.lambda0 * 1e-9; % nm → m
|
||||||
obj.dphimax = options.dphimax;
|
obj.gamma = options.gamma; % 1/(W·km) (assumed → 1/(W·m) internally)
|
||||||
|
obj.dphimax = options.dphimax;
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function signalclass_out = process(obj,signalclass_in)
|
function signalclass_out = process(obj, signalclass_in)
|
||||||
|
% process: Apply fiber propagation to input signal class.
|
||||||
|
% Calls the internal SSFM routine and logs the operation.
|
||||||
|
|
||||||
% actual processing of the signal (steps 1. - 3.)
|
% Run internal split-step propagation
|
||||||
signalclass_in = obj.process_(signalclass_in);
|
signalclass = obj.process_(signalclass_in);
|
||||||
|
|
||||||
% append to logbook
|
% Add entry to logbook for tracking
|
||||||
lbdesc = 'Fiber ';
|
signalclass = signalclass.logbookentry('Fiber ');
|
||||||
signalclass_in = signalclass_in.logbookentry(lbdesc);
|
|
||||||
|
|
||||||
% write to output
|
|
||||||
signalclass_out = signalclass_in;
|
|
||||||
|
|
||||||
|
% Return processed signal class
|
||||||
|
signalclass_out = signalclass;
|
||||||
end
|
end
|
||||||
|
|
||||||
function opt_sig = process_(obj,opt_sig)
|
function opt_sig = process_(obj, opt_sig)
|
||||||
%METHOD1 Summary of this method goes here
|
% process_: Internal routine for one-step fiber propagation.
|
||||||
% Detailed explanation goes here
|
% Computes linear and (optionally) nonlinear effects.
|
||||||
|
|
||||||
signal = opt_sig.signal;
|
% Extract time-domain field and wavelength
|
||||||
|
signal = opt_sig.signal;
|
||||||
lambda_signal = opt_sig.lambda;
|
lambda_signal = opt_sig.lambda;
|
||||||
|
|
||||||
obj.D = obj.D + (lambda_signal-obj.lambda0)*obj.Dslope;
|
% Update dispersion parameter D for current wavelength
|
||||||
|
obj.D = obj.D + (lambda_signal - obj.lambda0) * obj.Dslope;
|
||||||
|
|
||||||
obj.b2 = -obj.D*lambda_signal^2/(2*pi*Constant.LightSpeed);
|
% Compute dispersion coefficients (β2, β3)
|
||||||
obj.b3 = ((lambda_signal.^2/(2*pi*Constant.LightSpeed)).^2*obj.Dslope);
|
obj.b2 = -obj.D * lambda_signal^2 / (2 * pi * Constant.LightSpeed);
|
||||||
obj.alpha_lin = obj.alpha/10*log(10)/1000;
|
obj.b3 = (lambda_signal^2 / (2 * pi * Constant.LightSpeed))^2 * obj.Dslope;
|
||||||
|
|
||||||
|
% Convert attenuation from dB/km to linear 1/m
|
||||||
|
obj.alpha_lin = obj.alpha / 10 * log(10) / 1e3;
|
||||||
|
|
||||||
|
% Build frequency axis for FFT operations
|
||||||
N = length(signal);
|
N = length(signal);
|
||||||
faxis = linspace(-obj.fsimu/2,obj.fsimu/2,N+1);
|
faxis = linspace(-obj.fsimu/2, obj.fsimu/2, N+1);
|
||||||
faxis = ifftshift(faxis(:,1:end-1));
|
faxis = faxis(1:end-1); % drop redundant endpoint
|
||||||
faxis = faxis';
|
faxis = ifftshift(faxis)'; % center zero frequency
|
||||||
|
|
||||||
obj.linstep = -obj.alpha_lin/2 - 2*1j*pi^2*obj.b2*faxis.^2 - 4/3*1j*pi^3*obj.b3*faxis.^3;
|
% Define linear operator per meter in frequency domain
|
||||||
|
obj.linstep = -obj.alpha_lin/2 ... % half-step loss
|
||||||
if 0
|
- 1j*2*pi^2*obj.b2 .* faxis.^2 ... % second-order dispersion
|
||||||
H = exp((obj.linstep)*obj.fiber_length);
|
- 1j*(4/3)*pi^3*obj.b3 .* faxis.^3; % third-order dispersion
|
||||||
|
|
||||||
figure(222)
|
|
||||||
hold on
|
|
||||||
plot(faxis.*1e-9,abs(real(Y)),'LineStyle','-','DisplayName','Abs(real) part of complex TF');
|
|
||||||
xlabel("Frequency in GHz")
|
|
||||||
ylabel("$ R|(H(\omega, L))|$")
|
|
||||||
end
|
|
||||||
|
|
||||||
|
% Choose linear-only or nonlinear SSFM based on gamma
|
||||||
if obj.gamma ~= 0
|
if obj.gamma ~= 0
|
||||||
|
% Full adaptive SSFM with nonlinear Schrödinger solver
|
||||||
opt_out = obj.NLSE(signal);
|
opt_out = obj.NLSE(signal);
|
||||||
else
|
else
|
||||||
opt_out = ifft( fft(signal) .* exp(obj.linstep*obj.fiber_length) ); % only one linear step
|
% Single-step linear propagation in frequency domain
|
||||||
|
opt_out = ifft( fft(signal) .* exp(obj.linstep * obj.fiber_length) );
|
||||||
end
|
end
|
||||||
|
|
||||||
%TODO: attenuate nase ...
|
% Update output field in signal class
|
||||||
|
|
||||||
opt_sig.signal = opt_out;
|
opt_sig.signal = opt_out;
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function [yout] = NLSE(obj, xin)
|
function yout = NLSE(obj, xin)
|
||||||
|
% NLSE: Solve nonlinear Schrödinger equation by adaptive split-step
|
||||||
maxPow = obj.gamma.*max(abs(xin).^2);
|
% xin: input time-domain field
|
||||||
|
% Returns yout: output time-domain field after propagation
|
||||||
Leff = obj.dphimax / maxPow ;
|
|
||||||
|
|
||||||
dz = Leff;
|
|
||||||
|
|
||||||
|
% Initial estimate of effective length per step
|
||||||
|
maxPow = obj.gamma * max(abs(xin).^2);
|
||||||
|
Leff = obj.dphimax / maxPow;
|
||||||
|
dz = Leff;
|
||||||
z_prop = 0;
|
z_prop = 0;
|
||||||
|
|
||||||
yout = fft(xin);
|
% Apply initial half-step linear operator
|
||||||
|
yout = fft(xin) .* exp(obj.linstep * dz/2);
|
||||||
yout = ((yout).*exp(obj.linstep*dz/2));
|
|
||||||
|
|
||||||
|
% Loop until full fiber length is reached
|
||||||
while true
|
while true
|
||||||
|
% Inverse FFT to time domain for nonlinear phase shift
|
||||||
yout = ifft(yout);
|
yout = ifft(yout);
|
||||||
|
|
||||||
Leff = dz;
|
% Nonlinear phase rotation per segment
|
||||||
|
|
||||||
power = abs(yout).^2;
|
power = abs(yout).^2;
|
||||||
Hnl = exp( -1j*obj.gamma*power*Leff);
|
Hnl = exp(-1j * obj.gamma * power * dz);
|
||||||
yout = yout .* Hnl;
|
yout = yout .* Hnl;
|
||||||
|
|
||||||
|
% Accumulate propagation distance
|
||||||
z_prop = z_prop + dz;
|
z_prop = z_prop + dz;
|
||||||
|
|
||||||
maxPow = obj.gamma*max(abs(yout).^2);
|
% Compute adaptive step for next interval
|
||||||
Leff = obj.dphimax/maxPow;
|
maxPow = obj.gamma * max(abs(yout).^2);
|
||||||
|
dz_new = obj.dphimax / maxPow;
|
||||||
dz_new = Leff;
|
|
||||||
|
|
||||||
|
% If remaining length shorter than new step, finish loop
|
||||||
if z_prop + dz_new > obj.fiber_length
|
if z_prop + dz_new > obj.fiber_length
|
||||||
dz_new = obj.fiber_length - z_prop;
|
dz_new = obj.fiber_length - z_prop;
|
||||||
break
|
break;
|
||||||
end
|
end
|
||||||
|
|
||||||
yout = fft(yout);
|
% Half-step linear operator bridging segments
|
||||||
|
yout = fft(yout) .* exp(obj.linstep * ((dz/2) + (dz_new/2)));
|
||||||
yout = ((yout).*exp(obj.linstep*(dz/2+dz_new/2)));
|
dz = dz_new;
|
||||||
|
|
||||||
dz = dz_new;
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
yout = fft(yout);
|
% Final propagation segment: combine half-steps and nonlinear
|
||||||
|
yout = fft(yout) .* exp(obj.linstep * ((dz/2) + (dz_new/2)));
|
||||||
yout = ((yout).*exp(obj.linstep*(dz/2+dz_new/2)));
|
|
||||||
|
|
||||||
yout = ifft(yout);
|
yout = ifft(yout);
|
||||||
|
|
||||||
Leff = dz;
|
% Last nonlinear phase shift
|
||||||
|
|
||||||
power = abs(yout).^2;
|
power = abs(yout).^2;
|
||||||
|
Hnl = exp(-1j * obj.gamma * power * dz_new);
|
||||||
|
yout = yout .* Hnl;
|
||||||
|
|
||||||
Hnl = exp( -1j*obj.gamma*power*Leff);
|
% Final half-step linear operator to complete SSFM
|
||||||
|
yout = fft(yout) .* exp(obj.linstep * (dz_new/2));
|
||||||
yout = yout .* Hnl;
|
|
||||||
|
|
||||||
yout = fft(yout);
|
|
||||||
|
|
||||||
yout = ((yout).*exp(obj.linstep*(dz/2)));
|
|
||||||
|
|
||||||
yout = ifft(yout);
|
yout = ifft(yout);
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -83,6 +83,14 @@ classdef MLSE < handle
|
|||||||
% impulse respnse to remove from signal
|
% impulse respnse to remove from signal
|
||||||
obj.DIR = flip(obj.DIR); %i.e. -0.2676 -0.0478 1.0000
|
obj.DIR = flip(obj.DIR); %i.e. -0.2676 -0.0478 1.0000
|
||||||
|
|
||||||
|
% % make the combined impulse-response have net gain = 1
|
||||||
|
% h = obj.DIR(:);
|
||||||
|
% h = h / sum(h);
|
||||||
|
% obj.DIR = h.';
|
||||||
|
|
||||||
|
% Normalize the Trellis states to =1 RMS
|
||||||
|
obj.trellis_states = obj.trellis_states ./ rms(obj.trellis_states);
|
||||||
|
|
||||||
% seems to be the only way to use combvec for a flexible amount
|
% seems to be the only way to use combvec for a flexible amount
|
||||||
% of vectors. 'combs' contains all trellis states
|
% of vectors. 'combs' contains all trellis states
|
||||||
pre_comb_mat = repmat(obj.trellis_states,length(obj.DIR)-1,1);
|
pre_comb_mat = repmat(obj.trellis_states,length(obj.DIR)-1,1);
|
||||||
@@ -116,6 +124,7 @@ classdef MLSE < handle
|
|||||||
|
|
||||||
% first: RMS normalization of input data (rms==1)
|
% first: RMS normalization of input data (rms==1)
|
||||||
data_in = data_in ./ rms(data_in);
|
data_in = data_in ./ rms(data_in);
|
||||||
|
data_in = data_in - mean(data_in);
|
||||||
|
|
||||||
% then, match amplitude levels of input signal to those of the calculated ideal symbols
|
% then, match amplitude levels of input signal to those of the calculated ideal symbols
|
||||||
% i.e. match the rms values of data_in to noise_free_received (rms=1.xx)
|
% i.e. match the rms values of data_in to noise_free_received (rms=1.xx)
|
||||||
@@ -125,6 +134,10 @@ classdef MLSE < handle
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
y_clean = conv( data_ref, flip(obj.DIR), "same" );
|
||||||
|
sigma2 = var( data_in - y_clean );
|
||||||
|
inv2s2 = 1/(2*sigma2);
|
||||||
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
%%%%% FORWARD PASS (VITERBI -Alpha's) %%%%%
|
%%%%% FORWARD PASS (VITERBI -Alpha's) %%%%%
|
||||||
|
|
||||||
@@ -134,7 +147,7 @@ classdef MLSE < handle
|
|||||||
|
|
||||||
% first start is evaluated without ISI/ wihout the full Impulse response
|
% first start is evaluated without ISI/ wihout the full Impulse response
|
||||||
% so simply use the constellation here
|
% so simply use the constellation here
|
||||||
bm = -(data_in(1) - last_sym).^2 ;
|
bm = -(data_in(1) - last_sym).^2 * inv2s2;
|
||||||
pm = pm + bm;
|
pm = pm + bm;
|
||||||
[alpha(:,1),pm_survivor_fw_idx(:,1)] = max(pm,[],2);
|
[alpha(:,1),pm_survivor_fw_idx(:,1)] = max(pm,[],2);
|
||||||
pm = repmat(alpha(:,1).',nStates,1);
|
pm = repmat(alpha(:,1).',nStates,1);
|
||||||
@@ -143,10 +156,10 @@ classdef MLSE < handle
|
|||||||
% Forward Recursion (FSM Computation)
|
% Forward Recursion (FSM Computation)
|
||||||
for n = 2:length(data_in)
|
for n = 2:length(data_in)
|
||||||
|
|
||||||
bm = -(data_in(n) - noise_free_received).^2 ;
|
bm = -(data_in(n) - noise_free_received).^2 * inv2s2;
|
||||||
pm = pm + bm;
|
pm = pm + bm;
|
||||||
[alpha(:,n),pm_survivor_fw_idx(:,n)] = max(pm,[],2); % choose lowest path metric as new state
|
[alpha(:,n),pm_survivor_fw_idx(:,n)] = max(pm,[],2); % choose lowest path metric as new state
|
||||||
pm = repmat(alpha(:,n).',nStates,1); % update pm (chosen state to 2nd dimension -> FROM state)
|
pm = repmat(alpha(:,n).',nStates,1); % update pm (chosen state to 2nd dimension -> FROM state)
|
||||||
|
|
||||||
bm_fw(:,:,n) = bm;
|
bm_fw(:,:,n) = bm;
|
||||||
|
|
||||||
@@ -177,7 +190,7 @@ classdef MLSE < handle
|
|||||||
% predecessor
|
% predecessor
|
||||||
for h = length(data_in)-1:-1:1
|
for h = length(data_in)-1:-1:1
|
||||||
|
|
||||||
bm = -(data_in(h+1) - noise_free_received).^2 ;
|
bm = -(data_in(h+1) - noise_free_received).^2 * inv2s2;
|
||||||
pm = pm + bm.';
|
pm = pm + bm.';
|
||||||
[beta(:,h),pm_survivor_bw_idx(:,h)] = max(pm,[],2); % choose lowest path metric as new state
|
[beta(:,h),pm_survivor_bw_idx(:,h)] = max(pm,[],2); % choose lowest path metric as new state
|
||||||
pm = repmat(beta(:,h).',nStates,1); % update pm (chosen state to 2nd dimension -> FROM state)
|
pm = repmat(beta(:,h).',nStates,1); % update pm (chosen state to 2nd dimension -> FROM state)
|
||||||
@@ -214,10 +227,22 @@ classdef MLSE < handle
|
|||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
%%%%% FORWARD PASS PAM2,4,8 %%%%%
|
%%%%% FORWARD PASS PAM2,4,8 %%%%%
|
||||||
|
|
||||||
nml_LLP = LLP - max(LLP);
|
nml_LLP = LLP - max(LLP); %subtract highest value for better numerical stability, LLP's are not always close to zero
|
||||||
expLLP = exp(nml_LLP); %subtract highst value for better numerical stability, LLP's are not always close to zero
|
expLLP = exp(nml_LLP);
|
||||||
state_prob = expLLP ./ sum(expLLP);
|
state_prob = expLLP ./ sum(expLLP); % sums to one (or numerically close to one)
|
||||||
|
|
||||||
|
% compute symbol‐posteriors from LLP in the log‐domain:
|
||||||
|
amax = max(LLP,[],1);
|
||||||
|
logZ = amax + log(sum(exp(LLP - amax), 1));
|
||||||
|
logPstate = LLP - logZ; % still in log‐domain
|
||||||
|
state_prob = exp(logPstate); % exact, sums to 1
|
||||||
|
|
||||||
|
% figure
|
||||||
|
% hold on;
|
||||||
|
% for i = 1:obj.M
|
||||||
|
% scatter(1:length(expLLP),expLLP(i,:),1,'.');
|
||||||
|
% end
|
||||||
|
% scatter(1:length(expLLP),max(expLLP(:,:)),3,'.');
|
||||||
|
|
||||||
if obj.M == 6
|
if obj.M == 6
|
||||||
|
|
||||||
@@ -305,8 +330,8 @@ classdef MLSE < handle
|
|||||||
|
|
||||||
% Number of symbols and bits per symbol
|
% Number of symbols and bits per symbol
|
||||||
num_bits = log2(length(obj.trellis_states)); % 2 bits per symbol
|
num_bits = log2(length(obj.trellis_states)); % 2 bits per symbol
|
||||||
bit_mapping = PAMmapper(length(obj.trellis_states),0,"eth_style",0).demap(first_sym./rms(first_sym));
|
% bit_mapping = PAMmapper(length(obj.trellis_states),0,"eth_style",0).demap(first_sym./rms(first_sym));
|
||||||
|
bit_mapping = PAMmapper(length(obj.trellis_states),0,"eth_style",0).showBitMapping;
|
||||||
% Initialize LLR storage
|
% Initialize LLR storage
|
||||||
LLR_maxlogmap = zeros(length(data_in),num_bits);
|
LLR_maxlogmap = zeros(length(data_in),num_bits);
|
||||||
LLR_exact = zeros(length(data_in),num_bits);
|
LLR_exact = zeros(length(data_in),num_bits);
|
||||||
@@ -343,8 +368,8 @@ classdef MLSE < handle
|
|||||||
llr1 = LLR_exact(idx_bit_0,k);
|
llr1 = LLR_exact(idx_bit_0,k);
|
||||||
|
|
||||||
% Calculate mutual information for bit position k
|
% Calculate mutual information for bit position k
|
||||||
I0 = mean(log2(1 + exp(llr0(100:end-100)))); % exp(--LLR) = exp(positive) > 1
|
I0 = mean(log2(1 + exp(llr0))); % exp(--LLR) = exp(positive) > 1
|
||||||
I1 = mean(log2(1 + exp(-llr1(100:end-100)))); % exp(-+LLR) = exp(negative) < 1
|
I1 = mean(log2(1 + exp(-llr1))); % exp(-+LLR) = exp(negative) < 1
|
||||||
MI(k) = 1 - 0.5 * (I0 + I1);
|
MI(k) = 1 - 0.5 * (I0 + I1);
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -354,8 +379,7 @@ classdef MLSE < handle
|
|||||||
|
|
||||||
VITERBI_ESTIMATION_SYMBOLS = VITERBI_ESTIMATION_SYMBOLS./rms(VITERBI_ESTIMATION_SYMBOLS);
|
VITERBI_ESTIMATION_SYMBOLS = VITERBI_ESTIMATION_SYMBOLS./rms(VITERBI_ESTIMATION_SYMBOLS);
|
||||||
|
|
||||||
|
debug = 1;
|
||||||
debug = 0;
|
|
||||||
if debug
|
if debug
|
||||||
%%% DEBUG PLOT LIKELIHOOD RATIOS %%%
|
%%% DEBUG PLOT LIKELIHOOD RATIOS %%%
|
||||||
figure(115);clf
|
figure(115);clf
|
||||||
@@ -380,6 +404,7 @@ classdef MLSE < handle
|
|||||||
if debug
|
if debug
|
||||||
tx_bits = reshape(tx_bits',[],1);
|
tx_bits = reshape(tx_bits',[],1);
|
||||||
|
|
||||||
|
disp('Start DEBUG MLSE:')
|
||||||
% DECIDE based on Viterbi traceback
|
% DECIDE based on Viterbi traceback
|
||||||
VITERBI_ESTIMATION_SYMBOLS = VITERBI_ESTIMATION_SYMBOLS./rms(VITERBI_ESTIMATION_SYMBOLS);
|
VITERBI_ESTIMATION_SYMBOLS = VITERBI_ESTIMATION_SYMBOLS./rms(VITERBI_ESTIMATION_SYMBOLS);
|
||||||
rx_bits = PAMmapper(obj.M,0,"eth_style",0).demap(VITERBI_ESTIMATION_SYMBOLS');
|
rx_bits = PAMmapper(obj.M,0,"eth_style",0).demap(VITERBI_ESTIMATION_SYMBOLS');
|
||||||
@@ -417,13 +442,19 @@ classdef MLSE < handle
|
|||||||
rx_bits = reshape(rx_bits',[],1);
|
rx_bits = reshape(rx_bits',[],1);
|
||||||
[~,~,ber_fw,~] = calc_ber(rx_bits,tx_bits,"skip_front",100,"skip_end",150,"returnErrorLocation",1);
|
[~,~,ber_fw,~] = calc_ber(rx_bits,tx_bits,"skip_front",100,"skip_end",150,"returnErrorLocation",1);
|
||||||
fprintf('FW BER: %.2e \n',ber_fw);
|
fprintf('FW BER: %.2e \n',ber_fw);
|
||||||
|
disp('Stop DEBUG MLSE:')
|
||||||
|
disp('')
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
methods (Access=private)
|
function s = logsumexp(a,dim)
|
||||||
|
% returns log(sum(exp(a),dim)) safely
|
||||||
|
amax = max(a,[],dim);
|
||||||
|
s = amax + log(sum(exp(a - amax), dim));
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
152
Classes/04_DSP/Sequence Detection/MLSE_new.m
Normal file
152
Classes/04_DSP/Sequence Detection/MLSE_new.m
Normal file
@@ -0,0 +1,152 @@
|
|||||||
|
classdef MLSE_new < handle
|
||||||
|
%MLSE: BCJR‐based soft‐output for PAM‐M sequence estimation & GMI
|
||||||
|
|
||||||
|
properties
|
||||||
|
M % PAM order (e.g. 4)
|
||||||
|
DIR % channel impulse response
|
||||||
|
trellis_states % PAM constellation levels (e.g. [-3 -1 1 3])
|
||||||
|
end
|
||||||
|
|
||||||
|
methods
|
||||||
|
function obj = MLSE_new(opts)
|
||||||
|
arguments
|
||||||
|
opts.M double = 4;
|
||||||
|
opts.DIR double = 1;
|
||||||
|
opts.trellis_states double = [-3 -1 1 3];
|
||||||
|
end
|
||||||
|
obj.M = opts.M;
|
||||||
|
obj.DIR = opts.DIR;
|
||||||
|
obj.trellis_states = opts.trellis_states;
|
||||||
|
end
|
||||||
|
|
||||||
|
function [hd_out, LLR, NGMI] = process(obj, signalclass,ref_symbolclass)
|
||||||
|
% rx, tx: column vectors of equalized and reference symbols
|
||||||
|
data_in = signalclass.signal;
|
||||||
|
shape_in = size(data_in);
|
||||||
|
data_ref = ref_symbolclass.signal;
|
||||||
|
|
||||||
|
[data_out_hd,LLR,GMI] = obj.bcjr_soft(data_in,data_ref);
|
||||||
|
try
|
||||||
|
data_out_hd = reshape(data_out_hd,shape_in(1),shape_in(2));
|
||||||
|
catch
|
||||||
|
warning('output reshaping failed after MLSE');
|
||||||
|
end
|
||||||
|
|
||||||
|
signalclass_hd = signalclass;
|
||||||
|
signalclass_hd.signal = data_out_hd;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[hd_out, LLR, NGMI] = obj.bcjr_soft(rx, tx);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
methods (Access=private)
|
||||||
|
function [hd_sym, LLR, NGMI] = bcjr_soft(obj, y, x)
|
||||||
|
%--- build trellis states & branch outputs ---
|
||||||
|
DIR = flip(obj.DIR(:));
|
||||||
|
S = combvec(obj.trellis_states, obj.trellis_states)';
|
||||||
|
prev = S(:,1); cur = S(:,2);
|
||||||
|
branch_out = prev*DIR(1) + cur*DIR(2); % for 2‐tap
|
||||||
|
|
||||||
|
N = numel(y);
|
||||||
|
M = obj.M;
|
||||||
|
m = log2(M);
|
||||||
|
|
||||||
|
%--- forward/backward metrics (max‐log) ---
|
||||||
|
nStates = numel(obj.trellis_states);
|
||||||
|
alpha = -inf(nStates,N);
|
||||||
|
beta = -inf(nStates,N);
|
||||||
|
bm_fw = zeros(nStates,nStates,N);
|
||||||
|
|
||||||
|
% branch metrics
|
||||||
|
sigma2 = var(y - x);
|
||||||
|
inv2sigma2 = 1/(2*sigma2);
|
||||||
|
for n=1:N
|
||||||
|
bm = -((y(n)-branch_out).^2)* inv2sigma2;
|
||||||
|
bm = reshape(bm, nStates, nStates);
|
||||||
|
bm_fw(:,:,n) = bm;
|
||||||
|
end
|
||||||
|
% forward
|
||||||
|
alpha(:,1) = max(bm_fw(:,:,1),[],2);
|
||||||
|
for n=2:N
|
||||||
|
mat = alpha(:,n-1) + bm_fw(:,:,n);
|
||||||
|
alpha(:,n) = max(mat,[],2);
|
||||||
|
end
|
||||||
|
% backward
|
||||||
|
beta(:,N) = 0;
|
||||||
|
for n=N-1:-1:1
|
||||||
|
mat = beta(:,n+1).' + bm_fw(:,:,n+1);
|
||||||
|
beta(:,n) = max(mat,[],2);
|
||||||
|
end
|
||||||
|
|
||||||
|
% Precompute the “zero‐th” forward metric
|
||||||
|
alpha0 = zeros(nStates,1);
|
||||||
|
|
||||||
|
LLP = -inf(nStates,nStates,N);
|
||||||
|
for n = 1:N
|
||||||
|
% Select the correct previous alpha column
|
||||||
|
if n == 1
|
||||||
|
a_prev = alpha0;
|
||||||
|
else
|
||||||
|
a_prev = alpha(:,n-1);
|
||||||
|
end
|
||||||
|
|
||||||
|
% Combine α, branch metric, and β
|
||||||
|
mat = a_prev + bm_fw(:,:,n) + beta(:,n).';
|
||||||
|
LLP(:,:,n) = mat;
|
||||||
|
end
|
||||||
|
|
||||||
|
%--- compute LLRs symbol‐wise via log‐sum‐exp over branches ---
|
||||||
|
levels = obj.trellis_states;
|
||||||
|
bit_map = PAMmapper(M,0).demap(levels');
|
||||||
|
LLR = zeros(N,m);
|
||||||
|
for n=1:N
|
||||||
|
% sum branch posteriors per symbol
|
||||||
|
llp_n = LLP(:,:,n);
|
||||||
|
logZ = logsumexp(llp_n(:));
|
||||||
|
post = exp(llp_n - logZ);
|
||||||
|
% aggregate per symbol index
|
||||||
|
Psym = zeros(M,1);
|
||||||
|
for i=1:nStates
|
||||||
|
for j=1:nStates
|
||||||
|
% branch (i->j) emits symbol 'cur(j)'
|
||||||
|
idx = find(levels==cur(j));
|
||||||
|
Psym(idx) = Psym(idx) + post(i,j);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
% bit‐LLR from symbol posterior
|
||||||
|
for k=1:m
|
||||||
|
idx1 = bit_map(:,k)==1;
|
||||||
|
idx0 = ~idx1;
|
||||||
|
P1 = sum(Psym(idx1));
|
||||||
|
P0 = sum(Psym(idx0));
|
||||||
|
LLR(n,k) = log(P1/P0);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
%--- hard decisions ---
|
||||||
|
[~,symIdx] = max(LLR,[],2);
|
||||||
|
hd_sym = levels(symIdx);
|
||||||
|
|
||||||
|
%--- GMI via Alvarado Eq.(30) ---
|
||||||
|
tx_bits = PAMmapper(M,0).demap(x);
|
||||||
|
MI = zeros(1,m);
|
||||||
|
for k=1:m
|
||||||
|
r0 = LLR(tx_bits(:,k)==0,k);
|
||||||
|
r1 = LLR(tx_bits(:,k)==1,k);
|
||||||
|
I0 = mean(log2(1+exp(-r0)));
|
||||||
|
I1 = mean(log2(1+exp(+r1)));
|
||||||
|
MI(k) = 1 - 0.5*(I0+I1);
|
||||||
|
end
|
||||||
|
GMI = sum(MI);
|
||||||
|
NGMI = GMI/m;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function s = logsumexp(a)
|
||||||
|
m = max(a(:));
|
||||||
|
s = m + log(sum(exp(a-m), 'all'));
|
||||||
|
end
|
||||||
@@ -44,8 +44,6 @@ classdef DBHandler < handle
|
|||||||
|
|
||||||
% datasource = "jdbc:mysql://134.245.243.254:3306/labor";
|
% datasource = "jdbc:mysql://134.245.243.254:3306/labor";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
obj.conn = database( ...
|
obj.conn = database( ...
|
||||||
string(obj.dataBase), ... % Database name
|
string(obj.dataBase), ... % Database name
|
||||||
"silas", ... % Username
|
"silas", ... % Username
|
||||||
@@ -645,7 +643,7 @@ classdef DBHandler < handle
|
|||||||
cleanedTable.(varNames{i}) = numCol;
|
cleanedTable.(varNames{i}) = numCol;
|
||||||
else
|
else
|
||||||
% Clean double-quoted SQL literals (e.g., ""no_db"")
|
% Clean double-quoted SQL literals (e.g., ""no_db"")
|
||||||
cleanedTable.(varNames{i}) = strrep(string(col), '""', '"');
|
cleanedTable.(varNames{i}) = strrep(string(col), '"', '');
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -26,13 +26,15 @@ try
|
|||||||
% Initialize database connection
|
% Initialize database connection
|
||||||
database = DBHandler("dataBase", [options.dataBase], "type", options.database_type );
|
database = DBHandler("dataBase", [options.dataBase], "type", options.database_type );
|
||||||
|
|
||||||
% 2. Check if an equalizer configuration with the same hash exists
|
if 0
|
||||||
queryStr = sprintf('SELECT COUNT(DISTINCT eq_id) AS unique_eq_count, COUNT(*) AS entries_for_run FROM `Results` WHERE run_id = %d', run_id);
|
% 2. Check if an equalizer configuration with the same hash exists
|
||||||
existing_results = database.fetch(queryStr);
|
queryStr = sprintf('SELECT COUNT(DISTINCT eq_id) AS unique_eq_count, COUNT(*) AS entries_for_run FROM `Results` WHERE run_id = %d', run_id);
|
||||||
|
existing_results = database.fetch(queryStr);
|
||||||
|
|
||||||
if existing_results.unique_eq_count >= 6
|
if existing_results.unique_eq_count >= 6
|
||||||
if (existing_results.entries_for_run / existing_results.unique_eq_count) > 8
|
if (existing_results.entries_for_run / existing_results.unique_eq_count) > 5
|
||||||
return
|
return
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -94,8 +96,8 @@ try
|
|||||||
adaption= 1;
|
adaption= 1;
|
||||||
use_dd_mode = 1;
|
use_dd_mode = 1;
|
||||||
|
|
||||||
use_ffe = 1;
|
use_ffe = 0;
|
||||||
use_dfe = 1;
|
use_dfe = 0;
|
||||||
use_vnle_mlse = 1;
|
use_vnle_mlse = 1;
|
||||||
use_dbtgt = 1;
|
use_dbtgt = 1;
|
||||||
use_dbenc = 1;
|
use_dbenc = 1;
|
||||||
@@ -139,6 +141,10 @@ try
|
|||||||
% Preprocess signal
|
% Preprocess signal
|
||||||
Scpe_sig = preprocessSignal(Scpe_cell{r}, Symbols, fsym);
|
Scpe_sig = preprocessSignal(Scpe_cell{r}, Symbols, fsym);
|
||||||
|
|
||||||
|
% Scpe_sig.spectrum("fignum",2223,"normalizeTo0dB",1,"displayname",'Rx');
|
||||||
|
% Scpe_sig.spectrum("fignum",22233,"normalizeTo0dB",0,"displayname",'Rx');
|
||||||
|
% Scpe_sig.eye(fsym,M,"fignum",1024);
|
||||||
|
|
||||||
if duob_mode ~= db_mode.db_encoded
|
if duob_mode ~= db_mode.db_encoded
|
||||||
|
|
||||||
if use_ffe
|
if use_ffe
|
||||||
@@ -146,19 +152,19 @@ try
|
|||||||
ffe_order = [50, 0, 0];
|
ffe_order = [50, 0, 0];
|
||||||
eq_dfe = EQ("Ne",ffe_order,"Nb",[0,0,0],"training_length",len_tr,"training_loops",5,"dd_loops",5,"K",2,"DCmu",mu_dc,"DDmu",[mu_ffe mu_dfe],"DFEmu",0.005,"FFEmu",0,"plotfinal",0,"ideal_dfe",0);
|
eq_dfe = EQ("Ne",ffe_order,"Nb",[0,0,0],"training_length",len_tr,"training_loops",5,"dd_loops",5,"K",2,"DCmu",mu_dc,"DDmu",[mu_ffe mu_dfe],"DFEmu",0.005,"FFEmu",0,"plotfinal",0,"ideal_dfe",0);
|
||||||
|
|
||||||
dfe_results = ffe(eq_dfe,M,Scpe_sig,Symbols,Tx_bits,...
|
ffe_results = ffe(eq_dfe,M,Scpe_sig,Symbols,Tx_bits,...
|
||||||
"precode_mode",duob_mode,...
|
"precode_mode",duob_mode,...
|
||||||
'showAnalysis',0,...
|
'showAnalysis',0,...
|
||||||
"postFFE",[],...
|
"postFFE",[],...
|
||||||
"eth_style_symbol_mapping",0);
|
"eth_style_symbol_mapping",0);
|
||||||
|
|
||||||
output.ffe_package{r} = dfe_results;
|
output.ffe_package{r} = ffe_results;
|
||||||
|
|
||||||
dfe_results.metrics.print;
|
ffe_results.metrics.print;
|
||||||
dfe_results.config.equalizer_structure = "ffe";
|
ffe_results.config.equalizer_structure = "ffe";
|
||||||
|
|
||||||
if options.append_to_db
|
if options.append_to_db
|
||||||
database.addProcessingResult(run_id, dfe_results.metrics, dfe_results.config);
|
database.addProcessingResult(run_id, ffe_results.metrics, ffe_results.config);
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -110,12 +110,14 @@ if options.showAnalysis
|
|||||||
|
|
||||||
rx_signal.spectrum("normalizeTo0dB",1,"fignum",250,"displayname","Rx Spectrum");
|
rx_signal.spectrum("normalizeTo0dB",1,"fignum",250,"displayname","Rx Spectrum");
|
||||||
|
|
||||||
Duobinary().encode(tx_symbols).spectrum("normalizeTo0dB",1,"fignum",250,"displayname","DB encoded reference");
|
Duobinary().encode(tx_symbols).spectrum("normalizeTo0dB",1,"fignum",10,"displayname","DB encoded reference");
|
||||||
|
|
||||||
showEQNoisePSD(eq_noise,"fignum",250,"displayname",'Duobinary Target Noise after Equalization');
|
showEQNoisePSD(eq_noise,"fignum",250,"displayname",'Duobinary Target Noise after Equalization');
|
||||||
|
|
||||||
fprintf('DB tgt BER: %.2e \n',ber);
|
fprintf('DB tgt BER: %.2e \n',ber_db);
|
||||||
|
|
||||||
|
figure(341); clf;
|
||||||
|
showLevelHistogram(eq_signal, db_ref_sequence, "fignum", 341);
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ end
|
|||||||
|
|
||||||
% Hard decision on VNLE output
|
% Hard decision on VNLE output
|
||||||
eq_signal_hd = PAMmapper(M, 0).quantize(eq_signal_sd);
|
eq_signal_hd = PAMmapper(M, 0).quantize(eq_signal_sd);
|
||||||
|
eq_signal_hd.spectrum("displayname",'after full response FFE','fignum',2025,'normalizeTo0dB',1);
|
||||||
|
|
||||||
% Process through postfilter and MLSE
|
% Process through postfilter and MLSE
|
||||||
[mlse_sig_sd,whitened_noise] = pf_.process(eq_signal_sd, eq_noise);
|
[mlse_sig_sd,whitened_noise] = pf_.process(eq_signal_sd, eq_noise);
|
||||||
@@ -216,10 +217,24 @@ end
|
|||||||
|
|
||||||
|
|
||||||
function displayAnalysis(eq_noise, whitened_noise, eq_signal_sd, rx_signal, eq_, pf_, mlse_, tx_symbols, M, postFFE)
|
function displayAnalysis(eq_noise, whitened_noise, eq_signal_sd, rx_signal, eq_, pf_, mlse_, tx_symbols, M, postFFE)
|
||||||
|
|
||||||
|
% rx_signal.spectrum("displayname",'Rx Signal','fignum',100,'normalizeTo0dB',1);
|
||||||
|
|
||||||
% Display analysis plots and metrics
|
% Display analysis plots and metrics
|
||||||
figure(336);
|
figure(336);
|
||||||
|
hold on;
|
||||||
|
eq_signal_sd.spectrum("displayname",'Equalized Signal','fignum',336,'normalizeTo0dB',0);
|
||||||
|
eq_noise.spectrum("displayname",'Equalized Signal','fignum',336,'normalizeTo0dB',0);
|
||||||
showEQNoisePSD(eq_noise, "fignum", 336, "displayname", 'Residual Noise after VNLE', 'postfilter_taps', pf_.coefficients);
|
showEQNoisePSD(eq_noise, "fignum", 336, "displayname", 'Residual Noise after VNLE', 'postfilter_taps', pf_.coefficients);
|
||||||
|
|
||||||
|
for t = 1:4
|
||||||
|
pf_.ncoeff = t;
|
||||||
|
[~,~] = pf_.process(eq_signal_sd, eq_noise);
|
||||||
|
showEQNoisePSD(eq_noise, "fignum", 3388, "displayname", 'Residual Noise after VNLE', 'postfilter_taps', pf_.coefficients);
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
tx_symbols.spectrum("displayname",'Equalized Signal','fignum',1234,'normalizeTo0dB',1);
|
||||||
if ~isempty(postFFE)
|
if ~isempty(postFFE)
|
||||||
showEQcoefficients('n1', postFFE.e, "displayname", 'Coefficients', 'fignum', 338);
|
showEQcoefficients('n1', postFFE.e, "displayname", 'Coefficients', 'fignum', 338);
|
||||||
end
|
end
|
||||||
@@ -234,7 +249,7 @@ showLevelHistogram(eq_signal_sd, tx_symbols, "fignum", 341);
|
|||||||
|
|
||||||
warning off
|
warning off
|
||||||
showLevelScatter(eq_signal_sd, tx_symbols, "fignum", 400);
|
showLevelScatter(eq_signal_sd, tx_symbols, "fignum", 400);
|
||||||
showLevelScatter(rx_signal.resample("fs_out", tx_symbols.fs), tx_symbols, "fignum", 401);
|
% showLevelScatter(rx_signal.resample("fs_out", tx_symbols.fs), tx_symbols, "fignum", 401);
|
||||||
drawnow;
|
drawnow;
|
||||||
warning on
|
warning on
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ end
|
|||||||
|
|
||||||
% Ensure the figure is ready before calling spectrum
|
% Ensure the figure is ready before calling spectrum
|
||||||
eq_noise.spectrum("displayname", options.displayname, "fignum", fig.Number, "normalizeTo0dB", 1,"color",options.color);
|
eq_noise.spectrum("displayname", options.displayname, "fignum", fig.Number, "normalizeTo0dB", 1,"color",options.color);
|
||||||
title('Noise of soft decision signal (not MLSE)')
|
title('EEN')
|
||||||
|
|
||||||
if ~isnan(options.postfilter_taps)
|
if ~isnan(options.postfilter_taps)
|
||||||
% Hold on to the figure for further plotting
|
% Hold on to the figure for further plotting
|
||||||
@@ -43,5 +43,6 @@ end
|
|||||||
end
|
end
|
||||||
|
|
||||||
xlim([-eq_noise.fs/2* 1e-9 eq_noise.fs/2* 1e-9]);
|
xlim([-eq_noise.fs/2* 1e-9 eq_noise.fs/2* 1e-9]);
|
||||||
|
ylim([-15, 0]);
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -20,6 +20,12 @@ end
|
|||||||
f = f(1:half_nfft);
|
f = f(1:half_nfft);
|
||||||
H = H(1:half_nfft);
|
H = H(1:half_nfft);
|
||||||
|
|
||||||
|
H_mag = abs(H);
|
||||||
|
H_norm = H_mag ./ max(H_mag);
|
||||||
|
|
||||||
|
H_db = 20*log10(H_norm);
|
||||||
|
H_db = H_db - min(H_db);
|
||||||
|
|
||||||
% Determine the figure number to use or create a new figure
|
% Determine the figure number to use or create a new figure
|
||||||
if isnan(options.fignum)
|
if isnan(options.fignum)
|
||||||
fig = figure; % Create a new figure and get its handle
|
fig = figure; % Create a new figure and get its handle
|
||||||
@@ -30,7 +36,7 @@ end
|
|||||||
% Magnitude response (in dB)
|
% Magnitude response (in dB)
|
||||||
subplot(2,1,1);
|
subplot(2,1,1);
|
||||||
hold on
|
hold on
|
||||||
plot(f.*1e-9, 20*log10(abs(1./H)),'DisplayName',options.displayname);
|
plot(f.*1e-9, H_db,'DisplayName',options.displayname);
|
||||||
title('(Inverted) Magnitude Response of FFE Filter');
|
title('(Inverted) Magnitude Response of FFE Filter');
|
||||||
xlabel('Frequency (GHz)');
|
xlabel('Frequency (GHz)');
|
||||||
ylabel('Magnitude (dB)');
|
ylabel('Magnitude (dB)');
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ end
|
|||||||
received_sd = NaN(numel(constellation),length(ref_symbols));
|
received_sd = NaN(numel(constellation),length(ref_symbols));
|
||||||
lvlcol = cbrewer2('Paired',numel(constellation)*2);
|
lvlcol = cbrewer2('Paired',numel(constellation)*2);
|
||||||
lvlcol = lvlcol(2:2:end,:);
|
lvlcol = lvlcol(2:2:end,:);
|
||||||
|
lvlcol = linspecer(numel(constellation));
|
||||||
% lvlcol = cbrewer2('Set1',numel(constellation));
|
% lvlcol = cbrewer2('Set1',numel(constellation));
|
||||||
for lvl = 1:numel(constellation)
|
for lvl = 1:numel(constellation)
|
||||||
%Separate the equalized signal into the
|
%Separate the equalized signal into the
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
function [Bits, Symbols, Scpe_cell, found_sync] = loadAndSyncSignalDataFromDb(dataTable, options)
|
function [Bits, Symbols, Scpe_cell, found_sync] = loadAndSyncSignalDataFromDb(dataTable, options)
|
||||||
% LOADSIGNALDATA Loads and synchronizes signal data from storage
|
% LOADSIGNALDATA Loads and synchronizes signal data from storage
|
||||||
%
|
%
|
||||||
% Inputs:
|
% Inputs:d
|
||||||
% dataTable - Table with file paths and configuration
|
% dataTable - Table with file paths and configuration
|
||||||
% options - Struct with storage_path and max_occurences
|
% options - Struct with storage_path and max_occurences
|
||||||
%
|
%
|
||||||
|
|||||||
@@ -16,9 +16,9 @@ Scpe_sig = Scpe_sig.resample("fs_out", 2*fsym);
|
|||||||
[Scpe_sig, ~] = Scpe_sig.tsynch("reference", Symbols, "fs_ref", fsym, "debug_plots", 0);
|
[Scpe_sig, ~] = Scpe_sig.tsynch("reference", Symbols, "fs_ref", fsym, "debug_plots", 0);
|
||||||
|
|
||||||
% Apply Gaussian filter
|
% Apply Gaussian filter
|
||||||
Scpe_sig = Filter('filtdegree', 4, "f_cutoff", Symbols.fs.*0.6, ...
|
% Scpe_sig = Filter('filtdegree', 4, "f_cutoff", Symbols.fs.*0.6, ...
|
||||||
"fs", Scpe_sig.fs, "filterType", filtertypes.gaussian, ...
|
% "fs", Scpe_sig.fs, "filterType", filtertypes.gaussian, ...
|
||||||
"active", true).process(Scpe_sig);
|
% "active", true).process(Scpe_sig);
|
||||||
|
|
||||||
% Remove DC offset
|
% Remove DC offset
|
||||||
Scpe_sig = Scpe_sig - mean(Scpe_sig.signal);
|
Scpe_sig = Scpe_sig - mean(Scpe_sig.signal);
|
||||||
|
|||||||
@@ -120,7 +120,7 @@ switch submit_mode
|
|||||||
% fetchNext has already set Read=true on the errored future.
|
% fetchNext has already set Read=true on the errored future.
|
||||||
% Find the one Read==true that we have _not_ yet consumed.
|
% Find the one Read==true that we have _not_ yet consumed.
|
||||||
readMask = arrayfun(@(f) f.Read, futures);
|
readMask = arrayfun(@(f) f.Read, futures);
|
||||||
idxErr = find(readMask & ~consumedIdx, 1);
|
idxErr = find(readMask & ~consumedIdx', 1);
|
||||||
consumedIdx(idxErr) = true;
|
consumedIdx(idxErr) = true;
|
||||||
|
|
||||||
% Pull the _real_ exception out of the future object
|
% Pull the _real_ exception out of the future object
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
function [ach_inf_rate] = calc_air(test_signal,reference_signal,options)
|
function [ach_inf_rate] = calc_air(test_signal,reference_signal,options)
|
||||||
% Calculation of AIR acc. to J. Kozesnik, „Numerically Computing Achievable Rates of Memoryless Channels“, Francisco Javier Garcıa-Gomez, doi: 10.1007/978-94-009-9857-5.
|
% „Numerically Computing Achievable Rates of Memoryless Channels“, Francisco Javier Garcıa-Gomez, doi: 10.1007/978-94-009-9857-5.
|
||||||
% Implementation is not accessible, I mailed TUM to get the code...
|
% Implementation is not accessible, I mailed TUM to get the code...
|
||||||
|
|
||||||
arguments(Input)
|
arguments(Input)
|
||||||
@@ -26,7 +26,7 @@ end
|
|||||||
% TRIM
|
% TRIM
|
||||||
[test_signal,reference_signal]=trimseq(test_signal,reference_signal,options.skip_front,options.skip_end);
|
[test_signal,reference_signal]=trimseq(test_signal,reference_signal,options.skip_front,options.skip_end);
|
||||||
|
|
||||||
% CALC EVM
|
% CALC AIR
|
||||||
%%% new implementation of AIR
|
%%% new implementation of AIR
|
||||||
constellation = unique(reference_signal);
|
constellation = unique(reference_signal);
|
||||||
reference_idx = arrayfun(@(x) find(constellation == x, 1), reference_signal);
|
reference_idx = arrayfun(@(x) find(constellation == x, 1), reference_signal);
|
||||||
|
|||||||
94
Functions/Metrics/calc_gmi_bitwise.m
Normal file
94
Functions/Metrics/calc_gmi_bitwise.m
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
function [GMI,NGMI] = calc_gmi_bitwise(test_signal,reference_signal,options)
|
||||||
|
% https://cioffi-group.stanford.edu/doc/book/AppendixG.pdf
|
||||||
|
|
||||||
|
arguments(Input)
|
||||||
|
test_signal;
|
||||||
|
reference_signal;
|
||||||
|
options.skip_front = 0;
|
||||||
|
options.skip_end = 0;
|
||||||
|
options.returnErrorLocation = 0;
|
||||||
|
end
|
||||||
|
|
||||||
|
options.skip_end = abs(options.skip_end);
|
||||||
|
options.skip_front = abs(options.skip_front);
|
||||||
|
|
||||||
|
assert((options.skip_end+options.skip_front)<length(test_signal),"You can not skip more bits than overall length of data! Set skip_front or skip_end to lower value or check data_in");
|
||||||
|
|
||||||
|
if isa(reference_signal,'Signal')
|
||||||
|
reference_signal = reference_signal.signal;
|
||||||
|
end
|
||||||
|
|
||||||
|
if isa(test_signal,'Signal')
|
||||||
|
test_signal = test_signal.signal;
|
||||||
|
end
|
||||||
|
|
||||||
|
% TRIM
|
||||||
|
[test_signal,reference_signal]=trimseq(test_signal,reference_signal,options.skip_front,options.skip_end);
|
||||||
|
|
||||||
|
% CALC AIR
|
||||||
|
%%% new implementation of AIR
|
||||||
|
% Precompute
|
||||||
|
N = length(test_signal);
|
||||||
|
M = numel(unique(reference_signal));
|
||||||
|
nBits = log2(M);
|
||||||
|
levels = PAMmapper(M,0).levels / PAMmapper(M,0).scaling;
|
||||||
|
grayBits= PAMmapper(M,0).showBitMapping;
|
||||||
|
priors = ones(1,M)/M;
|
||||||
|
|
||||||
|
noise = test_signal-reference_signal;
|
||||||
|
sigma2 = var(noise);
|
||||||
|
|
||||||
|
% Allocate
|
||||||
|
LLR = zeros(N, nBits);
|
||||||
|
rxBits = zeros(N, nBits);
|
||||||
|
|
||||||
|
for n = 1:N
|
||||||
|
y = test_signal(n);
|
||||||
|
ll_table= -((y - levels).^2)/(2*sigma2) + log(priors); % M×1
|
||||||
|
|
||||||
|
% Per‐bit LLR
|
||||||
|
for b = 1:nBits
|
||||||
|
idx0 = grayBits(:,b)==0;
|
||||||
|
idx1 = grayBits(:,b)==1;
|
||||||
|
L0 = logsumexp(ll_table(idx0));
|
||||||
|
L1 = logsumexp(ll_table(idx1));
|
||||||
|
LLR(n,b) = L1 - L0;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
tx_bits = PAMmapper(M,0,"eth_style",0).demap(reference_signal);
|
||||||
|
|
||||||
|
% Compute GMI (bit‐wise MI averaged over all symbols)
|
||||||
|
MI_bits = zeros(1,nBits);
|
||||||
|
for b = 1:nBits
|
||||||
|
r0 = LLR(tx_bits(:,b)==0,b);
|
||||||
|
r1 = LLR(tx_bits(:,b)==1,b);
|
||||||
|
I0 = mean( log2(1 + exp(r0)) );
|
||||||
|
I1 = mean( log2(1 + exp( -r1)) );
|
||||||
|
MI_bits(b) = 1 - 0.5*(I0 + I1);
|
||||||
|
end
|
||||||
|
|
||||||
|
GMI = sum(MI_bits); % in bits per symbol
|
||||||
|
NGMI = GMI / nBits; % normalized per bit
|
||||||
|
|
||||||
|
% Auxiliary nested helper for numerically stable log-sum-exp
|
||||||
|
function s = logsumexp(a)
|
||||||
|
% LOGSUMEXP Compute log(sum(exp(a))) in a numerically stable way
|
||||||
|
m = max(a);
|
||||||
|
s = m + log(sum(exp(a - m)));
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function [data_,reference_]=trimseq(data,reference,skipstart,skip_end)
|
||||||
|
|
||||||
|
data_ = data(skipstart+1:end-skip_end,:);
|
||||||
|
|
||||||
|
delta_bits = length(reference) - length(data);
|
||||||
|
|
||||||
|
skip_end = delta_bits + skip_end;
|
||||||
|
|
||||||
|
reference_ = reference(skipstart+1:end-skip_end,:);
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
@@ -62,7 +62,7 @@ end
|
|||||||
m = log2(M); %bits per symbol
|
m = log2(M); %bits per symbol
|
||||||
|
|
||||||
entries = sum(~isnan(received_sd),2)';
|
entries = sum(~isnan(received_sd),2)';
|
||||||
P_X = entries./N;
|
P_X = ones(1,M)/M;%entries./N;
|
||||||
|
|
||||||
% Parameters
|
% Parameters
|
||||||
symbols = constellation'; % PAM-4 symbols
|
symbols = constellation'; % PAM-4 symbols
|
||||||
@@ -75,18 +75,20 @@ end
|
|||||||
% Entropy term
|
% Entropy term
|
||||||
H_X = -sum(P_X .* log2(P_X)); % Entropy of input distribution
|
H_X = -sum(P_X .* log2(P_X)); % Entropy of input distribution
|
||||||
|
|
||||||
% GMI computation
|
tx_bits = PAMmapper(M,0,"eth_style",0).demap(reference_signal);
|
||||||
noise_impact_term = 0;
|
|
||||||
for k = 1:N
|
|
||||||
y_k = test_signal(k); % Current received sample
|
|
||||||
[~, closest_symbol_idx] = min(abs(symbols - y_k)); % Closest symbol index
|
|
||||||
closest_symbol = symbols(closest_symbol_idx); % Closest symbol
|
|
||||||
|
|
||||||
for i = 1:m
|
% GMI computation
|
||||||
|
bit_llr_sum = 0;
|
||||||
|
for k = 1:N %loop over signal
|
||||||
|
y_k = test_signal(k); % Current received sample
|
||||||
|
% [~, closest_symbol_idx] = min(abs(symbols - y_k)); % Closest symbol index
|
||||||
|
|
||||||
|
for i = 1:m %loop over bit position
|
||||||
% Extract i-th bit for each symbol
|
% Extract i-th bit for each symbol
|
||||||
bit_mask = gray_bits(:, i); % Binary column for i-th bit of all symbols
|
bit_mask = gray_bits(:, i); % Binary column for i-th bit of all symbols
|
||||||
|
|
||||||
matching_symbols = symbols(bit_mask == gray_bits(closest_symbol_idx, i));
|
% matching_symbols = symbols(bit_mask == gray_bits(closest_symbol_idx, i)); %old, based on decision that mihht be wrong
|
||||||
|
matching_symbols = symbols(bit_mask == tx_bits(k,i)); %new, based on tx bits
|
||||||
|
|
||||||
% Numerator: Sum over x in x_{b_{k, i}}
|
% Numerator: Sum over x in x_{b_{k, i}}
|
||||||
numerator = sum(q_Y_given_X(y_k, matching_symbols) .* P_X(ismember(symbols, matching_symbols)));
|
numerator = sum(q_Y_given_X(y_k, matching_symbols) .* P_X(ismember(symbols, matching_symbols)));
|
||||||
@@ -95,15 +97,15 @@ end
|
|||||||
denominator = sum(q_Y_given_X(y_k, symbols) .* P_X);
|
denominator = sum(q_Y_given_X(y_k, symbols) .* P_X);
|
||||||
|
|
||||||
% Logarithmic contribution
|
% Logarithmic contribution
|
||||||
noise_impact_term = noise_impact_term + log2(numerator / denominator);
|
bit_llr_sum = bit_llr_sum + log2(numerator / denominator);
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
% Normalize the noise impact term by N
|
% Normalize the noise impact term by N
|
||||||
noise_impact_term = noise_impact_term / N;
|
bit_llr_sum = bit_llr_sum / N;
|
||||||
|
|
||||||
% GMI
|
% GMI
|
||||||
GMI = H_X + noise_impact_term;
|
GMI = H_X + bit_llr_sum;
|
||||||
NGMI = GMI / m;
|
NGMI = GMI / m;
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,20 +1,28 @@
|
|||||||
function [snr_all, snr_per_level] = calc_snr(tx_signal, eq_noise)
|
function [snr_all, snr_per_level] = calc_snr(tx_signal, eq_noise)
|
||||||
% CALC_SNR Calculates overall SNR and level-wise SNR for a PAM-M constellation.
|
% CALC_SNR Calculates overall SNR and level-wise SNR for a PAM-M constellation.
|
||||||
%
|
%
|
||||||
% [snr_all, snr_per_level] = calc_snr(tx_signal, eq_noise)
|
% [snr_all, snr_per_level] = calc_snr(tx_signal, eq_noise)
|
||||||
%
|
%
|
||||||
% Inputs:
|
% Inputs:
|
||||||
% tx_signal - Vector of transmitted signal values.
|
% tx_signal - Vector of transmitted signal values.
|
||||||
% eq_noise - Vector of corresponding noise samples.
|
% eq_noise - Vector of corresponding noise samples.
|
||||||
%
|
%
|
||||||
% Outputs:
|
% Outputs:
|
||||||
% snr_all - Overall SNR computed using all signal values.
|
% snr_all - Overall SNR computed using all signal values.
|
||||||
% snr_per_level - A vector where each element is the SNR computed
|
% snr_per_level - A vector where each element is the SNR computed
|
||||||
% for a unique amplitude level in tx_signal.
|
% for a unique amplitude level in tx_signal.
|
||||||
%
|
%
|
||||||
% The function first computes the overall SNR using the full signal vectors.
|
% The function first computes the overall SNR using the full signal vectors.
|
||||||
% Then it uses the unique levels in tx_signal to calculate the SNR for
|
% Then it uses the unique levels in tx_signal to calculate the SNR for
|
||||||
% the symbols corresponding to each level separately.
|
% the symbols corresponding to each level separately.
|
||||||
|
|
||||||
|
if isa(tx_signal,'Signal')
|
||||||
|
tx_signal = tx_signal.signal;
|
||||||
|
end
|
||||||
|
|
||||||
|
if isa(eq_noise,'Signal')
|
||||||
|
eq_noise = eq_noise.signal;
|
||||||
|
end
|
||||||
|
|
||||||
% Calculate overall SNR using the complete signals
|
% Calculate overall SNR using the complete signals
|
||||||
snr_all = snr(tx_signal, eq_noise);
|
snr_all = snr(tx_signal, eq_noise);
|
||||||
|
|||||||
54
Functions/Theory/dispersion_contour.m
Normal file
54
Functions/Theory/dispersion_contour.m
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
% Gitter für lambda0 und S0
|
||||||
|
lambda0_vec = linspace(1300,1320,200);
|
||||||
|
S0_vec = linspace(0.06,0.1,200);
|
||||||
|
[Lambda0, S0] = meshgrid(lambda0_vec, S0_vec);
|
||||||
|
|
||||||
|
% Festen Betriebsparameter
|
||||||
|
lambda = 1293; % nm
|
||||||
|
L = 10; % km
|
||||||
|
|
||||||
|
% Dispersion berechnen (lineare Näherung)
|
||||||
|
D = S0 .* ( lambda - Lambda0 ) * L;
|
||||||
|
|
||||||
|
%% 2D-Konturplot nur mit Linien und Text
|
||||||
|
figure('Color','w');
|
||||||
|
hold on
|
||||||
|
|
||||||
|
% Konturlinien
|
||||||
|
numLevels = 10;
|
||||||
|
levels = linspace(min(D(:)), max(D(:)), numLevels);
|
||||||
|
[C,h] = contour(S0, Lambda0, D, levels, ...
|
||||||
|
'LineWidth',1.5, ...
|
||||||
|
'ShowText','on', ...
|
||||||
|
'LabelFormat','%0.1f');
|
||||||
|
|
||||||
|
% cbrewer2-Colormap für die Linien
|
||||||
|
cmap = cbrewer2('div','RdYlGn', numLevels);
|
||||||
|
colormap(cmap);
|
||||||
|
|
||||||
|
% Achsenlinien
|
||||||
|
% yline(1310, '--k','ZDW_{mean}','LabelVerticalAlignment','top','LabelHorizontalAlignment','center');
|
||||||
|
x0 = 0.09;
|
||||||
|
% xline(x0, '--k','S_{0}','LabelHorizontalAlignment','left');
|
||||||
|
|
||||||
|
% Gaussian auf der x-Linie (S0 = 0.09)
|
||||||
|
mu_zwd = 1310; % nm
|
||||||
|
sigma_zwd = 2; % nm
|
||||||
|
zwd_vals = linspace(min(lambda0_vec), max(lambda0_vec), 500);
|
||||||
|
% PDF berechnen
|
||||||
|
gauss_pdf = (1/(sigma_zwd*sqrt(2*pi))) * exp(-0.5*((zwd_vals-mu_zwd)/sigma_zwd).^2);
|
||||||
|
% Normieren und auf eine sichtbare Breite skalieren
|
||||||
|
scale = 0.005; % passt die Maximal-Auslenkung in x-Richtung an
|
||||||
|
x_gauss = x0 + (gauss_pdf/max(gauss_pdf)) * scale;
|
||||||
|
|
||||||
|
% Plot
|
||||||
|
% plot(x_gauss, zwd_vals, 'LineWidth',2);
|
||||||
|
|
||||||
|
% Achsenbeschriftung & Titel
|
||||||
|
% Achsenbeschriftung & Titel
|
||||||
|
xlabel('S0 [ps / nm2 km]', 'FontSize', 12);
|
||||||
|
ylabel('ZDW [nm]', 'FontSize', 12);
|
||||||
|
title (sprintf('Dispersion: %d km; %d nm', L, lambda), 'FontSize', 14);
|
||||||
|
|
||||||
|
grid on
|
||||||
|
hold off
|
||||||
33
Functions/getFigureSize.m
Normal file
33
Functions/getFigureSize.m
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
% GETFIGURESIZE Retrieve the size of the current MATLAB figure window.
|
||||||
|
% [WIDTH, HEIGHT] = GETFIGURESIZE() returns the width and height of the
|
||||||
|
% current figure in pixels.
|
||||||
|
%
|
||||||
|
% Example:
|
||||||
|
% % Get size of current figure
|
||||||
|
% [w, h] = getFigureSize();
|
||||||
|
% fprintf('Current figure is %d pixels wide and %d pixels tall.\n', w, h);
|
||||||
|
%
|
||||||
|
% Adapt snippet for other figures:
|
||||||
|
% % Suppose H is a handle to any MATLAB figure (existing or new):
|
||||||
|
% H = figure; % or H = <some existing figure handle>;
|
||||||
|
% % Retrieve current size of the active (or any) figure:
|
||||||
|
% [wCur, hCur] = getFigureSize();
|
||||||
|
% % Set the other figure H to match that size, preserving its position:
|
||||||
|
% posH = get(H, 'Position'); % [left, bottom, width, height]
|
||||||
|
% newPos = [posH(1), posH(2), wCur, hCur];
|
||||||
|
% set(H, 'Position', newPos);
|
||||||
|
%
|
||||||
|
% Note:
|
||||||
|
% - Position vector is given as [left, bottom, width, height] in pixels.
|
||||||
|
% - If you want to specify a custom size directly, you can replace wCur/hCur
|
||||||
|
% with desired values.
|
||||||
|
|
||||||
|
function [width, height] = getFigureSize()
|
||||||
|
% Ensure a figure is available
|
||||||
|
fig = gcf;
|
||||||
|
% Get the position vector: [left, bottom, width, height]
|
||||||
|
pos = get(fig, 'Position');
|
||||||
|
% Extract width and height
|
||||||
|
width = pos(3);
|
||||||
|
height = pos(4);
|
||||||
|
end
|
||||||
@@ -0,0 +1,111 @@
|
|||||||
|
|
||||||
|
database_type = 'mysql';
|
||||||
|
dataBase = 'labor_highspeed';%'C:\Users\Silas\Documents\MATLAB\Datensätze\sioe_labor\silas_labor_newdsp_newstructure.db';
|
||||||
|
db = DBHandler("dataBase", [dataBase], "type", database_type);
|
||||||
|
|
||||||
|
fp = QueryFilter();
|
||||||
|
% fp.where('Runs', 'run_id','EQUALS', 987);
|
||||||
|
M = 6;
|
||||||
|
fp.where('Runs', 'pam_level','EQUALS', M);
|
||||||
|
baudrate = 162e9;
|
||||||
|
fp.where('Runs', 'symbolrate','EQUALS', baudrate);
|
||||||
|
% fp.where('Runs', 'fiber_length','EQUALS', 2);
|
||||||
|
fp.where('Runs', 'is_mpi','EQUALS', 0);
|
||||||
|
% fp.where('Runs', 'interference_path_length','EQUALS', 1000);
|
||||||
|
% fp.where('Runs', 'loop_id','GREATER_THAN', 11);
|
||||||
|
% fp.where('Runs', 'sir','EQUALS',18);
|
||||||
|
% fp.where('Runs', 'wavelength','EQUALS', 1310);
|
||||||
|
fp.where('Runs', 'db_mode','EQUALS', 1); % 0 == high preemphasis // 1 == low preemphasis
|
||||||
|
fp.where('Runs', 'rop_attenuation','EQUALS', 0);
|
||||||
|
|
||||||
|
|
||||||
|
fields = db.getTableFieldNames('power_state_info');
|
||||||
|
fields = [fields; db.getTableFieldNames('dashboard_ungrouped')];
|
||||||
|
[dataTable,~] = db.queryDB(fp, fields);
|
||||||
|
|
||||||
|
eqstructures = unique(dataTable.equalizer_structure);
|
||||||
|
fiber_len = unique(dataTable.fiber_length);
|
||||||
|
cnt = 1;
|
||||||
|
f=figure();
|
||||||
|
clf
|
||||||
|
hold on
|
||||||
|
|
||||||
|
markers = {'o', 's', 'd', '^', 'v', '>', '<', 'p', 'h'}; % Define marker styles
|
||||||
|
|
||||||
|
for fl = 1:numel(fiber_len)
|
||||||
|
|
||||||
|
fl_filtered = dataTable(dataTable.fiber_length == fiber_len(fl),:);
|
||||||
|
|
||||||
|
for eqs = [equalizer_structure.vnle_pf_mlse]
|
||||||
|
|
||||||
|
eq_choice = equalizer_structure(eqs);
|
||||||
|
if sum(eqstructures == eq_choice)~=1
|
||||||
|
disp(eq_choice)
|
||||||
|
continue
|
||||||
|
end
|
||||||
|
|
||||||
|
eq_filtered = fl_filtered(fl_filtered.equalizer_structure == eq_choice,:);
|
||||||
|
|
||||||
|
dispersion_sorted = sortrows(eq_filtered, {'accumulated_dispersion'}, 'ascend');
|
||||||
|
% dispersion_sorted = dispersion_sorted(dispersion_sorted.wavelength <= 1320,:);
|
||||||
|
% dispersion_sorted = dispersion_sorted(dispersion_sorted.BER < 0.02,:);
|
||||||
|
% pull out your vectors
|
||||||
|
accumulated_dispersion = dispersion_sorted.accumulated_dispersion;
|
||||||
|
ber = dispersion_sorted.BER;
|
||||||
|
% ber = dispersion_sorted.BER_precoded;
|
||||||
|
run_ids = dispersion_sorted.run_id; % <-- this is what we want in the datatip
|
||||||
|
len = dispersion_sorted.fiber_length;
|
||||||
|
lambda = dispersion_sorted.wavelength;
|
||||||
|
cols = cbrewer2('Set1',8);
|
||||||
|
% cols = flip(cbrewer2('RdYlGn',14));
|
||||||
|
cols = linspecer(8);
|
||||||
|
|
||||||
|
ber_wavelen_grouped = groupsummary( ...
|
||||||
|
dispersion_sorted, ... % input table
|
||||||
|
"wavelength", ... % grouping variable
|
||||||
|
"min", ... % which summary statistic
|
||||||
|
"BER_precoded");
|
||||||
|
|
||||||
|
dname = sprintf('%s; %d km',eq_choice, fiber_len(fl));
|
||||||
|
h1 = plot(ber_wavelen_grouped.wavelength, ber_wavelen_grouped.min_BER_precoded,'LineWidth', 2, 'MarkerSize', 5,'Marker',markers(cnt),'LineStyle','-','Color',cols(cnt,:),'MarkerEdgeColor','auto','MarkerFaceColor','white','DisplayName',dname);
|
||||||
|
|
||||||
|
|
||||||
|
plotallscatters=0;
|
||||||
|
if plotallscatters
|
||||||
|
% plot the two curves and capture their Line handles
|
||||||
|
dname = sprintf('%s; %d km',eq_choice, fiber_len(fl));
|
||||||
|
h1 = plot(lambda, ber,'LineWidth', 1.5, 'MarkerSize', 5,'Marker','o','LineStyle','none','Color',cols(cnt,:),'MarkerFaceColor',cols(cnt,:),'DisplayName',dname);
|
||||||
|
% —————— Add run_id as a datatip row ——————
|
||||||
|
% For each line, tell the datatip template where to find the run_id:
|
||||||
|
h1.DataTipTemplate.DataTipRows(end+1) = ...
|
||||||
|
dataTipTextRow('run\_id', run_ids);
|
||||||
|
h1.DataTipTemplate.DataTipRows(end+1) = ...
|
||||||
|
dataTipTextRow('len', len);
|
||||||
|
h1.DataTipTemplate.DataTipRows(end+1) = ...
|
||||||
|
dataTipTextRow('lambda', lambda);
|
||||||
|
end
|
||||||
|
|
||||||
|
xticks(sort(unique(lambda)));
|
||||||
|
xticklabels(sort(unique(lambda)));
|
||||||
|
|
||||||
|
grid on;
|
||||||
|
|
||||||
|
% Labels, scales, legend, etc.
|
||||||
|
xlabel('Wavelength in nm','FontSize',12);
|
||||||
|
ylabel('BER','FontSize',12);
|
||||||
|
tit = sprintf('%d GBd PAM-%d',baudrate.*1e-9, M);
|
||||||
|
title(tit,'FontSize',14,'FontWeight','bold');
|
||||||
|
set(gca, 'XScale','linear','YScale','log','FontSize',11);
|
||||||
|
legend
|
||||||
|
|
||||||
|
xlim([min(lambda)-2, max(lambda)+2]);
|
||||||
|
ylim([1e-4, 0.2]);
|
||||||
|
|
||||||
|
cnt = cnt+1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
yline([4.85e-3, 2e-2],'--','LineWidth',1,'HandleVisibility','off');
|
||||||
|
posH = get(f, 'Position'); % [left, bottom, width, height]
|
||||||
|
newPos = [posH(1), posH(2), 750, 300];
|
||||||
|
set(f, 'Position', newPos);
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
|
||||||
|
database_type = 'mysql';
|
||||||
|
dataBase = 'labor_highspeed';%'C:\Users\Silas\Documents\MATLAB\Datensätze\sioe_labor\silas_labor_newdsp_newstructure.db';
|
||||||
|
db = DBHandler("dataBase", [dataBase], "type", database_type);
|
||||||
|
|
||||||
|
fp = QueryFilter();
|
||||||
|
% fp.where('Runs', 'run_id','EQUALS', 987);
|
||||||
|
M = 8;
|
||||||
|
fp.where('Runs', 'pam_level','EQUALS', M);
|
||||||
|
% fp.where('Runs', 'bitrate','LESS_THAN', 310e9);
|
||||||
|
fp.where('Runs', 'fiber_length','EQUALS', 2);
|
||||||
|
fp.where('Runs', 'is_mpi','EQUALS', 0);
|
||||||
|
% fp.where('Runs', 'interference_path_length','EQUALS', 1000);
|
||||||
|
% fp.where('Runs', 'loop_id','GREATER_THAN', 11);
|
||||||
|
% fp.where('Runs', 'sir','EQUALS',18);
|
||||||
|
fp.where('Runs', 'wavelength','EQUALS', 1310);
|
||||||
|
% fp.where('Runs', 'db_mode','EQUALS', 1);
|
||||||
|
fp.where('Runs', 'rop_attenuation','EQUALS', 0);
|
||||||
|
|
||||||
|
% [dataTable,~] = db.queryDB(fp, db.getTableFieldNames('dashboard'));
|
||||||
|
|
||||||
|
eqstructures = unique(dataTable.equalizer_structure);
|
||||||
|
% Create the figure
|
||||||
|
figure(10);
|
||||||
|
hold on
|
||||||
|
for pre_emph = [1]
|
||||||
|
|
||||||
|
dbmode_filtered = dataTable(dataTable.db_mode == ~pre_emph,:);
|
||||||
|
|
||||||
|
for eqs = [equalizer_structure.vnle, equalizer_structure.vnle_pf_mlse , equalizer_structure.vnle_db_mlse]
|
||||||
|
|
||||||
|
eq_choice = equalizer_structure(eqs);
|
||||||
|
|
||||||
|
if sum(eqstructures == eq_choice)~=1
|
||||||
|
disp(eq_choice)
|
||||||
|
continue
|
||||||
|
end
|
||||||
|
|
||||||
|
eq_filtered = dbmode_filtered(dbmode_filtered.equalizer_structure == eq_choice,:);
|
||||||
|
|
||||||
|
symbolrate_sorted = sortrows(eq_filtered,{'symbolrate','min_BER_precoded'}, 'ascend');
|
||||||
|
[~, ia] = unique(symbolrate_sorted.symbolrate, 'first');
|
||||||
|
symbolrate_sorted = symbolrate_sorted(ia, :);
|
||||||
|
|
||||||
|
% Example data (replace these with your real vectors)
|
||||||
|
symbolrate = symbolrate_sorted.symbolrate.*1e-9; % in baud
|
||||||
|
bitrate = symbolrate * floor(log2(M)*10)/10;
|
||||||
|
ber = symbolrate_sorted.min_BER; % BER
|
||||||
|
ber_precoded = symbolrate_sorted.min_BER_precoded; % BER
|
||||||
|
cols = cbrewer2('Paired',12);
|
||||||
|
cols = [0.4660 0.6740 0.1880 ; 0.9290 0.6940 0.1250 ; 0 0.4470 0.7410; 0.4940 0.1840 0.5560]; %VNLE; PF ; DFE ; DB tgt
|
||||||
|
|
||||||
|
dname = [char(eq_choice)];
|
||||||
|
if pre_emph
|
||||||
|
dname = [dname,' with pre-emph.'];
|
||||||
|
else
|
||||||
|
dname = [dname,' w/o pre-emph.'];
|
||||||
|
end
|
||||||
|
|
||||||
|
plot(bitrate, ber, 'LineWidth', 1.5, 'MarkerSize', 5,'Marker','o','LineStyle','-','Color',cols((2*eqs)+1+pre_emph,:),'MarkerEdgeColor',cols((2*eqs)+1+pre_emph,:),'MarkerFaceColor',[1,1,1],'DisplayName',[dname]);
|
||||||
|
plot(bitrate, ber_precoded, 'LineWidth', 1.5, 'MarkerSize', 5,'Marker','square','LineStyle',':','Color',cols((2*eqs)+1+pre_emph,:),'MarkerEdgeColor',cols((2*eqs)+1+pre_emph,:),'MarkerFaceColor',[1,1,1],'DisplayName',[dname,'; pre-coded']);
|
||||||
|
grid on;
|
||||||
|
|
||||||
|
% Axis labels and title
|
||||||
|
xlabel('Baud Rate GBaud', 'FontSize', 12);
|
||||||
|
ylabel('BER', 'FontSize', 12);
|
||||||
|
title('BER vs. Baud Rate', 'FontSize', 14, 'FontWeight', 'bold');
|
||||||
|
|
||||||
|
% Improve tick formatting
|
||||||
|
set(gca, 'XScale', 'linear', ...
|
||||||
|
'YScale', 'log', ...
|
||||||
|
'TickLabelInterpreter', 'latex', ...
|
||||||
|
'FontSize', 11);
|
||||||
|
legend
|
||||||
|
|
||||||
|
xticks(bitrate);
|
||||||
|
|
||||||
|
% Optional: tighten axis limits
|
||||||
|
xlim([min(bitrate), max(bitrate)]);
|
||||||
|
ylim([5e-5, 0.5]);
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
yline([4.85e-3, 2e-2],'LineWidth',1,'LineStyle','--','HandleVisibility','off'); beautifyBERplot();
|
||||||
@@ -0,0 +1,117 @@
|
|||||||
|
|
||||||
|
database_type = 'mysql';
|
||||||
|
dataBase = 'labor_highspeed';%'C:\Users\Silas\Documents\MATLAB\Datensätze\sioe_labor\silas_labor_newdsp_newstructure.db';
|
||||||
|
db = DBHandler("dataBase", [dataBase], "type", database_type);
|
||||||
|
|
||||||
|
fp = QueryFilter();
|
||||||
|
% fp.where('Runs', 'run_id','EQUALS', 987);
|
||||||
|
M = 8;
|
||||||
|
fp.where('Runs', 'pam_level','EQUALS', M);
|
||||||
|
% fp.where('Runs', 'bitrate','LESS_THAN', 310e9);
|
||||||
|
fp.where('Runs', 'fiber_length','EQUALS', 2);
|
||||||
|
fp.where('Runs', 'is_mpi','EQUALS', 0);
|
||||||
|
% fp.where('Runs', 'interference_path_length','EQUALS', 1000);
|
||||||
|
% fp.where('Runs', 'loop_id','GREATER_THAN', 11);
|
||||||
|
% fp.where('Runs', 'sir','EQUALS',18);
|
||||||
|
fp.where('Runs', 'wavelength','EQUALS', 1310);
|
||||||
|
% fp.where('Runs', 'db_mode','EQUALS', 1);
|
||||||
|
fp.where('Runs', 'rop_attenuation','EQUALS', 0);
|
||||||
|
|
||||||
|
[dataTable,~] = db.queryDB(fp, db.getTableFieldNames('dashboard'));
|
||||||
|
|
||||||
|
eqstructures = unique(dataTable.equalizer_structure);
|
||||||
|
|
||||||
|
% Create the figure
|
||||||
|
f=figure(4);
|
||||||
|
hold on
|
||||||
|
|
||||||
|
eqs = [equalizer_structure.vnle, equalizer_structure.vnle_pf_mlse , equalizer_structure.vnle_db_mlse];
|
||||||
|
cols = [0.4660 0.6740 0.1880 ; 0.9290 0.6940 0.1250 ; 0 0.4470 0.7410; 0.4940 0.1840 0.5560]; %VNLE; PF ; DFE ; DB tgt
|
||||||
|
|
||||||
|
eq_choice = equalizer_structure.vnle;
|
||||||
|
pre_emph = 1;
|
||||||
|
dbmode_filtered = dataTable(dataTable.db_mode == ~pre_emph,:);
|
||||||
|
eq_filtered = dbmode_filtered(dbmode_filtered.equalizer_structure == eq_choice,:);
|
||||||
|
symbolrate_sorted = sortrows(eq_filtered,{'symbolrate','min_BER_precoded'}, 'ascend');
|
||||||
|
[~, ia] = unique(symbolrate_sorted.symbolrate, 'first');
|
||||||
|
symbolrate_sorted = symbolrate_sorted(ia, :);
|
||||||
|
symbolrate = symbolrate_sorted.symbolrate.*1e-9; % in baud
|
||||||
|
bitrate = symbolrate * floor(log2(M)*10)/10;
|
||||||
|
ber = symbolrate_sorted.min_BER; % BER
|
||||||
|
ber_precoded = symbolrate_sorted.min_BER_precoded; % BER
|
||||||
|
plot(bitrate, ber, 'LineWidth', 1.5, 'MarkerSize', 5,'Marker','v','LineStyle',':','Color',cols(1,:),'MarkerEdgeColor',cols(1,:),'MarkerFaceColor',cols(1,:),'DisplayName',['Tx pre-emphasis + VNLE']);
|
||||||
|
|
||||||
|
eq_choice = equalizer_structure.vnle_pf_mlse;
|
||||||
|
pre_emph = 0;
|
||||||
|
dbmode_filtered = dataTable(dataTable.db_mode == ~pre_emph,:);
|
||||||
|
eq_filtered = dbmode_filtered(dbmode_filtered.equalizer_structure == eq_choice,:);
|
||||||
|
symbolrate_sorted = sortrows(eq_filtered,{'symbolrate','min_BER_precoded'}, 'ascend');
|
||||||
|
[~, ia] = unique(symbolrate_sorted.symbolrate, 'first');
|
||||||
|
symbolrate_sorted = symbolrate_sorted(ia, :);
|
||||||
|
symbolrate = symbolrate_sorted.symbolrate.*1e-9; % in baud
|
||||||
|
bitrate = symbolrate * floor(log2(M)*10)/10;
|
||||||
|
ber = symbolrate_sorted.min_BER; % BER
|
||||||
|
ber_precoded = symbolrate_sorted.min_BER_precoded; % BER
|
||||||
|
plot(bitrate, ber, 'LineWidth', 1.5, 'MarkerSize', 5,'Marker','diamond','LineStyle',':','Color',cols(2,:),'MarkerEdgeColor',cols(2,:),'MarkerFaceColor',cols(2,:),'DisplayName',['VNLE+2-tap post-filter+MLSE']);
|
||||||
|
|
||||||
|
% eq_choice = equalizer_structure.dfe;
|
||||||
|
% pre_emph = 1;
|
||||||
|
% dbmode_filtered = dataTable(dataTable.db_mode == ~pre_emph,:);
|
||||||
|
% eq_filtered = dbmode_filtered(dbmode_filtered.equalizer_structure == eq_choice,:);
|
||||||
|
% symbolrate_sorted = sortrows(eq_filtered,{'symbolrate','min_BER_precoded'}, 'ascend');
|
||||||
|
% [~, ia] = unique(symbolrate_sorted.symbolrate, 'first');
|
||||||
|
% symbolrate_sorted = symbolrate_sorted(ia, :);
|
||||||
|
% symbolrate = symbolrate_sorted.symbolrate.*1e-9; % in baud
|
||||||
|
% bitrate = symbolrate * floor(log2(M)*10)/10;
|
||||||
|
% ber = symbolrate_sorted.min_BER; % BER
|
||||||
|
% ber_precoded = symbolrate_sorted.min_BER_precoded; % BER
|
||||||
|
% plot(bitrate, ber, 'LineWidth', 1.5, 'MarkerSize', 5,'Marker','o','LineStyle','-','Color',cols(3,:),'MarkerEdgeColor',cols(3,:),'MarkerFaceColor',cols(3,:),'DisplayName',[char(eq_choice)]);
|
||||||
|
|
||||||
|
eq_choice = equalizer_structure.vnle_db_mlse;
|
||||||
|
pre_emph = 0;
|
||||||
|
dbmode_filtered = dataTable(dataTable.db_mode == ~pre_emph,:);
|
||||||
|
eq_filtered = dbmode_filtered(dbmode_filtered.equalizer_structure == eq_choice,:);
|
||||||
|
symbolrate_sorted = sortrows(eq_filtered,{'symbolrate','min_BER_precoded'}, 'ascend');
|
||||||
|
[~, ia] = unique(symbolrate_sorted.symbolrate, 'first');
|
||||||
|
symbolrate_sorted = symbolrate_sorted(ia, :);
|
||||||
|
symbolrate = symbolrate_sorted.symbolrate.*1e-9; % in baud
|
||||||
|
bitrate = symbolrate * floor(log2(M)*10)/10;
|
||||||
|
ber = symbolrate_sorted.min_BER; % BER
|
||||||
|
ber_precoded = symbolrate_sorted.min_BER_precoded; % BER
|
||||||
|
plot(bitrate, ber_precoded, 'LineWidth', 1.5, 'MarkerSize', 5,'Marker','square','LineStyle',':','Color',cols(4,:),'MarkerEdgeColor',cols(4,:),'MarkerFaceColor',cols(4,:),'DisplayName',['DB precoding + DB tgt. + MLSE']);
|
||||||
|
|
||||||
|
|
||||||
|
% Axis labels and title with Arial font
|
||||||
|
xlabel('Gross bitrate [Gb/s]', 'FontSize', 12, 'FontName', 'Arial', 'Interpreter', 'none');
|
||||||
|
ylabel('BER', 'FontSize', 12, 'FontName', 'Arial', 'Interpreter', 'none');
|
||||||
|
title('', 'FontSize', 14, 'FontWeight', 'bold', 'FontName', 'Arial', 'Interpreter', 'none');
|
||||||
|
|
||||||
|
% Improve tick formatting
|
||||||
|
set(gca, 'XScale', 'linear', ...
|
||||||
|
'YScale', 'log', ...
|
||||||
|
'TickLabelInterpreter', 'none', ...
|
||||||
|
'FontSize', 11, ...
|
||||||
|
'FontName', 'Arial');
|
||||||
|
|
||||||
|
% Legend with Arial font
|
||||||
|
% legend('FontName', 'Arial', 'Interpreter', 'none','Location','best');
|
||||||
|
|
||||||
|
xticks(bitrate);
|
||||||
|
|
||||||
|
% Optional: tighten axis limits
|
||||||
|
xlim([min(bitrate), max(bitrate)]);
|
||||||
|
ylim([5e-4, 0.05]);
|
||||||
|
|
||||||
|
yline([3.8e-3], 'LineWidth', 2, 'LineStyle', '--', ...
|
||||||
|
'HandleVisibility', 'off', 'LabelHorizontalAlignment', 'left');
|
||||||
|
|
||||||
|
posH = get(f, 'Position'); % [left, bottom, width, height]
|
||||||
|
newPos = [posH(1), posH(2), 350, 200];
|
||||||
|
set(f, 'Position', newPos);
|
||||||
|
|
||||||
|
annotation(f,'textbox',...
|
||||||
|
[0.398095238095238 0.273381294964029 0.491428571428572 0.140287769784173],...
|
||||||
|
'String',{'PAM-8; 2 km; 1293 nm'},...
|
||||||
|
'LineWidth',0.5,...
|
||||||
|
'FitBoxToText','off',...
|
||||||
|
'BackgroundColor',[1 1 1]);
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
|
||||||
|
database_type = 'mysql';
|
||||||
|
dataBase = 'labor_highspeed';%'C:\Users\Silas\Documents\MATLAB\Datensätze\sioe_labor\silas_labor_newdsp_newstructure.db';
|
||||||
|
db = DBHandler("dataBase", [dataBase], "type", database_type);
|
||||||
|
|
||||||
|
M = 8;
|
||||||
|
fp = QueryFilter();
|
||||||
|
% fp.where('Runs', 'run_id','EQUALS', 987);
|
||||||
|
fp.where('Runs', 'pam_level','EQUALS', M);
|
||||||
|
% fp.where('Runs', 'symbolrate','EQUALS', 165e9);
|
||||||
|
fp.where('Runs', 'fiber_length','EQUALS', 2);
|
||||||
|
fp.where('Runs', 'is_mpi','EQUALS', 0);
|
||||||
|
% fp.where('Runs', 'interference_path_length','EQUALS', 1000);
|
||||||
|
% fp.where('Runs', 'loop_id','GREATER_THAN', 11);
|
||||||
|
% fp.where('Runs', 'sir','EQUALS',18);
|
||||||
|
fp.where('Runs', 'wavelength','EQUALS', 1310);
|
||||||
|
% fp.where('Runs', 'db_mode','EQUALS', 1); % 0 == high preemphasis // 1 == low preemphasis
|
||||||
|
fp.where('Runs', 'rop_attenuation','EQUALS', 0);
|
||||||
|
|
||||||
|
[dataTable,~] = db.queryDB(fp, db.getTableFieldNames('dashboard'));
|
||||||
|
|
||||||
|
eqstructures = unique(dataTable.equalizer_structure);
|
||||||
|
|
||||||
|
% Create the figure
|
||||||
|
figure(18);
|
||||||
|
hold on
|
||||||
|
|
||||||
|
for pre_emph = [0,1]
|
||||||
|
|
||||||
|
dbmode_filtered = dataTable(dataTable.db_mode == ~pre_emph,:);
|
||||||
|
|
||||||
|
for eqs = [equalizer_structure.vnle]
|
||||||
|
|
||||||
|
eq_choice = equalizer_structure(eqs);
|
||||||
|
if sum(eqstructures == eq_choice)~=1
|
||||||
|
disp(eq_choice)
|
||||||
|
continue
|
||||||
|
end
|
||||||
|
|
||||||
|
eq_filtered = dbmode_filtered(dbmode_filtered.equalizer_structure == eq_choice,:);
|
||||||
|
if eqs ==equalizer_structure.vnle_pf_mlse
|
||||||
|
eq_filtered = eq_filtered(eq_filtered.DIR == "1",:);
|
||||||
|
end
|
||||||
|
symbolrate_sorted = sortrows(eq_filtered,{'symbolrate'}, 'ascend');
|
||||||
|
|
||||||
|
% Example data (replace these with your real vectors)
|
||||||
|
symbolrate = symbolrate_sorted.symbolrate.*1e-9; % in baud
|
||||||
|
bitrate = symbolrate * 2;
|
||||||
|
gmi = symbolrate_sorted.max_GMI; % BER
|
||||||
|
snr = symbolrate_sorted.max_SNR; % BER
|
||||||
|
cols = cbrewer2('Paired',12);
|
||||||
|
|
||||||
|
dname = [char(eq_choice)];
|
||||||
|
dname = strrep(dname,'_','+');
|
||||||
|
if pre_emph
|
||||||
|
dname = [dname,'; w/ pre-emph.'];
|
||||||
|
else
|
||||||
|
dname = [dname,'; w/o pre-emph.'];
|
||||||
|
end
|
||||||
|
|
||||||
|
plot(symbolrate, snr, 'LineWidth', 1.5, 'MarkerSize', 5,'Marker','o','LineStyle','-','Color',cols((2*eqs)+1+pre_emph,:),'MarkerEdgeColor',cols((2*eqs)+1+pre_emph,:),'MarkerFaceColor',[1,1,1],'DisplayName',[dname]);
|
||||||
|
grid on;
|
||||||
|
|
||||||
|
% Axis labels and title
|
||||||
|
xlabel('Bit Rate Gbps', 'FontSize', 12);
|
||||||
|
ylabel('GMI', 'FontSize', 12);
|
||||||
|
title('GMI vs. Bit Rate', 'FontSize', 14, 'FontWeight', 'bold');
|
||||||
|
|
||||||
|
% Improve tick formatting
|
||||||
|
set(gca, 'XScale', 'linear', ...
|
||||||
|
'YScale', 'linear', ...
|
||||||
|
'TickLabelInterpreter', 'none', ...
|
||||||
|
'FontSize', 11);
|
||||||
|
legend
|
||||||
|
|
||||||
|
xticks(symbolrate);
|
||||||
|
|
||||||
|
% Optional: tighten axis limits
|
||||||
|
xlim([min(symbolrate), max(symbolrate)]);
|
||||||
|
% ylim([log2(M)-1, log2(M)]);
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
@@ -0,0 +1,96 @@
|
|||||||
|
|
||||||
|
database_type = 'mysql';
|
||||||
|
dataBase = 'labor_highspeed';%'C:\Users\Silas\Documents\MATLAB\Datensätze\sioe_labor\silas_labor_newdsp_newstructure.db';
|
||||||
|
db = DBHandler("dataBase", [dataBase], "type", database_type);
|
||||||
|
|
||||||
|
fp = QueryFilter();
|
||||||
|
fp.where('power_state_info', 'pam_level','EQUALS', 4);
|
||||||
|
fp.where('power_state_info', 'db_mode','EQUALS', 1);
|
||||||
|
% fp.where('power_state_info', 'fiber_length','EQUALS', 1);
|
||||||
|
fp.where('power_state_info', 'is_mpi','EQUALS', 0);
|
||||||
|
|
||||||
|
fields = db.getTableFieldNames('power_state_info');
|
||||||
|
% [dataTable,~] = db.queryDB(fp, fields);
|
||||||
|
|
||||||
|
fiber_len = unique(dataTable.fiber_length);
|
||||||
|
cnt = 0;
|
||||||
|
|
||||||
|
y_variable = 'power_mzm';
|
||||||
|
x_variable = "wavelength";
|
||||||
|
f = figure(3);
|
||||||
|
clf
|
||||||
|
hold on
|
||||||
|
for fl = 1:numel(fiber_len)
|
||||||
|
|
||||||
|
|
||||||
|
fl_filtered = dataTable(dataTable.fiber_length == fiber_len(fl),:);
|
||||||
|
[~, ia] = unique(fl_filtered.run_id, 'first');
|
||||||
|
fl_filtered = fl_filtered(ia, :);
|
||||||
|
|
||||||
|
fl_filtered_ = groupsummary( ...
|
||||||
|
fl_filtered, ... % input table
|
||||||
|
x_variable, ... % grouping variable
|
||||||
|
"mean", ... % which summary statistic
|
||||||
|
y_variable); % which column to average
|
||||||
|
|
||||||
|
wavelength_sorted = sortrows(fl_filtered, {'wavelength'}, 'ascend');
|
||||||
|
|
||||||
|
% pull out your vectors
|
||||||
|
lambda = wavelength_sorted.wavelength;
|
||||||
|
power_laser = wavelength_sorted.power_laser;
|
||||||
|
power_mzm = wavelength_sorted.power_mzm;
|
||||||
|
power_rop = wavelength_sorted.power_rop;
|
||||||
|
power_pd = wavelength_sorted.power_pd_in;
|
||||||
|
voa = wavelength_sorted.voa_atten;
|
||||||
|
len = wavelength_sorted.fiber_length;
|
||||||
|
run_ids = wavelength_sorted.run_id; % <-- this is what we want in the datatip
|
||||||
|
cols = linspecer(8);
|
||||||
|
|
||||||
|
|
||||||
|
% plot the two curves and capture their Line handles
|
||||||
|
% h1 = plot(lambda, power_laser,'LineWidth', 0.5, 'MarkerSize', 4,'Marker','o','LineStyle','none','Color',cols(fl,:),'MarkerFaceColor',cols(fl,:),'DisplayName','Laser Output');
|
||||||
|
% % —————— Add run_id as a datatip row ——————
|
||||||
|
% % For each line, tell the datatip template where to find the run_id:
|
||||||
|
% h1.DataTipTemplate.DataTipRows(end+1) = ...
|
||||||
|
% dataTipTextRow('run\_id', run_ids);
|
||||||
|
% h1.DataTipTemplate.DataTipRows(end+1) = ...
|
||||||
|
% dataTipTextRow('len', run_ids);
|
||||||
|
% h1.DataTipTemplate.DataTipRows(end+1) = ...
|
||||||
|
% dataTipTextRow('voaatten', voa);
|
||||||
|
|
||||||
|
%
|
||||||
|
dname = sprintf('%s; %d km',y_variable, fiber_len(fl));
|
||||||
|
h2 = plot(fl_filtered_.(x_variable), fl_filtered_.(['mean_',y_variable]), 'LineWidth', 1, 'MarkerSize', 4,'Marker','o','LineStyle','-','Color',cols(fl,:),'MarkerFaceColor',cols(fl,:),'DisplayName',dname);
|
||||||
|
|
||||||
|
h2.DataTipTemplate.DataTipRows(end+1) = ...
|
||||||
|
dataTipTextRow('run\_id', run_ids);
|
||||||
|
h2.DataTipTemplate.DataTipRows(end+1) = ...
|
||||||
|
dataTipTextRow('len', len);
|
||||||
|
h2.DataTipTemplate.DataTipRows(end+1) = ...
|
||||||
|
dataTipTextRow('voaatten', voa);
|
||||||
|
|
||||||
|
grid on;
|
||||||
|
xticks(sort(unique(lambda)));
|
||||||
|
xticklabels(sort(unique(lambda)));
|
||||||
|
|
||||||
|
% Labels, scales, legend, etc.
|
||||||
|
xlabel('Wavelength in nm','FontSize',12);
|
||||||
|
ylabel('Power in dB','FontSize',12);
|
||||||
|
title('Power ','FontSize',14,'FontWeight','bold');
|
||||||
|
set(gca, 'XScale','linear','YScale','linear','FontSize',11);
|
||||||
|
legend
|
||||||
|
|
||||||
|
xlim([min(lambda)-2, max(lambda)+2]);
|
||||||
|
ylim([floor(min(fl_filtered_.(['mean_',y_variable])))-1 12]);
|
||||||
|
ylim([-12 12]);
|
||||||
|
|
||||||
|
cnt = cnt+1;
|
||||||
|
|
||||||
|
yline(8,'HandleVisibility','off');
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
yline([4.85e-3, 2e-2],'--','LineWidth',1,'HandleVisibility','off');
|
||||||
|
posH = get(f, 'Position'); % [left, bottom, width, height]
|
||||||
|
newPos = [posH(1), posH(2), 750, 300];
|
||||||
|
set(f, 'Position', newPos);
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
% === SETTINGS ===
|
% === SETTINGS ===
|
||||||
dsp_options.append_to_db = 1;
|
dsp_options.append_to_db = 0;
|
||||||
dsp_options.max_occurences = 15;
|
dsp_options.max_occurences = 1;
|
||||||
|
|
||||||
experiment = "highspeed_2024";
|
experiment = "highspeed_2024";
|
||||||
dsp_options.mode = "load_run_id"; % 'simulate' & 'load_files'
|
dsp_options.mode = "load_run_id"; % 'simulate' & 'load_files'
|
||||||
@@ -41,14 +41,14 @@ end
|
|||||||
fp = QueryFilter();
|
fp = QueryFilter();
|
||||||
% fp.where('Runs', 'run_id','EQUALS', 987);
|
% fp.where('Runs', 'run_id','EQUALS', 987);
|
||||||
fp.where('Runs', 'pam_level','EQUALS', 4);
|
fp.where('Runs', 'pam_level','EQUALS', 4);
|
||||||
% fp.where('Runs', 'bitrate','LESS_THAN', 310e9);
|
fp.where('Runs', 'bitrate','EQUALS', 360e9);
|
||||||
% fp.where('Runs', 'fiber_length','EQUALS', 1);
|
fp.where('Runs', 'fiber_length','EQUALS', 2);
|
||||||
fp.where('Runs', 'is_mpi','EQUALS', 0);
|
fp.where('Runs', 'is_mpi','EQUALS', 0);
|
||||||
% fp.where('Runs', 'interference_path_length','EQUALS', 1000);
|
% fp.where('Runs', 'interference_path_length','EQUALS', 1000);
|
||||||
% fp.where('Runs', 'loop_id','GREATER_THAN', 11);
|
% fp.where('Runs', 'loop_id','GREATER_THAN', 11);
|
||||||
% fp.where('Runs', 'sir','EQUALS',18);
|
% fp.where('Runs', 'sir','EQUALS',18);
|
||||||
% fp.where('Runs', 'wavelength','EQUALS', 1310);
|
fp.where('Runs', 'wavelength','EQUALS', 1310);
|
||||||
% fp.where('Runs', 'db_mode','EQUALS', 1);
|
fp.where('Runs', 'db_mode','EQUALS', 0);
|
||||||
fp.where('Runs', 'rop_attenuation','EQUALS', 0);
|
fp.where('Runs', 'rop_attenuation','EQUALS', 0);
|
||||||
% fp.where('Runs', 'power_pd_in','GREATER_THAN', 7);
|
% fp.where('Runs', 'power_pd_in','GREATER_THAN', 7);
|
||||||
|
|
||||||
@@ -75,7 +75,7 @@ wh.addStorage("dbenc_package");
|
|||||||
|
|
||||||
% === RUN IT ===
|
% === RUN IT ===
|
||||||
|
|
||||||
[results,wh] = submitJobs(dataTable.run_id(:), dsp_options, "parallel", 'wh', wh, 'waitbar', true);
|
[results,wh] = submitJobs(dataTable.run_id(:), dsp_options, "serial", 'wh', wh, 'waitbar', true);
|
||||||
|
|
||||||
|
|
||||||
% wh.getStoValue('ffe_package',0.005);
|
% wh.getStoValue('ffe_package',0.005);
|
||||||
|
|||||||
@@ -0,0 +1,236 @@
|
|||||||
|
|
||||||
|
precomp_mode = 0;
|
||||||
|
precomp_path = "C:\Users\Silas\Documents\MATLAB\imdd_simulation\projects\HighSpeedExperiment_2024\Auswertung_JLT";
|
||||||
|
precomp_fn = "precomp_simulated.mat";
|
||||||
|
|
||||||
|
% TX
|
||||||
|
M = 4;
|
||||||
|
fsym = 72e9;
|
||||||
|
f_nyquist = fsym/2;
|
||||||
|
apply_pulsef = 1;
|
||||||
|
fdac = 256e9;
|
||||||
|
fadc = 256e9;
|
||||||
|
% fdac = 2*fsym;
|
||||||
|
% fadc = 2*fsym;
|
||||||
|
random_key = 1;
|
||||||
|
|
||||||
|
duob_mode = db_mode.no_db;
|
||||||
|
|
||||||
|
tx_bwl = 0.8.*f_nyquist;
|
||||||
|
rx_bwl = 0.8.*f_nyquist;
|
||||||
|
|
||||||
|
rcalpha = 0.05;
|
||||||
|
kover = 16;
|
||||||
|
vbias_rel = 0.5;
|
||||||
|
u_pi = 2.9;
|
||||||
|
vbias = -vbias_rel*u_pi;
|
||||||
|
laser_wavelength = 1293;
|
||||||
|
laser_linewidth = 0;
|
||||||
|
|
||||||
|
|
||||||
|
% Channel
|
||||||
|
link_length = 60000;
|
||||||
|
|
||||||
|
% RX
|
||||||
|
rop = -8;
|
||||||
|
|
||||||
|
% EQ
|
||||||
|
eq_mode = equalizer_structure.vnle_pf_mlse;
|
||||||
|
ffe_order=[50,0,0];
|
||||||
|
vnle_order=[50,5,5];
|
||||||
|
dfe_order = [0 0 0];
|
||||||
|
|
||||||
|
len_tr = 4096*2;
|
||||||
|
mu_ffe = [0.0004 0.0004 0.0004];
|
||||||
|
mu_dfe = 0.0004;
|
||||||
|
mu_dc = 0.00;
|
||||||
|
|
||||||
|
dfe_ = sum(dfe_order)>0;
|
||||||
|
|
||||||
|
Pform = Pulseformer("fsym",fsym,"fdac",4*fsym,"pulse","rc","pulselength",16,"alpha",rcalpha);
|
||||||
|
|
||||||
|
[Digi_sig,Symbols,Tx_bits] = PAMsource(...
|
||||||
|
"fsym",fsym,"M",M,"order",18,"useprbs",0,...
|
||||||
|
"fs_out",fdac,...
|
||||||
|
"applyclipping",0,"clipfactor",1.5,...
|
||||||
|
"applypulseform",apply_pulsef,"pulseformer",Pform,...
|
||||||
|
"randkey",random_key,...
|
||||||
|
"duobinary_mode",duob_mode).process();
|
||||||
|
|
||||||
|
if precomp_mode == 1 % measure channel
|
||||||
|
precomp_est = ChannelFreqResp("Nacq",1024,"Navg",64,"Ncp",63,'f_ref',fdac);
|
||||||
|
Digi_sig = precomp_est.buildOFDM();
|
||||||
|
elseif precomp_mode == 2 % apply precomp
|
||||||
|
precomp_est = ChannelFreqResp("Nacq",1024,"Navg",64,"Ncp",63,'f_ref',Digi_sig.fs);
|
||||||
|
Digi_sig = precomp_est.precomp(Digi_sig,'maxampdb',-50,'loadPath',precomp_path,'fileName',precomp_fn);
|
||||||
|
end
|
||||||
|
|
||||||
|
% Symbols.spectrum("displayname",'Tx Symbols','fignum',10,'normalizeTo0dB',1);
|
||||||
|
|
||||||
|
Digi_sig.eye(fsym,M,"fignum",1234567);
|
||||||
|
%%%%% AWG
|
||||||
|
%El_sig = M8199B("kover",kover).process(Digi_sig);
|
||||||
|
El_sig = AWG("fdac",fdac,"f_cutoff",fsym,"lpf_active",0,"kover",kover,"bit_resolution",12,"upsampling_method","samplehold","precomp_sinc_rolloff",1).process(Digi_sig);
|
||||||
|
% El_sig.spectrum("displayname",'Digi Spectrum','fignum',100,'normalizeTo0dB',0);
|
||||||
|
% El_sig = El_sig.setPower(0,"dBm");
|
||||||
|
El_sig.spectrum("displayname",'Tx Signal','fignum',10,'normalizeTo0dB',0);
|
||||||
|
%%%%% Low-pass el. components %%%%%%
|
||||||
|
|
||||||
|
El_sig = Filter('filtdegree',4,"f_cutoff",tx_bwl,"fs",fdac*kover,"filterType",filtertypes.gaussian,"active",true).process(El_sig);
|
||||||
|
% El_sig.spectrum("displayname",'Digi Spectrum','fignum',100,'normalizeTo0dB',1);
|
||||||
|
|
||||||
|
%%%%% Electrical Driver Amplifier %%%%%%
|
||||||
|
El_sig = Amplifier("amp_mode","ideal_no_noise","gain_mode","gain","amplification_db",3).process(El_sig);
|
||||||
|
El_sig = El_sig.normalize("mode","oneone");
|
||||||
|
|
||||||
|
%%%%% MODULATE E/O CONVERSION %%%%%%
|
||||||
|
[Opt_sig] = EML("mode",eml_mode.im_cosinus,"power",3,"fsimu",El_sig.fs,"lambda",laser_wavelength,"bias",vbias,"u_pi",u_pi,"linewidth",laser_linewidth,"randomkey",random_key+1).process(El_sig);
|
||||||
|
|
||||||
|
Opt_sig = Fiber("fsimu",Opt_sig.fs,"fiber_length",link_length/1000,"alpha",0.3,"D",0,"lambda0",1310,"gamma",0,"Dslope",0.07).process(Opt_sig);
|
||||||
|
|
||||||
|
%%%%%% ROP %%%%%%
|
||||||
|
Rx_sig = Amplifier("amp_mode","ideal_no_noise","gain_mode","output_power","amplification_db",rop).process(Opt_sig);
|
||||||
|
|
||||||
|
%%%%%% PD Square Law %%%%%%
|
||||||
|
Rx_sig = Photodiode("fsimu",fdac*kover,"dark_current",2e-08,"responsivity",1,"temperature",20,"nep",1.8e-11).process(Rx_sig);
|
||||||
|
|
||||||
|
%%%%%% Low-pass RX (PD, El. Connectors and Scope %%%%%%
|
||||||
|
Rx_sig = Filter('filtdegree',4,"f_cutoff",rx_bwl,"fs",fdac*kover,"filterType",filtertypes.bessel_inp,"active",true).process(Rx_sig);
|
||||||
|
|
||||||
|
% %%%%%% Low-pass Scope %%%%%%
|
||||||
|
Lp_scpe = Filter('filtdegree',4,"f_cutoff",35e9,"fs",fadc,"filterType",filtertypes.butterworth,"active",true);
|
||||||
|
|
||||||
|
% Rx_sig.spectrum("displayname",'Analog Rx Spectrum','fignum',100,'normalizeTo0dB',1);
|
||||||
|
|
||||||
|
%%%%%% Scope %%%%%%
|
||||||
|
Scpe_sig = Scope("fsimu",fdac*kover,"fadc",fadc,...
|
||||||
|
"delay",0,"fixed_delay",0,"filtertype",filtertypes.butterworth,...
|
||||||
|
"samplingdelay",0,"rand_samplingdelay",0,"freq_offset",0,"samp_jitter",0,...
|
||||||
|
"adcresolution",8,"quantbuffer",0.1,'block_dc',1,'lpf_active',1,'H_lpf',Lp_scpe).process(Rx_sig);
|
||||||
|
|
||||||
|
Scpe_sig.spectrum("displayname",'Rx Signal','fignum',10,'normalizeTo0dB',1);
|
||||||
|
Scpe_sig.eye(fsym,M,"fignum",1973763)
|
||||||
|
|
||||||
|
%%%%% Precompensation Routine %%%%%%
|
||||||
|
if precomp_mode == 1
|
||||||
|
Scpe_sig_resampled = Scpe_sig.resample("fs_in",fadc,"fs_out",2*fsym);
|
||||||
|
precomp_est.estimate(Scpe_sig_resampled,"save",false,"savePath",precomp_path,"fileName",precomp_fn);
|
||||||
|
precomp_est.plot();
|
||||||
|
precomp_est.save();
|
||||||
|
end
|
||||||
|
|
||||||
|
% Preprocess signal
|
||||||
|
Scpe_sig = preprocessSignal(Scpe_sig, Symbols, fsym);
|
||||||
|
Scpe_sig.signal = Scpe_sig.signal(1:2*Symbols.length);
|
||||||
|
use_ffe = 0;
|
||||||
|
use_dfe = 0;
|
||||||
|
use_vnle_mlse = 1;
|
||||||
|
use_dbtgt = 1;
|
||||||
|
use_dbenc = 1;
|
||||||
|
|
||||||
|
|
||||||
|
if duob_mode ~= db_mode.db_encoded
|
||||||
|
|
||||||
|
if use_ffe
|
||||||
|
|
||||||
|
ffe_order = [50, 0, 0];
|
||||||
|
eq_dfe = EQ("Ne",ffe_order,"Nb",[0,0,0],"training_length",len_tr,"training_loops",5,"dd_loops",5,"K",2,"DCmu",mu_dc,"DDmu",[mu_ffe mu_dfe],"DFEmu",0.005,"FFEmu",0,"plotfinal",0,"ideal_dfe",0);
|
||||||
|
|
||||||
|
ffe_results = ffe(eq_dfe,M,Scpe_sig,Symbols,Tx_bits,...
|
||||||
|
"precode_mode",duob_mode,...
|
||||||
|
'showAnalysis',1,...
|
||||||
|
"postFFE",[],...
|
||||||
|
"eth_style_symbol_mapping",0);
|
||||||
|
|
||||||
|
disp('FFE:')
|
||||||
|
ffe_results.metrics.print;
|
||||||
|
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
if use_dfe
|
||||||
|
|
||||||
|
ffe_order = [50, 5, 5];
|
||||||
|
eq_dfe = EQ("Ne",ffe_order,"Nb",[2,0,0],"training_length",len_tr,"training_loops",5,"dd_loops",5,"K",2,"DCmu",mu_dc,"DDmu",[mu_ffe mu_dfe],"DFEmu",0.005,"FFEmu",0,"plotfinal",0,"ideal_dfe",0);
|
||||||
|
|
||||||
|
dfe_results = ffe(eq_dfe,M,Scpe_sig,Symbols,Tx_bits,...
|
||||||
|
"precode_mode",duob_mode,...
|
||||||
|
'showAnalysis',0,...
|
||||||
|
"postFFE",[],...
|
||||||
|
"eth_style_symbol_mapping",0);
|
||||||
|
|
||||||
|
disp('DFE:')
|
||||||
|
dfe_results.metrics.print;
|
||||||
|
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
if use_vnle_mlse
|
||||||
|
|
||||||
|
if 0
|
||||||
|
pf_ncoeffs = 1;
|
||||||
|
eq_ = EQ("Ne",ffe_order,"Nb",dfe_order,"training_length",len_tr,"training_loops",5,"dd_loops",5,"K",2,"DCmu",mu_dc,"DDmu",[mu_ffe mu_dfe],"DFEmu",0.005,"FFEmu",0,"plotfinal",0,"ideal_dfe",1);
|
||||||
|
pf_ = Postfilter("ncoeff",pf_ncoeffs,"useBurg",1);
|
||||||
|
% mlse_ = MLSE_viterbi("duobinary_output",0,'M',M,'trellis_states',PAMmapper(M,0).levels);
|
||||||
|
mlse_ = MLSE("duobinary_output",0,'M',M,'trellis_states',PAMmapper(M,0).levels);
|
||||||
|
|
||||||
|
[ffe_results, mlse_results] = vnle_postfilter_mlse(eq_, pf_, mlse_, M, Scpe_sig, Symbols, Tx_bits, ...
|
||||||
|
"precode_mode", duob_mode,...
|
||||||
|
'showAnalysis', 1, ...
|
||||||
|
"postFFE", [],...
|
||||||
|
"eth_style_symbol_mapping", 0);
|
||||||
|
|
||||||
|
disp('VNLE:')
|
||||||
|
ffe_results.metrics.print;
|
||||||
|
disp('MLSE:')
|
||||||
|
mlse_results.metrics.print;
|
||||||
|
end
|
||||||
|
|
||||||
|
pf_ncoeffs = 2;
|
||||||
|
eq_ = EQ("Ne",ffe_order,"Nb",dfe_order,"training_length",len_tr,"training_loops",5,"dd_loops",5,"K",2,"DCmu",mu_dc,"DDmu",[mu_ffe mu_dfe],"DFEmu",0.005,"FFEmu",0,"plotfinal",0,"ideal_dfe",1);
|
||||||
|
pf_ = Postfilter("ncoeff",pf_ncoeffs,"useBurg",1);
|
||||||
|
% mlse_ = MLSE_viterbi("duobinary_output",0,'M',M,'trellis_states',PAMmapper(M,0).levels);
|
||||||
|
mlse_ = MLSE("duobinary_output",0,'M',M,'trellis_states',PAMmapper(M,0).levels);
|
||||||
|
|
||||||
|
[ffe_results, mlse_results] = vnle_postfilter_mlse(eq_, pf_, mlse_, M, Scpe_sig, Symbols, Tx_bits, ...
|
||||||
|
"precode_mode", duob_mode,...
|
||||||
|
'showAnalysis', 1, ...
|
||||||
|
"postFFE", [],...
|
||||||
|
"eth_style_symbol_mapping", 0);
|
||||||
|
|
||||||
|
disp('VNLE:')
|
||||||
|
ffe_results.metrics.print;
|
||||||
|
disp('MLSE:')
|
||||||
|
mlse_results.metrics.print;
|
||||||
|
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
if use_dbtgt
|
||||||
|
eq_ = EQ("Ne",ffe_order,"Nb",dfe_order,"training_length",len_tr,"training_loops",5,"dd_loops",5,"K",2,"DCmu",mu_dc,"DDmu",[mu_ffe mu_dfe],"DFEmu",0.005,"FFEmu",0,"plotfinal",0,"ideal_dfe",1);
|
||||||
|
|
||||||
|
mlse_db_ = MLSE("DIR",[1,1],"duobinary_output",0,"M",M,"trellis_states",PAMmapper(M,0).levels);
|
||||||
|
|
||||||
|
dbt_results = duobinary_target(eq_, mlse_db_, M, Scpe_sig, Symbols, Tx_bits, ...
|
||||||
|
"precode_mode", duob_mode, ...
|
||||||
|
'showAnalysis',1 ,...
|
||||||
|
"postFFE", []);
|
||||||
|
|
||||||
|
disp('DB:')
|
||||||
|
dbt_results.metrics.print;
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if duob_mode == db_mode.db_encoded
|
||||||
|
|
||||||
|
eq_db_enc = EQ("Ne", ffe_order, "Nb", dfe_order, "training_length", len_tr, ...
|
||||||
|
"training_loops", 5, "dd_loops", 5, "K", 2, "DCmu", mu_dc, ...
|
||||||
|
"DDmu", [mu_ffe mu_dfe], "DFEmu", 0.005, "FFEmu", 0, "plotfinal", 0, "ideal_dfe", 1);
|
||||||
|
|
||||||
|
mlse_db_enc = MLSE("DIR", [1,1], "duobinary_output", 0, "M", M, "trellis_states", PAMmapper(M,0).levels);
|
||||||
|
|
||||||
|
db_results = duobinary_signaling(eq_db_enc, mlse_db_enc, M, Scpe_sig, Symbols, Tx_bits, "precode_mode",duob_mode, "showAnalysis",1,"postFFE",[]);
|
||||||
|
|
||||||
|
db_results.metrics.print;
|
||||||
|
end
|
||||||
@@ -5,7 +5,7 @@ precomp_mode = 2; %0=do nothing ; 1= measure; 2=precomp active
|
|||||||
db_precode = 0;
|
db_precode = 0;
|
||||||
db_coding_approach = 0;
|
db_coding_approach = 0;
|
||||||
|
|
||||||
fsym = 224e9;
|
fsym = 160e9;
|
||||||
fdac = 256e9;
|
fdac = 256e9;
|
||||||
random_key = 0;
|
random_key = 0;
|
||||||
M = 4;
|
M = 4;
|
||||||
@@ -58,8 +58,7 @@ end
|
|||||||
|
|
||||||
|
|
||||||
rcalpha = 0.05;
|
rcalpha = 0.05;
|
||||||
Pform = Pulseformer("fsym",fsym,"fdac",4*fsym,"pulse","rrc","pulselength",16,"rrcalpha",rcalpha);
|
Pform = Pulseformer("fsym",fsym,"fdac",4*fsym,"pulse","rrc","pulselength",16,"alpha",rcalpha);
|
||||||
|
|
||||||
|
|
||||||
Pamsource = PAMsource(...
|
Pamsource = PAMsource(...
|
||||||
"fsym",fsym,"M",M,"order",19,"useprbs",1,...
|
"fsym",fsym,"M",M,"order",19,"useprbs",1,...
|
||||||
@@ -83,7 +82,9 @@ Digi_sig = precomp_est.precomp(Digi_sig,'maxampdb',precomp_amp_max,'loadPath',pr
|
|||||||
Digi_sig = Digi_sig.normalize("mode","rms");
|
Digi_sig = Digi_sig.normalize("mode","rms");
|
||||||
|
|
||||||
Digi_sig = Digi_sig.resample("fs_out",fdac);
|
Digi_sig = Digi_sig.resample("fs_out",fdac);
|
||||||
|
|
||||||
Digi_sig= Digi_sig.normalize("mode","rms");
|
Digi_sig= Digi_sig.normalize("mode","rms");
|
||||||
|
|
||||||
Digi_sig.spectrum("displayname","Strong Precomp","fignum",2223,"normalizeToNyquist",0,"normalizeTo0dB",0);
|
Digi_sig.spectrum("displayname","Strong Precomp","fignum",2223,"normalizeToNyquist",0,"normalizeTo0dB",0);
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
filename = "C:\Users\sioe\Documents\High_Speed_Measurement_2024\bias_5km\PAMX_5km_20241025_204334_wh.mat";
|
filename = "Z:\2024\sioe\High Speed Messungen Oktober\bias_5km\PAMX_5km_20241025_204334_wh.mat";
|
||||||
|
|
||||||
a = load(filename);
|
a = load(filename);
|
||||||
wh = a.obj;
|
wh = a.obj;
|
||||||
@@ -95,7 +95,7 @@ end
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
filename = "C:\Users\sioe\Documents\High_Speed_Measurement_2024\bias_testing_and_b2b\PAM4_b2b_bias_sweep_20241023_191202_wh_BB_BIAS_FINAL.mat";
|
filename = "Z:\2024\sioe\High Speed Messungen Oktober\bias_testing_and_b2b\PAM4_b2b_bias_sweep_20241023_191202_wh_BB_BIAS_FINAL.mat";
|
||||||
|
|
||||||
a = load(filename);
|
a = load(filename);
|
||||||
wh = a.obj;
|
wh = a.obj;
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
|
|
||||||
|
|
||||||
basePath = 'C:\Users\Silas\Documents\MATLAB\Datensätze\sioe_labor\';
|
basePath = 'C:\Users\Silas\Documents\MATLAB\Datensätze\sioe_labor\';
|
||||||
database = DBHandler("pathToDB",[basePath,'silas_labor.db'],"type",'sqlite');
|
database = DBHandler("dataBase",[basePath,'silas_labor.db'],"type",'sqlite');
|
||||||
|
|
||||||
filterParams = database.tables;
|
filterParams = database.tables;
|
||||||
filterParams.Configurations = struct( ...
|
filterParams.Configurations = struct( ...
|
||||||
'bitrate', [], ... %[224,336,360,390,420,448]
|
'bitrate', [390e9], ... %[224,336,360,390,420,448]
|
||||||
'db_mode', [], ...
|
'db_mode', 1, ...
|
||||||
'fiber_length', 1, ...
|
'fiber_length', 1, ...
|
||||||
'interference_attenuation', [], ...
|
'interference_attenuation', [], ...
|
||||||
'interference_path_length', [], ...
|
'interference_path_length', [], ...
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
function [output] = imdd_model(varargin)
|
function [output] = imdd_model(varargin)
|
||||||
|
|
||||||
simulation_mode = 0;
|
simulation_mode = 1;
|
||||||
|
|
||||||
%%% Change folder
|
%%% Change folder
|
||||||
curFolder = pwd;
|
curFolder = pwd;
|
||||||
|
|||||||
@@ -1,33 +1,24 @@
|
|||||||
%%% Run parameters
|
%%% Run parameters
|
||||||
% TX
|
% TX
|
||||||
M = 4;
|
M = 4;
|
||||||
fsym = 180e9;
|
fsym = 112e9;
|
||||||
|
|
||||||
apply_pulsef = 1;
|
apply_pulsef = 1;
|
||||||
fdac = 256e9;
|
fdac = 256e9;
|
||||||
fadc = 256e9;
|
fadc = 256e9;
|
||||||
random_key = 1;
|
random_key = 2;
|
||||||
|
|
||||||
db_precode = 0;
|
|
||||||
db_encode = 0;
|
|
||||||
|
|
||||||
rcalpha = 0.05;
|
rcalpha = 0.05;
|
||||||
kover = 16;
|
kover = 16;
|
||||||
vbias_rel = 0.5;
|
vbias_rel = 0.5;
|
||||||
u_pi = 2.9;
|
u_pi = 2.9;
|
||||||
vbias = -vbias_rel*u_pi;
|
vbias = -vbias_rel*u_pi;
|
||||||
laser_wavelength = 1310;
|
laser_wavelength = 1290;
|
||||||
laser_linewidth = 0;
|
laser_linewidth = 0;
|
||||||
tx_bw_nyquist = 0.6;
|
|
||||||
rx_bw_nyquist = 0.6;
|
|
||||||
|
|
||||||
|
|
||||||
% Channel
|
% Channel
|
||||||
link_length = 1;
|
link_length = 10000;
|
||||||
|
|
||||||
% RX
|
|
||||||
rop = -8;
|
|
||||||
|
|
||||||
|
|
||||||
vnle_order1 = 50;
|
vnle_order1 = 50;
|
||||||
vnle_order2 = 3;
|
vnle_order2 = 3;
|
||||||
@@ -49,55 +40,13 @@ mu_dc = 0.005;
|
|||||||
mu_ffe = [mu_ffe1 mu_ffe3 mu_ffe3];
|
mu_ffe = [mu_ffe1 mu_ffe3 mu_ffe3];
|
||||||
mu_dfe = 0.0004;
|
mu_dfe = 0.0004;
|
||||||
|
|
||||||
|
|
||||||
dfe_ = sum(dfe_order)>0;
|
dfe_ = sum(dfe_order)>0;
|
||||||
|
|
||||||
doub_mode = db_mode.no_db;
|
doub_mode = db_mode.no_db;
|
||||||
|
|
||||||
|
rop = [-8];
|
||||||
Pform = Pulseformer("fsym",fsym,"fdac",4*fsym,"pulse","rc","pulselength",16,"alpha",rcalpha);
|
bwl = [0.5:0.1:1.5];
|
||||||
|
fsym = [128:16:170].*1e9;
|
||||||
db_precode = 0;
|
|
||||||
db_encode = 0;
|
|
||||||
duob_mode = db_mode.no_db;
|
|
||||||
apply_pulsef = 1;
|
|
||||||
[Digi_sig,Symbols,Tx_bits] = PAMsource(...
|
|
||||||
"fsym",fsym,"M",M,"order",18,"useprbs",0,...
|
|
||||||
"fs_out",fdac,...
|
|
||||||
"applyclipping",0,"clipfactor",1.5,...
|
|
||||||
"applypulseform",apply_pulsef,"pulseformer",Pform,...
|
|
||||||
"randkey",random_key,...
|
|
||||||
"db_precode",db_precode,"db_encode",db_encode,...
|
|
||||||
"mrds_code",0,"mrds_blocklength",512,"duobinary_mode",duob_mode).process();
|
|
||||||
|
|
||||||
Digi_sig.spectrum("displayname",'Digi Spectrum','fignum',10,'normalizeTo0dB',1);
|
|
||||||
|
|
||||||
|
|
||||||
%%%%% AWG
|
|
||||||
% El_sig = M8199A("kover",kover).process(Digi_sig);
|
|
||||||
El_sig = AWG("fdac",fdac,"f_cutoff",fsym,"lpf_active",0,"kover",kover,"bit_resolution",12,"upsampling_method","samplehold","precomp_sinc_rolloff",1).process(Digi_sig);
|
|
||||||
% El_sig.spectrum("displayname",'Digi Spectrum','fignum',100,'normalizeTo0dB',0);
|
|
||||||
% El_sig = El_sig.setPower(0,"dBm");
|
|
||||||
|
|
||||||
%%%%% Low-pass el. components %%%%%%
|
|
||||||
f_nyquist = fsym/2;
|
|
||||||
tx_bwl = tx_bw_nyquist.*f_nyquist;
|
|
||||||
% tx_bwl = 80e9;
|
|
||||||
El_sig = Filter('filtdegree',4,"f_cutoff",tx_bwl,"fs",fdac*kover,"filterType",filtertypes.butterworth,"active",true).process(El_sig);
|
|
||||||
% El_sig.spectrum("displayname",'Digi Spectrum','fignum',100,'normalizeTo0dB',1);
|
|
||||||
|
|
||||||
%%%%% Electrical Driver Amplifier %%%%%%
|
|
||||||
El_sig = Amplifier("amp_mode","ideal_no_noise","gain_mode","gain","amplification_db",3).process(El_sig);
|
|
||||||
El_sig = El_sig.normalize("mode","oneone");
|
|
||||||
|
|
||||||
%%%%% MODULATE E/O CONVERSION %%%%%%
|
|
||||||
[Opt_sig] = EML("mode",eml_mode.im_cosinus,"power",3,"fsimu",El_sig.fs,"lambda",laser_wavelength,"bias",vbias,"u_pi",u_pi,"linewidth",laser_linewidth,"randomkey",random_key+1).process(El_sig);
|
|
||||||
|
|
||||||
Opt_sig = Fiber("fsimu",Opt_sig.fs,"fiber_length",link_length/1000,"alpha",0.3,"D",0,"lambda0",1310,"gamma",0,"Dslope",0.07).process(Opt_sig);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
rop = [-10];
|
|
||||||
ber_vnle = [];
|
ber_vnle = [];
|
||||||
ber_mlse = [];
|
ber_mlse = [];
|
||||||
ber_viterbi = [];
|
ber_viterbi = [];
|
||||||
@@ -107,72 +56,122 @@ gmi_vnle = [];
|
|||||||
gmi_mlse = [];
|
gmi_mlse = [];
|
||||||
gmi_mlse_db = [];
|
gmi_mlse_db = [];
|
||||||
|
|
||||||
for r = 1:length(rop)
|
for r = 1:length(fsym)
|
||||||
|
|
||||||
|
Pform = Pulseformer("fsym",fsym(r),"fdac",4*fsym(r),"pulse","rc","pulselength",16,"alpha",rcalpha);
|
||||||
|
|
||||||
|
db_precode = 0;
|
||||||
|
db_encode = 0;
|
||||||
|
duob_mode = db_mode.no_db;
|
||||||
|
apply_pulsef = 1;
|
||||||
|
|
||||||
|
[Digi_sig,Symbols,Tx_bits] = PAMsource(...
|
||||||
|
"fsym",fsym(r),"M",M,"order",18,"useprbs",0,...
|
||||||
|
"fs_out",fdac,...
|
||||||
|
"applyclipping",0,"clipfactor",1.5,...
|
||||||
|
"applypulseform",apply_pulsef,"pulseformer",Pform,...
|
||||||
|
"randkey",random_key,...
|
||||||
|
"db_precode",db_precode,"db_encode",db_encode,...
|
||||||
|
"mrds_code",0,"mrds_blocklength",512,"duobinary_mode",duob_mode).process();
|
||||||
|
|
||||||
|
|
||||||
|
% Digi_sig.spectrum("displayname",'Digi Spectrum','fignum',10,'normalizeTo0dB',0);
|
||||||
|
|
||||||
|
|
||||||
|
%%%%% AWG
|
||||||
|
% El_sig = M8199A("kover",kover).process(Digi_sig);
|
||||||
|
El_sig = AWG("fdac",fdac,"f_cutoff",fsym(r),"lpf_active",0,"kover",kover,"bit_resolution",12,"upsampling_method","samplehold","precomp_sinc_rolloff",1).process(Digi_sig);
|
||||||
|
% El_sig.spectrum("displayname",'Digi Spectrum','fignum',100,'normalizeTo0dB',0);
|
||||||
|
% El_sig = El_sig.setPower(0,"dBm");
|
||||||
|
|
||||||
|
%%%%% Low-pass el. components %%%%%%
|
||||||
|
% f_nyquist = fsym/2;
|
||||||
|
% tx_bwl = tx_bw_nyquist.*f_nyquist;
|
||||||
|
tx_bwl = 50e9;
|
||||||
|
El_sig = Filter('filtdegree',4,"f_cutoff",tx_bwl,"fs",fdac*kover,"filterType",filtertypes.butterworth,"active",true).process(El_sig);
|
||||||
|
% El_sig.spectrum("displayname",'Digi Spectrum','fignum',100,'normalizeTo0dB',1);
|
||||||
|
|
||||||
|
%%%%% Electrical Driver Amplifier %%%%%%
|
||||||
|
El_sig = Amplifier("amp_mode","ideal_no_noise","gain_mode","gain","amplification_db",3).process(El_sig);
|
||||||
|
El_sig = El_sig.normalize("mode","oneone");
|
||||||
|
|
||||||
|
%%%%% MODULATE E/O CONVERSION %%%%%%
|
||||||
|
[Opt_sig] = EML("mode",eml_mode.im_cosinus,"power",3,"fsimu",El_sig.fs,"lambda",laser_wavelength,"bias",vbias,"u_pi",u_pi,"linewidth",laser_linewidth,"randomkey",random_key+1).process(El_sig);
|
||||||
|
|
||||||
|
Opt_sig = Fiber("fsimu",Opt_sig.fs,"fiber_length",link_length/1000,"alpha",0.3,"D",0,"lambda0",1310,"gamma",0,"Dslope",0.07).process(Opt_sig);
|
||||||
|
|
||||||
%%%%%% ROP %%%%%%
|
%%%%%% ROP %%%%%%
|
||||||
Rx_sig = Amplifier("amp_mode","ideal_no_noise","gain_mode","output_power","amplification_db",rop(r)).process(Opt_sig);
|
Rx_sig = Amplifier("amp_mode","ideal_no_noise","gain_mode","output_power","amplification_db",rop).process(Opt_sig);
|
||||||
|
|
||||||
%%%%%% PD Square Law %%%%%%
|
%%%%%% PD Square Law %%%%%%
|
||||||
Rx_sig = Photodiode("fsimu",fdac*kover,"dark_current",2e-08,"responsivity",1,"temperature",20,"nep",1.8e-11).process(Rx_sig);
|
Rx_sig = Photodiode("fsimu",fdac*kover,"dark_current",2e-08,"responsivity",1,"temperature",20,"nep",1.8e-11).process(Rx_sig);
|
||||||
|
|
||||||
%%%%%% Low-pass RX (PD, El. Connectors and Scope %%%%%%
|
%%%%%% Low-pass RX (PD, El. Connectors and Scope %%%%%%
|
||||||
rx_bwl = rx_bw_nyquist.*f_nyquist;
|
% rx_bwl = rx_bw_nyquist.*f_nyquist;
|
||||||
% rx_bwl = 80e9;
|
rx_bwl = 50e9;
|
||||||
Rx_sig = Filter('filtdegree',4,"f_cutoff",rx_bwl,"fs",fdac*kover,"filterType",filtertypes.butterworth,"active",true).process(Rx_sig);
|
Rx_sig = Filter('filtdegree',4,"f_cutoff",rx_bwl,"fs",fdac*kover,"filterType",filtertypes.butterworth,"active",true).process(Rx_sig);
|
||||||
|
|
||||||
% %%%%%% Low-pass Scope %%%%%%
|
% %%%%%% Low-pass Scope %%%%%%
|
||||||
Lp_scpe = Filter('filtdegree',4,"f_cutoff",110e9,"fs",fadc,"filterType",filtertypes.butterworth,"active",true);
|
Lp_scpe = Filter('filtdegree',4,"f_cutoff",110e9,"fs",fadc,"filterType",filtertypes.butterworth,"active",true);
|
||||||
|
|
||||||
% Rx_sig.spectrum("displayname",'Analog Rx Spectrum','fignum',100,'normalizeTo0dB',1);
|
% Rx_sig.spectrum("displayname",'Analog Rx Spectrum','fignum',100,'normalizeTo0dB',1);
|
||||||
|
%
|
||||||
%%%%%% Scope %%%%%%
|
%%%%%% Scope %%%%%%
|
||||||
Scpe_sig = Scope("fsimu",fdac*kover,"fadc",fadc,...
|
Scpe_sig = Scope("fsimu",fdac*kover,"fadc",fadc,...
|
||||||
"delay",0,"fixed_delay",0,"filtertype",filtertypes.butterworth,...
|
"delay",0,"fixed_delay",0,"filtertype",filtertypes.butterworth,...
|
||||||
"samplingdelay",0,"rand_samplingdelay",0,"freq_offset",0,"samp_jitter",0,...
|
"samplingdelay",0,"rand_samplingdelay",0,"freq_offset",0,"samp_jitter",0,...
|
||||||
"adcresolution",8,"quantbuffer",0.1,'block_dc',1,'lpf_active',1,'H_lpf',Lp_scpe).process(Rx_sig);
|
"adcresolution",8,"quantbuffer",0.1,'block_dc',1,'lpf_active',0,'H_lpf',Lp_scpe).process(Rx_sig);
|
||||||
|
|
||||||
Scpe_sig_resampled = Scpe_sig.resample("fs_out",2*fsym);
|
Scpe_sig_resampled = Scpe_sig.resample("fs_out",2*fsym(r));
|
||||||
|
% Scpe_sig_resampled.signal = Scpe_sig_resampled.signal(1:2*length(Symbols));
|
||||||
|
|
||||||
[~, Scpe_cell, ~, found_sync] = Scpe_sig_resampled.tsynch("reference", Symbols, "fs_ref", fsym, "debug_plots", 1);
|
[~, Scpe_cell, ~, found_sync] = Scpe_sig_resampled.tsynch("reference", Symbols, "fs_ref", fsym(r), "debug_plots", 1);
|
||||||
|
% Scpe_cell = cell(1);
|
||||||
|
% Scpe_cell{1} = Scpe_sig_resampled;
|
||||||
|
|
||||||
|
Scpe_cell{1}.spectrum("displayname",'Analog Rx Spectrum','fignum',100,'normalizeTo0dB',1);
|
||||||
|
|
||||||
eq_ = EQ("Ne",[vnle_order1,vnle_order2,vnle_order3],"Nb",[dfe_order],"training_length",len_tr,"training_loops",5,"dd_loops",5,"K",2,"DCmu",mu_dc,"DDmu",[mu_ffe mu_dfe],"DFEmu",0.005,"FFEmu",0,"plotfinal",0,"ideal_dfe",1);
|
eq_ = EQ("Ne",[vnle_order1,vnle_order2,vnle_order3],"Nb",[dfe_order],"training_length",len_tr,"training_loops",5,"dd_loops",5,"K",2,"DCmu",mu_dc,"DDmu",[mu_ffe mu_dfe],"DFEmu",0.005,"FFEmu",0,"plotfinal",0,"ideal_dfe",1);
|
||||||
mlse_ = MLSE("DIR",[1,1],"duobinary_output",0,"M",M,"trellis_states",PAMmapper(M,0).levels);
|
mlse_ = MLSE("DIR",[1,1],"duobinary_output",0,"M",M,"trellis_states",PAMmapper(M,0).levels);
|
||||||
|
|
||||||
|
|
||||||
%Duobinary Targeting
|
|
||||||
if 0
|
if 0
|
||||||
db_ref_sequence = Duobinary().encode(Symbols);
|
%Duobinary Targeting
|
||||||
db_ref_constellation = unique(db_ref_sequence.signal);
|
db_ref_sequence = Duobinary().encode(Symbols);
|
||||||
[eq_signal, eq_noise] = eq_.process(Scpe_cell{1},db_ref_sequence);
|
db_ref_constellation = unique(db_ref_sequence.signal);
|
||||||
|
[eq_signal, eq_noise] = eq_.process(Scpe_cell{1},db_ref_sequence);
|
||||||
|
|
||||||
mlse_.DIR = [1,1];
|
mlse_.DIR = [1,1];
|
||||||
[mlse_sig_sd,LLR,gmi_mlse_db(r)] = mlse_.process(eq_signal,Symbols);
|
[mlse_sig_sd,LLR,gmi_mlse_db(r)] = mlse_.process(eq_signal,Symbols);
|
||||||
|
|
||||||
mlse_sig_hd = PAMmapper(M,0,"eth_style",0).quantize(mlse_sig_sd);
|
mlse_sig_hd = PAMmapper(M,0,"eth_style",0).quantize(mlse_sig_sd);
|
||||||
mlse_sig_hd_precoded = Duobinary().encode(mlse_sig_hd,"M",M);
|
mlse_sig_hd_precoded = Duobinary().encode(mlse_sig_hd,"M",M);
|
||||||
mlse_sig_hd_precoded = Duobinary().decode(mlse_sig_hd_precoded,"M",M);
|
mlse_sig_hd_precoded = Duobinary().decode(mlse_sig_hd_precoded,"M",M);
|
||||||
|
|
||||||
tx_symbols_precoded = Duobinary().encode(Symbols);
|
tx_symbols_precoded = Duobinary().encode(Symbols);
|
||||||
tx_symbols_precoded = Duobinary().decode(tx_symbols_precoded);
|
tx_symbols_precoded = Duobinary().decode(tx_symbols_precoded);
|
||||||
|
|
||||||
tx_bits_precoded = PAMmapper(M,0,"eth_style",0).demap(tx_symbols_precoded);
|
tx_bits_precoded = PAMmapper(M,0,"eth_style",0).demap(tx_symbols_precoded);
|
||||||
|
|
||||||
rx_bits_mlse = PAMmapper(M,0,"eth_style",0).demap(mlse_sig_hd_precoded);
|
rx_bits_mlse = PAMmapper(M,0,"eth_style",0).demap(mlse_sig_hd_precoded);
|
||||||
[~,errors_db_diff_precoded,ber_db_diff_precoded(r),~] = calc_ber(rx_bits_mlse.signal,tx_bits_precoded.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1);
|
[~,errors_db_diff_precoded,ber_db_diff_precoded(r),~] = calc_ber(rx_bits_mlse.signal,tx_bits_precoded.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1);
|
||||||
|
|
||||||
%B) Just determine BER
|
%B) Just determine BER
|
||||||
rx_bits_mlse = PAMmapper(M,0,"eth_style",0).demap(mlse_sig_hd);
|
rx_bits_mlse = PAMmapper(M,0,"eth_style",0).demap(mlse_sig_hd);
|
||||||
[bits_mlse,errors_mlse,ber_db(r),~] = calc_ber(rx_bits_mlse.signal,Tx_bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1);
|
[bits_mlse,errors_mlse,ber_db(r),~] = calc_ber(rx_bits_mlse.signal,Tx_bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1);
|
||||||
end
|
end
|
||||||
|
|
||||||
% FFE or VNLE
|
% FFE or VNLE
|
||||||
eq_ = EQ("Ne",[vnle_order1,vnle_order2,vnle_order3],"Nb",[dfe_order],"training_length",len_tr,"training_loops",5,"dd_loops",5,"K",2,"DCmu",mu_dc,"DDmu",[mu_ffe mu_dfe],"DFEmu",0.005,"FFEmu",0,"plotfinal",0,"ideal_dfe",1);
|
eq_ = EQ("Ne",[vnle_order1,vnle_order2,vnle_order3],"Nb",[dfe_order],"training_length",len_tr,"training_loops",5,"dd_loops",5,"K",2,"DCmu",mu_dc,"DDmu",[mu_ffe mu_dfe],"DFEmu",0.005,"FFEmu",0,"plotfinal",0,"ideal_dfe",1);
|
||||||
[eq_signal_sd, eq_noise] = eq_.process(Scpe_cell{1}, Symbols);
|
[eq_signal_sd, eq_noise] = eq_.process(Scpe_cell{1}, Symbols);
|
||||||
[gmi_vnle(r)] = calc_air(eq_signal_sd, Symbols, "skip_front", 100, "skip_end", 100);
|
[gmi_gomez(r)] = calc_air(eq_signal_sd, Symbols, "skip_front", 100, "skip_end", 100);
|
||||||
|
[gmi_vnle(r)] = calc_ngmi(eq_signal_sd,Symbols);
|
||||||
|
[gmi_bitwise(r)] = calc_gmi_bitwise(eq_signal_sd,Symbols);
|
||||||
|
|
||||||
|
snr_vnle(r) = calc_snr(Symbols, eq_signal_sd-Symbols);
|
||||||
eq_signal_sd.plot("displayname",'bla','fignum',118);
|
eq_signal_sd.plot("displayname",'bla','fignum',118);
|
||||||
|
|
||||||
|
|
||||||
% Hard decision on VNLE output
|
% Hard decision on VNLE output
|
||||||
eq_signal_hd = PAMmapper(M, 0).quantize(eq_signal_sd);
|
eq_signal_hd = PAMmapper(M, 0).quantize(eq_signal_sd);
|
||||||
rx_bits = PAMmapper(M,0,"eth_style",0).demap(eq_signal_hd);
|
rx_bits = PAMmapper(M,0,"eth_style",0).demap(eq_signal_hd);
|
||||||
@@ -180,6 +179,7 @@ for r = 1:length(rop)
|
|||||||
fprintf('BER VNLE: %.2e \n',ber_vnle(r));
|
fprintf('BER VNLE: %.2e \n',ber_vnle(r));
|
||||||
fprintf('NGMI VNLE: %.2f \n',gmi_vnle(r)./log2(M));
|
fprintf('NGMI VNLE: %.2f \n',gmi_vnle(r)./log2(M));
|
||||||
|
|
||||||
|
if 1
|
||||||
|
|
||||||
% Process through postfilter and MLSE
|
% Process through postfilter and MLSE
|
||||||
pf_ncoeffs = 1;
|
pf_ncoeffs = 1;
|
||||||
@@ -187,12 +187,13 @@ for r = 1:length(rop)
|
|||||||
mlse_ = MLSE("duobinary_output",0,'M',M,'trellis_states',PAMmapper(M,0).levels);
|
mlse_ = MLSE("duobinary_output",0,'M',M,'trellis_states',PAMmapper(M,0).levels);
|
||||||
[mlse_sig_sd,whitened_noise] = pf_.process(eq_signal_sd, eq_noise);
|
[mlse_sig_sd,whitened_noise] = pf_.process(eq_signal_sd, eq_noise);
|
||||||
mlse_.DIR = pf_.coefficients;
|
mlse_.DIR = pf_.coefficients;
|
||||||
|
alpha(r) = pf_.coefficients(2);
|
||||||
[signalclass_hd,LLR,gmi_mlse(r)] = mlse_.process(mlse_sig_sd,Symbols);
|
[signalclass_hd,LLR,gmi_mlse(r)] = mlse_.process(mlse_sig_sd,Symbols);
|
||||||
mlse_sig_hd = PAMmapper(M, 0, "eth_style", 0).quantize(signalclass_hd);
|
mlse_sig_hd = PAMmapper(M, 0, "eth_style", 0).quantize(signalclass_hd);
|
||||||
rx_bits = PAMmapper(M,0,"eth_style",0).demap(mlse_sig_hd);
|
rx_bits = PAMmapper(M,0,"eth_style",0).demap(mlse_sig_hd);
|
||||||
[~,~,ber_mlse(r),~] = calc_ber(rx_bits.signal,Tx_bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1);
|
[~,~,ber_mlse(r),~] = calc_ber(rx_bits.signal,Tx_bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1);
|
||||||
fprintf('BER: %.2e \n',ber_mlse(r));
|
fprintf('BER: %.2e \n',ber_mlse(r));
|
||||||
fprintf('NGMI MLSE: %.2f \n',gmi_mlse(r)./log2(M));
|
fprintf('GMI MLSE: %.5f \n',gmi_mlse(r));
|
||||||
|
|
||||||
|
|
||||||
% Process through postfilter and MLSE
|
% Process through postfilter and MLSE
|
||||||
@@ -205,23 +206,48 @@ for r = 1:length(rop)
|
|||||||
mlse_sig_hd = PAMmapper(M, 0, "eth_style", 0).quantize(mlse_sig_sd);
|
mlse_sig_hd = PAMmapper(M, 0, "eth_style", 0).quantize(mlse_sig_sd);
|
||||||
rx_bits = PAMmapper(M,0,"eth_style",0).demap(mlse_sig_hd);
|
rx_bits = PAMmapper(M,0,"eth_style",0).demap(mlse_sig_hd);
|
||||||
[~,~,ber_viterbi(r),~] = calc_ber(rx_bits.signal,Tx_bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1);
|
[~,~,ber_viterbi(r),~] = calc_ber(rx_bits.signal,Tx_bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1);
|
||||||
fprintf('FW BER: %.2e \n',ber_viterbi(r));
|
fprintf('Viterbi BER: %.2e \n',ber_viterbi(r));
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
cols = cbrewer2('Paired',8);
|
||||||
|
d = 1;
|
||||||
|
|
||||||
figure();hold on
|
figure(11);hold on
|
||||||
plot(rop,gmi_mlse,'DisplayName','MLSE','Marker','*');
|
plot(fsym.*1e-9,alpha,'DisplayName','VNLE','Marker','x','LineStyle','-','Color',cols(1+d,:));
|
||||||
plot(rop,gmi_vnle,'DisplayName','VNLE','Marker','*');
|
xlabel('Baudrate in GBd');
|
||||||
plot(rop,gmi_mlse_db,'DisplayName','MLSE DB Tgt','Marker','*');
|
ylabel('alpha');
|
||||||
|
|
||||||
|
figure(15);hold on
|
||||||
|
plot(fsym.*1e-9,gmi_gomez,'DisplayName','gomez','Marker','x','LineStyle','-','Color',cols(1+d,:));
|
||||||
|
plot(fsym.*1e-9,gmi_vnle,'DisplayName','vnle other','Marker','x','LineStyle','-','Color',cols(3+d,:));
|
||||||
|
plot(fsym.*1e-9,gmi_bitwise,'DisplayName','bitwise','Marker','x','LineStyle','--','Color',cols(5+d,:));
|
||||||
|
plot(fsym.*1e-9,gmi_mlse,'DisplayName','MLSE','Marker','*');
|
||||||
ylim([0 2.6]);
|
ylim([0 2.6]);
|
||||||
|
xlabel('Baudrate in GBd');
|
||||||
|
ylabel('GMI');
|
||||||
|
|
||||||
figure();hold on
|
|
||||||
plot(rop,ber_vnle,'DisplayName','VNLE');
|
|
||||||
|
|
||||||
plot(rop,ber_mlse,'DisplayName','MLSE','Marker','*');
|
figure(13);hold on
|
||||||
plot(rop,ber_viterbi,'DisplayName','Viterbi','Marker','*');
|
plot(fsym.*1e-9,ber_vnle,'DisplayName','VNLE','Marker','x','LineStyle','-','Color',cols(1+d,:));
|
||||||
plot(rop,ber_db_diff_precoded,'DisplayName','MLSE db diff','Marker','*');
|
plot(fsym.*1e-9,ber_mlse,'DisplayName','MLSE','Marker','x','LineStyle','-','Color',cols(3+d,:));
|
||||||
plot(rop,ber_db,'DisplayName','MLSE db','Marker','*');
|
plot(fsym.*1e-9,ber_viterbi,'DisplayName','Viterbi','Marker','x','LineStyle','--','Color',cols(5+d,:));
|
||||||
|
% plot(bwl,ber_db_diff_precoded,'DisplayName','MLSE db diff','Marker','.','MarkerSize',15,'LineStyle','-');
|
||||||
|
% plot(bwl,ber_db,'DisplayName','MLSE db','Marker','.','MarkerSize',15,'LineStyle','-');
|
||||||
|
xlabel('Baudrate in GBd');
|
||||||
|
ylabel('BER');
|
||||||
set(gca, 'yscale', 'log');
|
set(gca, 'yscale', 'log');
|
||||||
|
% ylim([1e-6 0.1]);
|
||||||
legend
|
legend
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
% Auxiliary nested helper for numerically stable log-sum-exp
|
||||||
|
function s = logsumexp(a)
|
||||||
|
% LOGSUMEXP Compute log(sum(exp(a))) in a numerically stable way
|
||||||
|
m = max(a);
|
||||||
|
s = m + log(sum(exp(a - m)));
|
||||||
|
end
|
||||||
|
|||||||
@@ -1,117 +0,0 @@
|
|||||||
% === SETTINGS ===
|
|
||||||
|
|
||||||
dsp_options.append_to_db = 1;
|
|
||||||
dsp_options.max_occurences = 15;
|
|
||||||
dsp_options.database_path = 'C:\Users\Silas\Documents\MATLAB\Datensätze\sioe_labor\';
|
|
||||||
dsp_options.database_name = 'silas_labor_newdsp_newstructure.db';
|
|
||||||
dsp_options.storage_path = 'Z:\2024\sioe_labor\';
|
|
||||||
dsp_options.parameters = struct();
|
|
||||||
dsp_options.parameters.mu_dc = [0.005];
|
|
||||||
|
|
||||||
% === Get Run ID's ===
|
|
||||||
db = DBHandler("pathToDB", [dsp_options.database_path, dsp_options.database_name], "type", "sqlite");
|
|
||||||
fp = QueryFilter();
|
|
||||||
% fp.where('Runs', 'run_id','EQUALS', 5108);
|
|
||||||
fp.where('Runs', 'is_mpi','EQUALS', 0);
|
|
||||||
% fp.where('Runs', 'fiber_length','EQUALS', 10);
|
|
||||||
fp.where('Runs', 'wavelength','EQUALS', 1310);
|
|
||||||
fp.where('Runs', 'db_mode','EQUALS', 1);
|
|
||||||
fp.where('Runs', 'rop_attenuation','EQUALS', 0);
|
|
||||||
fp.where('Runs', 'pam_level','EQUALS', 4);
|
|
||||||
% fp.where('Runs', 'bitrate','EQUALS', 360e9);
|
|
||||||
% fp.where('Runs', 'power_pd_in','GREATER_THAN', 7);
|
|
||||||
[dataTable,~] = db.queryDB(fp, db.getTableFieldNames('Runs'));
|
|
||||||
|
|
||||||
% === Initialize DataStorage ===
|
|
||||||
wh = DataStorage(dsp_options.parameters);
|
|
||||||
wh.addStorage("ffe_package");
|
|
||||||
wh.addStorage("mlse_package");
|
|
||||||
wh.addStorage("vnle_package");
|
|
||||||
wh.addStorage("dbtgt_package");
|
|
||||||
wh.addStorage("dbenc_package");
|
|
||||||
|
|
||||||
% === RUN IT ===
|
|
||||||
|
|
||||||
[results,wh] = submitJobs(dataTable.run_id(:), dsp_options, "parallel", 'wh', wh, 'waitbar', true);
|
|
||||||
% wh.getStoValue('ffe_package',0.005);
|
|
||||||
% wh.getStoValue('mlse_package',0.005);
|
|
||||||
|
|
||||||
[dataTable,~] = db.queryDB(fp, [db.getTableFieldNames('Runs');db.getTableFieldNames('Results');db.getTableFieldNames('Equalizer')]);
|
|
||||||
|
|
||||||
dataTable = cleanUpTable(dataTable);
|
|
||||||
|
|
||||||
% === Look at it ===
|
|
||||||
y_var = 'BER_precoded';
|
|
||||||
x_var = 'bitrate';
|
|
||||||
fixedVars = {'equalizer_structure', x_var};
|
|
||||||
|
|
||||||
[dataTableClean, outliersTable] = removeGroupOutliers(dataTable, fixedVars, y_var);
|
|
||||||
|
|
||||||
% --- Group and aggregate ---
|
|
||||||
dataTableGrpd_mean = groupIt(fixedVars, dataTableClean, @mean);
|
|
||||||
dataTableGrpd_min = groupIt(fixedVars, dataTableClean, @min);
|
|
||||||
dataTableGrpd_max = groupIt(fixedVars, dataTableClean, @max);
|
|
||||||
|
|
||||||
% Choose a color map
|
|
||||||
cols = linspecer(numel(unique(dataTableGrpd_mean.equalizer_structure)));
|
|
||||||
|
|
||||||
figure;
|
|
||||||
hold on;
|
|
||||||
|
|
||||||
% Get unique equalizer structures for grouping
|
|
||||||
unique_eq = unique(dataTableGrpd_mean.equalizer_structure);
|
|
||||||
|
|
||||||
for i = 1:numel(unique_eq)
|
|
||||||
eq_val = unique_eq(i);
|
|
||||||
|
|
||||||
% Filter grouped data for this equalizer structure
|
|
||||||
filt = dataTableGrpd_mean.equalizer_structure == eq_val;
|
|
||||||
|
|
||||||
x = dataTableGrpd_mean.(x_var)(filt);
|
|
||||||
y_mean = dataTableGrpd_mean.(y_var)(filt);
|
|
||||||
y_min = dataTableGrpd_min.(y_var)(filt);
|
|
||||||
y_max = dataTableGrpd_max.(y_var)(filt);
|
|
||||||
|
|
||||||
% Bounds for boundedline (distance from mean)
|
|
||||||
y_lower = y_mean - y_min;
|
|
||||||
y_upper = y_max - y_mean;
|
|
||||||
y_bounds = [y_lower, y_upper];
|
|
||||||
|
|
||||||
% --- Bounded line (mean ± min/max) ---
|
|
||||||
if exist('boundedline', 'file')
|
|
||||||
[hl, hp] = boundedline(x, y_mean, y_bounds, ...
|
|
||||||
'alpha', 'transparency', 0.1, ...
|
|
||||||
'cmap', cols(i,:), ...
|
|
||||||
'nan', 'fill', ...
|
|
||||||
'orientation', 'vert');
|
|
||||||
set(hl, 'LineWidth', 1.2, 'DisplayName', sprintf('Eq %s', eq_val));
|
|
||||||
set(hp, 'HandleVisibility', 'off');
|
|
||||||
else
|
|
||||||
% If boundedline is not available, use errorbar
|
|
||||||
errorbar(x, y_mean, y_lower, y_upper, ...
|
|
||||||
'o-', 'Color', cols(i,:), 'LineWidth', 1.2, ...
|
|
||||||
'DisplayName', sprintf('Eq %d', eq_val),'HandleVisibility', 'off');
|
|
||||||
end
|
|
||||||
|
|
||||||
% --- Normal line (mean only) ---
|
|
||||||
plot(x, y_mean, '-', 'Color', cols(i,:), 'LineWidth', 1.5, ...
|
|
||||||
'DisplayName', sprintf('Mean Eq %s', eq_val),'HandleVisibility', 'off');
|
|
||||||
|
|
||||||
% --- Scatter plot for individual points (from original data) ---
|
|
||||||
% Filter original data for this group
|
|
||||||
orig_filt = dataTableClean.equalizer_structure == eq_val;
|
|
||||||
x_scatter = dataTableClean.(x_var)(orig_filt);
|
|
||||||
y_scatter = dataTableClean.(y_var)(orig_filt);
|
|
||||||
|
|
||||||
scatter(x_scatter, y_scatter, 10,cols(i,:), 'filled', ...
|
|
||||||
'MarkerFaceAlpha', 0.5, 'DisplayName', sprintf('Scatter Eq %s', eq_val),'HandleVisibility', 'off');
|
|
||||||
end
|
|
||||||
|
|
||||||
yline([2.2e-4,4.85e-3,2e-2],'HandleVisibility', 'off','LineWidth',1,'LineStyle','--');
|
|
||||||
set(gca, 'YScale', 'log'); % BER is usually plotted log-scale
|
|
||||||
xlabel(x_var, 'Interpreter', 'none');
|
|
||||||
ylabel(y_var, 'Interpreter', 'none');
|
|
||||||
legend('show', 'Location', 'best');
|
|
||||||
grid on;
|
|
||||||
title(sprintf('%s vs. %s', y_var, x_var), 'Interpreter', 'none');
|
|
||||||
hold off;
|
|
||||||
@@ -1,116 +0,0 @@
|
|||||||
dsp_options.append_to_db = false;
|
|
||||||
dsp_options.max_occurences = 1;
|
|
||||||
dsp_options.mode = "load_run_id";
|
|
||||||
experiment = "highspeed_2024";
|
|
||||||
|
|
||||||
if dsp_options.mode == "load_run_id"
|
|
||||||
|
|
||||||
dsp_options.load_file_path = [];
|
|
||||||
if experiment == 'highspeed_2024'
|
|
||||||
|
|
||||||
dsp_options.database_path = 'C:\Users\Silas\Documents\MATLAB\Datensätze\sioe_labor\silas_labor_newdsp_newstructure.db';
|
|
||||||
dsp_options.storage_path = 'Z:\2024\sioe_labor\';
|
|
||||||
db = DBHandler("pathToDB", [dsp_options.database_path], "type", "sqlite");
|
|
||||||
|
|
||||||
elseif 'mpi_ecoc_2025'
|
|
||||||
|
|
||||||
dsp_options.database_path = []; %sqlite im netzwerk
|
|
||||||
dsp_options.storage_path = 'Z:\2025\ECOC Silas\ecoc_2025\';
|
|
||||||
db = DBHandler("pathToDB", [dsp_options.database_path], "type", "mysql");
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
elseif dsp_options.mode == "load_files"
|
|
||||||
|
|
||||||
dsp_options.load_file_path.tx_bits_path = "Z:\2025\ECOC Silas\ecoc_2025\mpi_opti_1000m_pam2 4 6 8\20250417_091513_PAM_4_R_112_bits.mat"';
|
|
||||||
dsp_options.load_file_path.tx_symbols_path = "Z:\2025\ECOC Silas\ecoc_2025\mpi_opti_1000m_pam2 4 6 8\20250417_091513_PAM_4_R_112_symbols.mat"';
|
|
||||||
dsp_options.load_file_path.rx_raw_path = "Z:\2025\ECOC Silas\ecoc_2025\mpi_opti_1000m_pam2 4 6 8\20250417_091525_PAM_4_R_112_rec01_rx_signal_raw.mat"';
|
|
||||||
|
|
||||||
elseif dsp_options.mode == "simulate"
|
|
||||||
|
|
||||||
error('Not yet implemented')
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
%% === Define Database Filters ===
|
|
||||||
|
|
||||||
if experiment == 'highspeed_2024'
|
|
||||||
|
|
||||||
fp = QueryFilter();
|
|
||||||
db = db.getDistinctValues;
|
|
||||||
%fp.where('Runs', 'run_id','EQUALS', 3);
|
|
||||||
fp.where('Runs', 'pam_level','EQUALS', 4);
|
|
||||||
allrates = string(num2str(sort(db.distinctValues.Runs.bitrate.*1e-9)));
|
|
||||||
fp.where('Runs', 'bitrate','EQUALS',390e9);
|
|
||||||
alllengths = string(num2str(sort(db.distinctValues.Runs.fiber_length)));
|
|
||||||
fp.where('Runs', 'fiber_length','EQUALS', 1);
|
|
||||||
fp.where('Runs', 'is_mpi','EQUALS', 0);
|
|
||||||
% fp.where('Runs', 'interference_path_length','EQUALS', 1000);
|
|
||||||
% fp.where('Runs', 'loop_id','GREATER_THAN', 11);
|
|
||||||
% fp.where('Runs', 'sir','EQUALS',18);
|
|
||||||
fp.where('Runs', 'wavelength','EQUALS', 1310);
|
|
||||||
fp.where('Runs', 'db_mode','EQUALS', 0);
|
|
||||||
% fp.where('Runs', 'rop_attenuation','EQUALS', 0);
|
|
||||||
fp.where('Runs', 'power_pd_in','GREATER_THAN', 7);
|
|
||||||
|
|
||||||
elseif experiment == 'mpi_ecoc_2025'
|
|
||||||
|
|
||||||
fp = QueryFilter();
|
|
||||||
%fp.where('Runs', 'run_id','EQUALS', 3);
|
|
||||||
fp.where('Runs', 'pam_level','EQUALS', 4);
|
|
||||||
fp.where('Runs', 'bitrate','EQUALS',224e9);
|
|
||||||
fp.where('Runs', 'is_mpi','EQUALS', 1);
|
|
||||||
fp.where('Runs', 'interference_path_length','EQUALS', 1000);
|
|
||||||
% fp.where('Runs', 'loop_id','GREATER_THAN', 11);
|
|
||||||
fp.where('Runs', 'sir','EQUALS',18);
|
|
||||||
fp.where('Runs', 'wavelength','EQUALS', 1310);
|
|
||||||
fp.where('Runs', 'db_mode','EQUALS', 0);
|
|
||||||
% fp.where('Runs', 'rop_attenuation','EQUALS', 0);
|
|
||||||
fp.where('Runs', 'power_pd_in','GREATER_THAN', 7);
|
|
||||||
% fp.where('Runs', 'loop_id','EQUALS', 14);
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
% === Queue from DB ===
|
|
||||||
[dataTable,~] = db.queryDB(fp, db.getTableFieldNames('Runs'));
|
|
||||||
|
|
||||||
% === Adapt or filter Matlab Table ===
|
|
||||||
% [~, unique_indices] = unique(dataTable.sir, 'first');
|
|
||||||
% dataTable = dataTable(unique_indices, :);
|
|
||||||
|
|
||||||
|
|
||||||
% === Set LOOPS & Initialize DataStorage ===
|
|
||||||
dsp_options.parameters = struct();
|
|
||||||
% dsp_options.parameters.adaption = [3];
|
|
||||||
% dsp_options.parameters.mu_tr = 0.999;%[0,logspace(-4,0,10)];
|
|
||||||
% dsp_options.parameters.mu_dd = [logspace(-0.004,0,20)];
|
|
||||||
% dsp_options.parameters.use_dd_mode = [1];
|
|
||||||
|
|
||||||
wh = DataStorage(dsp_options.parameters);
|
|
||||||
wh.addStorage("ffe_package");
|
|
||||||
wh.addStorage("mlse_package");
|
|
||||||
wh.addStorage("vnle_package");
|
|
||||||
wh.addStorage("dbtgt_package");
|
|
||||||
wh.addStorage("dbenc_package");
|
|
||||||
|
|
||||||
|
|
||||||
% === RUN IT ===
|
|
||||||
% run this function: dsp_runid(run_id, options)
|
|
||||||
[results,wh] = submitJobs(dataTable.run_id, dsp_options, "serial", 'wh', wh, 'waitbar', false);
|
|
||||||
|
|
||||||
|
|
||||||
%%
|
|
||||||
BERs = cellfun(@(c) c.ffe_package{1,1}.metrics.BER, results);
|
|
||||||
figure
|
|
||||||
hold on
|
|
||||||
plot(dsp_options.parameters.mu_dd,BERs,'Marker','+')
|
|
||||||
yline([2.2e-4,4.85e-3,2e-2],'HandleVisibility', 'off','LineWidth',1,'LineStyle','--');
|
|
||||||
set(gca, 'YScale', 'log'); % BER is usually plotted log-scale
|
|
||||||
xlabel('$\mu$ DD', 'Interpreter', 'latex');
|
|
||||||
ylabel('BER', 'Interpreter', 'latex');
|
|
||||||
legend('show', 'Location', 'best');
|
|
||||||
grid on;
|
|
||||||
hold off;
|
|
||||||
@@ -6,3 +6,11 @@ precomp_filename = "lab_high_speed";
|
|||||||
freqresp = ChannelFreqResp("Nacq",1024,"Navg",64,"Ncp",63,'f_ref',92e9);
|
freqresp = ChannelFreqResp("Nacq",1024,"Navg",64,"Ncp",63,'f_ref',92e9);
|
||||||
freqresp.load('loadPath',precomp_path,'fileName',precomp_filename);
|
freqresp.load('loadPath',precomp_path,'fileName',precomp_filename);
|
||||||
freqresp.plot();
|
freqresp.plot();
|
||||||
|
|
||||||
|
|
||||||
|
freqresp = ChannelFreqResp("Nacq",1024,"Navg",64,"Ncp",63,'f_ref',256e9);
|
||||||
|
precomp_path = "C:\Users\Silas\Documents\MATLAB\imdd_simulation\projects\HighSpeedExperiment_2024\Auswertung_JLT";
|
||||||
|
precomp_fn = "precomp_simulated.mat";
|
||||||
|
|
||||||
|
freqresp.load('loadPath',precomp_path,'fileName',precomp_fn);
|
||||||
|
freqresp.plot();
|
||||||
Reference in New Issue
Block a user