rusEFI
The most advanced open source ECU
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)
 
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)
 
BOARD_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 bool isUpEvent [4] = { false, true, false, true }
 
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 162 of file trigger_central.cpp.

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

BOARD_WEAK bool boardAllowTriggerActions ( )

Definition at line 746 of file trigger_central.cpp.

746 { 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 1090 of file trigger_central.cpp.

1093  {
1094 
1095 #if EFI_PROD_CODE
1096  efiAssertVoid(ObdCode::CUSTOM_TRIGGER_STACK, hasLotsOfRemainingStack(), "calc s");
1097 #endif
1098 
1099  shape.initializeSyncPoint(initState, primaryTriggerConfiguration);
1100 
1101  if (shape.getSize() >= PWM_PHASE_MAX_COUNT) {
1102  // todo: by the time we are here we had already modified a lot of RAM out of bounds!
1103  firmwareError(ObdCode::CUSTOM_ERR_TRIGGER_WAVEFORM_TOO_LONG, "Trigger length above maximum: %d", shape.getSize());
1104  shape.setShapeDefinitionError(true);
1105  return;
1106  }
1107 
1108  if (shape.getSize() == 0) {
1109  firmwareError(ObdCode::CUSTOM_ERR_TRIGGER_ZERO, "triggerShape size is zero");
1110  }
1111 }
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::updateWaveform().

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 99 of file trigger_central.cpp.

99  {
100  switch (operationMode) {
102  return 2;
104  return SYMMETRICAL_CRANK_SENSOR_DIVIDER;
106  return SYMMETRICAL_THREE_TIMES_CRANK_SENSOR_DIVIDER;
108  return SYMMETRICAL_SIX_TIMES_CRANK_SENSOR_DIVIDER;
110  return SYMMETRICAL_TWELVE_TIMES_CRANK_SENSOR_DIVIDER;
111  case OM_NONE:
113  case TWO_STROKE:
114  // That's easy - trigger cycle matches engine cycle
115  return 1;
116  /* let's NOT handle default in order to benefit from -Werror=switch */
117  }
118  /**
119  wow even while we explicitly handle all enumerations in the switch above we still need a return statement due to
120  https://stackoverflow.com/questions/34112483/gcc-how-best-to-handle-warning-about-unreachable-end-of-function-after-switch
121  */
122  criticalError("unreachable getCrankDivider");
123  return 1;
124 }
@ FOUR_STROKE_SYMMETRICAL_CRANK_SENSOR
Definition: rusefi_enums.h:270
@ FOUR_STROKE_TWELVE_TIMES_CRANK_SENSOR
Definition: rusefi_enums.h:280
@ FOUR_STROKE_THREE_TIMES_CRANK_SENSOR
Definition: rusefi_enums.h:275
@ FOUR_STROKE_CRANK_SENSOR
Definition: rusefi_enums.h:256
@ OM_NONE
Definition: rusefi_enums.h:250
@ FOUR_STROKE_CAM_SENSOR
Definition: rusefi_enums.h:260
@ TWO_STROKE
Definition: rusefi_enums.h:264
@ FOUR_STROKE_SIX_TIMES_CRANK_SENSOR
Definition: rusefi_enums.h:285

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 474 of file trigger_central.cpp.

474  {
475  bool isPrimary = signalIndex == 0;
476  if (!isPrimary && !TRIGGER_WAVEFORM(needSecondTriggerInput)) {
477  return;
478  }
479 
480  trigger_event_e signal;
481  // todo: add support for 3rd channel
482  if (isRising) {
483  signal = isPrimary ?
486  } else {
487  signal = isPrimary ?
490  }
491  if (isPrimary) {
493  } else {
495  }
496 
497  // Don't accept trigger input in case of some problems
498  if (!getLimpManager()->allowTriggerInput()) {
499  return;
500  }
501 
502 #if EFI_TOOTH_LOGGER
503  // Log to the Tunerstudio tooth logger
504  // We want to do this before anything else as we
505  // actually want to capture any noise/jitter that may be occurring
506 
508 
509  if (!logLogicState) {
510  // we log physical state even if displayLogicLevelsInEngineSniffer if both fronts are used by decoder
511  LogTriggerTooth(signal, timestamp);
512  }
513 
514 #endif /* EFI_TOOTH_LOGGER */
515 
516  // for effective noise filtering, we need both signal edges,
517  // so we pass them to handleShaftSignal() and defer this test
519  if (!isUsefulSignal(signal, getTriggerCentral()->triggerShape)) {
520  /**
521  * no need to process VR falls further
522  */
523  return;
524  }
525  }
526 
528 #if EFI_PROD_CODE
529  writePad("trigger debug", engineConfiguration->triggerInputDebugPins[signalIndex], 1);
530 #endif /* EFI_PROD_CODE */
531  getExecutorInterface()->scheduleByTimestampNt("dbg_off", &debugToggleScheduling, timestamp + DEBUG_PIN_DELAY, &turnOffAllDebugFields);
532  }
533 
534 #if EFI_TOOTH_LOGGER
535  if (logLogicState) {
536  // first log rising normally
537  LogTriggerTooth(signal, timestamp);
538  // in 'logLogicState' mode we log opposite front right after logical rising away
539  if (signal == SHAFT_PRIMARY_RISING) {
541  } else {
543  }
544  }
545 #endif /* EFI_TOOTH_LOGGER */
546 
547  uint32_t triggerHandlerEntryTime = getTimeNowLowerNt();
551 
552  getTriggerCentral()->handleShaftSignal(signal, timestamp);
553 
555  triggerDuration = getTimeNowLowerNt() - triggerHandlerEntryTime;
557 }
TunerStudioOutputChannels outputChannels
Definition: engine.h:99
TriggerWaveform triggerShape
void handleShaftSignal(trigger_event_e signal, efitick_t timestamp)
@ Unassigned
LimpManager * getLimpManager()
Definition: engine.cpp:597
ExecutorInterface * getExecutorInterface()
Definition: engine.cpp:586
Engine * engine
void writePad(const char *msg, brain_pin_e pin, int bit)
Definition: io_pins.cpp:115
uint32_t getTimeNowLowerNt()
trigger_event_e
@ SHAFT_SECONDARY_RISING
@ SHAFT_SECONDARY_FALLING
@ SHAFT_PRIMARY_FALLING
@ SHAFT_PRIMARY_RISING
virtual void scheduleByTimestampNt(const char *msg, scheduling_s *scheduling, efitick_t timeNt, action_s action)=0
void LogTriggerTooth(trigger_event_e tooth, efitick_t timestamp)
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 274 of file trigger_central.cpp.

