GCC Code Coverage Report


Directory: ./
File: firmware/controllers/algo/defaults/default_fuel.cpp
Date: 2025-10-03 00:57:22
Coverage Exec Excl Total
Lines: 100.0% 157 0 157
Functions: 100.0% 14 0 14
Branches: 100.0% 12 0 12
Decisions: 100.0% 12 - 12

Line Branch Decision Exec Source
1 #include "pch.h"
2
3 #include "defaults.h"
4 #include "table_helper.h"
5 #include "mazda_miata_vvt.h"
6 #include "engine_configuration_defaults.h"
7
8 1172 static void setBosch02880155868(injector_s& cfg) {
9 // http://www.boschdealer.com/specsheets/0280155868cs.jpg (use web.archive.org)
10 #if (VBAT_INJECTOR_CURVE_PRESSURE_SIZE == 2) && (VBAT_INJECTOR_CURVE_SIZE == 8)
11 // see https://github.com/rusefi/rusefi/issues/7521 for adding more values
12 1172 copyTable(cfg.battLagCorrTable, engine_configuration_defaults::INJECTOR_BATT_LAG_CURR);
13 #endif
14
15 #if (VBAT_INJECTOR_CURVE_SIZE == 8)
16 static const float vBattBins[8] = { 6.0, 8.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0 };
17 1172 copyArray(cfg.battLagCorrBattBins, vBattBins);
18 #else
19 setLinearCurve(cfg.battLagCorrBattBins, 6, 15, 0.1);
20 #endif
21
22 #if (VBAT_INJECTOR_CURVE_PRESSURE_SIZE == 2)
23 static const float pressureBins[2] = { 206.843, 413.685 };
24 1172 copyArray(cfg.battLagCorrPressBins,pressureBins);
25 #else
26 setLinearCurve(cfg.battLagCorrPressBins, 300, 400, 1);
27 #endif
28
29 1172 }
30
31 586 static void setDefaultWarmupFuelEnrichment() {
32 #if CLT_CURVE_SIZE == 16
33 static const float bins[] =
34 {
35 -40,
36 -30,
37 -20,
38 -10,
39 0,
40 10,
41 20,
42 30,
43 40,
44 50,
45 60,
46 70,
47 80,
48 90,
49 100,
50 110
51 };
52
53 586 copyArray(config->cltFuelCorrBins, bins);
54
55 static const float values[] =
56 {
57 1.50,
58 1.50,
59 1.42,
60 1.36,
61 1.28,
62 1.19,
63 1.12,
64 1.10,
65 1.06,
66 1.06,
67 1.03,
68 1.01,
69 1,
70 1,
71 1,
72 1
73 };
74
75 586 copyArray(config->cltFuelCorr, values);
76 #endif // CLT_CURVE_SIZE
77 586 }
78
79 586 static void setDefaultVETable() {
80 586 setRpmTableBin(config->veRpmBins);
81 #if (VE_LOAD_COUNT == 16) && (VE_RPM_COUNT == 16)
82 static const float hardCodedveTable[16][16] = {
83 {49.300, 49.300, 49.400, 49.600, 50.200, 51.400, 52.600, 53.800, 54.400, 54.600, 54.400, 53.700, 52.800, 51.800, 50.900, 50.000, },
84 {49.600, 50.500, 51.500, 54.100, 57.500, 60.700, 62.900, 64.400, 65.000, 65.000, 64.500, 63.500, 62.300, 61.100, 60.000, 58.800, },
85 {50.300, 52.400, 54.300, 58.500, 62.700, 66.100, 68.200, 69.700, 70.200, 70.100, 69.500, 68.400, 67.100, 65.800, 64.500, 63.300, },
86 {51.400, 55.200, 58.200, 63.500, 68.000, 71.400, 73.500, 74.900, 75.300, 75.200, 74.500, 73.300, 71.800, 70.400, 69.000, 67.700, },
87 {54.300, 60.900, 64.900, 70.700, 75.100, 78.300, 80.300, 81.700, 82.100, 81.900, 81.100, 79.700, 78.100, 76.500, 75.000, 73.500, },
88 {56.400, 64.400, 68.700, 74.500, 78.700, 81.800, 83.800, 85.100, 85.500, 85.300, 84.400, 83.000, 81.300, 79.600, 78.000, 76.400, },
89 {60.700, 70.200, 74.500, 79.900, 83.800, 86.800, 88.900, 90.200, 90.600, 90.300, 89.400, 87.800, 86.000, 84.200, 82.500, 80.800, },
90 {65.800, 76.000, 80.000, 85.000, 88.800, 91.800, 93.900, 95.200, 95.600, 95.300, 94.300, 92.600, 90.700, 88.800, 87.000, 85.200, },
91 {69.400, 79.100, 82.900, 87.800, 91.700, 94.800, 97.000, 98.300, 98.800, 98.400, 97.400, 95.600, 93.500, 91.500, 89.600, 87.700, },
92 {73.000, 82.200, 85.900, 90.700, 94.600, 97.800, 100.000, 101.500, 101.900, 101.600, 100.400, 98.500, 96.400, 94.200, 92.200, 90.200, },
93 {76.600, 85.300, 88.800, 93.500, 97.400, 100.700, 103.100, 104.600, 105.100, 104.700, 103.500, 101.500, 99.200, 96.900, 94.800, 92.600, },
94 {80.300, 88.500, 91.800, 96.400, 100.300, 103.700, 106.200, 107.800, 108.200, 107.800, 106.500, 104.400, 102.000, 99.700, 97.400, 95.100, },
95 {83.900, 91.600, 94.700, 99.200, 103.200, 106.700, 109.200, 110.900, 111.400, 110.900, 109.600, 107.400, 104.800, 102.400, 99.900, 97.600, },
96 {87.500, 94.700, 97.600, 102.000, 106.100, 109.700, 112.300, 114.000, 114.500, 114.100, 112.600, 110.300, 107.700, 105.100, 102.500, 100.100, },
97 {91.100, 97.800, 100.600, 104.900, 108.900, 112.600, 115.300, 117.200, 117.700, 117.200, 115.700, 113.300, 110.500, 107.800, 105.100, 102.500, },
98 {94.700, 100.900, 103.500, 107.700, 111.800, 115.600, 118.400, 120.300, 120.800, 120.300, 118.700, 116.200, 113.300, 110.500, 107.700, 105.000, },
99 };
100 586 copyTable(config->veTable, hardCodedveTable);
101 #else
102 setTable(config->veTable, 80);
103 #endif
104
105 586 setRpmTableBin(config->baroCorrRpmBins);
106 586 setLinearCurve(config->baroCorrPressureBins, 75, 105, 1);
107
108 586 setLinearCurve(config->tmfRatioBins, 0.5, 1.5, 0.1);
109
110 // Default baro table is all 1.0, we can't recommend a reasonable default here
111 586 setTable(config->baroCorrTable, 1);
112
113 // Give default axes for cylinder trim tables
114 #if FUEL_TRIM_SIZE == 4
115 586 copyArray(config->fuelTrimRpmBins, { 1000, 3000, 5000, 7000 });
116 586 copyArray(config->fuelTrimLoadBins, { 20, 50, 80, 100 });
117 #else
118 setRpmTableBin(config->fuelTrimRpmBins);
119 setLinearCurve(config->fuelTrimLoadBins, 20, 100);
120 #endif
121
122 // Default axes for VE blends
123
2/2
✓ Branch 1 taken 2344 times.
✓ Branch 2 taken 586 times.
2/2
✓ Decision 'true' taken 2344 times.
✓ Decision 'false' taken 586 times.
2930 for (size_t i = 0; i < efi::size(config->veBlends); i++) {
124 2344 auto& blend = config->veBlends[i];
125 2344 setLinearCurve(blend.loadBins, 0, 100, 10);
126 2344 setLinearCurve(blend.rpmBins, 0, 7000);
127
128 2344 setLinearCurve(blend.blendBins, 0, 100);
129 2344 setLinearCurve(blend.blendValues, 0, 100);
130 }
131
132
2/2
✓ Branch 1 taken 1172 times.
✓ Branch 2 taken 586 times.
2/2
✓ Decision 'true' taken 1172 times.
✓ Decision 'false' taken 586 times.
1758 for (size_t i = 0; i < efi::size(config->targetAfrBlends); i++) {
133 1172 auto& blend = config->targetAfrBlends[i];
134 1172 setLinearCurve(blend.rpmBins, 0, 7000);
135
136 1172 setLinearCurve(blend.blendBins, 0, 100);
137 1172 setLinearCurve(blend.blendValues, 0, 100);
138 }
139 586 }
140
141 586 static void setDefaultFuelCutParameters() {
142 586 engineConfiguration->coastingFuelCutEnabled = false;
143 586 engineConfiguration->coastingFuelCutRpmLow = 1300;
144 586 engineConfiguration->coastingFuelCutRpmHigh = 1500;
145 586 engineConfiguration->coastingFuelCutTps = 2;
146 586 engineConfiguration->coastingFuelCutMap = 30;
147 586 engineConfiguration->coastingFuelCutClt = 60;
148 586 }
149
150 586 static void setDefaultStftSettings() {
151 586 auto& cfg = engineConfiguration->stft;
152
153 // Default to disabled
154 586 engineConfiguration->fuelClosedLoopCorrectionEnabled = false;
155
156 // Default to proportional mode (for wideband sensors)
157 586 engineConfiguration->stftIgnoreErrorMagnitude = false;
158
159 // Also used in lambda monitor
160 586 engineConfiguration->noFuelTrimAfterDfcoTime = 5;
161
162 // 60 second startup delay - some O2 sensors are slow to warm up.
163 586 cfg.startupDelay = 60;
164
165 // Only correct in [12.0, 17.0]
166 586 cfg.minAfr = 12;
167 586 cfg.maxAfr = 17;
168
169 // Above 60 deg C
170 586 cfg.minClt = 60;
171
172 // 0.5% deadband
173 586 cfg.deadband = 0.5f;
174
175 // Sensible region defaults
176 586 cfg.maxIdleRegionRpm = 1000;
177 586 cfg.maxOverrunLoad = 35;
178 586 cfg.minPowerLoad = 85;
179
180 // Sensible cell defaults
181
2/2
✓ Branch 1 taken 2344 times.
✓ Branch 2 taken 586 times.
2/2
✓ Decision 'true' taken 2344 times.
✓ Decision 'false' taken 586 times.
2930 for (size_t i = 0; i < efi::size(cfg.cellCfgs); i++) {
182 // 30 second time constant - nice and slow
183 2344 cfg.cellCfgs[i].timeConstant = 30;
184
185 /// Allow +-5%
186 2344 cfg.cellCfgs[i].maxAdd = 5;
187 2344 cfg.cellCfgs[i].maxRemove = 5;
188 }
189 586 }
190
191 586 static void setDefaultLtftSettings() {
192 586 auto& cfg = engineConfiguration->ltft;
193
194 // Default to allow learning, but do not apply learned corrections
195 586 cfg.enabled = true;
196 586 cfg.correctionEnabled = false;
197
198 // Default to very slow learning
199 586 cfg.timeConstant = 3000;
200
201 // 0.5% deadband
202 586 cfg.deadband = 0.5f;
203
204 // Allow +-12.5%
205 586 cfg.maxAdd = 12.5;
206 586 cfg.maxRemove = 12.5;
207 586 }
208
209 static const uint8_t tpsTpsTable[TPS_TPS_ACCEL_TABLE][TPS_TPS_ACCEL_TABLE] = {
210 /* Generated by TS2C on Tue Apr 18 21:29:16 EDT 2017*/
211 {/* 0 0 *//* 0 0.0*/0, /* 1 10.0*/0, /* 2 20.0*/0, /* 3 35.0*/0, /* 4 50.0*/0, /* 5 65.0*/0, /* 6 80.0*/0, /* 7 100.0*/0, },
212 {/* 1 10 *//* 0 0.0*/10, /* 1 10.0*/0, /* 2 20.0*/0, /* 3 35.0*/0, /* 4 50.0*/0, /* 5 65.0*/0, /* 6 80.0*/0, /* 7 100.0*/0, },
213 {/* 2 20 *//* 0 0.0*/17, /* 1 10.0*/10, /* 2 20.0*/0, /* 3 35.0*/0, /* 4 50.0*/0, /* 5 65.0*/0, /* 6 80.0*/0, /* 7 100.0*/0, },
214 {/* 3 35 *//* 0 0.0*/23, /* 1 10.0*/17, /* 2 20.0*/10, /* 3 35.0*/0, /* 4 50.0*/0, /* 5 65.0*/0, /* 6 80.0*/0, /* 7 100.0*/0, },
215 {/* 4 50 *//* 0 0.0*/28, /* 1 10.0*/23, /* 2 20.0*/17, /* 3 35.0*/10, /* 4 50.0*/0, /* 5 65.0*/0, /* 6 80.0*/0, /* 7 100.0*/0, },
216 {/* 5 65 *//* 0 0.0*/32, /* 1 10.0*/28, /* 2 20.0*/23, /* 3 35.0*/17, /* 4 50.0*/10, /* 5 65.0*/0, /* 6 80.0*/0, /* 7 100.0*/0, },
217 {/* 6 80 *//* 0 0.0*/35, /* 1 10.0*/32, /* 2 20.0*/28, /* 3 35.0*/23, /* 4 50.0*/17, /* 5 65.0*/10, /* 6 80.0*/0, /* 7 100.0*/0, },
218 {/* 7 100 *//* 0 0.0*/37, /* 1 10.0*/35, /* 2 20.0*/32, /* 3 35.0*/28, /* 4 50.0*/23, /* 5 65.0*/17, /* 6 80.0*/10, /* 7 100.0*/0, },
219 };
220
221 586 static void setMazdaMiataNbTpsTps() {
222 586 setLinearCurve(config->tpsTpsAccelFromRpmBins, 0, 100, 10);
223 586 setLinearCurve(config->tpsTpsAccelToRpmBins, 0, 100, 10);
224 586 copyTable(config->tpsTpsAccelTable, tpsTpsTable);
225 586 }
226
227 586 static void setDefaultLambdaTable() {
228 586 setRpmTableBin(config->lambdaRpmBins);
229
230 #if (FUEL_LOAD_COUNT == 16) && (FUEL_RPM_COUNT == 16)
231 586 copyArray(config->lambdaLoadBins, engine_configuration_defaults::DEFAULT_LAMBDA_LOAD_BINS);
232
233 // Set each row to the corresponding value from rowValues
234
2/2
✓ Branch 1 taken 9376 times.
✓ Branch 2 taken 586 times.
2/2
✓ Decision 'true' taken 9376 times.
✓ Decision 'false' taken 586 times.
9962 for (size_t i = 0; i < efi::size(config->lambdaTable); i++) {
235
2/2
✓ Branch 2 taken 150016 times.
✓ Branch 3 taken 9376 times.
2/2
✓ Decision 'true' taken 150016 times.
✓ Decision 'false' taken 9376 times.
159392 for (size_t j = 0; j < efi::size(config->lambdaTable[i]); j++) {
236 150016 config->lambdaTable[i][j] = engine_configuration_defaults::DEFAULT_LAMBDA_TABLE_ROW[i];
237 }
238 }
239 #endif
240 586 }
241
242 1 void setGdiWallWetting() {
243 1 engineConfiguration->wwaeTau = 0;
244 1 engineConfiguration->wwaeBeta = 0;
245 1 }
246
247 586 void setDefaultWallWetting() {
248 #if !EFI_UNIT_TEST
249 // todo: this is a reasonable default for what kinds of engines exactly?
250 engineConfiguration->wwaeTau = 0.3;
251 engineConfiguration->wwaeBeta = 0.3;
252 #endif // EFI_UNIT_TEST
253
254 // linear reasonable bins
255 586 setLinearCurve(config->wwCltBins, -40, 100, 1);
256 586 setLinearCurve(config->wwMapBins, 10, 80, 1);
257
258 // These values are derived from the GM factory tune for a gen3 LS engine
259 // Who knows if they're good for anything else, but at least they look nice?
260 static constexpr float tauClt[] = {
261 1.45, 1.30, 1.17, 1.05, 0.90, 0.82, 0.75, 0.70
262 };
263 586 copyArray(config->wwTauCltValues, tauClt);
264
265 static constexpr float tauMap[] = {
266 0.38, 0.55, 0.69, 0.86, 0.90, 0.95, 0.97, 1.00
267 };
268 586 copyArray(config->wwTauMapValues, tauMap);
269
270 static constexpr float betaClt[] = {
271 0.73, 0.66, 0.57, 0.46, 0.38, 0.31, 0.24, 0.19
272 };
273 586 copyArray(config->wwBetaCltValues, betaClt);
274
275 static constexpr float betaMap[] = {
276 0.21, 0.40, 0.60, 0.79, 0.85, 0.90, 0.95, 1.00
277 };
278 586 copyArray(config->wwBetaMapValues, betaMap);
279 586 }
280
281 586 static void setDefaultWboSettings() {
282
2/2
✓ Branch 0 taken 1172 times.
✓ Branch 1 taken 586 times.
2/2
✓ Decision 'true' taken 1172 times.
✓ Decision 'false' taken 586 times.
1758 for (size_t i = 0; i < CAN_WBO_COUNT; i++) {
283 1172 engineConfiguration->canWbo[i].type = RUSEFI;
284 1172 engineConfiguration->canWbo[i].reId = static_cast<can_wbo_re_id_e>(i);
285 1172 engineConfiguration->canWbo[i].aemId = static_cast<can_wbo_aem_id_e>(i);
286 }
287 586 }
288
289 586 static void setDefaultLambdaProtection() {
290 586 engineConfiguration->lambdaProtectionEnable = false;
291
292 586 engineConfiguration->lambdaProtectionMinLoad = 60;
293 586 engineConfiguration->lambdaProtectionMinRpm = 2500;
294 586 engineConfiguration->lambdaProtectionMinTps = 50;
295 586 engineConfiguration->lambdaProtectionTimeout = 0.5f;
296
297 586 engineConfiguration->lambdaProtectionRestoreLoad = 30;
298 586 engineConfiguration->lambdaProtectionRestoreRpm = 2000;
299 586 engineConfiguration->lambdaProtectionRestoreTps = 20;
300 586 }
301
302 586 static void setDefaultPriming() {
303 // These defaults are reasonable for ~500cc cylinders
304 static constexpr int8_t primeBins[] = { -40, -20, 0, 20, 40, 60, 80, 100 };
305 static constexpr uint16_t primeValues[] = { 755, 605, 265, 140, 75, 50, 45, 40 };
306
307 586 copyArray(engineConfiguration->primeBins, primeBins);
308 586 copyArray(engineConfiguration->primeValues, primeValues);
309 586 }
310
311 586 void setDefaultFuel() {
312 // Base injection configuration
313 586 engineConfiguration->isInjectionEnabled = true;
314 586 engineConfiguration->injectionMode = IM_SEQUENTIAL;
315
316 /**
317 * By the way http://users.erols.com/srweiss/tableifc.htm has a LOT of data
318 */
319 586 engineConfiguration->injector.flow = 200;
320 586 engineConfiguration->injectorSecondary.flow = 200;
321 586 engineConfiguration->stoichRatioPrimary = STOICH_RATIO;
322
323 // 9.0 = E100 pure ethanol
324 586 engineConfiguration->stoichRatioSecondary = 9.0f;
325
326 // Injector deadtime
327 586 setBosch02880155868(engineConfiguration->injector);
328 586 setBosch02880155868(engineConfiguration->injectorSecondary);
329
330 // Tables
331 586 setFuelTablesLoadBin(10, 160);
332 586 setRpmTableBin(config->injPhaseRpmBins);
333
334 586 setRpmTableBin(config->tpsTspCorrValuesBins);
335 586 setLinearCurve(config->tpsTspCorrValues, 1, 1);
336
337 586 setRpmTableBin(config->predictiveMapBlendDurationBins);
338 586 setLinearCurve(config->predictiveMapBlendDurationValues, 1, 1);
339
340 586 setDefaultVETable();
341 586 setDefaultLambdaTable();
342
343 586 setLinearCurve(config->injectorStagingLoadBins, 0, 100, 10);
344 586 setRpmTableBin(config->injectorStagingRpmBins);
345
346 586 setRpmTableBin(config->mapEstimateRpmBins);
347 586 setLinearCurve(config->mapEstimateTpsBins, 0, 100);
348 586 setTable(config->mapEstimateTable, 60);
349
350 586 setTable(config->injectionPhase, PORT_INJECTION_OFFSET);
351
352 // Charge temperature estimation
353 586 engineConfiguration->tChargeMinRpmMinTps = 0.25;
354 586 engineConfiguration->tChargeMinRpmMaxTps = 0.25;
355 586 engineConfiguration->tChargeMaxRpmMinTps = 0.25;
356 586 engineConfiguration->tChargeMaxRpmMaxTps = 0.9;
357 586 engineConfiguration->tChargeMode = TCHARGE_MODE_RPM_TPS;
358 586 engineConfiguration->tChargeAirCoefMin = 0.098f;
359 586 engineConfiguration->tChargeAirCoefMax = 0.902f;
360 586 engineConfiguration->tChargeAirFlowMax = 153.6f;
361 586 engineConfiguration->tChargeAirIncrLimit = 1.0f;
362 586 engineConfiguration->tChargeAirDecrLimit = 12.5f;
363
364 // CLT correction table
365 586 setDefaultWarmupFuelEnrichment();
366
367 // IAT correction table
368 // TODO
369
370 // Closed loop fuel correction
371 586 setDefaultStftSettings();
372 586 setDefaultLtftSettings();
373
374 // Decel fuel cut
375 586 setDefaultFuelCutParameters();
376
377 586 engineConfiguration->tpsAccelEnrichmentThreshold = 40; // TPS % change, per engine cycle
378
379 586 setDefaultWallWetting();
380
381 // TPS/TPS AE curve
382 586 setMazdaMiataNbTpsTps();
383
384 // Some reasonable reference pressure that many vehicles use
385 586 engineConfiguration->fuelReferencePressure = 300;
386
387 586 setDefaultWboSettings();
388
389 // Lambda protection defaults
390 586 setDefaultLambdaProtection();
391
392 586 setDefaultPriming();
393
394 // Cut at 110% instantly
395 586 engineConfiguration->maxInjectorDutyInstant = 110;
396 // Cut at 96% after 0.5 second
397 586 engineConfiguration->maxInjectorDutySustained = 96;
398 586 engineConfiguration->maxInjectorDutySustainedTimeout = 0.5f;
399 586 }
400