rusEFI
An attempt to build an Engine Control Unit
Functions | Variables
main_trigger_callback.cpp File Reference

Detailed Description

Main logic is here!

See http://rusefi.com/docs/html/

Date
Feb 7, 2013
Author
Andrey Belomutskiy, (c) 2012-2020

This file is part of rusEfi - see http://rusefi.com

rusEfi is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.

rusEfi is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.

Definition in file main_trigger_callback.cpp.

Functions

void startSimultaniousInjection (Engine *engine)
 
static void endSimultaniousInjectionOnlyTogglePins (Engine *engine)
 
void endSimultaniousInjection (InjectionEvent *event)
 
static void turnInjectionPinHigh (InjectorOutputPin *output)
 
void turnInjectionPinHigh (InjectionEvent *event)
 
static void turnInjectionPinLow (InjectorOutputPin *output)
 
void turnInjectionPinLow (InjectionEvent *event)
 
void handleFuelInjectionEvent (int injEventIndex, InjectionEvent *event, int rpm, efitick_t nowNt DECLARE_ENGINE_PARAMETER_SUFFIX)
 
static ALWAYS_INLINE void handleFuel (const bool limitedFuel, uint32_t trgEventIndex, int rpm, efitick_t nowNt DECLARE_ENGINE_PARAMETER_SUFFIX)
 
static void mainTriggerCallback (trigger_event_e ckpSignalType, uint32_t trgEventIndex, efitick_t edgeTimestamp DECLARE_ENGINE_PARAMETER_SUFFIX)
 
static bool isPrimeInjectionPulseSkipped (DECLARE_ENGINE_PARAMETER_SIGNATURE)
 
void startPrimeInjectionPulse (DECLARE_ENGINE_PARAMETER_SIGNATURE)
 
void updatePrimeInjectionPulseState (DECLARE_ENGINE_PARAMETER_SIGNATURE)
 
static void showMainInfo (Engine *engine)
 
void initMainEventListener (Logging *sharedLogger DECLARE_ENGINE_PARAMETER_SUFFIX)
 

Variables

 EXTERN_ENGINE
 
static const char * prevOutputName = nullptr
 
static InjectionEvent primeInjEvent
 
static Logginglogger
 
uint32_t * cyccnt = (uint32_t*) &DWT->CYCCNT
 

Function Documentation

◆ endSimultaniousInjection()

void endSimultaniousInjection ( InjectionEvent event)

Definition at line 81 of file main_trigger_callback.cpp.

81  {
82 #if EFI_UNIT_TEST
83  Engine *engine = event->engine;
84  EXPAND_Engine;
85 #endif
86  event->isScheduled = false;
87 
89  engine->injectionEvents.addFuelEventsForCylinder(event->ownIndex PASS_ENGINE_PARAMETER_SUFFIX);
90 }
Engine * engine
bool addFuelEventsForCylinder(int cylinderIndex DECLARE_ENGINE_PARAMETER_SUFFIX)
static void endSimultaniousInjectionOnlyTogglePins(Engine *engine)
FuelSchedule injectionEvents
Definition: engine.h:139
Definition: engine.h:57

Referenced by handleFuelInjectionEvent().

Here is the call graph for this function:

◆ endSimultaniousInjectionOnlyTogglePins()

static void endSimultaniousInjectionOnlyTogglePins ( Engine engine)
static

Definition at line 75 of file main_trigger_callback.cpp.

75  {
76  for (int i = 0; i < engine->engineConfigurationPtr->specs.cylindersCount; i++) {
78  }
79 }
Engine * engine
InjectorOutputPin injectors[INJECTION_PIN_COUNT]
Definition: efi_gpio.h:174
EnginePins enginePins
Definition: efi_gpio.cpp:32
engine_configuration_s * engineConfigurationPtr
Definition: engine.h:186

Referenced by endSimultaniousInjection(), and startPrimeInjectionPulse().

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

◆ handleFuel()

static ALWAYS_INLINE void handleFuel ( const bool  limitedFuel,
uint32_t  trgEventIndex,
int  rpm,
efitick_t nowNt  DECLARE_ENGINE_PARAMETER_SUFFIX 
)
static

Ignition events are defined by addFuelEvents() according to selected fueling strategy

Definition at line 284 of file main_trigger_callback.cpp.

