void registerActuatorEventExt(engine_configuration_s const *engineConfiguration, trigger_shape_s * s, ActuatorEvent *e, OutputSignal *actuator, float angleOffset) { efiAssertVoid(s->getSize() > 0, "uninitialized trigger_shape_s"); if (e == NULL) { // error already reported return; } e->actuator = actuator; findTriggerPosition(engineConfiguration, s, &e->position, angleOffset); }
void testAngleResolver(void) { printf("*************************************************** testAngleResolver\r\n"); EngineTestHelper eth(FORD_ASPIRE_1996); Engine *engine = ð.engine; engine_configuration_s *engineConfiguration = eth.engine.engineConfiguration; engineConfiguration->globalTriggerAngleOffset = 175; assertTrue(engine->engineConfiguration2!=NULL); trigger_shape_s * ts = &engine->triggerShape; confgiureFordAspireTriggerShape(ts); ts->calculateTriggerSynchPoint(engineConfiguration, engine); assertEqualsM("index 2", 228.0450, ts->eventAngles[3]); // this angle is relation to synch point assertEqualsM("time 2", 0.3233, ts->wave.getSwitchTime(2)); assertEqualsM("index 5", 413.7470, ts->eventAngles[6]); assertEqualsM("time 5", 0.5692, ts->wave.getSwitchTime(5)); assertEquals(4, ts->getTriggerShapeSynchPointIndex()); assertEqualsM("shape size", 10, ts->getSize()); OutputSignalList list; ae.resetEventList(); printf("*************************************************** testAngleResolver 0\r\n"); findTriggerPosition(&ae.getNextActuatorEvent()->position, 53 - 175 PASS_ENGINE_PARAMETER); assertEqualsM("size", 1, ae.size); assertEquals(1, ae.events[0].position.eventIndex); assertEquals(3.1588, ae.events[0].position.angleOffset); printf("*************************************************** testAngleResolver 2\r\n"); ae.resetEventList(); findTriggerPosition(&ae.getNextActuatorEvent()->position, 51 + 180 - 175 PASS_ENGINE_PARAMETER); assertEquals(2, ae.events[0].position.eventIndex); assertEquals(112.3495, ae.events[0].position.angleOffset); }
static void registerSparkEvent(engine_configuration_s const *engineConfiguration, trigger_shape_s * s, IgnitionEventList *list, io_pin_e pin, float localAdvance, float dwell) { IgnitionEvent *event = list->getNextActuatorEvent(); if (event == NULL) return; // error already reported event->io_pin = pin; event->advance = localAdvance; findTriggerPosition(engineConfiguration, s, &event->dwellPosition, localAdvance - dwell); }
static ALWAYS_INLINE void handleSparkEvent(uint32_t eventIndex, IgnitionEvent *iEvent, int rpm DECLARE_ENGINE_PARAMETER_S) { float dwellMs = engine->engineState.sparkDwell; if (cisnan(dwellMs) || dwellMs < 0) { firmwareError("invalid dwell: %f at %d", dwellMs, rpm); return; } floatus_t chargeDelayUs = engine->rpmCalculator.oneDegreeUs * iEvent->dwellPosition.angleOffset; int isIgnitionError = chargeDelayUs < 0; ignitionErrorDetection.add(isIgnitionError); if (isIgnitionError) { #if EFI_PROD_CODE scheduleMsg(logger, "Negative spark delay=%f", chargeDelayUs); #endif chargeDelayUs = 0; return; } if (cisnan(dwellMs)) { firmwareError("NaN in scheduleOutput", dwellMs); return; } /** * We are alternating two event lists in order to avoid a potential issue around revolution boundary * when an event is scheduled within the next revolution. */ scheduling_s * sUp = &iEvent->signalTimerUp; scheduling_s * sDown = &iEvent->signalTimerDown; /** * The start of charge is always within the current trigger event range, so just plain time-based scheduling */ scheduleTask("spark up", sUp, chargeDelayUs, (schfunc_t) &turnPinHigh, iEvent->output); /** * Spark event is often happening during a later trigger event timeframe * TODO: improve precision */ findTriggerPosition(&iEvent->sparkPosition, iEvent->advance PASS_ENGINE_PARAMETER); if (iEvent->sparkPosition.eventIndex == eventIndex) { /** * Spark should be fired before the next trigger event - time-based delay is best precision possible */ float timeTillIgnitionUs = engine->rpmCalculator.oneDegreeUs * iEvent->sparkPosition.angleOffset; scheduleTask("spark 1down", sDown, (int) timeTillIgnitionUs, (schfunc_t) &turnPinLow, iEvent->output); } else { /** * Spark should be scheduled in relation to some future trigger event, this way we get better firing precision */ bool isPending = assertNotInList<IgnitionEvent>(iHead, iEvent); if (isPending) return; LL_APPEND(iHead, iEvent); } }