GCC Code Coverage Report


Directory: ./
File: firmware/controllers/engine_cycle/rpm_calculator.h
Date: 2025-10-03 00:57:22
Coverage Exec Excl Total
Lines: 100.0% 2 0 2
Functions: 100.0% 1 0 1
Branches: -% 0 0 0
Decisions: -% 0 - 0

Line Branch Decision Exec Source
1 /**
2 * @file rpm_calculator.h
3 * @brief Shaft position sensor(s) decoder header
4 *
5 * @date Jan 1, 2013
6 * @author Andrey Belomutskiy, (c) 2012-2020
7 */
8
9 #pragma once
10
11 #include "scheduler.h"
12 #include "stored_value_sensor.h"
13 #include <rusefi/timer.h>
14 #include "rpm_calculator_api.h"
15 #include "trigger_decoder.h"
16
17 #define MAX_ALLOWED_RPM 30000
18
19 typedef enum {
20 /**
21 * The engine is not spinning, RPM=0
22 */
23 STOPPED,
24 /**
25 * The engine is spinning up (reliable RPM is not detected yet).
26 * In this state, rpmValue is >= 0 (can be zero).
27 */
28 SPINNING_UP,
29 /**
30 * The engine is cranking (0 < RPM < cranking.rpm)
31 */
32 CRANKING,
33 /**
34 * The engine is running (RPM >= cranking.rpm)
35 */
36 RUNNING,
37 } spinning_state_e;
38
39 /**
40 * Most consumers should access value via Sensor framework by SensorType::Rpm key
41 */
42 class RpmCalculator : public StoredValueSensor, public EngineRotationState {
43 public:
44 RpmCalculator();
45
46 operation_mode_e getOperationMode() const override;
47
48 void onSlowCallback();
49
50 /**
51 * Returns true if the engine is not spinning (RPM==0)
52 */
53 bool isStopped() const override;
54 /**
55 * Returns true if the engine is spinning up
56 */
57 bool isSpinningUp() const;
58 /**
59 * Returns true if the engine is cranking OR spinning up
60 */
61 bool isCranking() const override;
62 /**
63 * Returns true if the engine is running and not cranking
64 */
65 bool isRunning() const;
66
67 bool checkIfSpinning(efitick_t nowNt) const;
68
69 /**
70 * This accessor is used in unit-tests.
71 */
72 spinning_state_e getState() const;
73
74 /**
75 * Should be called on every trigger event when the engine is just starting to spin up.
76 */
77 void setSpinningUp(efitick_t nowNt );
78 /**
79 * Called if the synchronization is lost due to a trigger timeout.
80 */
81 void setStopSpinning();
82
83 /**
84 * Just a quick getter for rpmValue
85 * Should be same exact value as Sensor::get(SensorType::Rpm).Value just quicker.
86 * Open question if we have any cases where this opimization is needed.
87 */
88 float getCachedRpm() const;
89 /**
90 * This method is invoked once per engine cycle right after we calculate new RPM value
91 */
92 void onNewEngineCycle();
93 uint32_t getRevolutionCounterM(void) const;
94 void setRpmValue(float value);
95 /**
96 * The same as setRpmValue() but without state change.
97 * We need this to be public because of calling rpmState->assignRpmValue() from rpmShaftPositionCallback()
98 */
99 void assignRpmValue(float value);
100 uint32_t getRevolutionCounterSinceStart(void) const;
101 /**
102 * RPM rate of change between current RPM and RPM measured during previous engine cycle
103 * see also SC_RPM_ACCEL
104 */
105 float getRpmAcceleration() const;
106
107 // Get elapsed time since the engine transitioned to the running state.
108 float getSecondsSinceEngineStart(efitick_t nowNt) const;
109
110 /**
111 * this is RPM on previous engine cycle.
112 */
113 float previousRpmValue = 0;
114
115 /**
116 * This is a performance optimization: let's pre-calculate this each time RPM changes
117 * NaN while engine is not spinning
118 */
119 floatus_t oneDegreeUs = NAN;
120
121 3152 floatus_t getOneDegreeUs() override {
122 3152 return oneDegreeUs;
123 }
124
125 Timer lastTdcTimer;
126
127 // RPM rate of change, in RPM per second
128 float rpmRate = 0;
129
130 protected:
131 // Print sensor info - current RPM state
132 void showInfo(const char* sensorName) const override;
133
134 private:
135 /**
136 * At this point this value is same exact value as in private m_value variable
137 * At this point all this is performance optimization?
138 * Open question is when do we need it for performance reasons.
139 */
140 float cachedRpmValue = 0;
141
142 /**
143 * This counter is incremented with each revolution of one of the shafts. Could be
144 * crankshaft could be camshaft.
145 */
146 uint32_t revolutionCounterSinceBoot = 0;
147 /**
148 * Same as the above, but since the engine started spinning
149 */
150 uint32_t revolutionCounterSinceStart = 0;
151
152 spinning_state_e state = STOPPED;
153
154 /**
155 * True if the engine is spinning (regardless of its state), i.e. if shaft position changes.
156 * Needed by spinning-up logic.
157 */
158 bool isSpinning = false;
159
160 Timer engineStartTimer;
161 };
162
163 void rpmShaftPositionCallback(trigger_event_e ckpSignalType, uint32_t trgEventIndex, efitick_t edgeTimestamp);
164
165 void tdcMarkCallback(
166 uint32_t trgEventIndex, efitick_t edgeTimestamp);
167
168 operation_mode_e lookupOperationMode();
169
170 #define getRevolutionCounter() (engine->rpmCalculator.getRevolutionCounterM())
171
172 /**
173 * @return tick time of scheduled action
174 */
175 efitick_t scheduleByAngle(scheduling_s *timer, efitick_t nowNt, angle_t angle, action_s const& action);
176