diff options
| author | Davit Grigoryan <[email protected]> | 2026-04-09 12:25:24 -0700 |
|---|---|---|
| committer | Davit Grigoryan <[email protected]> | 2026-04-22 02:37:26 -0700 |
| commit | 14ca50edb249d5f4ef621903259d955deb3a2fc3 (patch) | |
| tree | a1798764b97c2c351ea9c8ab1422886e9488d18b /adaptFFE.m | |
Diffstat (limited to 'adaptFFE.m')
| -rw-r--r-- | adaptFFE.m | 94 |
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 |
