+++ Changes +++

+ duobinary_target now supports memoryless decoding (FFE targets DB response without MLSE)
+ PAMmapper.quantize now supports custom constellations for quantization
+ Added a new folder 'Documentations' for pdfs, slides, etc.
+ Added new FSO evaluation scripts in projects/FSO transmission/Evaluation Scripts
+ Added ffe_db (rudimentary module, not important anymore)
This commit is contained in:
magf
2026-03-05 10:41:21 +01:00
parent 2a724b833f
commit 3676d92b30
32 changed files with 2307 additions and 232 deletions

View File

@@ -0,0 +1,26 @@
% Generate Random NRZ Signal
fsym = 50e9;
K_over = 4;
fs = K_over*fsym;
pulselength_mf = 16;
rolloff_mf = 0.1;
N = 2^18;
test_signal = (2*randi([0 1], 1, N) - 1).';
test_signal = Electricalsignal(test_signal,"fs",fsym);
% test_signal_en = Duobinary().encode(test_signal);
% test_signal_de = Duobinary().decode(test_signal_en);
%
% test_signal_de.normalize("mode","rms").spectrum("displayname",'After Enc-Dec','fignum',2);
% test_signal_de.normalize("mode","rms").plot("displayname",'After Enc-Dec','fignum',3);
test_signal_pre = Duobinary().precode(test_signal);
test_signal.normalize("mode","rms").spectrum("displayname",'Before Pre','fignum',2);
test_signal.normalize("mode","rms").plot("displayname",'Before Pre','fignum',3);
test_signal_pre.normalize("mode","rms").spectrum("displayname",'After Pre','fignum',2);
test_signal_pre.normalize("mode","rms").plot("displayname",'After Pre','fignum',3);

View File

@@ -0,0 +1,74 @@
%%
current = 225:10:285;
current = string(current);
power = [28.02, 33.2, 37.5, 42.3, 46.3, 49.3, 53.4];
power = string(power);
num_pf_coeff = 4;
taps_ffe = [200, 0, 0];
taps_dfe = [0, 0, 0];
M = 4;
trlength = 4096*4;
x = 225:10:285;
BER_PAM_2 = [];
post_only = 0;
filter_length_vec = 140;
num_signal = 11;
our_signal = 1;
weighted_DFE = 0;
for eq_method = 1
for db_target = 0:1
for j = 1:length(current)
BER_run = first_analysis_ber(current(j), power(j), num_pf_coeff, taps_ffe, taps_dfe, M, trlength, eq_method, filter_length_vec, num_signal, our_signal, weighted_DFE, db_target);
BER_PAM_2 = [BER_PAM_2, BER_run];
end
save('C:\Users\magf\Desktop\Desktop\Projekte\FSO\Data\BER_PAM_4_FFE_Only_DB_Target_' + string(db_target) + '.mat', 'x', 'BER_PAM_2')
BER_PAM_2 = [];
end
end
%%
x = 225:10:285;
for k = 0:1
BER = load('C:\Users\magf\Desktop\Desktop\Projekte\FSO\Data\BER_PAM_4_FFE_Only_DB_Target_' + string(k) + '.mat');
BER = BER.BER_PAM_2;
figure(202120)
plot(x, BER, '-o','LineWidth',1.75);
hold on
end
if M == 2
old_BER = [-1.5, -1.75, -2, -2.3, -2.6, -2.25, -1.95];
elseif M == 4
old_BER = [-1.6, -1.85, -2.2, -2.45, -2.3, -2, -1.4];
end
old_BER = 10.^(old_BER);
plot(x, old_BER, '-o','LineWidth',1.75)
h1 = yline(2e-2, ':k', 'LineWidth',1.5);
h2 = yline(3.8e-3,':b', 'LineWidth',1.5);
h3 = yline(4.85e-3,':g', 'LineWidth',1.5);
h4 = yline(2.2e-4,':r', 'LineWidth',1.5);
% Legende NUR für Kurven
legend('FFE without DB Target - 200 Taps', 'FFE with DB Target - 200 Taps', 'BER Paper', ...
'Interpreter','latex', ...
'Location','southwest', 'FontSize', 14)
% FEC Labels direkt im Plot
text(221,2.2e-2,'o-FEC','Color','k','FontSize', 14, 'Interpreter','latex')
text(221,3.3e-3,'HD-FEC','Color','b','FontSize', 14, 'Interpreter','latex')
text(221,5.4e-3,'KP4+Hamming','Color','g','FontSize', 14,'Interpreter','latex')
text(221,2.4e-4,'KP4','Color','r','FontSize', 14,'Interpreter','latex')
xlabel('Laser Bias Current [mA]', 'Interpreter','latex')
ylabel('BER', 'Interpreter','latex')
% title('BER for PAM-2', 'Interpreter','latex')
grid minor
ylim([1e-4 1])
set(gca,'YScale','log')
% beautifyBERplot
hold off

View File

@@ -0,0 +1,69 @@
%%
current = 225:10:285;
current = string(current);
power = [8.4, 8.4, 42.3, 8.4, 8.4];
power = string(power);
num_pf_coeff = 4;
taps_ffe = [200, 0, 0];
taps_dfe = [0, 0, 0];
M = 4;
trlength = 4096*4;
x = 4:1:8;
BER_PAM_2 = [];
post_only = 0;
filter_length_vec = 140;
num_signal = 11;
our_signal = 1;
weighted_DFE = 0;
for eq_method = 1
for db_target = 0:1
for baud_rate = 4:1:8
BER_run = first_analysis_baud_rate_sweep(string(baud_rate), power(baud_rate-3), num_pf_coeff, taps_ffe, taps_dfe, M, trlength, eq_method, filter_length_vec, num_signal, db_target);
BER_PAM_2 = [BER_PAM_2, BER_run];
end
save('C:\Users\magf\Desktop\Desktop\Projekte\FSO\Data\BER_PAM_4_FFE_Only_DB_Target_Baud_Rate_Sweep' + string(db_target) + '.mat', 'x', 'BER_PAM_2')
BER_PAM_2 = [];
end
end
%%
x = 4:1:8;
for k = 0:1
BER = load('C:\Users\magf\Desktop\Desktop\Projekte\FSO\Data\BER_PAM_4_FFE_Only_DB_Target_Baud_Rate_Sweep' + string(k) + '.mat');
BER = BER.BER_PAM_2;
figure(202120)
plot(x, BER, '-o','LineWidth',1.75);
hold on
end
h1 = yline(2e-2, ':k', 'LineWidth',1.5);
h2 = yline(3.8e-3,':b', 'LineWidth',1.5);
h3 = yline(4.85e-3,':g', 'LineWidth',1.5);
h4 = yline(2.2e-4,':r', 'LineWidth',1.5);
% Legende NUR für Kurven
legend('FFE without DB Target - 200 Taps', 'FFE with DB Target - 200 Taps', ...
'Interpreter','latex', ...
'Location','southwest', 'FontSize', 14)
% FEC Labels direkt im Plot
text(221,2.2e-2,'o-FEC','Color','k','FontSize', 14, 'Interpreter','latex')
text(221,3.3e-3,'HD-FEC','Color','b','FontSize', 14, 'Interpreter','latex')
text(221,5.4e-3,'KP4+Hamming','Color','g','FontSize', 14,'Interpreter','latex')
text(221,2.4e-4,'KP4','Color','r','FontSize', 14,'Interpreter','latex')
xlabel('Symbol Rate [GBd]', 'Interpreter','latex')
ylabel('BER', 'Interpreter','latex')
% title('BER for PAM-2', 'Interpreter','latex')
grid minor
ylim([1e-2 1])
set(gca,'YScale','log')
% beautifyBERplot
hold off

