rusEFI
The most advanced open source ECU
Loading...
Searching...
No Matches
Functions | Variables
trigger_central.cpp File Reference

Functions

int getCrankDivider (operation_mode_e operationMode)
 
static bool vvtWithRealDecoder (vvt_mode_e vvtMode)
 
static void turnOffAllDebugFields (void *arg)
 
static angle_t adjustCrankPhase (int camIndex)
 
static angle_t wrapVvt (angle_t vvtPosition, int period)
 
static void logVvtFront (bool useOnlyRise, bool isImportantFront, TriggerValue front, efitick_t nowNt, int index)
 
static bool tooSoonToHandleSignal ()
 
void hwHandleVvtCamSignal (bool isRising, efitick_t timestamp, int index)
 
void hwHandleVvtCamSignal (TriggerValue front, efitick_t nowNt, int index)
 
void handleVvtCamSignal (TriggerValue front, efitick_t nowNt, int index)
 
void hwHandleShaftSignal (int signalIndex, bool isRising, efitick_t timestamp)
 
void handleShaftSignal (int signalIndex, bool isRising, efitick_t timestamp)
 
static void reportEventToWaveChart (trigger_event_e ckpSignalType, int triggerEventIndex, bool addOppositeEvent)
 
PUBLIC_API_WEAK bool boardAllowTriggerActions ()
 
static void triggerShapeInfo ()
 
void triggerInfo (void)
 
static void resetRunningTriggerCounters ()
 
void onConfigurationChangeTriggerCallback ()
 
static void initVvtShape (TriggerWaveform &shape, const TriggerConfiguration &p_config, TriggerDecoderBase &initState)
 
static void calculateTriggerSynchPoint (const PrimaryTriggerConfiguration &primaryTriggerConfiguration, TriggerWaveform &shape, TriggerDecoderBase &initState)
 
void validateTriggerInputs ()
 
void initTriggerCentral ()
 

Variables

WaveChart waveChart
 
static scheduling_s debugToggleScheduling
 
int triggerReentrant = 0
 
int maxTriggerReentrant = 0
 
uint32_t triggerDuration
 
uint32_t triggerMaxDuration = 0
 
static const int wheelIndeces [4] = { 0, 0, 1, 1}
 
PwmConfig triggerEmulatorSignals [NUM_EMULATOR_CHANNELS]
 
TriggerDecoderBase initState ("init")
 

Function Documentation

◆ adjustCrankPhase()

static angle_t adjustCrankPhase ( int  camIndex)
static

Definition at line 161 of file trigger_central.cpp.

161 {
162 float maxSyncThreshold = engineConfiguration->maxCamPhaseResolveRpm;
163 if (maxSyncThreshold != 0 && Sensor::getOrZero(SensorType::Rpm) > maxSyncThreshold) {
164 // The user has elected to stop trying to resolve crank phase after some RPM.
165 // Maybe their cam sensor only works at low RPM or something.
166 // Anyway, don't try to change crank phase at all, and return that we made no change.
167 return 0;
168 }
169
171
172 auto crankDivider = getCrankDivider(operationMode);
173 if (crankDivider == 1) {
174 // Crank divider of 1 means there's no ambiguity, so don't try to resolve it
175 return 0;
176 }
177
179
180 vvt_mode_e vvtMode = engineConfiguration->vvtMode[camIndex];
181 switch (vvtMode) {
182 case VVT_MAP_V_TWIN:
183 case VVT_MITSUBISHI_4G63:
184 case VVT_MITSUBISHI_4G9x:
185 return tc->syncEnginePhaseAndReport(crankDivider, 1);
186 case VVT_SINGLE_TOOTH:
187 case VVT_NISSAN_VQ:
188 case VVT_BOSCH_QUICK_START:
189 case VVT_MIATA_NB:
190 case VVT_TOYOTA_3_TOOTH:
191 case VVT_TOYOTA_4_1:
192 case VVT_FORD_COYOTE:
193 case VVT_DEV:
194 case VVT_FORD_ST170:
195 case VVT_BARRA_3_PLUS_1:
196 case VVT_NISSAN_MR:
197 case VVT_HR12DDR_IN:
198 case VVT_MAZDA_SKYACTIV:
199 case VVT_MAZDA_L:
200 case VVT_MITSUBISHI_4G69:
201 case VVT_MITSUBISHI_3A92:
202 case VVT_MITSUBISHI_6G72:
203 case VVT_MITSUBISHI_6G75:
204 case VVT_HONDA_K_EXHAUST:
205 case VVT_HONDA_CBR_600:
206 return tc->syncEnginePhaseAndReport(crankDivider, 0);
207 case VVT_HONDA_K_INTAKE:
208 // with 4 evenly spaced tooth we cannot use this wheel for engine sync
209 criticalError("Honda K Intake is not suitable for engine sync");
210 [[fallthrough]];
211 case VVT_INACTIVE:
212 // do nothing
213 return 0;
214 }
215 return 0;
216}
virtual operation_mode_e getOperationMode() const =0
static float getOrZero(SensorType type)
Definition sensor.h:83
angle_t syncEnginePhaseAndReport(int divider, int remainder)
TriggerCentral * getTriggerCentral()
Definition engine.cpp:579
EngineRotationState * getEngineRotationState()
Definition engine.cpp:562
static constexpr engine_configuration_s * engineConfiguration
vvt_mode_e
operation_mode_e
int getCrankDivider(operation_mode_e operationMode)

