Zero forcing equalization plotting

39 views (last 30 days)
Tadeu Filho
Tadeu Filho on 14 Sep 2024
Edited: Pavl M. on 13 Oct 2024
Hello, I am working on this matlab script for my final paper and simulating the transmission of 1 pulse. First it gets shaped as a Raised Cossine pulse with a filter, then the transmitted Tx signal goes through a low-pass butterworth filter that acts like a channel introducing distortion to the pulse, then the received Rx signal comes to a Zero Forcing Equalizer filter that should correct the low-pass filter distortion.
The problem I'm facing is when I try to plot the pulse, here's the code:
clear;clf;clc;close all;
% This script performs a transmission of 1 pulse shaped with Raised Cossine
% that receives a distortion from a butterworth low-pass filter then
% the pulse gets an equalization from a Zero Forcing filter
% Building RC pulse shaping filter
rf = 0.5; % Roll-off factor
span = 16; % Pulse truncation factor
sps = 10; % Samples per pulse
p_rc = rcosdesign(rf,span,sps,"normal"); % Designing filter
p_rc_norm = p_rc/max(p_rc); % Normalizing
h_span = span/2; % Half symbol span
% Setting Data parameters
L = 1; % Total Data pulses
Rb = 1000; % Data rate in bps
% For Rb = 1000, that means that symbol time -> Tb = 1 milisecond
Fs = Rb * sps; % Sampling frequency
x = 1; % Data signal
% Note: Not starting at zero because of filter group delay
tx = 1000*(h_span:h_span)/Rb; % x Time vector sampled
% at symbol rate in milliseconds -> Data
% Applying RC filter
x_rc = upfirdn(x, p_rc_norm, sps); % Upsampling with upfirdn
% Note: By applying filtering, remember that the peak response of the
% filter gets delayed by the group delay of the filter, so we need to
% get rid of transients so that the pulses can be overlapping when plotting
trans_1 = sps*h_span; % Number of points for transient before peak operation
trans_2 = sps*(h_span-1); % Number of points for transient after peak operation
tx_rc = 1000*(0:L*sps+trans_1+trans_2)/Fs; % x_rc Time vector sampled at
% sampling frequency in milliseconds -> Tx signal
% Building and applying channel distortion via butterworth low-pass filter
Wn_butter = 0.1; % Normalized cutoff frequency
n_butter = 4; % Butterworth nth-order
[b_chan,a_chan] = butter(n_butter, Wn_butter); % Low-pass filter coefficients
x_rc_ch = filtfilt(b_chan,a_chan,x_rc); % Used filtfilt() so that it doesn't
% get any group delay when filtering
% Setting Zero Forcing Equalizer filter parameters
N2_plus_1 = 9; % Choose ZF EQ Filter Order = 2N+1 % Note: Odd number only
N2 = N2_plus_1 - 1;
% If ZF EQ Filter Order = 5, that means that N = 2, that also
% means that the matrix would be 5x5, because the row and column
% should be from Pr[0] to Pr[2N] = Pr[4] and from Pr[0] to Pr[-2N]= Pr[-4]
% Building and applying ZFE filter
zf_kTb_peak = max(x_rc_ch); % Identify pulse peak
zf_kTb_peak_pos = find(x_rc_ch==zf_kTb_peak); % Identify pulse peak position
Pr_minus_N2 = zf_kTb_peak_pos-(sps*N2); % Range points to feed the ZF equalizer: Pr[0] to Pr[-2N]
Pr_plus_N2 = zf_kTb_peak_pos+(sps*N2); % Range points to feed the ZF equalizer: Pr[0] to Pr[2N]
zf_kTb = x_rc_ch(Pr_minus_N2:sps:Pr_plus_N2); % Scrolling Rx signal
% to get kTb points (integer multiples"k" of symbol time"Tb")
zf_kTb = zf_kTb';
zf_Pr_row = zf_kTb(1:round(length(zf_kTb)/2));
zf_Pr_row = zf_Pr_row(end:-1:1); % Getting Pr[0] to Pr[-2N] vector
zf_Pr_col = zf_kTb(round(length(zf_kTb)/2):end); % Getting Pr[0] to Pr[2N] vector
Pr = toeplitz(zf_Pr_col, zf_Pr_row); % With kTb points we can build Toeplitz Matrix
Po = zeros(round(length(zf_kTb)/2), 1); % Creating Po vector to force neighbour pulses to 0
Po(round(length(Po)/2)) = 1;
Ck_zf = inv(Pr)*Po; % Calculating ZFE filter coefficients
% Applying ZFE filter to Rx kTb points:
zf_kTb_ZFE = conv(zf_kTb, Ck_zf, 'same');
% Plot 1
figure(1)
stem(zf_kTb, 'color', [0.8500 0.3250 0.0980]);
hold on
stem(zf_kTb_ZFE, 'color', [0.9290 0.6940 0.1250]);
hold off;
xlabel('Symbol spaced points (kTb)'); ylabel('Magnitude');
legend('Rx points','ZFE points','Location','southeast');
% Applying ZFE filter to Rx signal
x_rc_ch_zf = conv(x_rc_ch, Ck_zf, 'same');
% Plot 2
figure(2)
stem(tx, x, 'k');
hold on;
plot(tx_rc, x_rc, 'color', [0 0.4470 0.7410]);
plot(tx_rc, x_rc_ch, 'color', [0.8500 0.3250 0.0980]);
plot(tx_rc, x_rc_ch_zf, 'color', [0.9290 0.6940 0.1250]);
hold off;
xlabel('Time (ms)'); ylabel('Magnitude');
legend('Data','Tx Signal','Rx Signal','ZFE Signal','Location','southeast');
For the first figure, the equalyzer is working like it should, it is forcing the symbol spaced points(kTb) to zero.
But for the second figure, when the whole discretized pulse from the Rx signal goes through the same ZFE filter, it doesn't get equalyzed back to something like the Tx signal, it just gets a little bit bigger on the peak.
So my doubt is, can we equalyze the Rx pulse with this type of equalization and plot the equalized pulse to something close to Tx signal ?Or does it just works for the points of symbol time ?

