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_DEV:
195  case VVT_FORD_ST170:
196  case VVT_BARRA_3_PLUS_1:
197  case VVT_NISSAN_MR:
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:92
angle_t syncEnginePhaseAndReport(int divider, int remainder)
EngineRotationState * getEngineRotationState()
Definition: engine.cpp:592
TriggerCentral * getTriggerCentral()
Definition: engine.cpp:609
engine_configuration_s * engineConfiguration
vvt_mode_e
Definition: rusefi_enums.h:124
operation_mode_e
Definition: rusefi_enums.h:251
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 747 of file trigger_central.cpp.

747 { 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 1093 of file trigger_central.cpp.

1096  {
1097 
1098 #if EFI_PROD_CODE
1099  efiAssertVoid(ObdCode::CUSTOM_TRIGGER_STACK, hasLotsOfRemainingStack(), "calc s");
1100 #endif
1101 
1102  shape.initializeSyncPoint(initState, primaryTriggerConfiguration);
1103 
1104  if (shape.getSize() >= PWM_PHASE_MAX_COUNT) {
1105  // todo: by the time we are here we had already modified a lot of RAM out of bounds!
1106  firmwareError(ObdCode::CUSTOM_ERR_TRIGGER_WAVEFORM_TOO_LONG, "Trigger length above maximum: %d", shape.getSize());
1107  shape.setShapeDefinitionError(true);
1108  return;
1109  }
1110 
1111  if (shape.getSize() == 0) {
1112  firmwareError(ObdCode::CUSTOM_ERR_TRIGGER_ZERO, "triggerShape size is zero");
1113  }
1114 }
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:272
@ FOUR_STROKE_TWELVE_TIMES_CRANK_SENSOR
Definition: rusefi_enums.h:282
@ FOUR_STROKE_THREE_TIMES_CRANK_SENSOR
Definition: rusefi_enums.h:277
@ FOUR_STROKE_CRANK_SENSOR
Definition: rusefi_enums.h:258
@ OM_NONE
Definition: rusefi_enums.h:252
@ FOUR_STROKE_CAM_SENSOR
Definition: rusefi_enums.h:262
@ TWO_STROKE
Definition: rusefi_enums.h:266
@ FOUR_STROKE_SIX_TIMES_CRANK_SENSOR
Definition: rusefi_enums.h:287

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

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

275  {
277  if (index == 0) {
279  } else if (index == 1) {
281  } else if (index == 2) {
283  } else if (index == 3) {
285  }
286 
287  int bankIndex = BANK_BY_INDEX(index);
288  int camIndex = CAM_BY_INDEX(index);
289  if (front == TriggerValue::RISE) {
290  tc->vvtEventRiseCounter[index]++;
291  } else {
292  tc->vvtEventFallCounter[index]++;
293  }
294  if (engineConfiguration->vvtMode[camIndex] == VVT_INACTIVE) {
295  warning(ObdCode::CUSTOM_VVT_MODE_NOT_SELECTED, "VVT: event on %d but no mode", camIndex);
296  }
297 
298 #ifdef VR_HW_CHECK_MODE
299  // some boards do not have hardware VR input LEDs which makes such boards harder to validate
300  // from experience we know that assembly mistakes happen and quality control is required
303 
304  for (int i = 0 ; i < 100 ; i++) {
305  // turning pin ON and busy-waiting a bit
306  palWritePad(criticalErrorLedPort, criticalErrorLedPin, 1);
307  }
308 
309  palWritePad(criticalErrorLedPort, criticalErrorLedPin, 0);
310 #endif // VR_HW_CHECK_MODE
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
328  if (!tc->triggerState.getShaftSynchronized()) {
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  // yes we log data from all VVT channels into same fields for now
343  tc->triggerState.vvtToothDurations0 = (uint32_t)NT2US(vvtDecoder.toothDurations[0]);
345  }
346 
347  // here we count all cams together
348  tc->vvtCamCounter++;
349 
350  auto currentPhase = tc->getCurrentEnginePhase(nowNt);
351  if (!currentPhase) {
352  // If we couldn't resolve engine speed (yet primary trigger is sync'd), this
353  // probably means that we have partial crank sync, but not RPM information yet
354  return;
355  }
356 
357  angle_t angleFromPrimarySyncPoint = currentPhase.Value;
358  // convert trigger cycle angle into engine cycle angle
359  angle_t currentPosition = angleFromPrimarySyncPoint - tdcPosition();
360  // https://github.com/rusefi/rusefi/issues/1713 currentPosition could be negative that's expected
361 
362 #if EFI_UNIT_TEST
363  tc->currentVVTEventPosition[bankIndex][camIndex] = currentPosition;
364 #endif // EFI_UNIT_TEST
365 
366  tc->triggerState.vvtCurrentPosition = currentPosition;
367 
368  if (isVvtWithRealDecoder && vvtDecoder.currentCycle.current_index != 0) {
369  // this is not sync tooth - exiting
370  return;
371  }
372 
373  auto vvtPosition = engineConfiguration->vvtOffsets[bankIndex * CAMS_PER_BANK + camIndex] - currentPosition;
374  tc->triggerState.vvtToothPosition[index] = vvtPosition;
375 
376  switch(engineConfiguration->vvtMode[camIndex]) {
377  case VVT_TOYOTA_3_TOOTH:
378  {
381  // we do not know if we are in sync or out of sync, so we have to be looking for both possibilities
382  if ((currentPosition < from || currentPosition > to) &&
383  (currentPosition < from + 360 || currentPosition > to + 360)) {
384  // outside of the expected range
385  return;
386  }
387  }
388  break;
389  default:
390  // else, do nothing
391  break;
392  }
393 
394  // this could be just an 'if' but let's have it expandable for future use :)
395  switch(engineConfiguration->vvtMode[camIndex]) {
396  case VVT_HONDA_K_INTAKE:
397  // honda K has four tooth in VVT intake trigger, so we just wrap each of those to 720 / 4
398  vvtPosition = wrapVvt(vvtPosition, 180);
399  break;
400  default:
401  // else, do nothing
402  break;
403  }
404 
405  // Only do engine sync using one cam, other cams just provide VVT position.
406  if (index == engineConfiguration->engineSyncCam) {
407  angle_t crankOffset = adjustCrankPhase(camIndex);
408  // vvtPosition was calculated against wrong crank zero position. Now that we have adjusted crank position we
409  // shall adjust vvt position as well
410  vvtPosition -= crankOffset;
411  vvtPosition = wrapVvt(vvtPosition, FOUR_STROKE_CYCLE_DURATION);
412 
413  if (absF(angleFromPrimarySyncPoint) < 7) {
414  /**
415  * 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
416  * wrong order due to belt flex or else
417  * https://github.com/rusefi/rusefi/issues/3269
418  */
419  warning(ObdCode::CUSTOM_VVT_SYNC_POSITION, "VVT sync position too close to trigger sync");
420  }
421  } else {
422  // Not using this cam for engine sync, just wrap the value in to the reasonable range
423  vvtPosition = wrapVvt(vvtPosition, FOUR_STROKE_CYCLE_DURATION);
424  }
425 
426  // Only record VVT position if we have full engine sync - may be bogus before that point
428  tc->vvtPosition[bankIndex][camIndex] = vvtPosition;
429  } else {
430  tc->vvtPosition[bankIndex][camIndex] = 0;
431  }
432 }
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:808
ioportid_t criticalErrorLedPort
Definition: efi_gpio.cpp:807
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:59
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 444 of file trigger_central.cpp.

