GCC Code Coverage Report


Directory: ./
File: firmware/controllers/limp_manager.cpp
Date: 2025-10-03 00:57:22
Coverage Exec Excl Total
Lines: 91.5% 140 0 153
Functions: 100.0% 15 0 15
Branches: 81.6% 133 0 163
Decisions: 77.4% 65 - 84

Line Branch Decision Exec Source
1 #include "pch.h"
2
3 #include "limp_manager.h"
4 #include "fuel_math.h"
5 #include "main_trigger_callback.h"
6
7 #if EFI_ENGINE_CONTROL
8
9 #define CLEANUP_MODE_TPS 90
10
11 #if EFI_SHAFT_POSITION_INPUT
12 1165 static bool noFiringUntilVvtSync() {
13 1165 auto operationMode = getEngineRotationState()->getOperationMode();
14
15
2/2
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 1120 times.
2/2
✓ Decision 'true' taken 45 times.
✓ Decision 'false' taken 1120 times.
1165 if (engineConfiguration->isPhaseSyncRequiredForIgnition) {
16 // in rare cases engines do not like random sequential mode
17 45 return true;
18 }
19 1120 if (isGdiEngine()) {
20 #if EFI_PROD_CODE
21 criticalError("For GDI please configure CAM and require sync for ignition");
22 #endif
23 }
24
25
2/2
✓ Branch 0 taken 1041 times.
✓ Branch 1 taken 79 times.
2/2
✓ Decision 'true' taken 1041 times.
✓ Decision 'false' taken 79 times.
1120 if (engineConfiguration->ignitionMode == IM_ONE_COIL) {
26 // distributor routes to the correct cylinder, no need to worry about sync
27 1041 return false;
28 }
29
30 // Symmetrical crank modes require cam sync before firing
31 // non-symmetrical cranks can use faster spin-up mode (firing in wasted/batch before VVT sync)
32 // Examples include Nissan MR/VQ, Miata NB, etc
33 return
34
1/2
✓ Branch 0 taken 69 times.
✗ Branch 1 not taken.
69 operationMode == FOUR_STROKE_SYMMETRICAL_CRANK_SENSOR ||
35
3/4
✓ Branch 0 taken 69 times.
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 69 times.
148 operationMode == FOUR_STROKE_THREE_TIMES_CRANK_SENSOR ||
36 79 operationMode == FOUR_STROKE_TWELVE_TIMES_CRANK_SENSOR;
37 }
38 #endif // EFI_SHAFT_POSITION_INPUT
39
40 1122 void LimpManager::onFastCallback() {
41 1122 updateState(Sensor::getOrZero(SensorType::Rpm), getTimeNowNt());
42 1122 }
43
44 2285 void LimpManager::updateRevLimit(float rpm) {
45 // User-configured hard RPM limit, either constant or CLT-lookup
46 4570 m_revLimit = engineConfiguration->useCltBasedRpmLimit
47
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2279 times.
2285 ? interpolate2d(Sensor::getOrZero(SensorType::Clt), config->cltRevLimitRpmBins, config->cltRevLimitRpm)
48 2279 : (float)engineConfiguration->rpmHardLimit;
49
50 // Require configurable rpm drop before resuming
51 2285 resumeRpm = m_revLimit - engineConfiguration->rpmHardLimitHyst;
52
53 2285 m_timingRetard = interpolateClamped(resumeRpm, 0, m_revLimit, engineConfiguration->rpmSoftLimitTimingRetard, rpm);
54
55 2285 percent_t fuelAdded = interpolateClamped(resumeRpm, 0, m_revLimit, engineConfiguration->rpmSoftLimitFuelAdded, rpm);
56 2285 m_fuelCorrection = 1.0f + fuelAdded / 100;
57 2285 }
58
59 1165 void LimpManager::updateState(float rpm, efitick_t nowNt) {
60 1165 Clearable allowFuel = engineConfiguration->isInjectionEnabled;
61 1165 Clearable allowSpark = engineConfiguration->isIgnitionEnabled;
62
63 #if EFI_SHAFT_POSITION_INPUT && !EFI_UNIT_TEST
64 if (!m_ignitionOn
65 && !engine->triggerCentral.directSelfStimulation // useful to try things on real ECU even without ignition voltage
66 ) {
67 allowFuel.clear(ClearReason::IgnitionOff);
68 allowSpark.clear(ClearReason::IgnitionOff);
69 }
70 #endif
71
72
5/7
✓ Branch 1 taken 1165 times.
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 1159 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 6 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1165 times.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 1165 times.
1165 if (isGdiEngine() && engineConfiguration->externalRusEfiGdiModule) {
73 if (externalGdiCanBusComms.getElapsedSeconds() > 1) {
74 allowFuel.clear(ClearReason::GdiComms);
75 }
76 }
77
78
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1165 times.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 1165 times.
1165 if (engine->engineState.lua.luaIgnCut) {
79 allowSpark.clear(ClearReason::Lua);
80 }
81
82
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1165 times.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 1165 times.
1165 if (engine->engineState.lua.luaFuelCut) {
83 allowFuel.clear(ClearReason::Lua);
84 }
85
86
1/1
✓ Branch 1 taken 1165 times.
1165 updateRevLimit(rpm);
87
3/3
✓ Branch 1 taken 1165 times.
✓ Branch 3 taken 7 times.
✓ Branch 4 taken 1158 times.
2/2
✓ Decision 'true' taken 7 times.
✓ Decision 'false' taken 1158 times.
1165 if (m_revLimitHysteresis.test(rpm, m_revLimit, resumeRpm)) {
88
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
1/2
✓ Decision 'true' taken 7 times.
✗ Decision 'false' not taken.
7 if (engineConfiguration->cutFuelOnHardLimit) {
89 7 allowFuel.clear(ClearReason::HardLimit);
90 }
91
92
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
1/2
✓ Decision 'true' taken 7 times.
✗ Decision 'false' not taken.
7 if (engineConfiguration->cutSparkOnHardLimit) {
93 7 allowSpark.clear(ClearReason::HardLimit);
94 }
95 }
96
97 #if EFI_SHAFT_POSITION_INPUT
98
2/3
✓ Branch 1 taken 1165 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1165 times.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 1165 times.
1165 if (engine->lambdaMonitor.isCut()) {
99 allowFuel.clear(ClearReason::LambdaProtection);
100 }
101
102
1/1
✓ Branch 1 taken 1165 times.
2/2
✓ Decision 'true' taken 36 times.
✓ Decision 'false' taken 1129 times.
1165 if (noFiringUntilVvtSync()
103
6/6
✓ Branch 0 taken 55 times.
✓ Branch 1 taken 1110 times.
✓ Branch 3 taken 36 times.
✓ Branch 4 taken 19 times.
✓ Branch 5 taken 36 times.
✓ Branch 6 taken 1129 times.
1165 && !engine->triggerCentral.triggerState.hasSynchronizedPhase()) {
104 // Any engine that requires cam-assistance for a full crank sync (symmetrical crank) can't schedule until we have cam sync
105 // examples:
106 // NB2, Nissan VQ/MR: symmetrical crank wheel and we need to make sure no spark happens out of sync
107 // VTwin Harley: uneven firing order, so we need "cam" MAP sync to make sure no spark happens out of sync
108 36 allowFuel.clear(ClearReason::EnginePhase);
109 36 allowSpark.clear(ClearReason::EnginePhase);
110 }
111
112 // Force fuel limiting on the fault rev limit
113
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1165 times.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 1165 times.
1165 if (rpm > m_faultRevLimit) {
114 allowFuel.clear(m_rpmLimitReason);
115 }
116
117 // Limit fuel only on boost pressure (limiting spark bends valves)
118 1165 float mapCut = engineConfiguration->boostCutPressure;
119
2/2
✓ Branch 0 taken 1164 times.
✓ Branch 1 taken 1 time.
2/2
✓ Decision 'true' taken 1164 times.
✓ Decision 'false' taken 1 time.
1165 if (mapCut != 0) {
120 // require drop of 'boostCutPressureHyst' kPa to resume fuel
121
4/4
✓ Branch 2 taken 1164 times.
✓ Branch 5 taken 1164 times.
✓ Branch 7 taken 4 times.
✓ Branch 8 taken 1160 times.
2/2
✓ Decision 'true' taken 4 times.
✓ Decision 'false' taken 1160 times.
1164 if (m_boostCutHysteresis.checkIfLimitIsExceeded(Sensor::getOrZero(SensorType::Map), mapCut, engineConfiguration->boostCutPressureHyst)) {
122 4 allowFuel.clear(ClearReason::BoostCut);
123 }
124 }
125
126
3/3
✓ Branch 1 taken 1165 times.
✓ Branch 3 taken 76 times.
✓ Branch 4 taken 1089 times.
2/2
✓ Decision 'true' taken 76 times.
✓ Decision 'false' taken 1089 times.
1165 if (engine->rpmCalculator.isRunning()) {
127
1/1
✓ Branch 1 taken 76 times.
76 bool hasOilpSensor = Sensor::hasSensor(SensorType::OilPressure);
128
1/1
✓ Branch 2 taken 76 times.
76 auto oilp = Sensor::get(SensorType::OilPressure);
129 76 uint16_t minOilPressure = engineConfiguration->minOilPressureAfterStart;
130
131 // Only check if the setting is enabled and you have an oil pressure sensor
132
3/4
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 67 times.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
2/2
✓ Decision 'true' taken 9 times.
✓ Decision 'false' taken 67 times.
76 if (minOilPressure > 0 && hasOilpSensor) {
133 // Has it been long enough we should have pressure?
134
1/1
✓ Branch 1 taken 9 times.
9 bool isTimedOut = engine->rpmCalculator.getSecondsSinceEngineStart(nowNt) > 5.0f;
135
136 // Only check before timed out
137
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 4 times.
2/2
✓ Decision 'true' taken 5 times.
✓ Decision 'false' taken 4 times.
9 if (!isTimedOut) {
138
1/2
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
1/2
✓ Decision 'true' taken 5 times.
✗ Decision 'false' not taken.
5 if (oilp) {
139 // We had oil pressure! Set the flag.
140
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 4 times.
2/2
✓ Decision 'true' taken 1 time.
✓ Decision 'false' taken 4 times.
5 if (oilp.Value > minOilPressure) {
141 1 m_hadOilPressureAfterStart = true;
142 }
143 }
144 }
145
146 // If time is up, the sensor works, and no pressure, kill the engine.
147
4/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 2 times.
2/2
✓ Decision 'true' taken 2 times.
✓ Decision 'false' taken 7 times.
9 if (isTimedOut && !m_hadOilPressureAfterStart) {
148 2 allowFuel.clear(ClearReason::OilPressure);
149 }
150 }
151
152
6/6
✓ Branch 1 taken 19 times.
✓ Branch 2 taken 57 times.
✓ Branch 3 taken 5 times.
✓ Branch 4 taken 14 times.
✓ Branch 5 taken 5 times.
✓ Branch 6 taken 71 times.
2/2
✓ Decision 'true' taken 5 times.
✓ Decision 'false' taken 71 times.
76 if (oilp && engineConfiguration->enableOilPressureProtect) {
153
1/1
✓ Branch 1 taken 5 times.
5 float minPressure = interpolate2d(rpm, config->minimumOilPressureBins, config->minimumOilPressureValues);
154 5 bool isPressureSufficient = oilp.Value > minPressure;
155
156
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2 times.
2/2
✓ Decision 'true' taken 3 times.
✓ Decision 'false' taken 2 times.
5 if (isPressureSufficient) {
157
1/1
✓ Branch 1 taken 3 times.
3 m_lowOilPressureTimer.reset(nowNt);
158 }
159
160
3/3
✓ Branch 2 taken 5 times.
✓ Branch 4 taken 1 time.
✓ Branch 5 taken 4 times.
2/2
✓ Decision 'true' taken 1 time.
✓ Decision 'false' taken 4 times.
5 if (m_lowOilPressureTimer.hasElapsedSec(engineConfiguration->minimumOilPressureTimeout)) {
161 1 allowFuel.clear(ClearReason::OilPressure);
162 }
163 }
164
165 // check the maximum oil pressure
166
1/1
✓ Branch 1 taken 76 times.
76 float maxOilPressure = interpolate2d(rpm, config->maximumOilPressureBins, config->maximumOilPressureValues);
167
3/4
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 71 times.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
2/2
✓ Decision 'true' taken 5 times.
✓ Decision 'false' taken 71 times.
76 if (maxOilPressure > 0 && hasOilpSensor) {
168
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2 times.
2/2
✓ Decision 'true' taken 3 times.
✓ Decision 'false' taken 2 times.
5 if (oilp.Value < maxOilPressure) {
169
1/1
✓ Branch 1 taken 3 times.
3 m_highOilPressureTimer.reset(nowNt);
170 }
171
3/3
✓ Branch 2 taken 5 times.
✓ Branch 4 taken 1 time.
✓ Branch 5 taken 4 times.
2/2
✓ Decision 'true' taken 1 time.
✓ Decision 'false' taken 4 times.
5 if (m_highOilPressureTimer.hasElapsedSec(engineConfiguration->maxOilPressureTimeout)) {
172 1 allowFuel.clear(ClearReason::OilPressure);
173 }
174 }
175
176 } else {
177 // reset state in case of stalled engine
178 1089 m_hadOilPressureAfterStart = false;
179
1/1
✓ Branch 1 taken 1089 times.
1089 m_lowOilPressureTimer.reset(nowNt);
180 }
181
182 // If we're in engine stop mode, inhibit fuel
183
2/3
✓ Branch 1 taken 1165 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1165 times.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 1165 times.
1165 if (shutdownController.isEngineStop(nowNt)) {
184 /**
185 * todo: we need explicit clarification on why do we cut fuel but do not cut spark here!
186 */
187 allowFuel.clear(ClearReason::StopRequested);
188 }
189
190 {
191 // todo: we need to add some tests of this?
192 // If duty cycle is high, impose a fuel cut rev limiter.
193 // This is safer than attempting to limp along with injectors or a pump that are out of flow.
194 // Two conditions will trigger a cut:
195 // - An instantaneous excursion above maxInjectorDutyInstant
196 // - A sustained excursion above maxInjectorDutySustained for a duration of >= maxInjectorDutySustainedTimeout
197 // Only reset once below 20% duty to force the driver to lift off the pedal
198
199
1/1
✓ Branch 1 taken 1165 times.
1165 auto injDutyCycle = getInjectorDutyCycle(rpm);
200 1165 bool isOverInstantDutyCycle = injDutyCycle > engineConfiguration->maxInjectorDutyInstant;
201 1165 bool isOverSustainedDutyCycle = injDutyCycle > engineConfiguration->maxInjectorDutySustained;
202 1165 bool isUnderLowDuty = injDutyCycle < 20;
203
204
1/2
✓ Branch 0 taken 1165 times.
✗ Branch 1 not taken.
1/2
✓ Decision 'true' taken 1165 times.
✗ Decision 'false' not taken.
1165 if (!isOverSustainedDutyCycle) {
205 // Duty cycle is OK, reset timer.
206
1/1
✓ Branch 1 taken 1165 times.
1165 m_injectorDutySustainedTimer.reset(nowNt);
207 }
208
209 // True if isOverSustainedDutyCycle has been true for longer than the timeout
210
1/1
✓ Branch 2 taken 1165 times.
1165 bool sustainedLimitTimedOut = m_injectorDutySustainedTimer.hasElapsedSec(engineConfiguration->maxInjectorDutySustainedTimeout);
211
212
2/4
✓ Branch 0 taken 1165 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1165 times.
1165 bool someLimitTripped = isOverInstantDutyCycle || sustainedLimitTimedOut;
213
214
2/3
✓ Branch 1 taken 1165 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1165 times.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 1165 times.
1165 if (m_injectorDutyCutHysteresis.test(someLimitTripped, isUnderLowDuty)) {
215 allowFuel.clear(ClearReason::InjectorDutyCycle);
216 warning(ObdCode::CUSTOM_TOO_LONG_FUEL_INJECTION, "Injector duty cycle cut %.1f", injDutyCycle);
217 }
218 }
219
220 {
221 // GDI Fuel cut
222 1165 bool isGDIDriverInjectorTimeTooLong = engine->engineState.injectionDuration > engineConfiguration->mc33_t_hold_tot;
223
224
7/7
✓ Branch 1 taken 1165 times.
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 1159 times.
✓ Branch 5 taken 1 time.
✓ Branch 6 taken 5 times.
✓ Branch 7 taken 1 time.
✓ Branch 8 taken 1164 times.
2/2
✓ Decision 'true' taken 1 time.
✓ Decision 'false' taken 1164 times.
1165 if (isGdiEngine() && isGDIDriverInjectorTimeTooLong) {
225 1 allowFuel.clear(ClearReason::GdiLimits);
226
1/1
✓ Branch 1 taken 1 time.
1 warning(ObdCode::CUSTOM_TOO_LONG_FUEL_INJECTION, "Injection duration excess PT2001 limits time: %.4f", engine->engineState.injectionDuration);
227 }
228 }
229
230 // If the pedal is pushed while not running, cut fuel to clear a flood condition.
231
1/1
✓ Branch 1 taken 1165 times.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 1165 times.
1165 if (!engine->rpmCalculator.isRunning() &&
232
4/6
✓ Branch 0 taken 1089 times.
✓ Branch 1 taken 76 times.
✓ Branch 2 taken 1089 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1165 times.
2254 engineConfiguration->isCylinderCleanupEnabled &&
233
2/3
✓ Branch 1 taken 1089 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1089 times.
1089 Sensor::getOrZero(SensorType::DriverThrottleIntent) > CLEANUP_MODE_TPS) {
234 allowFuel.clear(ClearReason::FloodClear);
235 }
236 #endif // EFI_SHAFT_POSITION_INPUT
237
238
1/1
✓ Branch 1 taken 1165 times.
1/2
✓ Decision 'true' taken 1165 times.
✗ Decision 'false' not taken.
1165 if (!engine->isMainRelayEnabled()) {
239 /*
240 todo AndreiKA this change breaks 22 unit tests?
241 allowFuel.clear();
242 allowSpark.clear();
243 */
244 }
245
246 #if EFI_LAUNCH_CONTROL
247 // Fuel cut if launch control engaged
248
2/3
✓ Branch 1 taken 1165 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1165 times.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 1165 times.
1165 if (engine->launchController.isLaunchFuelRpmRetardCondition()) {
249 allowFuel.clear(ClearReason::LaunchCut);
250 }
251
252 // Spark cut if launch control engaged
253
3/3
✓ Branch 1 taken 1165 times.
✓ Branch 3 taken 8 times.
✓ Branch 4 taken 1157 times.
2/2
✓ Decision 'true' taken 8 times.
✓ Decision 'false' taken 1157 times.
1165 if (engine->launchController.isLaunchSparkRpmRetardCondition()) {
254 8 allowSpark.clear(ClearReason::LaunchCut);
255 }
256 #endif // EFI_LAUNCH_CONTROL
257
258 1165 m_transientAllowInjection = allowFuel;
259 1165 m_transientAllowIgnition = allowSpark;
260
261
6/6
✓ Branch 1 taken 1071 times.
✓ Branch 2 taken 94 times.
✓ Branch 4 taken 69 times.
✓ Branch 5 taken 1002 times.
✓ Branch 6 taken 163 times.
✓ Branch 7 taken 1002 times.
2/2
✓ Decision 'true' taken 163 times.
✓ Decision 'false' taken 1002 times.
1165 if (!m_transientAllowInjection || !m_transientAllowIgnition) {
262 // Tracks the last time any cut happened
263
1/1
✓ Branch 1 taken 163 times.
163 m_lastCutTime.reset(nowNt);
264 }
265 1165 }
266
267 1 void LimpManager::onIgnitionStateChanged(bool ignitionOn) {
268 1 m_ignitionOn = ignitionOn;
269 1 }
270
271 1 void LimpManager::reportEtbProblem() {
272 1 m_allowEtb.clear(ClearReason::EtbProblem);
273 1 setFaultRevLimit(/*rpm*/1500, ClearReason::EtbFaultRevLimit);
274 1 }
275
276 2 void LimpManager::fatalError() {
277 2 m_allowEtb.clear(ClearReason::Fatal);
278 2 m_allowIgnition.clear(ClearReason::Fatal);
279 2 m_allowInjection.clear(ClearReason::Fatal);
280 2 m_allowTriggerInput.clear(ClearReason::Fatal);
281
282 2 setFaultRevLimit(/*rpm*/0, ClearReason::FatalErrorRevLimit);
283 2 }
284
285 3 void LimpManager::setFaultRevLimit(int limit, ClearReason rpmLimitReason) {
286 // Only allow decreasing the limit
287 // aka uses the limit of the worst fault to yet occur
288
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
1/2
✓ Decision 'true' taken 3 times.
✗ Decision 'false' not taken.
3 if (limit < m_faultRevLimit) {
289 3 m_faultRevLimit = limit;
290 3 m_rpmLimitReason = rpmLimitReason;
291 }
292 3 }
293
294 #if EFI_ELECTRONIC_THROTTLE_BODY
295 417 bool LimpManager::allowElectronicThrottle() const {
296
3/4
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 415 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
417 return m_allowEtb || engine->etbIgnoreJamProtection;
297 }
298 #endif // EFI_ELECTRONIC_THROTTLE_BODY
299
300 67209 bool LimpManager::allowTriggerInput() const {
301 67209 return m_allowTriggerInput;
302 }
303
304 31232 LimpState LimpManager::allowInjection() const {
305
2/2
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 31231 times.
2/2
✓ Decision 'true' taken 1 time.
✓ Decision 'false' taken 31231 times.
31232 if (!m_allowInjection) {
306 1 return {false, m_allowInjection.clearReason};
307 }
308
2/2
✓ Branch 1 taken 2361 times.
✓ Branch 2 taken 28870 times.
2/2
✓ Decision 'true' taken 2361 times.
✓ Decision 'false' taken 28870 times.
31231 if (!m_transientAllowInjection) {
309 2361 return {false, m_transientAllowInjection.clearReason};
310 }
311 28870 return {true, ClearReason::None};
312 }
313
314 30532 LimpState LimpManager::allowIgnition() const {
315
2/2
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 30531 times.
2/2
✓ Decision 'true' taken 1 time.
✓ Decision 'false' taken 30531 times.
30532 if (!m_allowIgnition) {
316 1 return {false, m_allowIgnition.clearReason};
317 }
318
2/2
✓ Branch 1 taken 342 times.
✓ Branch 2 taken 30189 times.
2/2
✓ Decision 'true' taken 342 times.
✓ Decision 'false' taken 30189 times.
30531 if (!m_transientAllowIgnition) {
319 342 return {false, m_transientAllowIgnition.clearReason};
320 }
321 30189 return {true, ClearReason::None};
322 }
323
324 1092 angle_t LimpManager::getLimitingTimingRetard() const {
325
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1092 times.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 1092 times.
1092 if (!engineConfiguration->cutSparkOnHardLimit)
326 return 0;
327 1092 return m_timingRetard;
328 }
329
330 989 float LimpManager::getLimitingFuelCorrection() const {
331
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 989 times.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 989 times.
989 if (!engineConfiguration->cutFuelOnHardLimit)
332 return 1.0f; // no correction
333 989 return m_fuelCorrection;
334 }
335
336 1 float LimpManager::getTimeSinceAnyCut() const {
337 1 return m_lastCutTime.getElapsedSeconds();
338 }
339 #endif // EFI_ENGINE_CONTROL
340