View File

@@ -0,0 +1,149 @@
%%
M = 4;
current = 255;
power = [8.4, 8.4, 42.3, 8.4, 8.4, 8.4, 8.4];
rolloff = 0.6;
baudrate = 4:1:10;
baudrate_e = ["4e9", "5e9", "6e9", "7e9", "8e9", "9e9", "1e10"];
num_pf_coeff = 4;
taps_ffe = [300, 0, 0];
taps_dfe = [0, 0, 0];
trlength = 4096*4;
filter_length = 210;
x = 4:1:10;
num_currents = length(x);
num_signals = 18;
num_eq_methods = 4;
BER_PAM_2 = zeros(num_currents,num_signals);
save_name = "BER_PAM_4_Waitbar_Test";
% ---------------- Progressbar Setup ----------------
totalRuns = num_eq_methods * num_currents * num_signals;
runCount = 0;
h = waitbar(0, 'Starte Simulation...', 'Name', 'FSO Simulation Progress');
tStart = tic;
% Optional: nur alle N Schritte UI updaten (reduziert Overhead)
updateEvery = 1; % z.B. 10 setzen, wenn es extrem viele Iterationen werden
% ---------------------------------------------------
try
for eq_method = 1:1:4
num_current_iteration = 1;
for i = 1:num_currents
for num_signal = 1:1:num_signals
% --- Dein eigentlicher Run ---
try
BER_run = first_analysis_fso(current, power(i), baudrate(i), baudrate_e(i), rolloff, ...
num_pf_coeff, taps_ffe, taps_dfe, M, trlength, eq_method, filter_length, num_signal);
catch
BER_run = NaN;
end
BER_PAM_2(num_current_iteration, num_signal) = BER_run;
% -----------------------------
% --- Progress updaten ---
runCount = runCount + 1;
if mod(runCount, updateEvery) == 0 || runCount == 1 || runCount == totalRuns
frac = runCount / totalRuns;
elapsed = toc(tStart);
if frac > 0
remaining = elapsed * (1/frac - 1);
else
remaining = NaN;
end
msg = sprintf(['EQ %d/4 | i %d/%d | Signal %d/%d\n' ...
'Gesamt %d/%d (%.1f %%) | ETA ~ %.1f min'], ...
eq_method, i, num_currents, num_signal, num_signals, ...
runCount, totalRuns, 100*frac, remaining/60);
waitbar(frac, h, msg);
% Falls jemand das waitbar-Fenster schließt: sauber abbrechen
if ~ishandle(h)
error('Progressbar wurde geschlossen. Abbruch durch Nutzer.');
end
end
% ------------------------
end
num_current_iteration = num_current_iteration + 1;
end
save('C:\Users\magf\Desktop\Desktop\Projekte\FSO\Data\' + save_name + "_" + string(eq_method) + '.mat', 'x', 'BER_PAM_2')
BER_PAM_2 = zeros(num_currents, num_signals);
end
catch ME
% Falls irgendwas schiefgeht: waitbar schließen und Fehler weiterwerfen
if exist('h','var') && ishandle(h)
close(h);
end
rethrow(ME);
end
% Clean exit
if exist('h','var') && ishandle(h)
close(h);
end
%%
x = 4:1:10;
save_name = "BER_PAM_4_Waitbar_Test";
figure(202120); clf; hold on; grid on;
for k = 1:4
BER_min = zeros(1,length(x));
BER_avg = zeros(1,length(x));
BER_max = zeros(1,length(x));
tmp = load('C:\Users\magf\Desktop\Desktop\Projekte\FSO\Data\' + save_name + "_" + string(k) + '.mat');
BER = tmp.BER_PAM_2;
for i = 1:length(x)
BERs = BER(i,:);
BER_min(i) = min(BERs);
BER_avg(i) = mean(BERs);
BER_max(i) = max(BERs);
end
err_low = BER_avg - BER_min;
err_high = BER_max - BER_avg;
errorbar(x, BER_avg, err_low, err_high, '-o', 'LineWidth', 1.75);
end
old_BER = [-1.5, -1.75, -2, -2.3, -2.6, -2.25, -1.95];
old_BER = 10.^(old_BER);
plot(x, old_BER, '-o','LineWidth',1.75)
h1 = yline(2e-2, ':k', 'LineWidth',1.5);
h2 = yline(3.8e-3,':b', 'LineWidth',1.5);
h3 = yline(4.85e-3,':g', 'LineWidth',1.5);
h4 = yline(2.2e-4,':r', 'LineWidth',1.5);
% Legende NUR für Kurven
legend('FFE', 'FFE+PF+MLSE', 'DB', 'ML-MLSE', 'BER Paper', ...
'Interpreter','latex', ...
'Location','southwest', 'FontSize', 14)
% FEC Labels direkt im Plot
text(221,2.2e-2,'o-FEC','Color','k','FontSize', 14, 'Interpreter','latex')
text(221,3.3e-3,'HD-FEC','Color','b','FontSize', 14, 'Interpreter','latex')
text(221,5.4e-3,'KP4+Hamming','Color','g','FontSize', 14,'Interpreter','latex')
text(231,2.4e-4,'KP4','Color','r','FontSize', 14,'Interpreter','latex')
xlabel('Laser Bias Current [mA]', 'Interpreter','latex')
ylabel('BER', 'Interpreter','latex')
% title('BER for PAM-2', 'Interpreter','latex')
grid minor
ylim([1e-4 5e-1])
set(gca,'YScale','log')
% beautifyBERplot
hold off

View File

@@ -5,7 +5,7 @@ power = [28.02, 33.2, 37.5, 42.3, 46.3, 49.3, 53.4];
power = string(power);
num_pf_coeff = 4;
taps_ffe = [300, 0, 0];
taps_dfe = [0, 0, 0];
% taps_dfe = [0, 0, 0];
M = 4;
trlength = 4096*4;
x = 225:10:285;
@@ -13,20 +13,25 @@ BER_PAM_4 = [];
filter_length = 210;
num_signal = 11;
our_signal = 1;
weighted_DFE = [1, 0.1, 0.1];
for eq_method = 2
for j = 4
BER_run = first_analysis_ber(current(j), power(j), num_pf_coeff, taps_ffe, taps_dfe, M, trlength, eq_method, filter_length, num_signal, our_signal);
BER_PAM_4 = [BER_PAM_4, BER_run];
save_and_append('meineDB.sqlite', 'BER_PAM_4_Save_and_Append', eq_method, num_signal, BER_run, x)
for m = 0:5:40
for eq_method = 2
for j = 4
BER_run = first_analysis_ber(current(j), power(j), num_pf_coeff, taps_ffe, [m, 0, 0], M, trlength, eq_method, filter_length, num_signal, our_signal, weighted_DFE);
BER_PAM_4 = [BER_PAM_4, BER_run];
% save_and_append('meineDB.sqlite', 'BER_PAM_4_Save_and_Append', eq_method, num_signal, BER_run, x)
end
end
BER_PAM_4 = [];
end
save('C:\Users\magf\Desktop\Desktop\Projekte\FSO\Data\BER_PAM_4_Weighted_DFE_' + string(k) + '.mat');
BER_PAM_4 = [];
%%
x = 0:5:40;
for k = 2
BER = load('C:\Users\magf\Desktop\Desktop\Projekte\FSO\Data\BER_PAM_4_DFE_Tap_Sweep_' + string(k) + '.mat');
BER = load('C:\Users\magf\Desktop\Desktop\Projekte\FSO\Data\BER_PAM_4_Weighted_DFE_' + string(k) + '.mat');
BER_values = BER.BER_PAM_4;
figure(202120)
@@ -53,7 +58,7 @@ text(23,2.6e-3,'HD-FEC','Color','b','FontSize', 14, 'Interpreter','latex')
text(23.5,6.5e-3,'KP4+Hamming','Color','g','FontSize', 14,'Interpreter','latex')
text(23,1.4e-4,'KP4','Color','r','FontSize', 14,'Interpreter','latex')
xlabel('Laser Bias Current [mA]', 'Interpreter','latex', 'FontSize', 14)
xlabel('Number of First Order DFE Taps', 'Interpreter','latex', 'FontSize', 14)
ylabel('BER', 'Interpreter','latex', 'FontSize', 14)
% title('BER for PAM-4', 'Interpreter','latex')

View File

@@ -0,0 +1,18 @@
%%
M = 2;
current = 265;
power = 8.4;
rolloff = 0.6;
baudrate = 20;
baudrate_e = "2e10";
num_pf_coeff = 4;
taps_ffe = [200, 0, 0];
taps_dfe = [0, 0, 0];
trlength = 4096*2;
filter_length = 140;
num_signal = 1;
eq_method = 1;
BER_run = first_analysis_fso(current, power, baudrate, baudrate_e, rolloff, ...
num_pf_coeff, taps_ffe, taps_dfe, M, trlength, eq_method, filter_length, num_signal);

View File

@@ -0,0 +1,222 @@
function BER_value = first_analysis_fso(current, power, rolloff, num_pf_coeff, taps_ffe, taps_dfe, M, trlength, eq_method, filter_length, num_signal, our_signal, weighted_DFE_mode, db_target)
%%
close all
%%
base = "C:\Users\magf\Desktop\Desktop\MATLAB-Zeugs\FSO Equalizer\Sweep Data\";
mode = 0; %0 oder 1
% M = 2;
all_files = dir(fullfile(base, "**/*.mat"));
if M == 2
tx_data_path = fullfile(base, "20G_PAM2\tx_info\tx_info_PAM2_20Gbd" + rolloff + "RRC.mat");
filename = fullfile(base, "20G_PAM2\M=2_Rs=2e10_Fs=8e10_I=" + current + "mA_RoP=" + power + "mW_L=31m_PS=RRC_rolloff=" + rolloff + "_Mode=Rise.mat");
data_tr_mf = load("C:\Users\magf\Desktop\Desktop\MATLAB-Zeugs\FSO Equalizer\FSO_FP_QCL_60umUTC\Already Recovered and Filtered\AfterSync_M=2_Rs=1.4e10_Fs=8e10_I=265mA_RoP=46.3mW_L=31m_PS=RRC_rolloff=0.75_Mode=Rise.mat");
elseif M == 4
tx_data_path = fullfile(base, "6G_PAM4\tx_info\tx_info_PAM4_6Gbd0.6RRC.mat");
filename = fullfile(base, "6G_PAM4\M=4_Rs=6e9_Fs=8e10_I=" + current + "mA_RoP=" + power + "mW_L=31m_PS=RRC_rolloff=0.6_Mode=Rise.mat");
data_tr_mf = load("C:\Users\magf\Desktop\Desktop\MATLAB-Zeugs\FSO Equalizer\FSO_FP_QCL_60umUTC\Already Recovered and Filtered\AfterSync_M=4_Rs=6e9_Fs=8e10_I=255mA_RoP=42.3mW_L=31m_PS=RRC_rolloff=0.6_Mode=Rise.mat");
end
if mode == 1
[f, p] = uigetfile(fullfile(base, "**/*.mat"));
if f~=0
filename = fullfile(p,f);
end
end
tx_data = load(tx_data_path);
datas = load(filename);
%%
str = filename;
M_ = str2double(regexp(str, 'M=([^_]+)', 'tokens', 'once'));
assert(M==M_);
fsym = str2double(regexp(str, 'Rs=([^_]+)', 'tokens', 'once'));
fs = str2double(regexp(str, 'Fs=([^_]+)', 'tokens', 'once'));
I = sscanf(char(regexp(str, 'I=([^_]+)', 'tokens', 'once')), '%f');
rop = sscanf(char(regexp(str, 'RoP=([^_]+)', 'tokens', 'once')), '%f');
L = sscanf(char(regexp(str, 'L=([^_]+)', 'tokens', 'once')), '%f');
pulseshape = string( regexp(str, 'PS=([^_]+)', 'tokens', 'once'));
rolloff = str2double(regexp(str, 'rolloff=([^_]+)', 'tokens', 'once'));
mode = string( regexp(str, 'Mode=([^\.]+)', 'tokens', 'once'));
%%
% Tx data
Bits = Informationsignal(tx_data.tx_data,"fs",fsym);
Symbols = Informationsignal(real(tx_data.tx_PAM_sym),"fs",fsym);
mapping_style = M==4; % Pam2 is like move-it; PAM-4 is different, same mapping like ETH peopled used in Zurich... hence the "eth_style" argument here and there
PM = PAMmapper(M,0,"eth_style",mapping_style); % one should rename "eth style" as this is simply a different mapping scheme
Symbols_ = PM.map(Bits) .* PM.scaling;
assert(isequal(Symbols.signal,Symbols_.signal));
Bits_ = PM.demap(Symbols);
[bits,errors,ber,errorIndice] = calc_ber(Bits_.signal,Bits.signal);
assert(ber == 0);
%% For comparison, apply pulsef on Tx Symbols
Pform = Pulseformer("fsym",fsym,"fdac",fs,"pulse","rrc","pulselength",16,"alpha",rolloff);
Digi_sig_compare = Pform.process(Symbols);
MF = Pulseformer("fsym",fsym,"fdac",2*fsym,"pulse","rrc","pulselength",16,"alpha",rolloff);
Rx_sig_compare = MF.process(Digi_sig_compare);
%%
% Rx Data
traceData = datas.tr.lastData(2).trace.ch3;
%FYI: Voltage=(RawDataYReference)×YIncrement+YOrigin
scoperead_volts = (traceData.RawData - traceData.YReference) * traceData.YIncrement + traceData.YOrigin;
demystified = isequal(traceData.YData,scoperead_volts);
assert(demystified);
Scope_sig = Electricalsignal(traceData.YData,"fs",fs);
Scope_sig.plot("displayname",'raw','fignum',100);
Scope_sig.spectrum("displayname",'raw','fignum',101)
Kov = 14;
Scope_sig = Scope_sig.resample('fs_in', fs, 'fs_out', Kov*fsym);
% 1) matched filter
% pulse is symmetric, hence we can use pulsef firectly as matched filter.
% It feels off (bit I think correct) that the fsym is now the output freq.!!
% -> output 2 sps to omit timing recovery!?
Matched_Filter = Pulseformer("fsym",fsym,"fdac",Kov*fsym,"pulse","rrc","pulselength",16,"alpha",rolloff,"matched",1);
Rx_matched = Matched_Filter.process(Scope_sig);
Rx_matched.spectrum("displayname",'Signal after matched filter','fignum',1);
% timing sync -> at this point we still have no symbol timing recovery, we
% try to do this with 2sps EQ!
[~,Rx_synced_cell,inverted,sequenceFound,sequenceStarts] = Rx_matched.tsynch("reference", Symbols, "fs_ref", fsym, "debug_plots", 1);
Rx_matched_1 = Rx_synced_cell{num_signal};
data_tr_mf = Electricalsignal(data_tr_mf.Results, "fs", fsym);
[~,Rx_synced_cell_tr_mf,inverted_tr_mf,sequenceFound_tr_mf,sequenceStarts_tr_mf] = data_tr_mf.tsynch("reference", Symbols, "fs_ref", fsym, "debug_plots", 1);
Rx_tr_mf = Rx_synced_cell_tr_mf{num_signal};
% Rx_Time_Rec = Rx_matched;
% Rx_Time_Rec = Timing_Recovery_Move_It('f_sim', 28e9, 'gamma', 0.1).process(Rx_matched_1);
Time_Rec = 1;
if Time_Rec
Rx_Time_Rec = MaxVar_Timing_Recovery('mode',0,'fsym',fsym,'fadc',Kov*fsym,'num_tau',Kov*128,'sps',Kov,'comp_signal',0,'comp_mode',0).process(Rx_matched_1);
sps = 1;
else
sps = Kov;
end
Rx_Time_Rec.fs = fsym;
Rx_Time_Rec = Rx_Time_Rec.normalize('mode','rms');
Rx_tr_mf = Rx_tr_mf.normalize('mode','rms');
% Rx_Time_Rec.signal = resample(Rx_Time_Rec.signal, 12e9, 6e9);
% Rx_matched_1.plot("fignum",231231)
% Rx_Time_Rec.plot("fignum",231231)
%% not working..
if our_signal
Rx_synced = Rx_Time_Rec;
else
Rx_synced = Rx_tr_mf;
end
% Rx_synced = Rx_Time_Rec;
% Rx_synced = Rx_synced_cell{1};
len_tr = trlength;
mu_ffe1 = 0.0001;
mu_ffe2 = 0.0008;
mu_ffe3 = 0.001;
mu_dc = 0.004;
mu_ffe = [mu_ffe1 mu_ffe3 mu_ffe3];
mu_dfe = 0.0004;
duob_mode = db_mode.no_db;
Rx_synced.plot("displayname",'RX: Matched+Sync+2sps','fignum',103);
Rx_synced.spectrum("displayname",'RX: Matched+Sync+2sps','fignum',104);
Digi_sig_compare.normalize("mode","rms").spectrum("displayname",'Tx: RC-shaped','fignum',1,'normalizeTo0dB',1);
Rx_sig_compare.normalize("mode","rms").spectrum("displayname",'Tx: RC-shaped + matched filtered ','fignum',1,'normalizeTo0dB',1);
Rx_synced.normalize("mode","rms").spectrum("displayname",'RX: matched filtered + synced','fignum',1,'normalizeTo0dB',1);
if M == 2
ber_in_paper = 10^(-2.6); %fig 3a) 4 Gb/s MWIR FSO Transmission using Directly Modulated QCL and an Uncooled UTC-PD at Room-Temperature
elseif M == 4
ber_in_paper = 10^(-2.5);
end
if eq_method == 1
%% -------------------- FFE --------------------
% requires some more digging what is going on :-)
eq_ffe = EQ("Ne",taps_ffe,"Nb",taps_dfe, ...
"training_length",len_tr,"training_loops",5,"dd_loops",5, ...
"K",sps,"DCmu",mu_dc,"DDmu",[mu_ffe mu_dfe],"DFEmu",0.005, ...
"FFEmu",0,"plotfinal",0,"ideal_dfe",1);
ffe_results = ffe_db(eq_ffe,M,Rx_synced,Symbols,Bits, ...
"precode_mode",duob_mode,'showAnalysis',0,"postFFE",[], ...
"eth_style_symbol_mapping",mapping_style,'db_target',db_target);
% ffe_results.metrics.print
fprintf('My EQ: %.1e \n',ffe_results.metrics.BER);
fprintf('Paper: %.1e \n \n',ber_in_paper);
BER_value = ffe_results.metrics.BER;
elseif eq_method == 2
%% -------------------- VNLE + MLSE --------------------
pf_ncoeffs = num_pf_coeff;
eq_v = EQ("Ne",taps_ffe,"Nb",taps_dfe, ...
"training_length",len_tr,"training_loops",5,"dd_loops",5, ...
"K",sps,"DCmu",mu_dc,"DDmu",[mu_ffe mu_dfe],"DFEmu",0.005, ...
"FFEmu",0,"plotfinal",0,"ideal_dfe",0,'weighted_DFE',0,'weighted_DFE_d_min',0.5, ...
'weighted_DFE_mode','I2','weighted_DFE_I_mode',weighted_DFE_mode,'PDFE_coefficient',0.01);
pf_ = Postfilter("ncoeff",pf_ncoeffs,"useBurg",1);
mlse_ = MLSE("duobinary_output",0,'M',M,'trellis_states',PAMmapper(M,0,"eth_style",mapping_style).levels);
[vnle_results, mlse_results] = vnle_postfilter_mlse(eq_v, pf_, mlse_, M, Rx_synced, Symbols, Bits, ...
"precode_mode", duob_mode, 'showAnalysis', 1, "postFFE", [], "eth_style_symbol_mapping", mapping_style);
mlse_results.metrics.print
fprintf('My EQ: %.1e \n',mlse_results.metrics.BER);
fprintf('Paper: %.1e \n \n',ber_in_paper);
BER_value = mlse_results.metrics.BER;
elseif eq_method == 3
%% -------------------- DB target --------------------
mlse_db_ = MLSE("DIR",[1,1],"duobinary_output",0,"M",M,'trellis_states',PAMmapper(M,0).levels);
eq_ = EQ("Ne",taps_ffe,"Nb",taps_dfe,"training_length",len_tr,"training_loops",5,"dd_loops",5, ...
"K",sps,"DCmu",mu_dc,"DDmu",[mu_ffe mu_dfe],"DFEmu",0.005,"FFEmu",0,"plotfinal",0,"ideal_dfe",1);
dbt_results = duobinary_target(eq_,mlse_db_, M, Rx_synced, Symbols, Bits, ...
"precode_mode", duob_mode, 'showAnalysis', 0, "postFFE", [],"eth_style_symbol_mapping",mapping_style,"decoding_mode","memoryless");
dbt_results.metrics.print("description",'Duobinary');
fprintf('My EQ: %.1e \n',dbt_results.metrics.BER);
fprintf('Paper: %.1e \n \n',ber_in_paper);
BER_value = dbt_results.metrics.BER;
elseif eq_method == 4
%% -------------------- ML-based MLSE (L=2) --------------------
ml_mlse_equalizer = ML_MLSE("epochs_tr",150,"epochs_dd",1, ...
"len_tr",length(Rx_synced),"mu_dd",0.03,"mu_tr",0.03,"order",filter_length,"sps",1, ...
"traceback_depth",256,"L",1,"delta",4,"adaptive_mu",0);
[ml_mlse_results] = ml_mlse(ml_mlse_equalizer, M, Rx_synced, Symbols, Bits,"precode_mode",duob_mode,"eth_style_symbol_mapping",mapping_style);
fprintf('ML-based MLSE:\n');
fprintf('My EQ: %.1e \n',ml_mlse_results.metrics.BER);
fprintf('Paper: %.1e \n \n',ber_in_paper);
BER_value = ml_mlse_results.metrics.BER;
end
end

