function [db_results] = duobinary_target(eq_, mlse_,M, rx_signal, tx_symbols, tx_bits, options) arguments eq_ mlse_ M rx_signal tx_symbols tx_bits options.precode_mode db_mode options.showAnalysis = 0; options.eth_style_symbol_mapping = 0; options.postFFE = []; end %Duobinary Targeting db_ref_sequence = Duobinary().encode(tx_symbols); db_ref_constellation = unique(db_ref_sequence.signal); [eq_signal, eq_noise] = eq_.process(rx_signal,db_ref_sequence); if ~isempty(options.postFFE) [eq_signal,eq_noise] = options.postFFE.process(eq_signal,db_ref_sequence); end mlse_.DIR = [1,1]; mlse_sig_sd = mlse_.process(eq_signal); mlse_sig_hd = PAMmapper(M,0,"eth_style",options.eth_style_symbol_mapping).quantize(mlse_sig_sd); % precoding to mitigate error propagation, most prominently used in % combination with duobinary signaling to avoid catastrophic error % behavior (see J.W.M. Bergmans, Digital Baseband Transmission and Recording -> partial response signaling) switch options.precode_mode case db_mode.no_db % TX Data is not precoded: % A) Emulate diff precoding mlse_sig_hd_precoded = Duobinary().encode(mlse_sig_hd,"M",M); mlse_sig_hd_precoded = Duobinary().decode(mlse_sig_hd_precoded,"M",M); tx_symbols_precoded = Duobinary().encode(tx_symbols); tx_symbols_precoded = Duobinary().decode(tx_symbols_precoded); tx_bits_precoded = PAMmapper(M,0,"eth_style",options.eth_style_symbol_mapping).demap(tx_symbols_precoded); rx_bits_mlse = PAMmapper(M,0,"eth_style",options.eth_style_symbol_mapping).demap(mlse_sig_hd_precoded); [~,errors_db_diff_precoded,ber_db_diff_precoded,~] = calc_ber(rx_bits_mlse.signal,tx_bits_precoded.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1); %B) Just determine BER rx_bits_mlse = PAMmapper(M,0,"eth_style",options.eth_style_symbol_mapping).demap(mlse_sig_hd); [bits_mlse,errors_mlse,ber_db,~] = calc_ber(rx_bits_mlse.signal,tx_bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1); case db_mode.db_precoded % Daten SIND TATSÄCHLICH precoded auf TX Seite: % A) Decode at Rx if no DB targeting was applied (we are in VNLE or MLSE EQ structure here! mlse_sig_hd_decoded = Duobinary().encode(mlse_sig_hd,"M",M); mlse_sig_hd_decoded = Duobinary().decode(mlse_sig_hd_decoded,"M",M); rx_bits_mlse_decoded = PAMmapper(M,0,"eth_style",options.eth_style_symbol_mapping).demap(mlse_sig_hd_decoded); [~,errors_db_diff_precoded,ber_db_diff_precoded,~] = calc_ber(rx_bits_mlse_decoded.signal,tx_bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1); % B) Omit the Coding by comparing with demapped TX symbol sequence tx_bits = PAMmapper(M,0,"eth_style",options.eth_style_symbol_mapping).demap(tx_symbols); rx_bits_mlse = PAMmapper(M,0,"eth_style",options.eth_style_symbol_mapping).demap(mlse_sig_hd); [bits_db,errors_db,ber_db,~] = calc_ber(rx_bits_mlse.signal,tx_bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1); end % M = numel(unique(tx_symbols.signal)); rx_bits = PAMmapper(M,0,"eth_style",options.eth_style_symbol_mapping).demap(mlse_sig_hd); [bits_db,errors_db,ber_db,errorIndice_db] = calc_ber(rx_bits.signal,tx_bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1); db_results = struct(); db_results.metrics = Metricstruct; db_results.metrics.result_id = NaN; db_results.metrics.run_id = NaN; db_results.metrics.eqParam_id = NaN; db_results.metrics.date_of_processing = datetime('now'); db_results.metrics.BER = ber_db; db_results.metrics.numBits = bits_db; db_results.metrics.numBitErr = errors_db; db_results.metrics.BER_precoded = ber_db_diff_precoded; db_results.metrics.numBitErr_precoded = errors_db_diff_precoded; db_results.metrics.SNR = NaN; db_results.metrics.SNR_level = NaN; db_results.metrics.GMI = NaN; db_results.metrics.AIR = NaN; db_results.metrics.EVM = NaN; db_results.metrics.EVM_level = NaN; db_results.metrics.MLSE_dir = mlse_.DIR; % Create DB results structure db_results.config = Equalizerstruct(); eq_.e = []; eq_.e2 = []; eq_.e3 = []; db_results.config.eq = jsonencode(eq_); mlse_.DIR = []; db_results.config.mlse = jsonencode(mlse_); db_results.config.equalizer_structure = int32(equalizer_structure.vnle_db_mlse); db_results.config.comment = 'function: Duobinary tgt. (VNLE -> MLSE)'; if options.showAnalysis eq_noise = eq_noise - mean(eq_noise.signal); rx_signal.spectrum("normalizeTo0dB",1,"fignum",250,"displayname","Rx Spectrum"); Duobinary().encode(tx_symbols).spectrum("normalizeTo0dB",1,"fignum",250,"displayname","DB encoded reference"); showEQNoisePSD(eq_noise,"fignum",250,"displayname",'Duobinary Target Noise after Equalization'); fprintf('DB tgt BER: %.2e \n',ber); end end