rusEFI
The most advanced open source ECU
Loading...
Searching...
No Matches
trigger_central.h
Go to the documentation of this file.
1/*
2 * @file trigger_central.h
3 *
4 * @date Feb 23, 2014
5 * @author Andrey Belomutskiy, (c) 2012-2020
6 */
7
8#pragma once
9
10#include "rusefi_enums.h"
11#include "listener_array.h"
12#include "trigger_decoder.h"
15#include <rusefi/timer.h>
16#include "pin_repository.h"
18#include "cyclic_buffer.h"
19
20#define MAP_CAM_BUFFER 64
21
22#ifndef RPM_LOW_THRESHOLD
23// no idea what is the best value, 25 is as good as any other guess
24#define RPM_LOW_THRESHOLD 25
25#endif
26
27class Engine;
28typedef void (*ShaftPositionListener)(trigger_event_e signal, uint32_t index, efitick_t edgeTimestamp);
29
30#define HAVE_CAM_INPUT() (isBrainPinValid(engineConfiguration->camInputs[0]))
31
33public:
35 bool noiseFilter(efitick_t nowNt,
36 TriggerDecoderBase* triggerState,
37 trigger_event_e signal);
38
39 efitick_t lastSignalTimes[HW_EVENT_TYPES];
40 efitick_t accumSignalPeriods[HW_EVENT_TYPES];
41 efitick_t accumSignalPrevPeriods[HW_EVENT_TYPES];
42};
43
44/**
45 * Maybe merge TriggerCentral and TriggerState classes into one class?
46 * Probably not: we have an instance of TriggerState which is used for trigger initialization,
47 * also composition probably better than inheritance here
48 */
49class TriggerCentral final : public trigger_central_s {
50public:
52 /**
53 * we have two kinds of sync:
54 * this method is about detecting of exact engine phase with 720 degree precision usually based on cam wheel decoding
55 * not to be confused with a totally different trigger _wheel_ sync which could be either crank wheel sync or cam wheel sync
56 */
57 angle_t syncEnginePhaseAndReport(int divider, int remainder);
58 void handleShaftSignal(trigger_event_e signal, efitick_t timestamp);
59 int getHwEventCounter(int index) const;
60 void resetCounters();
63
64 angle_t findNextTriggerToothAngle(int nextToothIndex);
65
67
69#if EFI_ENGINE_CONTROL && EFI_SHAFT_POSITION_INPUT
71 // Nothing to do here if there's a problem with the trigger shape
72 return;
73 }
74
76#endif
77 }
78
79 // this is useful at least for real hardware integration testing - maybe a proper solution would be to simply
80 // GND input pins instead of leaving them floating
82
83 cyclic_buffer<int> triggerErrorDetection;
84
85 /**
86 * See also triggerSimulatorRpm
87 */
89
91#if CAMS_PER_BANK == 1
92 VvtTriggerConfiguration vvtTriggerConfiguration[CAMS_PER_BANK] = {{"VVT1 ", 0}};
93#else
94 VvtTriggerConfiguration vvtTriggerConfiguration[CAMS_PER_BANK] = {{"VVT1 ", 0}, {"VVT2 ", 1}};
95#endif
96
98
99 /**
100 * By the way:
101 * 'cranking' means engine is not stopped and the rpm are below crankingRpm
102 * 'running' means RPM are above crankingRpm
103 * 'spinning' means the engine is not stopped
104 */
105 // todo: combine with other RpmCalculator fields?
106 /**
107 * this is set to true each time we register a trigger tooth signal
108 */
110
113
114 /**
115 * value of 'triggerShape.getLength()'
116 * pre-calculating this value is a performance optimization
117 */
119 /**
120 * true if a recent configuration change has changed any of the trigger settings which
121 * we have not adjusted for yet
122 */
124
126#if EFI_UNIT_TEST
128#endif // EFI_UNIT_TEST
129
131
132 expected<float> getCurrentEnginePhase(efitick_t nowNt) const;
133
134 float getSecondsSinceTriggerEvent(efitick_t nowNt) const {
135 return m_lastEventTimer.getElapsedSeconds(nowNt);
136 }
137
138 bool engineMovedRecently(efitick_t nowNt) const {
139 // todo: this user-defined property is a quick solution, proper fix https://github.com/rusefi/rusefi/issues/6593 is needed
141 return false;
142 }
143
144 constexpr float oneRevolutionLimitInSeconds = 60.0 / RPM_LOW_THRESHOLD;
145 auto maxAverageToothTime = oneRevolutionLimitInSeconds / triggerShape.getSize();
146
147 // Some triggers may have long gaps (with many teeth), don't count that as stopped!
148 auto maxAllowedGap = maxAverageToothTime * 10;
149
150 // Clamp between 0.1 seconds ("instant" for a human) and worst case of one engine cycle on low tooth count wheel
151 maxAllowedGap = clampF(0.1f, maxAllowedGap, oneRevolutionLimitInSeconds);
152
153 return getSecondsSinceTriggerEvent(nowNt) < maxAllowedGap;
154 }
155
156 bool engineMovedRecently() const {
158 }
159
161
162 int vvtEventRiseCounter[CAM_INPUTS_COUNT];
163 int vvtEventFallCounter[CAM_INPUTS_COUNT];
164
165 angle_t getVVTPosition(uint8_t bankIndex, uint8_t camIndex);
166
167#if EFI_UNIT_TEST
168 // latest VVT event position (could be not synchronization event)
169 angle_t currentVVTEventPosition[BANKS_COUNT][CAMS_PER_BANK];
170#endif // EFI_UNIT_TEST
171
172 // synchronization event position
173 angle_t vvtPosition[BANKS_COUNT][CAMS_PER_BANK];
174
175#if EFI_SHAFT_POSITION_INPUT
177#endif //EFI_SHAFT_POSITION_INPUT
178
180
181 VvtTriggerDecoder vvtState[BANKS_COUNT][CAMS_PER_BANK] = {
182 {
183 "VVT B1 Int",
184#if CAMS_PER_BANK >= 2
185 "VVT B1 Exh"
186#endif
187 },
188#if BANKS_COUNT >= 2
189 {
190 "VVT B2 Int",
191#if CAMS_PER_BANK >= 2
192 "VVT B1 Exh"
193#endif
194 }
195#endif
196 };
197
198 TriggerWaveform vvtShape[CAMS_PER_BANK];
199
201
202 // Keep track of the last time we got a valid trigger event
204
205 /**
206 * this is based on engineSnifferRpmThreshold settings and current RPM
207 */
209
210private:
211 void decodeMapCam(efitick_t nowNt, float currentPhase);
212
213 bool isToothExpectedNow(efitick_t timestamp);
214
215 // Time since the last tooth
217 // Phase of the last tooth relative to the sync point
219
220 // At what engine phase do we expect the next tooth to arrive?
221 // Used for checking whether your trigger pattern is correct.
222 expected<float> expectedNextPhase = unexpected;
223};
224
225void triggerInfo(void);
226void hwHandleShaftSignal(int signalIndex, bool isRising, efitick_t timestamp);
227void handleShaftSignal(int signalIndex, bool isRising, efitick_t timestamp);
228void hwHandleVvtCamSignal(TriggerValue front, efitick_t timestamp, int index);
229void hwHandleVvtCamSignal(bool isRising, efitick_t timestamp, int index);
230void handleVvtCamSignal(TriggerValue front, efitick_t timestamp, int index);
231
233
234void initTriggerCentral();
235
237
239
240#define SYMMETRICAL_CRANK_SENSOR_DIVIDER (2 * 2)
241#define SYMMETRICAL_THREE_TIMES_CRANK_SENSOR_DIVIDER (3 * 2)
242#define SYMMETRICAL_SIX_TIMES_CRANK_SENSOR_DIVIDER (6 * 2)
243#define SYMMETRICAL_TWELVE_TIMES_CRANK_SENSOR_DIVIDER (12 * 2)
244
246int getCrankDivider(operation_mode_e operationMode);
247
248constexpr bool isTriggerUpEvent(trigger_event_e event) {
249 switch (event) {
252 return false;
255 return true;
256 }
257
258 return false;
259}
VvtTriggerDecoder vvtState[BANKS_COUNT][CAMS_PER_BANK]
bool engineMovedRecently() const
float getSecondsSinceTriggerEvent(efitick_t nowNt) const
InstantRpmCalculator instantRpm
PrimaryTriggerDecoder triggerState
float m_lastToothPhaseFromSyncPoint
bool engineMovedRecently(efitick_t nowNt) const
angle_t findNextTriggerToothAngle(int nextToothIndex)
angle_t getVVTPosition(uint8_t bankIndex, uint8_t camIndex)
TriggerWaveform vvtShape[CAMS_PER_BANK]
LocalVersionHolder triggerVersion
int getHwEventCounter(int index) const
int vvtEventFallCounter[CAM_INPUTS_COUNT]
expected< float > expectedNextPhase
TriggerWaveform triggerShape
bool isToothExpectedNow(efitick_t timestamp)
angle_t vvtPosition[BANKS_COUNT][CAMS_PER_BANK]
TriggerFormDetails triggerFormDetails
void handleShaftSignal(trigger_event_e signal, efitick_t timestamp)
TriggerNoiseFilter noiseFilter
bool checkIfTriggerConfigChanged()
cyclic_buffer< int > triggerErrorDetection
VvtTriggerConfiguration vvtTriggerConfiguration[CAMS_PER_BANK]
void decodeMapCam(efitick_t nowNt, float currentPhase)
int vvtEventRiseCounter[CAM_INPUTS_COUNT]
expected< float > getCurrentEnginePhase(efitick_t nowNt) const
bool triggerConfigChangedOnLastConfigurationChange
void prepareTriggerShape()
PrimaryTriggerConfiguration primaryTriggerConfiguration
angle_t currentVVTEventPosition[BANKS_COUNT][CAMS_PER_BANK]
uint32_t engineCycleEventCount
angle_t syncEnginePhaseAndReport(int divider, int remainder)
void prepareEventAngles(TriggerWaveform *shape)
efitick_t accumSignalPrevPeriods[HW_EVENT_TYPES]
bool noiseFilter(efitick_t nowNt, TriggerDecoderBase *triggerState, trigger_event_e signal)
efitick_t accumSignalPeriods[HW_EVENT_TYPES]
efitick_t lastSignalTimes[HW_EVENT_TYPES]
Trigger shape has all the fields needed to describe and decode trigger signal.
size_t getSize() const
efitick_t getTimeNowNt()
Definition efitime.cpp:19
static constexpr engine_configuration_s * engineConfiguration
I/O pin registry header.
Fundamental rusEFI enumerable types live here.
operation_mode_e
trigger_event_e
@ SHAFT_SECONDARY_RISING
@ SHAFT_SECONDARY_FALLING
@ SHAFT_PRIMARY_FALLING
@ SHAFT_PRIMARY_RISING
TriggerValue
constexpr bool isTriggerUpEvent(trigger_event_e event)
void handleVvtCamSignal(TriggerValue front, efitick_t timestamp, int index)
int getCrankDivider(operation_mode_e operationMode)
void validateTriggerInputs()
void hwHandleShaftSignal(int signalIndex, bool isRising, efitick_t timestamp)
void(* ShaftPositionListener)(trigger_event_e signal, uint32_t index, efitick_t edgeTimestamp)
void initTriggerCentral()
TriggerCentral * getTriggerCentral()
Definition engine.cpp:579
void triggerInfo(void)
int isSignalDecoderError(void)
void onConfigurationChangeTriggerCallback()
void handleShaftSignal(int signalIndex, bool isRising, efitick_t timestamp)
void hwHandleVvtCamSignal(TriggerValue front, efitick_t timestamp, int index)