GCC Code Coverage Report


Directory: ./
File: firmware/controllers/algo/ignition/ignition_state.cpp
Date: 2025-10-03 00:57:22
Coverage Exec Excl Total
Lines: 91.5% 173 0 189
Functions: 100.0% 17 0 17
Branches: 80.2% 101 0 126
Decisions: 86.4% 19 - 22

Line Branch Decision Exec Source
1 /**
2 * @file ignition_state.cpp
3 *
4 * @date Mar 27, 2013
5 * @author Andrey Belomutskiy, (c) 2012-2020
6 *
7 * This file is part of rusEfi - see http://rusefi.com
8 *
9 * rusEfi is free software; you can redistribute it and/or modify it under the terms of
10 * the GNU General Public License as published by the Free Software Foundation; either
11 * version 3 of the License, or (at your option) any later version.
12 *
13 * rusEfi is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
14 * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along with this program.
18 * If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "pch.h"
22
23 #include "idle_thread.h"
24 #include "launch_control.h"
25 #include "gppwm_channel.h"
26
27 #if EFI_ENGINE_CONTROL
28
29 // TODO: wow move this into engineState at least for context not to leak from test to test!
30 // todo: reset this between cranking attempts?! #2735
31 float minCrankingRpm = 0;
32
33 static Map3D<TRACTION_CONTROL_ETB_DROP_SLIP_SIZE, TRACTION_CONTROL_ETB_DROP_SPEED_SIZE, int8_t, uint16_t, uint8_t> tcTimingDropTable{"tct"};
34 static Map3D<TRACTION_CONTROL_ETB_DROP_SLIP_SIZE, TRACTION_CONTROL_ETB_DROP_SPEED_SIZE, int8_t, uint16_t, uint8_t> tcSparkSkipTable{"tcs"};
35
36 #if EFI_ENGINE_CONTROL && EFI_SHAFT_POSITION_INPUT
37
38 /**
39 * @return ignition timing angle advance before TDC
40 */
41 1105 angle_t getRunningAdvance(float rpm, float engineLoad) {
42
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1103 times.
2/2
✓ Decision 'true' taken 2 times.
✓ Decision 'false' taken 1103 times.
1105 if (std::isnan(engineLoad)) {
43 2 warning(ObdCode::CUSTOM_NAN_ENGINE_LOAD, "NaN engine load");
44 2 return NAN;
45 }
46
47
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1103 times.
1103 efiAssert(ObdCode::CUSTOM_ERR_ASSERT, !std::isnan(engineLoad), "invalid el", NAN);
48
49 // compute base ignition angle from main table
50 1103 float advanceAngle = IgnitionState::getInterpolatedIgnitionAngle(rpm, engineLoad);
51
52 1103 float vehicleSpeed = Sensor::getOrZero(SensorType::VehicleSpeed);
53 1103 float wheelSlip = Sensor::getOrZero(SensorType::WheelSlipRatio);
54
1/1
✓ Branch 2 taken 1103 times.
1103 engine->ignitionState.tractionAdvanceDrop = tcTimingDropTable.getValue(wheelSlip, vehicleSpeed);
55 1103 engine->engineState.tractionControlSparkSkip = tcSparkSkipTable.getValue(wheelSlip, vehicleSpeed);
56 1103 engine->engineState.updateSparkSkip();
57
58 1103 advanceAngle += engine->ignitionState.tractionAdvanceDrop;
59
60 #if EFI_ANTILAG_SYSTEM
61
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1103 times.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 1103 times.
1103 if (engine->antilagController.isAntilagCondition) {
62 float throttleIntent = Sensor::getOrZero(SensorType::DriverThrottleIntent);
63 engine->antilagController.timingALSCorrection = interpolate3d(
64 config->ALSTimingRetardTable,
65 config->alsIgnRetardLoadBins, throttleIntent,
66 config->alsIgnRetardrpmBins, rpm
67 );
68 advanceAngle += engine->antilagController.timingALSCorrection;
69 }
70 #endif /* EFI_ANTILAG_SYSTEM */
71
72 // Add any adjustments if configured
73
2/2
✓ Branch 1 taken 4412 times.
✓ Branch 2 taken 1103 times.
2/2
✓ Decision 'true' taken 4412 times.
✓ Decision 'false' taken 1103 times.
5515 for (size_t i = 0; i < efi::size(config->ignBlends); i++) {
74 4412 auto result = calculateBlend(config->ignBlends[i], rpm, engineLoad);
75
76 4412 engine->outputChannels.ignBlendParameter[i] = result.BlendParameter;
77 4412 engine->outputChannels.ignBlendBias[i] = result.Bias;
78 4412 engine->outputChannels.ignBlendOutput[i] = result.Value;
79 4412 engine->outputChannels.ignBlendYAxis[i] = result.TableYAxis;
80
81 4412 advanceAngle += result.Value;
82 }
83
84 // get advance from the separate table for Idle
85 #if EFI_IDLE_CONTROL
86
4/4
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 1096 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 1098 times.
2/2
✓ Decision 'true' taken 5 times.
✓ Decision 'false' taken 1105 times.
1110 if (engineConfiguration->useSeparateAdvanceForIdle &&
87
3/4
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 5 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 2 times.
7 (engine->module<IdleController>()->isIdlingOrTaper() || engine->module<IdleController>()->isCoastingAdvance())) {
88
1/1
✓ Branch 1 taken 5 times.
5 float idleAdvance = interpolate2d(rpm, config->idleAdvanceBins, config->idleAdvance);
89
90
1/1
✓ Branch 2 taken 5 times.
5 auto tps = Sensor::get(SensorType::DriverThrottleIntent);
91
1/2
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
1/2
✓ Decision 'true' taken 5 times.
✗ Decision 'false' not taken.
5 if (tps) {
92 // interpolate between idle table and normal (running) table using TPS threshold
93 // 0 TPS -> idle table
94 // 1/2 threshold -> idle table
95 // idle threshold -> normal table
96 5 float idleThreshold = engineConfiguration->idlePidDeactivationTpsThreshold;
97
1/1
✓ Branch 1 taken 5 times.
5 advanceAngle = interpolateClamped(idleThreshold / 2, idleAdvance, idleThreshold, advanceAngle, tps.Value);
98 }
99 }
100 #endif
101
102 #if EFI_IDLE_CONTROL
103 // reset ignition table dot, see #8198
104
6/6
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 1096 times.
✓ Branch 5 taken 5 times.
✓ Branch 6 taken 2 times.
✓ Branch 7 taken 5 times.
✓ Branch 8 taken 1098 times.
2/2
✓ Decision 'true' taken 5 times.
✓ Decision 'false' taken 1098 times.
1103 if(engineConfiguration->useSeparateAdvanceForIdle && engine->module<IdleController>()->isIdlingOrTaper()){
105 5 engine->ignitionState.rpmForIgnitionIdleTableDot = rpm;
106 5 engine->ignitionState.rpmForIgnitionTableDot = -1;
107 5 engine->ignitionState.loadForIgnitionTableDot = -1;
108 } else {
109 1098 engine->ignitionState.rpmForIgnitionIdleTableDot = -1;
110 1098 engine->ignitionState.rpmForIgnitionTableDot = rpm;
111 1098 engine->ignitionState.loadForIgnitionTableDot = engineLoad;
112 }
113 #endif
114
115 #if EFI_LAUNCH_CONTROL
116
4/4
✓ Branch 0 taken 92 times.
✓ Branch 1 taken 1011 times.
✓ Branch 2 taken 64 times.
✓ Branch 3 taken 28 times.
2/2
✓ Decision 'true' taken 64 times.
✓ Decision 'false' taken 1039 times.
1103 if (engineConfiguration->launchControlEnabled && engineConfiguration->enableLaunchRetard) {
117 64 const float launchAngle = engineConfiguration->launchTimingRetard;
118
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 52 times.
2/2
✓ Decision 'true' taken 12 times.
✓ Decision 'false' taken 52 times.
64 if (engine->launchController.isPreLaunchCondition) {
119 12 const int launchRpm = engineConfiguration->launchRpm;
120 12 const int smoothRetardStartRpm = (launchRpm - engineConfiguration->launchRpmWindow);
121 12 const int smoothRetardEndRpm = (launchRpm - engineConfiguration->launchCorrectionsEndRpm);
122
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
1/2
✓ Decision 'true' taken 12 times.
✗ Decision 'false' not taken.
12 if (smoothRetardStartRpm <= rpm) {
123
4/4
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 2 times.
2/2
✓ Decision 'true' taken 4 times.
✓ Decision 'false' taken 8 times.
12 if (engineConfiguration->launchSmoothRetard && (rpm <= smoothRetardEndRpm)) {
124 // https://github.com/rusefi/rusefi/issues/5611#issuecomment-2130431696
125 4 return interpolateClamped(smoothRetardStartRpm, advanceAngle, smoothRetardEndRpm, launchAngle, rpm);
126 } else {
127 8 return launchAngle;
128 }
129 }
130
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 42 times.
2/2
✓ Decision 'true' taken 10 times.
✓ Decision 'false' taken 42 times.
52 } else if (engine->launchController.isLaunchCondition) {
131 10 return launchAngle;
132 }
133 }
134
2/2
✓ Branch 0 taken 557 times.
✓ Branch 1 taken 524 times.
1081 if (engineConfiguration->torqueReductionEnabled
135
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 546 times.
557 && engine->shiftTorqueReductionController.isFlatShiftConditionSatisfied
136 ) {
137 11 return engine->shiftTorqueReductionController.getTorqueReductionIgnitionRetard();
138 }
139
6/6
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 1058 times.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 8 times.
✓ Branch 6 taken 4 times.
✓ Branch 7 taken 1066 times.
1070 if (engineConfiguration->nitrousControlEnabled && engine->module<NitrousController>()->isNitrousCondition) {
140 4 advanceAngle -= engineConfiguration->nitrousIgnitionRetard;
141 }
142 #endif /* EFI_LAUNCH_CONTROL */
143
144 #ifdef MODULE_VVL_CONTROLLER
145 1070 advanceAngle += engine->module<VvlController>().unmock().getTimingModifier();
146 #endif /* MODULE_VVL_CONTROLLER */
147
148 1070 return advanceAngle;
149 }
150
151 1120 angle_t getCltTimingCorrection(float engineLoad) {
152
1/1
✓ Branch 2 taken 1120 times.
1120 const auto clt = Sensor::get(SensorType::Clt);
153
154
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1120 times.
1120 if (!clt)
155 return 0; // this error should be already reported somewhere else, let's just handle it
156
157 2240 return interpolate3d(
158 1120 config->ignitionCltCorrTable,
159 1120 config->ignitionCltCorrLoadBins, engineLoad,
160
1/1
✓ Branch 1 taken 1120 times.
1120 config->ignitionCltCorrTempBins, clt.Value
161 1120 );
162 }
163
164 1120 void IgnitionState::updateAdvanceCorrections(float engineLoad) {
165
1/1
✓ Branch 2 taken 1120 times.
1120 cltTimingCorrection = getCltTimingCorrection(engineLoad);
166 1120 }
167
168 961 angle_t getAdvanceCorrections(float engineLoad) {
169
1/1
✓ Branch 2 taken 961 times.
961 auto iat = Sensor::get(SensorType::Iat);
170
171
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 961 times.
961 if (!iat) {
172 engine->ignitionState.timingIatCorrection = 0;
173 } else {
174 1922 engine->ignitionState.timingIatCorrection = interpolate3d(
175 961 config->ignitionIatCorrTable,
176 961 config->ignitionIatCorrLoadBins, engineLoad,
177
1/1
✓ Branch 1 taken 961 times.
961 config->ignitionIatCorrTempBins, iat.Value
178 );
179 }
180
181 #if EFI_IDLE_CONTROL
182 961 float instantRpm = engine->triggerCentral.instantRpm.getInstantRpm();
183
184
2/2
✓ Branch 2 taken 961 times.
✓ Branch 6 taken 961 times.
961 engine->ignitionState.timingPidCorrection = engine->module<IdleController>()->getIdleTimingAdjustment(instantRpm);
185 #endif // EFI_IDLE_CONTROL
186
187
2/2
✓ Branch 2 taken 961 times.
✓ Branch 6 taken 961 times.
961 engine->ignitionState.dfcoTimingRetard = engine->module<DfcoController>()->getTimingRetard();
188
189 #if EFI_TUNER_STUDIO
190 961 engine->outputChannels.multiSparkCounter = engine->engineState.multispark.count;
191 #endif /* EFI_TUNER_STUDIO */
192
193 961 return engine->ignitionState.timingIatCorrection
194 961 + engine->ignitionState.cltTimingCorrection
195 961 + engine->ignitionState.timingPidCorrection
196 1922 - engine->ignitionState.dfcoTimingRetard;
197 }
198
199 /**
200 * @return ignition timing angle advance before TDC for Cranking
201 */
202 130 angle_t getCrankingAdvance(float rpm, float engineLoad) {
203 // get advance from the separate table for Cranking
204
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 130 times.
130 if (engineConfiguration->useSeparateAdvanceForCranking) {
205 return interpolate2d(rpm, config->crankingAdvanceBins, config->crankingAdvance);
206 }
207
208 // Interpolate the cranking timing angle to the earlier running angle for faster engine start
209 130 angle_t crankingToRunningTransitionAngle = getRunningAdvance(engineConfiguration->cranking.rpm, engineLoad);
210 // interpolate not from zero, but starting from min. possible rpm detected
211
4/4
✓ Branch 0 taken 127 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 85 times.
✓ Branch 3 taken 42 times.
130 if (rpm < minCrankingRpm || minCrankingRpm == 0)
212 88 minCrankingRpm = rpm;
213 130 return interpolateClamped(minCrankingRpm, engineConfiguration->crankingTimingAngle, engineConfiguration->cranking.rpm, crankingToRunningTransitionAngle, rpm);
214 }
215 #endif // EFI_ENGINE_CONTROL && EFI_SHAFT_POSITION_INPUT
216
217 1122 angle_t IgnitionState::getAdvance(float rpm, float engineLoad) {
218
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1122 times.
1122 if (std::isnan(engineLoad)) {
219 return 0; // any error should already be reported
220 }
221
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 1089 times.
1122 if (engineConfiguration->timingMode == TM_FIXED) {
222 // fixed timing is the simple: cranking/running does not matter, no corrections!
223 33 return engineConfiguration->fixedTiming;
224 }
225
226 angle_t angle;
227
228 1089 bool isCranking = engine->rpmCalculator.isCranking();
229
2/2
✓ Branch 0 taken 129 times.
✓ Branch 1 taken 960 times.
1089 if (isCranking) {
230 129 angle = getCrankingAdvance(rpm, engineLoad);
231
2/4
✓ Branch 0 taken 129 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 129 times.
129 assertAngleRange(angle, "crAngle", ObdCode::CUSTOM_ERR_ANGLE_CR);
232
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 129 times.
129 efiAssert(ObdCode::CUSTOM_ERR_ASSERT, !std::isnan(angle), "cr_AngleN", 0);
233 } else {
234 960 angle = getRunningAdvance(rpm, engineLoad);
235
236
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 960 times.
960 if (std::isnan(angle)) {
237 warning(ObdCode::CUSTOM_ERR_6610, "NaN angle from table");
238 return 0;
239 }
240 }
241
242 // Allow if we're either not cranking OR allowed to correct in cranking
243
3/4
✓ Branch 0 taken 129 times.
✓ Branch 1 taken 960 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 129 times.
1089 bool allowCorrections = !isCranking || engineConfiguration->useAdvanceCorrectionsForCranking;
244
245
2/2
✓ Branch 0 taken 960 times.
✓ Branch 1 taken 129 times.
1089 if (allowCorrections) {
246 960 angle_t correction = getAdvanceCorrections(engineLoad);
247
1/2
✓ Branch 1 taken 960 times.
✗ Branch 2 not taken.
960 if (!std::isnan(correction)) { // correction could be NaN during settings update
248 960 angle += correction;
249 }
250 }
251
252
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1089 times.
1089 efiAssert(ObdCode::CUSTOM_ERR_ASSERT, !std::isnan(angle), "_AngleN5", 0);
253 1089 return angle;
254 }
255
256 1122 angle_t IgnitionState::getWrappedAdvance(const float rpm, const float engineLoad) {
257
1/1
✓ Branch 2 taken 1122 times.
1122 angle_t angle = getAdvance(rpm, engineLoad) * luaTimingMult + luaTimingAdd;
258
1/1
✓ Branch 1 taken 1122 times.
1122 wrapAngle(angle, "getWrappedAdvance", ObdCode::CUSTOM_ERR_ADCANCE_CALC_ANGLE);
259 1122 return angle;
260 }
261
262 PUBLIC_API_WEAK_SOMETHING_WEIRD
263 4513 angle_t getCylinderIgnitionTrim(size_t cylinderNumber, float rpm, float ignitionLoad) {
264 4513 return IgnitionState::getInterpolatedIgnitionTrim(cylinderNumber, rpm, ignitionLoad);
265 }
266
267 1141 size_t getMultiSparkCount(float rpm) {
268 // Compute multispark (if enabled)
269 2282 if (engineConfiguration->multisparkEnable
270
2/2
✓ Branch 1 taken 11 times.
✓ Branch 2 taken 2 times.
13 && rpm <= engineConfiguration->multisparkMaxRpm
271
5/6
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 1128 times.
✓ Branch 2 taken 11 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11 times.
✓ Branch 5 taken 1130 times.
1154 && engineConfiguration->multisparkMaxExtraSparkCount > 0) {
272 // For zero RPM, disable multispark. We don't yet know the engine speed, so multispark may not be safe.
273
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 10 times.
11 if (rpm == 0) {
274 1 return 0;
275 }
276
277 10 floatus_t multiDelay = 1000.0f * engineConfiguration->multisparkSparkDuration;
278 10 floatus_t multiDwell = 1000.0f * engineConfiguration->multisparkDwell;
279
280 // dwell times are below 10 seconds here so we use 32 bit type for performance reasons
281 10 engine->engineState.multispark.delay = (uint32_t)USF2NT(multiDelay);
282 10 engine->engineState.multispark.dwell = (uint32_t)USF2NT(multiDwell);
283
284 10 constexpr float usPerDegreeAt1Rpm = 60e6 / 360;
285 10 floatus_t usPerDegree = usPerDegreeAt1Rpm / rpm;
286
287 // How long is there for sparks? The user configured an angle, convert to time.
288 10 floatus_t additionalSparksUs = usPerDegree * engineConfiguration->multisparkMaxSparkingAngle;
289 // How long does one spark take?
290 10 floatus_t oneSparkTime = multiDelay + multiDwell;
291
292 // How many sparks can we fit in the alloted time?
293 10 float sparksFitInTime = additionalSparksUs / oneSparkTime;
294
295 // Take the floor (convert to uint8_t) - we want to undershoot, not overshoot
296 10 uint32_t floored = sparksFitInTime;
297
298 // Allow no more than the maximum number of extra sparks
299 10 return minI(floored, engineConfiguration->multisparkMaxExtraSparkCount);
300 } else {
301 1130 return 0;
302 }
303 }
304
305 587 void initIgnitionAdvanceControl() {
306 587 tcTimingDropTable.initTable(engineConfiguration->tractionControlTimingDrop, engineConfiguration->tractionControlSlipBins, engineConfiguration->tractionControlSpeedBins);
307 587 tcSparkSkipTable.initTable(engineConfiguration->tractionControlIgnitionSkip, engineConfiguration->tractionControlSlipBins, engineConfiguration->tractionControlSpeedBins);
308 587 }
309
310 /**
311 * @return Spark dwell time, in milliseconds. 0 if tables are not ready.
312 */
313 1124 floatms_t IgnitionState::getSparkDwell(float rpm, bool isCranking) {
314 float dwellMs;
315
2/2
✓ Branch 0 taken 145 times.
✓ Branch 1 taken 979 times.
1124 if (isCranking) {
316 145 dwellMs = engineConfiguration->ignitionDwellForCrankingMs;
317 } else {
318
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 979 times.
979 efiAssert(ObdCode::CUSTOM_ERR_ASSERT, !std::isnan(rpm), "invalid rpm", NAN);
319
320 979 baseDwell = interpolate2d(rpm, config->sparkDwellRpmBins, config->sparkDwellValues);
321 979 dwellVoltageCorrection = interpolate2d(
322 Sensor::getOrZero(SensorType::BatteryVoltage),
323 979 config->dwellVoltageCorrVoltBins,
324 979 config->dwellVoltageCorrValues
325 );
326
327 // for compat (table full of zeroes)
328
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 979 times.
979 if (dwellVoltageCorrection < 0.1f) {
329 dwellVoltageCorrection = 1;
330 }
331
332 979 dwellMs = baseDwell * dwellVoltageCorrection;
333 }
334
335
3/6
✓ Branch 1 taken 1124 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 1124 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1124 times.
1124 if (std::isnan(dwellMs) || dwellMs <= 0) {
336 // this could happen during engine configuration reset
337 warning(ObdCode::CUSTOM_ERR_DWELL_DURATION, "invalid dwell: %.2f at rpm=%.0f", dwellMs, rpm);
338 return 0;
339 }
340 1124 return dwellMs;
341 }
342
343 1124 void IgnitionState::updateDwell(float rpm, bool isCranking) {
344 1124 sparkDwell = getSparkDwell(rpm, isCranking);
345
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1124 times.
1124 dwellDurationAngle = std::isnan(rpm) ? NAN : getDwell() / getOneDegreeTimeMs(rpm);
346 1124 }
347
348 560916 floatms_t IgnitionState::getDwell() const {
349 560916 return sparkDwell;
350 }
351
352 1120 angle_t IgnitionState::getTrailingSparkAngle(const float rpm, const float engineLoad){
353
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1120 times.
1120 if (std::isnan(engineLoad)) {
354 // default value from: https://github.com/rusefi/rusefi/commit/86683afca22ed1a8af8fd5ac9231442e2124646e#diff-6e80cdd8c55add68105618ad9e8954170a47f59814201dadd2b888509d6b2e39R176
355 return 10;
356 }
357 2240 return interpolate3d(
358 1120 config->trailingSparkTable,
359 1120 config->trailingSparkLoadBins, engineLoad,
360 1120 config->trailingSparkRpmBins, rpm
361 1120 );
362 }
363
364 4513 angle_t IgnitionState::getSparkHardwareLatencyCorrection(){
365 // time => degree
366 4513 angle_t correction = engineConfiguration->sparkHardwareLatencyCorrection / engine->rpmCalculator.oneDegreeUs;
367
368
2/2
✓ Branch 1 taken 1206 times.
✓ Branch 2 taken 3307 times.
4513 if (!std::isnan(correction)) {
369 1206 return correction;
370 }
371 3307 return 0;
372 }
373
374 1103 angle_t IgnitionState::getInterpolatedIgnitionAngle(const float rpm, const float ignitionLoad) {
375 2206 return interpolate3d(
376 1103 config->ignitionTable,
377 1103 config->ignitionLoadBins, ignitionLoad,
378 1103 config->ignitionRpmBins, rpm
379 1103 );
380 }
381
382 4513 angle_t IgnitionState::getInterpolatedIgnitionTrim(
383 const size_t cylinderNumber,
384 const float rpm,
385 const float ignitionLoad
386 ) {
387 9026 return interpolate3d(
388 4513 config->ignTrims[cylinderNumber].table,
389 4513 config->ignTrimLoadBins, ignitionLoad,
390 4513 config->ignTrimRpmBins, rpm
391 4513 );
392 }
393
394 #endif // EFI_ENGINE_CONTROL
395