274  {
276  if (index == 0) {
278  } else if (index == 1) {
280  } else if (index == 2) {
282  } else if (index == 3) {
284  }
285 
286  int bankIndex = BANK_BY_INDEX(index);
287  int camIndex = CAM_BY_INDEX(index);
288  if (front == TriggerValue::RISE) {
289  tc->vvtEventRiseCounter[index]++;
290  } else {
291  tc->vvtEventFallCounter[index]++;
292  }
293  if (engineConfiguration->vvtMode[camIndex] == VVT_INACTIVE) {
294  warning(ObdCode::CUSTOM_VVT_MODE_NOT_SELECTED, "VVT: event on %d but no mode", camIndex);
295  }
296 
297 #ifdef VR_HW_CHECK_MODE
298  // some boards do not have hardware VR input LEDs which makes such boards harder to validate
299  // from experience we know that assembly mistakes happen and quality control is required
302 
303  for (int i = 0 ; i < 100 ; i++) {
304  // turning pin ON and busy-waiting a bit
305  palWritePad(criticalErrorLedPort, criticalErrorLedPin, 1);
306  }
307 
308  palWritePad(criticalErrorLedPort, criticalErrorLedPin, 0);
309 #endif // VR_HW_CHECK_MODE
310 
311  const auto& vvtShape = tc->vvtShape[camIndex];
312 
313  bool isVvtWithRealDecoder = vvtWithRealDecoder(engineConfiguration->vvtMode[camIndex]);
314 
315  // Non real decoders only use the rising edge
316  bool vvtUseOnlyRise = !isVvtWithRealDecoder || vvtShape.useOnlyRisingEdges;
317  bool isImportantFront = !vvtUseOnlyRise || (front == TriggerValue::RISE);
318 
319  logVvtFront(vvtUseOnlyRise, isImportantFront, front, nowNt, index);
320 
321  if (!isImportantFront) {
322  // This edge is unimportant, ignore it.
323  return;
324  }
325 
326  // If the main trigger is not synchronized, don't decode VVT yet
327  if (!tc->triggerState.getShaftSynchronized()) {
328  return;
329  }
330 
331  TriggerDecoderBase& vvtDecoder = tc->vvtState[bankIndex][camIndex];
332 
333  if (isVvtWithRealDecoder) {
334  vvtDecoder.decodeTriggerEvent(
335  "vvt",
336  vvtShape,
337  nullptr,
338  tc->vvtTriggerConfiguration[camIndex],
340  // yes we log data from all VVT channels into same fields for now
342  tc->triggerState.vvtToothDurations0 = (uint32_t)NT2US(vvtDecoder.toothDurations[0]);
344  }
345 
346  // here we count all cams together
347  tc->vvtCamCounter++;
348 
349  auto currentPhase = tc->getCurrentEnginePhase(nowNt);
350  if (!currentPhase) {
351  // If we couldn't resolve engine speed (yet primary trigger is sync'd), this
352  // probably means that we have partial crank sync, but not RPM information yet
353  return;
354  }
355 
356  angle_t angleFromPrimarySyncPoint = currentPhase.Value;
357  // convert trigger cycle angle into engine cycle angle
358  angle_t currentPosition = angleFromPrimarySyncPoint - tdcPosition();
359  // https://github.com/rusefi/rusefi/issues/1713 currentPosition could be negative that's expected
360 
361 #if EFI_UNIT_TEST
362  tc->currentVVTEventPosition[bankIndex][camIndex] = currentPosition;
363 #endif // EFI_UNIT_TEST
364 
365  tc->triggerState.vvtCurrentPosition = currentPosition;
366 
367  if (isVvtWithRealDecoder && vvtDecoder.currentCycle.current_index != 0) {
368  // this is not sync tooth - exiting
369  return;
370  }
371 
372  auto vvtPosition = engineConfiguration->vvtOffsets[bankIndex * CAMS_PER_BANK + camIndex] - currentPosition;
373  tc->triggerState.vvtToothPosition[index] = vvtPosition;
374 
375  switch(engineConfiguration->vvtMode[camIndex]) {
376  case VVT_TOYOTA_3_TOOTH:
377  {
380  // we do not know if we are in sync or out of sync, so we have to be looking for both possibilities
381  if ((currentPosition < from || currentPosition > to) &&
382  (currentPosition < from + 360 || currentPosition > to + 360)) {
383  // outside of the expected range
384  return;
385  }
386  }
387  break;
388  default:
389  // else, do nothing
390  break;
391  }
392 
393  // this could be just an 'if' but let's have it expandable for future use :)
394  switch(engineConfiguration->vvtMode[camIndex]) {
395  case VVT_HONDA_K_INTAKE:
396  // honda K has four tooth in VVT intake trigger, so we just wrap each of those to 720 / 4
397  vvtPosition = wrapVvt(vvtPosition, 180);
398  break;
399  default:
400  // else, do nothing
401  break;
402  }
403 
404  // Only do engine sync using one cam, other cams just provide VVT position.
405  if (index == engineConfiguration->engineSyncCam) {
406  angle_t crankOffset = adjustCrankPhase(camIndex);
407  // vvtPosition was calculated against wrong crank zero position. Now that we have adjusted crank position we
408  // shall adjust vvt position as well
409  vvtPosition -= crankOffset;
410  vvtPosition = wrapVvt(vvtPosition, FOUR_STROKE_CYCLE_DURATION);
411 
412  if (absF(angleFromPrimarySyncPoint) < 7) {
413  /**
414  * 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
415  * wrong order due to belt flex or else
416  * https://github.com/rusefi/rusefi/issues/3269
417  */
418  warning(ObdCode::CUSTOM_VVT_SYNC_POSITION, "VVT sync position too close to trigger sync");
419  }
420  } else {
421  // Not using this cam for engine sync, just wrap the value in to the reasonable range
422  vvtPosition = wrapVvt(vvtPosition, FOUR_STROKE_CYCLE_DURATION);
423  }
424 
425  // Only record VVT position if we have full engine sync - may be bogus before that point
427  tc->vvtPosition[bankIndex][camIndex] = vvtPosition;
428  } else {
429  tc->vvtPosition[bankIndex][camIndex] = 0;
430  }
431 }
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,...)
ioportmask_t criticalErrorLedPin
Definition: efi_gpio.cpp:809
ioportid_t criticalErrorLedPort
Definition: efi_gpio.cpp:808
uint32_t ioportmask_t
Digital I/O port sized unsigned type.
Definition: hal_pal_lld.h:78
GPIO_TypeDef * ioportid_t
Port Identifier.
Definition: hal_pal_lld.h:102
@ CUSTOM_VVT_SYNC_POSITION
@ CUSTOM_VVT_MODE_NOT_SELECTED
float angle_t
Definition: rusefi_types.h:58
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 443 of file trigger_central.cpp.

