2020-03-23 20:20:54 -07:00
|
|
|
/*
|
|
|
|
* @file launch_control.cpp
|
|
|
|
*
|
|
|
|
* @date 10. sep. 2019
|
|
|
|
* Author: Ola Ruud
|
2024-03-09 05:39:58 -08:00
|
|
|
* Rework: Patryk Chmura
|
2020-03-23 20:20:54 -07:00
|
|
|
*/
|
|
|
|
|
2021-07-25 22:05:17 -07:00
|
|
|
#include "pch.h"
|
2020-03-23 20:20:54 -07:00
|
|
|
|
|
|
|
#if EFI_LAUNCH_CONTROL
|
|
|
|
#include "boost_control.h"
|
|
|
|
#include "launch_control.h"
|
|
|
|
#include "advance_map.h"
|
|
|
|
#include "engine_state.h"
|
|
|
|
#include "advance_map.h"
|
2021-11-25 19:40:19 -08:00
|
|
|
#include "tinymt32.h"
|
2020-03-23 20:20:54 -07:00
|
|
|
|
2020-11-19 18:14:38 -08:00
|
|
|
/**
|
|
|
|
* We can have active condition from switch or from clutch.
|
|
|
|
* In case we are dependent on VSS we just return true.
|
|
|
|
*/
|
2021-11-15 17:09:03 -08:00
|
|
|
bool LaunchControlBase::isInsideSwitchCondition() {
|
2022-01-24 17:58:21 -08:00
|
|
|
isSwitchActivated = engineConfiguration->launchActivationMode == SWITCH_INPUT_LAUNCH;
|
|
|
|
isClutchActivated = engineConfiguration->launchActivationMode == CLUTCH_INPUT_LAUNCH;
|
2024-06-21 08:49:56 -07:00
|
|
|
isBrakePedalActivated = engineConfiguration->launchActivationMode == STOP_INPUT_LAUNCH;
|
2022-01-24 17:58:21 -08:00
|
|
|
|
|
|
|
if (isSwitchActivated) {
|
2021-11-16 13:45:14 -08:00
|
|
|
#if !EFI_SIMULATOR
|
2021-11-17 00:54:21 -08:00
|
|
|
if (isBrainPinValid(engineConfiguration->launchActivatePin)) {
|
2022-04-19 17:43:41 -07:00
|
|
|
launchActivatePinState = engineConfiguration->launchActivateInverted ^ efiReadPin(engineConfiguration->launchActivatePin);
|
2020-03-23 20:20:54 -07:00
|
|
|
}
|
2021-11-16 13:31:35 -08:00
|
|
|
#endif // EFI_PROD_CODE
|
2021-11-15 17:09:03 -08:00
|
|
|
return launchActivatePinState;
|
2022-01-24 17:58:21 -08:00
|
|
|
} else if (isClutchActivated) {
|
2024-06-24 18:46:34 -07:00
|
|
|
return getClutchDownState();
|
2024-06-21 08:49:56 -07:00
|
|
|
} else if (isBrakePedalActivated) {
|
2024-06-24 18:46:34 -07:00
|
|
|
return getBrakePedalState();
|
2024-06-21 08:49:56 -07:00
|
|
|
} else {
|
2020-03-23 20:20:54 -07:00
|
|
|
// ALWAYS_ACTIVE_LAUNCH
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-19 18:14:38 -08:00
|
|
|
/**
|
2023-07-20 13:09:52 -07:00
|
|
|
* Returns True when Vehicle speed ALLOWS launch control
|
2024-02-29 19:33:37 -08:00
|
|
|
*/
|
2020-11-19 05:15:56 -08:00
|
|
|
bool LaunchControlBase::isInsideSpeedCondition() const {
|
2023-07-20 13:09:52 -07:00
|
|
|
if (engineConfiguration->launchSpeedThreshold == 0) {
|
|
|
|
return true; // allow launch, speed does not matter
|
|
|
|
}
|
|
|
|
|
2021-10-05 16:59:07 -07:00
|
|
|
int speed = Sensor::getOrZero(SensorType::VehicleSpeed);
|
2024-02-29 19:33:37 -08:00
|
|
|
|
2023-07-20 13:25:24 -07:00
|
|
|
return engineConfiguration->launchSpeedThreshold > speed;
|
2020-11-19 05:15:56 -08:00
|
|
|
}
|
|
|
|
|
2020-11-19 18:14:38 -08:00
|
|
|
/**
|
2021-11-16 13:46:54 -08:00
|
|
|
* Returns false if TPS is invalid or TPS > preset threshold
|
2020-11-19 18:14:38 -08:00
|
|
|
*/
|
2020-11-19 05:15:56 -08:00
|
|
|
bool LaunchControlBase::isInsideTpsCondition() const {
|
|
|
|
auto tps = Sensor::get(SensorType::DriverThrottleIntent);
|
|
|
|
|
|
|
|
// Disallow launch without valid TPS
|
|
|
|
if (!tps.Valid) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2022-07-20 15:48:55 -07:00
|
|
|
// todo: should this be 'launchTpsThreshold <= tps.Value' so that nicely calibrated TPS of zero does not prevent launch?
|
|
|
|
return engineConfiguration->launchTpsThreshold < tps.Value;
|
2020-11-19 05:15:56 -08:00
|
|
|
}
|
|
|
|
|
2024-09-25 00:20:18 -07:00
|
|
|
LaunchCondition LaunchControlBase::calculateRPMLaunchCondition(const float rpm) {
|
2024-10-04 16:08:27 -07:00
|
|
|
if ((engineConfiguration->launchActivationMode == SWITCH_INPUT_LAUNCH)
|
|
|
|
&& (engineConfiguration->torqueReductionActivationMode == LAUNCH_BUTTON)
|
|
|
|
&& engineConfiguration->torqueReductionEnabled
|
|
|
|
&& (engineConfiguration->torqueReductionArmingRpm <= rpm)
|
|
|
|
) {
|
|
|
|
// We need perform Shift Torque Reduction stuff (see
|
|
|
|
// https://github.com/rusefi/rusefi/issues/5608#issuecomment-2391500472 and
|
|
|
|
// https://github.com/rusefi/rusefi/issues/5608#issuecomment-2391772899 for details)
|
|
|
|
return LaunchCondition::NotMet;
|
|
|
|
}
|
|
|
|
|
2024-05-20 12:54:05 -07:00
|
|
|
const int launchRpm = engineConfiguration->launchRpm;
|
2024-05-21 00:06:17 -07:00
|
|
|
const int preLaunchRpm = launchRpm - engineConfiguration->launchRpmWindow;
|
|
|
|
if (rpm < preLaunchRpm) {
|
2024-05-20 12:54:05 -07:00
|
|
|
return LaunchCondition::NotMet;
|
2024-05-21 00:06:17 -07:00
|
|
|
} else if (launchRpm <= rpm) {
|
2024-05-20 12:54:05 -07:00
|
|
|
return LaunchCondition::Launch;
|
2024-05-21 00:06:17 -07:00
|
|
|
} else {
|
2024-06-13 14:15:03 -07:00
|
|
|
return LaunchCondition::PreLaunch;
|
2024-05-20 12:54:05 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-09-25 00:20:18 -07:00
|
|
|
LaunchCondition LaunchControlBase::calculateLaunchCondition(const float rpm) {
|
2024-06-11 11:11:39 -07:00
|
|
|
const LaunchCondition currentRpmLaunchCondition = calculateRPMLaunchCondition(rpm);
|
2021-12-16 13:19:33 -08:00
|
|
|
activateSwitchCondition = isInsideSwitchCondition();
|
2024-06-11 11:11:39 -07:00
|
|
|
rpmLaunchCondition = (currentRpmLaunchCondition == LaunchCondition::Launch);
|
2024-06-11 11:14:30 -07:00
|
|
|
rpmPreLaunchCondition = (currentRpmLaunchCondition == LaunchCondition::PreLaunch);
|
2021-12-16 13:19:33 -08:00
|
|
|
speedCondition = isInsideSpeedCondition();
|
|
|
|
tpsCondition = isInsideTpsCondition();
|
2020-03-23 20:20:54 -07:00
|
|
|
|
2024-06-10 10:11:56 -07:00
|
|
|
if(speedCondition && activateSwitchCondition && tpsCondition) {
|
2024-06-11 11:11:39 -07:00
|
|
|
return currentRpmLaunchCondition;
|
2024-06-10 10:11:56 -07:00
|
|
|
} else {
|
|
|
|
return LaunchCondition::NotMet;
|
|
|
|
}
|
2020-11-19 05:15:56 -08:00
|
|
|
}
|
|
|
|
|
2021-12-16 11:47:00 -08:00
|
|
|
LaunchControlBase::LaunchControlBase() {
|
|
|
|
launchActivatePinState = false;
|
2024-06-11 08:39:15 -07:00
|
|
|
isPreLaunchCondition = false;
|
2021-12-16 11:47:00 -08:00
|
|
|
isLaunchCondition = false;
|
|
|
|
}
|
|
|
|
|
2024-02-29 19:33:37 -08:00
|
|
|
float LaunchControlBase::getFuelCoefficient() const {
|
2022-11-13 17:23:19 -08:00
|
|
|
return 1 + (isLaunchCondition && engineConfiguration->launchControlEnabled ? engineConfiguration->launchFuelAdderPercent / 100.0 : 0);
|
|
|
|
}
|
|
|
|
|
2020-11-19 05:15:56 -08:00
|
|
|
void LaunchControlBase::update() {
|
2021-11-17 00:54:21 -08:00
|
|
|
if (!engineConfiguration->launchControlEnabled) {
|
2020-11-19 05:15:56 -08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2024-09-25 00:20:18 -07:00
|
|
|
const float rpm = Sensor::getOrZero(SensorType::Rpm);
|
2024-06-10 10:11:56 -07:00
|
|
|
const LaunchCondition launchCondition = calculateLaunchCondition(rpm);
|
2024-06-11 08:46:49 -07:00
|
|
|
isLaunchCondition = (launchCondition == LaunchCondition::Launch);
|
2024-06-11 08:39:15 -07:00
|
|
|
isPreLaunchCondition = (launchCondition == LaunchCondition::PreLaunch);
|
2020-11-19 18:14:38 -08:00
|
|
|
|
2021-12-16 11:47:00 -08:00
|
|
|
//and still recalculate in case user changed the values
|
2024-05-22 13:15:30 -07:00
|
|
|
retardThresholdRpm = engineConfiguration->launchRpm;
|
2020-11-19 05:15:56 -08:00
|
|
|
|
2024-06-07 04:55:15 -07:00
|
|
|
sparkSkipRatio = calculateSparkSkipRatio(rpm);
|
2020-11-19 05:15:56 -08:00
|
|
|
}
|
|
|
|
|
2021-11-15 16:48:55 -08:00
|
|
|
bool LaunchControlBase::isLaunchRpmRetardCondition() const {
|
2024-05-30 08:03:15 -07:00
|
|
|
return isLaunchCondition && engineConfiguration->launchControlEnabled && (retardThresholdRpm < Sensor::getOrZero(SensorType::Rpm));
|
2021-11-15 16:48:55 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
bool LaunchControlBase::isLaunchSparkRpmRetardCondition() const {
|
|
|
|
return isLaunchRpmRetardCondition() && engineConfiguration->launchSparkCutEnable;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool LaunchControlBase::isLaunchFuelRpmRetardCondition() const {
|
|
|
|
return isLaunchRpmRetardCondition() && engineConfiguration->launchFuelCutEnable;
|
2020-03-23 20:20:54 -07:00
|
|
|
}
|
|
|
|
|
2024-09-25 21:34:00 -07:00
|
|
|
float LaunchControlBase::calculateSparkSkipRatio(const float rpm) const {
|
2024-06-07 04:55:15 -07:00
|
|
|
float result = 0.0f;
|
|
|
|
if (engineConfiguration->launchControlEnabled && engineConfiguration->launchSparkCutEnable) {
|
|
|
|
if (isLaunchCondition) {
|
|
|
|
result = 1.0f;
|
2024-06-11 08:39:15 -07:00
|
|
|
} else if (isPreLaunchCondition) {
|
2024-06-07 04:55:15 -07:00
|
|
|
const int launchRpm = engineConfiguration->launchRpm;
|
|
|
|
const int sparkSkipStartRpm = launchRpm - engineConfiguration->launchRpmWindow;
|
|
|
|
if (sparkSkipStartRpm <= rpm) {
|
|
|
|
const float initialIgnitionCutRatio = engineConfiguration->initialIgnitionCutPercent / 100.0f;
|
|
|
|
const int sparkSkipEndRpm = launchRpm - engineConfiguration->launchCorrectionsEndRpm;
|
|
|
|
const float finalIgnitionCutRatio = engineConfiguration->finalIgnitionCutPercentBeforeLaunch / 100.0f;
|
|
|
|
result = interpolateClamped(sparkSkipStartRpm, initialIgnitionCutRatio, sparkSkipEndRpm, finalIgnitionCutRatio, rpm);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2024-06-06 06:33:23 -07:00
|
|
|
SoftSparkLimiter::SoftSparkLimiter(const bool p_allowHardCut)
|
|
|
|
: allowHardCut(p_allowHardCut) {
|
2023-05-25 15:52:19 -07:00
|
|
|
#if EFI_UNIT_TEST
|
|
|
|
initLaunchControl();
|
|
|
|
#endif // EFI_UNIT_TEST
|
2023-05-25 09:41:11 -07:00
|
|
|
}
|
|
|
|
|
2024-06-07 04:55:15 -07:00
|
|
|
void SoftSparkLimiter::updateTargetSkipRatio(
|
|
|
|
const float luaSparkSkip,
|
|
|
|
const float tractionControlSparkSkip,
|
2024-10-04 15:19:48 -07:00
|
|
|
const float launchOrShiftTorqueReductionControllerSparkSkipRatio
|
2024-06-07 04:55:15 -07:00
|
|
|
) {
|
2024-06-06 07:29:48 -07:00
|
|
|
targetSkipRatio = luaSparkSkip;
|
|
|
|
if (engineConfiguration->useHardSkipInTraction) {
|
|
|
|
if (allowHardCut) {
|
|
|
|
targetSkipRatio += tractionControlSparkSkip;
|
|
|
|
}
|
|
|
|
} else if (!allowHardCut) {
|
|
|
|
targetSkipRatio += tractionControlSparkSkip;
|
|
|
|
}
|
2024-06-07 04:55:15 -07:00
|
|
|
|
|
|
|
if (allowHardCut) {
|
|
|
|
/*
|
|
|
|
* We are applying launch controller spark skip ratio only for hard skip limiter (see
|
|
|
|
* https://github.com/rusefi/rusefi/issues/6566#issuecomment-2153149902).
|
|
|
|
*/
|
2024-10-04 15:19:48 -07:00
|
|
|
targetSkipRatio += launchOrShiftTorqueReductionControllerSparkSkipRatio;
|
2024-06-07 04:55:15 -07:00
|
|
|
}
|
2024-06-06 07:29:48 -07:00
|
|
|
}
|
|
|
|
|
2021-11-25 19:40:19 -08:00
|
|
|
static tinymt32_t tinymt;
|
|
|
|
|
2021-11-16 10:15:12 -08:00
|
|
|
bool SoftSparkLimiter::shouldSkip() {
|
2023-05-25 12:17:07 -07:00
|
|
|
if (targetSkipRatio == 0 || (!allowHardCut && wasJustSkipped)) {
|
2021-11-16 10:15:12 -08:00
|
|
|
wasJustSkipped = false;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2021-11-25 19:40:19 -08:00
|
|
|
float r = tinymt32_generate_float(&tinymt);
|
2023-05-25 12:17:07 -07:00
|
|
|
wasJustSkipped = r < (allowHardCut ? 1 : 2) * targetSkipRatio;
|
2021-11-16 10:15:12 -08:00
|
|
|
return wasJustSkipped;
|
|
|
|
}
|
|
|
|
|
2021-11-16 01:15:29 -08:00
|
|
|
void initLaunchControl() {
|
2021-11-25 19:40:19 -08:00
|
|
|
tinymt32_init(&tinymt, 1345135);
|
2020-03-23 20:20:54 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* EFI_LAUNCH_CONTROL */
|