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:
Silas Oettinghaus
2025-08-11 07:42:04 +02:00
parent 09d9e5011c
commit 5dbc48abc0
37 changed files with 1506 additions and 570 deletions

View File

@@ -269,6 +269,7 @@ classdef Signal
SignalPower = [obj.power];
Nase = [0];
SignalCopy = obj.signal;
SignalCopy = [];
ModifierName = class(CallingModifier);
@@ -365,7 +366,7 @@ classdef Signal
if options.normalizeTo0dB
p_lin = p_lin./ max(p_lin);
p_dbm = 10*log10(p_lin); % normalized to 0 dB
ylab = "normalized to 0 dB";
ylab = "Normalized PSD";
else
p_dbm = 10*log10(p_lin);
ylab = "Power (dB/Hz)";
@@ -395,7 +396,7 @@ classdef Signal
if options.normalizeToNyquist == 0
xlabel("Frequency in GHz");
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([-128 128]);%256GSa/s
else
@@ -406,13 +407,20 @@ classdef Signal
ylabel(ylab);
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
ylim([floor(min(p_dbm))-3, ceil(max(p_dbm))+3]);
ylim([floor(min(p_dbm))-3, ceil(max(p_dbm))+3]);
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);
grid on; grid minor;
grid on;% grid minor;
legend
% legend('Interpreter','none');
@@ -912,8 +920,8 @@ classdef Signal
elseif mode == 1
% generate eye diagram using histogram
maxA = max(sig(100:end-100))*2;
minA = min(sig(100:end-100))*2;
maxA = max(sig(100:end-100))*1.3;
minA = min(sig(100:end-100))*1.3;
% maxA = 0.0015;
% minA = 0;
@@ -926,8 +934,8 @@ classdef Signal
nn=histcounts(data_ind_y(n,:),1:histpoints+1);
hist_data(:,n)=flip(nn.'); %without flip, the eye is upside down :-(
end
ax = gca;
plot_data = 20*log10(hist_data);
plot_data(plot_data==-Inf) = 0;
@@ -944,27 +952,29 @@ classdef Signal
if isa(obj,'Opticalsignal')
title(['Optical Eye ',options.displayname])
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);
max_ = abs(max(obj.signal(100:end-100)).^2);
elseif isa(obj,'Electricalsignal')
title(['Electrical Eye ',options.displayname])
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));
max_ = abs(max(obj.signal(100:end-100)));
else
title(['Digital Eye ',options.displayname])
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));
max_ = abs(max(obj.signal(100:end-100)));
end
xlabel('Time in ps')
% add information
if 0
if 1
pwr_dbm = round(obj.power,3);
pwr_lin = obj.power("unit",power_notation.W);
@@ -1073,13 +1083,15 @@ classdef Signal
end
yticks(linspace(0,histpoints,16));
yticks(linspace(0,histpoints,6));
y_tickstring = sprintfc('%.2f', 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);
xticklabels(x_tickstring);
grid off
end

View File

@@ -17,7 +17,7 @@ classdef M8199B < AWG
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,...
"bit_resolution",5.5,"normalize2dac",1,"upsampling_method","samplehold");

View File

@@ -136,6 +136,13 @@ classdef PAMsource
%%%%%% 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
case db_mode.no_db

View File

