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
|
2019-01-04 21:32:56 -08:00
|
|
|
* @author Andrey Belomutskiy, (c) 2012-2019
|
2015-07-10 06:01:56 -07:00
|
|
|
*/
|
|
|
|
|
2018-09-16 19:26:57 -07:00
|
|
|
#include "global.h"
|
2015-07-10 06:01:56 -07:00
|
|
|
#include "engine.h"
|
2019-05-27 15:58:43 -07:00
|
|
|
#include "allsensors.h"
|
2019-03-29 06:11:13 -07:00
|
|
|
#include "efi_gpio.h"
|
2015-07-10 06:01:56 -07:00
|
|
|
#include "trigger_central.h"
|
|
|
|
#include "fuel_math.h"
|
|
|
|
#include "engine_math.h"
|
|
|
|
#include "advance_map.h"
|
|
|
|
#include "speed_density.h"
|
2016-01-01 16:02:59 -08:00
|
|
|
#include "advance_map.h"
|
2019-07-06 17:15:49 -07:00
|
|
|
#include "os_util.h"
|
2017-06-24 22:35:46 -07:00
|
|
|
#include "settings.h"
|
2017-11-26 19:30:37 -08:00
|
|
|
#include "aux_valves.h"
|
2018-02-06 12:47:19 -08:00
|
|
|
#include "map_averaging.h"
|
2019-01-14 07:58:38 -08:00
|
|
|
#include "fsio_impl.h"
|
2019-10-11 17:43:21 -07:00
|
|
|
#include "perf_trace.h"
|
2015-07-10 06:01:56 -07:00
|
|
|
|
2019-04-12 19:07:03 -07:00
|
|
|
#if EFI_PROD_CODE
|
2015-07-10 06:01:56 -07:00
|
|
|
#include "injector_central.h"
|
|
|
|
#else
|
|
|
|
#define isRunningBenchTest() true
|
2016-01-23 15:01:40 -08:00
|
|
|
#endif /* EFI_PROD_CODE */
|
2015-07-10 06:01:56 -07:00
|
|
|
|
2019-09-06 17:30:27 -07:00
|
|
|
#if (BOARD_TLE8888_COUNT > 0)
|
|
|
|
#include "gpio/tle8888.h"
|
|
|
|
#endif
|
|
|
|
|
2018-12-25 18:18:14 -08:00
|
|
|
static TriggerState initState CCM_OPTIONAL;
|
|
|
|
|
2019-01-04 21:32:56 -08:00
|
|
|
LoggingWithStorage engineLogger("engine");
|
2016-01-01 16:02:59 -08:00
|
|
|
|
2015-07-10 06:01:56 -07:00
|
|
|
EXTERN_ENGINE
|
|
|
|
;
|
|
|
|
|
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 */
|
|
|
|
|
2019-01-05 20:48:37 -08:00
|
|
|
FsioState::FsioState() {
|
|
|
|
#if EFI_ENABLE_ENGINE_WARNING
|
|
|
|
isEngineWarning = FALSE;
|
|
|
|
#endif
|
|
|
|
#if EFI_ENABLE_CRITICAL_ENGINE_STOP
|
|
|
|
isCriticalEngineCondition = FALSE;
|
|
|
|
#endif
|
|
|
|
}
|
2016-01-23 15:01:40 -08:00
|
|
|
|
2019-12-21 17:43:11 -08:00
|
|
|
void Engine::resetEngineSnifferIfInTestMode() {
|
|
|
|
#if EFI_ENGINE_SNIFFER
|
|
|
|
if (isTestMode) {
|
|
|
|
waveChart.reset();
|
|
|
|
}
|
|
|
|
#endif /* EFI_ENGINE_SNIFFER */
|
|
|
|
}
|
|
|
|
|
2019-12-07 22:09:39 -08:00
|
|
|
void Engine::initializeTriggerWaveform(Logging *logger DECLARE_ENGINE_PARAMETER_SUFFIX) {
|
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
|
|
|
|
bool alreadyLocked = lockAnyContext();
|
|
|
|
|
2019-12-07 22:09:39 -08:00
|
|
|
TRIGGER_WAVEFORM(initializeTriggerWaveform(logger,
|
2019-08-07 21:32:31 -07:00
|
|
|
engineConfiguration->ambiguousOperationMode,
|
2018-12-25 19:47:29 -08:00
|
|
|
engineConfiguration->useOnlyRisingEdgeForTrigger, &engineConfiguration->trigger));
|
2018-12-25 18:18:14 -08:00
|
|
|
|
2019-12-07 22:09:39 -08:00
|
|
|
if (TRIGGER_WAVEFORM(bothFrontsRequired) && engineConfiguration->useOnlyRisingEdgeForTrigger) {
|
2019-08-08 19:57:22 -07:00
|
|
|
#if EFI_PROD_CODE || EFI_SIMULATOR
|
|
|
|
firmwareError(CUSTOM_ERR_BOTH_FRONTS_REQUIRED, "Inconsistent trigger setup");
|
|
|
|
#else
|
|
|
|
warning(CUSTOM_ERR_BOTH_FRONTS_REQUIRED, "Inconsistent trigger setup");
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-12-07 22:09:39 -08:00
|
|
|
if (!TRIGGER_WAVEFORM(shapeDefinitionError)) {
|
2018-12-25 18:18:14 -08:00
|
|
|
/**
|
2019-12-07 22:09:39 -08:00
|
|
|
* this instance is used only to initialize 'this' TriggerWaveform instance
|
2018-12-25 18:18:14 -08:00
|
|
|
* #192 BUG real hardware trigger events could be coming even while we are initializing trigger
|
|
|
|
*/
|
2019-01-22 16:07:36 -08:00
|
|
|
initState.resetTriggerState();
|
2018-12-25 19:47:29 -08:00
|
|
|
calculateTriggerSynchPoint(&ENGINE(triggerCentral.triggerShape),
|
|
|
|
&initState PASS_ENGINE_PARAMETER_SUFFIX);
|
2018-12-25 18:18:14 -08:00
|
|
|
|
|
|
|
if (engine->triggerCentral.triggerShape.getSize() == 0) {
|
|
|
|
firmwareError(CUSTOM_ERR_TRIGGER_ZERO, "triggerShape size is zero");
|
|
|
|
}
|
2019-12-07 22:09:39 -08:00
|
|
|
engine->engineCycleEventCount = TRIGGER_WAVEFORM(getLength());
|
2018-12-25 18:18:14 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!alreadyLocked) {
|
|
|
|
unlockAnyContext();
|
|
|
|
}
|
|
|
|
|
2019-12-07 22:09:39 -08:00
|
|
|
if (!TRIGGER_WAVEFORM(shapeDefinitionError)) {
|
2018-12-25 18:18:14 -08:00
|
|
|
prepareOutputSignals(PASS_ENGINE_PARAMETER_SIGNATURE);
|
|
|
|
}
|
2019-01-31 14:55:23 -08:00
|
|
|
#endif /* EFI_ENGINE_CONTROL && EFI_SHAFT_POSITION_INPUT */
|
2019-01-14 07:58:38 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void cylinderCleanupControl(DECLARE_ENGINE_PARAMETER_SIGNATURE) {
|
2019-04-12 19:07:03 -07:00
|
|
|
#if EFI_ENGINE_CONTROL
|
2019-01-14 07:58:38 -08:00
|
|
|
bool newValue;
|
|
|
|
if (engineConfiguration->isCylinderCleanupEnabled) {
|
|
|
|
newValue = !engine->rpmCalculator.isRunning(PASS_ENGINE_PARAMETER_SIGNATURE) && getTPS(PASS_ENGINE_PARAMETER_SIGNATURE) > CLEANUP_MODE_TPS;
|
|
|
|
} else {
|
|
|
|
newValue = false;
|
|
|
|
}
|
|
|
|
if (newValue != engine->isCylinderCleanupMode) {
|
|
|
|
engine->isCylinderCleanupMode = newValue;
|
|
|
|
scheduleMsg(&engineLogger, "isCylinderCleanupMode %s", boolToString(newValue));
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2019-09-06 17:30:27 -07:00
|
|
|
static efitick_t tle8888CrankingResetTime = 0;
|
|
|
|
|
2019-01-14 07:58:38 -08:00
|
|
|
void Engine::periodicSlowCallback(DECLARE_ENGINE_PARAMETER_SIGNATURE) {
|
2019-10-11 17:43:21 -07:00
|
|
|
ScopePerf perf(PE::EnginePeriodicSlowCallback);
|
|
|
|
|
2019-01-14 07:58:38 -08:00
|
|
|
watchdog();
|
|
|
|
updateSlowSensors(PASS_ENGINE_PARAMETER_SIGNATURE);
|
|
|
|
checkShutdown();
|
|
|
|
|
2019-04-12 19:07:03 -07:00
|
|
|
#if EFI_FSIO
|
2019-01-14 07:58:38 -08:00
|
|
|
runFsio(PASS_ENGINE_PARAMETER_SIGNATURE);
|
2019-11-25 17:08:01 -08:00
|
|
|
#else
|
|
|
|
runHardcodedFsio(PASS_ENGINE_PARAMETER_SIGNATURE);
|
|
|
|
#endif /* EFI_FSIO */
|
2018-12-25 18:18:14 -08:00
|
|
|
|
2019-01-14 07:58:38 -08:00
|
|
|
cylinderCleanupControl(PASS_ENGINE_PARAMETER_SIGNATURE);
|
|
|
|
|
2019-09-06 17:30:27 -07:00
|
|
|
#if (BOARD_TLE8888_COUNT > 0)
|
|
|
|
if (CONFIG(useTLE8888_cranking_hack) && ENGINE(rpmCalculator).isCranking(PASS_ENGINE_PARAMETER_SIGNATURE)) {
|
|
|
|
efitick_t nowNt = getTimeNowNt();
|
|
|
|
if (nowNt - tle8888CrankingResetTime > US2NT(MS2US(300))) {
|
|
|
|
requestTLE8888initialization();
|
|
|
|
// let's reset TLE8888 every 300ms while cranking since that's the best we can do to deal with undervoltage reset
|
|
|
|
// PS: oh yes, it's a horrible design! Please suggest something better!
|
|
|
|
tle8888CrankingResetTime = nowNt;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2019-01-14 07:58:38 -08:00
|
|
|
slowCallBackWasInvoked = TRUE;
|
2018-12-25 18:18:14 -08:00
|
|
|
}
|
|
|
|
|
2019-01-14 07:58:38 -08:00
|
|
|
|
2019-08-16 20:00:28 -07:00
|
|
|
#if (BOARD_TLE8888_COUNT > 0)
|
|
|
|
extern float vBattForTle8888;
|
|
|
|
#endif /* BOARD_TLE8888_COUNT */
|
|
|
|
|
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
|
|
|
*/
|
2017-05-15 20:28:49 -07:00
|
|
|
void Engine::updateSlowSensors(DECLARE_ENGINE_PARAMETER_SIGNATURE) {
|
2019-04-12 19:07:03 -07:00
|
|
|
#if EFI_ENGINE_CONTROL
|
2019-01-21 18:48:58 -08:00
|
|
|
int rpm = GET_RPM();
|
2016-01-30 19:03:36 -08:00
|
|
|
isEngineChartEnabled = CONFIG(isEngineChartEnabled) && rpm < CONFIG(engineSnifferRpmThreshold);
|
2019-12-11 14:48:55 -08:00
|
|
|
sensorChartMode = rpm < CONFIG(sensorSnifferRpmThreshold) ? CONFIG(sensorChartMode) : SC_OFF;
|
2016-01-30 19:03:36 -08:00
|
|
|
|
2017-05-15 20:28:49 -07:00
|
|
|
engineState.updateSlowSensors(PASS_ENGINE_PARAMETER_SIGNATURE);
|
2015-07-10 06:01:56 -07:00
|
|
|
|
2017-11-24 16:16:00 -08:00
|
|
|
// todo: move this logic somewhere to sensors folder?
|
2019-01-04 21:57:09 -08:00
|
|
|
if (CONFIG(fuelLevelSensor) != EFI_ADC_NONE) {
|
2019-09-22 06:56:06 -07:00
|
|
|
float fuelLevelVoltage = getVoltageDivided("fuel", engineConfiguration->fuelLevelSensor PASS_ENGINE_PARAMETER_SUFFIX);
|
2019-12-11 14:48:55 -08:00
|
|
|
sensors.fuelTankLevel = interpolateMsg("fgauge", CONFIG(fuelLevelEmptyTankVoltage), 0,
|
|
|
|
CONFIG(fuelLevelFullTankVoltage), 100,
|
2015-07-10 06:01:56 -07:00
|
|
|
fuelLevelVoltage);
|
|
|
|
}
|
2017-05-15 20:28:49 -07:00
|
|
|
sensors.vBatt = hasVBatt(PASS_ENGINE_PARAMETER_SIGNATURE) ? getVBatt(PASS_ENGINE_PARAMETER_SIGNATURE) : 12;
|
2015-07-10 06:01:56 -07:00
|
|
|
|
2019-08-16 20:00:28 -07:00
|
|
|
#if (BOARD_TLE8888_COUNT > 0)
|
|
|
|
// nasty value injection into C driver which would not be able to access Engine class
|
|
|
|
vBattForTle8888 = sensors.vBatt;
|
|
|
|
#endif /* BOARD_TLE8888_COUNT */
|
|
|
|
|
2019-08-26 20:41:04 -07:00
|
|
|
engineState.running.injectorLag = getInjectorLag(sensors.vBatt PASS_ENGINE_PARAMETER_SUFFIX);
|
2019-01-31 08:57:15 -08:00
|
|
|
#endif
|
2015-07-10 06:01:56 -07:00
|
|
|
}
|
|
|
|
|
2017-11-20 12:01:48 -08:00
|
|
|
void Engine::onTriggerSignalEvent(efitick_t nowNt) {
|
2015-07-10 06:01:56 -07:00
|
|
|
isSpinning = true;
|
2017-11-20 12:01:48 -08:00
|
|
|
lastTriggerToothEventTimeNt = nowNt;
|
2015-07-10 06:01:56 -07:00
|
|
|
}
|
|
|
|
|
2016-12-18 07:02:38 -08:00
|
|
|
Engine::Engine() {
|
|
|
|
reset();
|
|
|
|
}
|
|
|
|
|
2015-07-10 06:01:56 -07:00
|
|
|
Engine::Engine(persistent_config_s *config) {
|
2016-12-18 07:02:38 -08:00
|
|
|
setConfig(config);
|
|
|
|
reset();
|
|
|
|
}
|
|
|
|
|
2019-01-05 20:33:04 -08:00
|
|
|
/**
|
|
|
|
* @see scheduleStopEngine()
|
|
|
|
* @return true if there is a reason to stop engine
|
|
|
|
*/
|
2019-06-08 06:51:36 -07:00
|
|
|
bool Engine::needToStopEngine(efitick_t nowNt) const {
|
2019-01-05 20:33:04 -08:00
|
|
|
return stopEngineRequestTimeNt != 0 &&
|
|
|
|
nowNt - stopEngineRequestTimeNt < 3 * US2NT(US_PER_SECOND_LL);
|
|
|
|
}
|
|
|
|
|
2019-01-15 18:51:09 -08:00
|
|
|
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
|
|
|
/**
|
|
|
|
* it's important for fixAngle() that engineCycle field never has zero
|
|
|
|
*/
|
|
|
|
engineCycle = getEngineCycle(FOUR_STROKE_CRANK_SENSOR);
|
2015-07-10 06:01:56 -07:00
|
|
|
memset(&ignitionPin, 0, sizeof(ignitionPin));
|
|
|
|
|
|
|
|
memset(&m, 0, sizeof(m));
|
|
|
|
}
|
|
|
|
|
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
|
|
|
|
*/
|
2019-01-04 21:57:09 -08:00
|
|
|
void Engine::preCalculate(DECLARE_ENGINE_PARAMETER_SIGNATURE) {
|
2019-01-31 08:57:15 -08:00
|
|
|
#if HAL_USE_ADC
|
2019-01-04 21:57:09 -08:00
|
|
|
adcToVoltageInputDividerCoefficient = adcToVolts(1) * engineConfiguration->analogInputDividerCoefficient;
|
2018-11-03 06:44:34 -07:00
|
|
|
#else
|
2019-01-04 21:11:17 -08:00
|
|
|
adcToVoltageInputDividerCoefficient = engineConfigurationPtr->analogInputDividerCoefficient;
|
2018-11-03 06:44:34 -07:00
|
|
|
#endif
|
2015-07-10 06:01:56 -07:00
|
|
|
}
|
|
|
|
|
2019-12-05 22:57:11 -08:00
|
|
|
void Engine::OnTriggerStateDecodingError() {
|
|
|
|
Engine *engine = this;
|
|
|
|
EXPAND_Engine;
|
|
|
|
triggerCentral.triggerState.handleTriggerError(PASS_ENGINE_PARAMETER_SIGNATURE);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Engine::OnTriggerStateProperState(efitick_t nowNt) {
|
|
|
|
Engine *engine = this;
|
|
|
|
EXPAND_Engine;
|
|
|
|
rpmCalculator.setSpinningUp(nowNt PASS_ENGINE_PARAMETER_SUFFIX);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-12-18 07:02:38 -08:00
|
|
|
void Engine::setConfig(persistent_config_s *config) {
|
2016-01-25 00:02:33 -08:00
|
|
|
this->config = config;
|
2019-01-04 21:11:17 -08:00
|
|
|
engineConfigurationPtr = &config->engineConfiguration;
|
2016-01-25 00:02:33 -08:00
|
|
|
memset(config, 0, sizeof(persistent_config_s));
|
2015-07-10 06:01:56 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void Engine::printKnockState(void) {
|
2019-01-04 21:32:56 -08:00
|
|
|
scheduleMsg(&engineLogger, "knock now=%s/ever=%s", boolToString(knockNow), boolToString(knockEver));
|
2015-07-10 06:01:56 -07:00
|
|
|
}
|
|
|
|
|
2019-01-04 21:57:09 -08:00
|
|
|
void Engine::knockLogic(float knockVolts DECLARE_ENGINE_PARAMETER_SUFFIX) {
|
2015-07-11 13:01:31 -07:00
|
|
|
this->knockVolts = knockVolts;
|
2019-01-04 21:57:09 -08:00
|
|
|
knockNow = knockVolts > engineConfiguration->knockVThreshold;
|
2015-07-10 06:01:56 -07:00
|
|
|
/**
|
|
|
|
* KnockCount is directly proportional to the degrees of ignition
|
|
|
|
* advance removed
|
|
|
|
* ex: degrees to subtract = knockCount;
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* TODO use knockLevel as a factor for amount of ignition advance
|
|
|
|
* to remove
|
|
|
|
* Perhaps allow the user to set a multiplier
|
|
|
|
* ex: degrees to subtract = knockCount + (knockLevel * X)
|
|
|
|
* X = user configurable multiplier
|
|
|
|
*/
|
|
|
|
if (knockNow) {
|
|
|
|
knockEver = true;
|
|
|
|
timeOfLastKnockEvent = getTimeNowUs();
|
2019-01-04 21:57:09 -08:00
|
|
|
if (knockCount < engineConfiguration->maxKnockSubDeg)
|
2015-07-10 06:01:56 -07:00
|
|
|
knockCount++;
|
|
|
|
} else if (knockCount >= 1) {
|
|
|
|
knockCount--;
|
|
|
|
} else {
|
|
|
|
knockCount = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Engine::watchdog() {
|
|
|
|
#if EFI_ENGINE_CONTROL
|
|
|
|
if (isRunningPwmTest)
|
|
|
|
return;
|
|
|
|
if (!isSpinning) {
|
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(CUSTOM_ERR_2ND_WATCHDOG, "Some pins were turned off by 2nd pass watchdog");
|
2015-07-10 06:01:56 -07:00
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
efitick_t nowNt = getTimeNowNt();
|
2017-11-20 12:01:48 -08:00
|
|
|
// note that we are ignoring the number of tooth here - we
|
|
|
|
// check for duration between tooth as if we only have one tooth per revolution which is not the case
|
2017-11-04 16:35:38 -07:00
|
|
|
#define REVOLUTION_TIME_HIGH_THRESHOLD (60 * 1000000LL / RPM_LOW_THRESHOLD)
|
2015-07-10 06:01:56 -07:00
|
|
|
/**
|
|
|
|
* todo: better watch dog implementation should be implemented - see
|
|
|
|
* http://sourceforge.net/p/rusefi/tickets/96/
|
|
|
|
*
|
|
|
|
* note that the result of this subtraction could be negative, that would happen if
|
|
|
|
* we have a trigger event between the time we've invoked 'getTimeNow' and here
|
|
|
|
*/
|
2017-11-20 12:01:48 -08:00
|
|
|
efitick_t timeSinceLastTriggerEvent = nowNt - lastTriggerToothEventTimeNt;
|
2017-11-04 16:35:38 -07:00
|
|
|
if (timeSinceLastTriggerEvent < US2NT(REVOLUTION_TIME_HIGH_THRESHOLD)) {
|
2015-07-10 06:01:56 -07:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
isSpinning = false;
|
2016-12-18 07:02:38 -08:00
|
|
|
ignitionEvents.isReady = false;
|
2019-04-12 19:07:03 -07:00
|
|
|
#if EFI_PROD_CODE || EFI_SIMULATOR
|
2019-01-04 21:32:56 -08:00
|
|
|
scheduleMsg(&engineLogger, "engine has STOPPED");
|
|
|
|
scheduleMsg(&engineLogger, "templog engine has STOPPED [%x][%x] [%x][%x] %d",
|
2015-07-10 06:01:56 -07:00
|
|
|
(int)(nowNt >> 32), (int)nowNt,
|
2017-11-20 12:01:48 -08:00
|
|
|
(int)(lastTriggerToothEventTimeNt >> 32), (int)lastTriggerToothEventTimeNt,
|
2015-07-10 06:01:56 -07:00
|
|
|
(int)timeSinceLastTriggerEvent
|
|
|
|
);
|
|
|
|
triggerInfo();
|
|
|
|
#endif
|
|
|
|
|
2016-11-03 20:02:58 -07:00
|
|
|
enginePins.stopPins();
|
2015-07-10 06:01:56 -07:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2017-06-24 22:35:46 -07:00
|
|
|
void Engine::checkShutdown() {
|
2019-04-12 19:07:03 -07:00
|
|
|
#if EFI_MAIN_RELAY_CONTROL
|
2018-03-22 10:37:34 -07:00
|
|
|
int rpm = rpmCalculator.getRpm();
|
2017-06-24 22:35:46 -07:00
|
|
|
|
2019-01-05 20:33:04 -08:00
|
|
|
/**
|
|
|
|
* Something is weird here: "below 5.0 volts on battery" what is it about? Is this about
|
|
|
|
* Frankenso powering everything while driver has already turned ignition off? or what is this condition about?
|
|
|
|
*/
|
2017-06-24 22:35:46 -07:00
|
|
|
const float vBattThreshold = 5.0f;
|
2017-07-01 14:29:56 -07:00
|
|
|
if (isValidRpm(rpm) && sensors.vBatt < vBattThreshold && stopEngineRequestTimeNt == 0) {
|
2019-01-05 20:33:04 -08:00
|
|
|
scheduleStopEngine();
|
2017-06-24 22:35:46 -07:00
|
|
|
// todo: add stepper motor parking
|
|
|
|
}
|
|
|
|
#endif /* EFI_MAIN_RELAY_CONTROL */
|
|
|
|
}
|
|
|
|
|
2019-06-08 06:51:36 -07:00
|
|
|
bool Engine::isInShutdownMode() const {
|
2019-04-12 19:07:03 -07:00
|
|
|
#if EFI_MAIN_RELAY_CONTROL
|
2017-06-24 22:35:46 -07:00
|
|
|
if (stopEngineRequestTimeNt == 0) // the shutdown procedure is not started
|
|
|
|
return false;
|
|
|
|
|
2019-12-21 18:11:09 -08:00
|
|
|
const efitick_t engineStopWaitTimeoutNt = 5LL * 1000000LL;
|
2017-06-24 22:35:46 -07:00
|
|
|
// The engine is still spinning! Give it some time to stop (but wait no more than 5 secs)
|
|
|
|
if (isSpinning && (getTimeNowNt() - stopEngineRequestTimeNt) < US2NT(engineStopWaitTimeoutNt))
|
|
|
|
return true;
|
|
|
|
// todo: add checks for stepper motor parking
|
|
|
|
#endif /* EFI_MAIN_RELAY_CONTROL */
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-05-15 20:28:49 -07:00
|
|
|
injection_mode_e Engine::getCurrentInjectionMode(DECLARE_ENGINE_PARAMETER_SIGNATURE) {
|
2017-07-06 05:49:55 -07:00
|
|
|
return rpmCalculator.isCranking(PASS_ENGINE_PARAMETER_SIGNATURE) ? CONFIG(crankingInjectionMode) : CONFIG(injectionMode);
|
2016-11-30 19:06:43 -08:00
|
|
|
}
|
|
|
|
|
2019-08-07 21:19:09 -07:00
|
|
|
// see also in TunerStudio project '[doesTriggerImplyOperationMode] tag
|
|
|
|
static bool doesTriggerImplyOperationMode(trigger_type_e type) {
|
2019-08-08 19:33:52 -07:00
|
|
|
return type != TT_TOOTHED_WHEEL
|
|
|
|
&& type != TT_ONE
|
|
|
|
&& type != TT_ONE_PLUS_ONE
|
|
|
|
&& type != TT_3_1_CAM
|
|
|
|
&& type != TT_TOOTHED_WHEEL_60_2
|
|
|
|
&& type != TT_TOOTHED_WHEEL_36_1;
|
2019-08-07 21:19:09 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
operation_mode_e Engine::getOperationMode(DECLARE_ENGINE_PARAMETER_SIGNATURE) {
|
2019-08-17 19:00:01 -07:00
|
|
|
/**
|
|
|
|
* here we ignore user-provided setting for well known triggers.
|
|
|
|
* For instance for Miata NA, there is no reason to allow user to set FOUR_STROKE_CRANK_SENSOR
|
|
|
|
*/
|
|
|
|
return doesTriggerImplyOperationMode(engineConfiguration->trigger.type) ? triggerCentral.triggerShape.getOperationMode() : engineConfiguration->ambiguousOperationMode;
|
2019-08-07 21:19:09 -07: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
|
|
|
*/
|
2017-05-15 20:28:49 -07:00
|
|
|
void Engine::periodicFastCallback(DECLARE_ENGINE_PARAMETER_SIGNATURE) {
|
2019-10-11 17:43:21 -07:00
|
|
|
ScopePerf pc(PE::EnginePeriodicFastCallback);
|
2016-01-01 14:02:49 -08:00
|
|
|
|
2018-02-06 12:47:19 -08:00
|
|
|
#if EFI_MAP_AVERAGING
|
|
|
|
refreshMapAveragingPreCalc(PASS_ENGINE_PARAMETER_SIGNATURE);
|
|
|
|
#endif
|
2016-01-01 14:02:49 -08:00
|
|
|
|
2017-05-15 20:28:49 -07:00
|
|
|
engineState.periodicFastCallback(PASS_ENGINE_PARAMETER_SIGNATURE);
|
2016-01-25 00:02:33 -08:00
|
|
|
|
2019-05-07 16:32:08 -07:00
|
|
|
engine->m.beforeFuelCalc = getTimeNowLowerNt();
|
2019-01-21 18:48:58 -08:00
|
|
|
int rpm = GET_RPM();
|
2019-10-16 20:02:24 -07:00
|
|
|
|
2017-11-06 19:29:39 -08:00
|
|
|
ENGINE(injectionDuration) = getInjectionDuration(rpm PASS_ENGINE_PARAMETER_SUFFIX);
|
2019-05-07 16:32:08 -07:00
|
|
|
engine->m.fuelCalcTime = getTimeNowLowerNt() - engine->m.beforeFuelCalc;
|
2015-07-10 06:01:56 -07:00
|
|
|
}
|
2019-01-19 19:09:37 -08:00
|
|
|
|
|
|
|
void doScheduleStopEngine(DECLARE_ENGINE_PARAMETER_SIGNATURE) {
|
|
|
|
engine->stopEngineRequestTimeNt = getTimeNowNt();
|
|
|
|
// let's close injectors or else if these happen to be open right now
|
|
|
|
enginePins.stopPins();
|
|
|
|
}
|
2019-11-23 15:38:16 -08:00
|
|
|
|
|
|
|
void action_s::setAction(schfunc_t callback, void *param) {
|
|
|
|
this->callback = callback;
|
|
|
|
this->param = param;
|
|
|
|
}
|
|
|
|
|
|
|
|
void action_s::execute() {
|
|
|
|
efiAssertVoid(CUSTOM_ERR_ASSERT, callback != NULL, "callback==null1");
|
|
|
|
callback(param);
|
|
|
|
}
|
2019-11-23 17:36:40 -08:00
|
|
|
|
|
|
|
schfunc_t action_s::getCallback() const {
|
|
|
|
return callback;
|
|
|
|
}
|
|
|
|
|
|
|
|
void * action_s::getArgument() const {
|
|
|
|
return param;
|
|
|
|
}
|
|
|
|
|