+ duobinary_target now supports memoryless decoding (FFE targets DB response without MLSE) + PAMmapper.quantize now supports custom constellations for quantization + Added a new folder 'Documentations' for pdfs, slides, etc. + Added new FSO evaluation scripts in projects/FSO transmission/Evaluation Scripts + Added ffe_db (rudimentary module, not important anymore)
130 lines
4.4 KiB
Matlab
130 lines
4.4 KiB
Matlab
classdef Electrical_Hybrid < handle
|
|
|
|
properties(Access=public)
|
|
file_path
|
|
plot = 0
|
|
|
|
% If true: perform digital residual-echo cancellation using known TX
|
|
cancel_echo = 1
|
|
|
|
% If true: in addition return v_hyb and v_echo_est
|
|
return_intermediates = 1
|
|
end
|
|
|
|
methods(Access=public)
|
|
|
|
function obj = Electrical_Hybrid(options)
|
|
arguments
|
|
options.file_path = ''
|
|
options.plot = 0
|
|
options.cancel_echo = 1
|
|
options.return_intermediates = 1
|
|
end
|
|
|
|
fn = fieldnames(options);
|
|
for n = 1:numel(fn)
|
|
obj.(fn{n}) = options.(fn{n});
|
|
end
|
|
end
|
|
|
|
function [v_fe_rec, v_hyb, v_echo_est] = process(obj, v_ne_tx, v_fe_tx)
|
|
% v_ne_tx : Near-End TX signal object (Port 1)
|
|
% v_fe_tx : Far-End TX signal object (Port 2)
|
|
%
|
|
% Output:
|
|
% v_hyb : physical hybrid differential output (Port4 - Port3)
|
|
% v_echo_est : estimated residual echo due to local TX only
|
|
% v_fe_rec : v_hyb - v_echo_est (if cancel_echo enabled), else v_hyb
|
|
|
|
% --- Load S-Parameters (.s4p) ---
|
|
net = sparameters(obj.file_path);
|
|
f_s = net.Frequencies(:);
|
|
S4 = net.Parameters;
|
|
|
|
% Extract needed S-parameters for differential output:
|
|
% V3 = S31*V1 + S32*V2
|
|
% V4 = S41*V1 + S42*V2
|
|
% Vhyb = V4 - V3 = (S41-S31)*V1 + (S42-S32)*V2
|
|
S31_s = squeeze(S4(3,1,:));
|
|
S41_s = squeeze(S4(4,1,:));
|
|
S32_s = squeeze(S4(3,2,:));
|
|
S42_s = squeeze(S4(4,2,:));
|
|
|
|
% --- Time-domain signals ---
|
|
x1 = v_ne_tx.signal(:);
|
|
x2 = v_fe_tx.signal(:);
|
|
|
|
if length(x2) ~= length(x1)
|
|
error('Near-end and far-end signals must have the same length.');
|
|
end
|
|
|
|
N = length(x1);
|
|
Fs = v_ne_tx.fs;
|
|
|
|
% --- Use zero padding to avoid circular convolution artifacts ---
|
|
Nfft = 2^nextpow2(2*N); % robust choice
|
|
|
|
% --- FFT ---
|
|
V1 = fft(x1, Nfft);
|
|
V2 = fft(x2, Nfft);
|
|
|
|
% --- Frequency axis for interpolation (signed then abs) ---
|
|
f_fft = (0:Nfft-1).' * (Fs/Nfft);
|
|
f_signed = f_fft;
|
|
idxNeg = f_signed > Fs/2;
|
|
f_signed(idxNeg) = f_signed(idxNeg) - Fs; % (-Fs/2, Fs/2]
|
|
f_pos = abs(f_signed);
|
|
|
|
% --- Interpolate S-parameters onto f_pos ---
|
|
S31 = interp1(f_s, S31_s, f_pos, 'linear', 'extrap');
|
|
S41 = interp1(f_s, S41_s, f_pos, 'linear', 'extrap');
|
|
S32 = interp1(f_s, S32_s, f_pos, 'linear', 'extrap');
|
|
S42 = interp1(f_s, S42_s, f_pos, 'linear', 'extrap');
|
|
|
|
% Hermitian symmetry for real time-domain response:
|
|
% For negative frequencies enforce conj symmetry.
|
|
S31(idxNeg) = conj(S31(idxNeg));
|
|
S41(idxNeg) = conj(S41(idxNeg));
|
|
S32(idxNeg) = conj(S32(idxNeg));
|
|
S42(idxNeg) = conj(S42(idxNeg));
|
|
|
|
% --- Physical hybrid differential output ---
|
|
% Vhyb = (S41-S31)*V1 + (S42-S32)*V2
|
|
He = (S41 - S31); % residual echo transfer from local TX
|
|
Hr = (S42 - S32); % transfer from far-end TX to output
|
|
|
|
V_hyb = He .* V1 + Hr .* V2;
|
|
|
|
% --- Residual echo estimate (digital canceller model) ---
|
|
V_echo = He .* V1;
|
|
|
|
% --- Back to time-domain (take first N samples after padding) ---
|
|
v_hyb_full = ifft(V_hyb, 'symmetric');
|
|
v_echo_full = ifft(V_echo, 'symmetric');
|
|
|
|
v_hyb = v_hyb_full(1:N);
|
|
v_echo_est = v_echo_full(1:N);
|
|
|
|
% --- Optional cancellation ---
|
|
if obj.cancel_echo
|
|
v_fe_rec = v_hyb - v_echo_est;
|
|
else
|
|
v_fe_rec = v_hyb;
|
|
end
|
|
|
|
if ~obj.return_intermediates
|
|
v_hyb = [];
|
|
v_echo_est = [];
|
|
end
|
|
|
|
% --- Bring output in the correct form ---
|
|
v_fe_rec = Informationsignal(v_fe_rec,"fs",v_fe_tx.fs);
|
|
v_hyb = Informationsignal(v_hyb,"fs",v_fe_tx.fs);
|
|
v_echo_est = Informationsignal(v_echo_est,"fs",v_fe_tx.fs);
|
|
|
|
if obj.plot
|
|
rfplot(net)
|
|
end
|
|
end
|
|
end
|
|
end |