284  {
286 
287  efiAssertVoid(CUSTOM_STACK_6627, getCurrentRemainingStack() > 128, "lowstck#3");
288  efiAssertVoid(CUSTOM_ERR_6628, trgEventIndex < engine->engineCycleEventCount, "handleFuel/event index");
289 
290  if (!isInjectionEnabled(PASS_ENGINE_PARAMETER_SIGNATURE) || limitedFuel) {
291  return;
292  }
293  if (ENGINE(isCylinderCleanupMode)) {
294  return;
295  }
296 
297  // If duty cycle is high, impose a fuel cut rev limiter.
298  // This is safer than attempting to limp along with injectors or a pump that are out of flow.
299  if (getInjectorDutyCycle(rpm PASS_ENGINE_PARAMETER_SUFFIX) > 96.0f) {
300  return;
301  }
302 
303  /**
304  * Ignition events are defined by addFuelEvents() according to selected
305  * fueling strategy
306  */
307  FuelSchedule *fs = &ENGINE(injectionEvents);
308  if (!fs->isReady) {
309  fs->addFuelEvents(PASS_ENGINE_PARAMETER_SIGNATURE);
310  }
311 
312 #if FUEL_MATH_EXTREME_LOGGING
313  scheduleMsg(logger, "handleFuel ind=%d %d", trgEventIndex, getRevolutionCounter());
314 #endif /* FUEL_MATH_EXTREME_LOGGING */
315 
316  ENGINE(tpsAccelEnrichment.onNewValue(Sensor::get(SensorType::Tps1).value_or(0) PASS_ENGINE_PARAMETER_SUFFIX));
317  if (trgEventIndex == 0) {
318  ENGINE(tpsAccelEnrichment.onEngineCycleTps(PASS_ENGINE_PARAMETER_SIGNATURE));
319  ENGINE(engineLoadAccelEnrichment.onEngineCycle(PASS_ENGINE_PARAMETER_SIGNATURE));
320  }
321 
322  for (int injEventIndex = 0; injEventIndex < CONFIG(specs.cylindersCount); injEventIndex++) {
323  InjectionEvent *event = &fs->elements[injEventIndex];
324  uint32_t eventIndex = event->injectionStart.triggerEventIndex;
325 // right after trigger change we are still using old & invalid fuel schedule. good news is we do not change trigger on the fly in real life
326 // efiAssertVoid(CUSTOM_ERR_ASSERT_VOID, eventIndex < ENGINE(triggerShape.getLength()), "handleFuel/event sch index");
327  if (eventIndex != trgEventIndex) {
328  continue;
329  }
330  handleFuelInjectionEvent(injEventIndex, event, rpm, nowNt PASS_ENGINE_PARAMETER_SUFFIX);
331  }
332 }
virtual SensorResult get() const =0
int isInjectionEnabled(DECLARE_ENGINE_PARAMETER_SIGNATURE)
Definition: spark_logic.cpp:33
constexpr float value_or(TValue valueIfInvalid) const
Definition: expected.h:41
void handleFuelInjectionEvent(int injEventIndex, InjectionEvent *event, int rpm, efitick_t nowNt DECLARE_ENGINE_PARAMETER_SUFFIX)
percent_t getInjectorDutyCycle(int rpm DECLARE_ENGINE_PARAMETER_SUFFIX)
Definition: fuel_math.cpp:297
void addFuelEvents(DECLARE_ENGINE_PARAMETER_SIGNATURE)
static trigger_wheel_e eventIndex[6]
void scheduleMsg(Logging *, const char *,...)
InjectionEvent elements[MAX_INJECTION_OUTPUT_COUNT]
static Logging * logger

Referenced by mainTriggerCallback().

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

◆ handleFuelInjectionEvent()

void handleFuelInjectionEvent ( int  injEventIndex,
InjectionEvent event,
int  rpm,
efitick_t nowNt  DECLARE_ENGINE_PARAMETER_SUFFIX 
)

todo: this is a bit tricky with batched injection. is it? Does the same wetting coefficient works the same way for any injection mode, or is something x2 or /2?

todo: pre-calculate 'numberOfInjections' see also injectorDutyCycle

Definition at line 179 of file main_trigger_callback.cpp.

