M = 4; order = 18; randkey = 1; % bitpattern = []; % s = RandStream('twister','Seed',randkey); % for i = 1:log2(M) % N = 2^(order-1); %length of prbs % bitpattern(:,i) = randi(s,[0 1], N, 1); % end % % if M == 6 % bitpattern = reshape(bitpattern',[],1); % bitpattern = bitpattern(1:end-mod(length(bitpattern),5)); % end % % Bits = Informationsignal(bitpattern); Bits = Signalgenerator( ... "form", signalform.prms, ... "M", M, ... "order", order).process(); Symbols = PAMmapper(M,0).map(Bits); Symbols.fs = 200e9; Bits_ = PAMmapper(M, 0, "eth_style", 0).demap(Symbols); % --- Channel: minimal ISI response + AWGN --- h = [0.3 0.9 0.3,0.1]; % impulse response (normalized later if desired) h = h / norm(h); % optional normalization for unit energy symbols_filt = Symbols.filter(h,1); %% SHOW FIG 3 in Paper: "ML Base Pre-Eq" SNR_dB = [15:2:25]; ber_ffe = zeros(size(SNR_dB)); ber_mlse_l5 = zeros(size(SNR_dB)); ber_nwf_mlse_l2 = zeros(size(SNR_dB)); ber_ml_mlse_l2 = zeros(size(SNR_dB)); ber_ml_mlse_l3 = zeros(size(SNR_dB)); ber_ml_mlse_l4 = zeros(size(SNR_dB)); epochs_training = 100; parfor i = 1:numel(SNR_dB) symbols_noi = symbols_filt; symbols_noi.signal = awgn(symbols_filt.signal, SNR_dB(i), 'measured'); % AWGN with given SNR % Sequence Est L=5 mlse_ = MLSE("duobinary_output",0,'M',M,'trellis_states',PAMmapper(M,0).levels,'scale_mode',0,'trellis_exclusion',0,'trellis_state_mode',2,'debug',0,'DIR',h); mlse_.DIR = h; [y_mlse] = mlse_.process(symbols_noi,Symbols); mlse_bits = PAMmapper(M, 0, "eth_style", 0).demap(y_mlse); [~, ~, ber_mlse_l5(i), ~] = calc_ber(mlse_bits.signal, Bits.signal, "skip_front", 10, "skip_end", 10, "returnErrorLocation", 1); fprintf('MLSE L5: %.2e \n',ber_mlse_l5(i)); % 2nd Approach mu_lms = 0.0005; pf_ncoeffs = 1; eq_ = FFE("epochs_tr",5,"epochs_dd",5,"len_tr",2^13,"mu_dd",mu_lms,"mu_tr",mu_lms,"order",16,"sps",1,"dd_mode",1,"adaption_technique","lms"); pf_ = Postfilter("ncoeff",pf_ncoeffs,"useBurg",1); % FFE [y_ffe, ffe_noise] = eq_.process(symbols_noi, Symbols); Eq_bits = PAMmapper(M, 0, "eth_style", 0).demap(y_ffe); [~, ~, ber_ffe(i), ~] = calc_ber(Eq_bits.signal, Bits.signal, "skip_front", 0, "skip_end", 0, "returnErrorLocation", 1); fprintf('FFE: %.2e \n',ber_ffe(i)); % Postfilter [y_white,~] = pf_.process(y_ffe, ffe_noise); % Sequence Est mlse_ = MLSE("duobinary_output",0,'M',M,'trellis_states',PAMmapper(M,0).levels,'scale_mode',0,'trellis_exclusion',0,'trellis_state_mode',2,'debug',0,'DIR',pf_.coefficients); [y_mlse] = mlse_.process(y_white,Symbols); mlse_bits = PAMmapper(M, 0, "eth_style", 0).demap(y_mlse); [~, errors, ber_nwf_mlse_l2(i), errpos] = calc_ber(mlse_bits.signal, Bits.signal, "skip_front", 10, "skip_end", 10, "returnErrorLocation", 1); fprintf('MLSE: %.2e \n',ber_nwf_mlse_l2(i)); % ML-base MLSE L=2 adaptive_mu = 0; mu_lms = 0.15; ml_mlse_equalizer = ML_MLSE("epochs_tr",epochs_training,"epochs_dd",1,"len_tr",2^15,... "mu_dd",mu_lms,"mu_tr",mu_lms,"order",11,"sps",1,... "traceback_depth",128,"L",2,"delta",4,"adaptive_mu",adaptive_mu); [y_ml_mlse,~] = ml_mlse_equalizer.process(symbols_noi,Symbols); ml_mlse_bits = PAMmapper(M, 0, "eth_style", 0).demap(y_ml_mlse); [~, errors, ber_ml_mlse_l2(i), errpos] = calc_ber(ml_mlse_bits.signal, Bits.signal, "skip_front", 10, "skip_end", 10, "returnErrorLocation", 1); fprintf('ML MLSE BER: %.2e \n',ber_ml_mlse_l2(i)); % ML-base MLSE L=3 mu_lms = 0.15; ml_mlse_equalizer = ML_MLSE("epochs_tr",epochs_training,"epochs_dd",1,"len_tr",2^16,... "mu_dd",mu_lms,"mu_tr",mu_lms,"order",11,"sps",1,... "traceback_depth",128,"L",3,"delta",4,"adaptive_mu",adaptive_mu); [y_ml_mlse,~] = ml_mlse_equalizer.process(symbols_noi,Symbols); ml_mlse_bits = PAMmapper(M, 0, "eth_style", 0).demap(y_ml_mlse); [~, errors, ber_ml_mlse_l3(i), errpos] = calc_ber(ml_mlse_bits.signal, Bits.signal, "skip_front", 10, "skip_end", 10, "returnErrorLocation", 1); fprintf('ML MLSE BER: %.2e \n',ber_ml_mlse_l3(i)); % % ML-base MLSE L=5 % mu_lms = 0.15; % ml_mlse_equalizer = ML_MLSE("epochs_tr",epochs_training,"epochs_dd",1,"len_tr",2^15,... % "mu_dd",mu_lms,"mu_tr",mu_lms,"order",11,"sps",1,... % "traceback_depth",128,"L",5,"delta",4); % [y_ml_mlse,~] = ml_mlse_equalizer.process(symbols_noi,Symbols); % ml_mlse_bits = PAMmapper(M, 0, "eth_style", 0).demap(y_ml_mlse); % [~, errors, ber_ml_mlse_l5(i), errpos] = calc_ber(ml_mlse_bits.signal, Bits.signal, "skip_front", 10, "skip_end", 10, "returnErrorLocation", 1); % fprintf('ML MLSE BER: %.2e \n',ber_ml_mlse_l5(i)); end %% figure(); hold on; % --- define scheme colors (consistent palette) cols = cbrewer2('SET1',8); colFFE = cols(1,:); % blue colMLSE = cols(2,:); % orange colML_MLSE = cols(3,:); % green colNWF_MLSE = cols(4,:); % purple % --- local simulation results plot(SNR_dB, ber_ffe, '-o', 'Color', colFFE, 'DisplayName','FFE (N=16)'); if M==2, plot(FFE_wpd.X, FFE_wpd.Y, ':', 'LineWidth',1.5, 'Color', colFFE, 'DisplayName','Paper FFE'); end plot(SNR_dB, ber_mlse_l5, '-s', 'Color', colMLSE, 'DisplayName','MLSE (L=5)'); if M==2, plot(MLSE_wpd.X, MLSE_wpd.Y, ':', 'LineWidth',1.5, 'Color', colMLSE, 'DisplayName','Paper MLSE L=5'); end plot(SNR_dB, ber_nwf_mlse_l2,'--^','Color', colNWF_MLSE, 'DisplayName','FFE+PF+MLSE (L=2)'); plot(SNR_dB, ber_ml_mlse_l2, '-v', 'Color', colML_MLSE, 'DisplayName','ML-based MLSE (L=2)'); if M==2, plot(ML_MLSE_L_2_wpd.X,ML_MLSE_L_2_wpd.Y,':', 'LineWidth',1.5, 'Color', colML_MLSE, 'DisplayName','Paper ML-based MLSE L=2'); end plot(SNR_dB, ber_ml_mlse_l3, '-d', 'Color', colML_MLSE, 'DisplayName','ML-based MLSE (L=3)'); if M==2, plot(SNR_dB, ber_ml_mlse_l5, '-p', 'Color', colML_MLSE, 'DisplayName','ML-based MLSE (L=5)'); end if M==2, plot(ML_MLSE_L_5_wpd.X,ML_MLSE_L_5_wpd.Y,':', 'LineWidth',1.5, 'Color', colML_MLSE, 'DisplayName','Paper ML-based MLSE L=5'); end % --- imported WebPlotDigitizer data (dotted) yline(3.8e-3,'HandleVisibility','off'); yline(2.2e-4,'HandleVisibility','off'); % --- formatting beautifyBERplot; xlim([SNR_dB(1), SNR_dB(end)]); ylim([1e-5 0.1]); xlabel('Input SNR [dB]'); ylabel('Bit Error Rate (BER)'); title('PAM-4; M=4; AWGN Channel'); legend('Location','southwest'); grid on;