Line | Branch | Decision | Exec | Source |
---|---|---|---|---|
1 | /** | |||
2 | * @file test_trigger_noiseless.cpp | |||
3 | * | |||
4 | * @date Apr 20, 2018 | |||
5 | */ | |||
6 | ||||
7 | #include "pch.h" | |||
8 | ||||
9 | #include "trigger_decoder.h" | |||
10 | #include "event_queue.h" | |||
11 | #include "trigger_central.h" | |||
12 | #include "main_trigger_callback.h" | |||
13 | #include "advance_map.h" | |||
14 | #include "speed_density.h" | |||
15 | #include "fuel_math.h" | |||
16 | #include "spark_logic.h" | |||
17 | #include "trigger_universal.h" | |||
18 | ||||
19 | extern bool printTriggerDebug; | |||
20 | ||||
21 | 1908 | static void fireEvent(EngineTestHelper *eth, bool isRise) { | ||
22 | // mostly we fire only rise events (useOnlyRisingEdgeForTrigger=true). | |||
23 | // but for noise filtering, both edges should be processed, so we fire falling events too | |||
24 |
2/2✓ Branch 0 taken 954 times.
✓ Branch 1 taken 954 times.
|
2/2✓ Decision 'true' taken 954 times.
✓ Decision 'false' taken 954 times.
|
1908 | if (isRise) |
25 | 954 | eth->firePrimaryTriggerRise(); | ||
26 |
1/2✓ Branch 0 taken 954 times.
✗ Branch 1 not taken.
|
1/2✓ Decision 'true' taken 954 times.
✗ Decision 'false' not taken.
|
954 | else if (engineConfiguration->useNoiselessTriggerDecoder) |
27 | 954 | eth->firePrimaryTriggerFall(); | ||
28 | 1908 | } | ||
29 | ||||
30 | /* ________ __ _ _ __ | |||
31 | * __|_|_|__| OR | | | |________ | |||
32 | * spikes signal spikes signal | |||
33 | */ | |||
34 | 1856 | static void noisyPulse(EngineTestHelper *eth, int idx, int durationUs, bool isRise, int noiseIdx, int durationNoiseUs, int offsetNoiseUs, int numSpikes) { | ||
35 | // skip some time at the beginning | |||
36 | 1856 | eth->moveTimeForwardUs(offsetNoiseUs); | ||
37 | 1856 | durationUs -= offsetNoiseUs; | ||
38 | // add noise spikes | |||
39 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 1849 times.
|
2/2✓ Decision 'true' taken 7 times.
✓ Decision 'false' taken 1849 times.
|
1856 | if (idx == noiseIdx) { |
40 | // calculate the distance between noise spikes (evenly spaced) | |||
41 | 7 | int noiseIntervalUs = (durationUs - durationNoiseUs * numSpikes) / numSpikes; | ||
42 | ||||
43 |
2/2✓ Branch 0 taken 26 times.
✓ Branch 1 taken 7 times.
|
2/2✓ Decision 'true' taken 26 times.
✓ Decision 'false' taken 7 times.
|
33 | for (int i = 0; i < numSpikes; i++) { |
44 | // start spike | |||
45 | 26 | fireEvent(eth, isRise); | ||
46 | 26 | eth->moveTimeForwardUs(durationNoiseUs); | ||
47 | 26 | durationUs -= durationNoiseUs; | ||
48 | // end spike | |||
49 | 26 | fireEvent(eth, !isRise); | ||
50 | ||||
51 | // add space between spikes | |||
52 | 26 | eth->moveTimeForwardUs(noiseIntervalUs); | ||
53 | 26 | durationUs -= noiseIntervalUs; | ||
54 | } | |||
55 | } | |||
56 | ||||
57 | // add the rest of pulse period | |||
58 | 1856 | eth->moveTimeForwardUs(durationUs); | ||
59 | 1856 | fireEvent(eth, isRise); | ||
60 | 1856 | } | ||
61 | ||||
62 | 8 | static void fireNoisyCycle60_2(EngineTestHelper *eth, int numCycles, int durationUs, int noiseIdx, int durationNoiseUs, int offsetNoiseUs, int numSpikes) { | ||
63 | 8 | int idx = 0; | ||
64 |
2/2✓ Branch 0 taken 16 times.
✓ Branch 1 taken 8 times.
|
2/2✓ Decision 'true' taken 16 times.
✓ Decision 'false' taken 8 times.
|
24 | for (int cycles = 0; cycles < numCycles; cycles++) { |
65 | 16 | int count = 60 - 2 - 1; | ||
66 |
2/2✓ Branch 0 taken 912 times.
✓ Branch 1 taken 16 times.
|
2/2✓ Decision 'true' taken 912 times.
✓ Decision 'false' taken 16 times.
|
928 | for (int i = 0; i < count; i++) { |
67 | // rising | |||
68 | 912 | noisyPulse(eth, idx++, durationUs, true, noiseIdx, durationNoiseUs, offsetNoiseUs, numSpikes); | ||
69 | // falling | |||
70 | 912 | noisyPulse(eth, idx++, durationUs, false, noiseIdx, durationNoiseUs, offsetNoiseUs, numSpikes); | ||
71 | } | |||
72 | // skip 2 teeth (durationUs * 4) | |||
73 | // and add 1st rising teeth of the next cycle | |||
74 | 16 | noisyPulse(eth, idx++, (durationUs * 4) + durationUs, true, noiseIdx, durationNoiseUs, offsetNoiseUs, numSpikes); | ||
75 | // falling | |||
76 | 16 | noisyPulse(eth, idx++, durationUs, false, noiseIdx, durationNoiseUs, offsetNoiseUs, numSpikes); | ||
77 | } | |||
78 | 8 | } | ||
79 | ||||
80 | 7 | static void resetTrigger(EngineTestHelper ð) { | ||
81 | 7 | eth.applyTriggerWaveform(); | ||
82 | 7 | eth.engine.triggerCentral.noiseFilter.resetAccumSignalData(); | ||
83 | // reset error counter | |||
84 | 7 | eth.engine.triggerCentral.triggerState.totalTriggerErrorCounter = 0; | ||
85 | 7 | } | ||
86 | ||||
87 | 1 | static void testNoiselessDecoderProcedure(EngineTestHelper ð, int errorToleranceCnt) { | ||
88 | 1 | printf("*** (bc->useNoiselessTriggerDecoder = %s)\r\n", | ||
89 |
1/2✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
|
1 | engineConfiguration->useNoiselessTriggerDecoder ? "true" : "false"); | |
90 | ||||
91 | 1 | resetTrigger(eth); | ||
92 | ||||
93 | // first, no noise | |||
94 | 1 | fireNoisyCycle60_2(ð, 2, 1000, -1, 0, 0, 0); | ||
95 | ||||
96 | // should be no errors anyway | |||
97 |
3/9✓ Branch 3 taken 1 time.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 time.
✗ Branch 11 not taken.
✗ Branch 14 not taken.
✗ Branch 19 not taken.
✗ Branch 22 not taken.
✓ Branch 29 taken 1 time.
✗ Branch 30 not taken.
|
1 | ASSERT_EQ( 0u, engine->triggerCentral.triggerState.totalTriggerErrorCounter) << "testNoiselessDecoderProcedure totalTriggerErrorCounter"; | |
98 | // check if we're imitating the 60-2 signal correctly | |||
99 |
4/10✓ Branch 3 taken 1 time.
✓ Branch 7 taken 1 time.
✗ Branch 12 not taken.
✓ Branch 13 taken 1 time.
✗ Branch 16 not taken.
✗ Branch 19 not taken.
✗ Branch 24 not taken.
✗ Branch 27 not taken.
✓ Branch 34 taken 1 time.
✗ Branch 35 not taken.
|
1 | ASSERT_EQ( 0, eth.engine.triggerCentral.triggerState.getCurrentIndex()) << "index #1"; | |
100 | // check rpm (60secs / (1000us * 60teeth)) = 1000rpm | |||
101 |
4/10✓ Branch 3 taken 1 time.
✓ Branch 7 taken 1 time.
✗ Branch 12 not taken.
✓ Branch 13 taken 1 time.
✗ Branch 16 not taken.
✗ Branch 19 not taken.
✗ Branch 24 not taken.
✗ Branch 27 not taken.
✓ Branch 34 taken 1 time.
✗ Branch 35 not taken.
|
1 | ASSERT_EQ( 1000, Sensor::getOrZero(SensorType::Rpm)) << "testNoiselessDecoder RPM"; | |
102 | ||||
103 | // add noise1 - 1 spike in the middle of the 2nd rising pulse | |||
104 | 1 | fireNoisyCycle60_2(ð, 2, 1000, 2, 10, 500, 1); | ||
105 | ||||
106 |
3/9✓ Branch 2 taken 1 time.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 time.
✗ Branch 9 not taken.
✗ Branch 12 not taken.
✗ Branch 17 not taken.
✗ Branch 20 not taken.
✓ Branch 27 taken 1 time.
✗ Branch 28 not taken.
|
1 | ASSERT_NEAR(errorToleranceCnt, engine->triggerCentral.triggerState.totalTriggerErrorCounter, EPS4D) << "testNoiselessDecoder noise#1"; | |
107 | ||||
108 | 1 | resetTrigger(eth); | ||
109 | ||||
110 | // add noise2 - 1 spike in the middle of the 2nd falling pulse | |||
111 | 1 | fireNoisyCycle60_2(ð, 2, 1000, 3, 10, 500, 1); | ||
112 | ||||
113 | //assertEqualsM("noise#2", errorToleranceCnt, engine->triggerCentral.triggerState.totalTriggerErrorCounter); | |||
114 | ||||
115 | 1 | resetTrigger(eth); | ||
116 | ||||
117 | // add noise3 - in the middle of the sync.gap, | |||
118 | // so that we cannot tell for sure if it's a start of another 'extra' tooth or just a noise inside the gap, | |||
119 | // that's why we used expectedEventCount[] in our filtering algo to make a prediction about gap | |||
120 | 1 | fireNoisyCycle60_2(ð, 2, 1000, 114, 10, 1500, 1); | ||
121 | ||||
122 | // so everything runs smoothly! | |||
123 |
3/9✓ Branch 2 taken 1 time.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 time.
✗ Branch 9 not taken.
✗ Branch 12 not taken.
✗ Branch 17 not taken.
✗ Branch 20 not taken.
✓ Branch 27 taken 1 time.
✗ Branch 28 not taken.
|
1 | ASSERT_NEAR(errorToleranceCnt, engine->triggerCentral.triggerState.totalTriggerErrorCounter, EPS4D) << "noise#3"; | |
124 | ||||
125 | 1 | resetTrigger(eth); | ||
126 | ||||
127 | // add noise4 - too close to the start of the real next signal, so the noise spike is accepted as a signal | |||
128 | // but when the real signal comes shortly afterwards, it we be treated as a noise spike, | |||
129 | 1 | fireNoisyCycle60_2(ð, 2, 1000, 4, 10, 980, 1); | ||
130 | ||||
131 | // and we won't get out of sync! | |||
132 |
3/9✓ Branch 2 taken 1 time.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 time.
✗ Branch 9 not taken.
✗ Branch 12 not taken.
✗ Branch 17 not taken.
✗ Branch 20 not taken.
✓ Branch 27 taken 1 time.
✗ Branch 28 not taken.
|
1 | ASSERT_NEAR(errorToleranceCnt, engine->triggerCentral.triggerState.totalTriggerErrorCounter, EPS4D) << "noise#4"; | |
133 | ||||
134 | 1 | resetTrigger(eth); | ||
135 | ||||
136 | // add noise5 - one very long 333us noise spike | |||
137 | 1 | fireNoisyCycle60_2(ð, 2, 1000, 4, 333, 10, 1); | ||
138 | // still ok | |||
139 |
3/9✓ Branch 2 taken 1 time.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 time.
✗ Branch 9 not taken.
✗ Branch 12 not taken.
✗ Branch 17 not taken.
✗ Branch 20 not taken.
✓ Branch 27 taken 1 time.
✗ Branch 28 not taken.
|
1 | ASSERT_NEAR(errorToleranceCnt, engine->triggerCentral.triggerState.totalTriggerErrorCounter, EPS4D) << "noise#5"; | |
140 | ||||
141 | 1 | resetTrigger(eth); | ||
142 | ||||
143 | // add noise6 - 10 short spikes across the entire signal pulse | |||
144 | 1 | const int failProofNumSpikes = 10; | ||
145 | 1 | fireNoisyCycle60_2(ð, 2, 1000, 4, 5, 10, failProofNumSpikes); | ||
146 | ||||
147 | // we barely survived this time | |||
148 |
3/9✓ Branch 2 taken 1 time.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 time.
✗ Branch 9 not taken.
✗ Branch 12 not taken.
✗ Branch 17 not taken.
✗ Branch 20 not taken.
✓ Branch 27 taken 1 time.
✗ Branch 28 not taken.
|
1 | ASSERT_NEAR(errorToleranceCnt, engine->triggerCentral.triggerState.totalTriggerErrorCounter, EPS4D) << "testNoiselessDecoder noise#6"; | |
149 | ||||
150 | 1 | resetTrigger(eth); | ||
151 | ||||
152 | // add noise7 - 34 short spikes across the entire signal pulse | |||
153 | 1 | fireNoisyCycle60_2(ð, 2, 1000, 2, 10, 10, failProofNumSpikes + 1); | ||
154 | ||||
155 | // alas, this is a hard case even for noiseless decoder, and it fails... | |||
156 | // but still we're close to 33% signal-noise ratio threshold - not bad! | |||
157 | // so here's an error anyway! | |||
158 |
3/9✓ Branch 3 taken 1 time.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 time.
✗ Branch 11 not taken.
✗ Branch 14 not taken.
✗ Branch 19 not taken.
✗ Branch 22 not taken.
✓ Branch 29 taken 1 time.
✗ Branch 30 not taken.
|
1 | ASSERT_EQ( 1u, engine->triggerCentral.triggerState.totalTriggerErrorCounter) << "testNoiselessDecoder noise#7_fail_test"; | |
159 | } | |||
160 | ||||
161 | 4 | TEST(trigger, noiselessDecoder) { | ||
162 |
1/1✓ Branch 1 taken 1 time.
|
1 | printf("====================================================================================== testNoiselessDecoder\r\n"); | |
163 | ||||
164 |
1/1✓ Branch 2 taken 1 time.
|
1 | EngineTestHelper eth(engine_type_e::TEST_ENGINE); | |
165 | ||||
166 | 1 | engineConfiguration->ignitionMode = IM_WASTED_SPARK; | ||
167 | ||||
168 | // we'll test on 60-2 wheel | |||
169 |
1/1✓ Branch 1 taken 1 time.
|
1 | eth.setTriggerType(trigger_type_e::TT_TOOTHED_WHEEL_60_2); | |
170 | ||||
171 |
3/8✓ Branch 3 taken 1 time.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 time.
✗ Branch 11 not taken.
✗ Branch 16 not taken.
✗ Branch 19 not taken.
✓ Branch 26 taken 1 time.
✗ Branch 27 not taken.
|
1 | ASSERT_EQ( 0u, engine->triggerCentral.triggerState.totalTriggerErrorCounter); | |
172 |
4/10✓ Branch 3 taken 1 time.
✓ Branch 7 taken 1 time.
✗ Branch 12 not taken.
✓ Branch 13 taken 1 time.
✗ Branch 16 not taken.
✗ Branch 19 not taken.
✗ Branch 24 not taken.
✗ Branch 27 not taken.
✓ Branch 34 taken 1 time.
✗ Branch 35 not taken.
|
1 | ASSERT_EQ( 0, Sensor::getOrZero(SensorType::Rpm)) << "testNoiselessDecoder RPM"; | |
173 | ||||
174 | //printTriggerDebug = true; | |||
175 | ||||
176 | #if 0 | |||
177 | // try normal trigger mode, no noise filtering | |||
178 | engineConfiguration->useNoiselessTriggerDecoder = false; | |||
179 | // for test validation, it should be 1 trigger error | |||
180 | testNoiselessDecoderProcedure(eth, 1); | |||
181 | #endif | |||
182 | ||||
183 | // now enable our noise filtering algo | |||
184 | 1 | engineConfiguration->useNoiselessTriggerDecoder = true; | ||
185 | // should be 0 errors! | |||
186 |
1/1✓ Branch 1 taken 1 time.
|
1 | testNoiselessDecoderProcedure(eth, 0); | |
187 | ||||
188 | //printTriggerDebug = false; | |||
189 | 1 | } | ||
190 |