443  {
446 #ifdef VR_HW_CHECK_MODE
447  // some boards do not have hardware VR input LEDs which makes such boards harder to validate
448  // from experience we know that assembly mistakes happen and quality control is required
451 
452 #if HW_CHECK_ALWAYS_STIMULATE
454 #endif // HW_CHECK_ALWAYS_STIMULATE
455 
456 
457  for (int i = 0 ; i < 100 ; i++) {
458  // turning pin ON and busy-waiting a bit
459  palWritePad(criticalErrorLedPort, criticalErrorLedPin, 1);
460  }
461 
462  palWritePad(criticalErrorLedPort, criticalErrorLedPin, 0);
463 #endif // VR_HW_CHECK_MODE
464 
466  // sensor noise + self-stim = loss of trigger sync
467  return;
468  }
469 
470  handleShaftSignal(signalIndex, isRising, timestamp);
471 }
bool directSelfStimulation
bool hwTriggerInputEnabled
@ HandleShaftSignal
void handleShaftSignal(int signalIndex, bool isRising, efitick_t timestamp)
void disableTriggerStimulator()

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 260 of file trigger_central.cpp.

260  {
261  hwHandleVvtCamSignal(isRising ? TriggerValue::RISE : TriggerValue::FALL, timestamp, index);
262 }
void hwHandleVvtCamSignal(bool isRising, efitick_t timestamp, int index)

