GCC Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 80.4% 37 / 0 / 46
Functions: 100.0% 5 / 0 / 5
Branches: 41.2% 7 / 0 / 17
Decisions: 41.2% 7 / - / 17

firmware/controllers/algo/fuel/fuel_computer.cpp
Line Branch Decision Exec Source
1 #include "pch.h"
2
3 #include "engine_configuration.h"
4 #include "sensor.h"
5 #include "error_handling.h"
6 #include "efi_interpolation.h"
7 #include "table_helper.h"
8 #include "fuel_math.h"
9 #include "fuel_computer.h"
10
11 #if EFI_ENGINE_CONTROL
12
13 90822 mass_t FuelComputerBase::getCycleFuel(mass_t airmass, float rpm, float load) {
14 90822 load = getTargetLambdaLoadAxis(load);
15
16 90822 float stoich = getStoichiometricRatio();
17 90822 float lambda = getTargetLambda(rpm, load);
18 90822 float afr = stoich * lambda;
19
20 90822 afrTableYAxis = load;
21 90822 targetLambda = lambda;
22 90822 targetAFR = afr;
23 90822 stoichiometricRatio = stoich;
24
25 90822 return airmass / afr;
26 }
27
28 90827 float FuelComputer::getStoichiometricRatio() const {
29 90827 float primary = engineConfiguration->stoichRatioPrimary;
30
31
32
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 90827 times.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 90827 times.
90827 if (primary < 5) {
33 // Config compatibility: this field may be zero on ECUs with very old defaults
34 criticalError("Please set stoichRatioPrimary");
35 return 0;
36 }
37
38 // Without an ethanol/flex sensor, return primary configured stoich ratio
39
2/2
✓ Branch 1 taken 90822 times.
✓ Branch 2 taken 5 times.
2/2
✓ Decision 'true' taken 90822 times.
✓ Decision 'false' taken 5 times.
90827 if (!Sensor::hasSensor(SensorType::FuelEthanolPercent)) {
40 90822 return primary;
41 }
42
43 5 float secondary = engineConfiguration->stoichRatioSecondary;
44
45
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 5 times.
5 if (secondary < 5) {
46 // Config compatibility: this field may be zero on ECUs with very old defaults
47 criticalError("Please set stoichRatioSecondary");
48 return 0;
49 }
50
51 5 auto flex = Sensor::get(SensorType::FuelEthanolPercent);
52
53 // TODO: what do do if flex sensor fails?
54
55 // Linear interpolate between primary and secondary stoich ratios
56 5 return interpolateClamped(0, primary, 100, secondary, flex.Value);
57 }
58
59
60 90821 float FuelComputer::getTargetLambda(float rpm, float load) const {
61 181642 float target = interpolate3d(
62 90821 config->lambdaTable,
63 90821 config->lambdaLoadBins, load,
64 90821 config->lambdaRpmBins, rpm
65 );
66
67 // Add any blends if configured
68
2/2
✓ Branch 1 taken 181642 times.
✓ Branch 2 taken 90821 times.
2/2
✓ Decision 'true' taken 181642 times.
✓ Decision 'false' taken 90821 times.
272463 for (size_t i = 0; i < efi::size(config->targetAfrBlends); i++) {
69 181642 auto result = calculateBlend(config->targetAfrBlends[i], rpm, load);
70
71 181642 engine->outputChannels.targetAfrBlendParameter[i] = result.BlendParameter;
72 181642 engine->outputChannels.targetAfrBlendBias[i] = result.Bias;
73 181642 engine->outputChannels.targetAfrBlendOutput[i] = result.Value;
74 181642 engine->outputChannels.targetAfrBlendYAxis[i] = result.TableYAxis;
75
76 181642 target += result.Value;
77 }
78
79 90821 return target;
80 }
81
82 90821 float FuelComputer::getTargetLambdaLoadAxis(float defaultLoad) const {
83 90821 return getLoadOverride(defaultLoad, engineConfiguration->afrOverrideMode);
84 }
85
86 181642 float IFuelComputer::getLoadOverride(float defaultLoad, load_override_e overrideMode) const {
87
1/6
✓ Branch 0 taken 181642 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
181642 switch(overrideMode) {
88
1/1
✓ Decision 'true' taken 181642 times.
181642 case AFR_None: return defaultLoad;
89 // MAP default to 200kpa - failed MAP goes rich
90 case AFR_MAP: return Sensor::get(SensorType::Map).value_or(200);
91 // TPS/pedal default to 100% - failed TPS goes rich
92 case AFR_Tps: return Sensor::get(SensorType::Tps1).value_or(100);
93 case AFR_AccPedal: return Sensor::get(SensorType::AcceleratorPedal).value_or(100);
94 case AFR_CylFilling: return normalizedCylinderFilling;
95 default: return 0;
96 }
97 }
98
99 #endif // EFI_ENGINE_CONTROL
100