View File

@@ -1,4 +1,4 @@
function [BER, Channel_Alpha] = first_analysis_baud_rate_sweep(baud_rate, power, num_pf_coeff, taps_ffe, taps_dfe, M, trlength, method, filter_length, num_signal)
function [BER, Channel_Alpha] = first_analysis_baud_rate_sweep(baud_rate, power, num_pf_coeff, taps_ffe, taps_dfe, M, trlength, method, filter_length, num_signal, db_target)
%%
close all
base = "C:\Users\magf\Desktop\Desktop\MATLAB-Zeugs\FSO Equalizer\Sweep Data\";
@@ -138,14 +138,14 @@ function [BER, Channel_Alpha] = first_analysis_baud_rate_sweep(baud_rate, power,
if method == 1
%% -------------------- FFE --------------------
% requires some more digging what is going on :-)
eq_ffe = EQ("Ne",[500, 0, 0],"Nb",[0, 0, 0], ...
eq_ffe = EQ("Ne",taps_ffe,"Nb",taps_dfe, ...
"training_length",len_tr,"training_loops",5,"dd_loops",5, ...
"K",sps,"DCmu",mu_dc,"DDmu",[mu_ffe mu_dfe],"DFEmu",0.005, ...
"FFEmu",0,"plotfinal",0,"ideal_dfe",1);
ffe_results = ffe(eq_ffe,M,Rx_synced,Symbols,Bits, ...
"precode_mode",duob_mode,'showAnalysis',0,"postFFE",[], ...
"eth_style_symbol_mapping",mapping_style);
"eth_style_symbol_mapping",mapping_style,'db_target',db_target);
% ffe_results.metrics.print
fprintf('My EQ: %.1e \n',ffe_results.metrics.BER);