Referenced by handleVvtCamSignal().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ boardAllowTriggerActions()

PUBLIC_API_WEAK bool boardAllowTriggerActions ( )

Definition at line 735 of file trigger_central.cpp.

735{ return true; }

Referenced by TriggerCentral::handleShaftSignal().

Here is the caller graph for this function:

◆ calculateTriggerSynchPoint()

static void calculateTriggerSynchPoint ( const PrimaryTriggerConfiguration primaryTriggerConfiguration,
TriggerWaveform shape,
TriggerDecoderBase initState 
)
static

Calculate 'shape.triggerShapeSynchPointIndex' value using 'TriggerDecoderBase *state'

Definition at line 1079 of file trigger_central.cpp.

1082 {
1083
1084#if EFI_PROD_CODE
1085 efiAssertVoid(ObdCode::CUSTOM_TRIGGER_STACK, hasLotsOfRemainingStack(), "calc s");
1086#endif
1087
1088 shape.initializeSyncPoint(initState, primaryTriggerConfiguration);
1089
1090 if (shape.getSize() >= PWM_PHASE_MAX_COUNT) {
1091 // todo: by the time we are here we had already modified a lot of RAM out of bounds!
1092 firmwareError(ObdCode::CUSTOM_ERR_TRIGGER_WAVEFORM_TOO_LONG, "Trigger length above maximum: %d", shape.getSize());
1093 shape.setShapeDefinitionError(true);
1094 return;
1095 }
1096
1097 if (shape.getSize() == 0) {
1098 firmwareError(ObdCode::CUSTOM_ERR_TRIGGER_ZERO, "triggerShape size is zero");
1099 }
1100}
void setShapeDefinitionError(bool value)
void initializeSyncPoint(TriggerDecoderBase &state, const TriggerConfiguration &triggerConfiguration)
size_t getSize() const
void firmwareError(ObdCode code, const char *fmt,...)
@ CUSTOM_ERR_TRIGGER_ZERO
@ CUSTOM_ERR_TRIGGER_WAVEFORM_TOO_LONG
@ CUSTOM_TRIGGER_STACK
TriggerDecoderBase initState("init")

Referenced by TriggerCentral::applyShapesConfiguration().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ getCrankDivider()

int getCrankDivider ( operation_mode_e  operationMode)

todo: why is this method NOT reciprocal to getRpmMultiplier?!

wow even while we explicitly handle all enumerations in the switch above we still need a return statement due to https://stackoverflow.com/questions/34112483/gcc-how-best-to-handle-warning-about-unreachable-end-of-function-after-switch

Definition at line 98 of file trigger_central.cpp.

98 {
99 switch (operationMode) {
101 return 2;
103 return SYMMETRICAL_CRANK_SENSOR_DIVIDER;
105 return SYMMETRICAL_THREE_TIMES_CRANK_SENSOR_DIVIDER;
107 return SYMMETRICAL_SIX_TIMES_CRANK_SENSOR_DIVIDER;
109 return SYMMETRICAL_TWELVE_TIMES_CRANK_SENSOR_DIVIDER;
110 case OM_NONE:
112 case TWO_STROKE:
113 // That's easy - trigger cycle matches engine cycle
114 return 1;
115 /* let's NOT handle default in order to benefit from -Werror=switch */
116 }
117 /**
118 wow even while we explicitly handle all enumerations in the switch above we still need a return statement due to
119 https://stackoverflow.com/questions/34112483/gcc-how-best-to-handle-warning-about-unreachable-end-of-function-after-switch
120 */
121 criticalError("unreachable getCrankDivider");
122 return 1;
123}
@ FOUR_STROKE_SYMMETRICAL_CRANK_SENSOR
@ FOUR_STROKE_TWELVE_TIMES_CRANK_SENSOR
@ FOUR_STROKE_THREE_TIMES_CRANK_SENSOR
@ FOUR_STROKE_CRANK_SENSOR
@ OM_NONE
@ FOUR_STROKE_CAM_SENSOR
@ TWO_STROKE
@ FOUR_STROKE_SIX_TIMES_CRANK_SENSOR

Referenced by adjustCrankPhase(), getRpmMultiplier(), and TriggerCentral::handleShaftSignal().

Here is the caller graph for this function:

◆ handleShaftSignal()

void handleShaftSignal ( int  signalIndex,
bool  isRising,
efitick_t  timestamp 
)

no need to process VR falls further

Definition at line 464 of file trigger_central.cpp.