180  {
181 
182  /**
183  * todo: this is a bit tricky with batched injection. is it? Does the same
184  * wetting coefficient works the same way for any injection mode, or is something
185  * x2 or /2?
186  */
187 
188  size_t injectorIndex = event->outputs[0]->injectorIndex;
189  const floatms_t injectionDuration = ENGINE(wallFuel[injectorIndex]).adjust(ENGINE(injectionDuration) PASS_ENGINE_PARAMETER_SUFFIX);
190 #if EFI_PRINTF_FUEL_DETAILS
191  printf("fuel injectionDuration=%.2f adjusted=%.2f\t\n", ENGINE(injectionDuration), injectionDuration);
192 #endif /*EFI_PRINTF_FUEL_DETAILS */
193 
194  bool isCranking = ENGINE(rpmCalculator).isCranking(PASS_ENGINE_PARAMETER_SIGNATURE);
195  /**
196  * todo: pre-calculate 'numberOfInjections'
197  * see also injectorDutyCycle
198  */
199  if (!isCranking && injectionDuration * getNumberOfInjections(engineConfiguration->injectionMode PASS_ENGINE_PARAMETER_SUFFIX) > getEngineCycleDuration(rpm PASS_ENGINE_PARAMETER_SUFFIX)) {
200  warning(CUSTOM_TOO_LONG_FUEL_INJECTION, "Too long fuel injection %.2fms", injectionDuration);
201  } else if (isCranking && injectionDuration * getNumberOfInjections(engineConfiguration->crankingInjectionMode PASS_ENGINE_PARAMETER_SUFFIX) > getEngineCycleDuration(rpm PASS_ENGINE_PARAMETER_SUFFIX)) {
202  warning(CUSTOM_TOO_LONG_CRANKING_FUEL_INJECTION, "Too long cranking fuel injection %.2fms", injectionDuration);
203  }
204 
205  // Store 'pure' injection duration (w/o injector lag) for fuel rate calc.
206  engine->engineState.fuelConsumption.addData(injectionDuration - ENGINE(engineState.running.injectorLag));
207 
208  ENGINE(actualLastInjection) = injectionDuration;
209  if (cisnan(injectionDuration)) {
210  warning(CUSTOM_OBD_NAN_INJECTION, "NaN injection pulse");
211  return;
212  }
213  if (injectionDuration < 0) {
214  warning(CUSTOM_OBD_NEG_INJECTION, "Negative injection pulse %.2f", injectionDuration);
215  return;
216  }
217 
218  // If somebody commanded an impossibly short injection, do nothing.
219  // Durations under 50us-ish aren't safe for the scheduler
220  // as their order may be swapped, resulting in a stuck open injector
221  // see https://github.com/rusefi/rusefi/pull/596 for more details
222  if (injectionDuration < 0.050f)
223  {
224  return;
225  }
226 
227  floatus_t durationUs = MS2US(injectionDuration);
228 
229 
230  // we are ignoring low RPM in order not to handle "engine was stopped to engine now running" transition
231  if (rpm > 2 * engineConfiguration->cranking.rpm) {
232  const char *outputName = event->outputs[0]->name;
233  if (prevOutputName == outputName
236  warning(CUSTOM_OBD_SKIPPED_FUEL, "looks like skipped fuel event %d %s", getRevolutionCounter(), outputName);
237  }
238  prevOutputName = outputName;
239  }
240 
241 #if EFI_UNIT_TEST || EFI_SIMULATOR || EFI_PRINTF_FUEL_DETAILS
242  InjectorOutputPin *output = event->outputs[0];
243  printf("fuelout %s duration %d total=%d\t\n", output->name, (int)durationUs,
244  (int)MS2US(getCrankshaftRevolutionTimeMs(GET_RPM_VALUE)));
245 #endif /*EFI_PRINTF_FUEL_DETAILS */
246 
247  if (event->isScheduled) {
248 #if EFI_UNIT_TEST || EFI_SIMULATOR
249  printf("still used1 %s %d\r\n", output->name, (int)getTimeNowUs());
250 #endif /* EFI_UNIT_TEST || EFI_SIMULATOR */
251  return; // this InjectionEvent is still needed for an extremely long injection scheduled previously
252  }
253 
254  event->isScheduled = true;
255 
256  action_s startAction, endAction;
257  // We use different callbacks based on whether we're running sequential mode or not - everything else is the same
258  if (event->isSimultanious) {
259  startAction = { &startSimultaniousInjection, engine };
260  endAction = { &endSimultaniousInjection, event };
261  } else {
262  // sequential or batch
263  startAction = { &turnInjectionPinHigh, event };
264  endAction = { &turnInjectionPinLow, event };
265  }
266 
267  efitick_t startTime = scheduleByAngle(&event->signalTimerUp, nowNt, event->injectionStart.angleOffsetFromTriggerEvent, startAction PASS_ENGINE_PARAMETER_SUFFIX);
268  efitick_t turnOffTime = startTime + US2NT((int)durationUs);
269  engine->executor.scheduleByTimestampNt(&event->endOfInjectionEvent, turnOffTime, endAction);
270 
271 #if EFI_UNIT_TEST
272  printf("scheduling injection angle=%.2f/delay=%.2f injectionDuration=%.2f\r\n", event->injectionStart.angleOffsetFromTriggerEvent, NT2US(startTime - nowNt), injectionDuration);
273 #endif
274 #if EFI_DEFAILED_LOGGING
275  scheduleMsg(logger, "handleFuel pin=%s eventIndex %d duration=%.2fms %d", event->outputs[0]->name,
276  injEventIndex,
277  injectionDuration,
278  getRevolutionCounter());
279  scheduleMsg(logger, "handleFuel pin=%s delay=%.2f %d", event->outputs[0]->name, NT2US(startTime - nowNt),
280  getRevolutionCounter());
281 #endif /* EFI_DEFAILED_LOGGING */
282 }
void endSimultaniousInjection(InjectionEvent *event)
void addData(float durationMs)
Definition: engine2.cpp:83
efitimeus_t getTimeNowUs(void)
Engine * engine
floatms_t getCrankshaftRevolutionTimeMs(int rpm)
Definition: engine_math.cpp:45
int getNumberOfInjections(injection_mode_e mode DECLARE_ENGINE_PARAMETER_SUFFIX)
Definition: fuel_math.cpp:278
InjectorOutputPin * outputs[MAX_WIRES_COUNT]
float floatus_t
Definition: rusefi_types.h:75
SingleTimerExecutor executor
Definition: engine.h:129
FuelConsumptionState fuelConsumption
Definition: engine_state.h:29
float floatms_t
Definition: rusefi_types.h:74
scheduling_s signalTimerUp
EngineState engineState
Definition: engine.h:297
static const char * prevOutputName
engine_configuration_s * engineConfiguration
event_trigger_position_s injectionStart
const char * name
Definition: efi_gpio.h:99
scheduling_s endOfInjectionEvent
void scheduleByTimestampNt(scheduling_s *scheduling, efitime_t timeNt, action_s action) override
static void turnInjectionPinLow(InjectorOutputPin *output)
bool warning(obd_code_e code, const char *fmt,...)
void scheduleMsg(Logging *, const char *,...)
efitick_t scheduleByAngle(scheduling_s *timer, efitick_t edgeTimestamp, angle_t angle, action_s action DECLARE_ENGINE_PARAMETER_SUFFIX)
efitime_t efitick_t
Definition: rusefi_types.h:68
static void turnInjectionPinHigh(InjectorOutputPin *output)
static Logging * logger
floatms_t getEngineCycleDuration(int rpm DECLARE_ENGINE_PARAMETER_SUFFIX)
Definition: engine_math.cpp:38
void startSimultaniousInjection(Engine *engine)

