Files
imdd_silas/Functions/EQ_structures/duobinary_signaling.m
Silas Oettinghaus 0080cb2264 ML Equalizer works now.
Not yet perfectly integrated into all the routines
2025-11-12 09:24:02 +01:00

131 lines
4.1 KiB
Matlab

function [db_results] = duobinary_signaling(eq_, mlse_, M, rx_signal, tx_symbols, tx_bits, options)
% DUOBINARY_SIGNALING Processes signals through duobinary signaling
%
% Inputs:
% eq_ - Equalizer object
% mlse_ - MLSE object
% M - Modulation order
% rx_signal - Received signal
% tx_symbols - Transmitted symbols
% tx_bits - Transmitted bits
% options - Optional parameters
%
% Outputs:
% db_results - Results from duobinary signaling processing
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 = []
options.database = []
end
%% Process signals through equalizer
[eq_signal, eq_noise] = eq_.process(rx_signal, tx_symbols);
% Apply post-FFE if provided
if ~isempty(options.postFFE)
[eq_signal, eq_noise] = options.postFFE.process(eq_signal, tx_symbols);
end
% Process through MLSE
[mlse_signal] = mlse_.process(eq_signal);
% tx_symbols_ = Duobinary().decode(tx_symbols);
% [mlse_signal,~,GMI_MLSE] = mlse_.process(eq_signal,tx_symbols);
% Apply duobinary encoding and decoding
mlse_signal = Duobinary().encode(mlse_signal);
mlse_signal = Duobinary().decode(mlse_signal);
% Demap symbols to bits
rx_bits = PAMmapper(M, 0, "eth_style", options.eth_style_symbol_mapping).demap(mlse_signal);
%% Calculate BER and metrics
[bits_db, errors_db, ber_db, error_pos] = calc_ber(rx_bits.signal, tx_bits.signal, "skip_front", 100, "skip_end", 150, "returnErrorLocation", 1);
% Calculate performance metrics after duobinary FFE!
[snr, snr_lvl] = calc_snr(tx_symbols.signal, eq_noise.signal); %SNR of duobinary sequence - not directly comparable to
[gmi] = calc_air(eq_signal, tx_symbols, "skip_front", 10000, "skip_end", 10000);
air = tx_symbols.fs .* floor(log2(double(M))*10)/10 .* gmi ./ log2(double(M));
[evm_total, evm_lvl] = calc_evm(eq_signal, tx_symbols);
[std_total, std_lvl] = calc_std(eq_signal, tx_symbols);
[std_rxraw_total, std_rxraw_lvl] = calc_std(rx_signal.resample("fs_out", tx_symbols.fs), tx_symbols);
%% Prepare output structure
% Determine postFFE order
if ~isempty(options.postFFE)
npostFFE = options.postFFE.order;
else
npostFFE = 0;
end
% Create results structure
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.SNR = snr;
db_results.metrics.SNR_level = snr_lvl;
db_results.metrics.STD = std_total;
db_results.metrics.STD_level = std_lvl;
db_results.metrics.STDrx = std_rxraw_total;
db_results.metrics.STDrx_level = std_rxraw_lvl;
db_results.metrics.GMI = gmi;
db_results.metrics.AIR = air;
db_results.metrics.EVM = evm_total;
db_results.metrics.EVM_level = evm_lvl;
db_results.metrics.MLSE_dir = mlse_.DIR;
% Create configuration structure
eq_.e = [];
eq_.e2 = [];
eq_.e3 = [];
db_results.config = Equalizerstruct();
db_results.config.eq = jsonencode(eq_);
mlse_.DIR = [];
db_results.config.mlse = jsonencode(mlse_);
db_results.config.equalizer_structure = int32(equalizer_structure.db_encoded);
db_results.config.comment = 'function: duobinary_signaling';
%% Display analysis if requested
if options.showAnalysis
displayAnalysis(eq_noise, eq_signal, rx_signal, eq_, tx_symbols, M, options.postFFE);
end
end
%% Helper Function
function displayAnalysis(eq_noise, eq_signal, rx_signal, eq_, tx_symbols, M, postFFE)
% Display analysis plots and metrics
figure(336);
showEQNoisePSD(eq_noise, "fignum", 336, "displayname", 'Residual Noise after Duobinary');
if ~isempty(postFFE)
showEQcoefficients('n1', postFFE.e, "displayname", 'Coefficients', 'fignum', 338);
end
showEQfilter(eq_.e, eq_signal.fs.*2);
figure(341); clf;
showLevelHistogram(eq_signal, tx_symbols, "fignum", 341);
warning off
figure(400); clf;
showLevelScatter(eq_signal, tx_symbols, "fignum", 400);
figure(401); clf;
showLevelScatter(rx_signal.resample("fs_out", tx_symbols.fs), tx_symbols, "fignum", 401);
warning on
end