1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
|
function TapWeights = adaptFFE(waveIn,SamplesPerSymbol,SampleInterval,cmx,cpx,bmax)
%ADAPTFFE Adapt FFE taps based on an input impulse response
% Adapt FFE taps such that the convolution of FFE taps and pulse response
% results in minimum ISI in the root-mean squared sense.
% Determines the required FFE tap weights needed to cancel out ISI at the
% the UI sample points. Function is DFE aware, where it will NOT zero force
% 1st post-cursor ISI if a DFE is present. The resulting FFE will have
% cmx + 1 + cpx taps.
% Inputs:
% waveIn - Input impulse response to be equalized by the Rx FFE
% SamplesPerSymbol - the number of samples per each symbol UI used for waveIn
% SampleInterval - the simulation time step size
% cmx - number of pre-cursor FFE taps
% cpx - number of post-cursor FFE taps
% bmax - the maximum value of 1-tap DFE that follows FFE, if DFE isn't present
% then this should be set to zero
% Output:
% TapWeights - Adapted tap weights
%
% The required FFE taps are calculated as follows
% 1. To make the adaptation somewhat CDR implementation independent, the peak
% input pulse amplitude is assumed to be the UI center sampling point.
% 2. The input pulse response is sampled, once per UI, relative to the
% determined sampling point.
% 3. A circularly shifted matrix (VV) is constructed based on the sampled input
% pulse response. It is then trimmed such that the top first row starts at
% the cursor. This implmentation follows COM script implementation.
% 4. The target pulse response vector (FV) is constructed. This vector is an
% all zero matrix, other than at the cursor position (cmx+1), where the
% current cursor value is used.
% 5. If bmax is non-zero, then the target for the 1st post-cursor is set to the
% minimum of the current post-cursor value or bmax scaled by the cursor
% amplitude.
% 6. The tap weights are calcuated as the pseudo inverse of the VV matrix
% multiplied by the desired pulse target (FV).
% Copyright 2020 The MathWorks, Inc.
%Validate inputs
validateattributes(waveIn,{'numeric'},{'vector','finite'},'adaptFFE','waveIn',1);
validateattributes(SamplesPerSymbol,{'numeric'},...
{'scalar','finite','integer','positive'},...
'adaptFFE','SamplesPerSymbol',2);
validateattributes(SampleInterval,{'numeric'},...
{'scalar','finite','positive','real'},...
'adaptFFE','SampleInterval',3);
validateattributes(cmx,{'numeric'},...
{'scalar','finite','integer','nonnegative'},...
'adaptFFE','cmx',4);
validateattributes(cpx,{'numeric'},...
{'scalar','finite','integer','nonnegative'},...
'adaptFFE','cpx',5);
% Calculate pulse response
pulseIn = impulse2pulse(waveIn(:), SamplesPerSymbol, SampleInterval);
% Peak amplitude phase detection
[~, pulseMaxPt] = max(pulseIn);
% Sampling phase
samplePhase = mod(pulseMaxPt - 1, SamplesPerSymbol) + 1;
% Re-sample the pulse at UI centers
sampledPulseIn = pulseIn(samplePhase:SamplesPerSymbol:end);
% Construct the adaptation matrix: shifted versions of the sampled waveform
VV = convmtx(sampledPulseIn, cmx+cpx+1)';
% Find cursor in the sampled waveform
[sampledPulseMax, sampledPulseMaxPt] = max(sampledPulseIn);
% Trim the adaptation matrix to include pre- to post-cursor range
VV = VV(:, sampledPulseMaxPt : sampledPulseMaxPt + cmx + cpx);
% Construct adaptation target pulse, FV
FV = zeros(1, cmx + 1 + cpx);
FV(cmx + 1) = sampledPulseMax;
% Adjust adaptation target pulse: DFE takes precedence for 1st post-cursor
if (bmax > 0) && (cpx > 0)
FV(cmx+2) = min(bmax * sampledPulseMax, sampledPulseIn(sampledPulseMaxPt + 1));
end
% Calculate FFE tap weights: pseudo inverse of the adaptation matrix
[i_m, i_n] = size(VV);
I_VV = eye(i_m, i_n);
lambda = 0;
C = ((VV' * VV + lambda*I_VV)^-1 * VV')' * FV';
% Assign output
TapWeights = C';
end
|