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];
|
||||
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
|
||||
@@ -410,9 +411,16 @@ classdef Signal
|
||||
catch
|
||||
ylim([floor(min(p_dbm))-3, ceil(max(p_dbm))+3]);
|
||||
end
|
||||
|
||||
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;
|
||||
@@ -927,7 +935,7 @@ classdef Signal
|
||||
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
|
||||
|
||||
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
% Assign inputs to object properties, converting units to SI.
|
||||
obj.fsimu = options.fsimu;
|
||||
obj.fiber_length = options.fiber_length*1000; %km
|
||||
obj.fiber_length = options.fiber_length * 1e3; % km → m
|
||||
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.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.
|
||||
|
||||
% 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;
|
||||
% 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);
|
||||
obj.b3 = ((lambda_signal.^2/(2*pi*Constant.LightSpeed)).^2*obj.Dslope);
|
||||
obj.alpha_lin = obj.alpha/10*log(10)/1000;
|
||||
% 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';
|
||||
faxis = linspace(-obj.fsimu/2, obj.fsimu/2, N+1);
|
||||
faxis = faxis(1:end-1); % drop redundant endpoint
|
||||
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;
|
||||
|
||||
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 ;
|
||||
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);
|
||||
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)));
|
||||
|
||||
% 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*Leff);
|
||||
|
||||
Hnl = exp(-1j * obj.gamma * power * dz_new);
|
||||
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
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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,7 +156,7 @@ 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)
|
||||
@@ -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 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
|
||||
|
||||
@@ -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
|
||||
|
||||
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
|
||||
|
||||
methods (Access=private)
|
||||
|
||||
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";
|
||||
|
||||
|
||||
|
||||
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
|
||||
|
||||
@@ -26,15 +26,17 @@ try
|
||||
% Initialize database connection
|
||||
database = DBHandler("dataBase", [options.dataBase], "type", options.database_type );
|
||||
|
||||
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) > 8
|
||||
if (existing_results.entries_for_run / existing_results.unique_eq_count) > 5
|
||||
return
|
||||
end
|
||||
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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)');
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
%
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
@@ -1,20 +1,28 @@
|
||||
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);
|
||||
|
||||
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 ===
|
||||
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);
|
||||
|
||||
@@ -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_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);
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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', [], ...
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
function [output] = imdd_model(varargin)
|
||||
|
||||
simulation_mode = 0;
|
||||
simulation_mode = 1;
|
||||
|
||||
%%% Change folder
|
||||
curFolder = pwd;
|
||||
|
||||
@@ -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,42 +56,87 @@ 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_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);
|
||||
mlse_ = MLSE("DIR",[1,1],"duobinary_output",0,"M",M,"trellis_states",PAMmapper(M,0).levels);
|
||||
|
||||
|
||||
%Duobinary Targeting
|
||||
if 0
|
||||
%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);
|
||||
@@ -170,9 +164,14 @@ for r = 1:length(rop)
|
||||
% 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);
|
||||
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('NGMI VNLE: %.2f \n',gmi_vnle(r)./log2(M));
|
||||
|
||||
if 1
|
||||
|
||||
% Process through postfilter and MLSE
|
||||
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_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
|
||||
|
||||
@@ -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.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();
|
||||
Reference in New Issue
Block a user