464 {
465 bool isPrimary = signalIndex == 0;
466 if (!isPrimary && !TRIGGER_WAVEFORM(needSecondTriggerInput)) {
467 return;
468 }
469
470 trigger_event_e signal;
471 // todo: add support for 3rd channel
472 if (isRising) {
473 signal = isPrimary ?
475 (engineConfiguration->invertSecondaryTriggerSignal ? SHAFT_SECONDARY_FALLING : SHAFT_SECONDARY_RISING);
476 } else {
477 signal = isPrimary ?
479 (engineConfiguration->invertSecondaryTriggerSignal ? SHAFT_SECONDARY_RISING : SHAFT_SECONDARY_FALLING);
480 }
481 if (isPrimary) {
483 } else {
485 }
486
487 // Don't accept trigger input in case of some problems
488 if (!getLimpManager()->allowTriggerInput()) {
489 return;
490 }
491
492#if EFI_TOOTH_LOGGER
493 // Log to the Tunerstudio tooth logger
494 // We want to do this before anything else as we
495 // actually want to capture any noise/jitter that may be occurring
496
498
499 if (!logLogicState) {
500 // we log physical state even if displayLogicLevelsInEngineSniffer if both fronts are used by decoder
501 LogTriggerTooth(signal, timestamp);
502 }
503
504#endif /* EFI_TOOTH_LOGGER */
505
506 // for effective noise filtering, we need both signal edges,
507 // so we pass them to handleShaftSignal() and defer this test
509 if (!isUsefulSignal(signal, getTriggerCentral()->triggerShape)) {
510 /**
511 * no need to process VR falls further
512 */
513 return;
514 }
515 }
516
518#if EFI_PROD_CODE
519 writePad("trigger debug", engineConfiguration->triggerInputDebugPins[signalIndex], 1);
520#endif /* EFI_PROD_CODE */
521 getScheduler()->schedule("dbg_off", &debugToggleScheduling, timestamp + DEBUG_PIN_DELAY, &turnOffAllDebugFields);
522 }
523
524#if EFI_TOOTH_LOGGER
525 if (logLogicState) {
526 // first log rising normally
527 LogTriggerTooth(signal, timestamp);
528 // in 'logLogicState' mode we log opposite front right after logical rising away
529 if (signal == SHAFT_PRIMARY_RISING) {
531 } else {
533 }
534 }
535#endif /* EFI_TOOTH_LOGGER */
536
537 uint32_t triggerHandlerEntryTime = getTimeNowLowerNt();
541
542 getTriggerCentral()->handleShaftSignal(signal, timestamp);
543
545 triggerDuration = getTimeNowLowerNt() - triggerHandlerEntryTime;
547}
TunerStudioOutputChannels outputChannels
Definition engine.h:102
TriggerWaveform triggerShape
void handleShaftSignal(trigger_event_e signal, efitick_t timestamp)
@ Unassigned
LimpManager * getLimpManager()
Definition engine.cpp:585
Scheduler * getScheduler()
Definition engine.cpp:574
static Engine *const engine
Definition engine.h:389
void writePad(const char *msg, brain_pin_e pin, int bit)
Definition io_pins.cpp:115
uint32_t getTimeNowLowerNt()
@ LogTriggerTooth
trigger_event_e
@ SHAFT_SECONDARY_RISING
@ SHAFT_SECONDARY_FALLING
@ SHAFT_PRIMARY_FALLING
@ SHAFT_PRIMARY_RISING
virtual void schedule(const char *msg, scheduling_s *scheduling, efitick_t targetTime, action_s action)=0
Schedule an action to be executed in the future.
uint32_t triggerDuration
static scheduling_s debugToggleScheduling
int maxTriggerReentrant
static void turnOffAllDebugFields(void *arg)
int triggerReentrant
uint32_t triggerMaxDuration
bool isUsefulSignal(trigger_event_e signal, const TriggerWaveform &shape)

Referenced by TriggerEmulatorHelper::handleEmulatorCallback(), and hwHandleShaftSignal().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ handleVvtCamSignal()

void handleVvtCamSignal ( TriggerValue  front,
efitick_t  nowNt,
int  index 
)

we prefer not to have VVT sync right at trigger sync so that we do not have phase detection error if things happen a bit in wrong order due to belt flex or else https://github.com/rusefi/rusefi/issues/3269

Definition at line 289 of file trigger_central.cpp.