Referenced by handleFuel().

Here is the call graph for this function:

◆ initMainEventListener()

void initMainEventListener ( Logging *sharedLogger  DECLARE_ENGINE_PARAMETER_SUFFIX)

Definition at line 521 of file main_trigger_callback.cpp.

521  {
523  efiAssertVoid(CUSTOM_ERR_6631, engine!=NULL, "null engine");
524 
525 #if EFI_PROD_CODE
527 
528  printMsg(logger, "initMainLoop: %d", currentTimeMillis());
529  if (!isInjectionEnabled(PASS_ENGINE_PARAMETER_SIGNATURE))
530  printMsg(logger, "!!!!!!!!!!!!!!!!!!! injection disabled");
531 #endif
532 
534 
535  // We start prime injection pulse at the early init stage - don't wait for the engine to start spinning!
536  if (CONFIG(startOfCrankingPrimingPulse) > 0)
537  startPrimeInjectionPulse(PASS_ENGINE_PARAMETER_SIGNATURE);
538 
539 }
efitimems_t currentTimeMillis(void)
Returns the number of milliseconds since the board initialization.
Engine * engine
void addConsoleActionP(const char *token, VoidPtr callback, void *param)
static void showMainInfo(Engine *engine)
int isInjectionEnabled(DECLARE_ENGINE_PARAMETER_SIGNATURE)
Definition: spark_logic.cpp:33
void addTriggerEventListener(ShaftPositionListener listener, const char *name, Engine *engine)
Adds a trigger event listener.
LoggingWithStorage sharedLogger
void(* VoidPtr)(void *)
Definition: rusefi_types.h:126
static void mainTriggerCallback(trigger_event_e ckpSignalType, uint32_t trgEventIndex, efitick_t edgeTimestamp DECLARE_ENGINE_PARAMETER_SUFFIX)
void printMsg(Logging *logger, const char *fmt,...)
void startPrimeInjectionPulse(DECLARE_ENGINE_PARAMETER_SIGNATURE)
static Logging * logger

Referenced by commonInitEngineController().

Here is the call graph for this function:

◆ isPrimeInjectionPulseSkipped()

static bool isPrimeInjectionPulseSkipped ( DECLARE_ENGINE_PARAMETER_SIGNATURE  )
static

Definition at line 442 of file main_trigger_callback.cpp.

442  {
443  if (!engine->rpmCalculator.isStopped(PASS_ENGINE_PARAMETER_SIGNATURE))
444  return true;
445  return CONFIG(isCylinderCleanupEnabled) && (Sensor::get(SensorType::Tps1).value_or(0) > CLEANUP_MODE_TPS);
446 }
Engine * engine
virtual SensorResult get() const =0
bool isStopped(DECLARE_ENGINE_PARAMETER_SIGNATURE) const
constexpr float value_or(TValue valueIfInvalid) const
Definition: expected.h:41
RpmCalculator rpmCalculator
Definition: engine.h:180

Referenced by startPrimeInjectionPulse().

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

◆ mainTriggerCallback()

static void mainTriggerCallback ( trigger_event_e  ckpSignalType,
uint32_t  trgEventIndex,
efitick_t edgeTimestamp  DECLARE_ENGINE_PARAMETER_SUFFIX 
)
static

This is the main trigger event handler. Both injection and ignition are controlled from this method.

In case on a major error we should not process any more events. TODO: add 'pin shutdown' invocation somewhere - coils might be still open here!

this could happen in case of a trigger error, just exit silently since the trigger error is supposed to be handled already todo: should this check be somewhere higher so that no trigger listeners are invoked with noise?

