BCJR implementation
WDM code added (Pol Cont., Opt MUX/DEMUX, Opt Atten, DP_Fiber) -> the codebase is not optimized to always work with dp signals!
This commit is contained in:
@@ -6,10 +6,10 @@ Symbols = load("imdd_simulation\projects\ECOC_2025\dsp_test\pam4_symbols.mat");S
|
||||
|
||||
eq_ = FFE_DCremoval("epochs_tr",5,"epochs_dd",3,"len_tr",4096*2,"mu_dd",1e-5,"mu_tr",0,"order",50,"sps",2,"decide",0,"mu_dc",0.005,"dc_buffer_len",1);
|
||||
|
||||
savePath = 'Z:\2025\ECOC Silas\ecoc_2025\';
|
||||
databasePath = 'C:\Users\Silas\Documents\MATLAB\imdd_simulation\projects\ECOC_2025\';
|
||||
database_name = 'ecoc2025_loops.db';
|
||||
db = DBHandler("type","mysql");
|
||||
% savePath = 'Z:\2025\ECOC Silas\ecoc_2025\';
|
||||
% databasePath = 'C:\Users\Silas\Documents\MATLAB\imdd_simulation\projects\ECOC_2025\';
|
||||
% database_name = 'ecoc2025_loops.db';
|
||||
% db = DBHandler("type","mysql");
|
||||
|
||||
params = (logspace(-6,-2,20));
|
||||
params = floor((logspace(2,3,20)));
|
||||
@@ -19,16 +19,16 @@ for i = 1:length(params)
|
||||
|
||||
eq_ = FFE_DCremoval_adaptive_mu("epochs_tr",5,"epochs_dd",3,"len_tr",4096*2,"mu_dd",...
|
||||
0.0002,"mu_tr",0,"order",25,"sps",2,"decide",0,...
|
||||
"mu_dc",0.005,"dc_buffer_len",224, ...
|
||||
"mu_dc",0.005,"dc_buffer_len",1, ...
|
||||
"ffe_buffer_len",1,...
|
||||
"smoothing_buffer_length",0,...
|
||||
"smoothing_buffer_update",224);
|
||||
"smoothing_buffer_update",1);
|
||||
|
||||
result = vnle(eq_,4,Scpe_sig,Symbols,Tx_bits,"precode_mode",db_mode.no_db,'showAnalysis',1,"postFFE",[],"eth_style_symbol_mapping",0);
|
||||
ber_ffe(i) = result.ber_vnle;
|
||||
result = ffe(eq_,4,Scpe_sig,Symbols,Tx_bits,"precode_mode",db_mode.no_db,'showAnalysis',1,"postFFE",[],"eth_style_symbol_mapping",0);
|
||||
ber_ffe(i) = result.metrics;
|
||||
fprintf(" FFE Results: %.2e\n", ber_ffe(i));
|
||||
|
||||
db.addProcessingResult(run_id, result.resultsVNLE, result.equalizerConfigVNLE);
|
||||
% db.addProcessingResult(run_id, result.resultsVNLE, result.equalizerConfigVNLE);
|
||||
|
||||
% eq_ = FFE_adaptive_decision("epochs_tr",5,"epochs_dd",3,"len_tr",4096*2,"mu_dd",...
|
||||
% 0.0003,"mu_tr",0,"order",50,"sps",2,"decide",1,"buffer_length",params(i));
|
||||
|
||||
@@ -1,25 +1,24 @@
|
||||
|
||||
basePath = 'C:\Users\Silas\Documents\MATLAB\Datensätze\sioe_labor\';
|
||||
% basePath = 'C:\Users\Silas\Documents\MATLAB\Datensätze\sioe_labor\';
|
||||
% database = DBHandler("pathToDB",[basePath,'silas_labor.db']);
|
||||
database = DBHandler("type",'mysql');
|
||||
database = DBHandler("type",'mysql','dataBase','labor');
|
||||
|
||||
filterParams = database.tables;
|
||||
%filterParams.Runs.loop_id = 209;
|
||||
filterParams.Configurations = struct( ...
|
||||
'symbolrate', 112e9, ... %[224,336,360,390,420,448]
|
||||
'fiber_length', 0, ...
|
||||
'db_mode', '"no_db"', ...
|
||||
'interference_attenuation', [], ...
|
||||
'interference_path_length', [], ...
|
||||
'is_mpi', 1, ...
|
||||
'pam_level', 4, ...
|
||||
'wavelength', 1310, ...
|
||||
'precomp_amp', [], ...
|
||||
'signal_attenuation', [], ...
|
||||
'v_awg', [], ...
|
||||
'v_bias', [] ...
|
||||
);
|
||||
|
||||
filterParams.Runs.loop_id = 209;
|
||||
% filterParams.Configurations = struct( ...
|
||||
% 'symbolrate', 112e9, ... %[224,336,360,390,420,448]
|
||||
% 'fiber_length', 0, ...
|
||||
% 'db_mode', '"no_db"', ...
|
||||
% 'interference_attenuation', [], ...
|
||||
% 'interference_path_length', 1000, ...
|
||||
% 'is_mpi', 1, ...
|
||||
% 'pam_level', 4, ...
|
||||
% 'wavelength', 1310, ...
|
||||
% 'precomp_amp', [], ...
|
||||
% 'signal_attenuation', [], ...
|
||||
% 'v_awg', [], ...
|
||||
% 'v_bias', [] ...
|
||||
% );
|
||||
|
||||
% if 1
|
||||
% % filterParams.EqualizerParameters.dc_buffer_len = 1;
|
||||
@@ -28,9 +27,15 @@ filterParams.Configurations = struct( ...
|
||||
% filterParams.EqualizerParameters.smoothing_buffer_update = 224;
|
||||
% filterParams.EqualizerParameters.DCmu = 0;
|
||||
% end
|
||||
a = database.getTableFieldNames('Runs');
|
||||
b = database.getTableFieldNames('Results');
|
||||
c = database.getTableFieldNames('EqualizerParameters');
|
||||
d = [a;b;c];
|
||||
|
||||
selectedFields = {'Configurations.run_id' 'Runs.loop_id' 'Runs.date_of_run' 'Runs.rx_raw_path' 'Configurations.bitrate' 'Configurations.v_bias' 'Configurations.v_awg' 'Configurations.precomp_amp' 'Configurations.symbolrate' 'Configurations.pam_level'...
|
||||
'Configurations.db_mode' 'Configurations.rop_attenuation' 'Configurations.is_mpi' 'Configurations.interference_attenuation' 'Configurations.interference_path_length' 'Configurations.signal_attenuation' ...
|
||||
[dataTable,~] = database.queryDB(filterParams, d);
|
||||
|
||||
selectedFields = {'Configurations.run_id' 'Runs.loop_id' 'Runs.date_of_run' 'Runs.rx_raw_path' 'Runs.bitrate' 'Runs.v_bias' 'Runs.v_awg' 'Runs.precomp_amp' 'Runs.symbolrate' 'Runs.pam_level'...
|
||||
'Runs.db_mode' 'Runs.rop_attenuation' 'Runs.is_mpi' 'Runs.interference_attenuation' 'Runs.interference_path_length' 'Runs.signal_attenuation' ...
|
||||
'EqualizerParameters.equalizer_structure' 'EqualizerParameters.diff_precode' 'EqualizerParameters.eq_id' 'EqualizerParameters.dc_buffer_len' 'EqualizerParameters.ffe_buffer_len' 'EqualizerParameters.smoothing_buffer_len' 'EqualizerParameters.smoothing_buffer_update' 'EqualizerParameters.DCmu' 'Measurements.power_pd_in' ...
|
||||
'Measurements.power_mpi_interference' 'Measurements.power_mpi_signal' 'Results.BER' 'Results.BER_precoded' 'Results.EVM' 'Results.SNR' 'Results.GMI' 'Results.Alpha' 'Results.date_of_processing'};
|
||||
|
||||
|
||||
82
projects/ECOC_2025/theory/analytic_mpi_evaluation.m
Normal file
82
projects/ECOC_2025/theory/analytic_mpi_evaluation.m
Normal file
@@ -0,0 +1,82 @@
|
||||
% This script is used to evaluate Fig. 1b) in the paper "Adaptive Removal of Multipath Interference in Short Reach 112 GBd PAM-4 IM/DD Systems"
|
||||
|
||||
%% Parameters
|
||||
df = 1e6;%150e3; % Laser linewidth [Hz]
|
||||
SIR_dB = 20; % Interference attenuation [dB]
|
||||
alpha = 10^(-SIR_dB/20); % Interference attenuation [linear]
|
||||
n_fiber = 1.467; % Refractive index
|
||||
c = physconst('lightspeed'); % [m/s]
|
||||
|
||||
L = linspace(0,400,40); % Interference delay [m]
|
||||
tau = n_fiber./c.*L; % Interference time (= tau) [s]
|
||||
|
||||
tau_c = 1/(pi*df); % laser coherence time [s]
|
||||
L_c = (c/n_fiber)*tau_c; % laser coherence length [m]
|
||||
|
||||
var_sat = 2*alpha^2; % Analytical saturation of variance
|
||||
|
||||
%% Monte–Carlo Simulation
|
||||
fs = 100e9; % sampling rate [Hz]
|
||||
Tsim = 50e-6; % sim duration [s]
|
||||
N = round(Tsim*fs); % number of samples for each realization
|
||||
max_delay_samples = round(max(tau)*fs); % largest delay that is evaluated (based on max. Interference delay)
|
||||
phase_noise_std = sqrt(2*pi*df/fs); % standard dev. phase noise
|
||||
|
||||
num_realizations = 10; % number of parallel runs
|
||||
monte_carlo_variance = zeros(num_realizations, length(L));
|
||||
parfor r = 1:num_realizations
|
||||
|
||||
% generate a realization of phase noise random walk
|
||||
dphi = phase_noise_std * randn(1, N + max_delay_samples); % matlab randn process has std = 1
|
||||
phi = cumsum(dphi);
|
||||
phi_direct = phi(max_delay_samples+1 : max_delay_samples+N);
|
||||
var_k = zeros(1, length(L));
|
||||
for t = 1:length(tau)
|
||||
|
||||
nd = round( tau(t)*fs ); % delay in samples for current interference time
|
||||
phi_delayed = phi(max_delay_samples+1-nd : max_delay_samples+N-nd); %cut out interfering signal part (was earlier)
|
||||
|
||||
E = exp(1j*phi_direct) + alpha*exp(1j*phi_delayed); % E-fields combined
|
||||
I = abs(E).^2; % photo current as magnitude square of E-field
|
||||
var_k(t) = var(I);
|
||||
|
||||
end
|
||||
monte_carlo_variance(r, :) = var_k;
|
||||
end
|
||||
|
||||
avg_of_mc_variances = mean(monte_carlo_variance, 1);
|
||||
std_of_mc_variances = std(monte_carlo_variance, 0, 1);
|
||||
|
||||
%% Analytic variance
|
||||
analytic_variance = 2*alpha^2 * (1 - exp(-2*pi*df.*tau)).^2;
|
||||
|
||||
%% Plot
|
||||
cols = [0.3467 0.5360 0.6907
|
||||
0.9153 0.2816 0.2878
|
||||
0.4416 0.7490 0.4322];
|
||||
|
||||
coherence_length_multiples = 0.5:0.5:ceil(L(end)/L_c);
|
||||
|
||||
figure();
|
||||
hold on;
|
||||
plot(L, avg_of_mc_variances, 'LineWidth',2, 'DisplayName','Simulation','Color',cols(1,:),'LineStyle','-');
|
||||
errorbar(L, avg_of_mc_variances,std_of_mc_variances, 'LineWidth',0.7,'LineStyle','none', 'DisplayName','Simulation','Color',cols(1,:),'HandleVisibility','off');
|
||||
|
||||
plot(L, analytic_variance, 'LineWidth',2, 'DisplayName','Analytic','Color',cols(2,:),'LineStyle','-');
|
||||
xticks(coherence_length_multiples.*L_c);
|
||||
xticklabels(round(coherence_length_multiples.*L_c));
|
||||
|
||||
norm_to_coherence_len = 1;
|
||||
if norm_to_coherence_len
|
||||
xticklabels(coherence_length_multiples);
|
||||
xlabel('$\tau_c$', 'FontSize',12);
|
||||
end
|
||||
|
||||
xline(L_c.*coherence_length_multiples, 'LineWidth',1.5, 'DisplayName','Coh. Length','HandleVisibility','off','Color',[0.7,0.7,0.7],'LineStyle','-');
|
||||
xlim([0,L(end)]);
|
||||
yline(var_sat, '-.k','LineWidth',1.5, 'DisplayName','Saturation: 2$\alpha ^2$');
|
||||
xlabel('Interference Delay [m]', 'FontSize',12);
|
||||
grid on;
|
||||
ylabel('Intensity Variance', 'FontSize',12);
|
||||
title(sprintf('MPI Variance; %d MHz; SIR: %d dB',df.*1e-6,SIR_dB), 'FontSize',14);
|
||||
legend('Location','southeast');
|
||||
32
projects/ECOC_2025/theory/coherence_length_plot.m
Normal file
32
projects/ECOC_2025/theory/coherence_length_plot.m
Normal file
@@ -0,0 +1,32 @@
|
||||
%% Parameters
|
||||
df = linspace(100e3,50e6,10000); % Laser FWHM linewidth [Hz]
|
||||
n_fiber = 1.467; % Fiber group index
|
||||
c = 3e8; % Speed of light [m/s]
|
||||
|
||||
% Compute coherence length (1/e of mean-fringe decay)
|
||||
tau_c = 1./(pi*df);
|
||||
L_c = (c/n_fiber) .* tau_c; % Coherence length [m]
|
||||
|
||||
%% Plot
|
||||
figure('Color','w');
|
||||
loglog(df/1e6, L_c, 'LineWidth',2,'LineStyle','-'); % linewidth in MHz
|
||||
xticks([0.1, 1, 10, 50]);
|
||||
yticks([1, 10, 100, 1000]);
|
||||
yticklabels({'1','10','100','1000'})
|
||||
grid on; box on;
|
||||
xlabel('Laser linewidth [MHz]','FontSize',12,'Interpreter','none');
|
||||
ylabel('Coherence length [m]','FontSize',12,'Interpreter','none');
|
||||
title('Coherence Length vs. Laser Linewidth','FontSize',14,'Interpreter','none');
|
||||
|
||||
%% Annotate some key points
|
||||
hold on;
|
||||
freqs = [150e3, 1e6, 10e6, 50e6]; % [Hz]
|
||||
for f = freqs
|
||||
x = f/1e6;
|
||||
y = (c/n_fiber) * (1/(pi*f));
|
||||
scatter(x,y,'Marker','x','LineWidth',1,'MarkerEdgeColor','black');
|
||||
|
||||
text(x*1.1,y, sprintf('%.2f MHz', f/1e6), ...
|
||||
'FontSize',10,'HorizontalAlignment','left');
|
||||
|
||||
end
|
||||
@@ -4,30 +4,39 @@ dataBase = 'labor_highspeed';%'C:\Users\Silas\Documents\MATLAB\Datensätze\sio
|
||||
db = DBHandler("dataBase", [dataBase], "type", database_type);
|
||||
|
||||
fp = QueryFilter();
|
||||
% fp.where('Runs', 'run_id','EQUALS', 987);
|
||||
% 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);
|
||||
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', 1293);
|
||||
% fp.where('Runs', 'db_mode','EQUALS', 0);
|
||||
fp.where('Runs', 'rop_attenuation','EQUALS', 0);
|
||||
|
||||
% [dataTable,~] = db.queryDB(fp, db.getTableFieldNames('dashboard'));
|
||||
fields = db.getTableFieldNames('power_state_info');
|
||||
fields = [fields; db.getTableFieldNames('dashboard_ungrouped_new')];
|
||||
[dataTable,~] = db.queryDB(fp, fields);
|
||||
|
||||
eqstructures = unique(dataTable.equalizer_structure);
|
||||
% Create the figure
|
||||
figure(10);
|
||||
showFiltered = true;
|
||||
showPrecoded = false;
|
||||
show_bitrate = true;
|
||||
figure(5);
|
||||
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]
|
||||
for eqs = [equalizer_structure.vnle, equalizer_structure.vnle_pf_mlse]
|
||||
|
||||
% figure('Name',string([char(eqs),'']));
|
||||
% hold on
|
||||
|
||||
for pre_emph = [0,1]
|
||||
|
||||
dbmode_filtered = dataTable(dataTable.db_mode == ~pre_emph,:);
|
||||
|
||||
eq_choice = equalizer_structure(eqs);
|
||||
|
||||
@@ -37,50 +46,238 @@ for pre_emph = [1]
|
||||
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');
|
||||
|
||||
% ===== NEW: compute averages + per-row keep masks (robust filtering) =====
|
||||
[Tav, keepMask, keepMaskP] = avgBerBySymbolrate(eq_filtered); % <= NEW
|
||||
|
||||
% x-values (bitrate) for raw points (same mapping as your lines)
|
||||
M = unique(eq_filtered.pam_level); % (assumes single PAM per curve)
|
||||
if show_bitrate
|
||||
x_raw = eq_filtered.symbolrate.*1e-9 .* floor(log2(M)*10)/10;
|
||||
else
|
||||
x_raw = eq_filtered.symbolrate.*1e-9;
|
||||
end
|
||||
|
||||
% ===== NEW: scatter kept raw BER points (hidden from legend) =====
|
||||
cols = cbrewer2('Paired',12);
|
||||
thisColor = cols((2*eqs)+1+pre_emph,:);
|
||||
scatter(x_raw(keepMask), ... % kept points
|
||||
eq_filtered.BER(keepMask), ...
|
||||
14, thisColor, 'filled', ...
|
||||
'MarkerFaceAlpha', 0.35, ...
|
||||
'MarkerEdgeAlpha', 0.35, ...
|
||||
'HandleVisibility','off');
|
||||
|
||||
if showPrecoded
|
||||
scatter(x_raw(keepMaskP), ... % kept precoded points
|
||||
eq_filtered.BER_precoded(keepMaskP), ...
|
||||
14, thisColor, 'filled', ...
|
||||
'Marker', 'square', ...
|
||||
'MarkerFaceAlpha', 0.35, ...
|
||||
'MarkerEdgeAlpha', 0.35, ...
|
||||
'HandleVisibility','off');
|
||||
end
|
||||
|
||||
% ===== NEW: optionally show filtered-out points in red =====
|
||||
if showFiltered
|
||||
bad = ~keepMask;
|
||||
if any(bad)
|
||||
scatter(x_raw(bad), eq_filtered.BER(bad), ...
|
||||
18, 'r', 'x', 'LineWidth', 1.2, ...
|
||||
'HandleVisibility','off');
|
||||
end
|
||||
badp = ~keepMaskP;
|
||||
if any(badp)
|
||||
scatter(x_raw(badp), eq_filtered.BER_precoded(badp), ...
|
||||
18, 'r', '+', 'LineWidth', 1.2, ...
|
||||
'HandleVisibility','off');
|
||||
end
|
||||
end
|
||||
|
||||
% Keep your sorting and one-per-symbolrate behavior (using Tav)
|
||||
symbolrate_sorted = sortrows(Tav,{'symbolrate','avg_BER_calc'}, '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
|
||||
|
||||
if show_bitrate
|
||||
% Bitrate for the averaged curves (unchanged)
|
||||
xraw = symbolrate_sorted.symbolrate.*1e-9 .* floor(log2(M)*10)/10;
|
||||
else
|
||||
xraw = symbolrate_sorted.symbolrate.*1e-9;
|
||||
end
|
||||
% Use the MATLAB-averaged BERs
|
||||
ber = symbolrate_sorted.avg_BER_calc;
|
||||
ber_precoded = symbolrate_sorted.avg_BER_precoded_calc;
|
||||
|
||||
|
||||
dname = strrep([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
|
||||
plot(xraw, ber, ...
|
||||
'LineWidth', 1.5, 'MarkerSize', 5, ...
|
||||
'Marker','o','LineStyle','-', ...
|
||||
'Color',thisColor,'MarkerEdgeColor',thisColor,'MarkerFaceColor',[1,1,1], ...
|
||||
'DisplayName', dname);
|
||||
|
||||
xticks(bitrate);
|
||||
if showPrecoded
|
||||
plot(xraw, ber_precoded, ...
|
||||
'LineWidth', 1.5, 'MarkerSize', 5, ...
|
||||
'Marker','square','LineStyle',':', ...
|
||||
'Color',thisColor,'MarkerEdgeColor',thisColor,'MarkerFaceColor',[1,1,1], ...
|
||||
'DisplayName', [dname,'; pre-coded']);
|
||||
end
|
||||
|
||||
grid on;
|
||||
|
||||
if show_bitrate
|
||||
xlabel('Net bitrate [GBps]', 'FontSize', 12);
|
||||
else
|
||||
xlabel('Symbol rate [GBd]', 'FontSize', 12);
|
||||
end
|
||||
ylabel('BER', 'FontSize', 12);
|
||||
title('BER vs. Baud Rate','FontSize', 14, 'FontWeight', 'bold');
|
||||
|
||||
set(gca, 'XScale', 'linear', ...
|
||||
'YScale', 'log', ...
|
||||
'TickLabelInterpreter', 'latex', ...
|
||||
'FontSize', 11);
|
||||
|
||||
% Optional: tighten axis limits
|
||||
xlim([min(bitrate), max(bitrate)]);
|
||||
ylim([5e-5, 0.5]);
|
||||
xticks(xraw);
|
||||
if show_bitrate
|
||||
xticks(200:25:500);
|
||||
xlim([350 500]);
|
||||
else
|
||||
xlim([min(xraw), max(xraw)]);
|
||||
end
|
||||
|
||||
ylim([5e-4, 0.3]);
|
||||
|
||||
end
|
||||
|
||||
yline([2.2e-4, 4.85e-3, 2e-2],'LineWidth',1,'LineStyle','--','HandleVisibility','off');
|
||||
end
|
||||
|
||||
function [Tav, keepAll, keepAllP] = avgBerBySymbolrate(T, ZT, MIN_G)
|
||||
% Minimal robust averaging of BER per symbolrate (+ masks for kept points).
|
||||
% Usage: [Tav, keepAll, keepAllP] = avgBerBySymbolrate(T, ZT, MIN_G)
|
||||
% Defaults: ZT=3 (MAD z-thresh in log10), MIN_G=2 (min points to filter)
|
||||
|
||||
if nargin < 2, ZT = 5; end
|
||||
if nargin < 5, MIN_G = 0; end
|
||||
|
||||
hasP = ismember('BER_precoded', T.Properties.VariableNames);
|
||||
hasNB = ismember('numBits', T.Properties.VariableNames);
|
||||
|
||||
[G,~,idx] = unique(T.symbolrate);
|
||||
nG = numel(G);
|
||||
|
||||
avgBER = nan(nG,1);
|
||||
avgBERp = nan(nG,1);
|
||||
keepAll = false(height(T),1);
|
||||
keepAllP = false(height(T),1);
|
||||
|
||||
for gi = 1:nG
|
||||
r = idx==gi;
|
||||
|
||||
x = T.BER(r);
|
||||
nb = hasNB * T.numBits(r) + ~hasNB; % if missing, nb==1 (scalar expansion ok)
|
||||
|
||||
[avgBER(gi), keepAll(r)] = rmeanBer(x, nb, ZT, MIN_G);
|
||||
|
||||
if hasP
|
||||
xp = T.BER_precoded(r);
|
||||
[avgBERp(gi), keepAllP(r)] = rmeanBer(xp, nb, ZT, MIN_G);
|
||||
end
|
||||
end
|
||||
|
||||
Tav = table(G, avgBER, avgBERp, ...
|
||||
'VariableNames', {'symbolrate','avg_BER_calc','avg_BER_precoded_calc'});
|
||||
end
|
||||
|
||||
function [mu, keep] = rmeanBer(x, nb, ZT, MIN_G, onlyHighOutliers, minKeepThreshold)
|
||||
% Robust arithmetic mean of BER with log-domain MAD filtering (returns keep mask)
|
||||
%
|
||||
% Params:
|
||||
% x : BER values
|
||||
% nb : numBits (for floor)
|
||||
% ZT : MAD z-threshold
|
||||
% MIN_G : min group size before filtering
|
||||
% onlyHighOutliers : (bool) if true, only discard values above mean
|
||||
% minKeepThreshold : values below this BER are always kept
|
||||
%
|
||||
% Returns:
|
||||
% mu : robust mean
|
||||
% keep : logical mask of kept samples
|
||||
|
||||
if nargin < 5, onlyHighOutliers = false; end
|
||||
if nargin < 6, minKeepThreshold = 0; end
|
||||
|
||||
x(~isfinite(x)) = NaN;
|
||||
|
||||
if ~isscalar(nb), nb(~isfinite(nb)) = NaN; end
|
||||
if isscalar(nb) && ~isfinite(nb), nb = 1; end
|
||||
|
||||
floorVal = realmin;
|
||||
if ~isscalar(nb) || (isscalar(nb) && isfinite(nb) && nb~=1)
|
||||
fv = 0.5 ./ max(nb, eps); % rule-of-three style floor
|
||||
if isscalar(fv), floorVal = fv; else, floorVal = fv; end
|
||||
end
|
||||
|
||||
xAdj = x;
|
||||
bad = ~isfinite(xAdj) | xAdj <= 0;
|
||||
if isscalar(floorVal)
|
||||
xAdj(bad) = floorVal;
|
||||
else
|
||||
xAdj(bad) = floorVal(bad);
|
||||
end
|
||||
|
||||
valid = isfinite(xAdj) & xAdj > 0;
|
||||
keep = false(size(xAdj));
|
||||
|
||||
if nnz(valid)==0
|
||||
mu = NaN; return
|
||||
end
|
||||
if nnz(valid) < MIN_G
|
||||
mu = mean(xAdj(valid),'omitnan'); keep(valid)=true; return
|
||||
end
|
||||
|
||||
lx = log10(xAdj(valid));
|
||||
med = median(lx,'omitnan');
|
||||
mad = median(abs(lx-med),'omitnan');
|
||||
|
||||
if mad<=0 || ~isfinite(mad)
|
||||
keep(valid) = true;
|
||||
mu = mean(xAdj(valid),'omitnan');
|
||||
return
|
||||
end
|
||||
|
||||
sigma = 1.4826*mad;
|
||||
ksel = abs(lx-med) <= ZT*sigma;
|
||||
|
||||
% convert to linear indices
|
||||
vIdx = find(valid);
|
||||
|
||||
% === Extension A: only drop high outliers ===
|
||||
if onlyHighOutliers
|
||||
logMean = mean(lx,'omitnan');
|
||||
highIdx = lx > logMean;
|
||||
ksel = ksel | ~highIdx; % always keep values below/equal to mean
|
||||
end
|
||||
|
||||
% === Extension B: always keep values below minKeepThreshold ===
|
||||
belowThr = xAdj(valid) < minKeepThreshold;
|
||||
ksel = ksel | belowThr;
|
||||
|
||||
keep(vIdx(ksel)) = true;
|
||||
|
||||
if any(keep)
|
||||
mu = mean(xAdj(keep),'omitnan');
|
||||
else
|
||||
mu = mean(xAdj(valid),'omitnan');
|
||||
keep(valid) = true;
|
||||
end
|
||||
end
|
||||
|
||||
yline([4.85e-3, 2e-2],'LineWidth',1,'LineStyle','--','HandleVisibility','off'); beautifyBERplot();
|
||||
@@ -1,6 +1,6 @@
|
||||
% === SETTINGS ===
|
||||
dsp_options.append_to_db = 0;
|
||||
dsp_options.max_occurences = 1;
|
||||
dsp_options.append_to_db = 1;
|
||||
dsp_options.max_occurences = 15;
|
||||
|
||||
experiment = "highspeed_2024";
|
||||
dsp_options.mode = "load_run_id"; % 'simulate' & 'load_files'
|
||||
@@ -39,29 +39,23 @@ end
|
||||
% === Get Run ID's ===
|
||||
|
||||
fp = QueryFilter();
|
||||
% fp.where('Runs', 'run_id','EQUALS', 987);
|
||||
fp.where('Runs', 'pam_level','EQUALS', 4);
|
||||
fp.where('Runs', 'bitrate','EQUALS', 360e9);
|
||||
fp.where('Runs', 'fiber_length','EQUALS', 2);
|
||||
% fp.where('Runs', 'run_id','EQUALS', 987);
|
||||
M = 6;
|
||||
% fp.where('Runs', 'pam_level','EQUALS', M);
|
||||
% fp.where('Runs', 'bitrate','EQUALS', 480e9);
|
||||
% fp.where('Runs', 'symbolrate','EQUALS', 162e9);
|
||||
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', 'wavelength','LESS_THAN', 1311);
|
||||
% fp.where('Runs', 'db_mode','EQUALS', 0);
|
||||
% fp.where('Runs', 'rop_attenuation','NOT_EQUAL', 0);
|
||||
% fp.where('Runs', 'power_pd_in','GREATER_THAN', 7);
|
||||
|
||||
|
||||
[dataTable,~] = db.queryDB(fp, db.getTableFieldNames('Runs'));
|
||||
|
||||
|
||||
% Keep only the rows corresponding to the first occurrence of each 'sir' value
|
||||
% [~, unique_indices] = unique(dataTable.sir, 'first');
|
||||
% dataTable = dataTable(unique_indices, :);
|
||||
|
||||
% dataTable = dataTable(1,:);
|
||||
|
||||
% === Set LOOPS & Initialize DataStorage ===
|
||||
dsp_options.parameters = struct();
|
||||
% dsp_options.parameters.pf_ncoeffs = [1,2];%[0,logspace(-4,0,10)];
|
||||
@@ -75,150 +69,281 @@ wh.addStorage("dbenc_package");
|
||||
|
||||
% === RUN IT ===
|
||||
|
||||
[results,wh] = submitJobs(dataTable.run_id(:), dsp_options, "serial", 'wh', wh, 'waitbar', true);
|
||||
[results,wh] = submitJobs(dataTable.run_id(:), dsp_options, "parallel", 'wh', wh, 'waitbar', true);
|
||||
|
||||
results_db = results(dataTable.db_mode==1);
|
||||
results_nodb = results(dataTable.db_mode==0);
|
||||
|
||||
for i = 1:numel(results_db)
|
||||
|
||||
% VNLE (from results_nodb)
|
||||
gmi_v = cellfun(@(c) c.metrics.GMI, results_nodb{1,i}.vnle_package);
|
||||
ber_v = cellfun(@(c) c.metrics.BER, results_nodb{1,i}.vnle_package);
|
||||
air_v = cellfun(@(c) c.metrics.AIR, results_nodb{1,i}.vnle_package);
|
||||
snr_v = cellfun(@(c) c.metrics.SNR, results_nodb{1,i}.vnle_package);
|
||||
[BER_VNLE(i), idx_ber] = min(ber_v);
|
||||
GMI_VNLE(i) = gmi_v(idx_ber);
|
||||
AIR_VNLE(i) = air_v(idx_ber);
|
||||
SNR_VNLE(i) = max(snr_v);
|
||||
idx_gmi_min_vnle(i) = find(gmi_v == min(gmi_v), 1);
|
||||
idx_air_max_vnle(i) = find(air_v == max(air_v), 1);
|
||||
|
||||
% MLSE (from results_db)
|
||||
gmi_m = cellfun(@(c) c.metrics.GMI, results_nodb{1,i}.mlse_package);
|
||||
ber_m = cellfun(@(c) c.metrics.BER, results_nodb{1,i}.mlse_package);
|
||||
air_m = cellfun(@(c) c.metrics.AIR, results_nodb{1,i}.mlse_package);
|
||||
[BER_MLSE(i), idx_ber] = min(ber_m);
|
||||
GMI_MLSE(i) = gmi_m(idx_ber);
|
||||
AIR_MLSE(i) = air_m(idx_ber);
|
||||
idx_gmi_min_mlse(i) = find(gmi_m == min(gmi_m), 1);
|
||||
idx_air_max_mlse(i) = find(air_m == max(air_m), 1);
|
||||
|
||||
% DB (from results_db, BER_precoded)
|
||||
gmi_db = cellfun(@(c) c.metrics.GMI, results_db{1,i}.dbtgt_package);
|
||||
ber_db = cellfun(@(c) c.metrics.BER, results_db{1,i}.dbtgt_package);
|
||||
ber_db_prec = cellfun(@(c) c.metrics.BER_precoded, results_db{1,i}.dbtgt_package);
|
||||
air_db = cellfun(@(c) c.metrics.AIR, results_db{1,i}.dbtgt_package);
|
||||
[BER_DB(i), idx_ber] = min(ber_db);
|
||||
[BER_DB_PREC(i), idx_ber] = min(ber_db_prec);
|
||||
|
||||
GMI_DB(i) = gmi_db(idx_ber);
|
||||
AIR_DB(i) = air_db(idx_ber);
|
||||
idx_gmi_min_db(i) = find(gmi_db == min(gmi_db), 1);
|
||||
idx_air_max_db(i) = find(air_db == max(air_db), 1);
|
||||
|
||||
% metadata
|
||||
bitrate(i) = dataTable.bitrate(i);
|
||||
baudrate(i) = dataTable.symbolrate(i);
|
||||
end
|
||||
|
||||
STYLE_BASE = 2; % adjust this single number to scale markers & lines
|
||||
MARKER_SIZE = STYLE_BASE; % marker size (MATLAB MarkerSize)
|
||||
LINE_WIDTH = max(2, STYLE_BASE/3); % line width (keeps lines reasonable when STYLE_BASE large)
|
||||
|
||||
% --- color map / method -> color assignment (keeps colors consistent) ---
|
||||
cols = cbrewer2('Paired',8);
|
||||
cols = linspecer(6);
|
||||
d = 0;
|
||||
cm.VNLE = cols(1 + d, :);
|
||||
cm.MLSE = cols(2 + d, :);
|
||||
cm.DB_precode = cols(3 + d, :);
|
||||
cm.DB = cols(4 + d, :); % duobinary
|
||||
|
||||
% prepare x values in GBd
|
||||
xGHz = baudrate .* 1e-9;
|
||||
xticks_vals = xGHz;
|
||||
xtick_labels = arrayfun(@(v) sprintf('%d', round(v)), xticks_vals, 'UniformOutput', false);
|
||||
|
||||
% common marker settings (filled, same face+edge color)
|
||||
mk.VNLE = {'Marker','o','MarkerFaceColor',cm.VNLE,'MarkerEdgeColor',cm.VNLE,'MarkerSize',MARKER_SIZE};
|
||||
mk.MLSE = {'Marker','*','MarkerFaceColor',cm.MLSE,'MarkerEdgeColor',cm.MLSE,'MarkerSize',MARKER_SIZE};
|
||||
mk.DB_precode = {'Marker','^','MarkerFaceColor',cm.DB_precode,'MarkerEdgeColor',cm.DB_precode,'MarkerSize',MARKER_SIZE};
|
||||
mk.DB = {'Marker','d','MarkerFaceColor',cm.DB,'MarkerEdgeColor',cm.DB,'MarkerSize',MARKER_SIZE};
|
||||
|
||||
|
||||
% wh.getStoValue('ffe_package',0.005);
|
||||
% wh.getStoValue('mlse_package',0.005);
|
||||
% ---------------- FIGURE : BER ----------------
|
||||
figure(112+M); clf; hold on;
|
||||
plot(xGHz, BER_VNLE, ...
|
||||
'DisplayName','VNLE', ...
|
||||
mk.VNLE{:}, 'LineStyle','-','LineWidth',LINE_WIDTH,'Color',cm.VNLE);
|
||||
plot(xGHz, BER_MLSE, ...
|
||||
'DisplayName','MLSE', ...
|
||||
mk.MLSE{:}, 'LineStyle','-','LineWidth',LINE_WIDTH,'Color',cm.MLSE);
|
||||
plot(xGHz, BER_DB, ...
|
||||
'DisplayName','DB tgt.', ...
|
||||
mk.DB{:}, 'LineStyle','-','LineWidth',LINE_WIDTH,'Color',cm.DB);
|
||||
plot(xGHz, BER_DB_PREC, ...
|
||||
'DisplayName','Diff. Precode + DB tgt.', ...
|
||||
mk.DB{:}, 'LineStyle',':','LineWidth',LINE_WIDTH,'Color',cm.DB);
|
||||
yline(4.85e-3,'LineWidth',1,'HandleVisibility','off');
|
||||
yline(2.2e-4,'LineWidth',1,'HandleVisibility','off');
|
||||
xlabel('Baudrate in GBd');
|
||||
ylabel('BER');
|
||||
set(gca, 'yscale', 'log');
|
||||
set(gca, 'XTick', xticks_vals(1:2:end), 'XTickLabel', xtick_labels(1:2:end));
|
||||
grid on;
|
||||
legend('Location','best');
|
||||
|
||||
% [dataTable,~] = db.queryDB(fp, [db.getTableFieldNames('Runs');db.getTableFieldNames('Results');db.getTableFieldNames('Equalizer')]);
|
||||
|
||||
% ---------------- FIGURE 15 : GMI ----------------
|
||||
figure(113+M); clf; hold on;
|
||||
plot(xGHz, GMI_VNLE, ...
|
||||
'DisplayName','VNLE', ...
|
||||
mk.VNLE{:}, 'LineStyle','-','LineWidth',LINE_WIDTH,'Color',cm.VNLE);
|
||||
plot(xGHz, GMI_MLSE, ...
|
||||
'DisplayName','MLSE', ...
|
||||
mk.MLSE{:}, 'LineStyle','-','LineWidth',LINE_WIDTH,'Color',cm.MLSE);
|
||||
plot(xGHz, GMI_DB, ...
|
||||
'DisplayName','DB tgt.', ...
|
||||
mk.DB{:}, 'LineStyle','-','LineWidth',LINE_WIDTH,'Color',cm.DB);
|
||||
|
||||
ylim([log2(M)-1, log2(M)]);
|
||||
xlabel('Baudrate in GBd');
|
||||
ylabel('GMI');
|
||||
set(gca, 'XTick', xticks_vals(1:2:end), 'XTickLabel', xtick_labels(1:2:end));
|
||||
grid on;
|
||||
legend('Location','best');
|
||||
|
||||
|
||||
|
||||
% ---------------- FIGURE 15 : AIR ----------------
|
||||
m = floor(log2(M)*10)/10;
|
||||
figure(114+M); clf; hold on;
|
||||
plot(xGHz, GMI_VNLE.*xGHz, ...
|
||||
'DisplayName','AIR VNLE', ...
|
||||
mk.VNLE{:}, 'LineStyle','-','LineWidth',LINE_WIDTH,'Color',cm.VNLE);
|
||||
% duobinary has only one GMI curve (DB output)
|
||||
plot(xGHz, GMI_MLSE.*xGHz, ...
|
||||
'DisplayName','AIR MLSE', ...
|
||||
mk.MLSE{:}, 'LineStyle','-','LineWidth',LINE_WIDTH,'Color',cm.MLSE);
|
||||
% MLSE symbol-wise (if present)
|
||||
plot(xGHz, GMI_DB.*xGHz, ...
|
||||
'DisplayName','AIR DB tgt.', ...
|
||||
mk.DB{:}, 'LineStyle','-','LineWidth',LINE_WIDTH,'Color',cm.DB);
|
||||
|
||||
% ylim([log2(M)-1, log2(M)]);
|
||||
xlabel('Baudrate in GBd');
|
||||
ylabel('AIR in Gbps');
|
||||
set(gca, 'XTick', xticks_vals(1:2:end), 'XTickLabel', xtick_labels(1:2:end));
|
||||
grid on;
|
||||
legend('Location','best');
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
% ---------------- FIGURE 15 : Information Rates ----------------
|
||||
tp = TransmissionPerformance;
|
||||
|
||||
|
||||
m = floor(log2(M)*10)/10;
|
||||
figure(213+M); clf; hold on;
|
||||
|
||||
netrates_vnle = tp.calculateNetRate(baudrate.* m, ...
|
||||
'NGMI', GMI_VNLE./m, ...
|
||||
'BER', BER_VNLE);
|
||||
%
|
||||
% dataTable = cleanUpTable(dataTable);
|
||||
% wh_analyze = wh_adap;
|
||||
% % wh_analyze = wh_dcremoval_old2;
|
||||
% % wh_analyze = wh_dcremoval_old2;
|
||||
% plot(xGHz, GMI_VNLE.*xGHz, ...
|
||||
% 'DisplayName','GMI*R VNLE', ...
|
||||
% mk.VNLE{:}, 'LineStyle','-','LineWidth',LINE_WIDTH,'Color',cm.VNLE);
|
||||
%
|
||||
% res = cell(wh_analyze.parameter.mu_dc.length,wh_analyze.parameter.dc_buffer_len.length);
|
||||
% ber_mean = zeros(wh_analyze.parameter.mu_dc.length,wh_analyze.parameter.dc_buffer_len.length);
|
||||
% for m = 1:wh_analyze.parameter.mu_dc.length
|
||||
% for b = 1:wh_analyze.parameter.dc_buffer_len.length
|
||||
% res{m,b}=wh_analyze.getStoValue("ffe_package",wh_analyze.parameter.mu_dc.values(m),wh_analyze.parameter.dc_buffer_len.values(b));
|
||||
% try
|
||||
% cells = res{m,b}{1};
|
||||
% idx = cellfun(@(c) ~isempty(c), cells);
|
||||
% ber = cellfun(@(c) c.metrics.BER, cells(idx));
|
||||
% ber_mean(m,b) = mean(ber);
|
||||
% catch
|
||||
% ber_mean(m,b) = NaN;
|
||||
% end
|
||||
% end
|
||||
% end
|
||||
%
|
||||
% figure()
|
||||
% hold on
|
||||
% ber_fix = cellfun(@(c) c.ffe_package{1}.metrics.BER, results_fix);
|
||||
% ber_adap_m2 = cellfun(@(c) c.ffe_package{1}.metrics.BER, results_adap);
|
||||
% ber_adap_method1 = cellfun(@(c) c.ffe_package{1}.metrics.BER, results);
|
||||
% plot(dataTable.sir,ber_fix,'LineWidth',1,'DisplayName',sprintf('DCt; fix mu = 0.5; p=1024'),'Marker','.','MarkerSize',10);
|
||||
% plot(dataTable.sir,ber_adap_method1,'LineWidth',1,'DisplayName',sprintf('DCt; adap mu 1; p=1024'),'Marker','.','MarkerSize',10);
|
||||
% plot(dataTable.sir,ber_adap_m2,'LineWidth',1,'DisplayName',sprintf('DCt; adap mu 2; p=1024'),'Marker','.','MarkerSize',10);
|
||||
% xlabel('BER');
|
||||
% xlabel('SIR');
|
||||
% yline([4.85e-3,2e-2],'HandleVisibility', 'off','LineWidth',1,'LineStyle','--');
|
||||
% % ylim([9e-4, 0.5]);
|
||||
% set(gca, 'YScale', 'log'); % BER is usually plotted log-scale
|
||||
% legend('show', 'Location', 'best');
|
||||
% grid on;
|
||||
% plot(xGHz, netrates_vnle.SDHD.NetRate.*1e-9, ...
|
||||
% 'DisplayName','SD+HD VNLE', ...
|
||||
% mk.VNLE{:}, 'LineStyle',':','LineWidth',LINE_WIDTH,'Color',cm.VNLE);
|
||||
% plot(xGHz, netrates_vnle.HD.NetRate.*1e-9, ...
|
||||
% 'DisplayName','Staircase VNLE', ...
|
||||
% mk.VNLE{:}, 'LineStyle','-.','LineWidth',LINE_WIDTH,'Color',cm.VNLE);
|
||||
%
|
||||
%
|
||||
% %
|
||||
% % MLSE symbol-wise (if present)
|
||||
% plot(xGHz, GMI_MLSE.*xGHz, ...
|
||||
% 'DisplayName','GMI*R MLSE', ...
|
||||
% mk.MLSE{:}, 'LineStyle','-','LineWidth',LINE_WIDTH,'Color',cm.MLSE);
|
||||
%
|
||||
%
|
||||
% figure; clf
|
||||
%
|
||||
% % Create meshgrid for contourf
|
||||
% [X, Y] = meshgrid(dsp_options.parameters.mu_dc, dsp_options.parameters.dc_buffer_len);
|
||||
%
|
||||
% % Create contour plot
|
||||
% contourf(X, Y, ber_mean', 20); % 20 contour levels, adjust as needed
|
||||
%
|
||||
% % Set axes to logarithmic scale
|
||||
% set(gca, 'XScale', 'log', 'YScale', 'log');
|
||||
%
|
||||
% colormap("parula");
|
||||
% c = colorbar;
|
||||
% c.Label.String = 'BER';
|
||||
%
|
||||
% xlabel('\mu_{dc}');
|
||||
% ylabel('dc\_buffer\_len');
|
||||
% title('BER Optimization over \mu_{dc} and dc\_buffer\_len');
|
||||
%
|
||||
% % Make plot prettier
|
||||
% grid on
|
||||
% set(gca, 'Layer', 'top'); % Put grid lines on top of contours
|
||||
%
|
||||
%
|
||||
% % === 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;
|
||||
% netrates_mlse = tp.calculateNetRate(baudrate.* m, ...
|
||||
% 'NGMI', GMI_MLSE./m, ...
|
||||
% 'BER', BER_MLSE);
|
||||
% plot(xGHz, netrates_mlse.SDHD.NetRate.*1e-9, ...
|
||||
% 'DisplayName','SD+HD MLSE', ...
|
||||
% mk.MLSE{:}, 'LineStyle',':','LineWidth',LINE_WIDTH,'Color',cm.MLSE);
|
||||
% plot(xGHz, netrates_mlse.HD.NetRate.*1e-9, ...
|
||||
% 'DisplayName','Staircase MLSE', ...
|
||||
% mk.MLSE{:}, 'LineStyle','-.','LineWidth',LINE_WIDTH,'Color',cm.MLSE);
|
||||
|
||||
|
||||
% duobinary has only one GMI curve (DB output)
|
||||
figure(1111); clf; hold on;
|
||||
plot(xGHz, GMI_DB.*xGHz, ...
|
||||
'DisplayName','GMI*R DB tgt.', ...
|
||||
mk.DB{:}, 'LineStyle','-','LineWidth',LINE_WIDTH,'Color',cm.DB);
|
||||
|
||||
netrates_db = tp.calculateNetRate(baudrate.* m, ...
|
||||
'NGMI', GMI_DB./m, ...
|
||||
'BER', BER_DB_PREC);
|
||||
|
||||
plot(xGHz, netrates_db.SDHD.NetRate.*1e-9, ...
|
||||
'DisplayName','SD+HD DB', ...
|
||||
mk.DB{:}, 'LineStyle',':','LineWidth',LINE_WIDTH,'Color',cm.DB);
|
||||
plot(xGHz, netrates_db.STAIR.NetRate.*1e-9, ...
|
||||
'DisplayName','Staircase DB', ...
|
||||
mk.DB_precode{:}, 'LineStyle','-.','LineWidth',LINE_WIDTH,'Color',cm.DB_precode);
|
||||
plot(xGHz, netrates_db.O_FEC.NetRate.*1e-9, ...
|
||||
'DisplayName','O-FEC DB', ...
|
||||
mk.DB_precode{:}, 'LineStyle','--','LineWidth',LINE_WIDTH,'Color',cm.DB_precode);
|
||||
plot(xGHz, netrates_db.KP4_hamming.NetRate.*1e-9, ...
|
||||
'DisplayName','KP4 Hamming DB', ...
|
||||
mk.DB_precode{:}, 'LineStyle',':','LineWidth',LINE_WIDTH,'Color',cm.DB_precode);
|
||||
|
||||
% ylim([log2(M)-1, log2(M)]);
|
||||
xlabel('Baudrate in GBd');
|
||||
ylabel('AIR in Gbps');
|
||||
set(gca, 'XTick', xticks_vals(1:2:end), 'XTickLabel', xtick_labels(1:2:end));
|
||||
grid on;
|
||||
legend('Location','best');
|
||||
% xlim([1, 256])
|
||||
|
||||
|
||||
|
||||
figure(2222); clf; hold on;
|
||||
plot(xGHz, GMI_MLSE.*xGHz, ...
|
||||
'DisplayName','GMI*R DB tgt.', ...
|
||||
mk.MLSE{:}, 'LineStyle','-','LineWidth',LINE_WIDTH,'Color',cm.MLSE);
|
||||
|
||||
netrates_mlse = tp.calculateNetRate(baudrate.* m, ...
|
||||
'NGMI', GMI_MLSE./m, ...
|
||||
'BER', BER_MLSE);
|
||||
|
||||
plot(xGHz, netrates_mlse.SDHD.NetRate.*1e-9, ...
|
||||
'DisplayName','SD+HD DB', ...
|
||||
mk.MLSE{:}, 'LineStyle',':','LineWidth',LINE_WIDTH,'Color',cm.MLSE);
|
||||
plot(xGHz, netrates_mlse.STAIR.NetRate.*1e-9, ...
|
||||
'DisplayName','Staircase DB', ...
|
||||
mk.VNLE{:}, 'LineStyle','-.','LineWidth',LINE_WIDTH,'Color',cm.VNLE);
|
||||
plot(xGHz, netrates_mlse.O_FEC.NetRate.*1e-9, ...
|
||||
'DisplayName','O-FEC DB', ...
|
||||
mk.VNLE{:}, 'LineStyle','--','LineWidth',LINE_WIDTH,'Color',cm.VNLE);
|
||||
plot(xGHz, netrates_mlse.KP4_hamming.NetRate.*1e-9, ...
|
||||
'DisplayName','KP4 Hamming DB', ...
|
||||
mk.VNLE{:}, 'LineStyle',':','LineWidth',LINE_WIDTH,'Color',cm.VNLE);
|
||||
|
||||
% ylim([log2(M)-1, log2(M)]);
|
||||
xlabel('Baudrate in GBd');
|
||||
ylabel('AIR in Gbps');
|
||||
set(gca, 'XTick', xticks_vals(1:2:end), 'XTickLabel', xtick_labels(1:2:end));
|
||||
grid on;
|
||||
legend('Location','best');
|
||||
% xlim([1, 256])
|
||||
|
||||
|
||||
|
||||
figure(3333); clf; hold on;
|
||||
plot(xGHz, GMI_VNLE.*xGHz, ...
|
||||
'DisplayName','GMI*R DB tgt.', ...
|
||||
mk.MLSE{:}, 'LineStyle','-','LineWidth',LINE_WIDTH,'Color',cm.MLSE);
|
||||
|
||||
netrates_vnle = tp.calculateNetRate(baudrate.* m, ...
|
||||
'NGMI', GMI_VNLE./m, ...
|
||||
'BER', BER_VNLE);
|
||||
|
||||
plot(xGHz, netrates_vnle.SDHD.NetRate.*1e-9, ...
|
||||
'DisplayName','SD+HD DB', ...
|
||||
mk.MLSE{:}, 'LineStyle',':','LineWidth',LINE_WIDTH,'Color',cm.MLSE);
|
||||
plot(xGHz, netrates_vnle.STAIR.NetRate.*1e-9, ...
|
||||
'DisplayName','Staircase DB', ...
|
||||
mk.VNLE{:}, 'LineStyle','-.','LineWidth',LINE_WIDTH,'Color',cm.VNLE);
|
||||
plot(xGHz, netrates_vnle.O_FEC.NetRate.*1e-9, ...
|
||||
'DisplayName','O-FEC DB', ...
|
||||
mk.VNLE{:}, 'LineStyle','--','LineWidth',LINE_WIDTH,'Color',cm.VNLE);
|
||||
plot(xGHz, netrates_vnle.KP4_hamming.NetRate.*1e-9, ...
|
||||
'DisplayName','KP4 Hamming DB', ...
|
||||
mk.VNLE{:}, 'LineStyle',':','LineWidth',LINE_WIDTH,'Color',cm.VNLE);
|
||||
|
||||
% ylim([log2(M)-1, log2(M)]);
|
||||
xlabel('Baudrate in GBd');
|
||||
ylabel('AIR in Gbps');
|
||||
set(gca, 'XTick', xticks_vals(1:2:end), 'XTickLabel', xtick_labels(1:2:end));
|
||||
grid on;
|
||||
legend('Location','best');
|
||||
% xlim([1, 256])
|
||||
@@ -1,7 +1,8 @@
|
||||
%%% Run parameters
|
||||
% TX
|
||||
M = 6;
|
||||
fsym = 112e9;
|
||||
m = floor(log2(M)*10)/10;
|
||||
fsym = 224e9;
|
||||
|
||||
apply_pulsef = 1;
|
||||
fdac = 256e9;
|
||||
@@ -9,20 +10,20 @@ fadc = 256e9;
|
||||
random_key = 2;
|
||||
|
||||
rcalpha = 0.05;
|
||||
kover = 16;
|
||||
kover = 8;
|
||||
vbias_rel = 0.5;
|
||||
u_pi = 2.9;
|
||||
u_pi = 3.2;
|
||||
vbias = -vbias_rel*u_pi;
|
||||
laser_wavelength = 1290;
|
||||
laser_linewidth = 0;
|
||||
laser_wavelength = 1310;
|
||||
laser_linewidth = 1e6;
|
||||
|
||||
|
||||
% Channel
|
||||
link_length = 10000;
|
||||
link_length = 0;
|
||||
|
||||
vnle_order1 = 50;
|
||||
vnle_order2 = 3;
|
||||
vnle_order3 = 3;
|
||||
vnle_order2 = 0;
|
||||
vnle_order3 = 0;
|
||||
|
||||
vnle_order=[vnle_order1,vnle_order2,vnle_order3];
|
||||
dfe_order = [0 0 0];
|
||||
@@ -43,20 +44,22 @@ mu_dfe = 0.0004;
|
||||
dfe_ = sum(dfe_order)>0;
|
||||
|
||||
doub_mode = db_mode.no_db;
|
||||
|
||||
rop = [-5];
|
||||
cols = linspecer(6);
|
||||
rop = [-6];
|
||||
bwl = [0.5:0.1:1.5];
|
||||
fsym = [72:8:170].*1e9;
|
||||
ber_vnle = [];
|
||||
fsym = [120:8:256].*1e9;
|
||||
fsym =150e9;
|
||||
|
||||
ber_vnle = [];
|
||||
ber_mlse = [];
|
||||
ber_viterbi = [];
|
||||
ber_db = [];
|
||||
ber_db_diff_precoded = [];
|
||||
gmi_vnle = [];
|
||||
gmi_vnle_bitwise = [];
|
||||
gmi_mlse = [];
|
||||
gmi_mlse_db = [];
|
||||
|
||||
parfor r = 1:length(fsym)
|
||||
for r = 1:length(fsym)
|
||||
|
||||
Pform = Pulseformer("fsym",fsym(r),"fdac",4*fsym(r),"pulse","rc","pulselength",16,"alpha",rcalpha);
|
||||
|
||||
@@ -74,29 +77,94 @@ parfor r = 1:length(fsym)
|
||||
"db_precode",db_precode,"db_encode",db_encode,...
|
||||
"mrds_code",0,"mrds_blocklength",512,"duobinary_mode",duob_mode).process();
|
||||
|
||||
El_sig = AWG("fdac",fdac,"f_cutoff",fsym(r),"lpf_active",0,"kover",kover,"bit_resolution",12,"upsampling_method","samplehold","precomp_sinc_rolloff",0).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",0).process(Digi_sig);
|
||||
El_sig = M8199B("kover",kover).process(Digi_sig);
|
||||
% AWG("fdac",fdac,"f_cutoff",fsym(r),"lpf_active",0,"kover",kover,"bit_resolution",12,"upsampling_method","samplehold","precomp_sinc_rolloff",0).process(Digi_sig);
|
||||
|
||||
%%%%% Low-pass el. components %%%%%%
|
||||
tx_bwl = 50e9;
|
||||
El_sig = Filter('filtdegree',4,"f_cutoff",tx_bwl,"fs",fdac*kover,"filterType",filtertypes.butterworth,"active",true).process(El_sig);
|
||||
% tx_bwl = 100e9;
|
||||
% El_sig = Filter('filtdegree',3,"f_cutoff",tx_bwl,"fs",fdac*kover,"filterType",filtertypes.butterworth,"active",true).process(El_sig);
|
||||
|
||||
%%%%% Electrical Driver Amplifier %%%%%%
|
||||
El_sig = El_sig.normalize("mode","oneone");
|
||||
% El_sig = El_sig.setPower(1,"dBm");
|
||||
% figure;histogram(El_sig.signal);
|
||||
|
||||
%%%%% MODULATE E/O CONVERSION %%%%%%
|
||||
%%%%% MODULATE E/O CONVERSION %%%%%
|
||||
u_pi = 3.2;
|
||||
vbias = -u_pi*0.5;
|
||||
[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);
|
||||
|
||||
|
||||
figure(15);
|
||||
hold on
|
||||
scatter(El_sig.signal(1:100000)+vbias,(abs(Opt_sig.signal(1:100000)).^2)*1e3,0.1,'.','DisplayName','Modulator TF')
|
||||
xlabel('Input in V')
|
||||
ylabel('abs(Eopt)2 in mW','Interpreter','latex')
|
||||
ylim([0 2]);
|
||||
xlim([-3.2 0]);
|
||||
|
||||
Opt_sig.eye(fsym(r),M,"fignum",103837);
|
||||
|
||||
%%%%%% Fiber %%%%%%
|
||||
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 %%%%%%
|
||||
Opt_sig = Amplifier("amp_mode","ideal_no_noise","gain_mode","output_power","amplification_db",rop).process(Opt_sig);
|
||||
|
||||
|
||||
% Opt_sig.eye(fsym(r),M,"fignum",103838);
|
||||
|
||||
% % Opt_sig.signal = Opt_sig.signal + 5*abs(mean(Opt_sig.signal));
|
||||
% Opt_sig.move_it_spectrum("displayname",'Opt Sig after Amp','fignum',1223323);
|
||||
% Pc = abs(mean(Opt_sig.signal)).^2; % carrier power
|
||||
% Ptot = mean(abs(Opt_sig.signal).^2); % total power
|
||||
% Ps = max(Ptot - Pc, eps);
|
||||
% Pcdb = 10*log10(Pc);
|
||||
% Psdb = 10*log10(Ps);
|
||||
%
|
||||
% cspr_dB = 10*log10(Pc / Ps);
|
||||
%
|
||||
% % Minimal in-place CSPR set (real, nonnegative field constraint)
|
||||
% E = Opt_sig.signal; % real field samples
|
||||
% target_cspr_dB = 20; % <-- set your target CSPR (dB)
|
||||
%
|
||||
% % Decompose into DC + zero-mean waveform
|
||||
% m = mean(E);
|
||||
% x0 = E - m; % zero-mean modulation
|
||||
% Ps0 = mean(x0.^2); % sideband power (fixed if shape kept)
|
||||
%
|
||||
% % Current CSPR (for reference)
|
||||
% Pc_cur = m^2;
|
||||
% Ptot_cur = mean(E.^2);
|
||||
% Ps_cur = max(Ptot_cur - Pc_cur, eps);
|
||||
% cspr_in = 10*log10(Pc_cur / Ps_cur);
|
||||
%
|
||||
% % Bias needed for target CSPR, and minimal bias to keep E>=0
|
||||
% R_tgt = 10^(target_cspr_dB/10); % Pc/Ps
|
||||
% a_req = sqrt(R_tgt * Ps0); % required DC bias
|
||||
% a_min = -min(x0); % to avoid negatives everywhere
|
||||
% a = max(a_req, a_min); % if infeasible, lands at CSPR_min
|
||||
%
|
||||
% % Apply bias (preserves waveform shape)
|
||||
% E_new = a + x0;
|
||||
%
|
||||
% % Achieved CSPR
|
||||
% Pc_new = mean(E_new)^2;
|
||||
% Ptot_new = mean(E_new.^2);
|
||||
% Ps_new = max(Ptot_new - Pc_new, eps);
|
||||
% cspr_out = 10*log10(Pc_new / Ps_new);
|
||||
%
|
||||
% % (Optional) show feasibility info
|
||||
% cspr_min = 10*log10((a_min^2)/max(Ps0,eps));
|
||||
% disp(table(cspr_in, target_cspr_dB, cspr_min, cspr_out));
|
||||
%
|
||||
% % Use E_new as your adjusted field
|
||||
% Opt_sig.signal = E_new;
|
||||
|
||||
%%%%%% PD Square Law %%%%%%
|
||||
PD_sig = Photodiode("fsimu",fdac*kover,"dark_current",2e-08,"responsivity",1,"temperature",20,"nep",1.8e-11,"randomkey",random_key).process(Opt_sig);
|
||||
|
||||
|
||||
%%%%%% Low-pass RX (PD, El. Connectors and Scope %%%%%%
|
||||
rx_bwl = 50e9;
|
||||
rx_bwl = 70e9;
|
||||
PD_sig = Filter('filtdegree',4,"f_cutoff",rx_bwl,"fs",fdac*kover,"filterType",filtertypes.butterworth,"active",true).process(PD_sig);
|
||||
|
||||
% %%%%%% Low-pass Scope %%%%%%
|
||||
@@ -113,21 +181,29 @@ parfor r = 1:length(fsym)
|
||||
|
||||
[~, Scpe_cell, ~, found_sync] = Scpe_sig_2sps.tsynch("reference", Symbols, "fs_ref", fsym(r), "debug_plots", 0);
|
||||
Rx_sig = Scpe_cell{1};
|
||||
Rx_sig = Rx_sig.normalize("mode","rms");
|
||||
|
||||
if 1
|
||||
if 0
|
||||
%Duobinary Targeting
|
||||
|
||||
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);
|
||||
|
||||
|
||||
|
||||
db_ref_sequence = Duobinary().encode(Symbols);
|
||||
db_ref_constellation = unique(db_ref_sequence.signal);
|
||||
[eq_signal, eq_noise] = eq_.process(Rx_sig,db_ref_sequence);
|
||||
|
||||
mlse_.DIR = [1,1];
|
||||
[mlse_sig_sd,LLR,gmi_mlse_db(r)] = mlse_.process(eq_signal,Symbols);
|
||||
|
||||
|
||||
viterbi = 0;
|
||||
if viterbi
|
||||
mlse_ = MLSE_viterbi("duobinary_output",0,'M',M,'trellis_states',PAMmapper(M,0).levels);
|
||||
mlse_.DIR = [1,1];
|
||||
[mlse_sig_sd] = mlse_.process(eq_signal);
|
||||
else
|
||||
mlse_ = MLSE("DIR",[1,1],"duobinary_output",0,"M",M,"trellis_states",PAMmapper(M,0).get_levels ./ PAMmapper(M,0).get_scaling);
|
||||
mlse_.DIR = [1,1];
|
||||
[mlse_sig_sd,LLR,gmi_mlse_db(r)] = mlse_.process(eq_signal,Symbols);
|
||||
end
|
||||
|
||||
mlse_sig_hd = PAMmapper(M,0,"eth_style",0).quantize(mlse_sig_sd);
|
||||
mlse_sig_hd_precoded = Duobinary().encode(mlse_sig_hd,"M",M);
|
||||
mlse_sig_hd_precoded = Duobinary().decode(mlse_sig_hd_precoded,"M",M);
|
||||
@@ -138,48 +214,84 @@ parfor r = 1:length(fsym)
|
||||
tx_bits_precoded = PAMmapper(M,0,"eth_style",0).demap(tx_symbols_precoded);
|
||||
|
||||
rx_bits_mlse = PAMmapper(M,0,"eth_style",0).demap(mlse_sig_hd_precoded);
|
||||
[~,errors_db_diff_precoded,ber_db_diff_precoded(r),~] = calc_ber(rx_bits_mlse.signal,tx_bits_precoded.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1);
|
||||
[~,errors_db_diff_precoded,ber_db_diff_precoded(r),a] = calc_ber(rx_bits_mlse.signal,tx_bits_precoded.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1);
|
||||
burst_db_pre(r,:) = count_error_bursts(a, 15)./numel(Tx_bits.signal);
|
||||
|
||||
%B) Just determine BER
|
||||
rx_bits_mlse = PAMmapper(M,0,"eth_style",0).demap(mlse_sig_hd);
|
||||
[bits_mlse,errors_mlse,ber_db(r),~] = calc_ber(rx_bits_mlse.signal,Tx_bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1);
|
||||
[bits_mlse,errors_db,ber_db(r),a] = calc_ber(rx_bits_mlse.signal,Tx_bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1);
|
||||
burst_db(r,:) = count_error_bursts(a, 15)./numel(Tx_bits.signal);
|
||||
|
||||
fprintf('BER ber_db_diff_precoded: %.2e \n',ber_db_diff_precoded(r));
|
||||
fprintf('BER Vber_dbNLE: %.2e \n',ber_db(r));
|
||||
% figure();hold on;stem(1:15,burst_db(r,:),'LineWidth',1,'Color',cols(1,:));stem(1:15,burst_db_pre(r,:),'LineWidth',1,'Color',cols(2,:));set(gca, 'yscale', 'log');
|
||||
|
||||
end
|
||||
|
||||
|
||||
% FFE or VNLE
|
||||
eq_ = EQ("Ne",[vnle_order1,vnle_order2,vnle_order3],"Nb",[dfe_order],"training_length",len_tr,"training_loops",5,"dd_loops",5,"K",2,"DCmu",mu_dc,"DDmu",[mu_ffe mu_dfe],"DFEmu",0.005,"FFEmu",0,"plotfinal",0,"ideal_dfe",1);
|
||||
eq_ = EQ("Ne",[vnle_order1,vnle_order2,vnle_order3],"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.00,"FFEmu",0,"plotfinal",0,"ideal_dfe",0);
|
||||
% eq = VNLE("epochs_tr",5,"epochs_dd",5,"len_tr",4096*2,"mu_dd",[0.0004 0.0005 0.0006],"mu_tr",0,"order",[50,2,2],"sps",2,"decide",0);
|
||||
|
||||
[eq_signal_sd, eq_noise] = eq_.process(Rx_sig, Symbols);
|
||||
|
||||
[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);
|
||||
showEQNoisePSD(eq_noise, "fignum",1273876,"displayname",'noise after EQ');
|
||||
[mi_gomez(r)] = calc_air(eq_signal_sd, Symbols, "skip_front", 100, "skip_end", 100);
|
||||
[gmi_vnle_bitwise(r)] = calc_ngmi(eq_signal_sd,Symbols);
|
||||
[gmi_bitwise_2(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',199);
|
||||
eq_signal_sd.eye(fsym(r),M,"fignum",103837);
|
||||
|
||||
|
||||
% 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);
|
||||
[~,~,ber_vnle(r),~] = calc_ber(rx_bits.signal,Tx_bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1);
|
||||
[~,tot_err,ber_vnle(r),a] = calc_ber(rx_bits.signal,Tx_bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1);
|
||||
burst_vnle(r,:) = count_error_bursts(a, 10)./tot_err;
|
||||
|
||||
showLevelConfusionMatrix(eq_signal_hd,Symbols,"M",M,"fignum",200,"displayname",'bla');
|
||||
showLevelScatter(eq_signal_sd,Symbols,"displayname",'VNLE Out','f_sym',fsym(r),'fignum',201);
|
||||
show2Dconstellation(eq_signal_sd,Symbols,"displayname",'VNLE Out','fignum',2241);
|
||||
|
||||
fprintf('BER VNLE: %.2e \n',ber_vnle(r));
|
||||
fprintf('NGMI VNLE: %.2f \n',gmi_vnle(r)./log2(M));
|
||||
fprintf('NGMI VNLE: %.2f \n',gmi_vnle_bitwise(r)./m);
|
||||
|
||||
|
||||
if 1
|
||||
|
||||
% Process through postfilter and MLSE
|
||||
pf_ncoeffs = 1;
|
||||
pf_ = Postfilter("ncoeff",pf_ncoeffs,"useBurg",1);
|
||||
mlse_ = MLSE("duobinary_output",0,'M',M,'trellis_states',PAMmapper(M,0).levels);
|
||||
if fsym(r) < 200e9
|
||||
pf_ = Postfilter("ncoeff",pf_ncoeffs,"useBurg",1,"coefficients",[1,0.1]);
|
||||
else
|
||||
pf_ = Postfilter("ncoeff",pf_ncoeffs,"useBurg",1,"coefficients",[1,0.85]);
|
||||
end
|
||||
|
||||
mlse_ = MLSE("duobinary_output",0,'M',M,'trellis_states',PAMmapper(M,0).get_levels ./ PAMmapper(M,0).get_scaling);
|
||||
[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('GMI MLSE: %.5f \n',gmi_mlse(r));
|
||||
|
||||
|
||||
[~,tot_err,ber_mlse(r),a] = calc_ber(rx_bits.signal,Tx_bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1);
|
||||
burst_mlse(r,:) = count_error_bursts(a, 10);
|
||||
|
||||
showLevelConfusionMatrix(mlse_sig_hd,Symbols,"M",M,"fignum",300,"displayname",'bla');
|
||||
|
||||
fprintf('BER MLSE: %.2e \n',ber_mlse(r));
|
||||
fprintf('NGMI MLSE: %.5f \n',gmi_mlse(r)./m);
|
||||
|
||||
levels = sort(unique(Symbols.signal(:)).'); % 1×6
|
||||
pairs = reshape(mlse_sig_hd.signal,2,[]).';
|
||||
isedge = ismember(pairs, [levels(1) levels(end)]);
|
||||
isforbidden = sum(isedge,2)==2;
|
||||
fprintf('Found %d forbidden transitions (even→odd edges).\n', nnz(isforbidden));
|
||||
|
||||
|
||||
% Process through postfilter and MLSE
|
||||
pf_ncoeffs = 1;
|
||||
pf_ = Postfilter("ncoeff",pf_ncoeffs,"useBurg",1);
|
||||
@@ -198,36 +310,166 @@ parfor r = 1:length(fsym)
|
||||
|
||||
end
|
||||
|
||||
cols = cbrewer2('Paired',8);
|
||||
d = 1;
|
||||
|
||||
figure(11);hold on
|
||||
plot(fsym.*1e-9,alpha,'DisplayName','VNLE','Marker','x','LineStyle','-','Color',cols(1+d,:));
|
||||
|
||||
|
||||
% --- style control (one variable controls both marker size and linewidth) ---
|
||||
STYLE_BASE = 2; % adjust this single number to scale markers & lines
|
||||
MARKER_SIZE = STYLE_BASE; % marker size (MATLAB MarkerSize)
|
||||
LINE_WIDTH = max(1.5, STYLE_BASE/3); % line width (keeps lines reasonable when STYLE_BASE large)
|
||||
|
||||
% --- color map / method -> color assignment (keeps colors consistent) ---
|
||||
cols = cbrewer2('Paired',8);
|
||||
cols = linspecer(6);
|
||||
d = 0;
|
||||
cm.VNLE = cols(1 + d, :);
|
||||
cm.MLSE = cols(2 + d, :);
|
||||
cm.DB_precode = cols(3 + d, :);
|
||||
cm.DB = cols(4 + d, :); % duobinary
|
||||
|
||||
% prepare x values in GBd
|
||||
xGHz = fsym .* 1e-9;
|
||||
xticks_vals = xGHz;
|
||||
xtick_labels = arrayfun(@(v) sprintf('%d', round(v)), xticks_vals, 'UniformOutput', false);
|
||||
|
||||
% common marker settings (filled, same face+edge color)
|
||||
mk.VNLE = {'Marker','none','MarkerFaceColor',cm.MLSE,'MarkerEdgeColor',cm.VNLE,'MarkerSize',MARKER_SIZE};
|
||||
mk.MLSE = {'Marker','none','MarkerFaceColor',cm.MLSE,'MarkerEdgeColor',cm.MLSE,'MarkerSize',MARKER_SIZE};
|
||||
mk.DB_precode = {'Marker','none','MarkerFaceColor',cm.DB_precode,'MarkerEdgeColor',cm.DB_precode,'MarkerSize',MARKER_SIZE};
|
||||
mk.DB = {'Marker','none','MarkerFaceColor',cm.DB,'MarkerEdgeColor',cm.DB,'MarkerSize',MARKER_SIZE};
|
||||
|
||||
% ---------------- FIGURE 11 : alpha (VNLE) ----------------
|
||||
figure(110+M); clf; hold on;
|
||||
plot(xGHz, alpha, ...
|
||||
'DisplayName','VNLE', ...
|
||||
mk.VNLE{:}, 'LineStyle','-','LineWidth',LINE_WIDTH,'Color',cm.VNLE);
|
||||
xlabel('Baudrate in GBd');
|
||||
ylabel('alpha');
|
||||
set(gca, 'XTick', xticks_vals, 'XTickLabel', xtick_labels);
|
||||
grid on;
|
||||
legend('Location','best');
|
||||
|
||||
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','*');
|
||||
plot(fsym.*1e-9,gmi_mlse_db,'DisplayName','DB Output','Marker','*');
|
||||
ylim([log2(M)-1 log2(M)]);
|
||||
% ---------------- FIGURE 15 : GMI ----------------
|
||||
figure(111+M); clf; hold on;
|
||||
plot(xGHz, mi_gomez, ...
|
||||
'DisplayName','MI VNLE', ...
|
||||
mk.VNLE{:}, 'LineStyle',':','LineWidth',LINE_WIDTH,'Color',cm.VNLE);
|
||||
plot(xGHz, gmi_vnle_bitwise, ...
|
||||
'DisplayName','GMI VNLE', ...
|
||||
mk.VNLE{:}, 'LineStyle','-','LineWidth',LINE_WIDTH,'Color',cm.VNLE);
|
||||
% duobinary has only one GMI curve (DB output)
|
||||
plot(xGHz, gmi_mlse_db, ...
|
||||
'DisplayName','GMI DB tgt.', ...
|
||||
mk.DB{:}, 'LineStyle','-','LineWidth',LINE_WIDTH,'Color',cm.DB);
|
||||
% MLSE symbol-wise (if present)
|
||||
plot(xGHz, gmi_mlse, ...
|
||||
'DisplayName','GMI MLSE', ...
|
||||
mk.MLSE{:}, 'LineStyle','-','LineWidth',LINE_WIDTH,'Color',cm.MLSE);
|
||||
|
||||
ylim([log2(M)-1, log2(M)]);
|
||||
xlabel('Baudrate in GBd');
|
||||
ylabel('GMI');
|
||||
set(gca, 'XTick', xticks_vals(1:2:end), 'XTickLabel', xtick_labels(1:2:end));
|
||||
grid on;
|
||||
legend('Location','best');
|
||||
% xlim([184, 256])
|
||||
|
||||
% ---------------- FIGURE 13 : BER ----------------
|
||||
figure(312+M); hold on;
|
||||
plot(xGHz, ber_vnle, ...
|
||||
'DisplayName','VNLE', ...
|
||||
mk.VNLE{:}, 'LineStyle','-','LineWidth',LINE_WIDTH,'Color',cm.VNLE);
|
||||
plot(xGHz, ber_mlse, ...
|
||||
'DisplayName','MLSE', ...
|
||||
mk.MLSE{:}, 'LineStyle','-','LineWidth',LINE_WIDTH,'Color',cm.MLSE);
|
||||
plot(xGHz, ber_viterbi, ...
|
||||
'DisplayName','Viterbi', ...
|
||||
mk.MLSE{:}, 'LineStyle','--','LineWidth',LINE_WIDTH,'Color',cm.MLSE);
|
||||
|
||||
yline(4.85e-3,'LineWidth',1,'HandleVisibility','off');
|
||||
yline(2.2e-4,'LineWidth',1,'HandleVisibility','off');
|
||||
|
||||
plot(xGHz, ber_db, ...
|
||||
'DisplayName','DB tgt.', ...
|
||||
mk.DB{:}, 'LineStyle','-','LineWidth',LINE_WIDTH,'Color',cm.DB);
|
||||
|
||||
plot(xGHz, ber_db_diff_precoded, ...
|
||||
'DisplayName','Prec. + DB tgt.', ...
|
||||
mk.DB{:}, 'LineStyle',':','LineWidth',LINE_WIDTH,'Color',cm.DB);
|
||||
|
||||
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(fsym.*1e-9,ber_db_diff_precoded,'DisplayName','MLSE db diff','Marker','.','MarkerSize',15,'LineStyle','-');
|
||||
plot(fsym.*1e-9,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
|
||||
set(gca, 'XTick', xticks_vals(1:2:end), 'XTickLabel', xtick_labels(1:2:end));
|
||||
grid on;
|
||||
legend('Location','best');
|
||||
% xlim([184, 256])
|
||||
|
||||
% ---------------- FIGURE 15 : Information Rates ----------------
|
||||
tp = TransmissionPerformance;
|
||||
|
||||
|
||||
m = floor(log2(M)*10)/10;
|
||||
figure(113+M); clf; hold on;
|
||||
|
||||
netrates_vnle = tp.calculateNetRate(fsym.* m, ...
|
||||
'NGMI', gmi_vnle_bitwise./m, ...
|
||||
'BER', ber_vnle);
|
||||
%
|
||||
plot(xGHz, gmi_vnle_bitwise.*xGHz, ...
|
||||
'DisplayName','GMI*R VNLE', ...
|
||||
mk.VNLE{:}, 'LineStyle','-','LineWidth',LINE_WIDTH,'Color',cm.VNLE);
|
||||
|
||||
plot(xGHz, netrates_vnle.SDHD.NetRate.*1e-9, ...
|
||||
'DisplayName','SD+HD VNLE', ...
|
||||
mk.VNLE{:}, 'LineStyle',':','LineWidth',LINE_WIDTH,'Color',cm.VNLE);
|
||||
plot(xGHz, netrates_vnle.HD.NetRate.*1e-9, ...
|
||||
'DisplayName','Staircase VNLE', ...
|
||||
mk.VNLE{:}, 'LineStyle','-.','LineWidth',LINE_WIDTH,'Color',cm.VNLE);
|
||||
|
||||
|
||||
%
|
||||
% MLSE symbol-wise (if present)
|
||||
plot(xGHz, gmi_mlse.*xGHz, ...
|
||||
'DisplayName','GMI*R MLSE', ...
|
||||
mk.MLSE{:}, 'LineStyle','-','LineWidth',LINE_WIDTH,'Color',cm.MLSE);
|
||||
|
||||
netrates_mlse = tp.calculateNetRate(fsym.* m, ...
|
||||
'NGMI', gmi_mlse./m, ...
|
||||
'BER', ber_mlse);
|
||||
plot(xGHz, netrates_mlse.SDHD.NetRate.*1e-9, ...
|
||||
'DisplayName','SD+HD MLSE', ...
|
||||
mk.MLSE{:}, 'LineStyle',':','LineWidth',LINE_WIDTH,'Color',cm.MLSE);
|
||||
plot(xGHz, netrates_mlse.HD.NetRate.*1e-9, ...
|
||||
'DisplayName','Staircase MLSE', ...
|
||||
mk.MLSE{:}, 'LineStyle','-.','LineWidth',LINE_WIDTH,'Color',cm.MLSE);
|
||||
|
||||
|
||||
% duobinary has only one GMI curve (DB output)
|
||||
plot(xGHz, gmi_mlse_db.*xGHz, ...
|
||||
'DisplayName','GMI*R DB tgt.', ...
|
||||
mk.DB{:}, 'LineStyle','-','LineWidth',LINE_WIDTH,'Color',cm.DB);
|
||||
|
||||
netrates_db = tp.calculateNetRate(fsym.* m, ...
|
||||
'NGMI', gmi_mlse_db./m, ...
|
||||
'BER', ber_db);
|
||||
|
||||
plot(xGHz, netrates_db.SDHD.NetRate.*1e-9, ...
|
||||
'DisplayName','SD+HD DB', ...
|
||||
mk.DB{:}, 'LineStyle',':','LineWidth',LINE_WIDTH,'Color',cm.DB);
|
||||
plot(xGHz, netrates_db.HD.NetRate.*1e-9, ...
|
||||
'DisplayName','Staircase DB', ...
|
||||
mk.DB{:}, 'LineStyle','-.','LineWidth',LINE_WIDTH,'Color',cm.DB);
|
||||
|
||||
|
||||
|
||||
% ylim([log2(M)-1, log2(M)]);
|
||||
xlabel('Baudrate in GBd');
|
||||
ylabel('AIR in Gbps');
|
||||
set(gca, 'XTick', xticks_vals(1:2:end), 'XTickLabel', xtick_labels(1:2:end));
|
||||
grid on;
|
||||
legend('Location','best');
|
||||
xlim([184, 256])
|
||||
|
||||
% Auxiliary nested helper for numerically stable log-sum-exp
|
||||
function s = logsumexp(a)
|
||||
|
||||
268
projects/WDM/WDM_model.m
Normal file
268
projects/WDM/WDM_model.m
Normal file
@@ -0,0 +1,268 @@
|
||||
%%% Run parameters
|
||||
% TX
|
||||
|
||||
M = 4;
|
||||
m = floor(log2(M)*10)/10;
|
||||
fsym = 224e9;
|
||||
|
||||
apply_pulsef = 1;
|
||||
fdac = 2*fsym;
|
||||
fadc = 2*fsym;
|
||||
random_key = 2;
|
||||
|
||||
rcalpha = 0.05;
|
||||
kover = 8;
|
||||
vbias_rel = 0.5;
|
||||
u_pi = 3.2;
|
||||
vbias = -vbias_rel*u_pi;
|
||||
|
||||
laser_linewidth = 0e6;
|
||||
|
||||
|
||||
% Channel
|
||||
link_length = 2;
|
||||
rop = -5;
|
||||
|
||||
vnle_order1 = 50;
|
||||
vnle_order2 = 0;
|
||||
vnle_order3 = 0;
|
||||
|
||||
vnle_order=[vnle_order1,vnle_order2,vnle_order3];
|
||||
dfe_order = [0 0 0];
|
||||
|
||||
alpha = 0;
|
||||
|
||||
len_tr = 4096*2;
|
||||
|
||||
mu_ffe1 = 0.0001;
|
||||
mu_ffe2 = 0.0008;
|
||||
mu_ffe3 = 0.001;
|
||||
mu_dc = 0.005;
|
||||
% mu_dc = 0;
|
||||
|
||||
mu_ffe = [mu_ffe1 mu_ffe3 mu_ffe3];
|
||||
mu_dfe = 0.0004;
|
||||
|
||||
dfe_ = sum(dfe_order)>0;
|
||||
|
||||
doub_mode = db_mode.no_db;
|
||||
cols = linspecer(6);
|
||||
|
||||
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 = 0;
|
||||
|
||||
|
||||
% AWG("fdac",fdac,"f_cutoff",fsym,"lpf_active",0,"kover",kover,"bit_resolution",12,"upsampling_method","samplehold","precomp_sinc_rolloff",0).process(Digi_sig);
|
||||
|
||||
%%%%% Low-pass el. components %%%%%%
|
||||
% tx_bwl = 100e9;
|
||||
% El_sig = Filter('filtdegree',3,"f_cutoff",tx_bwl,"fs",fdac*kover,"filterType",filtertypes.butterworth,"active",true).process(El_sig);
|
||||
|
||||
wavelengthplan = calcWavelengthPlan(16,400e9,1310);
|
||||
wavelengthplan = [1295,1305,1315,1325];
|
||||
N = numel(wavelengthplan);
|
||||
f_plan = physconst('lightspeed')./(wavelengthplan.*1e-9);
|
||||
margin = 25e12; % some THz left and right
|
||||
f_span = (max(f_plan)+margin)-(min(f_plan)-margin);
|
||||
f_nyq = f_span/2;
|
||||
|
||||
upsample_required = f_nyq./(fdac*kover/2);
|
||||
upsample_pow = 2^nextpow2(upsample_required);
|
||||
upsample_ceil = ceil(upsample_required);
|
||||
|
||||
f_opt = fdac*kover*upsample_pow;
|
||||
f_opt_nyq = f_opt/2;
|
||||
|
||||
signal_cell = {};
|
||||
Symbols = {};
|
||||
Tx_bits = {};
|
||||
|
||||
rop = linspace(-11,0,6); %12 workers when parallel
|
||||
|
||||
num_realiz = 10;
|
||||
gmi_vnle_bitwise = NaN(length(wavelengthplan),length(rop),num_realiz);
|
||||
snr_vnle= NaN(length(wavelengthplan),length(rop),num_realiz);
|
||||
ber_vnle= NaN(length(wavelengthplan),length(rop),num_realiz);
|
||||
|
||||
for realiz = 1:num_realiz
|
||||
|
||||
for l = 1:N
|
||||
|
||||
[Digi_sig,Symbols{l},Tx_bits{l}] = 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+l+realiz,...
|
||||
"db_precode",db_precode,"db_encode",db_encode,...
|
||||
"mrds_code",0,"mrds_blocklength",512,"duobinary_mode",duob_mode).process();
|
||||
|
||||
% Digi_sig.spectrum("fignum",101,"displayname",'bla','normalizeTo0dB',0,'lambda0_nm',1310,'useWavelengthAxis',0);
|
||||
Lp_awg = Filter('filtdegree',3,"f_cutoff",100e9,"fs",fdac*kover,"filterType",filtertypes.gaussian,"active",true);
|
||||
El_sig = AWG("fdac",fdac,"f_cutoff",fsym,"lpf_active",1,"kover",kover,"bit_resolution",12,"upsampling_method","samplehold","precomp_sinc_rolloff",0,"H_lpf",Lp_awg,"dac_max",0.6,"dac_min",-0.6).process(Digi_sig);
|
||||
% El_sig = M8199B("kover",kover).process(Digi_sig);
|
||||
% El_sig.spectrum("fignum",101,"displayname",'bla','normalizeTo0dB',0,'lambda0_nm',1310,'useWavelengthAxis',0);
|
||||
|
||||
%%%%% Electrical Driver Amplifier %%%%%%
|
||||
El_sig = El_sig.normalize("mode","oneone");
|
||||
% El_sig = El_sig.setPower(1,"dBm");
|
||||
% figure;histogram(El_sig.signal);
|
||||
|
||||
%%%%% MODULATE E/O CONVERSION %%%%%
|
||||
Eml_out = EML("mode",eml_mode.im_cosinus,"power",3,"fsimu",El_sig.fs,"lambda",wavelengthplan(l),"bias",vbias,"u_pi",u_pi,"linewidth",laser_linewidth,"randomkey",random_key+l+realiz).process(El_sig);
|
||||
|
||||
signal_cell{l} = Polarization_Controller("mode","rot_power","desired_power",30).process(Eml_out);
|
||||
end
|
||||
|
||||
Opt_sig_wdm = Optical_Multiplex("fs_in",signal_cell{l}.fs,"fs_out",upsample_pow*Eml_out.fs,...
|
||||
"lambda_center",1310,"random_key",0,"filtype",1,"B",200e9).process(signal_cell);
|
||||
|
||||
Opt_sig_wdm = Amplifier("amp_mode","ideal_no_noise","gain_mode","output_power","amplification_db",3+10*log10(N)).process(Opt_sig_wdm);
|
||||
|
||||
% Opt_sig_wdm.spectrum("fignum",101,"displayname",'bla','normalizeTo0dB',0,'lambda0_nm',1310,'useWavelengthAxis',0);
|
||||
|
||||
% Opt_sig_wdm.spectrum("fignum",101,"displayname",'bla','normalizeTo0dB',1,'max_num_lines',2);
|
||||
|
||||
%%%%%% Fiber %%%%%%
|
||||
Opt_sig_wdm_fib=Opt_sig_wdm;
|
||||
|
||||
nSegments = 2;
|
||||
zdw = 1310;
|
||||
D_local = 0; %if ~=0, simulation uses "segmented fiber with d+,d-)
|
||||
randomize_D = true;
|
||||
Dvec = getDispersionVector(nSegments, D_local, zdw, randomize_D, random_key+realiz);
|
||||
for s = 1:nSegments
|
||||
|
||||
Opt_sig_wdm_fib = DP_Fiber("L",link_length/nSegments,"D",Dvec(s),"Dpmd",0.1,"Ds",0.06,...
|
||||
"beat_len",10,"corr_len",100,"dz",1,"manakov",0,...
|
||||
"gamma",0.0023,"lambda",zdw,"n_waveplates",10,"SS_dphimax",0.01,...
|
||||
"SS_dzmax",50,"SS_dzmin",10,"X_alpha",0.3,"X_beta",0,"rng",1).process(Opt_sig_wdm_fib);
|
||||
|
||||
end
|
||||
|
||||
Opt_sig_wdm_fib.spectrum("fignum",realiz,"displayname",'bla','lambda0_nm',1310,'useWavelengthAxis',0);
|
||||
|
||||
% Opt_sig_wdm_fib.move_it_spectrum("fignum",100212,"displayname",'bla');
|
||||
|
||||
% 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)
|
||||
|
||||
parfor ri = 1:length(rop)
|
||||
|
||||
%%%%%% ROP %%%%%%
|
||||
Opt_sig_wdm_rx = Amplifier("amp_mode","ideal_no_noise","gain_mode","output_power","amplification_db",rop(ri)+10*log10(N)).process(Opt_sig_wdm_fib);
|
||||
|
||||
Opt_sig_wdm_demux = Optical_Demultiplex("attenuation",0,"B",200e9,"filtype",1,"fs_out",Opt_sig_wdm_rx.fs/upsample_pow,"fs_in",Opt_sig_wdm_rx.fs,"lambda_center",1310).process(Opt_sig_wdm_rx);
|
||||
|
||||
PD_cell = {};
|
||||
for l = 1:N
|
||||
|
||||
%%%%%% PD Square Law %%%%%%
|
||||
assert(fdac*kover==Opt_sig_wdm_demux{l}.fs,'Sampling Frequencies do not match! Check previous steps');
|
||||
PD_sig = Photodiode("fsimu",fdac*kover,"dark_current",2e-08,"responsivity",1,"temperature",20,"nep",1.8e-11,"randomkey",random_key+l+realiz).process(Opt_sig_wdm_demux{l});
|
||||
|
||||
PD_sig.spectrum("fignum",222,"displayname",'bla','normalizeTo0dB',1);
|
||||
|
||||
%%%%%% Low-pass RX (PD, El. Connectors and Scope %%%%%%
|
||||
rx_bwl = 100e9;
|
||||
PD_sig = Filter('filtdegree',4,"f_cutoff",rx_bwl,"fs",fdac*kover,"filterType",filtertypes.butterworth,"active",true).process(PD_sig);
|
||||
|
||||
% %%%%%% Low-pass Scope %%%%%%
|
||||
Lp_scpe = Filter('filtdegree',4,"f_cutoff",110e9,"fs",fadc,"filterType",filtertypes.butterworth,"active",true);
|
||||
|
||||
%%%%%% 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(PD_sig);
|
||||
|
||||
Scpe_sig_2sps = Scpe_sig.resample("fs_out",2*fsym);
|
||||
% Scpe_sig.spectrum("fignum",222,"displayname",'bla','normalizeTo0dB',1);
|
||||
|
||||
[~, Scpe_cell, ~, found_sync] = Scpe_sig_2sps.tsynch("reference", Symbols{l}, "fs_ref", fsym, "debug_plots", 1);
|
||||
Rx_sig = Scpe_cell{1};
|
||||
Rx_sig = Rx_sig.normalize("mode","rms");
|
||||
|
||||
% FFE or VNLE
|
||||
eq_ = EQ("Ne",[vnle_order1,vnle_order2,vnle_order3],"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.00,"FFEmu",0,"plotfinal",0,"ideal_dfe",0);
|
||||
|
||||
[eq_signal_sd, eq_noise] = eq_.process(Rx_sig, Symbols{l});
|
||||
showEQNoisePSD(eq_noise, "fignum",1273876,"displayname",'noise after EQ');
|
||||
[mi_gomez] = calc_air(eq_signal_sd, Symbols{l}, "skip_front", 100, "skip_end", 100);
|
||||
[gmi_vnle_bitwise(l,ri,realiz)] = calc_ngmi(eq_signal_sd,Symbols{l});
|
||||
% [gmi_bitwise_2] = calc_gmi_bitwise(eq_signal_sd,Symbols{l});
|
||||
snr_vnle(l,ri,realiz) = calc_snr(Symbols{l}, eq_signal_sd-Symbols{l});
|
||||
|
||||
% eq_signal_sd.plot("displayname",'bla','fignum',199);
|
||||
% eq_signal_sd.eye(fsym,M,"fignum",103837);
|
||||
|
||||
eq_signal_hd = PAMmapper(M, 0).quantize(eq_signal_sd);
|
||||
rx_bits = PAMmapper(M,0,"eth_style",0).demap(eq_signal_hd);
|
||||
[~,tot_err,ber_vnle(l,ri,realiz),a] = calc_ber(rx_bits.signal,Tx_bits{l}.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1);
|
||||
burst_vnle = count_error_bursts(a, 10)./tot_err;
|
||||
|
||||
% showLevelConfusionMatrix(eq_signal_hd,Symbols{l},"M",M,"fignum",200,"displayname",'bla');
|
||||
% showLevelScatter(eq_signal_sd,Symbols{l},"displayname",'VNLE Out','f_sym',fsym,'fignum',201);
|
||||
% show2Dconstellation(eq_signal_sd,Symbols{l},"displayname",'VNLE Out','fignum',2241);
|
||||
|
||||
fprintf('CH %d :BER VNLE: %.2e \n',l,ber_vnle(l,ri,realiz));
|
||||
fprintf('CH %d :NGMI VNLE: %.2f \n',l,gmi_vnle_bitwise(l,ri,realiz)./m);
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
figure();hold on;
|
||||
cols = linspecer(N);
|
||||
for l = 1:N
|
||||
% plot(rop,mean(squeeze(ber_vnle(l,:,:)),2,'omitnan'),'Marker','*','DisplayName',sprintf('Ch: %d',wavelengthplan(l)))
|
||||
plot(rop,squeeze(ber_vnle(l,:,:)),'Marker','*','DisplayName',sprintf('Ch: %d',wavelengthplan(l)),'Color',cols(l,:),'HandleVisibility','on')
|
||||
end
|
||||
yline([3.8e-3,2.2e-4],'HandleVisibility','off');
|
||||
ylabel('BER');
|
||||
xlabel('ROP')
|
||||
title('BER vs. ROP');
|
||||
set(gca, 'XScale', 'linear', ...
|
||||
'YScale', 'log', ...
|
||||
'TickLabelInterpreter', 'latex', ...
|
||||
'FontSize', 11);
|
||||
|
||||
|
||||
function dispersion_vector = getDispersionVector(N, D, ref_zdw, randomize_ZDW, randomkey)
|
||||
% MATLAB version of the Python generator shown above.
|
||||
% Returns an N×1 vector (ps/(nm·km)).
|
||||
%
|
||||
% D is the nominal dispersion magnitude. For D>0 the link is segmented with
|
||||
% alternating sign (+D, -D, +D, …). For D==0 it is flat (0) except for
|
||||
% ZDW randomization. The ZDW detuning is ~N(0, 2 nm) around 1310 nm and is
|
||||
% converted to dispersion via 0.09 ps/(nm·km) per nm.
|
||||
|
||||
% constants (matching the Python code)
|
||||
meanLambda_nm = 1310; % center wavelength
|
||||
sigma_nm = 2; % ZDW sigma
|
||||
Dslope = 0.09; % ps/(nm·km) per nm detuning
|
||||
|
||||
% random ZDW-induced dispersion offset
|
||||
if randomize_ZDW
|
||||
rng(randomkey, 'twister');
|
||||
rand_zdws_nm = meanLambda_nm + sigma_nm .* randn(N,1);
|
||||
rand_D = (rand_zdws_nm - ref_zdw) .* Dslope; % ps/(nm·km)
|
||||
else
|
||||
rand_D = zeros(N,1);
|
||||
end
|
||||
|
||||
% nominal segmented pattern (match Python intent; keep length N)
|
||||
if D > 0
|
||||
base = (-1) .^ ((0:N-1).'); % +1,-1,+1,-1,...
|
||||
else % D == 0 (or anything else)
|
||||
base = ones(N,1);
|
||||
end
|
||||
|
||||
dispersion_vector = base .* D + rand_D; % ps/(nm·km)
|
||||
end
|
||||
Reference in New Issue
Block a user