289 {
291 if (index == 0) {
293 } else if (index == 1) {
295 } else if (index == 2) {
297 } else if (index == 3) {
299 }
300
301 int bankIndex = BANK_BY_INDEX(index);
302 int camIndex = CAM_BY_INDEX(index);
303 if (front == TriggerValue::RISE) {
304 tc->vvtEventRiseCounter[index]++;
305 } else {
306 tc->vvtEventFallCounter[index]++;
307 }
308 if (engineConfiguration->vvtMode[camIndex] == VVT_INACTIVE) {
309 warning(ObdCode::CUSTOM_VVT_MODE_NOT_SELECTED, "VVT: event on %d but no mode", camIndex);
310 }
311
312 const auto& vvtShape = tc->vvtShape[camIndex];
313
314 bool isVvtWithRealDecoder = vvtWithRealDecoder(engineConfiguration->vvtMode[camIndex]);
315
316 // Non real decoders only use the rising edge
317 bool vvtUseOnlyRise = !isVvtWithRealDecoder || vvtShape.useOnlyRisingEdges;
318 bool isImportantFront = !vvtUseOnlyRise || (front == TriggerValue::RISE);
319
320 logVvtFront(vvtUseOnlyRise, isImportantFront, front, nowNt, index);
321
322 if (!isImportantFront) {
323 // This edge is unimportant, ignore it.
324 return;
325 }
326
327 // If the main trigger is not synchronized, don't decode VVT yet
329 return;
330 }
331
332 TriggerDecoderBase& vvtDecoder = tc->vvtState[bankIndex][camIndex];
333
334 if (isVvtWithRealDecoder) {
335 vvtDecoder.decodeTriggerEvent(
336 "vvt",
337 vvtShape,
338 nullptr,
339 tc->vvtTriggerConfiguration[camIndex],
341 vvtDecoder.vvtToothDurations0 = (uint32_t)NT2US(vvtDecoder.toothDurations[0]);
342 }
343
344 // here we count all cams together
345 tc->vvtCamCounter++;
346
347 auto currentPhase = tc->getCurrentEnginePhase(nowNt);
348 if (!currentPhase) {
349 // If we couldn't resolve engine speed (yet primary trigger is sync'd), this
350 // probably means that we have partial crank sync, but not RPM information yet
351 return;
352 }
353
354 angle_t angleFromPrimarySyncPoint = currentPhase.Value;
355 // convert trigger cycle angle into engine cycle angle
356 angle_t currentPosition = angleFromPrimarySyncPoint - tdcPosition();
357 // https://github.com/rusefi/rusefi/issues/1713 currentPosition could be negative that's expected
358
359#if EFI_UNIT_TEST
360 tc->currentVVTEventPosition[bankIndex][camIndex] = currentPosition;
361#endif // EFI_UNIT_TEST
362
363 tc->triggerState.vvtCurrentPosition = currentPosition;
364
365 if (isVvtWithRealDecoder && vvtDecoder.currentCycle.current_index != 0) {
366 // this is not sync tooth - exiting
367 return;
368 }
369
370 auto vvtPosition = engineConfiguration->vvtOffsets[bankIndex * CAMS_PER_BANK + camIndex] - currentPosition;
371 tc->triggerState.vvtToothPosition[index] = vvtPosition;
372
373 switch(engineConfiguration->vvtMode[camIndex]) {
374 case VVT_TOYOTA_3_TOOTH:
375 {
378 // we do not know if we are in sync or out of sync, so we have to be looking for both possibilities
379 if ((currentPosition < from || currentPosition > to) &&
380 (currentPosition < from + 360 || currentPosition > to + 360)) {
381 // outside of the expected range
382 return;
383 }
384 }
385 break;
386 default:
387 // else, do nothing
388 break;
389 }
390
391 // this could be just an 'if' but let's have it expandable for future use :)
392 switch(engineConfiguration->vvtMode[camIndex]) {
393 case VVT_HONDA_K_INTAKE:
394 // honda K has four tooth in VVT intake trigger, so we just wrap each of those to 720 / 4
395 vvtPosition = wrapVvt(vvtPosition, 180);
396 break;
397 default:
398 // else, do nothing
399 break;
400 }
401
402#if EFI_PROD_CODE
405 criticalError("Selected engine sync input not configured: %d", engineConfiguration->engineSyncCam);
406 }
407#endif // EFI_PROD_CODE
408
409 // Only do engine sync using one cam, other cams just provide VVT position.
410 if (index == engineConfiguration->engineSyncCam) {
411 angle_t crankOffset = adjustCrankPhase(camIndex);
412 // vvtPosition was calculated against wrong crank zero position. Now that we have adjusted crank position we
413 // shall adjust vvt position as well
414 vvtPosition -= crankOffset;
415 vvtPosition = wrapVvt(vvtPosition, FOUR_STROKE_CYCLE_DURATION);
416
417 if (absF(angleFromPrimarySyncPoint) < 7) {
418 /**
419 * we prefer not to have VVT sync right at trigger sync so that we do not have phase detection error if things happen a bit in
420 * wrong order due to belt flex or else
421 * https://github.com/rusefi/rusefi/issues/3269
422 */
423 warning(ObdCode::CUSTOM_VVT_SYNC_POSITION, "VVT sync position too close to trigger sync");
424 }
425 } else {
426 // Not using this cam for engine sync, just wrap the value in to the reasonable range
427 vvtPosition = wrapVvt(vvtPosition, FOUR_STROKE_CYCLE_DURATION);
428 }
429
430 // Only record VVT position if we have full engine sync - may be bogus before that point
432 tc->vvtPosition[bankIndex][camIndex] = vvtPosition;
433 } else {
434 tc->vvtPosition[bankIndex][camIndex] = 0;
435 }
436}
bool hasSynchronizedPhase() const
VvtTriggerDecoder vvtState[BANKS_COUNT][CAMS_PER_BANK]
PrimaryTriggerDecoder triggerState
TriggerWaveform vvtShape[CAMS_PER_BANK]
int vvtEventFallCounter[CAM_INPUTS_COUNT]
angle_t vvtPosition[BANKS_COUNT][CAMS_PER_BANK]
VvtTriggerConfiguration vvtTriggerConfiguration[CAMS_PER_BANK]
int vvtEventRiseCounter[CAM_INPUTS_COUNT]
expected< float > getCurrentEnginePhase(efitick_t nowNt) const
angle_t currentVVTEventPosition[BANKS_COUNT][CAMS_PER_BANK]
expected< TriggerDecodeResult > decodeTriggerEvent(const char *msg, const TriggerWaveform &triggerShape, TriggerStateListener *triggerStateListener, const TriggerConfiguration &triggerConfiguration, const trigger_event_e signal, const efitick_t nowNt)
Trigger decoding happens here VR falls are filtered out and some VR noise detection happens prior to ...
current_cycle_state_s currentCycle
uint32_t toothDurations[GAP_TRACKING_LENGTH+1]
bool warning(ObdCode code, const char *fmt,...)
@ CUSTOM_VVT_SYNC_POSITION
@ CUSTOM_VVT_MODE_NOT_SELECTED
bool isBrainPinValid(brain_pin_e brainPin)
float angle_t
static bool vvtWithRealDecoder(vvt_mode_e vvtMode)
static void logVvtFront(bool useOnlyRise, bool isImportantFront, TriggerValue front, efitick_t nowNt, int index)
static angle_t wrapVvt(angle_t vvtPosition, int period)
static angle_t adjustCrankPhase(int camIndex)