For fuel we schedule start of injection based on trigger angle, and then inject for specified duration of time

For spark we schedule both start of coil charge and actual spark based on trigger angle

Definition at line 345 of file main_trigger_callback.cpp.

345  {
347 
348  (void) ckpSignalType;
349 
350 
352  // this is a bit spaghetti code for sure
353  // do not spark & do not fuel until we have VVT sync. NB2 is a special case
354  // due to symmetrical crank wheel and we need to make sure no spark happens out of sync
355  return;
356  }
357 
358  if (hasFirmwareError()) {
359  /**
360  * In case on a major error we should not process any more events.
361  * TODO: add 'pin shutdown' invocation somewhere - coils might be still open here!
362  */
363  return;
364  }
365  efiAssertVoid(CUSTOM_STACK_6629, getCurrentRemainingStack() > EXPECTED_REMAINING_STACK, "lowstck#2a");
366 
367 #if EFI_CDM_INTEGRATION
368  if (trgEventIndex == 0 && CONFIG(cdmInputPin) != GPIO_UNASSIGNED) {
370  engine->knockLogic(cdmKnockValue);
371  }
372 #endif /* EFI_CDM_INTEGRATION */
373 
374  if (trgEventIndex >= ENGINE(engineCycleEventCount)) {
375  /**
376  * this could happen in case of a trigger error, just exit silently since the trigger error is supposed to be handled already
377  * todo: should this check be somewhere higher so that no trigger listeners are invoked with noise?
378  */
379  return;
380  }
381 
382  int rpm = GET_RPM_VALUE;
383  if (rpm == 0) {
384  // this happens while we just start cranking
385  // todo: check for 'trigger->is_synchnonized?'
386  // TODO: add 'pin shutdown' invocation somewhere - coils might be still open here!
387  return;
388  }
389  if (rpm == NOISY_RPM) {
391  // TODO: add 'pin shutdown' invocation somewhere - coils might be still open here!
392  return;
393  }
394  bool limitedSpark = rpm > engine->getRpmHardLimit(PASS_ENGINE_PARAMETER_SIGNATURE);
395  bool limitedFuel = rpm > engine->getRpmHardLimit(PASS_ENGINE_PARAMETER_SIGNATURE);
396 
397  if (CONFIG(boostCutPressure) != 0) {
398  if (getMap(PASS_ENGINE_PARAMETER_SIGNATURE) > CONFIG(boostCutPressure)) {
399  limitedSpark = true;
400  limitedFuel = true;
401  }
402  }
403 
404  if (trgEventIndex == 0) {
405  if (HAVE_CAM_INPUT()) {
407  }
408 
409  if (checkIfTriggerConfigChanged(PASS_ENGINE_PARAMETER_SIGNATURE)) {
410  engine->ignitionEvents.isReady = false; // we need to rebuild complete ignition schedule
411  engine->injectionEvents.isReady = false;
412  // moved 'triggerIndexByAngle' into trigger initialization (why was it invoked from here if it's only about trigger shape & optimization?)
413  // see initializeTriggerWaveform() -> prepareOutputSignals(PASS_ENGINE_PARAMETER_SIGNATURE)
414 
415  // we need this to apply new 'triggerIndexByAngle' values
416  engine->periodicFastCallback(PASS_ENGINE_PARAMETER_SIGNATURE);
417  }
418  }
419 
420  efiAssertVoid(CUSTOM_IGN_MATH_STATE, !CONFIG(useOnlyRisingEdgeForTrigger) || CONFIG(ignMathCalculateAtIndex) % 2 == 0, "invalid ignMathCalculateAtIndex");
421 
422  if (trgEventIndex == (uint32_t)CONFIG(ignMathCalculateAtIndex)) {
423  if (CONFIG(externalKnockSenseAdc) != EFI_ADC_NONE) {
424  float externalKnockValue = getVoltageDivided("knock", engineConfiguration->externalKnockSenseAdc PASS_ENGINE_PARAMETER_SUFFIX);
425  engine->knockLogic(externalKnockValue PASS_ENGINE_PARAMETER_SUFFIX);
426  }
427  }
428 
429 
430  /**
431  * For fuel we schedule start of injection based on trigger angle, and then inject for
432  * specified duration of time
433  */
434  handleFuel(limitedFuel, trgEventIndex, rpm, edgeTimestamp PASS_ENGINE_PARAMETER_SUFFIX);
435  /**
436  * For spark we schedule both start of coil charge and actual spark based on trigger angle
437  */
438  onTriggerEventSparkLogic(limitedSpark, trgEventIndex, rpm, edgeTimestamp PASS_ENGINE_PARAMETER_SUFFIX);
439 }
void validateCamVvtCounters()
void onTriggerEventSparkLogic(bool limitedSpark, uint32_t trgEventIndex, int rpm, efitick_t edgeTimestamp DECLARE_ENGINE_PARAMETER_SUFFIX)
float getVoltageDivided(const char *msg, adc_channel_e hwChannel DECLARE_ENGINE_PARAMETER_SUFFIX)
Definition: adc_inputs.cpp:50
Engine * engine
void knockLogic(float knockVolts DECLARE_ENGINE_PARAMETER_SUFFIX)
Definition: engine.cpp:366
float getMap(void)
TriggerCentral triggerCentral
Definition: engine.h:212
bool checkIfTriggerConfigChanged(DECLARE_ENGINE_PARAMETER_SIGNATURE)
IgnitionEventList ignitionEvents
Definition: engine.h:140
int getRpmHardLimit(DECLARE_ENGINE_PARAMETER_SIGNATURE)
Definition: engine.cpp:488
int getTotalRevolutionCounter() const
engine_configuration_s * engineConfiguration
efitick_t vvtSyncTimeNt
FuelSchedule injectionEvents
Definition: engine.h:139
static ALWAYS_INLINE void handleFuel(const bool limitedFuel, uint32_t trgEventIndex, int rpm, efitick_t nowNt DECLARE_ENGINE_PARAMETER_SUFFIX)
void periodicFastCallback(DECLARE_ENGINE_PARAMETER_SIGNATURE)
Definition: engine.cpp:499
bool warning(obd_code_e code, const char *fmt,...)
TriggerStateWithRunningStatistics triggerState
int getCurrentCdmValue(int currentRevolution)

