void Engine::reset() { isEngineChartEnabled = false; sensorChartMode = SC_OFF; actualLastInjection = 0; isAlternatorControlEnabled = false; wallFuelCorrection = 0; /** * it's important for fixAngle() that engineCycle field never has zero */ engineCycle = getEngineCycle(FOUR_STROKE_CRANK_SENSOR); lastTriggerEventTimeNt = 0; isCylinderCleanupMode = false; engineCycleEventCount = 0; stopEngineRequestTimeNt = 0; isRunningPwmTest = false; isTestMode = false; isSpinning = false; adcToVoltageInputDividerCoefficient = NAN; engineState.iat = engineState.clt = NAN; memset(&ignitionPin, 0, sizeof(ignitionPin)); knockNow = false; knockEver = false; knockCount = 0; knockDebug = false; knockVolts = 0; iHead = NULL; timeOfLastKnockEvent = 0; fuelMs = 0; clutchDownState = clutchUpState = false; memset(&m, 0, sizeof(m)); }
/** * The idea of this method is to execute all heavy calculations in a lower-priority thread, * so that trigger event handler/IO scheduler tasks are faster. */ void Engine::periodicFastCallback(DECLARE_ENGINE_PARAMETER_F) { int rpm = rpmCalculator.rpmValue; if (isValidRpm(rpm)) { MAP_sensor_config_s * c = &engineConfiguration->map; angle_t start = interpolate2d(rpm, c->samplingAngleBins, c->samplingAngle, MAP_ANGLE_SIZE); angle_t offsetAngle = TRIGGER_SHAPE(eventAngles[CONFIG(mapAveragingSchedulingAtIndex)]); for (int i = 0; i < engineConfiguration->specs.cylindersCount; i++) { angle_t cylinderOffset = getEngineCycle(engineConfiguration->operationMode) * i / engineConfiguration->specs.cylindersCount; float cylinderStart = start + cylinderOffset - offsetAngle + tdcPosition(); fixAngle(cylinderStart, "cylinderStart"); engine->engineState.mapAveragingStart[i] = cylinderStart; } engine->engineState.mapAveragingDuration = interpolate2d(rpm, c->samplingWindowBins, c->samplingWindow, MAP_WINDOW_SIZE); } else { for (int i = 0; i < engineConfiguration->specs.cylindersCount; i++) { engine->engineState.mapAveragingStart[i] = NAN; } engine->engineState.mapAveragingDuration = NAN; } engineState.periodicFastCallback(PASS_ENGINE_PARAMETER_F); engine->m.beforeFuelCalc = GET_TIMESTAMP(); ENGINE(fuelMs) = getInjectionDuration(rpm PASS_ENGINE_PARAMETER) * engineConfiguration->globalFuelCorrection; engine->m.fuelCalcTime = GET_TIMESTAMP() - engine->m.beforeFuelCalc; }
Engine::Engine(persistent_config_s *config) { init(config); isEngineChartEnabled = false; sensorChartMode = SC_OFF; /** * it's important for fixAngle() that engineCycle field never has zero */ engineCycle = getEngineCycle(FOUR_STROKE_CRANK_SENSOR); lastTriggerEventTimeNt = 0; isCylinderCleanupMode = false; engineCycleEventCount = 0; stopEngineRequestTimeNt = 0; isRunningPwmTest = false; isTestMode = false; isSpinning = false; adcToVoltageInputDividerCoefficient = NAN; engineConfiguration2 = NULL; engineState.iat = engineState.clt = NAN; memset(&ignitionPin, 0, sizeof(ignitionPin)); knockNow = false; knockEver = false; knockCount = 0; knockDebug = false; knockVolts = 0; iHead = NULL; timeOfLastKnockEvent = 0; injectorLagMs = fuelMs = 0; clutchDownState = clutchUpState = false; memset(&m, 0, sizeof(m)); addConfigurationListener(invokeEnginePreCalculate); }
void setVwConfiguration(TriggerShape *s) { efiAssertVoid(s != NULL, "TriggerShape is NULL"); operation_mode_e operationMode = FOUR_STROKE_CRANK_SENSOR; s->useRiseEdge = true; initializeSkippedToothTriggerShapeExt(s, 60, 2, operationMode); s->isSynchronizationNeeded = true; s->reset(operationMode, false); int totalTeethCount = 60; int skippedCount = 2; float engineCycle = getEngineCycle(operationMode); float toothWidth = 0.5; addSkippedToothTriggerEvents(T_PRIMARY, s, 60, 2, toothWidth, 0, engineCycle, NO_LEFT_FILTER, 690); float angleDown = engineCycle / totalTeethCount * (totalTeethCount - skippedCount - 1 + (1 - toothWidth) ); s->addEvent(0 + angleDown + 12, T_PRIMARY, TV_HIGH, NO_LEFT_FILTER, NO_RIGHT_FILTER); s->addEvent(0 + engineCycle, T_PRIMARY, TV_LOW, NO_LEFT_FILTER, NO_RIGHT_FILTER); s->setTriggerSynchronizationGap2(1.6, 4); }
void initializeSkippedToothTriggerShapeExt(TriggerShape *s, int totalTeethCount, int skippedCount, operation_mode_e operationMode) { efiAssertVoid(totalTeethCount > 0, "totalTeethCount is zero"); efiAssertVoid(s != NULL, "TriggerShape is NULL"); s->initialize(operationMode, false); s->setTriggerSynchronizationGap(skippedCount + 1); s->isSynchronizationNeeded = (skippedCount != 0); addSkippedToothTriggerEvents(T_PRIMARY, s, totalTeethCount, skippedCount, 0.5, 0, getEngineCycle(operationMode), NO_LEFT_FILTER, NO_RIGHT_FILTER); }
static void configureOnePlusOne(TriggerShape *s, operation_mode_e operationMode) { float engineCycle = getEngineCycle(operationMode); s->reset(FOUR_STROKE_CAM_SENSOR, true); s->addEvent(180, T_PRIMARY, TV_HIGH); s->addEvent(360, T_PRIMARY, TV_LOW); s->addEvent(540, T_SECONDARY, TV_HIGH); s->addEvent(720, T_SECONDARY, TV_LOW); s->isSynchronizationNeeded = false; }
void configureOnePlusOne(TriggerShape *s, operation_mode_e operationMode) { float engineCycle = getEngineCycle(operationMode); s->initialize(FOUR_STROKE_CAM_SENSOR, true); s->addEvent720(180, T_PRIMARY, TV_RISE); s->addEvent720(360, T_PRIMARY, TV_FALL); s->addEvent720(540, T_SECONDARY, TV_RISE); s->addEvent720(720, T_SECONDARY, TV_FALL); s->isSynchronizationNeeded = false; s->useOnlyPrimaryForSync = true; }
void initializeSkippedToothTriggerShapeExt(TriggerShape *s, int totalTeethCount, int skippedCount, operation_mode_e operationMode) { if (totalTeethCount <= 0) { warning(CUSTOM_OBD_TRIGGER_SHAPE, "totalTeethCount is zero or less: %d", totalTeethCount); s->shapeDefinitionError = true; return; } efiAssertVoid(CUSTOM_ERR_6588, s != NULL, "TriggerShape is NULL"); s->initialize(operationMode, false); s->setTriggerSynchronizationGap(skippedCount + 1); s->isSynchronizationNeeded = (totalTeethCount > 2) && (skippedCount != 0); addSkippedToothTriggerEvents(T_PRIMARY, s, totalTeethCount, skippedCount, 0.5, 0, getEngineCycle(operationMode), NO_LEFT_FILTER, NO_RIGHT_FILTER); }
void Engine::reset() { withError = isEngineChartEnabled = false; etbAutoTune = false; sensorChartMode = SC_OFF; actualLastInjection = 0; fsioTimingAdjustment = 0; isAlternatorControlEnabled = false; callFromPitStopEndTime = 0; rpmHardLimitTimestamp = 0; wallFuelCorrection = 0; /** * it's important for fixAngle() that engineCycle field never has zero */ engineCycle = getEngineCycle(FOUR_STROKE_CRANK_SENSOR); lastTriggerToothEventTimeNt = 0; isCylinderCleanupMode = false; engineCycleEventCount = 0; stopEngineRequestTimeNt = 0; isRunningPwmTest = false; isTestMode = false; isSpinning = false; isCltBroken = false; adcToVoltageInputDividerCoefficient = NAN; sensors.reset(); memset(&ignitionPin, 0, sizeof(ignitionPin)); knockNow = false; knockEver = false; knockCount = 0; knockDebug = false; knockVolts = 0; iHead = NULL; timeOfLastKnockEvent = 0; injectionDuration = 0; clutchDownState = clutchUpState = brakePedalState = false; memset(&m, 0, sizeof(m)); }
void TriggerShape::addEvent(float angle, trigger_wheel_e const waveIndex, trigger_value_e const stateParam) { efiAssertVoid(operationMode != OM_NONE, "operationMode not set"); efiAssertVoid(waveIndex!= T_SECONDARY || needSecondTriggerInput, "secondary needed or not?"); trigger_value_e state; if (invertOnAdd) { state = (stateParam == TV_LOW) ? TV_HIGH : TV_LOW; } else { state = stateParam; } #if EFI_UNIT_TEST int signal = waveIndex * 1000 + stateParam; events[size] = signal; #endif float engineCycle = getEngineCycle(operationMode); /** * While '720' value works perfectly it has not much sense for crank sensor-only scenario. * todo: accept angle as a value in the 0..1 range? */ angle /= engineCycle; #if EFI_PROD_CODE // todo: PASS_ENGINE? if (!engineConfiguration->useOnlyFrontForTrigger || stateParam == TV_HIGH) { expectedEventCount[waveIndex]++; } #endif efiAssertVoid(angle > 0, "angle should be positive"); if (size > 0) { if (angle <= previousAngle) { firmwareError("invalid angle order: %f and %f", angle, previousAngle); return; } } previousAngle = angle; if (size == 0) { size = 1; for (int i = 0; i < PWM_PHASE_MAX_WAVE_PER_PWM; i++) { single_wave_s *wave = &this->wave.waves[i]; if (wave->pinStates == NULL) { firmwareError("wave pinStates is NULL"); return; } wave->pinStates[0] = initialState[i]; } isFrontEvent[0] = TV_HIGH == stateParam; wave.setSwitchTime(0, angle); wave.waves[waveIndex].pinStates[0] = state; return; } int exactMatch = wave.findAngleMatch(angle, size); if (exactMatch != EFI_ERROR_CODE) { firmwareError("same angle: not supported"); return; } int index = wave.waveIndertionAngle(angle, size); // shifting existing data // todo: does this logic actually work? I think it does not! for (int i = size - 1; i >= index; i--) { for (int j = 0; j < PWM_PHASE_MAX_WAVE_PER_PWM; j++) { wave.waves[j].pinStates[i + 1] = wave.getChannelState(j, index); } wave.setSwitchTime(i + 1, wave.getSwitchTime(i)); } isFrontEvent[index] = TV_HIGH == stateParam; if (index != size) { firmwareError("are we ever here?"); } // int index = size; size++; for (int i = 0; i < PWM_PHASE_MAX_WAVE_PER_PWM; i++) { wave.waves[i].pinStates[index] = wave.getChannelState(i, index - 1); } wave.setSwitchTime(index, angle); wave.waves[waveIndex].pinStates[index] = state; }