View File

@@ -1,4 +1,4 @@
function BER_value = first_analysis_ber(current, power, num_pf_coeff, taps_ffe, taps_dfe, M, trlength, eq_method, filter_length, num_signal, our_signal, weighted_DFE)
function BER_value = first_analysis_ber(current, power, num_pf_coeff, taps_ffe, taps_dfe, M, trlength, eq_method, filter_length, num_signal, our_signal, weighted_DFE, db_target)
%%
close all
@@ -154,14 +154,14 @@ function BER_value = first_analysis_ber(current, power, num_pf_coeff, taps_ffe,
%% -------------------- FFE --------------------
% requires some more digging what is going on :-)
eq_ffe = EQ("Ne",[500, 0, 0],"Nb",[0, 0, 0], ...
eq_ffe = EQ("Ne",taps_ffe,"Nb",taps_dfe, ...
"training_length",len_tr,"training_loops",5,"dd_loops",5, ...
"K",sps,"DCmu",mu_dc,"DDmu",[mu_ffe mu_dfe],"DFEmu",0.005, ...
"FFEmu",0,"plotfinal",0,"ideal_dfe",1);
ffe_results = ffe(eq_ffe,M,Rx_synced,Symbols,Bits, ...
"precode_mode",duob_mode,'showAnalysis',0,"postFFE",[], ...
"eth_style_symbol_mapping",mapping_style);
"eth_style_symbol_mapping",mapping_style,'db_target',db_target);
% ffe_results.metrics.print
fprintf('My EQ: %.1e \n',ffe_results.metrics.BER);