Answers (1)

Pavl M.
Pavl M. on 13 Oct 2024
Edited: Pavl M. on 13 Oct 2024

In order it will sound reasonable and Signal Processing domain logically correct,

you need your Zero Forcing Equalizer filter or generally calling it academically correctly : channel adjustment filter to catch the channel properties (to estimate channel parameters) and to be as close as possible to the channel transfer function. Please review your paper logic. In your specific case the ZFE(z) = 1/channel_tf(z);
[b_chan,a_chan] = butter(n_butter, Wn_butter)

The magic is in scrolling:
zf_kTb = x_rc_ch(Pr_minus_N2:sps:Pr_plus_N2); % Scrolling Rx signal

I found correction to your observations:

You wrote:
"But for the second figure, when the whole discretized pulse from the Rx signal goes through the same ZFE filter, it doesn't get equalyzed back to something like the Tx signal, it just gets a little bit bigger on the peak."
in fact if you mean x_rc_ch_zf, it becomes expanded (spreads, broadens, bolsters) in time domain.

For it you need to modify Ck_zf which you convolve with.

So in frequency domain we need to correct / narrow(shrink, de-broad) it
fck = fft(Ck_zf)
n1 = length(fck);
v = (0:1:n1-1);
Narrow_factor = some_function(span,sps,filter_design);
Ck_zf_s_narrowed = ifft(fck'.*narrow_factor,'symmetric');
x_rc_ch_zf = conv(x_rc_ch, Ck_zf_s_narrowed, 'same');

Or even more elegant solution is to better modify the parameters when you desgin your filter initially and then you will not need to make computation fft and ifft operations:

Where you design the filter:

zf_kTb = x_rc_ch(Pr_minus_N2:sps:Pr_plus_N2); % Scrolling Rx signal
% to get kTb points (integer multiples"k" of symbol time"Tb")
zf_kTb = zf_kTb';
zf_Pr_row = zf_kTb(1:round(length(zf_kTb)/2));
zf_Pr_row = zf_Pr_row(end:-1:1); % Getting Pr[0] to Pr[-2N] vector
zf_Pr_col = zf_kTb(round(length(zf_kTb)/2):end); % Getting Pr[0] to Pr[2N] vector
Pr = toeplitz(zf_Pr_col, zf_Pr_row); % With kTb points we can build Toeplitz Matrix
Po = zeros(round(length(zf_kTb)/2), 1); % Creating Po vector to force neighbour pulses to 0
Po(round(length(Po)/2)) = 1;
Ck_zf = inv(Pr)*Po; % Calculating ZFE filter coefficients
More signal processing analysis I can do if you hire me
It is a part of some larger digital communication system, which?

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!