Referenced by cam_callback(), comp_cam_callback(), and TriggerCentral::decodeMapCam().

Here is the caller graph for this function:

◆ hwHandleVvtCamSignal() [2/2]

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

Definition at line 265 of file trigger_central.cpp.

265  {
268  // sensor noise + self-stim = loss of trigger sync
269  return;
270  }
271  handleVvtCamSignal(front, nowNt, index);
272 }
void handleVvtCamSignal(TriggerValue front, efitick_t nowNt, int index)
Here is the call graph for this function:

◆ initTriggerCentral()

void initTriggerCentral ( )

Definition at line 1224 of file trigger_central.cpp.

1224  {
1225 
1226 #if EFI_ENGINE_SNIFFER
1228 #endif /* EFI_ENGINE_SNIFFER */
1229 
1230 #if EFI_PROD_CODE || EFI_SIMULATOR
1231  addConsoleAction(CMD_TRIGGERINFO, triggerInfo);
1232  addConsoleAction("trigger_shape_info", triggerShapeInfo);
1234 #endif // EFI_PROD_CODE || EFI_SIMULATOR
1235 
1236 }
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 1072 of file trigger_central.cpp.

1072  {
1074  shape.initializeSyncPoint(initState, p_config);
1075 }
trigger_config_s TriggerType
void initializeTriggerWaveform(operation_mode_e triggerOperationMode, const trigger_config_s &triggerType)

Referenced by TriggerCentral::updateWaveform().

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 231 of file trigger_central.cpp.