@@ -1,189 +1,171 @@
classdef Fiber
%FIBER Summary of this class goes here
% Detailed explanation goes here
% Fiber: Simulate optical fiber signal propagation using
% the split-step Fourier method (SSFM).
properties
% Simulation sampling frequency [Hz]
fsimu
% Fiber length [m]
fiber_length
% Attenuation coefficient [dB/km]
alpha
% Dispersion parameter D [s/m^2]
D
% Dispersion slope [s/m^3]
Dslope
% Reference wavelength [m]
lambda0
% Nonlinear coefficient [1/(W·m)]
gamma
% Maximum allowed nonlinear phase change per step [rad]
dphimax
% Derived parameters:
% Second-order dispersion coefficient β2 [s^2/m]
b2
% Third-order dispersion coefficient β3 [s^3/m]
b3
% Linear attenuation constant [1/m]
alpha_lin
% Frequency-domain linear operator per unit length
linstep
end
methods
function obj = Fiber(options)
%FIBER Construct an instance of this class
% Detailed explanation goes here
% Constructor: initialize fiber physical and simulation parameters.
arguments
options.fsimu
options.fiber_length = 0
options.alpha = 0.2
options.D = 17
options.Dslope = 0.06
options.lambda0 = 1550
options.gamma = 0
options.dphimax = 5e-3
options.fsimu % Sampling frequency [Hz]
options.fiber_length = 0 % Fiber length [km]
options.alpha = 0.2 % Attenuation [dB/km]
options.D = 17 % Dispersion D parameter [ps/(nm·km)]
options.Dslope = 0.06 % Dispersion slope [ps/(nm^2·km)]
options.lambda0 = 1550 % Reference wavelength [nm]
options.gamma = 0 % Nonlinear coefficient [1/(W·km)]
options.dphimax = 5e-3 % Max phase step [rad]
end
obj.fsimu = options.fsimu;
obj.fiber_length = options.fiber_length*1000; %km
obj.alpha = options.alpha;
obj.D = options.D*1e-6;
obj.Dslope = options.Dslope*1e3;
obj.lambda0 = options.lambda0*1e-9;
obj.gamma = options.gamma;
obj.dphimax = options.dphimax;
% Assign inputs to object properties, converting units to SI.
obj.fsimu = options.fsimu;
obj.fiber_length = options.fiber_length * 1e3; % km m
obj.alpha = options.alpha;
obj.D = options.D * 1e-6; % ps/(nm·km) s/(m·m)
obj.Dslope = options.Dslope * 1e3; % ps/(nm^2·km) s/m^2
obj.lambda0 = options.lambda0 * 1e-9; % nm m
obj.gamma = options.gamma; % 1/(W·km) (assumed 1/(W·m) internally)
obj.dphimax = options.dphimax;
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.)
signalclass_in = obj.process_(signalclass_in);
% Run internal split-step propagation
signalclass = obj.process_(signalclass_in);
% append to logbook
lbdesc = 'Fiber ';
signalclass_in = signalclass_in.logbookentry(lbdesc);
% write to output
signalclass_out = signalclass_in;
% Add entry to logbook for tracking
signalclass = signalclass.logbookentry('Fiber ');
% Return processed signal class
signalclass_out = signalclass;
end
function opt_sig = process_(obj,opt_sig)
%METHOD1 Summary of this method goes here
% Detailed explanation goes here
function opt_sig = process_(obj, opt_sig)
% process_: Internal routine for one-step fiber propagation.
% 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;
obj.D = obj.D + (lambda_signal-obj.lambda0)*obj.Dslope;
obj.b2 = -obj.D*lambda_signal^2/(2*pi*Constant.LightSpeed);
obj.b3 = ((lambda_signal.^2/(2*pi*Constant.LightSpeed)).^2*obj.Dslope);
obj.alpha_lin = obj.alpha/10*log(10)/1000;
% Update dispersion parameter D for current wavelength
obj.D = obj.D + (lambda_signal - obj.lambda0) * obj.Dslope;
% Compute dispersion coefficients (β2, β3)
obj.b2 = -obj.D * lambda_signal^2 / (2 * pi * Constant.LightSpeed);
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);
faxis = linspace(-obj.fsimu/2,obj.fsimu/2,N+1);
faxis = ifftshift(faxis(:,1:end-1));
faxis = faxis';
obj.linstep = -obj.alpha_lin/2 - 2*1j*pi^2*obj.b2*faxis.^2 - 4/3*1j*pi^3*obj.b3*faxis.^3;
faxis = linspace(-obj.fsimu/2, obj.fsimu/2, N+1);
faxis = faxis(1:end-1); % drop redundant endpoint
faxis = ifftshift(faxis)'; % center zero frequency
if 0
H = exp((obj.linstep)*obj.fiber_length);
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
% Define linear operator per meter in frequency domain
obj.linstep = -obj.alpha_lin/2 ... % half-step loss
- 1j*2*pi^2*obj.b2 .* faxis.^2 ... % second-order dispersion
- 1j*(4/3)*pi^3*obj.b3 .* faxis.^3; % third-order dispersion
% Choose linear-only or nonlinear SSFM based on gamma
if obj.gamma ~= 0
% Full adaptive SSFM with nonlinear Schrödinger solver
opt_out = obj.NLSE(signal);
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
%TODO: attenuate nase ...
% Update output field in signal class
opt_sig.signal = opt_out;
end
function [yout] = NLSE(obj, xin)
maxPow = obj.gamma.*max(abs(xin).^2);
Leff = obj.dphimax / maxPow ;
dz = Leff;
function yout = NLSE(obj, xin)
% NLSE: Solve nonlinear Schrödinger equation by adaptive split-step
% xin: input time-domain field
% Returns yout: output time-domain field after propagation
% Initial estimate of effective length per step
maxPow = obj.gamma * max(abs(xin).^2);
Leff = obj.dphimax / maxPow;
dz = Leff;
z_prop = 0;
yout = fft(xin);
yout = ((yout).*exp(obj.linstep*dz/2));
% Apply initial half-step linear operator
yout = fft(xin) .* exp(obj.linstep * dz/2);
% Loop until full fiber length is reached
while true
% Inverse FFT to time domain for nonlinear phase shift
yout = ifft(yout);
Leff = dz;
% Nonlinear phase rotation per segment
power = abs(yout).^2;
Hnl = exp( -1j*obj.gamma*power*Leff);
yout = yout .* Hnl;
Hnl = exp(-1j * obj.gamma * power * dz);
yout = yout .* Hnl;
% Accumulate propagation distance
z_prop = z_prop + dz;
maxPow = obj.gamma*max(abs(yout).^2);
Leff = obj.dphimax/maxPow;
dz_new = Leff;
% Compute adaptive step for next interval
maxPow = obj.gamma * max(abs(yout).^2);
dz_new = obj.dphimax / maxPow;
% If remaining length shorter than new step, finish loop
if z_prop + dz_new > obj.fiber_length
dz_new = obj.fiber_length - z_prop;
break
break;
end
yout = fft(yout);
yout = ((yout).*exp(obj.linstep*(dz/2+dz_new/2)));
dz = dz_new;
% Half-step linear operator bridging segments
yout = fft(yout) .* exp(obj.linstep * ((dz/2) + (dz_new/2)));
dz = dz_new;
end
yout = fft(yout);
yout = ((yout).*exp(obj.linstep*(dz/2+dz_new/2)));
% Final propagation segment: combine half-steps and nonlinear
yout = fft(yout) .* exp(obj.linstep * ((dz/2) + (dz_new/2)));
yout = ifft(yout);
Leff = dz;
% Last nonlinear phase shift
power = abs(yout).^2;
Hnl = exp(-1j * obj.gamma * power * dz_new);
yout = yout .* Hnl;
Hnl = exp( -1j*obj.gamma*power*Leff);
yout = yout .* Hnl;
yout = fft(yout);
yout = ((yout).*exp(obj.linstep*(dz/2)));
% Final half-step linear operator to complete SSFM
yout = fft(yout) .* exp(obj.linstep * (dz_new/2));
yout = ifft(yout);
end
end
end

