141 lines
5.9 KiB
Matlab
141 lines
5.9 KiB
Matlab
clear; clc;
|
|
|
|
M = 4;
|
|
randkey = 1;
|
|
duob_mode = db_mode.no_db;
|
|
|
|
mlse = 1;
|
|
dbtgt = 1;
|
|
|
|
link_lengths = 0:1:8; % [m] --- outer loop
|
|
rops = linspace(-10, 0, 12); % [dBm] --- inner sweep
|
|
FEC_thr = 3.8e-3; % BER target
|
|
baudrate = 200e9;
|
|
|
|
% --- allocate results
|
|
reqROP_FFE = nan(size(link_lengths));
|
|
reqROP_MLSE = nan(size(link_lengths));
|
|
reqROP_DBTGT = nan(size(link_lengths));
|
|
reqROP_ML_MLSE2 = nan(size(link_lengths));
|
|
reqROP_ML_MLSE3 = nan(size(link_lengths));
|
|
|
|
%% ====================== OUTER LOOP ======================
|
|
for L = 1:numel(link_lengths)
|
|
link_length_m = link_lengths(L);
|
|
fprintf('\n=== %.0f m fiber length ===\n', link_length_m);
|
|
|
|
ber_ffe = nan(size(rops));
|
|
ber_mlse = nan(size(rops));
|
|
ber_dbtgt = nan(size(rops));
|
|
ber_ml2 = nan(size(rops));
|
|
ber_ml3 = nan(size(rops));
|
|
|
|
%% -------- inner ROP loop --------
|
|
parfor i = 1:length(rops)
|
|
rop = rops(i);
|
|
|
|
[Rx_sig_2sps_v1, Symbols_v1, Tx_bits_v1] = standard_link_model( ...
|
|
"M",M,"fsym",baudrate,"rop",rop,"laser_wavelength",1290, ...
|
|
"link_length_km",link_length_m,"random_key",1);
|
|
|
|
Rx_sig_2sps_v1.spectrum("displayname",'Rx Sig','normalizeTo0dB',1);
|
|
|
|
%% FFE + MLSE
|
|
if mlse
|
|
pf_ncoeffs = 1;
|
|
ffe_order = [50, 0, 0];
|
|
mu_ffe = [0.0001, 0.0008, 0.001];
|
|
mu_dfe = 0.0004;
|
|
eq_ = EQ("Ne",ffe_order,"Nb",[0,0,0],"training_length",2^13, ...
|
|
"training_loops",5,"dd_loops",5,"K",2,"DCmu",0.005, ...
|
|
"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).levels,'scale_mode',2, ...
|
|
'trellis_exclusion',0,'trellis_state_mode',2,'debug',0, ...
|
|
'DIR',pf_.coefficients);
|
|
|
|
[ffe_results, mlse_results] = vnle_postfilter_mlse(eq_, pf_, mlse_, M, ...
|
|
Rx_sig_2sps_v1, Symbols_v1, Tx_bits_v1, ...
|
|
"precode_mode", duob_mode,'showAnalysis', 0, "postFFE", [], ...
|
|
"eth_style_symbol_mapping", 0);
|
|
|
|
ber_ffe(i) = ffe_results.metrics.BER;
|
|
ber_mlse(i) = mlse_results.metrics.BER;
|
|
end
|
|
|
|
%% FFE + duobinary target MLSE
|
|
if dbtgt
|
|
mlse_db_ = MLSE("DIR",[1,1],"duobinary_output",0,"M",M, ...
|
|
"trellis_states",PAMmapper(M,0).levels,'scale_mode',2, ...
|
|
'trellis_exclusion',0,'trellis_state_mode',3);
|
|
ffe_order = [50, 0, 0];
|
|
mu_ffe = [0.0001, 0.0008, 0.001];
|
|
mu_dfe = 0.0004;
|
|
eq_ = EQ("Ne",ffe_order,"Nb",[0,0,0],"training_length",2^13, ...
|
|
"training_loops",5,"dd_loops",5,"K",2,"DCmu",0.005, ...
|
|
"DDmu",[mu_ffe mu_dfe],"DFEmu",0.005,"FFEmu",0, ...
|
|
"plotfinal",0,"ideal_dfe",1);
|
|
|
|
dbt_results = duobinary_target(eq_, mlse_db_, M, Rx_sig_2sps_v1, ...
|
|
Symbols_v1, Tx_bits_v1, "precode_mode", duob_mode, ...
|
|
'showAnalysis', 0, "postFFE", []);
|
|
ber_dbtgt(i) = dbt_results.metrics.BER;
|
|
end
|
|
|
|
%% ML-based MLSE (L=2)
|
|
mu_ml = 0.1; training_epochs = 100;
|
|
ml_mlse_equalizer = ML_MLSE("epochs_tr",training_epochs,"epochs_dd",1, ...
|
|
"len_tr",2^16,"mu_dd",mu_ml,"mu_tr",mu_ml,"order",11,"sps",2, ...
|
|
"traceback_depth",128,"L",2,"delta",4,"adaptive_mu",0);
|
|
[y_ml_mlse,y_ref] = ml_mlse_equalizer.process(Rx_sig_2sps_v1,Symbols_v1);
|
|
ref_bits = PAMmapper(M,0).demap(y_ref);
|
|
ml_bits = PAMmapper(M,0).demap(y_ml_mlse);
|
|
[~,~,ber_ml2(i)] = calc_ber(ml_bits.signal, ref_bits.signal, ...
|
|
"skip_front",10,"skip_end",10);
|
|
|
|
%% ML-based MLSE (L=3)
|
|
ml_mlse_equalizer = ML_MLSE("epochs_tr",training_epochs,"epochs_dd",1, ...
|
|
"len_tr",2^16,"mu_dd",mu_ml,"mu_tr",mu_ml,"order",11,"sps",2, ...
|
|
"traceback_depth",128,"L",3,"delta",4,"adaptive_mu",0);
|
|
[y_ml_mlse,y_ref] = ml_mlse_equalizer.process(Rx_sig_2sps_v1,Symbols_v1);
|
|
ref_bits = PAMmapper(M,0).demap(y_ref);
|
|
ml_bits = PAMmapper(M,0).demap(y_ml_mlse);
|
|
[~,~,ber_ml3(i)] = calc_ber(ml_bits.signal, ref_bits.signal, ...
|
|
"skip_front",10,"skip_end",10);
|
|
end % ROP loop
|
|
|
|
%% --- find required ROP (FEC crossing)
|
|
reqROP_FFE(L) = interp_fec_cross(rops, ber_ffe, FEC_thr);
|
|
reqROP_MLSE(L) = interp_fec_cross(rops, ber_mlse, FEC_thr);
|
|
reqROP_DBTGT(L) = interp_fec_cross(rops, ber_dbtgt, FEC_thr);
|
|
reqROP_ML_MLSE2(L) = interp_fec_cross(rops, ber_ml2, FEC_thr);
|
|
reqROP_ML_MLSE3(L) = interp_fec_cross(rops, ber_ml3, FEC_thr);
|
|
|
|
fprintf('Length %.0f m: FFE %.1f, MLSE %.1f, DB %.1f, ML2 %.1f, ML3 %.1f\n', ...
|
|
link_length_m, reqROP_FFE(L), reqROP_MLSE(L), reqROP_DBTGT(L), ...
|
|
reqROP_ML_MLSE2(L), reqROP_ML_MLSE3(L));
|
|
end
|
|
|
|
%% ====================== PLOT REQUIRED ROP ======================
|
|
cols = cbrewer2('Set1',8);
|
|
colFFE = cols(1,:);
|
|
colMLSE = cols(2,:);
|
|
colDBTGT = cols(4,:);
|
|
colML_MLSE = cols(3,:);
|
|
|
|
figure(); hold on
|
|
plot(link_lengths, reqROP_FFE, '-o','Color',colFFE, 'DisplayName','FFE');
|
|
plot(link_lengths, reqROP_MLSE, '-s','Color',colMLSE, 'DisplayName','FFE+PF+MLSE');
|
|
plot(link_lengths, reqROP_DBTGT, '--^','Color',colDBTGT, 'DisplayName','DB tgt. MLSE');
|
|
plot(link_lengths, reqROP_ML_MLSE2, '-v','Color',colML_MLSE, 'DisplayName','ML-based MLSE (L=2)');
|
|
plot(link_lengths, reqROP_ML_MLSE3, '-d','Color',colML_MLSE*0.8,'DisplayName','ML-based MLSE (L=3)');
|
|
|
|
xlabel('Link length [km]');
|
|
ylabel('Required ROP [dBm]');
|
|
title(sprintf('Required ROP the reach FEC threshold (3.8e-3); %.0f GBd PAM-%d', baudrate.*1e-9, M));
|
|
legend('Location','northwest');
|
|
grid on;
|
|
beautifyBERplot("logscale",0,"polyfit",1,"polyorder",3,"fitmethod",'smoothingspline');
|