2015-07-10 06:01:56 -07:00
|
|
|
/**
|
|
|
|
* @file advance_map.cpp
|
|
|
|
*
|
|
|
|
* @date Mar 27, 2013
|
2020-01-07 21:02:40 -08:00
|
|
|
* @author Andrey Belomutskiy, (c) 2012-2020
|
2015-07-10 06:01:56 -07:00
|
|
|
*
|
|
|
|
* 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/>.
|
|
|
|
*/
|
|
|
|
|
2021-07-25 22:05:17 -07:00
|
|
|
#include "pch.h"
|
|
|
|
|
2015-07-10 06:01:56 -07:00
|
|
|
#include "advance_map.h"
|
2019-03-22 19:55:51 -07:00
|
|
|
#include "idle_thread.h"
|
2020-03-24 16:55:12 -07:00
|
|
|
#include "launch_control.h"
|
2022-09-16 17:07:04 -07:00
|
|
|
#include "gppwm_channel.h"
|
2015-07-10 06:01:56 -07:00
|
|
|
|
2020-02-26 15:16:35 -08:00
|
|
|
#if EFI_ENGINE_CONTROL
|
|
|
|
|
2023-03-01 14:08:37 -08:00
|
|
|
// TODO: wow move this into engineState at least for context not to leak from test to test!
|
2021-05-23 10:54:49 -07:00
|
|
|
// todo: reset this between cranking attempts?! #2735
|
2024-09-24 23:52:14 -07:00
|
|
|
float minCrankingRpm = 0;
|
2017-12-03 10:25:24 -08:00
|
|
|
|
2024-05-03 19:13:30 -07:00
|
|
|
static Map3D<TRACTION_CONTROL_ETB_DROP_SIZE, TRACTION_CONTROL_ETB_DROP_SIZE, int8_t, uint16_t, uint8_t> tcTimingDropTable{"tct"};
|
|
|
|
static Map3D<TRACTION_CONTROL_ETB_DROP_SIZE, TRACTION_CONTROL_ETB_DROP_SIZE, int8_t, uint16_t, uint8_t> tcSparkSkipTable{"tcs"};
|
2024-02-03 14:02:30 -08:00
|
|
|
|
2023-11-04 21:18:31 -07:00
|
|
|
#if EFI_ENGINE_CONTROL && EFI_SHAFT_POSITION_INPUT
|
|
|
|
|
2015-07-10 06:01:56 -07:00
|
|
|
/**
|
|
|
|
* @return ignition timing angle advance before TDC
|
|
|
|
*/
|
2024-09-24 23:52:14 -07:00
|
|
|
angle_t getRunningAdvance(float rpm, float engineLoad) {
|
2024-07-22 12:15:40 -07:00
|
|
|
if (std::isnan(engineLoad)) {
|
2023-04-11 17:01:34 -07:00
|
|
|
warning(ObdCode::CUSTOM_NAN_ENGINE_LOAD, "NaN engine load");
|
2015-07-10 06:01:56 -07:00
|
|
|
return NAN;
|
|
|
|
}
|
2020-03-24 16:55:12 -07:00
|
|
|
|
2024-07-22 16:00:59 -07:00
|
|
|
efiAssert(ObdCode::CUSTOM_ERR_ASSERT, !std::isnan(engineLoad), "invalid el", NAN);
|
2015-07-10 06:01:56 -07:00
|
|
|
|
2022-09-16 17:07:04 -07:00
|
|
|
// compute base ignition angle from main table
|
2021-12-20 05:14:30 -08:00
|
|
|
float advanceAngle = interpolate3d(
|
|
|
|
config->ignitionTable,
|
|
|
|
config->ignitionLoadBins, engineLoad,
|
|
|
|
config->ignitionRpmBins, rpm
|
|
|
|
);
|
2020-03-24 16:55:12 -07:00
|
|
|
|
2024-02-03 14:02:30 -08:00
|
|
|
float vehicleSpeed = Sensor::getOrZero(SensorType::VehicleSpeed);
|
|
|
|
float wheelSlip = Sensor::getOrZero(SensorType::WheelSlipRatio);
|
2024-03-04 15:23:48 -08:00
|
|
|
engine->ignitionState.tractionAdvanceDrop = tcTimingDropTable.getValue(wheelSlip, vehicleSpeed);
|
2024-03-04 18:21:17 -08:00
|
|
|
engine->engineState.tractionControlSparkSkip = tcSparkSkipTable.getValue(wheelSlip, vehicleSpeed);
|
|
|
|
engine->engineState.updateSparkSkip();
|
2024-02-03 14:02:30 -08:00
|
|
|
|
|
|
|
advanceAngle += engine->ignitionState.tractionAdvanceDrop;
|
|
|
|
|
2022-12-21 16:46:31 -08:00
|
|
|
#if EFI_ANTILAG_SYSTEM
|
2023-06-01 11:09:30 -07:00
|
|
|
if (engine->antilagController.isAntilagCondition) {
|
|
|
|
float throttleIntent = Sensor::getOrZero(SensorType::DriverThrottleIntent);
|
2022-12-21 16:46:31 -08:00
|
|
|
engine->antilagController.timingALSCorrection = interpolate3d(
|
|
|
|
config->ALSTimingRetardTable,
|
2023-02-06 14:14:21 -08:00
|
|
|
config->alsIgnRetardLoadBins, throttleIntent,
|
2022-12-21 16:46:31 -08:00
|
|
|
config->alsIgnRetardrpmBins, rpm
|
|
|
|
);
|
|
|
|
advanceAngle += engine->antilagController.timingALSCorrection;
|
2023-06-01 11:09:30 -07:00
|
|
|
}
|
2022-12-21 16:46:31 -08:00
|
|
|
#endif /* EFI_ANTILAG_SYSTEM */
|
|
|
|
|
2022-09-16 17:07:04 -07:00
|
|
|
// Add any adjustments if configured
|
|
|
|
for (size_t i = 0; i < efi::size(config->ignBlends); i++) {
|
|
|
|
auto result = calculateBlend(config->ignBlends[i], rpm, engineLoad);
|
|
|
|
|
2023-04-02 13:56:42 -07:00
|
|
|
engine->outputChannels.ignBlendParameter[i] = result.BlendParameter;
|
2022-09-16 17:07:04 -07:00
|
|
|
engine->outputChannels.ignBlendBias[i] = result.Bias;
|
|
|
|
engine->outputChannels.ignBlendOutput[i] = result.Value;
|
|
|
|
|
|
|
|
advanceAngle += result.Value;
|
|
|
|
}
|
|
|
|
|
2018-01-22 20:47:58 -08:00
|
|
|
// get advance from the separate table for Idle
|
2022-12-17 15:04:54 -08:00
|
|
|
#if EFI_IDLE_CONTROL
|
2021-11-17 09:13:19 -08:00
|
|
|
if (engineConfiguration->useSeparateAdvanceForIdle &&
|
2023-06-01 11:09:30 -07:00
|
|
|
engine->module<IdleController>()->isIdlingOrTaper()) {
|
2021-02-16 06:32:16 -08:00
|
|
|
float idleAdvance = interpolate2d(rpm, config->idleAdvanceBins, config->idleAdvance);
|
2020-04-03 16:59:08 -07:00
|
|
|
|
2022-07-28 00:04:28 -07:00
|
|
|
auto tps = Sensor::get(SensorType::DriverThrottleIntent);
|
|
|
|
if (tps) {
|
2020-04-03 16:59:08 -07:00
|
|
|
// interpolate between idle table and normal (running) table using TPS threshold
|
2022-07-28 00:04:28 -07:00
|
|
|
advanceAngle = interpolateClamped(0.0f, idleAdvance, engineConfiguration->idlePidDeactivationTpsThreshold, advanceAngle, tps.Value);
|
2020-04-03 16:59:08 -07:00
|
|
|
}
|
2018-01-22 20:47:58 -08:00
|
|
|
}
|
2022-12-17 15:04:54 -08:00
|
|
|
#endif
|
2018-01-22 20:47:58 -08:00
|
|
|
|
2020-03-24 16:55:12 -07:00
|
|
|
#if EFI_LAUNCH_CONTROL
|
2024-06-11 11:49:20 -07:00
|
|
|
if (engineConfiguration->launchControlEnabled && engineConfiguration->enableLaunchRetard) {
|
|
|
|
const float launchAngle = engineConfiguration->launchTimingRetard;
|
2024-06-11 12:22:38 -07:00
|
|
|
if (engine->launchController.isPreLaunchCondition) {
|
|
|
|
const int launchRpm = engineConfiguration->launchRpm;
|
|
|
|
const int smoothRetardStartRpm = (launchRpm - engineConfiguration->launchRpmWindow);
|
|
|
|
const int smoothRetardEndRpm = (launchRpm - engineConfiguration->launchCorrectionsEndRpm);
|
|
|
|
if (smoothRetardStartRpm <= rpm) {
|
|
|
|
if (engineConfiguration->launchSmoothRetard && (rpm <= smoothRetardEndRpm)) {
|
|
|
|
// https://github.com/rusefi/rusefi/issues/5611#issuecomment-2130431696
|
|
|
|
return interpolateClamped(smoothRetardStartRpm, advanceAngle, smoothRetardEndRpm, launchAngle, rpm);
|
|
|
|
} else {
|
|
|
|
return launchAngle;
|
|
|
|
}
|
2024-05-28 15:12:07 -07:00
|
|
|
}
|
2024-06-11 12:22:38 -07:00
|
|
|
} else if (engine->launchController.isLaunchCondition) {
|
|
|
|
return launchAngle;
|
2023-06-01 11:09:30 -07:00
|
|
|
}
|
2020-03-24 16:55:12 -07:00
|
|
|
}
|
2024-10-04 15:52:26 -07:00
|
|
|
if (engineConfiguration->torqueReductionEnabled
|
|
|
|
&& engine->shiftTorqueReductionController.isFlatShiftConditionSatisfied
|
|
|
|
) {
|
|
|
|
return engineConfiguration->torqueReductionIgnitionRetard;
|
|
|
|
}
|
2020-03-24 16:55:12 -07:00
|
|
|
#endif /* EFI_LAUNCH_CONTROL */
|
|
|
|
|
2018-01-22 20:47:58 -08:00
|
|
|
return advanceAngle;
|
|
|
|
}
|
|
|
|
|
2024-03-20 11:05:56 -07:00
|
|
|
angle_t getAdvanceCorrections(float engineLoad) {
|
2022-07-28 00:04:28 -07:00
|
|
|
auto iat = Sensor::get(SensorType::Iat);
|
2020-04-18 15:45:30 -07:00
|
|
|
|
2022-07-28 00:04:28 -07:00
|
|
|
if (!iat) {
|
2023-01-15 05:26:08 -08:00
|
|
|
engine->ignitionState.timingIatCorrection = 0;
|
2016-05-17 21:03:11 -07:00
|
|
|
} else {
|
2023-01-15 05:26:08 -08:00
|
|
|
engine->ignitionState.timingIatCorrection = interpolate3d(
|
2021-12-20 05:14:30 -08:00
|
|
|
config->ignitionIatCorrTable,
|
2023-01-06 18:59:34 -08:00
|
|
|
config->ignitionIatCorrLoadBins, engineLoad,
|
|
|
|
config->ignitionIatCorrTempBins, iat.Value
|
2021-12-20 05:14:30 -08:00
|
|
|
);
|
2016-05-17 21:03:11 -07:00
|
|
|
}
|
2020-04-18 15:45:30 -07:00
|
|
|
|
2023-11-04 10:05:19 -07:00
|
|
|
#if EFI_IDLE_CONTROL
|
2022-11-06 08:56:18 -08:00
|
|
|
float instantRpm = engine->triggerCentral.instantRpm.getInstantRpm();
|
2022-08-29 19:18:06 -07:00
|
|
|
|
2023-01-15 05:26:08 -08:00
|
|
|
engine->ignitionState.timingPidCorrection = engine->module<IdleController>()->getIdleTimingAdjustment(instantRpm);
|
2023-11-04 10:05:19 -07:00
|
|
|
#endif // EFI_IDLE_CONTROL
|
2019-03-22 19:55:51 -07:00
|
|
|
|
2019-04-12 19:07:03 -07:00
|
|
|
#if EFI_TUNER_STUDIO
|
2023-05-04 14:00:18 -07:00
|
|
|
engine->outputChannels.multiSparkCounter = engine->engineState.multispark.count;
|
2018-11-16 04:40:06 -08:00
|
|
|
#endif /* EFI_TUNER_STUDIO */
|
2020-03-25 22:49:36 -07:00
|
|
|
|
2023-01-15 05:26:08 -08:00
|
|
|
return engine->ignitionState.timingIatCorrection
|
|
|
|
+ engine->ignitionState.cltTimingCorrection
|
|
|
|
+ engine->ignitionState.timingPidCorrection;
|
2015-07-10 06:01:56 -07:00
|
|
|
}
|
|
|
|
|
2018-02-02 05:18:00 -08:00
|
|
|
/**
|
|
|
|
* @return ignition timing angle advance before TDC for Cranking
|
|
|
|
*/
|
2024-09-24 23:52:14 -07:00
|
|
|
angle_t getCrankingAdvance(float rpm, float engineLoad) {
|
2018-02-02 05:18:00 -08:00
|
|
|
// get advance from the separate table for Cranking
|
2021-11-17 00:54:21 -08:00
|
|
|
if (engineConfiguration->useSeparateAdvanceForCranking) {
|
2022-05-01 20:43:43 -07:00
|
|
|
return interpolate2d(rpm, config->crankingAdvanceBins, config->crankingAdvance);
|
2018-02-02 05:18:00 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Interpolate the cranking timing angle to the earlier running angle for faster engine start
|
2021-11-17 00:54:21 -08:00
|
|
|
angle_t crankingToRunningTransitionAngle = getRunningAdvance(engineConfiguration->cranking.rpm, engineLoad);
|
2018-02-02 05:18:00 -08:00
|
|
|
// interpolate not from zero, but starting from min. possible rpm detected
|
|
|
|
if (rpm < minCrankingRpm || minCrankingRpm == 0)
|
|
|
|
minCrankingRpm = rpm;
|
2021-11-17 00:54:21 -08:00
|
|
|
return interpolateClamped(minCrankingRpm, engineConfiguration->crankingTimingAngle, engineConfiguration->cranking.rpm, crankingToRunningTransitionAngle, rpm);
|
2018-02-02 05:18:00 -08:00
|
|
|
}
|
2023-11-04 10:05:19 -07:00
|
|
|
#endif // EFI_ENGINE_CONTROL && EFI_SHAFT_POSITION_INPUT
|
2018-02-02 05:18:00 -08:00
|
|
|
|
2024-09-24 23:52:14 -07:00
|
|
|
angle_t getAdvance(float rpm, float engineLoad) {
|
2019-04-12 19:07:03 -07:00
|
|
|
#if EFI_ENGINE_CONTROL && EFI_SHAFT_POSITION_INPUT
|
2024-07-22 12:15:40 -07:00
|
|
|
if (std::isnan(engineLoad)) {
|
2017-12-03 13:45:39 -08:00
|
|
|
return 0; // any error should already be reported
|
|
|
|
}
|
2024-09-01 13:58:04 -07:00
|
|
|
if (engineConfiguration->timingMode == TM_FIXED) {
|
|
|
|
// fixed timing is the simple: cranking/running does not matter, no corrections!
|
|
|
|
return engineConfiguration->fixedTiming;
|
|
|
|
}
|
2020-04-02 05:54:55 -07:00
|
|
|
|
2015-07-10 06:01:56 -07:00
|
|
|
angle_t angle;
|
2020-04-02 05:54:55 -07:00
|
|
|
|
2021-11-17 00:54:21 -08:00
|
|
|
bool isCranking = engine->rpmCalculator.isCranking();
|
2020-04-02 05:54:55 -07:00
|
|
|
if (isCranking) {
|
2021-11-16 01:15:29 -08:00
|
|
|
angle = getCrankingAdvance(rpm, engineLoad);
|
2023-04-11 17:01:34 -07:00
|
|
|
assertAngleRange(angle, "crAngle", ObdCode::CUSTOM_ERR_ANGLE_CR);
|
2024-07-22 12:15:40 -07:00
|
|
|
efiAssert(ObdCode::CUSTOM_ERR_ASSERT, !std::isnan(angle), "cr_AngleN", 0);
|
2015-07-10 06:01:56 -07:00
|
|
|
} else {
|
2021-11-16 01:15:29 -08:00
|
|
|
angle = getRunningAdvance(rpm, engineLoad);
|
2020-04-02 05:54:55 -07:00
|
|
|
|
2024-07-22 12:15:40 -07:00
|
|
|
if (std::isnan(angle)) {
|
2023-04-11 17:01:34 -07:00
|
|
|
warning(ObdCode::CUSTOM_ERR_6610, "NaN angle from table");
|
2018-09-16 19:11:59 -07:00
|
|
|
return 0;
|
|
|
|
}
|
2020-04-02 05:54:55 -07:00
|
|
|
}
|
|
|
|
|
2024-09-01 13:58:04 -07:00
|
|
|
// Allow if we're either not cranking OR allowed to correct in cranking
|
|
|
|
bool allowCorrections = !isCranking || engineConfiguration->useAdvanceCorrectionsForCranking;
|
2020-04-02 05:54:55 -07:00
|
|
|
|
|
|
|
if (allowCorrections) {
|
2023-01-06 18:59:34 -08:00
|
|
|
angle_t correction = getAdvanceCorrections(engineLoad);
|
2024-07-22 12:15:40 -07:00
|
|
|
if (!std::isnan(correction)) { // correction could be NaN during settings update
|
2018-10-07 11:22:05 -07:00
|
|
|
angle += correction;
|
|
|
|
}
|
2015-07-10 06:01:56 -07:00
|
|
|
}
|
2020-04-02 05:54:55 -07:00
|
|
|
|
2024-07-22 12:15:40 -07:00
|
|
|
efiAssert(ObdCode::CUSTOM_ERR_ASSERT, !std::isnan(angle), "_AngleN5", 0);
|
2015-07-10 06:01:56 -07:00
|
|
|
return angle;
|
2019-01-31 14:55:23 -08:00
|
|
|
#else
|
|
|
|
return 0;
|
|
|
|
#endif
|
2015-07-10 06:01:56 -07:00
|
|
|
}
|
|
|
|
|
2024-09-24 23:52:14 -07:00
|
|
|
angle_t getWrappedAdvance(const float rpm, const float engineLoad) {
|
2024-07-25 09:43:49 -07:00
|
|
|
angle_t angle = getAdvance(rpm, engineLoad) * engine->ignitionState.luaTimingMult + engine->ignitionState.luaTimingAdd;
|
|
|
|
wrapAngle(angle, "getWrappedAdvance", ObdCode::CUSTOM_ERR_ADCANCE_CALC_ANGLE);
|
|
|
|
return angle;
|
|
|
|
}
|
|
|
|
|
2024-09-24 23:52:14 -07:00
|
|
|
angle_t getCylinderIgnitionTrim(size_t cylinderNumber, float rpm, float ignitionLoad) {
|
2024-03-24 18:45:03 -07:00
|
|
|
return interpolate3d(
|
2022-01-01 12:47:47 -08:00
|
|
|
config->ignTrims[cylinderNumber].table,
|
|
|
|
config->ignTrimLoadBins, ignitionLoad,
|
|
|
|
config->ignTrimRpmBins, rpm
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2024-09-24 23:52:14 -07:00
|
|
|
size_t getMultiSparkCount(float rpm) {
|
2020-03-25 22:49:36 -07:00
|
|
|
// Compute multispark (if enabled)
|
2021-11-17 00:54:21 -08:00
|
|
|
if (engineConfiguration->multisparkEnable
|
|
|
|
&& rpm <= engineConfiguration->multisparkMaxRpm
|
|
|
|
&& engineConfiguration->multisparkMaxExtraSparkCount > 0) {
|
2020-03-25 22:49:36 -07:00
|
|
|
// For zero RPM, disable multispark. We don't yet know the engine speed, so multispark may not be safe.
|
|
|
|
if (rpm == 0) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2022-04-28 05:16:02 -07:00
|
|
|
floatus_t multiDelay = 1000.0f * engineConfiguration->multisparkSparkDuration;
|
|
|
|
floatus_t multiDwell = 1000.0f * engineConfiguration->multisparkDwell;
|
2020-03-25 22:49:36 -07:00
|
|
|
|
2022-04-28 05:16:02 -07:00
|
|
|
// dwell times are below 10 seconds here so we use 32 bit type for performance reasons
|
2021-11-17 00:54:21 -08:00
|
|
|
engine->engineState.multispark.delay = (uint32_t)USF2NT(multiDelay);
|
|
|
|
engine->engineState.multispark.dwell = (uint32_t)USF2NT(multiDwell);
|
2020-03-25 22:49:36 -07:00
|
|
|
|
|
|
|
constexpr float usPerDegreeAt1Rpm = 60e6 / 360;
|
|
|
|
floatus_t usPerDegree = usPerDegreeAt1Rpm / rpm;
|
|
|
|
|
|
|
|
// How long is there for sparks? The user configured an angle, convert to time.
|
2021-11-17 00:54:21 -08:00
|
|
|
floatus_t additionalSparksUs = usPerDegree * engineConfiguration->multisparkMaxSparkingAngle;
|
2020-03-25 22:49:36 -07:00
|
|
|
// How long does one spark take?
|
|
|
|
floatus_t oneSparkTime = multiDelay + multiDwell;
|
|
|
|
|
|
|
|
// How many sparks can we fit in the alloted time?
|
|
|
|
float sparksFitInTime = additionalSparksUs / oneSparkTime;
|
|
|
|
|
|
|
|
// Take the floor (convert to uint8_t) - we want to undershoot, not overshoot
|
|
|
|
uint32_t floored = sparksFitInTime;
|
|
|
|
|
|
|
|
// Allow no more than the maximum number of extra sparks
|
2021-11-17 00:54:21 -08:00
|
|
|
return minI(floored, engineConfiguration->multisparkMaxExtraSparkCount);
|
2020-03-25 22:49:36 -07:00
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-02-03 14:02:30 -08:00
|
|
|
void initIgnitionAdvanceControl() {
|
2024-03-04 14:58:24 -08:00
|
|
|
tcTimingDropTable.initTable(engineConfiguration->tractionControlTimingDrop, engineConfiguration->tractionControlSlipBins, engineConfiguration->tractionControlSpeedBins);
|
2024-03-04 18:21:17 -08:00
|
|
|
tcSparkSkipTable.initTable(engineConfiguration->tractionControlIgnitionSkip, engineConfiguration->tractionControlSlipBins, engineConfiguration->tractionControlSpeedBins);
|
2024-02-03 14:02:30 -08:00
|
|
|
}
|
|
|
|
|
2020-02-26 15:16:35 -08:00
|
|
|
#endif // EFI_ENGINE_CONTROL
|