GCC Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 91.4% 171 / 0 / 187
Functions: 100.0% 17 / 0 / 17
Branches: 79.5% 97 / 0 / 122
Decisions: 86.4% 19 / - / 22

firmware/controllers/algo/ignition/ignition_state.cpp
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 static Map3D<TRACTION_CONTROL_ETB_DROP_SLIP_SIZE, TRACTION_CONTROL_ETB_DROP_SPEED_SIZE, int8_t, uint16_t, uint8_t> tcTimingDropTable{"tct"};
30 static Map3D<TRACTION_CONTROL_ETB_DROP_SLIP_SIZE, TRACTION_CONTROL_ETB_DROP_SPEED_SIZE, int8_t, uint16_t, uint8_t> tcSparkSkipTable{"tcs"};
31
32 #if EFI_ENGINE_CONTROL && EFI_SHAFT_POSITION_INPUT
33
34 /**
35 * @return ignition timing angle advance before TDC
36 */
37 81644 angle_t getRunningAdvance(float rpm, float engineLoad) {
38
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 81642 times.
2/2
✓ Decision 'true' taken 2 times.
✓ Decision 'false' taken 81642 times.
81644 if (std::isnan(engineLoad)) {
39 2 warning(ObdCode::CUSTOM_NAN_ENGINE_LOAD, "NaN engine load");
40 2 return NAN;
41 }
42
43
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 81642 times.
81642 efiAssert(ObdCode::CUSTOM_ERR_ASSERT, !std::isnan(engineLoad), "invalid el", NAN);
44
45 // compute base ignition angle from main table
46 81642 float advanceAngle = IgnitionState::getInterpolatedIgnitionAngle(rpm, engineLoad);
47
48 81642 float vehicleSpeed = Sensor::getOrZero(SensorType::VehicleSpeed);
49 81642 float wheelSlip = Sensor::getOrZero(SensorType::WheelSlipRatio);
50
1/1
✓ Branch 2 taken 81642 times.
81642 engine->ignitionState.tractionAdvanceDrop = tcTimingDropTable.getValue(wheelSlip, vehicleSpeed);
51 81642 engine->engineState.tractionControlSparkSkip = tcSparkSkipTable.getValue(wheelSlip, vehicleSpeed);
52 81642 engine->engineState.updateSparkSkip();
53
54 81642 advanceAngle += engine->ignitionState.tractionAdvanceDrop;
55
56 #if EFI_ANTILAG_SYSTEM
57
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 81642 times.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 81642 times.
81642 if (engine->antilagController.isAntilagCondition) {
58 float throttleIntent = Sensor::getOrZero(SensorType::DriverThrottleIntent);
59 engine->antilagController.timingALSCorrection = interpolate3d(
60 config->ALSTimingRetardTable,
61 config->alsIgnRetardLoadBins, throttleIntent,
62 config->alsIgnRetardrpmBins, rpm
63 );
64 advanceAngle += engine->antilagController.timingALSCorrection;
65 }
66 #endif /* EFI_ANTILAG_SYSTEM */
67
68 // Add any adjustments if configured
69
2/2
✓ Branch 1 taken 326568 times.
✓ Branch 2 taken 81642 times.
2/2
✓ Decision 'true' taken 326568 times.
✓ Decision 'false' taken 81642 times.
408210 for (size_t i = 0; i < efi::size(config->ignBlends); i++) {
70 326568 auto result = calculateBlend(config->ignBlends[i], rpm, engineLoad);
71
72 326568 engine->outputChannels.ignBlendParameter[i] = result.BlendParameter;
73 326568 engine->outputChannels.ignBlendBias[i] = result.Bias;
74 326568 engine->outputChannels.ignBlendOutput[i] = result.Value;
75 326568 engine->outputChannels.ignBlendYAxis[i] = result.TableYAxis;
76
77 326568 advanceAngle += result.Value;
78 }
79
80 // get advance from the separate table for Idle
81 #if EFI_IDLE_CONTROL
82
4/4
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 81635 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 81637 times.
2/2
✓ Decision 'true' taken 5 times.
✓ Decision 'false' taken 81644 times.
81649 if (engineConfiguration->useSeparateAdvanceForIdle &&
83
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())) {
84
1/1
✓ Branch 1 taken 5 times.
5 float idleAdvance = interpolate2d(rpm, config->idleAdvanceBins, config->idleAdvance);
85
86
1/1
✓ Branch 2 taken 5 times.
5 auto tps = Sensor::get(SensorType::DriverThrottleIntent);
87
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) {
88 // interpolate between idle table and normal (running) table using TPS threshold
89 // 0 TPS -> idle table
90 // 1/2 threshold -> idle table
91 // idle threshold -> normal table
92 5 float idleThreshold = engineConfiguration->idlePidDeactivationTpsThreshold;
93
1/1
✓ Branch 1 taken 5 times.
5 advanceAngle = interpolateClamped(idleThreshold / 2, idleAdvance, idleThreshold, advanceAngle, tps.Value);
94 }
95 }
96 #endif
97
98 #if EFI_IDLE_CONTROL
99 // reset ignition table dot, see #8198
100
6/6
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 81635 times.
✓ Branch 5 taken 5 times.
✓ Branch 6 taken 2 times.
✓ Branch 7 taken 5 times.
✓ Branch 8 taken 81637 times.
2/2
✓ Decision 'true' taken 5 times.
✓ Decision 'false' taken 81637 times.
81642 if(engineConfiguration->useSeparateAdvanceForIdle && engine->module<IdleController>()->isIdlingOrTaper()){
101 5 engine->ignitionState.rpmForIgnitionIdleTableDot = rpm;
102 5 engine->ignitionState.rpmForIgnitionTableDot = -1;
103 5 engine->ignitionState.loadForIgnitionTableDot = -1;
104 } else {
105 81637 engine->ignitionState.rpmForIgnitionIdleTableDot = -1;
106 81637 engine->ignitionState.rpmForIgnitionTableDot = rpm;
107 81637 engine->ignitionState.loadForIgnitionTableDot = engineLoad;
108 }
109 #endif
110
111 #if EFI_LAUNCH_CONTROL
112
4/4
✓ Branch 0 taken 692 times.
✓ Branch 1 taken 80950 times.
✓ Branch 2 taken 64 times.
✓ Branch 3 taken 628 times.
2/2
✓ Decision 'true' taken 64 times.
✓ Decision 'false' taken 81578 times.
81642 if (engineConfiguration->launchControlEnabled && engineConfiguration->enableLaunchRetard) {
113 64 const float launchAngle = engineConfiguration->launchTimingRetard;
114
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) {
115 12 const int launchRpm = engineConfiguration->launchRpm;
116 12 const int smoothRetardStartRpm = (launchRpm - engineConfiguration->launchRpmWindow);
117 12 const int smoothRetardEndRpm = (launchRpm - engineConfiguration->launchCorrectionsEndRpm);
118
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) {
119
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)) {
120 // https://github.com/rusefi/rusefi/issues/5611#issuecomment-2130431696
121 4 return interpolateClamped(smoothRetardStartRpm, advanceAngle, smoothRetardEndRpm, launchAngle, rpm);
122 } else {
123 8 return launchAngle;
124 }
125 }
126
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) {
127 10 return launchAngle;
128 }
129 }
130
2/2
✓ Branch 0 taken 533 times.
✓ Branch 1 taken 81087 times.
81620 if (engineConfiguration->torqueReductionEnabled
131
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 522 times.
533 && engine->shiftTorqueReductionController.isFlatShiftConditionSatisfied
132 ) {
133 11 return engine->shiftTorqueReductionController.getTorqueReductionIgnitionRetard();
134 }
135
6/6
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 81597 times.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 8 times.
✓ Branch 6 taken 4 times.
✓ Branch 7 taken 81605 times.
81609 if (engineConfiguration->nitrousControlEnabled && engine->module<NitrousController>()->isNitrousCondition) {
136 4 advanceAngle -= engineConfiguration->nitrousIgnitionRetard;
137 }
138 #endif /* EFI_LAUNCH_CONTROL */
139
140 #ifdef MODULE_VVL_CONTROLLER
141 81609 advanceAngle += engine->module<VvlController>().unmock().getTimingModifier();
142 #endif /* MODULE_VVL_CONTROLLER */
143
144 81609 return advanceAngle;
145 }
146
147 91140 angle_t getCltTimingCorrection(float engineLoad) {
148
1/1
✓ Branch 2 taken 91140 times.
91140 const auto clt = Sensor::get(SensorType::Clt);
149
150
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 91140 times.
91140 if (!clt)
151 return 0; // this error should be already reported somewhere else, let's just handle it
152
153 182280 return interpolate3d(
154 91140 config->ignitionCltCorrTable,
155 91140 config->ignitionCltCorrLoadBins, engineLoad,
156
1/1
✓ Branch 1 taken 91140 times.
91140 config->ignitionCltCorrTempBins, clt.Value
157 91140 );
158 }
159
160 91140 void IgnitionState::updateAdvanceCorrections(float engineLoad) {
161
1/1
✓ Branch 2 taken 91140 times.
91140 cltTimingCorrection = getCltTimingCorrection(engineLoad);
162 91140 }
163
164 57345 angle_t getAdvanceCorrections(float engineLoad) {
165
1/1
✓ Branch 2 taken 57345 times.
57345 auto iat = Sensor::get(SensorType::Iat);
166
167
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 57345 times.
57345 if (!iat) {
168 engine->ignitionState.timingIatCorrection = 0;
169 } else {
170 114690 engine->ignitionState.timingIatCorrection = interpolate3d(
171 57345 config->ignitionIatCorrTable,
172 57345 config->ignitionIatCorrLoadBins, engineLoad,
173
1/1
✓ Branch 1 taken 57345 times.
57345 config->ignitionIatCorrTempBins, iat.Value
174 );
175 }
176
177 #if EFI_IDLE_CONTROL
178 57345 float instantRpm = engine->triggerCentral.instantRpm.getInstantRpm();
179
180
2/2
✓ Branch 2 taken 57345 times.
✓ Branch 6 taken 57345 times.
57345 engine->ignitionState.timingPidCorrection = engine->module<IdleController>()->getIdleTimingAdjustment(instantRpm);
181 #endif // EFI_IDLE_CONTROL
182
183
2/2
✓ Branch 2 taken 57345 times.
✓ Branch 6 taken 57345 times.
57345 engine->ignitionState.dfcoTimingRetard = engine->module<DfcoController>()->getTimingRetard();
184
185 #if EFI_TUNER_STUDIO
186 57345 engine->outputChannels.multiSparkCounter = engine->engineState.multispark.count;
187 #endif /* EFI_TUNER_STUDIO */
188
189 57345 return engine->ignitionState.timingIatCorrection
190 57345 + engine->ignitionState.cltTimingCorrection
191 57345 + engine->ignitionState.timingPidCorrection
192 114690 - engine->ignitionState.dfcoTimingRetard;
193 }
194
195 /**
196 * @return ignition timing angle advance before TDC for Cranking
197 */
198 24285 angle_t getCrankingAdvance(float rpm, float engineLoad) {
199 // get advance from the separate table for Cranking
200
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24285 times.
24285 if (engineConfiguration->useSeparateAdvanceForCranking) {
201 return interpolate2d(rpm, config->crankingAdvanceBins, config->crankingAdvance);
202 }
203
204 // Interpolate the cranking timing angle to the earlier running angle for faster engine start
205 24285 angle_t crankingToRunningTransitionAngle = getRunningAdvance(engineConfiguration->cranking.rpm, engineLoad);
206 // interpolate not from zero, but starting from min. possible rpm detected
207 24285 return interpolateClamped(engine->rpmCalculator.getMinCrankingRpm(), engineConfiguration->crankingTimingAngle, engineConfiguration->cranking.rpm, crankingToRunningTransitionAngle, rpm);
208 }
209 #endif // EFI_ENGINE_CONTROL && EFI_SHAFT_POSITION_INPUT
210
211 91142 angle_t IgnitionState::getAdvance(float rpm, float engineLoad) {
212
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 91142 times.
91142 if (std::isnan(engineLoad)) {
213 return 0; // any error should already be reported
214 }
215
2/2
✓ Branch 0 taken 9515 times.
✓ Branch 1 taken 81627 times.
91142 if (engineConfiguration->timingMode == TM_FIXED) {
216 // fixed timing is the simple: cranking/running does not matter, no corrections!
217 9515 return engineConfiguration->fixedTiming;
218 }
219
220 angle_t angle;
221
222 81627 bool isCranking = engine->rpmCalculator.isCranking();
223
2/2
✓ Branch 0 taken 24283 times.
✓ Branch 1 taken 57344 times.
81627 if (isCranking) {
224 24283 angle = getCrankingAdvance(rpm, engineLoad);
225
2/4
✓ Branch 0 taken 24283 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 24283 times.
24283 assertAngleRange(angle, "crAngle", ObdCode::CUSTOM_ERR_ANGLE_CR);
226
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 24283 times.
24283 efiAssert(ObdCode::CUSTOM_ERR_ASSERT, !std::isnan(angle), "cr_AngleN", 0);
227 } else {
228 57344 angle = getRunningAdvance(rpm, engineLoad);
229
230
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 57344 times.
57344 if (std::isnan(angle)) {
231 warning(ObdCode::CUSTOM_ERR_6610, "NaN angle from table");
232 return 0;
233 }
234 }
235
236 // Allow if we're either not cranking OR allowed to correct in cranking
237
3/4
✓ Branch 0 taken 24283 times.
✓ Branch 1 taken 57344 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 24283 times.
81627 bool allowCorrections = !isCranking || engineConfiguration->useAdvanceCorrectionsForCranking;
238
239
2/2
✓ Branch 0 taken 57344 times.
✓ Branch 1 taken 24283 times.
81627 if (allowCorrections) {
240 57344 angle_t correction = getAdvanceCorrections(engineLoad);
241
1/2
✓ Branch 1 taken 57344 times.
✗ Branch 2 not taken.
57344 if (!std::isnan(correction)) { // correction could be NaN during settings update
242 57344 angle += correction;
243 }
244 }
245
246
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 81627 times.
81627 efiAssert(ObdCode::CUSTOM_ERR_ASSERT, !std::isnan(angle), "_AngleN5", 0);
247 81627 return angle;
248 }
249
250 91142 angle_t IgnitionState::getWrappedAdvance(const float rpm, const float engineLoad) {
251
1/1
✓ Branch 2 taken 91142 times.
91142 angle_t angle = getAdvance(rpm, engineLoad) * luaTimingMult + luaTimingAdd;
252
1/1
✓ Branch 1 taken 91142 times.
91142 wrapAngle(angle, "getWrappedAdvance", ObdCode::CUSTOM_ERR_ADCANCE_CALC_ANGLE);
253 91142 return angle;
254 }
255
256 PUBLIC_API_WEAK_SOMETHING_WEIRD
257 354185 angle_t getCylinderIgnitionTrim(size_t cylinderNumber, float rpm, float ignitionLoad) {
258 354185 return IgnitionState::getInterpolatedIgnitionTrim(cylinderNumber, rpm, ignitionLoad);
259 }
260
261 91161 size_t getMultiSparkCount(float rpm) {
262 // Compute multispark (if enabled)
263 182322 if (engineConfiguration->multisparkEnable
264
2/2
✓ Branch 1 taken 11 times.
✓ Branch 2 taken 2 times.
13 && rpm <= engineConfiguration->multisparkMaxRpm
265
5/6
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 91148 times.
✓ Branch 2 taken 11 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11 times.
✓ Branch 5 taken 91150 times.
91174 && engineConfiguration->multisparkMaxExtraSparkCount > 0) {
266 // For zero RPM, disable multispark. We don't yet know the engine speed, so multispark may not be safe.
267
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 10 times.
11 if (rpm == 0) {
268 1 return 0;
269 }
270
271 10 floatus_t multiDelay = 1000.0f * engineConfiguration->multisparkSparkDuration;
272 10 floatus_t multiDwell = 1000.0f * engineConfiguration->multisparkDwell;
273
274 // dwell times are below 10 seconds here so we use 32 bit type for performance reasons
275 10 engine->engineState.multispark.delay = (uint32_t)USF2NT(multiDelay);
276 10 engine->engineState.multispark.dwell = (uint32_t)USF2NT(multiDwell);
277
278 10 constexpr float usPerDegreeAt1Rpm = 60e6 / 360;
279 10 floatus_t usPerDegree = usPerDegreeAt1Rpm / rpm;
280
281 // How long is there for sparks? The user configured an angle, convert to time.
282 10 floatus_t additionalSparksUs = usPerDegree * engineConfiguration->multisparkMaxSparkingAngle;
283 // How long does one spark take?
284 10 floatus_t oneSparkTime = multiDelay + multiDwell;
285
286 // How many sparks can we fit in the alloted time?
287 10 float sparksFitInTime = additionalSparksUs / oneSparkTime;
288
289 // Take the floor (convert to uint8_t) - we want to undershoot, not overshoot
290 10 uint32_t floored = sparksFitInTime;
291
292 // Allow no more than the maximum number of extra sparks
293 10 return minI(floored, engineConfiguration->multisparkMaxExtraSparkCount);
294 } else {
295 91150 return 0;
296 }
297 }
298
299 607 void initIgnitionAdvanceControl() {
300 607 tcTimingDropTable.initTable(engineConfiguration->tractionControlTimingDrop, engineConfiguration->tractionControlSlipBins, engineConfiguration->tractionControlSpeedBins);
301 607 tcSparkSkipTable.initTable(engineConfiguration->tractionControlIgnitionSkip, engineConfiguration->tractionControlSlipBins, engineConfiguration->tractionControlSpeedBins);
302 607 }
303
304 /**
305 * @return Spark dwell time, in milliseconds. 0 if tables are not ready.
306 */
307 91144 floatms_t IgnitionState::getSparkDwell(float rpm, bool isCranking) {
308 float dwellMs;
309
2/2
✓ Branch 0 taken 29500 times.
✓ Branch 1 taken 61644 times.
91144 if (isCranking) {
310 29500 dwellMs = engineConfiguration->ignitionDwellForCrankingMs;
311 } else {
312
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 61644 times.
61644 efiAssert(ObdCode::CUSTOM_ERR_ASSERT, !std::isnan(rpm), "invalid rpm", NAN);
313
314 61644 baseDwell = interpolate2d(rpm, config->sparkDwellRpmBins, config->sparkDwellValues);
315 61644 dwellVoltageCorrection = interpolate2d(
316 Sensor::getOrZero(SensorType::BatteryVoltage),
317 61644 config->dwellVoltageCorrVoltBins,
318 61644 config->dwellVoltageCorrValues
319 );
320
321 // for compat (table full of zeroes)
322
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 61644 times.
61644 if (dwellVoltageCorrection < 0.1f) {
323 dwellVoltageCorrection = 1;
324 }
325
326 61644 dwellMs = baseDwell * dwellVoltageCorrection;
327 }
328
329
3/6
✓ Branch 1 taken 91144 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 91144 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 91144 times.
91144 if (std::isnan(dwellMs) || dwellMs <= 0) {
330 // this could happen during engine configuration reset
331 warning(ObdCode::CUSTOM_ERR_DWELL_DURATION, "invalid dwell: %.2f at rpm=%.0f", dwellMs, rpm);
332 return 0;
333 }
334 91144 return dwellMs;
335 }
336
337 91144 void IgnitionState::updateDwell(float rpm, bool isCranking) {
338 91144 sparkDwell = getSparkDwell(rpm, isCranking);
339
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 91144 times.
91144 dwellDurationAngle = std::isnan(rpm) ? NAN : getDwell() / getOneDegreeTimeMs(rpm);
340 91144 }
341
342 661708 floatms_t IgnitionState::getDwell() const {
343 661708 return sparkDwell;
344 }
345
346 91140 angle_t IgnitionState::getTrailingSparkAngle(const float rpm, const float engineLoad){
347
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 91140 times.
91140 if (std::isnan(engineLoad)) {
348 // default value from: https://github.com/rusefi/rusefi/commit/86683afca22ed1a8af8fd5ac9231442e2124646e#diff-6e80cdd8c55add68105618ad9e8954170a47f59814201dadd2b888509d6b2e39R176
349 return 10;
350 }
351 182280 return interpolate3d(
352 91140 config->trailingSparkTable,
353 91140 config->trailingSparkLoadBins, engineLoad,
354 91140 config->trailingSparkRpmBins, rpm
355 91140 );
356 }
357
358 354185 angle_t IgnitionState::getSparkHardwareLatencyCorrection(){
359 // time => degree
360 354185 angle_t correction = engineConfiguration->sparkHardwareLatencyCorrection / engine->rpmCalculator.oneDegreeUs;
361
362
2/2
✓ Branch 1 taken 215018 times.
✓ Branch 2 taken 139167 times.
354185 if (!std::isnan(correction)) {
363 215018 return correction;
364 }
365 139167 return 0;
366 }
367
368 81642 angle_t IgnitionState::getInterpolatedIgnitionAngle(const float rpm, const float ignitionLoad) {
369 163284 return interpolate3d(
370 81642 config->ignitionTable,
371 81642 config->ignitionLoadBins, ignitionLoad,
372 81642 config->ignitionRpmBins, rpm
373 81642 );
374 }
375
376 354185 angle_t IgnitionState::getInterpolatedIgnitionTrim(
377 const size_t cylinderNumber,
378 const float rpm,
379 const float ignitionLoad
380 ) {
381 708370 return interpolate3d(
382 354185 config->ignTrims[cylinderNumber].table,
383 354185 config->ignTrimLoadBins, ignitionLoad,
384 354185 config->ignTrimRpmBins, rpm
385 354185 );
386 }
387
388 #endif // EFI_ENGINE_CONTROL
389