From 16846d4eb75f9543ae7964caee7d69c69abb023d Mon Sep 17 00:00:00 2001 From: Silas Oettinghaus Date: Mon, 12 Jan 2026 11:36:15 +0100 Subject: [PATCH 1/7] stuff --- .../a_minimal_example.m | 125 +++++++++--------- projects/WDM/WDM_auswertung.m | 14 +- projects/WDM/WDM_model_16x200.m | 30 +++-- 3 files changed, 91 insertions(+), 78 deletions(-) diff --git a/projects/HighSpeedExperiment_2024/a_minimal_example.m b/projects/HighSpeedExperiment_2024/a_minimal_example.m index 966d5b9..2a94e13 100644 --- a/projects/HighSpeedExperiment_2024/a_minimal_example.m +++ b/projects/HighSpeedExperiment_2024/a_minimal_example.m @@ -4,70 +4,77 @@ dsp_options.storage_path = 'Z:\2024\sioe_labor\'; dsp_options.max_occurences = 1; db = DBHandler("dataBase", 'labor_highspeed', "type", 'mysql' ); -fp = QueryFilter(); - -fp.where('Runs','fiber_length','EQUALS', 2); -fp.where('Runs','wavelength','EQUALS', 1310); -fp.where('Runs','bitrate','EQUALS', 300e9); -fp.where('Runs','pam_level','EQUALS', 4); -fp.where('Runs','rop_attenuation','EQUALS', 0); -fp.where('Runs','is_mpi','EQUALS', 0); -fp.where('Runs', 'db_mode','EQUALS', 0); -% fields = db.getTableFieldNames('Runs'); -% [dataTable,~] = db.queryDB(fp, fields); -fields = db.getTableFieldNames('power_state_info'); -fields = [fields; db.getTableFieldNames('Runs')]; -fields = [fields; db.getTableFieldNames('dashboard_ungrouped_alltime')]; %dashboard_ungrouped_after_nov_2025 dashboard_ungrouped_aug_nov_2025 -fields = unique(fields); -[dataTable,~] = db.queryDB(fp, fields); - - -fsym = dataTable(1,:).symbolrate; -M = double(dataTable(1,:).pam_level); -duob_mode = db_mode(strrep(dataTable(1,:).db_mode,'"','')); - - -% Load and Sync signal data from DB -[Tx_bits, Symbols, Scpe_cell, ~] = loadAndSyncSignalDataFromDb(dataTable(1,:), dsp_options); - -% Preprocess signal -Scpe_sig = preprocessSignal(Scpe_cell{1}, Symbols, fsym); - -% Show spectrum -Scpe_sig.spectrum("fignum",1,"displayname",'Rx') - -% meta = struct(); -% meta.varnames = dataTable.Properties.VariableNames; +% fp = QueryFilter(); % -% for k = 1:numel(meta.varnames) -% v = meta.varnames{k}; -% col = dataTable.(v); +% fp.where('Runs','fiber_length','EQUALS', 2); +% fp.where('Runs','wavelength','EQUALS', 1310); +% fp.where('Runs','bitrate','EQUALS', 300e9); +% fp.where('Runs','pam_level','EQUALS', 4); +% fp.where('Runs','rop_attenuation','EQUALS', 0); +% fp.where('Runs','is_mpi','EQUALS', 0); +% fp.where('Runs', 'db_mode','EQUALS', 0); +% % fields = db.getTableFieldNames('Runs'); +% % [dataTable,~] = db.queryDB(fp, fields); % -% if isnumeric(col) || islogical(col) -% meta.(v) = col; -% elseif isstring(col) -% meta.(v) = cellstr(col); -% elseif iscellstr(col) -% meta.(v) = col; -% else -% error("Unsupported table column type: %s", class(col)) -% end -% end -% exp_data.metadata = meta; -exp_data = struct(); -exp_data.metadata = dataTable; -exp_data.tx_bits = Tx_bits.signal; -exp_data.tx_signal = Symbols.signal; -exp_data.rx_signal_2sps = Scpe_sig.signal; +run_ids = [ 993 1205 1413 1623 1833 2043 2253 2628 2836 2958 3000 3042 3323 5098 5225 5267 5309]; -fname = dataTable(1,:).rx_raw_path; -[~, filename, ext] = fileparts(fname); -filename = strrep(filename,"_raw_signal",""); -filename = filename + ext; -savepath = fullfile('F:\2024\sioe_labor\export_skuehl\',filename); -save(savepath,'exp_data','-v7.3'); +for id = run_ids + + fp = QueryFilter(); + fp.where('Runs', 'run_id','EQUALS', id); + fields = db.getTableFieldNames('power_state_info'); + fields = [fields; db.getTableFieldNames('Runs')]; + fields = [fields; db.getTableFieldNames('dashboard_ungrouped_alltime')]; %dashboard_ungrouped_after_nov_2025 dashboard_ungrouped_aug_nov_2025 + fields = unique(fields); + [dataTable,~] = db.queryDB(fp, fields); + + fsym = dataTable(1,:).symbolrate; + M = double(dataTable(1,:).pam_level); + duob_mode = db_mode(strrep(dataTable(1,:).db_mode,'"','')); + + % Load and Sync signal data from DB + [Tx_bits, Symbols, Scpe_cell, ~] = loadAndSyncSignalDataFromDb(dataTable(1,:), dsp_options); + + % Preprocess signal + Scpe_sig = preprocessSignal(Scpe_cell{1}, Symbols, fsym); + + % Show spectrum + Scpe_sig.spectrum("fignum",1,"displayname",'Rx') + + meta = struct(); + meta.varnames = dataTable.Properties.VariableNames; + + for k = 1:numel(meta.varnames) + v = meta.varnames{k}; + col = dataTable.(v); + + if isnumeric(col) || islogical(col) + meta.(v) = col; + elseif isstring(col) + meta.(v) = cellstr(col); + elseif iscellstr(col) + meta.(v) = col; + else + error("Unsupported table column type: %s", class(col)) + end + end + exp_data.metadata = meta; + + exp_data = struct(); + exp_data.metadata = dataTable; + exp_data.tx_bits = Tx_bits.signal; + exp_data.tx_signal = Symbols.signal; + exp_data.rx_signal_2sps = Scpe_sig.signal; + + fname = dataTable(1,:).rx_raw_path; + [~, filename, ext] = fileparts(fname); + filename = strrep(filename,"_raw_signal",""); + filename = filename + ext; + savepath = fullfile('F:\2024\sioe_labor\export_skuehl\',filename); + save(savepath,'exp_data','-v7.3'); +end diff --git a/projects/WDM/WDM_auswertung.m b/projects/WDM/WDM_auswertung.m index d13c97f..1f3b949 100644 --- a/projects/WDM/WDM_auswertung.m +++ b/projects/WDM/WDM_auswertung.m @@ -21,7 +21,7 @@ Smlse = cell(1,N); Sdbt = cell(1,N); % Choose your quantile band. For your old style, use 0.04/0.99: -qLow = 0.0; % lower quantile (e.g., 0.04 for old script) +qLow = 0.0; % lower quantile (e.g.,s 0.04 for old script) qHigh = 1; % upper quantile (e.g., 0.99 for old script) cols = linspecer(N); % one color per wavelength (Ch) cols = cbrewer2('set1',N); @@ -51,10 +51,10 @@ for l = 1:N showLegend = 1; % one legend entry per technique % Plot shaded band + mean line with boundedline - % plotBandMeanBL(rop, ffe_mat, cols(l,:), sprintf('FFE @ %.1d nm',round(wavelengthplan(l))), qLow, qHigh, '--s', showLegend); + plotBandMeanBL(rop, ffe_mat, cols(l,:), sprintf('FFE @ %.1d nm',round(wavelengthplan(l))), qLow, qHigh, '--s', showLegend); % scatter(Sffe,fec.*ones(size(Sffe)),20,'v','MarkerFaceColor','black'); - plotBandMeanBL(rop, vnle_mat, cols(l,:), sprintf('VNLE @ %.1d nm',round(wavelengthplan(l))), qLow, qHigh, '--x', showLegend); + % plotBandMeanBL(rop, vnle_mat, cols(l,:), sprintf('VNLE @ %.1d nm',round(wavelengthplan(l))), qLow, qHigh, '--x', showLegend); % plotBandMeanBL(rop, mlse_mat, cols(l,:), sprintf('VNLE+PF+MLSE @ %.1d nm',round(wavelengthplan(l))), qLow, qHigh, '-o', showLegend); @@ -73,7 +73,7 @@ ylim([1e-5 0.3]); grid on; legend show; - +%% S_cell = Sdbt; S_cell =Smlse; S_cell = {Svnle,Smlse,Sdbt}; @@ -106,7 +106,7 @@ for i = 1:length(S_cell) 'Bandwidth', 0.05); ylim([floor(min(S_mat,[],'all')), ceil(max(S_mat,[],'all'))]) - ylim([-8 0]); + % ylim([-8 0]); ylabel('ROP at FEC crossing'); title(sprintf('RROP to cross BER %.2e', fec)); grid on; box on; @@ -118,10 +118,6 @@ end - - - - %% ================= helper ================= function plotBandMeanBL(x, Y, color, techLabel, qLow, qHigh, lineSpec, showLegend) % Y: (nPoints x nRealizations) diff --git a/projects/WDM/WDM_model_16x200.m b/projects/WDM/WDM_model_16x200.m index 7000966..3d6dac9 100644 --- a/projects/WDM/WDM_model_16x200.m +++ b/projects/WDM/WDM_model_16x200.m @@ -6,9 +6,9 @@ run(fullfile(fileparts(mfilename('fullpath')),'WDM_settings.m')); s.num_realiz = 2; s.wavelengthplan = calcWavelengthPlan(16,400e9,1310); % wavelengthplan = [1295,1305,1315,1325]; -link_length = 0; -pmd = 0.1; -gamma = 0.0023; +link_length = 1; +s.pmd = 0.1; +s.gamma = 0.0023; s.M = 4; m = floor(log2(s.M)*10)/10; @@ -52,7 +52,7 @@ f_plan = physconst('lightspeed')./(s.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; -kover = 8; +kover = 4; upsample_required = f_nyq./(fdac*kover/2); upsample_pow = 2^nextpow2(upsample_required); upsample_ceil = ceil(upsample_required); @@ -64,13 +64,23 @@ signal_cell = {}; Symbols = {}; Tx_bits = {}; -s.rop = -6:0.75:-0.75; +s.rop = -12:0.75:-0.75; output_ffe = cell(length(s.wavelengthplan),length(s.rop),s.num_realiz); output_vnle = cell(length(s.wavelengthplan),length(s.rop),s.num_realiz); output_mlse = cell(length(s.wavelengthplan),length(s.rop),s.num_realiz); output_dbt = cell(length(s.wavelengthplan),length(s.rop),s.num_realiz); +s.p = "pair"; +switch s.p + case "co" + pol_rot = 100.*ones(1,length(s.wavelengthplan)); + case "pair" + pol_rot = repmat([100,100,0,0],1,length(s.wavelengthplan)/4); + case "alt" + pol_rot = repmat([100,0,100,0],1,length(s.wavelengthplan)/4); +end + for realiz = 1:s.num_realiz @@ -100,7 +110,7 @@ for realiz = 1:s.num_realiz %%%%% s.MODULATE E/O CONVERSION %%%%% Eml_out = EML("mode",eml_mode.im_cosinus,"power",3,"fsimu",El_sig.fs,"lambda",s.wavelengthplan(l),"bias",vbias,"u_pi",u_pi,"linewidth",laser_linewidth,"randomkey",s.random_key+l+realiz).process(El_sig); - signal_cell{l} = Polarization_Controller("mode","rot_power","desired_power",100).process(Eml_out); + signal_cell{l} = Polarization_Controller("mode","rot_power","desired_power",pol_rot(l)).process(Eml_out); end Opt_sig_wdm = Optical_Multiplex("fs_in",fdac*kover,"fs_out",upsample_pow*fdac*kover,... @@ -108,7 +118,7 @@ for realiz = 1:s.num_realiz 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',0,'lambda0_nm',1310,'useWavelengthAxis',0); % Opt_sig_wdm.spectrum("fignum",101,"displayname",'bla','normalizeTo0dB',1,'max_num_lines',2); @@ -123,7 +133,7 @@ for realiz = 1:s.num_realiz Dvec = getDispersionVector(nSegments, D_local, zdw, randomize_D, s.random_key+realiz); for seg = 1:nSegments - Opt_sig_wdm_fib = DP_Fiber("L",segment_length,"D",Dvec(s),"Dpmd",pmd,"Ds",0.07,... + Opt_sig_wdm_fib = DP_Fiber("L",segment_length,"D",Dvec(seg),"Dpmd",s.pmd,"Ds",0.07,... "beat_len",10,"corr_len",100,"dz",1,"manakov",0,... "gamma",s.gamma,"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); @@ -135,11 +145,11 @@ for realiz = 1:s.num_realiz % Opt_sig_wdm_fib.move_it_spectrum("fignum",100212,"displayname",'bla'); % Opt_sig = Fiber("fsimu",Opt_sig.fs,"fiber_length",s.link_length/1000,"alpha",0.3,"D",0,"lambda0",1310,"s.gamma",0,"Dslope",0.07).process(Opt_sig) - 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_fib); + Opt_sig_wdm_demux = Optical_Demultiplex("attenuation",0,"B",200e9,"filtype",1,"fs_out",fdac*kover,"fs_in",fdac*kover*upsample_pow,"lambda_center",1310).process(Opt_sig_wdm_fib); for ri = 1:length(s.rop) - parfor l = 1:N + for l = 1:N %%%%%% ROP %%%%%% Opt_sig_wdm_rx = Amplifier("amp_mode","ideal_no_noise","gain_mode","output_power","amplification_db",s.rop(ri)).process(Opt_sig_wdm_demux{l}); % rop+10*log10(N) From 719e5508e776c18e3dcf72a954c71bdedda179e0 Mon Sep 17 00:00:00 2001 From: Silas Oettinghaus Date: Tue, 20 Jan 2026 10:49:59 +0100 Subject: [PATCH 2/7] FSO analysis: - minimal changes in several files - new Timing Rec from Magnus --- Classes/00_signals/Signal.m | 6 +- Classes/04_DSP/Timing_Recovery.m | 10 +- Functions/EQ_structures/dsp_runid.m | 7 +- Functions/EQ_structures/ffe.m | 25 +- Functions/EQ_structures/ml_mlse.m | 6 +- .../EQ_structures/vnle_postfilter_mlse.m | 2 +- .../{violinplot.m => violinplot_community.m} | 0 projects/FSO_transmission/first_analysis.m | 215 ++++++++++++------ .../Auswertung_JLT/final/FIGURE_EYES.m | 36 ++- .../Auswertung_JLT/run_dsp_from_db.m | 8 +- .../baudrate_evaluation.m | 2 +- projects/IMDD_base_system/minimal_example.m | 50 ++-- .../lambda_vs_spectrum.m | 88 +++++++ projects/WDM/WDM_auswertung.m | 186 ++++++++++++++- 14 files changed, 511 insertions(+), 130 deletions(-) rename Libs/Violinplot-Matlab-master/{violinplot.m => violinplot_community.m} (100%) create mode 100644 projects/Lab_analysis/data_analysis_and_plot_scripts/lambda_vs_spectrum.m diff --git a/Classes/00_signals/Signal.m b/Classes/00_signals/Signal.m index 5905556..1377ddc 100644 --- a/Classes/00_signals/Signal.m +++ b/Classes/00_signals/Signal.m @@ -971,8 +971,8 @@ classdef Signal maxA = max(sig(100:end-100))*1.3; minA = min(sig(100:end-100))*1.3; - % maxA = 0.12; - % minA = -0.08; + maxA = 0.12; + minA = -0.08; difference= maxA-minA; @@ -993,7 +993,9 @@ classdef Signal % beautify cm=flip(cbrewer2("RdYlBu",4096)); % cm=flip(cbrewer2("RdBu",4096)); + % cm=flip(cbrewer2("Blues",4096)); cm(1,:) = [1,1,1]; % set zeros to white => clean background + colormap(cm); % colormap('turbo'); % ax.CLim = [0 50]; diff --git a/Classes/04_DSP/Timing_Recovery.m b/Classes/04_DSP/Timing_Recovery.m index ba16f10..23cc331 100644 --- a/Classes/04_DSP/Timing_Recovery.m +++ b/Classes/04_DSP/Timing_Recovery.m @@ -9,7 +9,7 @@ classdef Timing_Recovery < handle end methods(Access=public) - function obj = FFE(options) + function obj = Timing_Recovery(options) arguments(Input) options.timing_error_detector = 'Gardner'; @@ -25,12 +25,11 @@ classdef Timing_Recovery < handle obj.(fn{n}) = options.(fn{n}); end - obj.e = zeros(obj.order,1); - obj.error = 0; + end - function data_out = process(obj, data_in) + function [data_out,timing_error] = process(obj, data_in) timing_synchronization = comm.SymbolSynchronizer( ... "TimingErrorDetector", obj.timing_error_detector, ... @@ -39,7 +38,8 @@ classdef Timing_Recovery < handle "NormalizedLoopBandwidth", obj.normalized_loop_bandwidth, ... "DetectorGain", obj.detector_gain); - data_out.signal = timing_synchronization(data_in.signal); + data_out = data_in; + [data_out.signal,timing_error] = timing_synchronization(data_in.signal); end end diff --git a/Functions/EQ_structures/dsp_runid.m b/Functions/EQ_structures/dsp_runid.m index 4d207bd..c10cb5c 100644 --- a/Functions/EQ_structures/dsp_runid.m +++ b/Functions/EQ_structures/dsp_runid.m @@ -95,7 +95,7 @@ try adaption= 1; use_dd_mode = 1; - use_ffe = 0; + use_ffe = 1; use_dfe = 0; use_vnle_mlse = 0; use_dbtgt = 0; @@ -149,6 +149,9 @@ try % Scpe_sig.spectrum("fignum",22233,"normalizeTo0dB",0,"displayname",'Rx'); % Scpe_sig.eye(fsym,M,"fignum",1024); + Scpe_sig.signal = Scpe_sig.signal(1:2*Symbols.length); + Scpe_sig.signal = real(Scpe_sig.signal); + if duob_mode ~= db_mode.db_encoded if use_ffe @@ -246,7 +249,7 @@ try %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",length(Scpe_sig),"mu_dd",mu_ml,"mu_tr",mu_ml,"order",11,"sps",2, ... + "len_tr",length(Scpe_sig)/4,"mu_dd",mu_ml,"mu_tr",mu_ml,"order",11,"sps",2, ... "traceback_depth",128,"L",1,"delta",4,"adaptive_mu",0); [ml_mlse_results] = ml_mlse(ml_mlse_equalizer, M, Scpe_sig, Symbols, Tx_bits,"precode_mode",duob_mode); diff --git a/Functions/EQ_structures/ffe.m b/Functions/EQ_structures/ffe.m index df4138e..c7e7c52 100644 --- a/Functions/EQ_structures/ffe.m +++ b/Functions/EQ_structures/ffe.m @@ -157,7 +157,7 @@ function displayAnalysis(eq_noise, eq_signal_sd, rx_signal, eq_, tx_symbols, M, % Initialize figure handles % Corrected line - added tx_symbols as second positional argument - showLevelScatter(rx_signal.resample("fs_out", tx_symbols.fs), tx_symbols, "fignum", 100); + % showLevelScatter(rx_signal.resample("fs_out", tx_symbols.fs), tx_symbols, "fignum", 100); warning off showLevelScatter(eq_signal_sd, tx_symbols, "fignum", 101); @@ -174,19 +174,20 @@ function displayAnalysis(eq_noise, eq_signal_sd, rx_signal, eq_, tx_symbols, M, end try - figure(339); - showEQfilter(eq_.e_tr, eq_signal_sd.fs.*2,"displayname",'training','fignum',339); - showEQfilter(eq_.e, eq_signal_sd.fs.*2,"displayname",'dec. directed','fignum',339); + figure(339);hold on + showEQfilter(eq_.e, eq_signal_sd.fs.*2,"displayname",'training','fignum',339); + % showEQfilter(eq_.e, eq_signal_sd.fs.*2,"displayname",'dec. directed','fignum',339); legend on end - try - figure(240); hold on; plot(pow2db(movmean(eq_.debug_struct.error_tr',100)));ylim([-30,3]);title('error training'); - - figure(241); hold on; plot(pow2db(movmean(eq_.debug_struct.update_tr',100)));title('update step training'); - - figure(242); hold on; plot(pow2db(movmean(eq_.debug_struct.update',1000)));title('update step dd'); - end - % eq_signal_sd.eye(eq_signal_sd.fs,M,"displayname",'Eye','fignum',105); + % try + % figure(240); hold on; plot(pow2db(movmean(eq_.debug_struct.error_tr',100)));ylim([-30,3]);title('error training'); + % + % figure(241); hold on; plot(pow2db(movmean(eq_.debug_struct.update_tr',100)));title('update step training'); + % + % figure(242); hold on; plot(pow2db(movmean(eq_.debug_struct.update',1000)));title('update step dd'); + % end + + eq_signal_sd.eye(eq_signal_sd.fs,M,"displayname",'Eye','fignum',105); end \ No newline at end of file diff --git a/Functions/EQ_structures/ml_mlse.m b/Functions/EQ_structures/ml_mlse.m index f2d468d..ce2112c 100644 --- a/Functions/EQ_structures/ml_mlse.m +++ b/Functions/EQ_structures/ml_mlse.m @@ -45,8 +45,7 @@ end ml_mlse_results.config = Equalizerstruct(); -eq_small = strip_eq(eq_, 10); -json_str = jsonencode(eq_small); +eq_ = strip_eq(eq_, 10); ml_mlse_results.config.eq = jsonencode(eq_); ml_mlse_results.config.equalizer_structure = int32(equalizer_structure.ml_mlse); @@ -135,6 +134,9 @@ function eq_out = strip_eq(eq_, max_elems) eq_.(props{i}) = []; end end + if issparse(val) + eq_.(props{i}) = find(eq_.(props{i})); + end end eq_out = eq_; end diff --git a/Functions/EQ_structures/vnle_postfilter_mlse.m b/Functions/EQ_structures/vnle_postfilter_mlse.m index c7f10e1..0e6aea5 100644 --- a/Functions/EQ_structures/vnle_postfilter_mlse.m +++ b/Functions/EQ_structures/vnle_postfilter_mlse.m @@ -283,7 +283,7 @@ if ~isempty(postFFE) showEQcoefficients('n1', postFFE.e, "displayname", 'Coefficients', 'fignum', 338); end -showEQcoefficients('n1', eq_.e,'n2', eq_.e2,'n3', eq_.e3, "displayname", 'Coefficients', 'fignum', 339); +% showEQcoefficients('n1', eq_.e1,'n2', eq_.e2,'n3', eq_.e3, "displayname", 'Coefficients', 'fignum', 339); showEQfilter(eq_.e, eq_signal_sd.fs.*2); figure(340); clf; diff --git a/Libs/Violinplot-Matlab-master/violinplot.m b/Libs/Violinplot-Matlab-master/violinplot_community.m similarity index 100% rename from Libs/Violinplot-Matlab-master/violinplot.m rename to Libs/Violinplot-Matlab-master/violinplot_community.m diff --git a/projects/FSO_transmission/first_analysis.m b/projects/FSO_transmission/first_analysis.m index c47a2b1..d8361bc 100644 --- a/projects/FSO_transmission/first_analysis.m +++ b/projects/FSO_transmission/first_analysis.m @@ -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 '); \ No newline at end of file diff --git a/projects/HighSpeedExperiment_2024/Auswertung_JLT/final/FIGURE_EYES.m b/projects/HighSpeedExperiment_2024/Auswertung_JLT/final/FIGURE_EYES.m index c22e90f..0d953af 100644 --- a/projects/HighSpeedExperiment_2024/Auswertung_JLT/final/FIGURE_EYES.m +++ b/projects/HighSpeedExperiment_2024/Auswertung_JLT/final/FIGURE_EYES.m @@ -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', ... diff --git a/projects/HighSpeedExperiment_2024/Auswertung_JLT/run_dsp_from_db.m b/projects/HighSpeedExperiment_2024/Auswertung_JLT/run_dsp_from_db.m index 8f96ba2..ab31451 100644 --- a/projects/HighSpeedExperiment_2024/Auswertung_JLT/run_dsp_from_db.m +++ b/projects/HighSpeedExperiment_2024/Auswertung_JLT/run_dsp_from_db.m @@ -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); diff --git a/projects/HighSpeedExperiment_2024/baudrate_evaluation.m b/projects/HighSpeedExperiment_2024/baudrate_evaluation.m index 0a48e57..100fa1d 100644 --- a/projects/HighSpeedExperiment_2024/baudrate_evaluation.m +++ b/projects/HighSpeedExperiment_2024/baudrate_evaluation.m @@ -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; diff --git a/projects/IMDD_base_system/minimal_example.m b/projects/IMDD_base_system/minimal_example.m index 89f24ff..32e1ef8 100644 --- a/projects/IMDD_base_system/minimal_example.m +++ b/projects/IMDD_base_system/minimal_example.m @@ -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); diff --git a/projects/Lab_analysis/data_analysis_and_plot_scripts/lambda_vs_spectrum.m b/projects/Lab_analysis/data_analysis_and_plot_scripts/lambda_vs_spectrum.m new file mode 100644 index 0000000..c14d43d --- /dev/null +++ b/projects/Lab_analysis/data_analysis_and_plot_scripts/lambda_vs_spectrum.m @@ -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]') diff --git a/projects/WDM/WDM_auswertung.m b/projects/WDM/WDM_auswertung.m index 98b42b9..1435d1f 100644 --- a/projects/WDM/WDM_auswertung.m +++ b/projects/WDM/WDM_auswertung.m @@ -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_(?\d{8})_(?