View File

@@ -0,0 +1,180 @@
function BER_value = first_analysis_fso(current, power, baudrate, baudrate_e, rolloff, ...
num_pf_coeff, taps_ffe, taps_dfe, M, trlength, eq_method, filter_length, num_signal)
%% Close Remaining Figures
close all
%% Load Data
base = "C:\Users\magf\Desktop\Desktop\MATLAB-Zeugs\FSO Equalizer\Sweep Data\";
mode = 0; %0 oder 1
tx_data_path = fullfile(base, string(baudrate) + "G_PAM" + string(M) + "\tx_info\tx_info_PAM" + string(M) + "_" + string(baudrate) + "Gbd" + string(rolloff) + "RRC.mat");
filename = fullfile(base, string(baudrate) + "G_PAM" + string(M) + "\M=" + string(M) + "_Rs=" + baudrate_e + "_Fs=8e10_I=" + string(current) + "mA_RoP=" + string(power) + "mW_L=31m_PS=RRC_rolloff=" + string(rolloff) + "_Mode=Rise.mat");
if mode == 1
[f, p] = uigetfile(fullfile(base, "**/*.mat"));
if f~=0
filename = fullfile(p,f);
end
end
tx_data = load(tx_data_path);
datas = load(filename);
%%
str = filename;
M_ = str2double(regexp(str, 'M=([^_]+)', 'tokens', 'once'));
assert(M==M_);
fsym = str2double(regexp(str, 'Rs=([^_]+)', 'tokens', 'once'));
fs = str2double(regexp(str, 'Fs=([^_]+)', 'tokens', 'once'));
I = sscanf(char(regexp(str, 'I=([^_]+)', 'tokens', 'once')), '%f');
rop = sscanf(char(regexp(str, 'RoP=([^_]+)', 'tokens', 'once')), '%f');
L = sscanf(char(regexp(str, 'L=([^_]+)', 'tokens', 'once')), '%f');
pulseshape = string( regexp(str, 'PS=([^_]+)', 'tokens', 'once'));
rolloff = str2double(regexp(str, 'rolloff=([^_]+)', 'tokens', 'once'));
mode = string( regexp(str, 'Mode=([^\.]+)', 'tokens', 'once'));
%% Generate Tx Data
Bits = Informationsignal(tx_data.tx_data,"fs",fsym);
Symbols = Informationsignal(real(tx_data.tx_PAM_sym),"fs",fsym);
mapping_style = M==4; % Pam2 is like move-it; PAM-4 is different, same mapping like ETH peopled used in Zurich... hence the "eth_style" argument here and there
PM = PAMmapper(M,0,"eth_style",mapping_style); % one should rename "eth style" as this is simply a different mapping scheme
Symbols_ = PM.map(Bits) .* PM.scaling;
assert(isequal(Symbols.signal,Symbols_.signal));
Bits_ = PM.demap(Symbols);
[bits,errors,ber,errorIndice] = calc_ber(Bits_.signal,Bits.signal);
assert(ber == 0);
%% For comparison, apply pulsef on Tx Symbols
Pform = Pulseformer("fsym",fsym,"fdac",fs,"pulse","rrc","pulselength",16,"alpha",rolloff);
Digi_sig_compare = Pform.process(Symbols);
MF = Pulseformer("fsym",fsym,"fdac",2*fsym,"pulse","rrc","pulselength",16,"alpha",rolloff);
Rx_sig_compare = MF.process(Digi_sig_compare);
%% Matched Filter
traceData = datas.tr.lastData(2).trace.ch3;
%FYI: Voltage=(RawDataYReference)×YIncrement+YOrigin
scoperead_volts = (traceData.RawData - traceData.YReference) * traceData.YIncrement + traceData.YOrigin;
demystified = isequal(traceData.YData,scoperead_volts);
assert(demystified);
Scope_sig = Electricalsignal(traceData.YData,"fs",fs);
Scope_sig.plot("displayname",'raw','fignum',100);
Scope_sig.spectrum("displayname",'raw','fignum',101)
Kov = 14;
Scope_sig = Scope_sig.resample('fs_in', fs, 'fs_out', Kov*fsym);
% Apply Matched Filter
Matched_Filter = Pulseformer("fsym",fsym,"fdac",Kov*fsym,"pulse","rrc","pulselength",16,"alpha",rolloff,"matched",1);
Rx_matched = Matched_Filter.process(Scope_sig);
Rx_matched.spectrum("displayname",'Signal after matched filter','fignum',1);
%% Timing Synchronization
[~,Rx_synced_cell,inverted,sequenceFound,sequenceStarts] = Rx_matched.tsynch("reference", Symbols, "fs_ref", fsym, "debug_plots", 1);
Rx_matched_1 = Rx_synced_cell{num_signal};
%% Timing Recovery
Time_Rec = 1;
if Time_Rec
Rx_Time_Rec = MaxVar_Timing_Recovery('mode',0,'fsym',fsym,'fadc',Kov*fsym,'num_tau',Kov*128,'sps',Kov,'comp_signal',0,'comp_mode',0).process(Rx_matched_1);
sps = 1;
else
sps = Kov;
end
Rx_Time_Rec.fs = fsym;
Rx_Time_Rec = Rx_Time_Rec.normalize('mode','rms');
%% DSP Parameters
Rx_synced = Rx_Time_Rec;
len_tr = trlength;
mu_ffe1 = 0.0001;
mu_ffe2 = 0.0008;
mu_ffe3 = 0.001;
mu_dc = 0.004;
mu_ffe = [mu_ffe1 mu_ffe3 mu_ffe3];
mu_dfe = 0.0004;
duob_mode = db_mode.no_db;
if M == 2
ber_in_paper = 10^(-2.6); %fig 3a) 4 Gb/s MWIR FSO Transmission using Directly Modulated QCL and an Uncooled UTC-PD at Room-Temperature
elseif M == 4
ber_in_paper = 10^(-2.5);
end
%% EQ Methods
if eq_method == 1
% -------------------- FFE --------------------
% requires some more digging what is going on :-)
eq_ffe = EQ("Ne",[500, 0, 0],"Nb",[0, 0, 0], ...
"training_length",len_tr,"training_loops",5,"dd_loops",5, ...
"K",sps,"DCmu",mu_dc,"DDmu",[mu_ffe mu_dfe],"DFEmu",0.005, ...
"FFEmu",0,"plotfinal",0,"ideal_dfe",1);
ffe_results = ffe(eq_ffe,M,Rx_synced,Symbols,Bits, ...
"precode_mode",duob_mode,'showAnalysis',0,"postFFE",[], ...
"eth_style_symbol_mapping",mapping_style);
% ffe_results.metrics.print
fprintf('My EQ: %.1e \n',ffe_results.metrics.BER);
fprintf('Paper: %.1e \n \n',ber_in_paper);
BER_value = ffe_results.metrics.BER;
elseif eq_method == 2
% -------------------- VNLE + MLSE --------------------
pf_ncoeffs = num_pf_coeff;
eq_v = EQ("Ne",taps_ffe,"Nb",taps_dfe, ...
"training_length",len_tr,"training_loops",5,"dd_loops",5, ...
"K",sps,"DCmu",mu_dc,"DDmu",[mu_ffe mu_dfe],"DFEmu",0.005, ...
"FFEmu",0,"plotfinal",0,"ideal_dfe",0,'weighted_DFE',0,'weighted_DFE_d_min',0.5, ...
'weighted_DFE_mode','I2','weighted_DFE_I_mode',0,'PDFE_coefficient',0.01);
pf_ = Postfilter("ncoeff",pf_ncoeffs,"useBurg",1);
mlse_ = MLSE("duobinary_output",0,'M',M,'trellis_states',PAMmapper(M,0,"eth_style",mapping_style).levels);
[vnle_results, mlse_results] = vnle_postfilter_mlse(eq_v, pf_, mlse_, M, Rx_synced, Symbols, Bits, ...
"precode_mode", duob_mode, 'showAnalysis', 1, "postFFE", [], "eth_style_symbol_mapping", mapping_style);
mlse_results.metrics.print
fprintf('My EQ: %.1e \n',mlse_results.metrics.BER);
fprintf('Paper: %.1e \n \n',ber_in_paper);
BER_value = mlse_results.metrics.BER;
elseif eq_method == 3
% -------------------- DB target --------------------
mlse_db_ = MLSE("DIR",[1,1],"duobinary_output",0,"M",M,'trellis_states',PAMmapper(M,0).levels);
eq_ = EQ("Ne",taps_ffe,"Nb",taps_dfe,"training_length",len_tr,"training_loops",5,"dd_loops",5, ...
"K",sps,"DCmu",mu_dc,"DDmu",[mu_ffe mu_dfe],"DFEmu",0.005,"FFEmu",0,"plotfinal",0,"ideal_dfe",1);
dbt_results = duobinary_target(eq_,mlse_db_, M, Rx_synced, Symbols, Bits, ...
"precode_mode", duob_mode, 'showAnalysis', 0, "postFFE", [],"eth_style_symbol_mapping",mapping_style,"decoding_mode","sequencedetection");
dbt_results.metrics.print("description",'Duobinary');
fprintf('My EQ: %.1e \n',dbt_results.metrics.BER);
fprintf('Paper: %.1e \n \n',ber_in_paper);
BER_value = dbt_results.metrics.BER;
elseif eq_method == 4
% -------------------- ML-based MLSE (L=2) --------------------
ml_mlse_equalizer = ML_MLSE("epochs_tr",150,"epochs_dd",1, ...
"len_tr",length(Rx_synced),"mu_dd",0.03,"mu_tr",0.03,"order",filter_length,"sps",1, ...
"traceback_depth",256,"L",1,"delta",4,"adaptive_mu",0);
[ml_mlse_results] = ml_mlse(ml_mlse_equalizer, M, Rx_synced, Symbols, Bits,"precode_mode",duob_mode,"eth_style_symbol_mapping",mapping_style);
fprintf('ML-based MLSE:\n');
fprintf('My EQ: %.1e \n',ml_mlse_results.metrics.BER);
fprintf('Paper: %.1e \n \n',ber_in_paper);
BER_value = ml_mlse_results.metrics.BER;
end
end