444  {
447 #ifdef VR_HW_CHECK_MODE
448  // some boards do not have hardware VR input LEDs which makes such boards harder to validate
449  // from experience we know that assembly mistakes happen and quality control is required
452 
453 #if HW_CHECK_ALWAYS_STIMULATE
455 #endif // HW_CHECK_ALWAYS_STIMULATE
456 
457 
458  for (int i = 0 ; i < 100 ; i++) {
459  // turning pin ON and busy-waiting a bit
460  palWritePad(criticalErrorLedPort, criticalErrorLedPin, 1);
461  }
462 
463  palWritePad(criticalErrorLedPort, criticalErrorLedPin, 0);
464 #endif // VR_HW_CHECK_MODE
465 
467  // sensor noise + self-stim = loss of trigger sync
468  return;
469  }
470 
471  handleShaftSignal(signalIndex, isRising, timestamp);
472 }
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 261 of file trigger_central.cpp.

261  {
262  hwHandleVvtCamSignal(isRising ? TriggerValue::RISE : TriggerValue::FALL, timestamp, index);
263 }
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 266 of file trigger_central.cpp.

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

◆ initTriggerCentral()

void initTriggerCentral ( )

Definition at line 1228 of file trigger_central.cpp.

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

1075  {
1077  shape.initializeSyncPoint(initState, p_config);
1078 }
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 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 */
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
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
256 #endif /* EFI_TOOTH_LOGGER */
257  }
258  }
259 }
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 1023 of file trigger_central.cpp.

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