View File

@@ -83,6 +83,14 @@ classdef MLSE < handle
% impulse respnse to remove from signal
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
% of vectors. 'combs' contains all trellis states
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)
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
% 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
y_clean = conv( data_ref, flip(obj.DIR), "same" );
sigma2 = var( data_in - y_clean );
inv2s2 = 1/(2*sigma2);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%% FORWARD PASS (VITERBI -Alpha's) %%%%%
@@ -134,7 +147,7 @@ classdef MLSE < handle
% first start is evaluated without ISI/ wihout the full Impulse response
% so simply use the constellation here
bm = -(data_in(1) - last_sym).^2 ;
bm = -(data_in(1) - last_sym).^2 * inv2s2;
pm = pm + bm;
[alpha(:,1),pm_survivor_fw_idx(:,1)] = max(pm,[],2);
pm = repmat(alpha(:,1).',nStates,1);
@@ -143,10 +156,10 @@ classdef MLSE < handle
% Forward Recursion (FSM Computation)
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;
[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)
[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)
bm_fw(:,:,n) = bm;
@@ -177,7 +190,7 @@ classdef MLSE < handle
% predecessor
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.';
[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)
@@ -214,10 +227,22 @@ classdef MLSE < handle
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%% FORWARD PASS PAM2,4,8 %%%%%
nml_LLP = LLP - max(LLP);
expLLP = exp(nml_LLP); %subtract highst value for better numerical stability, LLP's are not always close to zero
state_prob = expLLP ./ sum(expLLP);
nml_LLP = LLP - max(LLP); %subtract highest value for better numerical stability, LLP's are not always close to zero
expLLP = exp(nml_LLP);
state_prob = expLLP ./ sum(expLLP); % sums to one (or numerically close to one)
% compute symbolposteriors from LLP in the logdomain:
amax = max(LLP,[],1);
logZ = amax + log(sum(exp(LLP - amax), 1));
logPstate = LLP - logZ; % still in logdomain
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
@@ -305,8 +330,8 @@ classdef MLSE < handle
% Number of symbols and 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
LLR_maxlogmap = 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);
% Calculate mutual information for bit position k
I0 = mean(log2(1 + exp(llr0(100:end-100)))); % exp(--LLR) = exp(positive) > 1
I1 = mean(log2(1 + exp(-llr1(100:end-100)))); % exp(-+LLR) = exp(negative) < 1
I0 = mean(log2(1 + exp(llr0))); % exp(--LLR) = exp(positive) > 1
I1 = mean(log2(1 + exp(-llr1))); % exp(-+LLR) = exp(negative) < 1
MI(k) = 1 - 0.5 * (I0 + I1);
end
@@ -354,8 +379,7 @@ classdef MLSE < handle
VITERBI_ESTIMATION_SYMBOLS = VITERBI_ESTIMATION_SYMBOLS./rms(VITERBI_ESTIMATION_SYMBOLS);
debug = 0;
debug = 1;
if debug
%%% DEBUG PLOT LIKELIHOOD RATIOS %%%
figure(115);clf
@@ -380,6 +404,7 @@ classdef MLSE < handle
if debug
tx_bits = reshape(tx_bits',[],1);
disp('Start DEBUG MLSE:')
% DECIDE based on Viterbi traceback
VITERBI_ESTIMATION_SYMBOLS = VITERBI_ESTIMATION_SYMBOLS./rms(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);
[~,~,ber_fw,~] = calc_ber(rx_bits,tx_bits,"skip_front",100,"skip_end",150,"returnErrorLocation",1);
fprintf('FW BER: %.2e \n',ber_fw);
disp('Stop DEBUG MLSE:')
disp('')
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

View File

@@ -0,0 +1,152 @@
classdef MLSE_new < handle
%MLSE: BCJRbased softoutput for PAMM 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 2tap
N = numel(y);
M = obj.M;
m = log2(M);
%--- forward/backward metrics (maxlog) ---
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 zeroth 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 symbolwise via logsumexp 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
% bitLLR 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

View File

@@ -44,8 +44,6 @@ classdef DBHandler < handle
% datasource = "jdbc:mysql://134.245.243.254:3306/labor";
obj.conn = database( ...
string(obj.dataBase), ... % Database name
"silas", ... % Username
@@ -645,7 +643,7 @@ classdef DBHandler < handle
cleanedTable.(varNames{i}) = numCol;
else
% Clean double-quoted SQL literals (e.g., ""no_db"")
cleanedTable.(varNames{i}) = strrep(string(col), '""', '"');
cleanedTable.(varNames{i}) = strrep(string(col), '"', '');
end
end
end

View File

@@ -26,13 +26,15 @@ try
% Initialize database connection
database = DBHandler("dataBase", [options.dataBase], "type", options.database_type );
% 2. Check if an equalizer configuration with the same hash exists
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.entries_for_run / existing_results.unique_eq_count) > 8
return
if 0
% 2. Check if an equalizer configuration with the same hash exists
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.entries_for_run / existing_results.unique_eq_count) > 5
return
end
end
end
@@ -94,8 +96,8 @@ try
adaption= 1;
use_dd_mode = 1;
use_ffe = 1;
use_dfe = 1;
use_ffe = 0;
use_dfe = 0;
use_vnle_mlse = 1;
use_dbtgt = 1;
use_dbenc = 1;
@@ -139,6 +141,10 @@ try
% Preprocess signal
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 use_ffe
@@ -146,19 +152,19 @@ try
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);
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,...
'showAnalysis',0,...
"postFFE",[],...
"eth_style_symbol_mapping",0);
output.ffe_package{r} = dfe_results;
output.ffe_package{r} = ffe_results;
dfe_results.metrics.print;
dfe_results.config.equalizer_structure = "ffe";
ffe_results.metrics.print;
ffe_results.config.equalizer_structure = "ffe";
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