Referenced by TriggerEmulatorHelper::handleEmulatorCallback(), and hwHandleVvtCamSignal().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ hwHandleShaftSignal()

void hwHandleShaftSignal ( int  signalIndex,
bool  isRising,
efitick_t  timestamp 
)

This function is called by all "hardware" trigger inputs:

  • Hardware triggers
  • Trigger replay from CSV (unit tests)

Definition at line 448 of file trigger_central.cpp.

448 {
449 if (tooSoonToHandleSignal()) {
450 return;
451 }
454
456 // sensor noise + self-stim = loss of trigger sync
457 return;
458 }
459
460 handleShaftSignal(signalIndex, isRising, timestamp);
461}
@ HandleShaftSignal
static bool tooSoonToHandleSignal()
void handleShaftSignal(int signalIndex, bool isRising, efitick_t timestamp)

Referenced by comp_shaft_callback(), onTriggerChanged(), and shaft_callback().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ hwHandleVvtCamSignal() [1/2]

void hwHandleVvtCamSignal ( bool  isRising,
efitick_t  timestamp,
int  index 
)

Definition at line 272 of file trigger_central.cpp.

272 {
273 hwHandleVvtCamSignal(isRising ? TriggerValue::RISE : TriggerValue::FALL, timestamp, index);
274}
TriggerValue
void hwHandleVvtCamSignal(bool isRising, efitick_t timestamp, int index)

Referenced by cam_callback(), comp_cam_callback(), and hwHandleVvtCamSignal().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ hwHandleVvtCamSignal() [2/2]

void hwHandleVvtCamSignal ( TriggerValue  front,
efitick_t  nowNt,
int  index 
)

Definition at line 277 of file trigger_central.cpp.

277 {
278 if (tooSoonToHandleSignal()) {
279 return;
280 }
283 // sensor noise + self-stim = loss of trigger sync
284 return;
285 }
286 handleVvtCamSignal(front, nowNt, index);
287}
void handleVvtCamSignal(TriggerValue front, efitick_t nowNt, int index)

Referenced by TriggerCentral::decodeMapCam().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ initTriggerCentral()

void initTriggerCentral ( )

Definition at line 1214 of file trigger_central.cpp.

1214 {
1215
1216#if EFI_ENGINE_SNIFFER
1218#endif /* EFI_ENGINE_SNIFFER */
1219
1220#if EFI_PROD_CODE || EFI_SIMULATOR
1221 addConsoleAction(CMD_TRIGGERINFO, triggerInfo);
1222 addConsoleAction("trigger_shape_info", triggerShapeInfo);
1224#endif // EFI_PROD_CODE || EFI_SIMULATOR
1225
1226}
void addConsoleAction(const char *token, Void callback)
Register console action without parameters.
void initWaveChart(WaveChart *chart)
static void triggerShapeInfo()
void triggerInfo(void)
static void resetRunningTriggerCounters()
WaveChart waveChart

Referenced by commonEarlyInit().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ initVvtShape()

static void initVvtShape ( TriggerWaveform shape,
const TriggerConfiguration p_config,
TriggerDecoderBase initState 
)
static

Definition at line 1061 of file trigger_central.cpp.

1061 {
1062 shape.initializeTriggerWaveform(FOUR_STROKE_CAM_SENSOR, p_config.TriggerType, /*isCrank*/ false);
1063 shape.initializeSyncPoint(initState, p_config);
1064}
trigger_config_s TriggerType
void initializeTriggerWaveform(operation_mode_e triggerOperationMode, const trigger_config_s &triggerType, bool isCrankWheel=true)

Referenced by TriggerCentral::applyShapesConfiguration().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ logVvtFront()

static void logVvtFront ( bool  useOnlyRise,
bool  isImportantFront,
TriggerValue  front,
efitick_t  nowNt,
int  index 
)
static

Definition at line 232 of file trigger_central.cpp.

232 {
233 if (isImportantFront && isBrainPinValid(engineConfiguration->camInputsDebug[index])) {
234#if EFI_PROD_CODE
235 writePad("cam debug", engineConfiguration->camInputsDebug[index], 1);
236#endif /* EFI_PROD_CODE */
237 getScheduler()->schedule("dbg_on", &debugToggleScheduling, nowNt + DEBUG_PIN_DELAY, &turnOffAllDebugFields);
238 }
239
241 // If we care about both edges OR displayLogicLevel is set, log every front exactly as it is
243
244#if EFI_TOOTH_LOGGER
245 LogTriggerCamTooth(front == TriggerValue::RISE, nowNt, index);
246#endif /* EFI_TOOTH_LOGGER */
247 } else {
248 if (isImportantFront) {
249 // On the important edge, log a rise+fall pair, and nothing on the real falling edge
252
253#if EFI_TOOTH_LOGGER
254 LogTriggerCamTooth(true, nowNt, index);
255 LogTriggerCamTooth(false, nowNt, index);
256#endif /* EFI_TOOTH_LOGGER */
257 }
258 }
259}
void addEngineSnifferVvtEvent(int vvtIndex, FrontDirection frontDirection)
FrontDirection
void LogTriggerCamTooth(bool isRising, efitick_t timestamp, int index)

