summaryrefslogtreecommitdiff
path: root/adaptFFE.m
diff options
context:
space:
mode:
Diffstat (limited to 'adaptFFE.m')
-rw-r--r--adaptFFE.m94
1 files changed, 94 insertions, 0 deletions
diff --git a/adaptFFE.m b/adaptFFE.m
new file mode 100644
index 0000000..b76bae3
--- /dev/null
+++ b/adaptFFE.m
@@ -0,0 +1,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 \ No newline at end of file