| 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 | 1146 | static bool noFiringUntilVvtSync() { | ||
| 13 | 1146 | auto operationMode = getEngineRotationState()->getOperationMode(); | ||
| 14 | ||||
| 15 |
2/2✓ Branch 0 taken 45 times.
✓ Branch 1 taken 1101 times.
|
2/2✓ Decision 'true' taken 45 times.
✓ Decision 'false' taken 1101 times.
|
1146 | if (engineConfiguration->isPhaseSyncRequiredForIgnition) { |
| 16 | // in rare cases engines do not like random sequential mode | |||
| 17 | 45 | return true; | ||
| 18 | } | |||
| 19 | 1101 | 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 1022 times.
✓ Branch 1 taken 79 times.
|
2/2✓ Decision 'true' taken 1022 times.
✓ Decision 'false' taken 79 times.
|
1101 | if (engineConfiguration->ignitionMode == IM_ONE_COIL) { |
| 26 | // distributor routes to the correct cylinder, no need to worry about sync | |||
| 27 | 1022 | 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 | 1103 | void LimpManager::onFastCallback() { | ||
| 41 | 1103 | updateState(Sensor::getOrZero(SensorType::Rpm), getTimeNowNt()); | ||
| 42 | 1103 | } | ||
| 43 | ||||
| 44 | 2247 | void LimpManager::updateRevLimit(float rpm) { | ||
| 45 | // User-configured hard RPM limit, either constant or CLT-lookup | |||
| 46 | 4494 | m_revLimit = engineConfiguration->useCltBasedRpmLimit | ||
| 47 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2241 times.
|
2247 | ? interpolate2d(Sensor::getOrZero(SensorType::Clt), config->cltRevLimitRpmBins, config->cltRevLimitRpm) | |
| 48 | 2241 | : (float)engineConfiguration->rpmHardLimit; | ||
| 49 | ||||
| 50 | // Require configurable rpm drop before resuming | |||
| 51 | 2247 | resumeRpm = m_revLimit - engineConfiguration->rpmHardLimitHyst; | ||
| 52 | ||||
| 53 | 2247 | m_timingRetard = interpolateClamped(resumeRpm, 0, m_revLimit, engineConfiguration->rpmSoftLimitTimingRetard, rpm); | ||
| 54 | ||||
| 55 | 2247 | percent_t fuelAdded = interpolateClamped(resumeRpm, 0, m_revLimit, engineConfiguration->rpmSoftLimitFuelAdded, rpm); | ||
| 56 | 2247 | m_fuelCorrection = 1.0f + fuelAdded / 100; | ||
| 57 | 2247 | } | ||
| 58 | ||||
| 59 | 1146 | void LimpManager::updateState(float rpm, efitick_t nowNt) { | ||
| 60 | 1146 | Clearable allowFuel = engineConfiguration->isInjectionEnabled; | ||
| 61 | 1146 | 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 1146 times.
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 1140 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 6 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1146 times.
|
1/2✗ Decision 'true' not taken.
✓ Decision 'false' taken 1146 times.
|
1146 | 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 1146 times.
|
1/2✗ Decision 'true' not taken.
✓ Decision 'false' taken 1146 times.
|
1146 | if (engine->engineState.lua.luaIgnCut) { |
| 79 | ✗ | allowSpark.clear(ClearReason::Lua); | ||
| 80 | } | |||
| 81 | ||||
| 82 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1146 times.
|
1/2✗ Decision 'true' not taken.
✓ Decision 'false' taken 1146 times.
|
1146 | if (engine->engineState.lua.luaFuelCut) { |
| 83 | ✗ | allowFuel.clear(ClearReason::Lua); | ||
| 84 | } | |||
| 85 | ||||
| 86 |
1/1✓ Branch 1 taken 1146 times.
|
1146 | updateRevLimit(rpm); | |
| 87 |
3/3✓ Branch 1 taken 1146 times.
✓ Branch 3 taken 7 times.
✓ Branch 4 taken 1139 times.
|
2/2✓ Decision 'true' taken 7 times.
✓ Decision 'false' taken 1139 times.
|
1146 | 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 1146 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1146 times.
|
1/2✗ Decision 'true' not taken.
✓ Decision 'false' taken 1146 times.
|
1146 | if (engine->lambdaMonitor.isCut()) { |
| 99 | ✗ | allowFuel.clear(ClearReason::LambdaProtection); | ||
| 100 | } | |||
| 101 | ||||
| 102 |
1/1✓ Branch 1 taken 1146 times.
|
2/2✓ Decision 'true' taken 36 times.
✓ Decision 'false' taken 1110 times.
|
1146 | if (noFiringUntilVvtSync() |
| 103 |
6/6✓ Branch 0 taken 55 times.
✓ Branch 1 taken 1091 times.
✓ Branch 3 taken 36 times.
✓ Branch 4 taken 19 times.
✓ Branch 5 taken 36 times.
✓ Branch 6 taken 1110 times.
|
1146 | && !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 1146 times.
|
1/2✗ Decision 'true' not taken.
✓ Decision 'false' taken 1146 times.
|
1146 | if (rpm > m_faultRevLimit) { |
| 114 | ✗ | allowFuel.clear(m_rpmLimitReason); | ||
| 115 | } | |||
| 116 | ||||
| 117 | // Limit fuel only on boost pressure (limiting spark bends valves) | |||
| 118 | 1146 | float mapCut = engineConfiguration->boostCutPressure; | ||
| 119 |
2/2✓ Branch 0 taken 1145 times.
✓ Branch 1 taken 1 time.
|
2/2✓ Decision 'true' taken 1145 times.
✓ Decision 'false' taken 1 time.
|
1146 | if (mapCut != 0) { |
| 120 | // require drop of 'boostCutPressureHyst' kPa to resume fuel | |||
| 121 |
4/4✓ Branch 2 taken 1145 times.
✓ Branch 5 taken 1145 times.
✓ Branch 7 taken 4 times.
✓ Branch 8 taken 1141 times.
|
2/2✓ Decision 'true' taken 4 times.
✓ Decision 'false' taken 1141 times.
|
1145 | 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 1146 times.
✓ Branch 3 taken 77 times.
✓ Branch 4 taken 1069 times.
|
2/2✓ Decision 'true' taken 77 times.
✓ Decision 'false' taken 1069 times.
|
1146 | if (engine->rpmCalculator.isRunning()) { |
| 127 |
1/1✓ Branch 1 taken 77 times.
|
77 | bool hasOilpSensor = Sensor::hasSensor(SensorType::OilPressure); | |
| 128 |
1/1✓ Branch 2 taken 77 times.
|
77 | auto oilp = Sensor::get(SensorType::OilPressure); | |
| 129 | 77 | 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 68 times.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
|
2/2✓ Decision 'true' taken 9 times.
✓ Decision 'false' taken 68 times.
|
77 | 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 58 times.
✓ Branch 3 taken 5 times.
✓ Branch 4 taken 14 times.
✓ Branch 5 taken 5 times.
✓ Branch 6 taken 72 times.
|
2/2✓ Decision 'true' taken 5 times.
✓ Decision 'false' taken 72 times.
|
77 | 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 77 times.
|
77 | float maxOilPressure = interpolate2d(rpm, config->maximumOilPressureBins, config->maximumOilPressureValues); | |
| 167 |
3/4✓ Branch 0 taken 5 times.
✓ Branch 1 taken 72 times.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
|
2/2✓ Decision 'true' taken 5 times.
✓ Decision 'false' taken 72 times.
|
77 | 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 | 1069 | m_hadOilPressureAfterStart = false; | ||
| 179 |
1/1✓ Branch 1 taken 1069 times.
|
1069 | m_lowOilPressureTimer.reset(nowNt); | |
| 180 | } | |||
| 181 | ||||
| 182 | // If we're in engine stop mode, inhibit fuel | |||
| 183 |
2/3✓ Branch 1 taken 1146 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1146 times.
|
1/2✗ Decision 'true' not taken.
✓ Decision 'false' taken 1146 times.
|
1146 | 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 1146 times.
|
1146 | auto injDutyCycle = getInjectorDutyCycle(rpm); | |
| 200 | 1146 | bool isOverInstantDutyCycle = injDutyCycle > engineConfiguration->maxInjectorDutyInstant; | ||
| 201 | 1146 | bool isOverSustainedDutyCycle = injDutyCycle > engineConfiguration->maxInjectorDutySustained; | ||
| 202 | 1146 | bool isUnderLowDuty = injDutyCycle < 20; | ||
| 203 | ||||
| 204 |
1/2✓ Branch 0 taken 1146 times.
✗ Branch 1 not taken.
|
1/2✓ Decision 'true' taken 1146 times.
✗ Decision 'false' not taken.
|
1146 | if (!isOverSustainedDutyCycle) { |
| 205 | // Duty cycle is OK, reset timer. | |||
| 206 |
1/1✓ Branch 1 taken 1146 times.
|
1146 | m_injectorDutySustainedTimer.reset(nowNt); | |
| 207 | } | |||
| 208 | ||||
| 209 | // True if isOverSustainedDutyCycle has been true for longer than the timeout | |||
| 210 |
1/1✓ Branch 2 taken 1146 times.
|
1146 | bool sustainedLimitTimedOut = m_injectorDutySustainedTimer.hasElapsedSec(engineConfiguration->maxInjectorDutySustainedTimeout); | |
| 211 | ||||
| 212 |
2/4✓ Branch 0 taken 1146 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1146 times.
|
1146 | bool someLimitTripped = isOverInstantDutyCycle || sustainedLimitTimedOut; | |
| 213 | ||||
| 214 |
2/3✓ Branch 1 taken 1146 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1146 times.
|
1/2✗ Decision 'true' not taken.
✓ Decision 'false' taken 1146 times.
|
1146 | 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 | 1146 | bool isGDIDriverInjectorTimeTooLong = engine->engineState.injectionDuration > engineConfiguration->mc33_t_hold_tot; | ||
| 223 | ||||
| 224 |
7/7✓ Branch 1 taken 1146 times.
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 1140 times.
✓ Branch 5 taken 1 time.
✓ Branch 6 taken 5 times.
✓ Branch 7 taken 1 time.
✓ Branch 8 taken 1145 times.
|
2/2✓ Decision 'true' taken 1 time.
✓ Decision 'false' taken 1145 times.
|
1146 | 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 1146 times.
|
1/2✗ Decision 'true' not taken.
✓ Decision 'false' taken 1146 times.
|
1146 | if (!engine->rpmCalculator.isRunning() && |
| 232 |
4/6✓ Branch 0 taken 1069 times.
✓ Branch 1 taken 77 times.
✓ Branch 2 taken 1069 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1146 times.
|
2215 | engineConfiguration->isCylinderCleanupEnabled && | |
| 233 |
2/3✓ Branch 1 taken 1069 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1069 times.
|
1069 | 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 1146 times.
|
1/2✓ Decision 'true' taken 1146 times.
✗ Decision 'false' not taken.
|
1146 | 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 1146 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1146 times.
|
1/2✗ Decision 'true' not taken.
✓ Decision 'false' taken 1146 times.
|
1146 | if (engine->launchController.isLaunchFuelRpmRetardCondition()) { |
| 249 | ✗ | allowFuel.clear(ClearReason::LaunchCut); | ||
| 250 | } | |||
| 251 | ||||
| 252 | // Spark cut if launch control engaged | |||
| 253 |
3/3✓ Branch 1 taken 1146 times.
✓ Branch 3 taken 8 times.
✓ Branch 4 taken 1138 times.
|
2/2✓ Decision 'true' taken 8 times.
✓ Decision 'false' taken 1138 times.
|
1146 | if (engine->launchController.isLaunchSparkRpmRetardCondition()) { |
| 254 | 8 | allowSpark.clear(ClearReason::LaunchCut); | ||
| 255 | } | |||
| 256 | #endif // EFI_LAUNCH_CONTROL | |||
| 257 | ||||
| 258 | 1146 | m_transientAllowInjection = allowFuel; | ||
| 259 | 1146 | m_transientAllowIgnition = allowSpark; | ||
| 260 | ||||
| 261 |
6/6✓ Branch 1 taken 1052 times.
✓ Branch 2 taken 94 times.
✓ Branch 4 taken 69 times.
✓ Branch 5 taken 983 times.
✓ Branch 6 taken 163 times.
✓ Branch 7 taken 983 times.
|
2/2✓ Decision 'true' taken 163 times.
✓ Decision 'false' taken 983 times.
|
1146 | 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 | 1146 | } | ||
| 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 | 71914 | bool LimpManager::allowTriggerInput() const { | ||
| 301 | 71914 | return m_allowTriggerInput; | ||
| 302 | } | |||
| 303 | ||||
| 304 | 33570 | LimpState LimpManager::allowInjection() const { | ||
| 305 |
2/2✓ Branch 1 taken 1 time.
✓ Branch 2 taken 33569 times.
|
2/2✓ Decision 'true' taken 1 time.
✓ Decision 'false' taken 33569 times.
|
33570 | if (!m_allowInjection) { |
| 306 | 1 | return {false, m_allowInjection.clearReason}; | ||
| 307 | } | |||
| 308 |
2/2✓ Branch 1 taken 2361 times.
✓ Branch 2 taken 31208 times.
|
2/2✓ Decision 'true' taken 2361 times.
✓ Decision 'false' taken 31208 times.
|
33569 | if (!m_transientAllowInjection) { |
| 309 | 2361 | return {false, m_transientAllowInjection.clearReason}; | ||
| 310 | } | |||
| 311 | 31208 | return {true, ClearReason::None}; | ||
| 312 | } | |||
| 313 | ||||
| 314 | 32870 | LimpState LimpManager::allowIgnition() const { | ||
| 315 |
2/2✓ Branch 1 taken 1 time.
✓ Branch 2 taken 32869 times.
|
2/2✓ Decision 'true' taken 1 time.
✓ Decision 'false' taken 32869 times.
|
32870 | if (!m_allowIgnition) { |
| 316 | 1 | return {false, m_allowIgnition.clearReason}; | ||
| 317 | } | |||
| 318 |
2/2✓ Branch 1 taken 342 times.
✓ Branch 2 taken 32527 times.
|
2/2✓ Decision 'true' taken 342 times.
✓ Decision 'false' taken 32527 times.
|
32869 | if (!m_transientAllowIgnition) { |
| 319 | 342 | return {false, m_transientAllowIgnition.clearReason}; | ||
| 320 | } | |||
| 321 | 32527 | return {true, ClearReason::None}; | ||
| 322 | } | |||
| 323 | ||||
| 324 | 1073 | angle_t LimpManager::getLimitingTimingRetard() const { | ||
| 325 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1073 times.
|
1/2✗ Decision 'true' not taken.
✓ Decision 'false' taken 1073 times.
|
1073 | if (!engineConfiguration->cutSparkOnHardLimit) |
| 326 | ✗ | return 0; | ||
| 327 | 1073 | return m_timingRetard; | ||
| 328 | } | |||
| 329 | ||||
| 330 | 969 | float LimpManager::getLimitingFuelCorrection() const { | ||
| 331 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 969 times.
|
1/2✗ Decision 'true' not taken.
✓ Decision 'false' taken 969 times.
|
969 | if (!engineConfiguration->cutFuelOnHardLimit) |
| 332 | ✗ | return 1.0f; // no correction | ||
| 333 | 969 | return m_fuelCorrection; | ||
| 334 | } | |||
| 335 | ||||
| 336 | 1 | float LimpManager::getTimeSinceAnyCut() const { | ||
| 337 | 1 | return m_lastCutTime.getElapsedSeconds(); | ||
| 338 | } | |||
| 339 | #endif // EFI_ENGINE_CONTROL | |||
| 340 |