Referenced by handleVvtCamSignal().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ onConfigurationChangeTriggerCallback()

void onConfigurationChangeTriggerCallback ( )

Definition at line 1009 of file trigger_central.cpp.

1009 {
1010 bool changed = false;
1011 // todo: how do we static_assert here?
1012 criticalAssertVoid(efi::size(engineConfiguration->camInputs) == efi::size(engineConfiguration->vvtOffsets), "sizes");
1013
1014 for (size_t camIndex = 0; camIndex < efi::size(engineConfiguration->camInputs); camIndex++) {
1015 changed |= isConfigurationChanged(camInputs[camIndex]);
1016 changed |= isConfigurationChanged(vvtOffsets[camIndex]);
1017 }
1018
1019 for (size_t i = 0; i < efi::size(engineConfiguration->triggerGapOverrideFrom); i++) {
1020 changed |= isConfigurationChanged(triggerGapOverrideFrom[i]);
1021 changed |= isConfigurationChanged(triggerGapOverrideTo[i]);
1022 }
1023
1024 for (size_t i = 0; i < efi::size(engineConfiguration->triggerInputPins); i++) {
1025 changed |= isConfigurationChanged(triggerInputPins[i]);
1027 if (engineConfiguration->vvtMode[0] == VVT_MAP_V_TWIN && isBrainPinValid(pin)) {
1028 criticalError("Please no physical sensors in CAM by MAP mode index=%d %s", i, hwPortname(pin));
1029 }
1030 }
1031
1032 for (size_t i = 0; i < efi::size(engineConfiguration->vvtMode); i++) {
1033 changed |= isConfigurationChanged(vvtMode[i]);
1034 }
1035
1036 changed |= isConfigurationChanged(trigger.type);
1037 changed |= isConfigurationChanged(skippedWheelOnCam);
1038 changed |= isConfigurationChanged(twoStroke);
1039 changed |= isConfigurationChanged(globalTriggerAngleOffset);
1040 changed |= isConfigurationChanged(trigger.customTotalToothCount);
1041 changed |= isConfigurationChanged(trigger.customSkippedToothCount);
1042 changed |= isConfigurationChanged(overrideTriggerGaps);
1043 changed |= isConfigurationChanged(gapTrackingLengthOverride);
1044 changed |= isConfigurationChanged(overrideVvtTriggerGaps);
1045 changed |= isConfigurationChanged(gapVvtTrackingLengthOverride);
1046
1047 if (changed) {
1048 #if EFI_ENGINE_CONTROL
1051 #endif
1052 }
1053#if EFI_DEFAILED_LOGGING
1054 efiPrintf("isTriggerConfigChanged=%d", triggerConfigChanged);
1055#endif /* EFI_DEFAILED_LOGGING */
1056
1057 // we do not want to miss two updates in a row
1059}
void updateTriggerConfiguration()
Definition engine.cpp:125
TriggerNoiseFilter noiseFilter
bool triggerConfigChangedOnLastConfigurationChange
const char * hwPortname(brain_pin_e brainPin)
brain_pin_e pin
Definition stm32_adc.cpp:15
brain_input_pin_e triggerInputPins[TRIGGER_INPUT_PIN_COUNT]

Referenced by incrementGlobalConfigurationVersion().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ reportEventToWaveChart()

static void reportEventToWaveChart ( trigger_event_e  ckpSignalType,
int  triggerEventIndex,
bool  addOppositeEvent 
)
static

Definition at line 555 of file trigger_central.cpp.

555 {
556 if (!getTriggerCentral()->isEngineSnifferEnabled) { // this is here just as a shortcut so that we avoid engine sniffer as soon as possible
557 return; // engineSnifferRpmThreshold is accounted for inside getTriggerCentral()->isEngineSnifferEnabled
558 }
559
560 int wheelIndex = wheelIndeces[(int )ckpSignalType];
561
562 bool isUp = isTriggerUpEvent(ckpSignalType);
563
564 addEngineSnifferCrankEvent(wheelIndex, triggerEventIndex, isUp ? FrontDirection::UP : FrontDirection::DOWN);
565 if (addOppositeEvent) {
566 // let's add the opposite event right away
567 addEngineSnifferCrankEvent(wheelIndex, triggerEventIndex, isUp ? FrontDirection::DOWN : FrontDirection::UP);
568 }
569}
void addEngineSnifferCrankEvent(int wheelIndex, int triggerEventIndex, FrontDirection frontDirection)
static const int wheelIndeces[4]
constexpr bool isTriggerUpEvent(trigger_event_e event)

Referenced by TriggerCentral::handleShaftSignal().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ resetRunningTriggerCounters()

static void resetRunningTriggerCounters ( )
static

