GCC Code Coverage Report


Directory: ./
File: firmware/controllers/limp_manager.h
Date: 2025-10-03 00:57:22
Coverage Exec Excl Total
Lines: 100.0% 14 0 14
Functions: 100.0% 5 0 5
Branches: 75.0% 3 0 4
Decisions: 75.0% 3 - 4

Line Branch Decision Exec Source
1 #pragma once
2
3 #include "shutdown_controller.h"
4 #include "max_limit_with_hysteresis.h"
5
6 #include <cstdint>
7
8 // Keep this list in sync with fuelIgnCutCodeList in tunerstudio.template.ini!
9 enum class ClearReason : uint8_t {
10 None, // 0
11 Fatal, // 1
12 Settings, // 2
13 HardLimit, // 3
14 EtbFaultRevLimit, // 4 means 1500 RPM limit in case of ETB fault
15 BoostCut, // 5
16 OilPressure, // 6
17 StopRequested, // 7
18 EtbProblem, // 8
19 LaunchCut, // 9
20 InjectorDutyCycle, // 10
21 FloodClear, // 11
22 EnginePhase, // 12
23 KickStart, // 13
24 IgnitionOff, // 14
25 Lua, // 15
26 ACR, // 16 - Harley Automatic Compression Release
27 LambdaProtection, // 17
28 GdiComms, // 18
29 PleaseBrake, // 19
30 FatalErrorRevLimit, // 20
31 GdiLimits, // 21
32 GdiPumpLimit, // 22
33
34 // Keep this list in sync with fuelIgnCutCodeList in tunerstudio.template.ini!
35 // todo: add a code generator between ClearReason and fuelIgnCutCodeList in tunerstudio.template.ini
36 };
37
38 enum class EtbStatus : uint8_t {
39 None, // 0
40 EngineStopped, // 1
41 TpsError, // 2
42 PpsError, // 3
43 IntermittentTps, // 4
44 AutoTune, // 5
45 Lua, // 6
46 AutoCalibrate, // 7
47 NotConfigured, // 8
48 Redundancy, // 9
49 IntermittentPps, // 10
50 JamDetected, // 11
51 // keep this list in sync with etbCutCodeList in tunerstudio.template.ini!
52 };
53
54 // Only allows clearing the value, but never resetting it.
55 class Clearable {
56 public:
57 2752 Clearable() : m_value(true) {}
58 3706 Clearable(bool value) : m_value(value) {
59
2/2
✓ Branch 0 taken 107 times.
✓ Branch 1 taken 3599 times.
2/2
✓ Decision 'true' taken 107 times.
✓ Decision 'false' taken 3599 times.
3706 if (!m_value) {
60 107 clearReason = ClearReason::Settings;
61 }
62 3706 }
63
64 112 void clear(ClearReason p_clearReason) {
65
1/2
✓ Branch 0 taken 112 times.
✗ Branch 1 not taken.
1/2
✓ Decision 'true' taken 112 times.
✗ Decision 'false' not taken.
112 if (m_value) {
66 112 m_value = false;
67 112 clearReason = p_clearReason;
68 }
69 112 }
70
71 193388 operator bool() const {
72 193388 return m_value;
73 }
74
75 ClearReason clearReason = ClearReason::None;
76 private:
77 bool m_value = true;
78 };
79
80 struct LimpState {
81 const bool value;
82 const ClearReason reason;
83
84 // Implicit conversion operator to bool, so you can do things like if (myResult) { ... }
85 61 constexpr explicit operator bool() const {
86 61 return value;
87 }
88 };
89
90 class LimpManager : public EngineModule {
91 public:
92 ShutdownController shutdownController;
93 // Mockable<> interface
94 using interface_t = LimpManager;
95
96 // This is called from periodicFastCallback to update internal state
97 void updateState(float rpm, efitick_t nowNt);
98
99 void onFastCallback() override;
100 void onIgnitionStateChanged(bool ignitionOn) override;
101
102 // Other subsystems call these APIs to determine their behavior
103 bool allowElectronicThrottle() const;
104
105 LimpState allowInjection() const;
106 LimpState allowIgnition() const;
107
108 float getTimeSinceAnyCut() const;
109
110 bool allowTriggerInput() const;
111
112 void updateRevLimit(float rpm);
113 angle_t getLimitingTimingRetard() const;
114 float getLimitingFuelCorrection() const;
115
116 // Other subsystems call these APIs to indicate a problem has occurred
117 void reportEtbProblem();
118 void fatalError();
119 Timer externalGdiCanBusComms;
120
121 private:
122 void setFaultRevLimit(int limit, ClearReason rpmLimitReason);
123
124 Hysteresis m_revLimitHysteresis;
125 MaxLimitWithHysteresis<> m_boostCutHysteresis;
126 Hysteresis m_injectorDutyCutHysteresis;
127
128 // Start with no fault rev limit
129 int32_t m_faultRevLimit = INT32_MAX;
130
131 Clearable m_allowEtb;
132 Clearable m_allowInjection;
133 Clearable m_allowIgnition;
134 Clearable m_allowTriggerInput;
135
136 Clearable m_transientAllowInjection = true;
137 Clearable m_transientAllowIgnition = true;
138
139 bool m_hadOilPressureAfterStart = false;
140
141 // Ignition switch state
142 bool m_ignitionOn = false;
143
144 angle_t m_timingRetard = 0;
145 float m_fuelCorrection = 1.0f;
146
147 // todo: migrate to engineState->desiredRpmLimit to get this variable logged
148 float m_revLimit;
149 ClearReason m_rpmLimitReason = ClearReason::None;
150 float resumeRpm;
151
152 // Tracks how long since a cut (ignition or fuel) was active for any reason
153 Timer m_lastCutTime;
154
155 // Tracks how long injector duty has been over the sustained limit
156 Timer m_injectorDutySustainedTimer;
157
158 // Tracks how long oil pressure has been out of thresholds
159 Timer m_lowOilPressureTimer;
160 Timer m_highOilPressureTimer;
161 };
162
163 #if EFI_ENGINE_CONTROL
164 LimpManager * getLimpManager();
165 #endif // EFI_ENGINE_CONTROL
166
167
168