147 lines
6.0 KiB
Matlab
147 lines
6.0 KiB
Matlab
function [eq_package] = 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
|
|
|
|
% 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)
|
|
|
|
% takes:
|
|
% -> eq_signal_hd: hard decision signal after eq
|
|
% -> tx_symbols: that where used as reference for eq
|
|
|
|
switch options.precode_mode
|
|
case db_mode.db_emulate
|
|
|
|
mlse_sig_hd = Duobinary().encode(mlse_sig_hd,"M",M);
|
|
mlse_sig_hd = Duobinary().decode(mlse_sig_hd,"M",M);
|
|
|
|
tx_symbols_precoded = Duobinary().encode(tx_symbols);
|
|
tx_symbols_precoded = Duobinary().decode(tx_symbols_precoded);
|
|
|
|
tx_bits = PAMmapper(M,0,"eth_style",options.eth_style_symbol_mapping).demap(tx_symbols_precoded);
|
|
|
|
case db_mode.db_discard
|
|
|
|
% normal dsp for precoded sequence == discard/omit/ignore precode
|
|
tx_bits = PAMmapper(M,0,"eth_style",options.eth_style_symbol_mapping).demap(tx_symbols);
|
|
|
|
case db_mode.db_encoded
|
|
|
|
% normal DB encoded data (only for 10KM)
|
|
|
|
case db_mode.db_precoded
|
|
|
|
mlse_sig_hd = Duobinary().encode(mlse_sig_hd,"M",M);
|
|
mlse_sig_hd = Duobinary().decode(mlse_sig_hd,"M",M);
|
|
|
|
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);
|
|
eq_package.ber = ber_db;
|
|
|
|
resultsDBtgt = struct( ...
|
|
'result_id', NaN, ... %
|
|
'run_id', NaN, ... % Beispielhafte Run-ID
|
|
'eqParam_id', NaN, ... % Beispielhafter Fremdschlüssel zur EqualizerParameters-Tabelle
|
|
'date_of_processing', datetime('now'), ... % Aktuelles Datum und Uhrzeit
|
|
'numBits', bits_db, ... % Beispiel: 1.000.000 Bits
|
|
'numBitErr', errors_db, ... % Beispiel: 120 Bitfehler
|
|
'BER', ber_db, ... % BER = 120 / 1.000.000
|
|
'SNR', [], ... % Beispielhafte SNR
|
|
'SNR_level', jsonencode([]), ... % SNR-Level als JSON-codiertes Array
|
|
'GMI', [], ... % Beispielhafter GMI-Wert
|
|
'AIR', [], ... % Beispielhafter AIR-Wert
|
|
'EVM', [], ... % Beispielhafte EVM
|
|
'EVM_level', jsonencode([]), ... % EVM-Level als JSON-codiertes Array
|
|
'Alpha', [] ... % Beispielhafter Alpha-Wert
|
|
);
|
|
|
|
if ~isempty(options.postFFE)
|
|
npostFFE = options.postFFE.order;
|
|
else
|
|
npostFFE = 0;
|
|
end
|
|
|
|
equalizerConfigDBtgt = struct( ...
|
|
'eq_id', NaN, ... % Auto-Inkrement, wird in der DB gesetzt
|
|
'equalizer_structure', int32(equalizer_structure.vnle_db_mlse), ... % Beispiel: 1 (z.B. für vnle)
|
|
'M', M, ... % Ordnung der PAM-Konstellation
|
|
'target_constellation', jsonencode(round(db_ref_constellation,5)), ... % Beispielhafter Target-String
|
|
'db_target', 1, ... % 0 oder 1
|
|
'diff_precode', int32(options.precode_mode), ... % 0 oder 1
|
|
'postFFE', ~isempty(options.postFFE), ... % Beispielwert
|
|
'NpostFFE', npostFFE, ... % Beispielwert
|
|
'Ne1', eq_.Ne(1), ... % Feedforward Koeffizienten 1. Ordnung
|
|
'Ne2', eq_.Ne(2), ... % Feedforward Koeffizienten 2. Ordnung
|
|
'Ne3', eq_.Ne(3), ... % Feedforward Koeffizienten 3. Ordnung
|
|
'Nb1', eq_.Nb(1), ... % Decision Feedback Koeffizienten 1. Ordnung
|
|
'Nb2', eq_.Nb(2), ... % Decision Feedback Koeffizienten 2. Ordnung
|
|
'Nb3', eq_.Nb(3), ... % Decision Feedback Koeffizienten 3. Ordnung
|
|
'K', eq_.K, ... % Samples pro Symbol
|
|
'DCmu', eq_.DCmu, ... % Anpassungsrate für DC-Tap
|
|
'ideal_dfe', eq_.ideal_dfe, ... % Flag für ideal DFE (0 oder 1)
|
|
'training_length', eq_.training_length, ... % Anzahl Trainingssymbole
|
|
'training_loops', eq_.training_loops, ... % Anzahl Trainingsdurchläufe
|
|
'TRmu1', eq_.FFEmu, ... % mu für DD-Modus (1. Ordnung)
|
|
'TRmu2', eq_.FFEmu, ... % mu für DD-Modus (2. Ordnung)
|
|
'TRmu3', eq_.FFEmu, ... % mu für DD-Modus (3. Ordnung)
|
|
'TRmuDFE', eq_.DFEmu, ... % mu für DFE-Modus im DD
|
|
'dd_loops', 5, ... % Anzahl Durchläufe im DD-Modus
|
|
'DDmu1', eq_.DDmu(1), ... % mu für DD-Modus (1. Ordnung)
|
|
'DDmu2', eq_.DDmu(2), ... % mu für DD-Modus (2. Ordnung)
|
|
'DDmu3', eq_.DDmu(3), ... % mu für DD-Modus (3. Ordnung)
|
|
'DDmuDFE', eq_.DDmu(4), ... % mu für DFE-Modus im DD
|
|
'MLSE_mode', 'viterbi', ... % Beispiel: MLSE-Modus als String
|
|
'MLSE_trellis_states', jsonencode(mlse_.trellis_states), ... % Trellis-States, z.B. als JSON-String oder kommasepariert
|
|
'comment', 'function: duobinary_target.m', ... % Zusätzliche Kommentare
|
|
'config_hash', NaN ...
|
|
);
|
|
|
|
eq_package.resultsDBtgt = resultsDBtgt;
|
|
eq_package.equalizerConfigDBtgt = equalizerConfigDBtgt;
|
|
|
|
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 |