View File

@@ -110,12 +110,14 @@ if options.showAnalysis
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');
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

View File

@@ -43,6 +43,7 @@ end
% Hard decision on VNLE output
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
[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)
% rx_signal.spectrum("displayname",'Rx Signal','fignum',100,'normalizeTo0dB',1);
% Display analysis plots and metrics
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);
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)
showEQcoefficients('n1', postFFE.e, "displayname", 'Coefficients', 'fignum', 338);
end
@@ -234,7 +249,7 @@ showLevelHistogram(eq_signal_sd, tx_symbols, "fignum", 341);
warning off
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;
warning on

View File

@@ -22,7 +22,7 @@ end
% Ensure the figure is ready before calling spectrum
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)
% Hold on to the figure for further plotting
@@ -43,5 +43,6 @@ end
end
xlim([-eq_noise.fs/2* 1e-9 eq_noise.fs/2* 1e-9]);
ylim([-15, 0]);
end

View File

@@ -20,6 +20,12 @@ end
f = f(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
if isnan(options.fignum)
fig = figure; % Create a new figure and get its handle
@@ -30,7 +36,7 @@ end
% Magnitude response (in dB)
subplot(2,1,1);
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');
xlabel('Frequency (GHz)');
ylabel('Magnitude (dB)');

View File

@@ -27,6 +27,7 @@ end
received_sd = NaN(numel(constellation),length(ref_symbols));
lvlcol = cbrewer2('Paired',numel(constellation)*2);
lvlcol = lvlcol(2:2:end,:);
lvlcol = linspecer(numel(constellation));
% lvlcol = cbrewer2('Set1',numel(constellation));
for lvl = 1:numel(constellation)
%Separate the equalized signal into the

View File

@@ -1,7 +1,7 @@
function [Bits, Symbols, Scpe_cell, found_sync] = loadAndSyncSignalDataFromDb(dataTable, options)
% LOADSIGNALDATA Loads and synchronizes signal data from storage
%
% Inputs:
% Inputs:d
% dataTable - Table with file paths and configuration
% options - Struct with storage_path and max_occurences
%

View File

@@ -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);
% Apply Gaussian filter
Scpe_sig = Filter('filtdegree', 4, "f_cutoff", Symbols.fs.*0.6, ...
"fs", Scpe_sig.fs, "filterType", filtertypes.gaussian, ...
"active", true).process(Scpe_sig);
% Scpe_sig = Filter('filtdegree', 4, "f_cutoff", Symbols.fs.*0.6, ...
% "fs", Scpe_sig.fs, "filterType", filtertypes.gaussian, ...
% "active", true).process(Scpe_sig);
% Remove DC offset
Scpe_sig = Scpe_sig - mean(Scpe_sig.signal);

