FSO analysis:
- minimal changes in several files - new Timing Rec from Magnus
This commit is contained in:
@@ -1,15 +1,15 @@
|
||||
|
||||
base = "C:\Users\Silas\Nextcloud\Dokumente\02_Ablage_Office\FSO_FP_QCL_60umUTC";
|
||||
base = "C:\Users\Silas\Nextcloud4\Dokumente\02_Ablage_Office\FSO_FP_QCL_60umUTC";
|
||||
mode = 0; %0 oder 1
|
||||
M = 2;
|
||||
|
||||
all_files = dir(fullfile(base, "**/*.mat"));
|
||||
|
||||
if M == 2
|
||||
tx_data = load("C:\Users\Silas\Nextcloud\Dokumente\02_Ablage_Office\FSO_FP_QCL_60umUTC\14G_PAM2\tx_info\tx_info_PAM2_14Gbd0.75RRC.mat");
|
||||
tx_data = load("C:\Users\Silas\Nextcloud4\Dokumente\02_Ablage_Office\FSO_FP_QCL_60umUTC\14G_PAM2\tx_info\tx_info_PAM2_14Gbd0.75RRC.mat");
|
||||
filename = fullfile(base, "14G_PAM2\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 = load("C:\Users\Silas\Nextcloud\Dokumente\02_Ablage_Office\FSO_FP_QCL_60umUTC\6G_PAM4\tx_info\tx_info_PAM4_6Gbd0.6RRC.mat");
|
||||
tx_data = load("C:\Users\Silas\Nextcloud4\Dokumente\02_Ablage_Office\FSO_FP_QCL_60umUTC\6G_PAM4\tx_info\tx_info_PAM4_6Gbd0.6RRC.mat");
|
||||
filename = fullfile(base, "6G_PAM4\M=4_Rs=6e9_Fs=8e10_I=255mA_RoP=42.3mW_L=31m_PS=RRC_rolloff=0.6_Mode=Rise.mat");
|
||||
end
|
||||
|
||||
@@ -53,10 +53,14 @@ Bits_ = PM.demap(Symbols);
|
||||
assert(ber == 0);
|
||||
|
||||
%% For comparison, apply pulsef on Tx Symbols
|
||||
Pform = Pulseformer("fsym",fsym,"fdac",fs,"pulse","rc","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);
|
||||
Pform = Pulseformer("fsym",fsym,"fdac",fs,"pulse","rrc","pulselength",16,"alpha",rolloff);
|
||||
Digi_sig_tx_compare = Pform.process(Symbols);
|
||||
|
||||
Pform = Pulseformer("fsym",fsym,"fdac",4*fsym,"pulse","rrc","pulselength",16,"alpha",rolloff);
|
||||
Digi_sync = Pform.process(Symbols);
|
||||
|
||||
MF = Pulseformer("fsym",fsym,"fdac",4*fsym,"pulse","rrc","pulselength",16,"alpha",rolloff);
|
||||
Rx_sig_compare = MF.process(Digi_sig_tx_compare);
|
||||
|
||||
%%
|
||||
|
||||
@@ -68,53 +72,47 @@ scoperead_volts = (traceData.RawData - traceData.YReference) * traceData.YIncrem
|
||||
demystified = isequal(traceData.YData,scoperead_volts);
|
||||
assert(demystified);
|
||||
|
||||
timesig_compare = [0:1:datas.tr.lastData(1).trace.ch3.Points-1] ./ fs;
|
||||
timesig = datas.tr.lastData(1).trace.ch3.XData;
|
||||
assert(isequal(traceData.YData,scoperead_volts));
|
||||
|
||||
Scope_sig = Electricalsignal(traceData.YData,"fs",fs);
|
||||
|
||||
Scope_sig.plot("displayname",'raw','fignum',100);
|
||||
Scope_sig.spectrum("displayname",'raw','fignum',101)
|
||||
|
||||
%%
|
||||
% 1) matched filter
|
||||
% pulse is symmetric, hence we can use pulsef firectly as matched filter.
|
||||
% pulse is symmetric, hence we can use pulsef directly 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!?
|
||||
Pform = Pulseformer("fsym",fsym,"fdac",2*fsym,"pulse","rrc","pulselength",16,"alpha",rolloff,"matched",1);
|
||||
Rx_matched = Pform.process(Scope_sig);
|
||||
Rx_matched.spectrum("displayname",'Signal after matched filter','fignum',1);
|
||||
apply_matched_filter = 0;
|
||||
k = 4;
|
||||
if apply_matched_filter
|
||||
|
||||
Pform = Pulseformer("fsym",fsym,"fdac",k*fsym,"pulse","rrc","pulselength",16,"alpha",rolloff,"matched",1);
|
||||
Rx_matched = Pform.process(Scope_sig);
|
||||
else
|
||||
|
||||
Rx_matched = Filter('filtdegree',4,"f_cutoff",fsym*0.5,"fs",Scope_sig.fs,"filterType",filtertypes.gaussian,"active",true).process(Scope_sig);
|
||||
Rx_matched = Rx_matched.resample("fs_out",k*fsym);
|
||||
end
|
||||
Rx_matched.spectrum();
|
||||
|
||||
%%
|
||||
|
||||
sys = comm.SymbolSynchronizer('TimingErrorDetector', 'Gardner (non-data-aided)', ...
|
||||
'SamplesPerSymbol', 2, ...
|
||||
'DampingFactor', 0.7, ...
|
||||
'NormalizedLoopBandwidth', 0.01);
|
||||
Rx_symbolsync = Rx_matched;
|
||||
[Rx_symbolsync.signal, timing_error] = sys(Rx_matched.signal);
|
||||
|
||||
plot(timing_error); % If this is a ramp, you have drift!
|
||||
|
||||
%% 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_symbolsync.tsynch("reference", Symbols, "fs_ref", fsym, "debug_plots", 1);
|
||||
|
||||
|
||||
%% not working..
|
||||
Rx_synced = Rx_synced_cell{1};
|
||||
len_tr = 4096*2;
|
||||
mu_ffe1 = 0.0001;
|
||||
mu_ffe2 = 0.0008;
|
||||
mu_ffe3 = 0.001;
|
||||
mu_dc = 0.005;
|
||||
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',2);
|
||||
|
||||
Digi_sig_compare.normalize("mode","rms").spectrum("displayname",'Tx: RC-shaped','fignum',1,'normalizeTo0dB',0);
|
||||
Rx_sig_compare.normalize("mode","rms").spectrum("displayname",'Tx: RC-shaped + matched filtered ','fignum',1,'normalizeTo0dB',0);
|
||||
Rx_synced.normalize("mode","rms").spectrum("displayname",'RX: matched filtered + synced','fignum',1,'normalizeTo0dB',0);
|
||||
%% Timing Rec
|
||||
apply_timing_rec = 1;
|
||||
if apply_timing_rec
|
||||
[Rx_symbolsync, timing_error] = Timing_Recovery("timing_error_detector",'Gardner (non-data-aided)','sps',k,'damping_factor',0.1,'normalized_loop_bandwidth',0.1,'detector_gain',2.7).process(Rx_matched);
|
||||
figure();plot(timing_error);
|
||||
Rx_symbolsync.fs = fsym;
|
||||
% Tsynch
|
||||
[~,Rx_synced_cell,inverted,sequenceFound,sequenceStarts] = Rx_symbolsync.tsynch("reference", Symbols, "fs_ref", fsym, "debug_plots", 0);
|
||||
Rx_synced = Rx_synced_cell{1};
|
||||
sps = 1;
|
||||
else
|
||||
% Tsynch
|
||||
[~,Rx_synced_cell,inverted,sequenceFound,sequenceStarts] = Rx_matched.tsynch("reference", Symbols, "fs_ref", fsym, "debug_plots", 0);
|
||||
Rx_synced = Rx_synced_cell{1};
|
||||
Rx_synced = Rx_synced.resample("fs_out",2*fsym);
|
||||
sps = 2;
|
||||
end
|
||||
|
||||
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
|
||||
@@ -122,50 +120,121 @@ elseif M == 4
|
||||
ber_in_paper = 10^(-2.5);
|
||||
end
|
||||
|
||||
%% -------------------- FFE --------------------
|
||||
% requires some more digging what is going on :-)
|
||||
eq_ffe = EQ("Ne",[50, 5, 5],"Nb",[2,0,0], ...
|
||||
"training_length",len_tr,"training_loops",5,"dd_loops",5, ...
|
||||
"K",2,"DCmu",mu_dc,"DDmu",[mu_ffe mu_dfe],"DFEmu",0.005, ...
|
||||
|
||||
%%
|
||||
|
||||
Rx_synced = Rx_synced_cell{1};
|
||||
|
||||
|
||||
% -------------------- FFE --------------------
|
||||
% requires some more digging what is going on :-)
|
||||
eq_ffe = EQ("Ne",[50, 1, 1],"Nb",[2,0,0], ...
|
||||
"training_length",512,"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);
|
||||
vars = logspace(-4,-3,36);
|
||||
|
||||
% ffe_results.metrics.print
|
||||
fprintf('My EQ: %.1e \n',ffe_results.metrics.BER);
|
||||
parfor i = 1:numel(vars)
|
||||
|
||||
len_tr = 4096;
|
||||
mu_ffe1 = 0.01;% mus(i);%0.0001;
|
||||
mu_ffe2 = 0.0008;
|
||||
mu_ffe3 = 0.001;
|
||||
mu_dc = 0.005;
|
||||
mu_ffe = [mu_ffe1 mu_ffe2 mu_ffe3];
|
||||
mu_dfe = vars(i);
|
||||
duob_mode = db_mode.no_db;
|
||||
|
||||
% requires some more digging what is going on :-)
|
||||
eq_ffe_1 = EQ("Ne",[150, 1, 0],"Nb",[50,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);
|
||||
|
||||
eq_ffe_2 = FFE("epochs_tr",1,"epochs_dd",vars(i),"len_tr",4096,"mu_dd",vars(i),"mu_tr",vars(i),"order",999,"sps",1,"decide",0, "adaption",adaption_method.nlms,"dd_mode",0);
|
||||
% eq_ffe_2 = FFE_DFE("epochs_tr",5,"epochs_dd",5,"len_tr",4096*2,"ffe_mu_dd",1e-5,"dfe_mu_dd",mus(i),"ffe_mu_tr",0,"dfe_mu_tr",0,"ffe_order",50,"dfe_order",10,"sps",1,"decide",1);
|
||||
|
||||
|
||||
ffe_results = ffe(eq_ffe_1,M,Rx_synced,Symbols,Bits, ...
|
||||
"precode_mode",duob_mode,'showAnalysis',1,"postFFE",[], ...
|
||||
"eth_style_symbol_mapping",mapping_style);
|
||||
|
||||
ffe_results.metrics.BER
|
||||
bers(i) = ffe_results.metrics.BER;
|
||||
end
|
||||
|
||||
figure();
|
||||
plot(vars,bers);
|
||||
yline(ber_in_paper)
|
||||
beautifyBERplot();
|
||||
%
|
||||
fprintf('Paper: %.1e \n \n',ber_in_paper);
|
||||
ffe_results.metrics.print("description",'FFE');
|
||||
fprintf('FFE: %.1e \n',ffe_results.metrics.BER);
|
||||
|
||||
|
||||
%% -------------------- VNLE + MLSE --------------------
|
||||
len_tr = 4096;
|
||||
mu_ffe1 = 0.0001;% mus(i);%0.0001;
|
||||
mu_ffe2 = 0.0008;
|
||||
mu_ffe3 = 0.001;
|
||||
mu_dc = 0.005;
|
||||
mu_ffe = [mu_ffe1 mu_ffe2 mu_ffe3];
|
||||
mu_dfe = 0.0004;
|
||||
duob_mode = db_mode.no_db;
|
||||
|
||||
pf_ncoeffs = 1;
|
||||
eq_v = EQ("Ne",[100, 5, 5],"Nb",[0, 0, 0], ...
|
||||
pf_ncoeffs = 4;
|
||||
|
||||
vars = 1:7;
|
||||
bers = zeros(size(vars));
|
||||
parfor i = 1:numel(vars)
|
||||
|
||||
eqv = EQ("Ne",[200, 1, 0],"Nb",[2, 0, 0], ...
|
||||
"training_length",len_tr,"training_loops",5,"dd_loops",5, ...
|
||||
"K",2,"DCmu",mu_dc,"DDmu",[mu_ffe mu_dfe],"DFEmu",0.005, ...
|
||||
"K",sps,"DCmu",mu_dc,"DDmu",[mu_ffe mu_dfe],"DFEmu",0.005, ...
|
||||
"FFEmu",0,"plotfinal",0,"ideal_dfe",1);
|
||||
pf_ = Postfilter("ncoeff",pf_ncoeffs,"useBurg",1);
|
||||
mlse_ = MLSE("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("description",'MLSE')
|
||||
fprintf('My EQ: %.1e \n',mlse_results.metrics.BER);
|
||||
fprintf('Paper: %.1e \n \n',ber_in_paper);
|
||||
pf_ncoeffs = vars(i);
|
||||
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(eqv, pf, mlse_, M, Rx_synced, Symbols, Bits, ...
|
||||
"precode_mode", duob_mode, 'showAnalysis', 1, "postFFE", [], "eth_style_symbol_mapping", mapping_style);
|
||||
fprintf('Paper: %.1e \n \n',ber_in_paper);
|
||||
vnle_results.metrics.print("description",'VNLE');
|
||||
mlse_results.metrics.print("description",'MLSE');
|
||||
bers(i) = mlse_results.metrics.BER;
|
||||
end
|
||||
%%
|
||||
figure();hold on
|
||||
plot(vars,bers_ffe,'DisplayName','FFE [200,0,0] + PF + MLSE');
|
||||
plot(vars,bers_vnle,'DisplayName','VNLE [200,1,0] + PF + MLSE');
|
||||
plot(vars,bers_vnledfe,'DisplayName','VNLE [200,1,0] + DFE [2] + PF + MLSE');
|
||||
plot(vars,bers_vnledfe_ideal,'DisplayName','VNLE [200,1,0] + ideal DFE [2] + PF + MLSE');
|
||||
yline(ber_in_paper);
|
||||
yline([2e-2, 4.85e-3, 3.8e-3, 2,2e-4],'LineWidth',2,'Color',[0.8,0.8,0.8],'LineStyle',':','HandleVisibility','off');
|
||||
ylim([1e-5,0.1]);
|
||||
beautifyBERplot();
|
||||
|
||||
%% -------------------- DB target --------------------
|
||||
mlse_db_ = MLSE("DIR",[1,1],"duobinary_output",0,"M",M,'trellis_states',PAMmapper(M,0).levels);
|
||||
|
||||
eq_ = EQ("Ne",[50, 5, 5],"Nb",[0,0,0],"training_length",len_tr,"training_loops",5,"dd_loops",5, ...
|
||||
"K",2,"DCmu",mu_dc,"DDmu",[mu_ffe mu_dfe],"DFEmu",0.005,"FFEmu",0,"plotfinal",0,"ideal_dfe",1);
|
||||
"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);
|
||||
|
||||
dbt_results.metrics.print("description",'Duobinary');
|
||||
mlse_results.metrics.print
|
||||
fprintf('My EQ: %.1e \n',dbt_results.metrics.BER);
|
||||
fprintf('Paper: %.1e \n \n',ber_in_paper);
|
||||
dbt_results.metrics.print("description",'Duobinary');
|
||||
|
||||
|
||||
%%
|
||||
|
||||
%ML-based MLSE (L=2)
|
||||
mu_ml = 0.01; training_epochs = 100;
|
||||
ml_mlse_equalizer = ML_MLSE("epochs_tr",training_epochs,"epochs_dd",1, ...
|
||||
"len_tr",len_tr,"mu_dd",mu_ml,"mu_tr",mu_ml,"order",11,"sps",1, ...
|
||||
"traceback_depth",128,"L",3,"delta",4,"adaptive_mu",0);
|
||||
|
||||
[ml_mlse_results] = ml_mlse(ml_mlse_equalizer, M, Rx_synced, Symbols, Bits,"precode_mode",duob_mode);
|
||||
ml_mlse_results.metrics.print("description",'ML ');
|
||||
@@ -2,7 +2,7 @@ dsp_options.storage_path = 'Z:\2024\sioe_labor\';
|
||||
dsp_options.max_occurences = 1;
|
||||
database = DBHandler("dataBase", 'labor_highspeed', "type", 'mysql' );
|
||||
|
||||
rate = [300e9];
|
||||
|
||||
cols = cbrewer2('BuPu',25);
|
||||
cols = [cols(end-10:2:end,:)];
|
||||
cols = cbrewer2('Set1',6);
|
||||
@@ -12,10 +12,10 @@ fig=figure(fignum);clf;
|
||||
|
||||
dbmode = 0;
|
||||
|
||||
|
||||
% 1 - PAM 4 with preemphasis
|
||||
fp = QueryFilter();
|
||||
M = 6;
|
||||
M = 8;
|
||||
rate = [360e9];
|
||||
fp.where('Runs', 'pam_level','EQUALS', M);
|
||||
fp.where('Runs', 'bitrate','EQUALS', rate);%360,390
|
||||
fp.where('Runs', 'fiber_length','EQUALS', 2);
|
||||
@@ -23,7 +23,7 @@ fp.where('Runs', 'wavelength','EQUALS', 1310);
|
||||
fp.where('Runs', 'db_mode','EQUALS', dbmode);
|
||||
fp.where('Runs', 'rop_attenuation','EQUAL', 0);
|
||||
|
||||
[dataTable,~] = db.queryDB(fp, database.getTableFieldNames('Runs'));
|
||||
[dataTable,~] = database.queryDB(fp, database.getTableFieldNames('Runs'));
|
||||
|
||||
dataTable = queryRunid(dataTable.run_id, database);
|
||||
fsym = dataTable.symbolrate;
|
||||
@@ -33,14 +33,36 @@ duob_mode = db_mode(strrep(dataTable.db_mode,'"',''));
|
||||
% Load and Sync signal data from DB
|
||||
[Tx_bits, Symbols, Scpe_cell, ~] = loadAndSyncSignalDataFromDb(dataTable, dsp_options);
|
||||
|
||||
Scpe_sig_syncd = Scpe_cell{1};
|
||||
Scpe_sig_syncd.eye(fsym,M,"fignum",rate.*1e-9*M+1,"displayname",' Eye of Signal');
|
||||
%%%%%% SNR CHEAT - Avges the measured signal occurences found after correlation in "tsynch" %%%%%%
|
||||
average_signals = 1;
|
||||
if average_signals
|
||||
Scpe_sig_avg = Scpe_sig_syncd;
|
||||
scope_mean = zeros(size(Scpe_cell{1}.signal));
|
||||
for n=1:numel(Scpe_cell)
|
||||
scope_mean = scope_mean + Scpe_cell{n}.signal;
|
||||
end
|
||||
scope_mean = scope_mean ./ n;
|
||||
Scpe_sig_avg.signal = scope_mean;
|
||||
|
||||
Scpe_sig_avg.spectrum("displayname","Scope PSD","fignum",20,"normalizeTo0dB",1);
|
||||
Scpe_sig_avg.plot("displayname","Scope raw signal","fignum",27,"clear",1);
|
||||
Scpe_sig_avg = Scpe_sig_avg.*1.25;
|
||||
Scpe_sig_avg.eye(fsym,M,"fignum",rate.*1e-9*M,"displayname",' Eye of AVG Signal');
|
||||
end
|
||||
|
||||
% Preprocess signal
|
||||
Scpe_sig = preprocessSignal(Scpe_cell{1}, Symbols, fsym);
|
||||
Scpe_sig = preprocessSignal(Scpe_sig_avg, Symbols, fsym);
|
||||
|
||||
Scpe_sig.eye(fsym,M,"fignum",M*10);
|
||||
|
||||
|
||||
|
||||
%% === EXPORT TO TIKZ ===
|
||||
% outfile = ['C:\Users\Silas\Documents\latex\JLT_400G copy\media\matlab2tikz\eye_pam_',num2str(M),'.tikz'];
|
||||
% outfile = ['C:\Users\Silas\Documents\latex\JLT_400G copy\media\matlab2tikz\vnle_optimization.tikz'];
|
||||
|
||||
% outfile = ['C:\Users\Silas\Documents\latex\JLT_400G_submission\media\matlab2tikz\eye_pam_',num2str(M),'-2.tikz'];
|
||||
% % outfile = ['C:\Users\Silas\Documents\latex\JLT_400G copy\media\matlab2tikz\vnle_optimization.tikz'];
|
||||
% matlab2tikz(outfile, ...
|
||||
% 'width','\fwidth', ...
|
||||
% 'height','\fheight', ...
|
||||
|
||||
@@ -42,14 +42,14 @@ fp = QueryFilter();
|
||||
% fp.where('Runs', 'run_id','EQUALS', 2776);
|
||||
M = 6;
|
||||
fp.where('Runs', 'pam_level','EQUALS', M);
|
||||
% fp.where('Runs', 'bitrate','EQUALS', 390e9);%360,390
|
||||
fp.where('Runs', 'bitrate','EQUALS', 360e9);%360,390
|
||||
% fp.where('Runs', 'symbolrate','EQUALS', 195e9);
|
||||
fp.where('Runs', 'fiber_length','EQUALS', 10);
|
||||
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', 'wavelength','EQUALS', 1310);
|
||||
fp.where('Runs', 'db_mode','EQUALS', 0);
|
||||
fp.where('Runs', 'rop_attenuation','EQUAL', 0);
|
||||
% fp.where('Runs', 'power_pd_in','LESS_THAN', 7);
|
||||
@@ -70,7 +70,7 @@ wh.addStorage("mlmlse_package");
|
||||
|
||||
%% === RUN IT ===
|
||||
|
||||
[results,wh] = submitJobs(dataTable.run_id(:), dsp_options, "parallel", 'wh', wh, 'waitbar', true);
|
||||
[results,wh] = submitJobs(dataTable.run_id(:), dsp_options, "serial", 'wh', wh, 'waitbar', true);
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
filename = "C:\Users\sioe\Documents\High_Speed_Measurement_2024\baudrate_sweep_b2b\PAMX_b2b_baudrate20241024_210648_wh.mat";
|
||||
filename = "F:\2024\sioe\High Speed Messungen Oktober\baudrate_sweep_b2b\PAMX_b2b_baudrate20241024_210648_wh_final.mat";
|
||||
|
||||
a = load(filename);
|
||||
wh = a.obj;
|
||||
|
||||
@@ -8,7 +8,7 @@ fdac = 256e9;
|
||||
fadc = 256e9;
|
||||
random_key = 1;
|
||||
|
||||
rcalpha = 0.05;
|
||||
rcalpha = 0.6;
|
||||
kover = 16;
|
||||
|
||||
duob_mode = db_mode.no_db;
|
||||
@@ -25,7 +25,7 @@ tx_bw_nyquist = 0.8;
|
||||
link_length = 1;
|
||||
|
||||
% RX
|
||||
rop = -8;
|
||||
rop = -9;
|
||||
rx_bw_nyquist = 0.8;
|
||||
|
||||
vnle_order1 = 50;
|
||||
@@ -51,7 +51,7 @@ mu_ffe = [mu_ffe1 mu_ffe3 mu_ffe3];
|
||||
mu_dfe = 0.0004;
|
||||
|
||||
|
||||
Pform = Pulseformer("fsym",fsym,"fdac",4*fsym,"pulse","rc","pulselength",16,"alpha",rcalpha);
|
||||
Pform = Pulseformer("fsym",fsym,"fdac",4*fsym,"pulse","rrc","pulselength",16,"alpha",rcalpha);
|
||||
|
||||
[Digi_sig,Symbols,Tx_bits] = PAMsource(...
|
||||
"fsym",fsym,"M",M,"order",18,"useprbs",0,...
|
||||
@@ -65,7 +65,7 @@ Pform = Pulseformer("fsym",fsym,"fdac",4*fsym,"pulse","rc","pulselength",1
|
||||
%%%%% AWG
|
||||
El_sig = M8199A("kover",kover).process(Digi_sig);
|
||||
% El_sig = AWG("fdac",fdac,"f_cutoff",fsym,"lpf_active",0,"kover",kover,"bit_resolution",12,"upsampling_method","samplehold","precomp_sinc_rolloff",1).process(Digi_sig);
|
||||
El_sig.spectrum("displayname",'Digi Spectrum','fignum',100,'normalizeTo0dB',0);
|
||||
El_sig.spectrum("displayname",'Digi Spectrum','fignum',1,'normalizeTo0dB',1);
|
||||
% El_sig = El_sig.setPower(0,"dBm");
|
||||
|
||||
%%%%% Electrical Driver Amplifier %%%%%%
|
||||
@@ -101,32 +101,53 @@ Scpe_sig = Scope("fsimu",fdac*kover,"fadc",fadc,...
|
||||
"delay",0,"fixed_delay",0,"filtertype",filtertypes.butterworth,...
|
||||
"samplingdelay",0,"rand_samplingdelay",0,"freq_offset",0,"samp_jitter",0,...
|
||||
"adcresolution",8,"quantbuffer",0.1,'block_dc',1,'lpf_active',1,'H_lpf',Lp_scpe).process(Rx_sig);
|
||||
%%
|
||||
|
||||
%%%%%% Sample to 2x fsym %%%%%%
|
||||
Scpe_sig = Scpe_sig.resample("fs_out",2*fsym);
|
||||
Scpe_sig.signal = Scpe_sig.signal(1:2*length(Symbols));
|
||||
% 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!?
|
||||
Pform = Pulseformer("fsym",fsym,"fdac",2*fsym,"pulse","rrc","pulselength",16,"alpha",rcalpha,"matched",1);
|
||||
Scpe_sig = Pform.process(Scpe_sig);
|
||||
Scpe_sig.spectrum("displayname",'Signal after matched filter','fignum',1,'normalizeTo0dB',1);
|
||||
%
|
||||
|
||||
% %%
|
||||
% %%%%%% Sample to 2x fsym %%%%%%
|
||||
% Scpe_sig = Scpe_sig.resample("fs_out",2*fsym);
|
||||
% Scpe_sig.signal = Scpe_sig.signal(1:2*length(Symbols));
|
||||
|
||||
%%
|
||||
%%%%%% Sync Rx signal with reference %%%%%%
|
||||
[Scpe_sig,~] = Scpe_sig.tsynch("reference",Symbols,"fs_ref",fsym,"debug_plots",0);
|
||||
[Scpe_sig,~] = Scpe_sig.tsynch("reference",Symbols,"fs_ref",fsym,"debug_plots",1);
|
||||
Scpe_sig.spectrum("displayname",'Opt Spectrum','fignum',11,'normalizeTo0dB',1);
|
||||
|
||||
Scpe_sig = Filter('filtdegree',4,"f_cutoff",Symbols.fs.*0.5,"fs",Scpe_sig.fs,"filterType",filtertypes.gaussian,"active",true).process(Scpe_sig);
|
||||
% Scpe_sig = Filter('filtdegree',4,"f_cutoff",Symbols.fs.*0.5,"fs",Scpe_sig.fs,"filterType",filtertypes.gaussian,"active",true).process(Scpe_sig);
|
||||
|
||||
Scpe_sig = Scpe_sig - mean(Scpe_sig.signal);
|
||||
Scpe_sig.signal = Scpe_sig.signal(1:2*length(Symbols));
|
||||
|
||||
%%
|
||||
|
||||
% -------------------- FFE --------------------
|
||||
ffe_order = [50, 0, 0];
|
||||
eq_ffe = EQ("Ne",ffe_order,"Nb",[0,0,0], ...
|
||||
eq_ = EQ("Ne",ffe_order,"Nb",[2,0,0], ...
|
||||
"training_length",len_tr,"training_loops",5,"dd_loops",5, ...
|
||||
"K",2,"DCmu",mu_dc,"DDmu",[mu_ffe mu_dfe],"DFEmu",0.005, ...
|
||||
"FFEmu",0,"plotfinal",0,"ideal_dfe",0);
|
||||
|
||||
output.ffe_results = ffe(eq_ffe,M,Scpe_sig,Symbols,Tx_bits, ...
|
||||
"precode_mode",duob_mode,'showAnalysis',0,"postFFE",[], ...
|
||||
% eq_ = FFE("epochs_tr",4,"epochs_dd",5,"len_tr",4096,"mu_dd",0.01,"mu_tr",0.01,"order",50,"sps",2,"decide",0, "adaption",adaption_method.nlms,"dd_mode",1);
|
||||
eq_ = FFE_DFE("epochs_tr",5,"epochs_dd",5,"len_tr",512,"ffe_mu_dd",1e-4,"dfe_mu_dd",5e-4,"ffe_mu_tr",0,"dfe_mu_tr",0,"ffe_order",99,"dfe_order",99,"sps",2,"decide",0);
|
||||
|
||||
|
||||
output.ffe_results = ffe(eq_,M,Scpe_sig,Symbols,Tx_bits, ...
|
||||
"precode_mode",duob_mode,'showAnalysis',1,"postFFE",[], ...
|
||||
"eth_style_symbol_mapping",0);
|
||||
|
||||
output.ffe_results.metrics.print
|
||||
|
||||
%%
|
||||
|
||||
% -------------------- VNLE + MLSE --------------------
|
||||
pf_ncoeffs = 1;
|
||||
ffe_order3 = [50, 5, 5];
|
||||
@@ -139,8 +160,11 @@ pf_ = Postfilter("ncoeff",pf_ncoeffs,"useBurg",1);
|
||||
mlse_ = MLSE("duobinary_output",0,'M',M,'trellis_states',PAMmapper(M,0).levels);
|
||||
|
||||
[output.vnle_results, output.mlse_results] = vnle_postfilter_mlse(eq_v, pf_, mlse_, M, Scpe_sig, Symbols, Tx_bits, ...
|
||||
"precode_mode", duob_mode, 'showAnalysis', 0, "postFFE", [], "eth_style_symbol_mapping", 0);
|
||||
"precode_mode", duob_mode, 'showAnalysis', 1, "postFFE", [], "eth_style_symbol_mapping", 0);
|
||||
|
||||
output.mlse_results.metrics.print
|
||||
|
||||
%%
|
||||
|
||||
% -------------------- DB target --------------------
|
||||
mlse_db_ = MLSE("DIR",[1,1],"duobinary_output",0,"M",M,'trellis_states',PAMmapper(M,0).levels);
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
wh_aeon = load("C:\Users\Silas\Documents\MATLAB\imdd_simulation\projects\Lab_analysis\aeon_soa_measurement_lambda_plaser_pump.mat");
|
||||
wh_aeon = wh_aeon.wh;
|
||||
wh_thor = load("C:\Users\Silas\Documents\MATLAB\imdd_simulation\projects\Lab_analysis\thorlabs_pdfa_measurement_lambda_plaser_pump.mat");
|
||||
wh_thor = wh_thor.wh;
|
||||
|
||||
% Silas' custom "warehouse" datatype
|
||||
wh_aeon.showInfo;
|
||||
wh_thor.showInfo;
|
||||
|
||||
%% PLOT OSA SPECTRA
|
||||
|
||||
figure();hold on
|
||||
cols = linspecer(4);
|
||||
cols = cbrewer2('Paired',8);
|
||||
subplot(1,2,1);hold on;
|
||||
wh = wh_thor;
|
||||
ccnt = 1;
|
||||
|
||||
pumps = wh.parameter.pump.values;
|
||||
plasers = wh.parameter.laserpower.values;
|
||||
scnt = 1;
|
||||
for p = 1:numel(plasers)
|
||||
|
||||
for pmp = 1:numel(pumps)
|
||||
subplot(numel(plasers),numel(pumps),scnt);hold on;
|
||||
title(sprintf('Laser: %d dBm; Pump: %d %',plasers(p),pumps(pmp)),"Interpreter","tex")
|
||||
for lambda = wh.parameter.lambda.values
|
||||
|
||||
spectrum_osa = wh_thor.getStoValue('spectrum_osa',plasers(p),lambda,pumps(pmp));
|
||||
wavelength_osa = wh_thor.getStoValue('wavelength_osa',plasers(p),lambda,pumps(pmp));
|
||||
plot(wavelength_osa,spectrum_osa,'DisplayName',sprintf('P_{in}: %d dB ',plasers(p)),'Color',cols(ccnt,:));
|
||||
|
||||
|
||||
spectrum_osa = wh_aeon.getStoValue('spectrum_osa',plasers(p),lambda,pumps(pmp));
|
||||
wavelength_osa = wh_aeon.getStoValue('wavelength_osa',plasers(p),lambda,pumps(pmp));
|
||||
plot(wavelength_osa,spectrum_osa,'DisplayName',sprintf('P_{in}: %d dB ',plasers(p)),'Color',cols(ccnt+1,:));
|
||||
|
||||
|
||||
ylim([-60, 20]);
|
||||
beautifyBERplot("logscale",false,"setmarkers",0,"setcolors",0);
|
||||
end
|
||||
scnt = scnt +1;
|
||||
end
|
||||
ccnt = ccnt+2;
|
||||
end
|
||||
|
||||
|
||||
xlabel('Wavelength [nm]');
|
||||
ylabel('OSNR [dB]')
|
||||
|
||||
|
||||
%%
|
||||
|
||||
figure();hold on
|
||||
cols = linspecer(4);
|
||||
subplot(1,2,1);hold on;
|
||||
wh = wh_thor;
|
||||
ccnt = 1;
|
||||
|
||||
pumps = wh.parameter.pump.values;
|
||||
plasers = wh.parameter.laserpower.values;
|
||||
scnt = 1;
|
||||
for p = 1:numel(plasers)
|
||||
|
||||
for pmp = 1:numel(pumps)
|
||||
subplot(numel(plasers),numel(pumps),scnt);hold on;
|
||||
|
||||
|
||||
ase_noise = wh_thor.getStoValue('pase_osa',plasers(p),wh.parameter.lambda.values,pumps(pmp));
|
||||
signal = wh_thor.getStoValue('psig_osa',plasers(p),wh.parameter.lambda.values,pumps(pmp));
|
||||
plot(wh.parameter.lambda.values,ase_noise,'DisplayName',sprintf('P_{in}: %d dB ',plasers(p)),'Color',cols(ccnt,:));
|
||||
|
||||
|
||||
ase_noise = wh_aeon.getStoValue('pase_osa',plasers(p),wh.parameter.lambda.values,pumps(pmp));
|
||||
signal = wh_aeon.getStoValue('psig_osa',plasers(p),wh.parameter.lambda.values,pumps(pmp));
|
||||
plot(wh.parameter.lambda.values,ase_noise,'DisplayName',sprintf('P_{in}: %d dB ',plasers(p)),'Color',cols(ccnt,:),'LineStyle','-');
|
||||
|
||||
ylim([-60, 20]);
|
||||
beautifyBERplot("logscale",false,"setmarkers",0,"setcolors",0);
|
||||
|
||||
scnt = scnt +1;
|
||||
end
|
||||
ccnt = ccnt+1;
|
||||
end
|
||||
|
||||
|
||||
xlabel('Wavelength [nm]');
|
||||
ylabel('OSNR [dB]')
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
base = "C:\Users\Silas\Nextcloud\Cluster";
|
||||
base = "C:\Users\Silas\Nextcloud4\Cluster";
|
||||
all_files = dir(fullfile(base, "**/*.mat"));
|
||||
|
||||
schemes = ["co","pair","alt","seg"];
|
||||
@@ -13,8 +13,8 @@ T = table('Size',[0 10], ...
|
||||
rx = "^WDM_(?<date>\d{8})_(?<time>\d{6})_n(?<node>\d+)_(?<jobid>\d+)_" + ...
|
||||
"(?<L>\d+)km_(?<Nch>\d+)ch_(?<df>\d+)ghz_(?<scheme>[a-z]+)_alpha(?<alpha>\d+(?:_\d+)?)\.mat$";
|
||||
|
||||
for k = 1:numel(all_files)
|
||||
f = all_files(k);
|
||||
for i = 1:numel(all_files)
|
||||
f = all_files(i);
|
||||
folder = string(f.folder);
|
||||
file = string(f.name);
|
||||
|
||||
@@ -44,6 +44,8 @@ for k = 1:numel(all_files)
|
||||
end
|
||||
|
||||
%%
|
||||
|
||||
|
||||
idx = strcmp(T.scheme,"co") & ...
|
||||
T.alpha == 0.4 & ...
|
||||
T.date >= datetime(2026,1,9) & ...
|
||||
@@ -51,13 +53,181 @@ idx = strcmp(T.scheme,"co") & ...
|
||||
|
||||
T_sel = T(idx,:);
|
||||
|
||||
i = 2;
|
||||
res = load(fullfile(T_sel.folder(i),T_sel.file(i)),'res');
|
||||
res = res.res;
|
||||
% ---- Load all res ----
|
||||
R = cell(numel(T_sel.file),1);
|
||||
for i = 1:numel(T_sel.file)
|
||||
S = load(fullfile(T_sel.folder(i),T_sel.file(i)),'res');
|
||||
S.res = strip_config_from_res(S.res);
|
||||
R{i} = S.res;
|
||||
end
|
||||
|
||||
res_all = combine_res_list(R);
|
||||
res_all = drop_empty_realizations(res_all);
|
||||
|
||||
|
||||
%%
|
||||
|
||||
|
||||
|
||||
%%
|
||||
|
||||
|
||||
%%
|
||||
% Routine A: plot BER curves and compute crossings
|
||||
S = plot_BER_vs_ROP(res, 'fec', 3.8e-3);
|
||||
S = plot_BER_vs_ROP(res_all, 'fec', 3.8e-3);
|
||||
|
||||
%% Routine B: violin plot (independent)
|
||||
plot_FEC_violin(res, 'tech','VNLE', 'fec',3.8e-3, 'ylim',[-10 0]);
|
||||
plot_FEC_violin(res_all, 'tech','VNLE', 'fec',3.8e-3, 'ylim',[-10 0],'eval_ptr',5);
|
||||
|
||||
|
||||
%%
|
||||
|
||||
function res = strip_config_from_res(res)
|
||||
% Remove the "config" payload from every non-empty result cell
|
||||
% Works whether entries are structs-with-field or objects-with-property.
|
||||
|
||||
techs = {'ffe','dfe','vnle','mlse','dbt'};
|
||||
|
||||
for t = 1:numel(techs)
|
||||
fn = techs{t};
|
||||
if ~isfield(res, fn) || isempty(res.(fn)), continue; end
|
||||
|
||||
C = res.(fn);
|
||||
if ~iscell(C), continue; end
|
||||
|
||||
idx = find(~cellfun('isempty', C)); % fast builtin
|
||||
for k = 1:numel(idx)
|
||||
x = C{idx(k)};
|
||||
|
||||
% Case 1: struct entry with field "config"
|
||||
if isstruct(x) && isfield(x,'config')
|
||||
x = rmfield(x,'config');
|
||||
|
||||
% Case 2: object entry with property "config"
|
||||
elseif isobject(x) && isprop(x,'config')
|
||||
try
|
||||
x.config = []; % lighter than keeping Equalizerstruct JSON
|
||||
catch
|
||||
% ignore if class forbids assignment
|
||||
end
|
||||
end
|
||||
|
||||
C{idx(k)} = x;
|
||||
end
|
||||
|
||||
res.(fn) = C;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
% ===================== Local helper functions =====================
|
||||
|
||||
function res_out = combine_res_list(R)
|
||||
% Concatenate along realization dimension (dim=3) for all techniques.
|
||||
% Requires consistent sizes in dims 1,2,4 and consistent eval_dist_km.
|
||||
|
||||
fieldsTech = ["ffe","dfe","vnle","mlse","dbt"];
|
||||
|
||||
% Start with first
|
||||
res_out = R{1};
|
||||
|
||||
% --- Build common distance axis (union, stable) ---
|
||||
dist_all = res_out.eval_dist_km(:).';
|
||||
for k = 2:numel(R)
|
||||
dist_all = unique([dist_all, R{k}.eval_dist_km(:).'], 'stable');
|
||||
end
|
||||
|
||||
% --- If res_out not already on dist_all, expand it ---
|
||||
if ~isequal(res_out.eval_dist_km(:).', dist_all)
|
||||
res_out = expand_res_dist(res_out, dist_all);
|
||||
end
|
||||
|
||||
% --- For each file: expand to dist_all, then merge realizations (your logic) ---
|
||||
for k = 2:numel(R)
|
||||
R{k} = expand_res_dist(R{k}, dist_all);
|
||||
end
|
||||
|
||||
|
||||
% Concatenate technique cell arrays along dim=3 (realizations)
|
||||
for f = fieldsTech
|
||||
A = res_out.(f);
|
||||
for k = 2:numel(R)
|
||||
B = R{k}.(f);
|
||||
A = cat(3, A, B);
|
||||
end
|
||||
res_out.(f) = A;
|
||||
end
|
||||
|
||||
% Update num_realiz in settings to match concatenated dim
|
||||
dims = size(res_out.ffe); if numel(dims)<3, dims(3)=1; end
|
||||
res_out.settings.num_realiz = dims(3);
|
||||
end
|
||||
|
||||
function res = expand_res_dist(res, dist_all)
|
||||
techs = {'ffe','dfe','vnle','mlse','dbt'};
|
||||
|
||||
old = res.eval_dist_km(:).';
|
||||
new = dist_all(:).';
|
||||
[~,loc] = ismember(old, new); % mapping old -> new positions
|
||||
if any(loc==0)
|
||||
error('expand_res_dist: internal: old distances not found in union.');
|
||||
end
|
||||
|
||||
% sizes from an existing field (prefer ffe)
|
||||
Cref = res.ffe;
|
||||
sz = size(Cref); sz(end+1:4) = 1; % ensure 4 dims
|
||||
Nch=sz(1); Nrop=sz(2); Nreal=sz(3); Nnew=numel(new);
|
||||
|
||||
for t = 1:numel(techs)
|
||||
fn = techs{t};
|
||||
if ~isfield(res,fn) || isempty(res.(fn)), continue; end
|
||||
Cold = res.(fn);
|
||||
sz2 = size(Cold); sz2(end+1:4) = 1;
|
||||
|
||||
Cnew = cell(sz2(1), sz2(2), sz2(3), Nnew);
|
||||
Cnew(:,:,:,loc) = Cold; % place old distances into new axis
|
||||
res.(fn) = Cnew;
|
||||
end
|
||||
|
||||
res.eval_dist_km = new;
|
||||
end
|
||||
|
||||
|
||||
function res_out = drop_empty_realizations(res_in)
|
||||
% Removes realizations where ALL entries are empty across ALL techniques
|
||||
% (across channels, rop, distances).
|
||||
|
||||
res_out = res_in;
|
||||
fieldsTech = ["ffe","dfe","vnle","mlse","dbt"];
|
||||
|
||||
% Determine sizes from one field
|
||||
dims = size(res_in.ffe);
|
||||
if numel(dims) < 4, dims(end+1:4) = 1; end
|
||||
Nreal = dims(3);
|
||||
|
||||
% For each realization, check if there is at least one non-empty result anywhere
|
||||
keep = false(1, Nreal);
|
||||
for r = 1:Nreal
|
||||
hasAny = false;
|
||||
for f = fieldsTech
|
||||
C = res_in.(f); % cell array
|
||||
% Slice all ch,rop,dist for this realization
|
||||
slice = C(:,:,r,:); % still a cell array
|
||||
hasAny = any(~cellfun(@isempty, slice(:)));
|
||||
if hasAny, break; end
|
||||
end
|
||||
keep(r) = hasAny;
|
||||
end
|
||||
|
||||
fprintf('drop_empty_realizations: keeping %d/%d realizations (dropping %d)\n', ...
|
||||
sum(keep), Nreal, sum(~keep));
|
||||
|
||||
% Apply keep mask
|
||||
for f = fieldsTech
|
||||
res_out.(f) = res_out.(f)(:,:,keep,:);
|
||||
end
|
||||
|
||||
% Update settings
|
||||
res_out.settings.num_realiz = sum(keep);
|
||||
end
|
||||
|
||||
|
||||
Reference in New Issue
Block a user