231  {
232  if (isImportantFront && isBrainPinValid(engineConfiguration->camInputsDebug[index])) {
233 #if EFI_PROD_CODE
234  writePad("cam debug", engineConfiguration->camInputsDebug[index], 1);
235 #endif /* EFI_PROD_CODE */
237  }
238 
240  // If we care about both edges OR displayLogicLevel is set, log every front exactly as it is
242 
243 #if EFI_TOOTH_LOGGER
245 #endif /* EFI_TOOTH_LOGGER */
246  } else {
247  if (isImportantFront) {
248  // On the important edge, log a rise+fall pair, and nothing on the real falling edge
251 
252 #if EFI_TOOTH_LOGGER
255 #endif /* EFI_TOOTH_LOGGER */
256  }
257  }
258 }
void addEngineSnifferVvtEvent(int vvtIndex, FrontDirection frontDirection)
bool isBrainPinValid(brain_pin_e brainPin)

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 1020 of file trigger_central.cpp.

1020  {
1021  bool changed = false;
1022  // todo: how do we static_assert here?
1023  criticalAssertVoid(efi::size(engineConfiguration->camInputs) == efi::size(engineConfiguration->vvtOffsets), "sizes");
1024 
1025  for (size_t camIndex = 0; camIndex < efi::size(engineConfiguration->camInputs); camIndex++) {
1026  changed |= isConfigurationChanged(camInputs[camIndex]);
1027  changed |= isConfigurationChanged(vvtOffsets[camIndex]);
1028  }
1029 
1030  for (size_t i = 0; i < efi::size(engineConfiguration->triggerGapOverrideFrom); i++) {
1031  changed |= isConfigurationChanged(triggerGapOverrideFrom[i]);
1032  changed |= isConfigurationChanged(triggerGapOverrideTo[i]);
1033  }
1034 
1035  for (size_t i = 0; i < efi::size(engineConfiguration->triggerInputPins); i++) {
1036  changed |= isConfigurationChanged(triggerInputPins[i]);
1038  if (engineConfiguration->vvtMode[0] == VVT_MAP_V_TWIN && isBrainPinValid(pin)) {
1039  criticalError("Please no physical sensors in CAM by MAP mode index=%d %s", i, hwPortname(pin));
1040  }
1041  }
1042 
1043  for (size_t i = 0; i < efi::size(engineConfiguration->vvtMode); i++) {
1044  changed |= isConfigurationChanged(vvtMode[i]);
1045  }
1046 
1047  changed |= isConfigurationChanged(trigger.type);
1048  changed |= isConfigurationChanged(skippedWheelOnCam);
1049  changed |= isConfigurationChanged(twoStroke);
1050  changed |= isConfigurationChanged(globalTriggerAngleOffset);
1051  changed |= isConfigurationChanged(trigger.customTotalToothCount);
1052  changed |= isConfigurationChanged(trigger.customSkippedToothCount);
1053  changed |= isConfigurationChanged(overrideTriggerGaps);
1054  changed |= isConfigurationChanged(gapTrackingLengthOverride);
1055  changed |= isConfigurationChanged(overrideVvtTriggerGaps);
1056  changed |= isConfigurationChanged(gapVvtTrackingLengthOverride);
1057 
1058  if (changed) {
1059  #if EFI_ENGINE_CONTROL
1062  #endif
1063  }
1064 #if EFI_DEFAILED_LOGGING
1065  efiPrintf("isTriggerConfigChanged=%d", triggerConfigChanged);
1066 #endif /* EFI_DEFAILED_LOGGING */
1067 
1068  // we do not want to miss two updates in a row
1070 }
void updateTriggerWaveform()
Definition: engine.cpp:120
TriggerNoiseFilter noiseFilter
bool triggerConfigChangedOnLastConfigurationChange
Gpio
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]
composite packet size

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 566 of file trigger_central.cpp.