Referenced by initMainEventListener().

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

◆ showMainInfo()

static void showMainInfo ( Engine engine)
static

Definition at line 512 of file main_trigger_callback.cpp.

512  {
513 #if EFI_PROD_CODE
514  int rpm = GET_RPM();
515  float el = getEngineLoadT(PASS_ENGINE_PARAMETER_SIGNATURE);
516  scheduleMsg(logger, "rpm %d engine_load %.2f", rpm, el);
517  scheduleMsg(logger, "fuel %.2fms timing %.2f", getInjectionDuration(rpm PASS_ENGINE_PARAMETER_SUFFIX), engine->engineState.timingAdvance);
518 #endif /* EFI_PROD_CODE */
519 }
Engine * engine
angle_t timingAdvance
Definition: engine_state.h:55
EngineState engineState
Definition: engine.h:297
float getEngineLoadT(DECLARE_ENGINE_PARAMETER_SIGNATURE)
Returns engine load according to selected engine_load_mode.
Definition: engine_math.cpp:56
floatms_t getInjectionDuration(int rpm DECLARE_ENGINE_PARAMETER_SUFFIX)
Definition: fuel_math.cpp:315
void scheduleMsg(Logging *, const char *,...)
static Logging * logger

Referenced by initMainEventListener().

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

◆ startPrimeInjectionPulse()

void startPrimeInjectionPulse ( DECLARE_ENGINE_PARAMETER_SIGNATURE  )

Prime injection pulse, mainly needed for mono-injectors or long intake manifolds. See testStartOfCrankingPrimingPulse()

Definition at line 452 of file main_trigger_callback.cpp.

452  {
453  // First, we need a protection against 'fake' ignition switch on and off (i.e. no engine started), to avoid repeated prime pulses.
454  // So we check and update the ignition switch counter in non-volatile backup-RAM
455 #if EFI_PROD_CODE
456  uint32_t ignSwitchCounter = backupRamLoad(BACKUP_IGNITION_SWITCH_COUNTER);
457 #else /* EFI_PROD_CODE */
458  uint32_t ignSwitchCounter = 0;
459 #endif /* EFI_PROD_CODE */
460 
461  // if we're just toying with the ignition switch, give it another chance eventually...
462  if (ignSwitchCounter > 10)
463  ignSwitchCounter = 0;
464  // If we're going to skip this pulse, then save the counter as 0.
465  // That's because we'll definitely need the prime pulse next time (either due to the cylinder cleanup or the engine spinning)
466  if (isPrimeInjectionPulseSkipped(PASS_ENGINE_PARAMETER_SIGNATURE))
467  ignSwitchCounter = -1;
468  // start prime injection if this is a 'fresh start'
469  if (ignSwitchCounter == 0) {
470  // fill-in the prime event struct
471 #if EFI_UNIT_TEST
472  primeInjEvent.engine = engine;
473 #endif /* EFI_UNIT_TEST */
476 
477  scheduling_s *sDown = &ENGINE(injectionEvents.elements[0]).endOfInjectionEvent;
478  // When the engine is hot, basically we don't need prime inj.pulse, so we use an interpolation over temperature (falloff).
479  // If 'primeInjFalloffTemperature' is not specified (by default), we have a prime pulse deactivation at zero celsius degrees, which is okay.
480  const float maxPrimeInjAtTemperature = -40.0f; // at this temperature the pulse is maximal.
481  floatms_t pulseLength = interpolateClamped(maxPrimeInjAtTemperature, CONFIG(startOfCrankingPrimingPulse),
482  CONFIG(primeInjFalloffTemperature), 0.0f, Sensor::get(SensorType::Clt).value_or(70));
483  if (pulseLength > 0) {
485  efitimeus_t turnOffDelayUs = (efitimeus_t)efiRound(MS2US(pulseLength), 1.0f);
487  }
488  }
489 #if EFI_PROD_CODE
490  // we'll reset it later when the engine starts
491  backupRamSave(BACKUP_IGNITION_SWITCH_COUNTER, ignSwitchCounter + 1);
492 #endif /* EFI_PROD_CODE */
493 }
Engine * engine
virtual SensorResult get() const =0
void scheduleForLater(scheduling_s *scheduling, int delayUs, action_s action) override
SingleTimerExecutor executor
Definition: engine.h:129
static void endSimultaniousInjectionOnlyTogglePins(Engine *engine)
static InjectionEvent primeInjEvent
float floatms_t
Definition: rusefi_types.h:74
float efiRound(float value, float precision)
Definition: efilib.cpp:36
float interpolateClamped(float x1, float y1, float x2, float y2, float x)
static bool isPrimeInjectionPulseSkipped(DECLARE_ENGINE_PARAMETER_SIGNATURE)
efitime_t efitimeus_t
Definition: rusefi_types.h:56
void backupRamSave(backup_ram_e idx, uint32_t value)
Definition: backup_ram.cpp:32
void startSimultaniousInjection(Engine *engine)
uint32_t backupRamLoad(backup_ram_e idx)
Definition: backup_ram.cpp:9