View File

@@ -120,7 +120,7 @@ switch submit_mode
% fetchNext has already set Read=true on the errored future.
% Find the one Read==true that we have _not_ yet consumed.
readMask = arrayfun(@(f) f.Read, futures);
idxErr = find(readMask & ~consumedIdx, 1);
idxErr = find(readMask & ~consumedIdx', 1);
consumedIdx(idxErr) = true;
% Pull the _real_ exception out of the future object

View File

@@ -1,5 +1,5 @@
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...
arguments(Input)
@@ -26,7 +26,7 @@ end
% TRIM
[test_signal,reference_signal]=trimseq(test_signal,reference_signal,options.skip_front,options.skip_end);
% CALC EVM
% CALC AIR
%%% new implementation of AIR
constellation = unique(reference_signal);
reference_idx = arrayfun(@(x) find(constellation == x, 1), reference_signal);

View 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
% Perbit 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 (bitwise 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

View File

@@ -1,5 +1,5 @@
function [GMI,NGMI] = calc_ngmi(test_signal,reference_signal,options)
% Silas implementation of (N)GMI calculation according to: J. Cho, L. Schmalen, und P. J. Winzer,
% Silas implementation of (N)GMI calculation according to: J. Cho, L. Schmalen, und P. J. Winzer,
% Normalized Generalized Mutual Information as a Forward Error Correction Threshold for Probabilistically Shaped QAM,
% in 2017 European Conference on Optical Communication (ECOC), Sep. 2017, doi: 10.1109/ECOC.2017.8345872.
@@ -38,7 +38,7 @@ end
assert(length(test_signal) == length(reference_signal),"Sequence length does not match");
%%% implemented according to [1] J. Cho, L. Schmalen, und P. J. Winzer,
%%% implemented according to [1] J. Cho, L. Schmalen, und P. J. Winzer,
% Normalized Generalized Mutual Information as a Forward Error Correction Threshold for Probabilistically Shaped QAM,
% in 2017 European Conference on Optical Communication (ECOC), Sep. 2017, S. 13. doi: 10.1109/ECOC.2017.8345872.
@@ -62,7 +62,7 @@ end
m = log2(M); %bits per symbol
entries = sum(~isnan(received_sd),2)';
P_X = entries./N;
P_X = ones(1,M)/M;%entries./N;
% Parameters
symbols = constellation'; % PAM-4 symbols
@@ -75,18 +75,20 @@ end
% Entropy term
H_X = -sum(P_X .* log2(P_X)); % Entropy of input distribution
% GMI computation
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
tx_bits = PAMmapper(M,0,"eth_style",0).demap(reference_signal);
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
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(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);
% Logarithmic contribution
noise_impact_term = noise_impact_term + log2(numerator / denominator);
bit_llr_sum = bit_llr_sum + log2(numerator / denominator);
end
end
% Normalize the noise impact term by N
noise_impact_term = noise_impact_term / N;
bit_llr_sum = bit_llr_sum / N;
% GMI
GMI = H_X + noise_impact_term;
GMI = H_X + bit_llr_sum;
NGMI = GMI / m;
end

View File

@@ -1,24 +1,32 @@
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.
%
% [snr_all, snr_per_level] = calc_snr(tx_signal, eq_noise)
%
% Inputs:
% tx_signal - Vector of transmitted signal values.
% eq_noise - Vector of corresponding noise samples.
%
% Outputs:
% snr_all - Overall SNR computed using all signal values.
% snr_per_level - A vector where each element is the SNR computed
% for a unique amplitude level in tx_signal.
%
% 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
% the symbols corresponding to each level separately.
% 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)
%
% Inputs:
% tx_signal - Vector of transmitted signal values.
% eq_noise - Vector of corresponding noise samples.
%
% Outputs:
% snr_all - Overall SNR computed using all signal values.
% snr_per_level - A vector where each element is the SNR computed
% for a unique amplitude level in tx_signal.
%
% 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
% 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
snr_all = snr(tx_signal, eq_noise);
% Get the unique amplitude levels in the transmitted signal
levels = unique(tx_signal);
@@ -27,10 +35,10 @@ function [snr_all, snr_per_level] = calc_snr(tx_signal, eq_noise)
for i = 1:length(levels)
% Find indices where tx_signal equals the current level
idx = (tx_signal == levels(i));
% Compute the SNR for these indices
snr_per_level(i) = snr(tx_signal(idx), eq_noise(idx));
histogram(eq_noise(idx));
end
end

View 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
View 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

View File

@@ -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);

