blob: ed20f67b854e01fd23f41bc1aa8960656cf5bace (
plain)
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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
|
classdef LeveragedLMS < handle
% Version: 0.2 (min-COM-based)
% Description:
% If the smallest registered COM is above 3dB for some period,
% then assume it is safe to turn off the most "insignificant"
% tap (which now is, kind of, the smallest one)
%
% However, if smallest COM drops below 3dB for some period,
% then activate the fallback mechanism and turn on the recently
% disabled tap and terminate the algorithm
properties
lastDisabledTap
internalFFETapsMask
lastUpdateTime
reachedHighErr
lastMeanErr
maxErr
reachedHighCOM
reducedErrSeqCounter
increasedErrSeqCounter
targetCounters
targetCounterIndex
end
methods
function obj = LeveragedLMS(LMSUpdateObj)
obj.lastDisabledTap = -1;
obj.internalFFETapsMask = LMSUpdateObj.FFE_TapsMask;
obj.lastUpdateTime = LMSUpdateObj.StartFFEAdaptTime * LMSUpdateObj.WindowSize;
obj.reachedHighErr = 0;
obj.lastMeanErr = inf;
obj.maxErr = 0;
obj.reachedHighCOM = 0;
obj.reducedErrSeqCounter = 0;
obj.increasedErrSeqCounter = 0;
obj.targetCounters = [2 1];
obj.targetCounterIndex = 1;
end
function FFETapsMask = GetFFETapsMask(obj, LMSUpdateObj)
initialTogglingStart = LMSUpdateObj.StartFFEAdaptTime + 5;
if ismember(LMSUpdateObj.IterCount, LMSUpdateObj.LearningRatesAdjustTimes * LMSUpdateObj.WindowSize)
obj.targetCounterIndex = obj.targetCounterIndex + 1;
end
obj.maxErr = max(obj.maxErr, max(abs(LMSUpdateObj.ErrorVec)));
if mod(LMSUpdateObj.IterCount, LMSUpdateObj.WindowSize) == 0 && ...
LMSUpdateObj.IterCount > initialTogglingStart * LMSUpdateObj.WindowSize && ~obj.reachedHighErr
%avgErr = mean(abs(LMSUpdateObj.ErrorVec));
dlevDiff1 = LMSUpdateObj.Dlev_0p5 - LMSUpdateObj.Dlev_0p16;
dlevDiff2 = LMSUpdateObj.Dlev_0p16 - LMSUpdateObj.Dlev_m0p16;
dlevDiff3 = LMSUpdateObj.Dlev_m0p16 - LMSUpdateObj.Dlev_m0p5;
minDlevDiff = min([dlevDiff1 dlevDiff2 dlevDiff3]);
t = minDlevDiff / 2;
minCOM = 20*log10(t / obj.maxErr);
if minCOM >= 3
obj.reducedErrSeqCounter = obj.reducedErrSeqCounter + 1;
obj.increasedErrSeqCounter = 0;
obj.reachedHighCOM = 1;
else
obj.reducedErrSeqCounter = 0;
if obj.reachedHighCOM
obj.increasedErrSeqCounter = obj.increasedErrSeqCounter + 1;
end
end
%obj.lastMeanErr = avgErr * 1.125;
obj.maxErr = 0;
end
weights = abs(LMSUpdateObj.TapWeights);
% Take into account the neighboring taps as well
weights_padded = [0 weights 0];
weights_avg = (weights_padded(1:end-2) + 2*weights_padded(2:end-1) + weights_padded(3:end)) / 3;
weights_avg(~obj.internalFFETapsMask) = inf;
[~, minTapIndex] = min(weights_avg);
if obj.reducedErrSeqCounter == obj.targetCounters(obj.targetCounterIndex) && ...
LMSUpdateObj.IterCount > initialTogglingStart * LMSUpdateObj.WindowSize && ~obj.reachedHighErr
obj.internalFFETapsMask(minTapIndex) = 0;
obj.lastDisabledTap = minTapIndex;
obj.lastUpdateTime = LMSUpdateObj.IterCount;
obj.reducedErrSeqCounter = 0;
obj.increasedErrSeqCounter = 0;
end
if obj.increasedErrSeqCounter == obj.targetCounters(obj.targetCounterIndex)*2 && ~obj.reachedHighErr
obj.reachedHighErr = 1;
if obj.lastDisabledTap ~= -1
obj.internalFFETapsMask(obj.lastDisabledTap) = 1;
end
% to make sure it throws an error in case tried being accessed
obj.lastDisabledTap = -1;
obj.reducedErrSeqCounter = 0;
obj.increasedErrSeqCounter = 0;
end
FFETapsMask = obj.internalFFETapsMask;
end
end
end
|