Definition at line 1002 of file trigger_central.cpp.

1002 {
1003#if !EFI_UNIT_TEST
1005 triggerInfo();
1006#endif
1007}

Referenced by initTriggerCentral().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ tooSoonToHandleSignal()

static bool tooSoonToHandleSignal ( )
static

Definition at line 261 of file trigger_central.cpp.

261 {
262#if EFI_PROD_CODE
263extern bool main_loop_started;
264 if (!main_loop_started) {
266 return true;
267 }
268#endif //EFI_PROD_CODE
269 return false;
270}
@ CUSTOM_ERR_INPUT_DURING_INITIALISATION
bool main_loop_started
Definition rusefi.cpp:143

Referenced by hwHandleShaftSignal(), and hwHandleVvtCamSignal().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ triggerInfo()

void triggerInfo ( void  )

Definition at line 904 of file trigger_central.cpp.

904 {
905#if EFI_PROD_CODE || EFI_SIMULATOR
906
908 TriggerWaveform *ts = &tc->triggerShape;
909
910
911#if (HAL_TRIGGER_USE_PAL == TRUE) && (PAL_USE_CALLBACKS == TRUE)
912 efiPrintf("trigger PAL mode %d", tc->hwTriggerInputEnabled);
913#else
914
915#endif /* HAL_TRIGGER_USE_PAL */
916
917 efiPrintf("Template %s (%d) trigger %s (%d) syncEdge=%s tdcOffset=%.2f",
922 getSyncEdge(TRIGGER_WAVEFORM(syncEdge)), TRIGGER_WAVEFORM(tdcPosition));
923
925 efiPrintf("total %d/skipped %d", engineConfiguration->trigger.customTotalToothCount,
927 }
928
929
930 efiPrintf("trigger#1 event counters up=%d/down=%d", tc->getHwEventCounter(0),
931 tc->getHwEventCounter(1));
932
933 if (ts->needSecondTriggerInput) {
934 efiPrintf("trigger#2 event counters up=%d/down=%d", tc->getHwEventCounter(2),
935 tc->getHwEventCounter(3));
936 }
937 efiPrintf("expected cycle events %d/%d",
938 TRIGGER_WAVEFORM(getExpectedEventCount(TriggerWheel::T_PRIMARY)),
939 TRIGGER_WAVEFORM(getExpectedEventCount(TriggerWheel::T_SECONDARY)));
940
941 efiPrintf("trigger type=%d/need2ndChannel=%s", (int)engineConfiguration->trigger.type,
942 boolToString(TRIGGER_WAVEFORM(needSecondTriggerInput)));
943
944
945 efiPrintf("synchronizationNeeded=%s/isError=%s/total errors=%lu ord_err=%lu/total revolutions=%d/self=%s",
952
953 if (TRIGGER_WAVEFORM(isSynchronizationNeeded)) {
954 efiPrintf("gap from %.2f to %.2f", TRIGGER_WAVEFORM(synchronizationRatioFrom[0]), TRIGGER_WAVEFORM(synchronizationRatioTo[0]));
955 }
956
957#endif /* EFI_PROD_CODE || EFI_SIMULATOR */
958
959#if EFI_PROD_CODE
960
961 efiPrintf("primary trigger input: %s", hwPortname(engineConfiguration->triggerInputPins[0]));
962 efiPrintf("primary trigger simulator: %s %s freq=%d",
966
967 if (ts->needSecondTriggerInput) {
968 efiPrintf("secondary trigger input: %s", hwPortname(engineConfiguration->triggerInputPins[1]));
969#if EFI_EMULATE_POSITION_SENSORS
970 efiPrintf("secondary trigger simulator: %s %s phase=%d",
973#endif /* EFI_EMULATE_POSITION_SENSORS */
974 }
975
976
977 for (int camInputIndex = 0; camInputIndex<CAM_INPUTS_COUNT;camInputIndex++) {
978 if (isBrainPinValid(engineConfiguration->camInputs[camInputIndex])) {
979 int camLogicalIndex = camInputIndex % CAMS_PER_BANK;
980 efiPrintf("VVT input: %s mode %s", hwPortname(engineConfiguration->camInputs[camInputIndex]),
981 getVvt_mode_e(engineConfiguration->vvtMode[camLogicalIndex]));
982 efiPrintf("VVT %d event counters: %d/%d",
983 camInputIndex,
984 tc->vvtEventRiseCounter[camInputIndex], tc->vvtEventFallCounter[camInputIndex]);
985 }
986 }
987
988 efiPrintf("primary logic input: %s", hwPortname(engineConfiguration->logicAnalyzerPins[0]));
989 efiPrintf("secondary logic input: %s", hwPortname(engineConfiguration->logicAnalyzerPins[1]));
990
991
992 efiPrintf("totalTriggerHandlerMaxTime=%lu", triggerMaxDuration);
993
994#endif /* EFI_PROD_CODE */
995
996#if EFI_ENGINE_SNIFFER
997 efiPrintf("engine sniffer current size=%d", waveChart.getSize());
998#endif /* EFI_ENGINE_SNIFFER */
999
1000}
const char * getPin_output_mode_e(pin_output_mode_e value)
const char * getVvt_mode_e(vvt_mode_e value)
const char * getEngine_type_e(engine_type_e value)
const char * getTrigger_type_e(trigger_type_e value)
const char * getSyncEdge(SyncEdge value)
pwm_config_safe_state_s safe
int getHwEventCounter(int index) const
int getSynchronizationCounter() const
uint32_t totalTriggerErrorCounter
Trigger shape has all the fields needed to describe and decode trigger signal.
const char * boolToString(bool value)
Definition efilib.cpp:18
brain_input_pin_e logicAnalyzerPins[LOGIC_ANALYZER_CHANNEL_COUNT]
pin_output_mode_e triggerSimulatorPinModes[TRIGGER_SIMULATOR_PIN_COUNT]
PwmConfig triggerEmulatorSignals[NUM_EMULATOR_CHANNELS]

Referenced by initTriggerCentral(), and resetRunningTriggerCounters().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ triggerShapeInfo()

static void triggerShapeInfo ( )
static

Definition at line 887 of file trigger_central.cpp.

887 {
888#if EFI_PROD_CODE || EFI_SIMULATOR
891 efiPrintf("syncEdge=%s", getSyncEdge(TRIGGER_WAVEFORM(syncEdge)));
892 efiPrintf("gap from %.2f to %.2f", TRIGGER_WAVEFORM(synchronizationRatioFrom[0]), TRIGGER_WAVEFORM(synchronizationRatioTo[0]));
893
894 for (size_t i = 0; i < shape->getSize(); i++) {
895 efiPrintf("event %d %.2f", i, triggerFormDetails->eventAngles[i]);
896 }
897#endif
898}
TriggerFormDetails triggerFormDetails
angle_t eventAngles[2 *PWM_PHASE_MAX_COUNT]

Referenced by initTriggerCentral().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ turnOffAllDebugFields()

static void turnOffAllDebugFields ( void *  arg)
static

Definition at line 145 of file trigger_central.cpp.

145 {
146 (void)arg;
147#if EFI_PROD_CODE
148 for (int index = 0;index<TRIGGER_INPUT_PIN_COUNT;index++) {
150 writePad("trigger debug", engineConfiguration->triggerInputDebugPins[index], 0);
151 }
152 }
153 for (int index = 0;index<CAM_INPUTS_COUNT;index++) {
155 writePad("cam debug", engineConfiguration->camInputsDebug[index], 0);
156 }
157 }
158#endif /* EFI_PROD_CODE */
159}

Referenced by handleShaftSignal(), and logVvtFront().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ validateTriggerInputs()

void validateTriggerInputs ( )

Definition at line 1204 of file trigger_central.cpp.

1204 {
1206 criticalError("First trigger channel not configured while second one is.");
1207 }
1208
1210 criticalError("First bank cam input is required if second bank specified");
1211 }
1212}