View File

@@ -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();

View File

@@ -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]);

View File

@@ -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

View File

@@ -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);

View File

@@ -1,6 +1,6 @@
% === SETTINGS ===
dsp_options.append_to_db = 1;
dsp_options.max_occurences = 15;
dsp_options.append_to_db = 0;
dsp_options.max_occurences = 1;
experiment = "highspeed_2024";
dsp_options.mode = "load_run_id"; % 'simulate' & 'load_files'
@@ -41,14 +41,14 @@ end
fp = QueryFilter();
% fp.where('Runs', 'run_id','EQUALS', 987);
fp.where('Runs', 'pam_level','EQUALS', 4);
% fp.where('Runs', 'bitrate','LESS_THAN', 310e9);
% fp.where('Runs', 'fiber_length','EQUALS', 1);
fp.where('Runs', 'bitrate','EQUALS', 360e9);
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', '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);
@@ -75,7 +75,7 @@ wh.addStorage("dbenc_package");
% === 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);

View File

@@ -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

View File

@@ -5,7 +5,7 @@ precomp_mode = 2; %0=do nothing ; 1= measure; 2=precomp active
db_precode = 0;
db_coding_approach = 0;
fsym = 224e9;
fsym = 160e9;
fdac = 256e9;
random_key = 0;
M = 4;
@@ -58,8 +58,7 @@ end
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(...
"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.resample("fs_out",fdac);
Digi_sig= Digi_sig.normalize("mode","rms");
Digi_sig.spectrum("displayname","Strong Precomp","fignum",2223,"normalizeToNyquist",0,"normalizeTo0dB",0);

View File

@@ -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);
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);
wh = a.obj;