566  {
567  if (!getTriggerCentral()->isEngineSnifferEnabled) { // this is here just as a shortcut so that we avoid engine sniffer as soon as possible
568  return; // engineSnifferRpmThreshold is accounted for inside getTriggerCentral()->isEngineSnifferEnabled
569  }
570 
571  int wheelIndex = wheelIndeces[(int )ckpSignalType];
572 
573  bool isUp = isUpEvent[(int) ckpSignalType];
574 
575  addEngineSnifferCrankEvent(wheelIndex, triggerEventIndex, isUp ? FrontDirection::UP : FrontDirection::DOWN);
576  if (addOppositeEvent) {
577  // let's add the opposite event right away
578  addEngineSnifferCrankEvent(wheelIndex, triggerEventIndex, isUp ? FrontDirection::DOWN : FrontDirection::UP);
579  }
580 }
void addEngineSnifferCrankEvent(int wheelIndex, int triggerEventIndex, FrontDirection frontDirection)
static const bool isUpEvent[4]
static const int wheelIndeces[4]

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 1013 of file trigger_central.cpp.

1013  {
1014 #if !EFI_UNIT_TEST
1016  triggerInfo();
1017 #endif
1018 }

Referenced by initTriggerCentral().

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

◆ triggerInfo()

void triggerInfo ( void  )

Definition at line 917 of file trigger_central.cpp.