Referenced by startHardware().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ vvtWithRealDecoder()

static bool vvtWithRealDecoder ( vvt_mode_e  vvtMode)
static

Definition at line 125 of file trigger_central.cpp.

125 {
126 return vvtMode != VVT_INACTIVE
127 && vvtMode != VVT_TOYOTA_3_TOOTH /* VVT_2JZ is an unusual 3/0 missed tooth symmetrical wheel */
128 && vvtMode != VVT_HONDA_K_INTAKE
129 && vvtMode != VVT_MAP_V_TWIN
130 && vvtMode != VVT_SINGLE_TOOTH;
131}

Referenced by handleVvtCamSignal().

Here is the caller graph for this function:

◆ wrapVvt()

static angle_t wrapVvt ( angle_t  vvtPosition,
int  period 
)
static

See also wrapAngle

Definition at line 221 of file trigger_central.cpp.

221 {
222 // Wrap VVT position in to the range [-360, 360)
223 while (vvtPosition < -period / 2) {
224 vvtPosition += period;
225 }
226 while (vvtPosition >= period / 2) {
227 vvtPosition -= period;
228 }
229 return vvtPosition;
230}
beuint32_t period

Referenced by handleVvtCamSignal().

Here is the caller graph for this function:

Variable Documentation

◆ debugToggleScheduling

scheduling_s debugToggleScheduling
static

Definition at line 36 of file trigger_central.cpp.

Referenced by handleShaftSignal(), and logVvtFront().

◆ initState

TriggerDecoderBase initState("init") ( "init"  )

◆ maxTriggerReentrant

int maxTriggerReentrant = 0

◆ triggerDuration

uint32_t triggerDuration

Definition at line 440 of file trigger_central.cpp.

Referenced by handleShaftSignal().

◆ triggerEmulatorSignals

PwmConfig triggerEmulatorSignals[NUM_EMULATOR_CHANNELS]
extern

◆ triggerMaxDuration

uint32_t triggerMaxDuration = 0

Definition at line 441 of file trigger_central.cpp.

Referenced by handleShaftSignal(), resetMaxValues(), and triggerInfo().

◆ triggerReentrant

int triggerReentrant = 0

Definition at line 438 of file trigger_central.cpp.

Referenced by handleShaftSignal().

◆ waveChart

WaveChart waveChart

◆ wheelIndeces

const int wheelIndeces[4] = { 0, 0, 1, 1}
static

Definition at line 553 of file trigger_central.cpp.

553{ 0, 0, 1, 1};

Referenced by reportEventToWaveChart().

Go to the source code of this file.