Referenced by initMainEventListener().

Here is the call graph for this function:

◆ startSimultaniousInjection()

void startSimultaniousInjection ( Engine engine)

Definition at line 69 of file main_trigger_callback.cpp.

69  {
70  for (int i = 0; i < engine->engineConfigurationPtr->specs.cylindersCount; i++) {
72  }
73 }
Engine * engine
InjectorOutputPin injectors[INJECTION_PIN_COUNT]
Definition: efi_gpio.h:174
EnginePins enginePins
Definition: efi_gpio.cpp:32
engine_configuration_s * engineConfigurationPtr
Definition: engine.h:186
void setHigh()
Definition: efi_gpio.cpp:241

Referenced by handleFuelInjectionEvent(), and startPrimeInjectionPulse().

Here is the call graph for this function:

◆ turnInjectionPinHigh() [1/2]

static void turnInjectionPinHigh ( InjectorOutputPin output)
inlinestatic

#299 this is another kind of overlap which happens in case of a small duty cycle after a large duty cycle

Definition at line 92 of file main_trigger_callback.cpp.

92  {
93  output->overlappingCounter++;
94 
95 #if FUEL_MATH_EXTREME_LOGGING
96  printf("turnInjectionPinHigh %s %d %d\r\n", output->name, output->overlappingCounter, (int)getTimeNowUs());
97 #endif /* FUEL_MATH_EXTREME_LOGGING */
98 
99  if (output->overlappingCounter > 1) {
100 // /**
101 // * #299
102 // * this is another kind of overlap which happens in case of a small duty cycle after a large duty cycle
103 // */
104 #if FUEL_MATH_EXTREME_LOGGING
105  printf("overlapping, no need to touch pin %s %d\r\n", output->name, (int)getTimeNowUs());
106 #endif /* FUEL_MATH_EXTREME_LOGGING */
107  } else {
108 #if FUEL_MATH_EXTREME_LOGGING
109  const char * w = output->currentLogicValue == true ? "err" : "";
110 // scheduleMsg(&sharedLogger, "^ %spin=%s eventIndex %d %d", w, output->name,
111 // getRevolutionCounter(), getTimeNowUs());
112 #endif /* FUEL_MATH_EXTREME_LOGGING */
113 
114  output->setHigh();
115  }
116 }
efitimeus_t getTimeNowUs(void)
const char * name
Definition: efi_gpio.h:99
int8_t overlappingCounter
Definition: efi_gpio.h:112
int8_t currentLogicValue
Definition: efi_gpio.h:72
void setHigh()
Definition: efi_gpio.cpp:241

Referenced by handleFuelInjectionEvent(), and turnInjectionPinHigh().

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

◆ turnInjectionPinHigh() [2/2]

void turnInjectionPinHigh ( InjectionEvent event)

Definition at line 118 of file main_trigger_callback.cpp.

118  {
119  efitick_t nowNt = getTimeNowNt();
120 
121 #if EFI_TOOTH_LOGGER
122  LogTriggerInjectorState(nowNt, true PASS_ENGINE_PARAMETER_SUFFIX);
123 #endif // EFI_TOOTH_LOGGER
124 
125  for (int i = 0;i < MAX_WIRES_COUNT;i++) {
126  InjectorOutputPin *output = event->outputs[i];
127 
128  if (output) {
129  turnInjectionPinHigh(output);
130  }
131  }
132 }
efitick_t getTimeNowNt(void)
void LogTriggerInjectorState(efitick_t timestamp, bool state DECLARE_ENGINE_PARAMETER_SUFFIX)
efitime_t efitick_t
Definition: rusefi_types.h:68
static void turnInjectionPinHigh(InjectorOutputPin *output)
Here is the call graph for this function:

◆ turnInjectionPinLow() [1/2]

static void turnInjectionPinLow ( InjectorOutputPin output)
inlinestatic

Definition at line 134 of file main_trigger_callback.cpp.

134  {
135 #if FUEL_MATH_EXTREME_LOGGING
136  printf("turnInjectionPinLow %s %d %d\r\n", output->name, output->overlappingCounter, (int)getTimeNowUs());
137 #endif /* FUEL_MATH_EXTREME_LOGGING */
138 
139 
140 #if FUEL_MATH_EXTREME_LOGGING
141  const char * w = output->currentLogicValue == false ? "err" : "";
142 
143 // scheduleMsg(&sharedLogger, "- %spin=%s eventIndex %d %d", w, output->name,
144 // getRevolutionCounter(), getTimeNowUs());
145 #endif /* FUEL_MATH_EXTREME_LOGGING */
146 
147  output->overlappingCounter--;
148  if (output->overlappingCounter > 0) {
149 #if FUEL_MATH_EXTREME_LOGGING
150  printf("was overlapping, no need to touch pin %s %d\r\n", output->name, (int)getTimeNowUs());
151 #endif /* FUEL_MATH_EXTREME_LOGGING */
152  } else {
153  output->setLow();
154  }
155 
156 }
efitimeus_t getTimeNowUs(void)
const char * name
Definition: efi_gpio.h:99
int8_t overlappingCounter
Definition: efi_gpio.h:112
int8_t currentLogicValue
Definition: efi_gpio.h:72

Referenced by doScheduleForLater(), handleFuelInjectionEvent(), timerCallback(), and turnInjectionPinLow().

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

◆ turnInjectionPinLow() [2/2]

void turnInjectionPinLow ( InjectionEvent event)

Definition at line 158 of file main_trigger_callback.cpp.

158  {
159  efitick_t nowNt = getTimeNowNt();
160 
161 #if EFI_TOOTH_LOGGER
162  LogTriggerInjectorState(nowNt, false PASS_ENGINE_PARAMETER_SUFFIX);
163 #endif // EFI_TOOTH_LOGGER
164 
165  event->isScheduled = false;
166  for (int i = 0;i<MAX_WIRES_COUNT;i++) {
167  InjectorOutputPin *output = event->outputs[i];
168  if (output != NULL) {
169  turnInjectionPinLow(output);
170  }
171  }
172 #if EFI_UNIT_TEST
173  Engine *engine = event->engine;
174  EXPAND_Engine;
175 #endif
176  ENGINE(injectionEvents.addFuelEventsForCylinder(event->ownIndex PASS_ENGINE_PARAMETER_SUFFIX));
177 }
Engine * engine
efitick_t getTimeNowNt(void)
void LogTriggerInjectorState(efitick_t timestamp, bool state DECLARE_ENGINE_PARAMETER_SUFFIX)
static void turnInjectionPinLow(InjectorOutputPin *output)
efitime_t efitick_t
Definition: rusefi_types.h:68
Definition: engine.h:57
Here is the call graph for this function:

◆ updatePrimeInjectionPulseState()

void updatePrimeInjectionPulseState ( DECLARE_ENGINE_PARAMETER_SIGNATURE  )

Definition at line 495 of file main_trigger_callback.cpp.

495  {
496 #if EFI_PROD_CODE
497  static bool counterWasReset = false;
498  if (counterWasReset)
499  return;
500 
501  if (!engine->rpmCalculator.isStopped(PASS_ENGINE_PARAMETER_SIGNATURE)) {
503  counterWasReset = true;
504  }
505 #endif /* EFI_PROD_CODE */
506 }
Engine * engine
bool isStopped(DECLARE_ENGINE_PARAMETER_SIGNATURE) const
RpmCalculator rpmCalculator
Definition: engine.h:180
void backupRamSave(backup_ram_e idx, uint32_t value)
Definition: backup_ram.cpp:32

Referenced by doPeriodicSlowCallback().

Here is the call graph for this function:

Variable Documentation

◆ cyccnt

uint32_t* cyccnt = (uint32_t*) &DWT->CYCCNT

this field is used as an Expression in IAR debugger

Definition at line 338 of file main_trigger_callback.cpp.

◆ EXTERN_ENGINE

EXTERN_ENGINE

Definition at line 54 of file main_trigger_callback.cpp.

◆ logger

Logging* logger
static

◆ prevOutputName

const char* prevOutputName = nullptr
static

Definition at line 56 of file main_trigger_callback.cpp.

Referenced by handleFuelInjectionEvent().

◆ primeInjEvent

InjectionEvent primeInjEvent
static

Definition at line 58 of file main_trigger_callback.cpp.

Referenced by startPrimeInjectionPulse().

Go to the source code of this file.