rusefi/firmware/controllers/algo/engine.cpp

606 lines
18 KiB
C++
Raw Normal View History

2015-07-10 06:01:56 -07:00
/**
* @file engine.cpp
*
*
* This might be a http://en.wikipedia.org/wiki/God_object but that's best way I can
* express myself in C/C++. I am open for suggestions :)
*
* @date May 21, 2014
2020-01-07 21:02:40 -08:00
* @author Andrey Belomutskiy, (c) 2012-2020
2015-07-10 06:01:56 -07:00
*/
#include "pch.h"
2015-07-10 06:01:56 -07:00
#include "trigger_central.h"
#include "fuel_math.h"
#include "advance_map.h"
#include "speed_density.h"
2016-01-01 16:02:59 -08:00
#include "advance_map.h"
#include "init.h"
2022-09-07 12:56:45 -07:00
#include "rusefi_wideband.h"
2017-11-26 19:30:37 -08:00
#include "aux_valves.h"
#include "map_averaging.h"
2019-10-11 17:43:21 -07:00
#include "perf_trace.h"
2020-09-07 12:08:54 -07:00
#include "backup_ram.h"
#include "idle_thread.h"
#include "idle_hardware.h"
#include "gppwm.h"
#include "tachometer.h"
2023-10-15 14:59:39 -07:00
#include "speedometer.h"
#include "dynoview.h"
#include "boost_control.h"
#include "fan_control.h"
#include "ac_control.h"
#include "vr_pwm.h"
2024-03-10 04:54:04 -07:00
#include "max3185x.h"
2020-10-19 19:04:06 -07:00
#if EFI_MC33816
#include "mc33816.h"
#endif // EFI_MC33816
2015-07-10 06:01:56 -07:00
#include "bench_test.h"
2019-04-12 19:07:03 -07:00
#if EFI_PROD_CODE
#include "trigger_emulator_algo.h"
2016-01-23 15:01:40 -08:00
#endif /* EFI_PROD_CODE */
2015-07-10 06:01:56 -07:00
#if (BOARD_TLE8888_COUNT > 0)
#include "gpio/tle8888.h"
#endif
2019-12-21 17:43:11 -08:00
#if EFI_ENGINE_SNIFFER
#include "engine_sniffer.h"
extern int waveChartUsedSize;
extern WaveChart waveChart;
#endif /* EFI_ENGINE_SNIFFER */
void Engine::resetEngineSnifferIfInTestMode() {
#if EFI_ENGINE_SNIFFER
if (isFunctionalTestMode) {
// TODO: what is the exact reasoning for the exact engine sniffer pause time I wonder
waveChart.pauseEngineSnifferUntilNt = getTimeNowNt() + MS2NT(300);
2019-12-21 17:43:11 -08:00
waveChart.reset();
}
#endif /* EFI_ENGINE_SNIFFER */
}
2021-10-24 14:05:37 -07:00
/**
* VVT decoding delegates to universal trigger decoder. Here we map vvt_mode_e into corresponding trigger_type_e
*/
2020-08-26 10:30:55 -07:00
trigger_type_e getVvtTriggerType(vvt_mode_e vvtMode) {
switch (vvtMode) {
case VVT_INACTIVE:
return trigger_type_e::TT_HALF_MOON;
2023-09-14 13:53:16 -07:00
case VVT_TOYOTA_3_TOOTH:
return trigger_type_e::TT_VVT_TOYOTA_3_TOOTH;
2022-01-31 15:20:43 -08:00
case VVT_MIATA_NB:
return trigger_type_e::TT_VVT_MIATA_NB;
2020-08-26 21:43:23 -07:00
case VVT_BOSCH_QUICK_START:
return trigger_type_e::TT_VVT_BOSCH_QUICK_START;
2022-09-24 20:43:00 -07:00
case VVT_HONDA_K_EXHAUST:
return trigger_type_e::TT_HONDA_K_CAM_4_1;
2022-09-24 20:25:36 -07:00
case VVT_HONDA_K_INTAKE:
case VVT_SINGLE_TOOTH:
2022-08-31 21:18:06 -07:00
case VVT_MAP_V_TWIN:
return trigger_type_e::TT_HALF_MOON;
case VVT_FORD_ST170:
return trigger_type_e::TT_FORD_ST170;
case VVT_BARRA_3_PLUS_1:
return trigger_type_e::TT_VVT_BARRA_3_PLUS_1;
case VVT_FORD_COYOTE:
return trigger_type_e::TT_VVT_FORD_COYOTE;
case VVT_DEV:
return trigger_type_e::TT_DEV;
case VVT_MAZDA_SKYACTIV:
return trigger_type_e::TT_VVT_MAZDA_SKYACTIV;
2024-05-27 21:07:57 -07:00
case VVT_MAZDA_L:
return trigger_type_e::TT_VVT_MAZDA_L;
2021-07-03 06:43:27 -07:00
case VVT_NISSAN_VQ:
return trigger_type_e::TT_VVT_NISSAN_VQ35;
2022-03-22 03:34:22 -07:00
case VVT_TOYOTA_4_1:
return trigger_type_e::TT_VVT_TOYOTA_4_1;
2023-08-24 22:10:03 -07:00
case VVT_MITSUBISHI_4G69:
return trigger_type_e::TT_VVT_MITSUBISHI_4G69;
case VVT_MITSUBISHI_3A92:
return trigger_type_e::TT_VVT_MITSUBISHI_3A92;
2023-11-08 11:51:12 -08:00
case VVT_MITSUBISHI_6G72:
return trigger_type_e::TT_VVT_MITSU_6G72;
case VVT_HONDA_CBR_600:
return trigger_type_e::TT_HONDA_CBR_600;
case VVT_MITSUBISHI_6G75:
case VVT_NISSAN_MR:
return trigger_type_e::TT_NISSAN_MR18_CAM_VVT;
case VVT_MITSUBISHI_4G9x:
return trigger_type_e::TT_MITSU_4G9x_CAM;
case VVT_MITSUBISHI_4G63:
return trigger_type_e::TT_MITSU_4G63_CAM;
2024-09-07 21:27:05 -07:00
case VVT_HR12DDR_IN:
return trigger_type_e::TT_NISSAN_HR_CAM_IN;
2020-08-26 10:30:55 -07:00
default:
2024-02-08 17:17:53 -08:00
criticalError("Broken VVT mode maybe corrupted calibration %d: %s", vvtMode, getVvt_mode_e(vvtMode));
return trigger_type_e::TT_HALF_MOON; // we have to return something for the sake of -Werror=return-type
2020-08-26 10:30:55 -07:00
}
}
2022-04-02 16:27:18 -07:00
void Engine::updateTriggerWaveform() {
2020-08-26 20:35:11 -07:00
2019-04-12 19:07:03 -07:00
#if EFI_ENGINE_CONTROL && EFI_SHAFT_POSITION_INPUT
2018-12-25 18:18:14 -08:00
// we have a confusing threading model so some synchronization would not hurt
chibios_rt::CriticalSectionLocker csl;
2018-12-25 18:18:14 -08:00
engine->triggerCentral.updateWaveform();
2020-08-26 10:30:55 -07:00
if (!engine->triggerCentral.triggerShape.shapeDefinitionError) {
prepareOutputSignals();
2018-12-25 18:18:14 -08:00
}
2019-01-31 14:55:23 -08:00
#endif /* EFI_ENGINE_CONTROL && EFI_SHAFT_POSITION_INPUT */
}
void Engine::periodicSlowCallback() {
2019-10-11 17:43:21 -07:00
ScopePerf perf(PE::EnginePeriodicSlowCallback);
#if EFI_CAN_SUPPORT
if (engineConfiguration->suppressWboWorkaround7048) {
static Timer canBusWboSetIndex;
if (canBusWboSetIndex.getElapsedSeconds() > 1) {
canBusWboSetIndex.reset();
setWidebandOffset(3);
}
}
#endif // EFI_CAN_SUPPORT
2022-12-17 11:43:51 -08:00
#if EFI_SHAFT_POSITION_INPUT
// Re-read config in case it's changed
triggerCentral.primaryTriggerConfiguration.update();
2021-02-08 19:21:02 -08:00
for (int camIndex = 0;camIndex < CAMS_PER_BANK;camIndex++) {
triggerCentral.vvtTriggerConfiguration[camIndex].update();
2021-02-08 19:21:02 -08:00
}
getEngineState()->heaterControlEnabled = engineConfiguration->forceO2Heating || engine->rpmCalculator.isRunning();
enginePins.o2heater.setValue(getEngineState()->heaterControlEnabled);
enginePins.starterRelayDisable.setValue(Sensor::getOrZero(SensorType::Rpm) < engineConfiguration->cranking.rpm);
2022-12-17 11:43:51 -08:00
#endif // EFI_SHAFT_POSITION_INPUT
2022-09-09 15:02:38 -07:00
efiWatchdog();
updateSlowSensors();
checkShutdown();
2024-08-01 21:45:54 -07:00
module<TpsAccelEnrichment>()->onNewValue(Sensor::getOrZero(SensorType::Tps1));
updateVrThresholdPwm();
updateGppwm();
engine->engineModules.apply_all([](auto & m) { m.onSlowCallback(); });
#if (BOARD_TLE8888_COUNT > 0)
tle8888startup();
#endif
#if EFI_DYNO_VIEW
updateDynoView();
#endif
slowCallBackWasInvoked = true;
#if EFI_PROD_CODE
void baroLps25Update();
baroLps25Update();
#endif // EFI_PROD_CODE
2018-12-25 18:18:14 -08:00
}
2015-07-10 06:01:56 -07:00
/**
* We are executing these heavy (logarithm) methods from outside the trigger callbacks for performance reasons.
2016-01-01 14:02:49 -08:00
* See also periodicFastCallback
2015-07-10 06:01:56 -07:00
*/
void Engine::updateSlowSensors() {
updateSwitchInputs();
2020-12-26 18:31:41 -08:00
2022-12-17 11:43:51 -08:00
#if EFI_SHAFT_POSITION_INPUT
2024-09-25 00:16:53 -07:00
float rpm = Sensor::getOrZero(SensorType::Rpm);
triggerCentral.isEngineSnifferEnabled = rpm < engineConfiguration->engineSnifferRpmThreshold;
2022-09-15 18:45:48 -07:00
getEngineState()->sensorChartMode = rpm < engineConfiguration->sensorSnifferRpmThreshold ? engineConfiguration->sensorChartMode : SC_OFF;
2016-01-30 19:03:36 -08:00
engineState.updateSlowSensors();
2022-12-17 11:43:51 -08:00
#endif // EFI_SHAFT_POSITION_INPUT
2015-07-10 06:01:56 -07:00
}
bool getClutchDownState() {
2021-12-15 16:20:07 -08:00
#if EFI_GPIO_HARDWARE
if (isBrainPinValid(engineConfiguration->clutchDownPin)) {
return engineConfiguration->clutchDownPinInverted ^ efiReadPin(engineConfiguration->clutchDownPin);
}
#endif // EFI_GPIO_HARDWARE
// todo: boolean sensors should leverage sensor framework #6342
return engine->engineState.lua.clutchDownState;
}
static bool getClutchUpState() {
#if EFI_GPIO_HARDWARE
2021-12-15 14:48:21 -08:00
if (isBrainPinValid(engineConfiguration->clutchUpPin)) {
return engineConfiguration->clutchUpPinInverted ^ efiReadPin(engineConfiguration->clutchUpPin);
}
#endif // EFI_GPIO_HARDWARE
// todo: boolean sensors should leverage sensor framework #6342
return engine->engineState.lua.clutchUpState;
2021-12-15 14:48:21 -08:00
}
bool getBrakePedalState() {
#if EFI_GPIO_HARDWARE
if (isBrainPinValid(engineConfiguration->brakePedalPin)) {
return engineConfiguration->brakePedalPinInverted ^ efiReadPin(engineConfiguration->brakePedalPin);
2021-12-15 14:48:21 -08:00
}
#endif // EFI_GPIO_HARDWARE
// todo: boolean sensors should leverage sensor framework #6342
return engine->engineState.lua.brakePedalState;
2021-12-15 14:48:21 -08:00
}
2021-12-15 14:48:21 -08:00
void Engine::updateSwitchInputs() {
2020-12-26 18:31:41 -08:00
// this value is not used yet
engine->engineState.clutchDownState = getClutchDownState();
engine->clutchUpSwitchedState.update(getClutchUpState());
engine->brakePedalSwitchedState.update(getBrakePedalState());
#if EFI_GPIO_HARDWARE
2022-07-07 21:51:53 -07:00
{
bool currentState;
if (hasAcToggle()) {
currentState = getAcToggle();
2023-03-12 09:01:51 -07:00
#ifdef EFI_KLINE
} else if (engineConfiguration->hondaK) {
extern bool kAcRequestState;
currentState = kAcRequestState;
#endif // EFI_KLINE
2022-07-07 21:51:53 -07:00
} else {
currentState = engine->engineState.lua.acRequestState;
}
AcController & acController = engine->module<AcController>().unmock();
if (engine->acButtonSwitchedState.update(currentState)) {
2024-09-12 23:52:10 -07:00
acController.timeSinceStateChange.reset();
2020-12-26 18:31:41 -08:00
}
}
2021-12-15 14:48:21 -08:00
#if EFI_IDLE_CONTROL
if (isBrainPinValid(engineConfiguration->throttlePedalUpPin)) {
engine->module<IdleController>().unmock().throttlePedalUpState = efiReadPin(engineConfiguration->throttlePedalUpPin);
2020-12-26 18:31:41 -08:00
}
#endif // EFI_IDLE_CONTROL
2020-12-26 18:31:41 -08:00
pokeAuxDigital();
2021-12-15 14:48:21 -08:00
2020-12-26 18:31:41 -08:00
#endif // EFI_GPIO_HARDWARE
}
2023-05-25 09:41:11 -07:00
Engine::Engine()
: clutchUpSwitchedState(&engineState.clutchUpState),
brakePedalSwitchedState(&engineState.brakePedalState),
acButtonSwitchedState(&module<AcController>().unmock().acButtonState)
2023-05-25 09:41:11 -07:00
#if EFI_LAUNCH_CONTROL
, softSparkLimiter(false), hardSparkLimiter(true)
2023-05-25 09:41:11 -07:00
#if EFI_ANTILAG_SYSTEM
// , ALSsoftSparkLimiter(false)
2023-05-25 09:41:11 -07:00
#endif /* EFI_ANTILAG_SYSTEM */
#endif // EFI_LAUNCH_CONTROL
{
2016-12-18 07:02:38 -08:00
reset();
}
int Engine::getGlobalConfigurationVersion(void) const {
return globalConfigurationVersion;
}
2016-12-18 07:02:38 -08:00
void Engine::reset() {
2016-01-14 21:01:42 -08:00
/**
2023-10-19 14:34:29 -07:00
* it's important for wrapAngle() that engineCycle field never has zero
2016-01-14 21:01:42 -08:00
*/
engineState.engineCycle = getEngineCycle(FOUR_STROKE_CRANK_SENSOR);
2022-07-14 09:36:55 -07:00
resetLua();
2015-07-10 06:01:56 -07:00
}
2022-07-14 09:36:55 -07:00
void Engine::resetLua() {
// todo: https://github.com/rusefi/rusefi/issues/4308
engineState.lua = {};
engineState.lua.fuelAdd = 0;
2022-07-14 09:36:55 -07:00
engineState.lua.fuelMult = 1;
engineState.lua.luaDisableEtb = false;
engineState.lua.luaIgnCut = false;
2024-07-25 05:27:40 -07:00
engineState.lua.luaFuelCut = false;
2024-07-03 17:48:49 -07:00
engineState.lua.disableDecelerationFuelCutOff = false;
#if EFI_BOOST_CONTROL
module<BoostController>().unmock().resetLua();
#endif // EFI_BOOST_CONTROL
2022-07-14 09:36:55 -07:00
ignitionState.luaTimingAdd = 0;
ignitionState.luaTimingMult = 1;
#if EFI_IDLE_CONTROL
module<IdleController>().unmock().luaAdd = 0;
#endif // EFI_IDLE_CONTROL
2022-07-14 09:36:55 -07:00
}
2016-01-01 14:02:49 -08:00
2015-07-10 06:01:56 -07:00
/**
* Here we have a bunch of stuff which should invoked after configuration change
* so that we can prepare some helper structures
*/
void Engine::preCalculate() {
2020-05-09 19:43:39 -07:00
#if EFI_TUNER_STUDIO
// we take 2 bytes of crc32, no idea if it's right to call it crc16 or not
2020-05-09 21:59:32 -07:00
// we have a hack here - we rely on the fact that engineMake is the first of three relevant fields
engine->outputChannels.engineMakeCodeNameCrc16 = crc32(engineConfiguration->engineMake, 3 * VEHICLE_INFO_SIZE);
2020-06-04 21:43:05 -07:00
// we need and can empty warning message for CRC purposes
2023-03-16 12:53:01 -07:00
memset(config->warning_message, 0, sizeof(config->warning_message));
engine->outputChannels.tuneCrc16 = crc32(config, sizeof(persistent_config_s));
2020-05-09 19:43:39 -07:00
#endif /* EFI_TUNER_STUDIO */
2015-07-10 06:01:56 -07:00
}
#if EFI_SHAFT_POSITION_INPUT
void Engine::OnTriggerStateProperState(efitick_t nowNt) {
rpmCalculator.setSpinningUp(nowNt);
}
2020-01-26 09:02:54 -08:00
void Engine::OnTriggerSynchronizationLost() {
// Needed for early instant-RPM detection
rpmCalculator.setStopSpinning();
2022-11-05 21:32:38 -07:00
triggerCentral.triggerState.resetState();
triggerCentral.instantRpm.resetInstantRpm();
for (size_t i = 0; i < efi::size(triggerCentral.vvtState); i++) {
for (size_t j = 0; j < efi::size(triggerCentral.vvtState[0]); j++) {
2022-11-05 21:32:38 -07:00
triggerCentral.vvtState[i][j].resetState();
}
}
2020-01-26 09:02:54 -08:00
}
2023-09-09 16:51:09 -07:00
void Engine::OnTriggerSynchronization(bool wasSynchronized, bool isDecodingError) {
// TODO: this logic probably shouldn't be part of engine.cpp
2020-01-26 00:33:45 -08:00
2020-01-23 10:39:50 -08:00
// We only care about trigger shape once we have synchronized trigger. Anything could happen
// during first revolution and it's fine
if (wasSynchronized) {
enginePins.triggerDecoderErrorPin.setValue(isDecodingError);
// 'triggerStateListener is not null' means we are running a real engine and now just preparing trigger shape
// that's a bit of a hack, a sweet OOP solution would be a real callback or at least 'needDecodingErrorLogic' method?
if (isDecodingError) {
#if EFI_PROD_CODE
if (engineConfiguration->verboseTriggerSynchDetails || (triggerCentral.triggerState.someSortOfTriggerError() && !engineConfiguration->silentTriggerError)) {
efiPrintf("error: synchronizationPoint @ index %lu expected %d/%d got %d/%d",
triggerCentral.triggerState.currentCycle.current_index,
2022-11-06 17:47:57 -08:00
triggerCentral.triggerShape.getExpectedEventCount(TriggerWheel::T_PRIMARY),
triggerCentral.triggerShape.getExpectedEventCount(TriggerWheel::T_SECONDARY),
triggerCentral.triggerState.currentCycle.eventCount[0],
triggerCentral.triggerState.currentCycle.eventCount[1]);
}
#endif /* EFI_PROD_CODE */
2020-01-23 10:39:50 -08:00
}
engine->triggerCentral.triggerErrorDetection.add(isDecodingError);
2020-01-23 10:39:50 -08:00
}
2020-01-22 10:25:35 -08:00
}
#endif
void Engine::injectEngineReferences() {
2022-12-17 11:43:51 -08:00
#if EFI_SHAFT_POSITION_INPUT
triggerCentral.primaryTriggerConfiguration.update();
2021-02-08 19:21:02 -08:00
for (int camIndex = 0;camIndex < CAMS_PER_BANK;camIndex++) {
triggerCentral.vvtTriggerConfiguration[camIndex].update();
2021-02-08 19:21:02 -08:00
}
2022-12-17 11:43:51 -08:00
#endif // EFI_SHAFT_POSITION_INPUT
}
void Engine::setConfig() {
#if !EFI_UNIT_TEST
// huh should this be happy? static_assert(config != nullptr);
#endif
efi::clear(config);
injectEngineReferences();
2015-07-10 06:01:56 -07:00
}
2023-11-17 12:20:40 -08:00
/**
* This code asserts that we do not have unexpected gaps in time flow with the exception of internal flash burn.
*/
static void assertTimeIsLinear() {
static efitimems_t mostRecentMs = 0;
efitimems_t msNow = getTimeNowMs();
if (engineConfiguration->watchOutForLinearTime && engine->configBurnTimer.hasElapsedSec(5)) {
if (mostRecentMs != 0) {
efitimems_t gapInMs = msNow - mostRecentMs;
2023-11-17 13:43:53 -08:00
// todo: lower gapInMs threshold?
if (gapInMs > 200) {
firmwareError(ObdCode::WATCH_DOG_SECONDS, "gap in time: mostRecentMs %lumS, now=%lumS, gap=%lumS",
2023-11-20 08:57:42 -08:00
mostRecentMs, msNow, gapInMs);
}
}
}
mostRecentMs = msNow;
2023-11-17 12:20:40 -08:00
}
void Engine::efiWatchdog() {
2023-11-17 12:33:06 -08:00
assertTimeIsLinear();
2023-11-17 12:20:40 -08:00
if (isRunningPwmTest)
return;
2023-11-17 12:46:28 -08:00
#if EFI_ENGINE_CONTROL && EFI_SHAFT_POSITION_INPUT
if (module<PrimeController>()->isPriming() || triggerCentral.engineMovedRecently()) {
// do not invoke check in priming or if engine moved recently, no need to assert safe pin state.
2023-11-17 12:20:40 -08:00
return;
}
2023-11-17 12:58:08 -08:00
if (!triggerCentral.isSpinningJustForWatchdog) {
2016-11-03 20:02:58 -07:00
if (!isRunningBenchTest() && enginePins.stopPins()) {
2016-11-04 19:02:42 -07:00
// todo: make this a firmwareError assuming functional tests would run
warning(ObdCode::CUSTOM_ERR_2ND_WATCHDOG, "Some pins were turned off by 2nd pass watchdog");
2015-07-10 06:01:56 -07:00
}
return;
}
2015-07-10 06:01:56 -07:00
/**
* todo: better watch dog implementation should be implemented - see
* http://sourceforge.net/p/rusefi/tickets/96/
*/
2023-11-17 12:58:08 -08:00
triggerCentral.isSpinningJustForWatchdog = false;
onEngineHasStopped();
#endif // EFI_ENGINE_CONTROL && EFI_SHAFT_POSITION_INPUT
}
void Engine::onEngineHasStopped() {
#if EFI_ENGINE_CONTROL
2016-12-18 07:02:38 -08:00
ignitionEvents.isReady = false;
2023-11-17 12:58:08 -08:00
#endif // EFI_ENGINE_CONTROL
2019-04-12 19:07:03 -07:00
#if EFI_PROD_CODE || EFI_SIMULATOR
2023-11-17 12:42:32 -08:00
efiPrintf("Engine has stopped spinning.");
2015-07-10 06:01:56 -07:00
#endif
2023-11-17 12:58:08 -08:00
// this invocation should be the last layer of defence in terms of making sure injectors/coils are not active
2016-11-03 20:02:58 -07:00
enginePins.stopPins();
2015-07-10 06:01:56 -07:00
}
void Engine::checkShutdown() {
2019-04-12 19:07:03 -07:00
#if EFI_MAIN_RELAY_CONTROL
// if we are already in the "ignition_on" mode, then do nothing
2022-09-28 19:42:08 -07:00
/* this logic is not alive
if (ignitionOnTimeNt > 0) {
return;
}
2022-09-28 19:42:08 -07:00
todo: move to shutdown_controller.cpp
*/
// here we are in the shutdown (the ignition is off) or initial mode (after the firmware fresh start)
2023-11-02 10:02:33 -07:00
/* this needs work or tests
const efitick_t engineStopWaitTimeoutUs = 500000LL; // 0.5 sec
// in shutdown mode, we need a small cooldown time between the ignition off and on
2022-09-28 19:42:08 -07:00
todo: move to shutdown_controller.cpp
if (stopEngineRequestTimeNt == 0 || (getTimeNowNt() - stopEngineRequestTimeNt) > US2NT(engineStopWaitTimeoutUs)) {
// if the ignition key is turned on again,
// we cancel the shutdown mode, but only if all shutdown procedures are complete
const float vBattThresholdOn = 8.0f;
2021-12-01 08:22:13 -08:00
// we fallback into zero instead of VBAT_FALLBACK_VALUE because it's not safe to false-trigger the "ignition on" event,
// and we want to turn on the main relay only when 100% sure.
2022-12-14 16:48:07 -08:00
if ((Sensor::getOrZero(SensorType::BatteryVoltage) > vBattThresholdOn) && !isInShutdownMode()) {
ignitionOnTimeNt = getTimeNowNt();
efiPrintf("Ignition voltage detected!");
if (stopEngineRequestTimeNt != 0) {
efiPrintf("Cancel the engine shutdown!");
stopEngineRequestTimeNt = 0;
}
}
}
*/
#endif /* EFI_MAIN_RELAY_CONTROL */
}
bool Engine::isInShutdownMode() const {
// TODO: this logic is currently broken
#if 0 && EFI_MAIN_RELAY_CONTROL && EFI_PROD_CODE
// if we are in "ignition_on" mode and not in shutdown mode
if (stopEngineRequestTimeNt == 0 && ignitionOnTimeNt > 0) {
const float vBattThresholdOff = 5.0f;
// start the shutdown process if the ignition voltage dropped low
2021-03-11 19:52:34 -08:00
if (Sensor::get(SensorType::BatteryVoltage).value_or(VBAT_FALLBACK_VALUE) <= vBattThresholdOff) {
scheduleStopEngine();
}
}
// we are not in the shutdown mode?
if (stopEngineRequestTimeNt == 0) {
return false;
}
2021-01-10 20:46:50 -08:00
const efitick_t turnOffWaitTimeoutNt = NT_PER_SECOND;
// We don't want any transients to step in, so we wait at least 1 second whatever happens.
// Also it's good to give the stepper motor some time to start moving to the initial position (or parking)
2021-01-10 20:46:50 -08:00
if ((getTimeNowNt() - stopEngineRequestTimeNt) < turnOffWaitTimeoutNt)
return true;
2021-01-10 20:46:50 -08:00
const efitick_t engineSpinningWaitTimeoutNt = 5 * NT_PER_SECOND;
// The engine is still spinning! Give it some time to stop (but wait no more than 5 secs)
2021-01-10 20:46:50 -08:00
if (isSpinning && (getTimeNowNt() - stopEngineRequestTimeNt) < engineSpinningWaitTimeoutNt)
return true;
// The idle motor valve is still moving! Give it some time to park (but wait no more than 10 secs)
// Usually it can move to the initial 'cranking' position or zero 'parking' position.
2021-01-10 20:46:50 -08:00
const efitick_t idleMotorWaitTimeoutNt = 10 * NT_PER_SECOND;
if (isIdleMotorBusy() && (getTimeNowNt() - stopEngineRequestTimeNt) < idleMotorWaitTimeoutNt)
return true;
#endif /* EFI_MAIN_RELAY_CONTROL */
return false;
}
bool Engine::isMainRelayEnabled() const {
#if EFI_MAIN_RELAY_CONTROL
return enginePins.mainRelay.getLogicValue();
#else
// if no main relay control, we assume it's always turned on
return true;
#endif /* EFI_MAIN_RELAY_CONTROL */
}
injection_mode_e getCurrentInjectionMode() {
return getEngineRotationState()->isCranking() ? engineConfiguration->crankingInjectionMode : engineConfiguration->injectionMode;
2016-11-30 19:06:43 -08:00
}
2015-07-10 06:01:56 -07:00
/**
* The idea of this method is to execute all heavy calculations in a lower-priority thread,
2016-01-01 14:02:49 -08:00
* so that trigger event handler/IO scheduler tasks are faster.
2015-07-10 06:01:56 -07:00
*/
void Engine::periodicFastCallback() {
2019-10-11 17:43:21 -07:00
ScopePerf pc(PE::EnginePeriodicFastCallback);
2016-01-01 14:02:49 -08:00
#if EFI_MAP_AVERAGING
refreshMapAveragingPreCalc();
#endif
2016-01-01 14:02:49 -08:00
engineState.periodicFastCallback();
2023-10-15 14:59:39 -07:00
tachUpdate();
speedoUpdate();
2024-08-07 20:14:23 -07:00
engineModules.apply_all([](auto & m) { m.onFastCallback(); });
2015-07-10 06:01:56 -07:00
}
EngineRotationState * getEngineRotationState() {
return &engine->rpmCalculator;
}
EngineState * getEngineState() {
return &engine->engineState;
}
2022-09-07 16:35:52 -07:00
TunerStudioOutputChannels *getTunerStudioOutputChannels() {
return &engine->outputChannels;
}
2024-07-11 17:03:13 -07:00
Scheduler *getScheduler() {
return &engine->scheduler;
}
2022-12-17 11:43:51 -08:00
#if EFI_SHAFT_POSITION_INPUT
TriggerCentral * getTriggerCentral() {
return &engine->triggerCentral;
}
2022-12-17 11:43:51 -08:00
#endif // EFI_SHAFT_POSITION_INPUT
#if EFI_ENGINE_CONTROL
LimpManager * getLimpManager() {
return &engine->module<LimpManager>().unmock();
}
FuelSchedule *getFuelSchedule() {
return &engine->injectionEvents;
}
IgnitionEventList *getIgnitionEvents() {
return &engine->ignitionEvents;
}
2022-12-17 11:43:51 -08:00
#endif // EFI_ENGINE_CONTROL