View File

@@ -1,12 +1,12 @@
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.Configurations = struct( ...
'bitrate', [], ... %[224,336,360,390,420,448]
'db_mode', [], ...
'bitrate', [390e9], ... %[224,336,360,390,420,448]
'db_mode', 1, ...
'fiber_length', 1, ...
'interference_attenuation', [], ...
'interference_path_length', [], ...

View File

@@ -1,6 +1,6 @@
function [output] = imdd_model(varargin)
simulation_mode = 0;
simulation_mode = 1;
%%% Change folder
curFolder = pwd;

View File

@@ -1,33 +1,24 @@
%%% Run parameters
% TX
M = 4;
fsym = 180e9;
fsym = 112e9;
apply_pulsef = 1;
fdac = 256e9;
fadc = 256e9;
random_key = 1;
db_precode = 0;
db_encode = 0;
random_key = 2;
rcalpha = 0.05;
kover = 16;
vbias_rel = 0.5;
u_pi = 2.9;
vbias = -vbias_rel*u_pi;
laser_wavelength = 1310;
laser_wavelength = 1290;
laser_linewidth = 0;
tx_bw_nyquist = 0.6;
rx_bw_nyquist = 0.6;
% Channel
link_length = 1;
% RX
rop = -8;
link_length = 10000;
vnle_order1 = 50;
vnle_order2 = 3;
@@ -49,55 +40,13 @@ mu_dc = 0.005;
mu_ffe = [mu_ffe1 mu_ffe3 mu_ffe3];
mu_dfe = 0.0004;
dfe_ = sum(dfe_order)>0;
doub_mode = db_mode.no_db;
Pform = Pulseformer("fsym",fsym,"fdac",4*fsym,"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,"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];
rop = [-8];
bwl = [0.5:0.1:1.5];
fsym = [128:16:170].*1e9;
ber_vnle = [];
ber_mlse = [];
ber_viterbi = [];
@@ -107,71 +56,121 @@ gmi_vnle = [];
gmi_mlse = [];
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 %%%%%%
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 %%%%%%
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_bwl = rx_bw_nyquist.*f_nyquist;
% rx_bwl = 80e9;
% rx_bwl = rx_bw_nyquist.*f_nyquist;
rx_bwl = 50e9;
Rx_sig = Filter('filtdegree',4,"f_cutoff",rx_bwl,"fs",fdac*kover,"filterType",filtertypes.butterworth,"active",true).process(Rx_sig);
% %%%%%% Low-pass Scope %%%%%%
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);
%
%%%%%% 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);
"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_cell, ~, found_sync] = Scpe_sig_resampled.tsynch("reference", Symbols, "fs_ref", fsym, "debug_plots", 1);
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(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);
mlse_ = MLSE("DIR",[1,1],"duobinary_output",0,"M",M,"trellis_states",PAMmapper(M,0).levels);
%Duobinary Targeting
if 0
db_ref_sequence = Duobinary().encode(Symbols);
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_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_precoded = Duobinary().encode(mlse_sig_hd,"M",M);
mlse_sig_hd_precoded = Duobinary().decode(mlse_sig_hd_precoded,"M",M);
tx_symbols_precoded = Duobinary().encode(Symbols);
tx_symbols_precoded = Duobinary().decode(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);
[~,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
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);
%Duobinary Targeting
db_ref_sequence = Duobinary().encode(Symbols);
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_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_precoded = Duobinary().encode(mlse_sig_hd,"M",M);
mlse_sig_hd_precoded = Duobinary().decode(mlse_sig_hd_precoded,"M",M);
tx_symbols_precoded = Duobinary().encode(Symbols);
tx_symbols_precoded = Duobinary().decode(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);
[~,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
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);
end
% 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_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);
% Hard decision on VNLE output
eq_signal_hd = PAMmapper(M, 0).quantize(eq_signal_sd);
@@ -180,19 +179,21 @@ for r = 1:length(rop)
fprintf('BER VNLE: %.2e \n',ber_vnle(r));
fprintf('NGMI VNLE: %.2f \n',gmi_vnle(r)./log2(M));
if 1
% Process through postfilter and MLSE
pf_ncoeffs = 1;
pf_ = Postfilter("ncoeff",pf_ncoeffs,"useBurg",1);
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_.DIR = pf_.coefficients;
alpha(r) = pf_.coefficients(2);
[signalclass_hd,LLR,gmi_mlse(r)] = mlse_.process(mlse_sig_sd,Symbols);
mlse_sig_hd = PAMmapper(M, 0, "eth_style", 0).quantize(signalclass_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);
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
@@ -205,23 +206,48 @@ for r = 1:length(rop)
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);
[~,~,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
cols = cbrewer2('Paired',8);
d = 1;
figure();hold on
plot(rop,gmi_mlse,'DisplayName','MLSE','Marker','*');
plot(rop,gmi_vnle,'DisplayName','VNLE','Marker','*');
plot(rop,gmi_mlse_db,'DisplayName','MLSE DB Tgt','Marker','*');
figure(11);hold on
plot(fsym.*1e-9,alpha,'DisplayName','VNLE','Marker','x','LineStyle','-','Color',cols(1+d,:));
xlabel('Baudrate in GBd');
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]);
xlabel('Baudrate in GBd');
ylabel('GMI');
figure();hold on
plot(rop,ber_vnle,'DisplayName','VNLE');
plot(rop,ber_mlse,'DisplayName','MLSE','Marker','*');
plot(rop,ber_viterbi,'DisplayName','Viterbi','Marker','*');
plot(rop,ber_db_diff_precoded,'DisplayName','MLSE db diff','Marker','*');
plot(rop,ber_db,'DisplayName','MLSE db','Marker','*');
figure(13);hold on
plot(fsym.*1e-9,ber_vnle,'DisplayName','VNLE','Marker','x','LineStyle','-','Color',cols(1+d,:));
plot(fsym.*1e-9,ber_mlse,'DisplayName','MLSE','Marker','x','LineStyle','-','Color',cols(3+d,:));
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');
% ylim([1e-6 0.1]);
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

View File

@@ -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;

View File

@@ -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;

View File

@@ -6,3 +6,11 @@ precomp_filename = "lab_high_speed";
freqresp = ChannelFreqResp("Nacq",1024,"Navg",64,"Ncp",63,'f_ref',92e9);
freqresp.load('loadPath',precomp_path,'fileName',precomp_filename);
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();