917  {
918 #if EFI_PROD_CODE || EFI_SIMULATOR
919 
921  TriggerWaveform *ts = &tc->triggerShape;
922 
923 
924 #if (HAL_TRIGGER_USE_PAL == TRUE) && (PAL_USE_CALLBACKS == TRUE)
925  efiPrintf("trigger PAL mode %d", tc->hwTriggerInputEnabled);
926 #else
927 
928 #endif /* HAL_TRIGGER_USE_PAL */
929 
930  efiPrintf("Template %s (%d) trigger %s (%d) syncEdge=%s tdcOffset=%.2f",
933  getSyncEdge(TRIGGER_WAVEFORM(syncEdge)), TRIGGER_WAVEFORM(tdcPosition));
934 
936  efiPrintf("total %d/skipped %d", engineConfiguration->trigger.customTotalToothCount,
938  }
939 
940 
941  efiPrintf("trigger#1 event counters up=%d/down=%d", tc->getHwEventCounter(0),
942  tc->getHwEventCounter(1));
943 
944  if (ts->needSecondTriggerInput) {
945  efiPrintf("trigger#2 event counters up=%d/down=%d", tc->getHwEventCounter(2),
946  tc->getHwEventCounter(3));
947  }
948  efiPrintf("expected cycle events %d/%d",
949  TRIGGER_WAVEFORM(getExpectedEventCount(TriggerWheel::T_PRIMARY)),
950  TRIGGER_WAVEFORM(getExpectedEventCount(TriggerWheel::T_SECONDARY)));
951 
952  efiPrintf("trigger type=%d/need2ndChannel=%s", engineConfiguration->trigger.type,
953  boolToString(TRIGGER_WAVEFORM(needSecondTriggerInput)));
954 
955 
956  efiPrintf("synchronizationNeeded=%s/isError=%s/total errors=%d ord_err=%d/total revolutions=%d/self=%s",
963 
964  if (TRIGGER_WAVEFORM(isSynchronizationNeeded)) {
965  efiPrintf("gap from %.2f to %.2f", TRIGGER_WAVEFORM(synchronizationRatioFrom[0]), TRIGGER_WAVEFORM(synchronizationRatioTo[0]));
966  }
967 
968 #endif /* EFI_PROD_CODE || EFI_SIMULATOR */
969 
970 #if EFI_PROD_CODE
971 
972  efiPrintf("primary trigger input: %s", hwPortname(engineConfiguration->triggerInputPins[0]));
973  efiPrintf("primary trigger simulator: %s %s freq=%d",
977 
978  if (ts->needSecondTriggerInput) {
979  efiPrintf("secondary trigger input: %s", hwPortname(engineConfiguration->triggerInputPins[1]));
980 #if EFI_EMULATE_POSITION_SENSORS
981  efiPrintf("secondary trigger simulator: %s %s phase=%d",
984 #endif /* EFI_EMULATE_POSITION_SENSORS */
985  }
986 
987 
988  for (int camInputIndex = 0; camInputIndex<CAM_INPUTS_COUNT;camInputIndex++) {
989  if (isBrainPinValid(engineConfiguration->camInputs[camInputIndex])) {
990  int camLogicalIndex = camInputIndex % CAMS_PER_BANK;
991  efiPrintf("VVT input: %s mode %s", hwPortname(engineConfiguration->camInputs[camInputIndex]),
992  getVvt_mode_e(engineConfiguration->vvtMode[camLogicalIndex]));
993  efiPrintf("VVT %d event counters: %d/%d",
994  camInputIndex,
995  tc->vvtEventRiseCounter[camInputIndex], tc->vvtEventFallCounter[camInputIndex]);
996  }
997  }
998 
999  efiPrintf("primary logic input: %s", hwPortname(engineConfiguration->logicAnalyzerPins[0]));
1000  efiPrintf("secondary logic input: %s", hwPortname(engineConfiguration->logicAnalyzerPins[1]));
1001 
1002 
1003  efiPrintf("totalTriggerHandlerMaxTime=%d", triggerMaxDuration);
1004 
1005 #endif /* EFI_PROD_CODE */
1006 
1007 #if EFI_ENGINE_SNIFFER
1008  efiPrintf("engine sniffer current size=%d", waveChart.getSize());
1009 #endif /* EFI_ENGINE_SNIFFER */
1010 
1011 }
const char * getPin_output_mode_e(pin_output_mode_e value)
const char * getVvt_mode_e(vvt_mode_e value)
const char * getTrigger_type_e(trigger_type_e value)
const char * getEngine_type_e(engine_type_e value)
const char * getSyncEdge(SyncEdge value)
pwm_config_safe_state_s safe
int getHwEventCounter(int index) const
int getCrankSynchronizationCounter() const
uint32_t orderingErrorCounter
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 900 of file trigger_central.cpp.

900  {
901 #if EFI_PROD_CODE || EFI_SIMULATOR
903  TriggerFormDetails *triggerFormDetails = &getTriggerCentral()->triggerFormDetails;
904  efiPrintf("syncEdge=%s", getSyncEdge(TRIGGER_WAVEFORM(syncEdge)));
905  efiPrintf("gap from %.2f to %.2f", TRIGGER_WAVEFORM(synchronizationRatioFrom[0]), TRIGGER_WAVEFORM(synchronizationRatioTo[0]));
906 
907  for (size_t i = 0; i < shape->getSize(); i++) {
908  efiPrintf("event %d %.2f", i, triggerFormDetails->eventAngles[i]);
909  }
910 #endif
911 }
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 146 of file trigger_central.cpp.

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

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 1214 of file trigger_central.cpp.

1214  {
1216  criticalError("First trigger channel not configured while second one is.");
1217  }
1218 
1220  criticalError("First bank cam input is required if second bank specified");
1221  }
1222 }

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 126 of file trigger_central.cpp.

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

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 220 of file trigger_central.cpp.

220  {
221  // Wrap VVT position in to the range [-360, 360)
222  while (vvtPosition < -period / 2) {
223  vvtPosition += period;
224  }
225  while (vvtPosition >= period / 2) {
226  vvtPosition -= period;
227  }
228  return vvtPosition;
229 }
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"  )

◆ isUpEvent

const bool isUpEvent[4] = { false, true, false, true }
static

Definition at line 563 of file trigger_central.cpp.

Referenced by reportEventToWaveChart().

◆ maxTriggerReentrant

int maxTriggerReentrant = 0

◆ triggerDuration

uint32_t triggerDuration

Definition at line 435 of file trigger_central.cpp.

Referenced by handleShaftSignal().

◆ triggerEmulatorSignals

PwmConfig triggerEmulatorSignals[NUM_EMULATOR_CHANNELS]
extern

◆ triggerMaxDuration

uint32_t triggerMaxDuration = 0

Definition at line 436 of file trigger_central.cpp.

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

◆ triggerReentrant

int triggerReentrant = 0

Definition at line 433 of file trigger_central.cpp.

Referenced by handleShaftSignal().

◆ waveChart

WaveChart waveChart

◆ wheelIndeces

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

Definition at line 564 of file trigger_central.cpp.

Referenced by reportEventToWaveChart().

Go to the source code of this file.