Line | Branch | Decision | Exec | Source |
---|---|---|---|---|
1 | // Deceleration Fuel Cut-off | |||
2 | ||||
3 | #include "pch.h" | |||
4 | ||||
5 | #include "dfco.h" | |||
6 | #include "closed_loop_fuel.h" | |||
7 | ||||
8 | 1120 | bool DfcoController::getState() const { | ||
9 |
2/2✓ Branch 0 taken 1103 times.
✓ Branch 1 taken 17 times.
|
2/2✓ Decision 'true' taken 1103 times.
✓ Decision 'false' taken 17 times.
|
1120 | if (!engineConfiguration->coastingFuelCutEnabled) { |
10 | 1103 | return false; | ||
11 | } | |||
12 | ||||
13 |
2/3✓ Branch 1 taken 17 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 17 times.
|
1/2✗ Decision 'true' not taken.
✓ Decision 'false' taken 17 times.
|
17 | if (checkIfTuningVeNow()) { |
14 | ✗ | return false; | ||
15 | } | |||
16 | ||||
17 |
1/1✓ Branch 2 taken 17 times.
|
17 | const auto tps = Sensor::get(SensorType::DriverThrottleIntent); | |
18 |
1/1✓ Branch 2 taken 17 times.
|
17 | const auto clt = Sensor::get(SensorType::Clt); | |
19 |
1/1✓ Branch 2 taken 17 times.
|
17 | const auto map = Sensor::get(SensorType::Map); | |
20 | ||||
21 | // If some sensor is broken, inhibit DFCO | |||
22 |
3/6✓ Branch 1 taken 17 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 17 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 17 times.
|
1/2✗ Decision 'true' not taken.
✓ Decision 'false' taken 17 times.
|
17 | if (!tps || !clt) { |
23 | ✗ | return false; | ||
24 | } | |||
25 | ||||
26 | // MAP sensor is optional, only inhibit if the sensor is present but broken | |||
27 |
1/1✓ Branch 1 taken 17 times.
|
17 | bool hasMap = Sensor::hasSensor(SensorType::Map); | |
28 |
3/6✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 17 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 17 times.
|
1/2✗ Decision 'true' not taken.
✓ Decision 'false' taken 17 times.
|
17 | if (hasMap && !map) { |
29 | ✗ | return false; | ||
30 | } | |||
31 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
|
1/2✗ Decision 'true' not taken.
✓ Decision 'false' taken 17 times.
|
17 | if (engine->engineState.lua.disableDecelerationFuelCutOff) { |
32 | // Lua might have reasons to disable | |||
33 | ✗ | return false; | ||
34 | } | |||
35 | ||||
36 |
1/1✓ Branch 1 taken 17 times.
|
17 | float rpm = Sensor::getOrZero(SensorType::Rpm); | |
37 |
1/1✓ Branch 1 taken 17 times.
|
17 | float vss = Sensor::getOrZero(SensorType::VehicleSpeed); | |
38 | ||||
39 |
3/5✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
✓ Branch 4 taken 17 times.
✓ Branch 6 taken 17 times.
✗ Branch 7 not taken.
|
17 | bool mapActivate = !hasMap || !m_mapHysteresis.test(map.value_or(0), engineConfiguration->coastingFuelCutMap + 1, engineConfiguration->coastingFuelCutMap - 1); | |
40 | 17 | bool tpsActivate = tps.Value < engineConfiguration->coastingFuelCutTps; | ||
41 | 17 | bool cltActivate = clt.Value > engineConfiguration->coastingFuelCutClt; | ||
42 | // True if throttle, MAP, and CLT are all acceptable for DFCO to occur | |||
43 |
5/6✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 13 times.
✓ Branch 5 taken 1 time.
|
17 | bool dfcoAllowed = mapActivate && tpsActivate && cltActivate; | |
44 | ||||
45 | 17 | bool rpmActivate = (rpm > engineConfiguration->coastingFuelCutRpmHigh); | ||
46 | 17 | bool rpmDeactivate = (rpm < engineConfiguration->coastingFuelCutRpmLow); | ||
47 | ||||
48 | // greater than or equal so that it works if both config params are set to 0 | |||
49 | 17 | bool vssActivate = (vss >= engineConfiguration->coastingFuelCutVssHigh); | ||
50 | 17 | bool vssDeactivate = (vss < engineConfiguration->coastingFuelCutVssLow); | ||
51 | ||||
52 | // RPM is high enough, VSS high enough, and DFCO allowed | |||
53 |
6/6✓ Branch 0 taken 13 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 7 times.
✓ Branch 5 taken 3 times.
|
2/2✓ Decision 'true' taken 7 times.
✓ Decision 'false' taken 10 times.
|
17 | if (dfcoAllowed && rpmActivate && vssActivate) { |
54 | 7 | return true; | ||
55 | } | |||
56 | ||||
57 | // RPM too low, VSS too low, or DFCO not allowed | |||
58 |
6/6✓ Branch 0 taken 6 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 1 time.
✓ Branch 4 taken 1 time.
✓ Branch 5 taken 4 times.
|
2/2✓ Decision 'true' taken 6 times.
✓ Decision 'false' taken 4 times.
|
10 | if (!dfcoAllowed || rpmDeactivate || vssDeactivate) { |
59 | 6 | return false; | ||
60 | } | |||
61 | ||||
62 | // No conditions hit, no change to state (provides hysteresis) | |||
63 | 4 | return m_isDfco; | ||
64 | } | |||
65 | ||||
66 | 1120 | void DfcoController::update() { | ||
67 | // Run state machine | |||
68 | 1120 | bool newState = getState(); | ||
69 | ||||
70 | // If fuel is cut, reset the timer | |||
71 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 1112 times.
|
2/2✓ Decision 'true' taken 8 times.
✓ Decision 'false' taken 1112 times.
|
1120 | if (newState) { |
72 | 8 | m_timeSinceCut.reset(); | ||
73 | } else { | |||
74 | // If fuel is not cut, reset the not-cut timer | |||
75 | 1112 | m_timeSinceNoCut.reset(); | ||
76 | } | |||
77 | ||||
78 | 1120 | m_isDfco = newState; | ||
79 | 1120 | } | ||
80 | ||||
81 | 524079 | bool DfcoController::cutFuel() const { | ||
82 | 524079 | float cutDelay = engineConfiguration->dfcoDelay; | ||
83 | ||||
84 | // 0 delay means cut immediately, aka timer has always expired | |||
85 |
4/4✓ Branch 0 taken 5 times.
✓ Branch 1 taken 524074 times.
✓ Branch 3 taken 1 time.
✓ Branch 4 taken 4 times.
|
524079 | bool hasBeenDelay = (cutDelay == 0) || m_timeSinceNoCut.hasElapsedSec(cutDelay); | |
86 | ||||
87 |
4/4✓ Branch 0 taken 8 times.
✓ Branch 1 taken 524071 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 2 times.
|
524079 | return m_isDfco && hasBeenDelay; | |
88 | } | |||
89 | ||||
90 | 1 | float DfcoController::getTimeSinceCut() const { | ||
91 | 1 | return m_timeSinceCut.getElapsedSeconds(); | ||
92 | } | |||
93 | ||||
94 | 961 | float DfcoController::getTimingRetard() const { | ||
95 | 961 | float cutTiming = clampF(0, engineConfiguration->dfcoRetardDeg, 30); | ||
96 | ||||
97 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 953 times.
|
2/2✓ Decision 'true' taken 8 times.
✓ Decision 'false' taken 953 times.
|
961 | if (m_isDfco) { |
98 | // While cut, always retard timing | |||
99 | 8 | return cutTiming; | ||
100 | } else { | |||
101 | 953 | float timeSinceCut = m_timeSinceCut.getElapsedSeconds(); | ||
102 | 953 | float rampInTime = engineConfiguration->dfcoRetardRampInTime; | ||
103 | ||||
104 |
2/2✓ Branch 0 taken 946 times.
✓ Branch 1 taken 7 times.
|
2/2✓ Decision 'true' taken 946 times.
✓ Decision 'false' taken 7 times.
|
953 | if (timeSinceCut > rampInTime) { |
105 | // Normal operation, no retard | |||
106 | 946 | return 0; | ||
107 | } else { | |||
108 | 7 | return interpolateClamped(0, cutTiming, 0.5, 0, timeSinceCut); | ||
109 | } | |||
110 | } | |||
111 | } | |||
112 |