View File

@@ -189,7 +189,7 @@ for our_signal = 1
end
% Rx_synced = Rx_Time_Rec;
% Rx_synced = Rx_synced_cell{1};
len_tr = 4096*4;
len_tr = 4096*2;
mu_ffe1 = 0.0001;
mu_ffe2 = 0.0008;
mu_ffe3 = 0.001;
@@ -212,7 +212,7 @@ for our_signal = 1
end
%% -------------------- FFE --------------------
% requires some more digging what is going on :-)
% % requires some more digging what is going on :-)
% eq_ffe = EQ("Ne",[150, 0, 0],"Nb",[0,0,0], ...
% "training_length",len_tr,"training_loops",5,"dd_loops",5, ...
% "K",sps,"DCmu",mu_dc,"DDmu",[mu_ffe mu_dfe],"DFEmu",0.005, ...
@@ -222,7 +222,7 @@ for our_signal = 1
%
% ffe_results = ffe(eq_ffe,M,Rx_synced,Symbols,Bits, ...
% "precode_mode",duob_mode,'showAnalysis',0,"postFFE",[], ...
% "eth_style_symbol_mapping",mapping_style);
% "eth_style_symbol_mapping",mapping_style,'db_target',1);
%
% if our_signal
% fprintf('Our signal: %.1e \n',ffe_results.metrics.BER);
@@ -233,29 +233,43 @@ for our_signal = 1
% end
%% -------------------- VNLE + MLSE --------------------
pf_ncoeffs = 4;
eq_v = EQ("Ne",[300, 0, 0],"Nb",[2, 0, 0], ...
"training_length",len_tr,"training_loops",5,"dd_loops",5, ...
"K",sps,"DCmu",mu_dc,"DDmu",[mu_ffe mu_dfe],"DFEmu",0.005, ...
"FFEmu",0,"plotfinal",0,"ideal_dfe",0, ...
'weighted_DFE',1,'weighted_DFE_d_min',0.5,'weighted_DFE_mode','I2','weighted_DFE_I_mode',[1,0.1,0.1], ...
'PDFE_coefficient',0.01);
% eq_v = FFE_DFE('ffe_order',300,'dfe_order',5,'len_tr',len_tr,'epochs_tr',5,'epochs_dd',5, ...
% 'ffe_mu_dd',mu_ffe,'ffe_mu_tr',0,'dfe_mu_dd',mu_dfe,'dfe_mu_tr',0.005,'sps',sps,'decide',0);
pf_ = Postfilter("ncoeff",pf_ncoeffs,"useBurg",1);
mlse_ = MLSE("duobinary_output",0,'M',M,'trellis_states',PAMmapper(M,0,"eth_style",mapping_style).levels);
% pf_ncoeffs = 4;
% eq_v = EQ("Ne",[300, 0, 0],"Nb",[0, 0, 0], ...
% "training_length",len_tr,"training_loops",5,"dd_loops",5, ...
% "K",sps,"DCmu",mu_dc,"DDmu",[mu_ffe mu_dfe],"DFEmu",0.005, ...
% "FFEmu",0,"plotfinal",0,"ideal_dfe",0, ...
% 'weighted_DFE',2,'weighted_DFE_d_min',0.9,'weighted_DFE_mode','R1','weighted_DFE_I_mode',[1,0.1,0.1], ...
% 'PDFE_coefficient',0.01);
% % eq_v = FFE_DFE('ffe_order',300,'dfe_order',5,'len_tr',len_tr,'epochs_tr',5,'epochs_dd',5, ...
% % 'ffe_mu_dd',mu_ffe,'ffe_mu_tr',0,'dfe_mu_dd',mu_dfe,'dfe_mu_tr',0.005,'sps',sps,'decide',0);
% pf_ = Postfilter("ncoeff",pf_ncoeffs,"useBurg",1);
% mlse_ = MLSE("duobinary_output",0,'M',M,'trellis_states',PAMmapper(M,0,"eth_style",mapping_style).levels);
%
% [vnle_results, mlse_results] = vnle_postfilter_mlse(eq_v, pf_, mlse_, M, Rx_synced, Symbols, Bits, ...
% "precode_mode", duob_mode, 'showAnalysis', 1, "postFFE", [], "eth_style_symbol_mapping", mapping_style);
%
% mlse_results.metrics.print
% if our_signal
% fprintf('Our Signal: %.1e \n',mlse_results.metrics.BER);
% fprintf('Paper: %.1e \n \n',ber_in_paper);
% else
% fprintf('Their Signal: %.1e \n',mlse_results.metrics.BER);
% fprintf('Paper: %.1e \n \n',ber_in_paper);
% end
[vnle_results, mlse_results] = vnle_postfilter_mlse(eq_v, pf_, mlse_, M, Rx_synced, Symbols, Bits, ...
"precode_mode", duob_mode, 'showAnalysis', 1, "postFFE", [], "eth_style_symbol_mapping", mapping_style);
%% -------------------- DB target --------------------
mlse_db_ = MLSE("DIR",[1,1],"duobinary_output",0,"M",M,'trellis_states',PAMmapper(M,0).levels);
mlse_results.metrics.print
if our_signal
fprintf('Our Signal: %.1e \n',mlse_results.metrics.BER);
fprintf('Paper: %.1e \n \n',ber_in_paper);
else
fprintf('Their Signal: %.1e \n',mlse_results.metrics.BER);
fprintf('Paper: %.1e \n \n',ber_in_paper);
end
eq_ = EQ("Ne",[150, 0, 0],"Nb",[0, 0, 0],"training_length",len_tr,"training_loops",5,"dd_loops",5, ...
"K",sps,"DCmu",mu_dc,"DDmu",[mu_ffe mu_dfe],"DFEmu",0.005,"FFEmu",0,"plotfinal",0,"ideal_dfe",1);
dbt_results = duobinary_target(eq_,mlse_db_, M, Rx_synced, Symbols, Bits, ...
"precode_mode", duob_mode, 'showAnalysis', 0, "postFFE", [],"eth_style_symbol_mapping",mapping_style,'decoding_mode',0);
dbt_results.metrics.print("description",'Duobinary');
fprintf('My EQ: %.1e \n',dbt_results.metrics.BER);
fprintf('Paper: %.1e \n \n',ber_in_paper);
BER_value = dbt_results.metrics.BER;
%% -------------------- ML-based MLSE (L=2) --------------------
% ml_mlse_equalizer = ML_MLSE("epochs_tr",100,"epochs_dd",1, ...

View File

@@ -0,0 +1,83 @@
figure(202120); clf; hold on
set(gcf, 'WindowState', 'maximized');
x = 225:10:285;
shift = 0.5;
x = [x;x-shift;x+shift;x;x];
hErr = gobjects(1,4); % Errorbars -> für Legende
hLine = gobjects(1,4); % Linien durch Mittelwerte (nicht in Legende)
for k = 1:4
BER = load("C:\Users\magf\Desktop\Desktop\Projekte\FSO\Data\BER_PAM_2_Optimal" + string(k) + ".mat");
BER_all = BER.BER_num_signal_sweep_matrix;
BER_traces = BER_all((k-1)*7+1:k*7,:);
BER_min = zeros(1,7); BER_avg = zeros(1,7); BER_max = zeros(1,7);
for l = 1:7
BER_min(l) = min(BER_traces(l,:));
BER_avg(l) = mean(BER_traces(l,:));
BER_max(l) = max(BER_traces(l,:));
end
% Log-sicherer Floor
yFloor = 1e-12;
BER_min(BER_min <= 0 | isnan(BER_min) | isinf(BER_min)) = yFloor;
BER_max(BER_max <= 0 | isnan(BER_max) | isinf(BER_max)) = yFloor;
BER_max = max(BER_max, BER_min);
% Errorbar-Parameter (asymmetrisch)
y = BER_avg;
yneg = BER_avg - BER_min;
ypos = BER_max - BER_avg;
% Errorbars (Punkt + Intervall)
hErr(k) = errorbar(x(k,:), y, yneg, ypos, 'o', ...
'LineWidth', 2.75, 'MarkerSize', 8, 'CapSize', 10);
% Gestrichelte Linie durch die Mittelwerte (gleiche Farbe)
hLine(k) = plot(x(k,:), y, '--o', ...
'LineWidth', 2.75, ...
'MarkerSize', 8, ...
'Color', hErr(k).Color);
end
% Paper-Kurve
old_BER = 10.^([-1.5, -1.75, -2, -2.3, -2.6, -2.25, -1.95]);
hPaper = plot(x(k+1,:), old_BER, '-o', 'LineWidth', 2.75, 'MarkerSize', 8);
% FEC-Linien
yline(2e-2, ':k', 'LineWidth',1.2);
yline(3.8e-3,':b', 'LineWidth',1.2);
yline(4.85e-3,':g','LineWidth',1.2);
yline(2.2e-4,':r', 'LineWidth',1.2);
% FEC Labels (FontSize = 22)
text(240, 2.3e-2,'o-FEC', 'Color','k','FontSize',22,'Interpreter','latex')
text(222, 3e-3,'HD-FEC', 'Color','b','FontSize',22,'Interpreter','latex')
text(221, 5.7e-3,'KP4+Hamming', 'Color','g','FontSize',22,'Interpreter','latex')
text(232, 2.5e-4,'KP4', 'Color','r','FontSize',22,'Interpreter','latex')
% Achsen
set(gca,'YScale','log'); grid minor
ylim([1e-4 5e-1])
% Schriftgrößen Achsen
ax = gca;
ax.FontSize = 22;
ax.LabelFontSizeMultiplier = 1;
xlabel('Laser Bias Current [mA]', 'Interpreter','latex', 'FontSize', 22)
ylabel('BER', 'Interpreter','latex', 'FontSize', 22)
% Legende: Errorbar-Handles verwenden (Marker + vertikale Linie in der Legende)
lgd = legend([hErr(1) hErr(2) hErr(3) hErr(4) hPaper], ...
{'FFE','FFE+PF+MLSE','DB','ML-MLSE','BER Paper'}, ...
'Interpreter','latex','Location','southwest');
lgd.FontSize = 22;
% Figure-Style
set(gcf, 'Color', 'w');
set(gcf, 'Renderer', 'painters');
hold off

View File

@@ -0,0 +1,80 @@
figure(202120); clf; hold on
set(gcf, 'WindowState', 'maximized'); % automatisch Vollbild
x = 4:1:8;
shift = 0.05;
x = [x;x-shift;x;x+shift];
hErr = gobjects(1,4); % Errorbars -> für Legende
hLine = gobjects(1,4); % Linien durch Mittelwerte (nicht in Legende)
for k = 1:4
BER = load("C:\Users\magf\Desktop\Desktop\Projekte\FSO\Data\BER_PAM_4_Baud_Rate_Sweep_Optimal_" + string(k) + ".mat");
BER_all = BER.BER_num_signal_sweep_matrix;
BER_traces = BER_all((k-1)*5+1:k*5,:);
BER_min = zeros(1,5); BER_avg = zeros(1,5); BER_max = zeros(1,5);
for l = 1:5
BER_min(l) = min(BER_traces(l,:));
BER_avg(l) = mean(BER_traces(l,:));
BER_max(l) = max(BER_traces(l,:));
end
% Floor für Log-Plot (muss > 0 sein)
yFloor = 1e-7;
BER_min(BER_min <= 0 | isnan(BER_min) | isinf(BER_min)) = yFloor;
BER_max(BER_max <= 0 | isnan(BER_max) | isinf(BER_max)) = yFloor;
BER_max = max(BER_max, BER_min);
% Errorbar-Parameter (asymmetrisch)
y = BER_avg;
yneg = BER_avg - BER_min;
ypos = BER_max - BER_avg;
% Errorbars (Punkt + Intervall)
hErr(k) = errorbar(x(k,:), y, yneg, ypos, 'o', ...
'LineWidth', 2.5, 'MarkerSize', 8, 'CapSize', 10);
% Gestrichelte Linie durch die Mittelwerte (gleiche Farbe)
hLine(k) = plot(x(k,:), y, '--o', ...
'LineWidth', 2.5, ...
'MarkerSize', 8, ...
'Color', hErr(k).Color);
end
% FEC-Linien
yline(2e-2, ':k', 'LineWidth',1.2);
yline(3.8e-3,':b', 'LineWidth',1.2);
yline(4.85e-3,':g','LineWidth',1.2);
yline(2.2e-4,':r', 'LineWidth',1.2);
% FEC Labels (bleiben bei 14)
text(3.1,2.4e-2,'o-FEC','Color','k','FontSize',22,'Interpreter','latex')
text(3.1,2.7e-3,'HD-FEC','Color','b','FontSize',22,'Interpreter','latex')
text(3.1,6.3e-3,'KP4+Hamming','Color','g','FontSize',22,'Interpreter','latex')
text(3.1,2.7e-4,'KP4','Color','r','FontSize',22,'Interpreter','latex')
% Achsen
set(gca,'YScale','log'); grid minor
ylim([5e-7 5e-1])
xlim([3 9])
% ---- Schriftgrößen: Achsen + Legende = 22 ----
ax = gca;
ax.FontSize = 22;
ax.LabelFontSizeMultiplier = 1;
xlabel('Baud Rate [GBd]', 'Interpreter','latex', 'FontSize', 22)
ylabel('BER', 'Interpreter','latex', 'FontSize', 22)
% ---- Legende: Errorbar-Handles verwenden (Marker + vertikale Linie) ----
lgd = legend([hErr(1) hErr(2) hErr(3) hErr(4)], ...
{'FFE','FFE+PF+MLSE','DB','ML-MLSE'}, ...
'Interpreter','latex','Location','southwest');
lgd.FontSize = 22;
% ---- Figure "Presentation"-Style ----
set(gcf, 'Color', 'w');
set(gcf, 'Renderer', 'painters');
hold off

View File

@@ -0,0 +1,84 @@
figure(202120); clf; hold on
set(gcf, 'WindowState', 'maximized');
x = 225:10:285;
shift = 0.5;
x = [x;x-shift;x+shift;x;x];
hErr = gobjects(1,4); % Errorbars -> für Legende
hLine = gobjects(1,4); % Linien durch Mittelwerte (nicht in Legende)
for k = 1:4
BER = load("C:\Users\magf\Desktop\Desktop\Projekte\FSO\Data\BER_PAM_4_Optimal" + string(k) + ".mat");
BER_all = BER.BER_num_signal_sweep_matrix;
BER_traces = BER_all((k-1)*7+1:k*7,:);
BER_min = zeros(1,7); BER_avg = zeros(1,7); BER_max = zeros(1,7);
for l = 1:7
BER_min(l) = min(BER_traces(l,:));
BER_avg(l) = mean(BER_traces(l,:));
BER_max(l) = max(BER_traces(l,:));
end
% Log-sicherer Floor (falls min=0)
yFloor = 1e-12;
BER_min(BER_min <= 0 | isnan(BER_min) | isinf(BER_min)) = yFloor;
BER_max(BER_max <= 0 | isnan(BER_max) | isinf(BER_max)) = yFloor;
BER_max = max(BER_max, BER_min);
% Errorbar-Parameter (asymmetrisch)
y = BER_avg;
yneg = BER_avg - BER_min;
ypos = BER_max - BER_avg;
% Errorbars (Punkt + Intervall)
hErr(k) = errorbar(x(k,:), y, yneg, ypos, 'o', ...
'LineWidth', 2.75, 'MarkerSize', 8, 'CapSize', 10);
% Gestrichelte Linie durch die Mittelwerte (gleiche Farbe)
hLine(k) = plot(x(k,:), y, '--o', ...
'LineWidth', 2.75, ...
'MarkerSize', 8, ...
'Color', hErr(k).Color);
end
% Paper-Kurve
old_BER = 10.^([-1.6, -1.85, -2.2, -2.45, -2.3, -2, -1.4]);
hPaper = plot(x(k+1,:), old_BER, '-o', 'LineWidth', 2.75, 'MarkerSize', 8);
% FEC-Linien
yline(2e-2, ':k', 'LineWidth',1.2);
yline(3.8e-3,':b', 'LineWidth',1.2);
yline(4.85e-3,':g','LineWidth',1.2);
yline(2.2e-4,':r', 'LineWidth',1.2);
% FEC Labels (wie bei dir, FontSize = 16)
text(221, 2.3e-2,'o-FEC', 'Color','k','FontSize',22,'Interpreter','latex')
text(221, 3e-3,'HD-FEC', 'Color','b','FontSize',22,'Interpreter','latex')
text(221, 6e-3,'KP4+Hamming', 'Color','g','FontSize',22,'Interpreter','latex')
text(221, 2.5e-4,'KP4', 'Color','r','FontSize',22,'Interpreter','latex')
% Achsen
set(gca,'YScale','log'); grid minor
ylim([1e-5 5e-1])
% ---- Schriftgrößen: Achsen + Legende = 22 ----
ax = gca;
ax.FontSize = 22;
ax.LabelFontSizeMultiplier = 1;
xlabel('Laser Bias Current [mA]', 'Interpreter','latex', 'FontSize', 22)
ylabel('BER', 'Interpreter','latex', 'FontSize', 22)
% Legende: Errorbar-Handles verwenden (Marker + vertikale Linie)
lgd = legend([hErr(1) hErr(2) hErr(3) hErr(4) hPaper], ...
{'FFE','FFE+PF+MLSE','DB','ML-MLSE','BER Paper'}, ...
'Interpreter','latex','Location','southwest');
lgd.FontSize = 22;
% ---- Figure "Presentation"-Style ----
set(gcf, 'Color', 'w');
set(gcf, 'Units', 'pixels', 'Position', [100 100 1400 900]);
set(gcf, 'Renderer', 'painters');
hold off