567  {
568  if (!getTriggerCentral()->isEngineSnifferEnabled) { // this is here just as a shortcut so that we avoid engine sniffer as soon as possible
569  return; // engineSnifferRpmThreshold is accounted for inside getTriggerCentral()->isEngineSnifferEnabled
570  }
571 
572  int wheelIndex = wheelIndeces[(int )ckpSignalType];
573 
574  bool isUp = isUpEvent[(int) ckpSignalType];
575 
576  addEngineSnifferCrankEvent(wheelIndex, triggerEventIndex, isUp ? FrontDirection::UP : FrontDirection::DOWN);
577  if (addOppositeEvent) {
578  // let's add the opposite event right away
579  addEngineSnifferCrankEvent(wheelIndex, triggerEventIndex, isUp ? FrontDirection::DOWN : FrontDirection::UP);
580  }
581 }
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 1016 of file trigger_central.cpp.

1016  {
1017 #if !EFI_UNIT_TEST
1019  triggerInfo();
1020 #endif
1021 }

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

918  {
919 #if EFI_PROD_CODE || EFI_SIMULATOR
920 
922  TriggerWaveform *ts = &tc->triggerShape;
923 
924 
925 #if (HAL_TRIGGER_USE_PAL == TRUE) && (PAL_USE_CALLBACKS == TRUE)
926  efiPrintf("trigger PAL mode %d", tc->hwTriggerInputEnabled);
927 #else
928 
929 #endif /* HAL_TRIGGER_USE_PAL */
930 
931  efiPrintf("Template %s (%d) trigger %s (%d) syncEdge=%s tdcOffset=%.2f",
936  getSyncEdge(TRIGGER_WAVEFORM(syncEdge)), TRIGGER_WAVEFORM(tdcPosition));
937 
939  efiPrintf("total %d/skipped %d", engineConfiguration->trigger.customTotalToothCount,
941  }
942 
943 
944  efiPrintf("trigger#1 event counters up=%d/down=%d", tc->getHwEventCounter(0),
945  tc->getHwEventCounter(1));
946 
947  if (ts->needSecondTriggerInput) {
948  efiPrintf("trigger#2 event counters up=%d/down=%d", tc->getHwEventCounter(2),
949  tc->getHwEventCounter(3));
950  }
951  efiPrintf("expected cycle events %d/%d",
952  TRIGGER_WAVEFORM(getExpectedEventCount(TriggerWheel::T_PRIMARY)),
953  TRIGGER_WAVEFORM(getExpectedEventCount(TriggerWheel::T_SECONDARY)));
954 
955  efiPrintf("trigger type=%d/need2ndChannel=%s", (int)engineConfiguration->trigger.type,
956  boolToString(TRIGGER_WAVEFORM(needSecondTriggerInput)));
957 
958 
959  efiPrintf("synchronizationNeeded=%s/isError=%s/total errors=%lu ord_err=%lu/total revolutions=%d/self=%s",
966 
967  if (TRIGGER_WAVEFORM(isSynchronizationNeeded)) {
968  efiPrintf("gap from %.2f to %.2f", TRIGGER_WAVEFORM(synchronizationRatioFrom[0]), TRIGGER_WAVEFORM(synchronizationRatioTo[0]));
969  }
970 
971 #endif /* EFI_PROD_CODE || EFI_SIMULATOR */
972 
973 #if EFI_PROD_CODE
974 
975  efiPrintf("primary trigger input: %s", hwPortname(engineConfiguration->triggerInputPins[0]));
976  efiPrintf("primary trigger simulator: %s %s freq=%d",
980 
981  if (ts->needSecondTriggerInput) {
982  efiPrintf("secondary trigger input: %s", hwPortname(engineConfiguration->triggerInputPins[1]));
983 #if EFI_EMULATE_POSITION_SENSORS
984  efiPrintf("secondary trigger simulator: %s %s phase=%d",
987 #endif /* EFI_EMULATE_POSITION_SENSORS */
988  }
989 
990 
991  for (int camInputIndex = 0; camInputIndex<CAM_INPUTS_COUNT;camInputIndex++) {
992  if (isBrainPinValid(engineConfiguration->camInputs[camInputIndex])) {
993  int camLogicalIndex = camInputIndex % CAMS_PER_BANK;
994  efiPrintf("VVT input: %s mode %s", hwPortname(engineConfiguration->camInputs[camInputIndex]),
995  getVvt_mode_e(engineConfiguration->vvtMode[camLogicalIndex]));
996  efiPrintf("VVT %d event counters: %d/%d",
997  camInputIndex,
998  tc->vvtEventRiseCounter[camInputIndex], tc->vvtEventFallCounter[camInputIndex]);
999  }
1000  }
1001 
1002  efiPrintf("primary logic input: %s", hwPortname(engineConfiguration->logicAnalyzerPins[0]));
1003  efiPrintf("secondary logic input: %s", hwPortname(engineConfiguration->logicAnalyzerPins[1]));
1004 
1005 
1006  efiPrintf("totalTriggerHandlerMaxTime=%lu", triggerMaxDuration);
1007 
1008 #endif /* EFI_PROD_CODE */
1009 
1010 #if EFI_ENGINE_SNIFFER
1011  efiPrintf("engine sniffer current size=%d", waveChart.getSize());
1012 #endif /* EFI_ENGINE_SNIFFER */
1013 
1014 }
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 901 of file trigger_central.cpp.

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

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

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 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"  )

◆ isUpEvent

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

Definition at line 564 of file trigger_central.cpp.

Referenced by reportEventToWaveChart().

◆ maxTriggerReentrant

int maxTriggerReentrant = 0

◆ triggerDuration

uint32_t triggerDuration

Definition at line 436 of file trigger_central.cpp.

Referenced by handleShaftSignal().

◆ triggerEmulatorSignals

PwmConfig triggerEmulatorSignals[NUM_EMULATOR_CHANNELS]
extern

◆ triggerMaxDuration

uint32_t triggerMaxDuration = 0

Definition at line 437 of file trigger_central.cpp.

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

◆ triggerReentrant

int triggerReentrant = 0

Definition at line 434 of file trigger_central.cpp.

Referenced by handleShaftSignal().

◆ waveChart

WaveChart waveChart

◆ wheelIndeces

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

Definition at line 565 of file trigger_central.cpp.

Referenced by reportEventToWaveChart().

Go to the source code of this file.