rusefi/firmware/controllers/engine_controller.cpp

709 lines
20 KiB
C++
Raw Normal View History

2015-07-10 06:01:56 -07:00
/**
* @file engine_controller.cpp
* @brief Controllers package entry point code
*
*
*
* @date Feb 7, 2013
2018-01-20 17:55:31 -08:00
* @author Andrey Belomutskiy, (c) 2012-2018
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/>.
*/
2015-09-12 16:01:20 -07:00
#include "sensor_chart.h"
2015-07-10 06:01:56 -07:00
#include "main.h"
#include "engine_configuration.h"
#include "trigger_central.h"
#include "engine_controller.h"
#include "fsio_core.h"
#include "fsio_impl.h"
#include "idle_thread.h"
#include "rpm_calculator.h"
#include "signal_executor.h"
#include "main_trigger_callback.h"
#include "io_pins.h"
#include "flash_main.h"
#include "tunerstudio.h"
#include "injector_central.h"
#include "rfiutil.h"
#include "engine_math.h"
#include "wave_analyzer.h"
#include "allsensors.h"
#include "electronic_throttle.h"
#include "map_averaging.h"
#include "malfunction_central.h"
#include "malfunction_indicator.h"
#include "engine.h"
#include "algo.h"
#include "LocalVersionHolder.h"
#include "alternatorController.h"
#include "fuel_math.h"
#include "settings.h"
2016-06-27 19:02:41 -07:00
#include "aux_pid.h"
2017-08-28 17:11:32 -07:00
#include "accelerometer.h"
2015-07-10 06:01:56 -07:00
#if HAL_USE_ADC || defined(__DOXYGEN__)
#include "AdcConfiguration.h"
2016-08-20 20:02:09 -07:00
#endif /* HAL_USE_ADC */
2015-07-10 06:01:56 -07:00
2015-08-19 13:01:36 -07:00
#if EFI_PROD_CODE || defined(__DOXYGEN__)
2015-07-10 06:01:56 -07:00
#include "pwm_generator.h"
#include "adc_inputs.h"
#include "efilib2.h"
#include "PwmTester.h"
#include "pwm_generator.h"
#include "lcd_controller.h"
#include "pin_repository.h"
2015-08-19 13:01:36 -07:00
#include "tachometer.h"
2018-01-22 09:24:03 -08:00
#include "CJ125.h"
2016-08-20 20:02:09 -07:00
#endif /* EFI_PROD_CODE */
2015-07-10 06:01:56 -07:00
extern bool hasFirmwareErrorFlag;
2017-02-24 16:42:34 -08:00
extern EnginePins enginePins;
2015-07-10 06:01:56 -07:00
2017-06-04 12:01:40 -07:00
EXTERN_ENGINE;
2015-07-10 06:01:56 -07:00
/**
* CH_FREQUENCY is the number of system ticks in a second
*/
2016-02-04 18:03:01 -08:00
static virtual_timer_t periodicSlowTimer;
static virtual_timer_t periodicFastTimer;
2015-07-10 06:01:56 -07:00
static LoggingWithStorage logger("Engine Controller");
#if (EFI_PROD_CODE || EFI_SIMULATOR) || defined(__DOXYGEN__)
/**
* todo: this should probably become 'static', i.e. private, and propagated around explicitly?
*/
2016-12-18 07:02:38 -08:00
Engine _engine CCM_OPTIONAL;
2015-07-10 06:01:56 -07:00
Engine * engine = &_engine;
2016-08-20 20:02:09 -07:00
#endif /* EFI_PROD_CODE */
2015-07-10 06:01:56 -07:00
static msg_t csThread(void) {
chRegSetThreadName("status");
#if EFI_SHAFT_POSITION_INPUT || defined(__DOXYGEN__)
while (true) {
2017-07-06 05:49:55 -07:00
int is_cranking = ENGINE(rpmCalculator).isCranking(PASS_ENGINE_PARAMETER_SIGNATURE);
bool is_running = ENGINE(rpmCalculator).isRunning(PASS_ENGINE_PARAMETER_SIGNATURE);
2015-07-10 06:01:56 -07:00
if (is_running) {
// blinking while running
2017-02-24 16:42:34 -08:00
enginePins.runningPin.setValue(0);
2015-07-10 06:01:56 -07:00
chThdSleepMilliseconds(50);
2017-02-24 16:42:34 -08:00
enginePins.runningPin.setValue(1);
2015-07-10 06:01:56 -07:00
chThdSleepMilliseconds(50);
} else {
// constant on while cranking and off if engine is stopped
2017-02-24 16:42:34 -08:00
enginePins.runningPin.setValue(is_cranking);
2015-07-10 06:01:56 -07:00
chThdSleepMilliseconds(100);
}
}
#endif /* EFI_SHAFT_POSITION_INPUT */
return -1;
}
#if EFI_PROD_CODE || defined(__DOXYGEN__)
2017-06-08 19:54:51 -07:00
static Overflow64Counter halTime;
2015-07-10 06:01:56 -07:00
2015-12-26 13:01:56 -08:00
/**
* 64-bit result would not overflow, but that's complex stuff for our 32-bit MCU
*/
2015-07-10 06:01:56 -07:00
//todo: macro to save method invocation
efitimeus_t getTimeNowUs(void) {
return getTimeNowNt() / (CORE_CLOCK / 1000000);
}
//todo: macro to save method invocation
efitick_t getTimeNowNt(void) {
#if EFI_PROD_CODE
bool alreadyLocked = lockAnyContext();
efitime_t localH = halTime.state.highBits;
uint32_t localLow = halTime.state.lowBits;
uint32_t value = GET_TIMESTAMP();
if (value < localLow) {
// new value less than previous value means there was an overflow in that 32 bit counter
localH += 0x100000000LL;
}
efitime_t result = localH + value;
if (!alreadyLocked) {
unlockAnyContext();
}
return result;
#else
// todo: why is this implementation not used?
/**
* this method is lock-free and thread-safe, that's because the 'update' method
* is atomic with a critical zone requirement.
*
* http://stackoverflow.com/questions/5162673/how-to-read-two-32bit-counters-as-a-64bit-integer-without-race-condition
*/
efitime_t localH;
efitime_t localH2;
uint32_t localLow;
int counter = 0;
do {
localH = halTime.state.highBits;
localLow = halTime.state.lowBits;
localH2 = halTime.state.highBits;
#if EFI_PROD_CODE || defined(__DOXYGEN__)
if (counter++ == 10000)
chDbgPanic("lock-free frozen");
#endif /* EFI_PROD_CODE */
} while (localH != localH2);
/**
* We need to take current counter after making a local 64 bit snapshot
*/
uint32_t value = GET_TIMESTAMP();
if (value < localLow) {
// new value less than previous value means there was an overflow in that 32 bit counter
localH += 0x100000000LL;
}
return localH + value;
#endif
2015-07-10 06:01:56 -07:00
}
2016-02-05 13:01:55 -08:00
/**
* number of SysClock ticks in one ms
*/
2017-03-21 11:58:14 -07:00
#define TICKS_IN_MS (CH_CFG_ST_FREQUENCY / 1000)
2016-02-05 13:01:55 -08:00
// todo: this overflows pretty fast!
2015-07-10 06:01:56 -07:00
efitimems_t currentTimeMillis(void) {
// todo: migrate to getTimeNowUs? or not?
2017-03-21 11:58:14 -07:00
return chVTGetSystemTimeX() / TICKS_IN_MS;
2015-07-10 06:01:56 -07:00
}
2016-02-05 13:01:55 -08:00
// todo: this overflows pretty fast!
2016-07-14 20:02:55 -07:00
efitimesec_t getTimeNowSeconds(void) {
2016-02-05 13:01:55 -08:00
return currentTimeMillis() / 1000;
2015-07-10 06:01:56 -07:00
}
#endif /* EFI_PROD_CODE */
static void cylinderCleanupControl(Engine *engine) {
#if EFI_ENGINE_CONTROL || defined(__DOXYGEN__)
bool newValue;
if (engineConfiguration->isCylinderCleanupEnabled) {
2017-05-15 20:28:49 -07:00
newValue = !engine->rpmCalculator.isRunning(PASS_ENGINE_PARAMETER_SIGNATURE) && getTPS(PASS_ENGINE_PARAMETER_SIGNATURE) > CLEANUP_MODE_TPS;
2015-07-10 06:01:56 -07:00
} else {
newValue = false;
}
if (newValue != engine->isCylinderCleanupMode) {
engine->isCylinderCleanupMode = newValue;
scheduleMsg(&logger, "isCylinderCleanupMode %s", boolToString(newValue));
}
#endif
}
static LocalVersionHolder versionForConfigurationListeners;
static void periodicSlowCallback(Engine *engine);
static void scheduleNextSlowInvocation(void) {
// schedule next invocation
2016-02-05 13:01:55 -08:00
int periodMs = boardConfiguration->generalPeriodicThreadPeriod;
if (periodMs == 0)
periodMs = 50; // this might happen while resetting configuration
chVTSetAny(&periodicSlowTimer, MS2ST(periodMs), (vtfunc_t) &periodicSlowCallback, engine);
2015-07-10 06:01:56 -07:00
}
2017-05-15 20:28:49 -07:00
static void periodicFastCallback(DECLARE_ENGINE_PARAMETER_SIGNATURE) {
2015-07-10 06:01:56 -07:00
engine->periodicFastCallback();
2016-02-05 13:01:55 -08:00
chVTSetAny(&periodicFastTimer, MS2ST(20), (vtfunc_t) &periodicFastCallback, engine);
2015-07-10 06:01:56 -07:00
}
2016-01-08 12:01:38 -08:00
static void resetAccel(void) {
engine->engineLoadAccelEnrichment.reset();
engine->tpsAccelEnrichment.reset();
2016-02-06 07:01:34 -08:00
engine->wallFuel.reset();
2016-01-08 12:01:38 -08:00
}
2015-07-10 06:01:56 -07:00
static void periodicSlowCallback(Engine *engine) {
2017-03-21 11:58:14 -07:00
efiAssertVoid(getRemainingStack(chThdGetSelfX()) > 64, "lowStckOnEv");
2015-07-10 06:01:56 -07:00
#if EFI_PROD_CODE
/**
* We need to push current value into the 64 bit counter often enough so that we do not miss an overflow
*/
bool alreadyLocked = lockAnyContext();
2017-03-21 11:58:14 -07:00
updateAndSet(&halTime.state, port_rt_get_counter_value());
2015-07-10 06:01:56 -07:00
if (!alreadyLocked) {
unlockAnyContext();
}
#endif
2017-07-06 16:33:25 -07:00
/**
* Update engine RPM state if needed (check timeouts).
*/
2017-07-06 18:21:45 -07:00
engine->rpmCalculator.checkIfSpinning(PASS_ENGINE_PARAMETER_SIGNATURE);
2017-07-06 16:33:25 -07:00
2017-07-06 16:15:10 -07:00
if (engine->rpmCalculator.isStopped(PASS_ENGINE_PARAMETER_SIGNATURE)) {
2015-09-03 06:01:31 -07:00
#if (EFI_PROD_CODE && EFI_ENGINE_CONTROL && EFI_INTERNAL_FLASH) || defined(__DOXYGEN__)
2015-07-10 06:01:56 -07:00
writeToFlashIfPending();
#endif
2016-01-08 12:01:38 -08:00
resetAccel();
} else {
updatePrimeInjectionPulseState(PASS_ENGINE_PARAMETER_SIGNATURE);
2015-09-03 06:01:31 -07:00
}
2015-07-10 06:01:56 -07:00
if (versionForConfigurationListeners.isOld()) {
2016-01-31 13:01:26 -08:00
updateAccelParameters();
2016-02-06 14:01:38 -08:00
engine->engineState.warmupAfrPid.reset();
2015-07-10 06:01:56 -07:00
}
engine->watchdog();
engine->updateSlowSensors();
engine->checkShutdown();
2015-07-10 06:01:56 -07:00
#if (EFI_PROD_CODE && EFI_FSIO) || defined(__DOXYGEN__)
2017-12-16 21:03:26 -08:00
runFsio(PASS_ENGINE_PARAMETER_SIGNATURE);
2017-07-24 16:38:00 -07:00
#endif /* EFI_PROD_CODE && EFI_FSIO */
2015-07-10 06:01:56 -07:00
cylinderCleanupControl(engine);
scheduleNextSlowInvocation();
}
2017-05-15 20:28:49 -07:00
void initPeriodicEvents(DECLARE_ENGINE_PARAMETER_SIGNATURE) {
2015-07-10 06:01:56 -07:00
scheduleNextSlowInvocation();
2017-05-15 20:28:49 -07:00
periodicFastCallback(PASS_ENGINE_PARAMETER_SIGNATURE);
2015-07-10 06:01:56 -07:00
}
2016-12-27 11:04:04 -08:00
char * getPinNameByAdcChannel(const char *msg, adc_channel_e hwChannel, char *buffer) {
2015-07-10 06:01:56 -07:00
#if HAL_USE_ADC || defined(__DOXYGEN__)
2016-12-27 11:04:04 -08:00
if (hwChannel == EFI_ADC_NONE) {
strcpy(buffer, "NONE");
} else {
strcpy((char*) buffer, portname(getAdcChannelPort(msg, hwChannel)));
itoa10(&buffer[2], getAdcChannelPin(hwChannel));
}
2015-07-10 06:01:56 -07:00
#else
strcpy(buffer, "NONE");
#endif
return (char*) buffer;
}
static char pinNameBuffer[16];
#if HAL_USE_ADC || defined(__DOXYGEN__)
extern AdcDevice fastAdc;
#endif
static void printAnalogChannelInfoExt(const char *name, adc_channel_e hwChannel, float adcVoltage,
float dividerCoeff) {
#if HAL_USE_ADC || defined(__DOXYGEN__)
if (hwChannel == EFI_ADC_NONE) {
scheduleMsg(&logger, "ADC is not assigned for %s", name);
return;
}
if (fastAdc.isHwUsed(hwChannel)) {
scheduleMsg(&logger, "fast enabled=%s", boolToString(boardConfiguration->isFastAdcEnabled));
}
float voltage = adcVoltage * dividerCoeff;
2018-01-23 09:05:14 -08:00
scheduleMsg(&logger, "%s ADC%d %s %s adc=%.2f/input=%.2fv/divider=%.2f", name, hwChannel, getAdcMode(hwChannel),
2016-12-27 11:04:04 -08:00
getPinNameByAdcChannel(name, hwChannel, pinNameBuffer), adcVoltage, voltage, dividerCoeff);
2015-07-10 06:01:56 -07:00
#endif
}
static void printAnalogChannelInfo(const char *name, adc_channel_e hwChannel) {
#if HAL_USE_ADC || defined(__DOXYGEN__)
printAnalogChannelInfoExt(name, hwChannel, getVoltage("print", hwChannel), engineConfiguration->analogInputDividerCoefficient);
#endif
}
static void printAnalogInfo(void) {
2018-01-23 09:05:14 -08:00
scheduleMsg(&logger, "analogInputDividerCoefficient: %.2f", engineConfiguration->analogInputDividerCoefficient);
2015-07-10 06:01:56 -07:00
printAnalogChannelInfo("hip9011", engineConfiguration->hipOutputChannel);
printAnalogChannelInfo("fuel gauge", engineConfiguration->fuelLevelSensor);
printAnalogChannelInfo("TPS", engineConfiguration->tpsAdcChannel);
printAnalogChannelInfo("pPS", engineConfiguration->pedalPositionChannel);
2016-12-17 06:02:59 -08:00
if (engineConfiguration->clt.adcChannel != EFI_ADC_NONE) {
printAnalogChannelInfo("CLT", engineConfiguration->clt.adcChannel);
}
if (engineConfiguration->iat.adcChannel != EFI_ADC_NONE) {
2015-07-10 06:01:56 -07:00
printAnalogChannelInfo("IAT", engineConfiguration->iat.adcChannel);
}
if (hasMafSensor()) {
printAnalogChannelInfo("MAF", engineConfiguration->mafAdcChannel);
}
2017-08-06 16:43:01 -07:00
for (int i = 0; i < FSIO_ANALOG_INPUT_COUNT ; i++) {
2016-05-15 21:02:01 -07:00
adc_channel_e ch = engineConfiguration->fsioAdc[i];
if (ch != EFI_ADC_NONE) {
printAnalogChannelInfo("fsio", ch);
}
}
2015-07-10 06:01:56 -07:00
printAnalogChannelInfo("AFR", engineConfiguration->afr.hwChannel);
2017-05-15 20:28:49 -07:00
if (hasMapSensor(PASS_ENGINE_PARAMETER_SIGNATURE)) {
2015-07-10 06:01:56 -07:00
printAnalogChannelInfo("MAP", engineConfiguration->map.sensor.hwChannel);
}
2017-05-15 20:28:49 -07:00
if (hasBaroSensor(PASS_ENGINE_PARAMETER_SIGNATURE)) {
2015-07-10 06:01:56 -07:00
printAnalogChannelInfo("BARO", engineConfiguration->baroSensor.hwChannel);
}
if (engineConfiguration->externalKnockSenseAdc != EFI_ADC_NONE) {
printAnalogChannelInfo("extKno", engineConfiguration->externalKnockSenseAdc);
}
printAnalogChannelInfo("OilP", engineConfiguration->oilPressure.hwChannel);
2015-07-10 06:01:56 -07:00
printAnalogChannelInfo("A/C sw", engineConfiguration->acSwitchAdc);
printAnalogChannelInfo("HIP9011", engineConfiguration->hipOutputChannel);
printAnalogChannelInfoExt("Vbatt", engineConfiguration->vbattAdcChannel, getVoltage("vbatt", engineConfiguration->vbattAdcChannel),
engineConfiguration->vbattDividerCoeff);
}
static THD_WORKING_AREA(csThreadStack, UTILITY_THREAD_STACK_SIZE); // declare thread stack
#define isOutOfBounds(offset) ((offset<0) || (offset) >= (int) sizeof(engine_configuration_s))
static void getShort(int offset) {
if (isOutOfBounds(offset))
return;
uint16_t *ptr = (uint16_t *) (&((char *) engineConfiguration)[offset]);
uint16_t value = *ptr;
/**
* this response is part of dev console API
*/
scheduleMsg(&logger, "short @%d is %d", offset, value);
}
static void setBit(const char *offsetStr, const char *bitStr, const char *valueStr) {
int offset = atoi(offsetStr);
if (absI(offset) == absI(ERROR_CODE)) {
scheduleMsg(&logger, "invalid offset [%s]", offsetStr);
return;
}
if (isOutOfBounds(offset)) {
return;
}
int bit = atoi(bitStr);
if (absI(bit) == absI(ERROR_CODE)) {
scheduleMsg(&logger, "invalid bit [%s]", bitStr);
return;
}
int value = atoi(valueStr);
if (absI(value) == absI(ERROR_CODE)) {
scheduleMsg(&logger, "invalid value [%s]", valueStr);
return;
}
int *ptr = (int *) (&((char *) engineConfiguration)[offset]);
*ptr ^= (-value ^ *ptr) & (1 << bit);
/**
* this response is part of dev console API
*/
scheduleMsg(&logger, "bit @%d/%d is %d", offset, bit, value);
2017-05-15 20:28:49 -07:00
incrementGlobalConfigurationVersion(PASS_ENGINE_PARAMETER_SIGNATURE);
2015-07-10 06:01:56 -07:00
}
static void setShort(const int offset, const int value) {
if (isOutOfBounds(offset))
return;
uint16_t *ptr = (uint16_t *) (&((char *) engineConfiguration)[offset]);
*ptr = (uint16_t) value;
getShort(offset);
2017-05-15 20:28:49 -07:00
incrementGlobalConfigurationVersion(PASS_ENGINE_PARAMETER_SIGNATURE);
2015-07-10 06:01:56 -07:00
}
static void getBit(int offset, int bit) {
if (isOutOfBounds(offset))
return;
int *ptr = (int *) (&((char *) engineConfiguration)[offset]);
int value = (*ptr >> bit) & 1;
/**
* this response is part of dev console API
*/
scheduleMsg(&logger, "bit @%d/%d is %d", offset, bit, value);
}
static void getInt(int offset) {
if (isOutOfBounds(offset))
return;
int *ptr = (int *) (&((char *) engineConfiguration)[offset]);
int value = *ptr;
/**
* this response is part of dev console API
*/
scheduleMsg(&logger, "int @%d is %d", offset, value);
}
static void setInt(const int offset, const int value) {
if (isOutOfBounds(offset))
return;
int *ptr = (int *) (&((char *) engineConfiguration)[offset]);
*ptr = value;
getInt(offset);
2017-05-15 20:28:49 -07:00
incrementGlobalConfigurationVersion(PASS_ENGINE_PARAMETER_SIGNATURE);
2015-07-10 06:01:56 -07:00
}
static void getFloat(int offset) {
if (isOutOfBounds(offset))
return;
float *ptr = (float *) (&((char *) engineConfiguration)[offset]);
float value = *ptr;
/**
* this response is part of dev console API
*/
2017-04-07 13:35:43 -07:00
scheduleMsg(&logger, "float @%d is %.5f", offset, value);
2015-07-10 06:01:56 -07:00
}
static void setFloat(const char *offsetStr, const char *valueStr) {
int offset = atoi(offsetStr);
if (absI(offset) == absI(ERROR_CODE)) {
scheduleMsg(&logger, "invalid offset [%s]", offsetStr);
return;
}
if (isOutOfBounds(offset))
return;
float value = atoff(valueStr);
if (cisnan(value)) {
scheduleMsg(&logger, "invalid value [%s]", valueStr);
return;
}
float *ptr = (float *) (&((char *) engine->engineConfiguration)[offset]);
*ptr = value;
getFloat(offset);
}
2016-01-23 15:01:40 -08:00
#if EFI_ENABLE_MOCK_ADC || EFI_SIMULATOR
static void setMockVoltage(int hwChannel, float voltage) {
engine->engineState.mockAdcState.setMockVoltage(hwChannel, voltage);
}
2017-11-27 18:10:49 -08:00
void setMockCltVoltage(float voltage) {
2016-01-23 15:01:40 -08:00
setMockVoltage(engineConfiguration->clt.adcChannel, voltage);
}
2017-11-27 18:10:49 -08:00
void setMockIatVoltage(float voltage) {
2016-01-23 15:01:40 -08:00
setMockVoltage(engineConfiguration->iat.adcChannel, voltage);
}
2017-11-27 18:10:49 -08:00
void setMockMafVoltage(float voltage) {
2016-01-23 15:01:40 -08:00
setMockVoltage(engineConfiguration->mafAdcChannel, voltage);
}
2017-11-27 18:10:49 -08:00
void setMockAfrVoltage(float voltage) {
2016-01-23 15:01:40 -08:00
setMockVoltage(engineConfiguration->afr.hwChannel, voltage);
}
2017-11-27 18:10:49 -08:00
void setMockTpsVoltage(float voltage) {
2016-01-23 15:01:40 -08:00
setMockVoltage(engineConfiguration->tpsAdcChannel, voltage);
}
2017-11-27 18:10:49 -08:00
void setMockMapVoltage(float voltage) {
2016-01-23 15:01:40 -08:00
setMockVoltage(engineConfiguration->map.sensor.hwChannel, voltage);
}
2017-11-27 18:10:49 -08:00
void setMockVBattVoltage(float voltage) {
2016-01-23 15:01:40 -08:00
setMockVoltage(engineConfiguration->vbattAdcChannel, voltage);
}
static void initMockVoltage(void) {
2016-07-25 22:04:34 -07:00
#if EFI_SIMULATOR || defined(__DOXYGEN__)
2017-11-27 18:25:33 -08:00
setMockCltVoltage(2);
2016-07-25 22:04:34 -07:00
#endif /* EFI_SIMULATOR */
#if EFI_SIMULATOR || defined(__DOXYGEN__)
2017-11-27 18:25:33 -08:00
setMockIatVoltage(2);
2016-07-25 22:04:34 -07:00
#endif /* EFI_SIMULATOR */
2016-01-23 15:01:40 -08:00
}
#endif /* EFI_ENABLE_MOCK_ADC */
2016-01-12 19:01:53 -08:00
static void initConfigActions(void) {
2015-07-10 06:01:56 -07:00
addConsoleActionSS("set_float", (VoidCharPtrCharPtr) setFloat);
addConsoleActionII("set_int", (VoidIntInt) setInt);
addConsoleActionII("set_short", (VoidIntInt) setShort);
addConsoleActionSSS("set_bit", setBit);
addConsoleActionI("get_float", getFloat);
addConsoleActionI("get_int", getInt);
addConsoleActionI("get_short", getShort);
addConsoleActionII("get_bit", getBit);
}
// todo: move this logic somewhere else?
static void getKnockInfo(void) {
adc_channel_e hwChannel = engineConfiguration->externalKnockSenseAdc;
2016-12-27 11:04:04 -08:00
scheduleMsg(&logger, "externalKnockSenseAdc on ADC", getPinNameByAdcChannel("knock", hwChannel, pinNameBuffer));
2015-07-10 06:01:56 -07:00
engine->printKnockState();
}
2016-01-12 19:01:53 -08:00
// this method is used by real firmware and simulator
2017-05-15 20:28:49 -07:00
void commonInitEngineController(Logging *sharedLogger DECLARE_ENGINE_PARAMETER_SUFFIX) {
2015-07-10 06:01:56 -07:00
initConfigActions();
2016-01-23 15:01:40 -08:00
initMockVoltage();
2016-01-18 19:01:26 -08:00
2016-09-04 21:02:31 -07:00
#if EFI_PROD_CODE || EFI_SIMULATOR || defined(__DOXYGEN__)
2016-01-18 19:01:26 -08:00
initSignalExecutor();
#endif
2016-05-28 16:02:28 -07:00
#if EFI_SENSOR_CHART || defined(__DOXYGEN__)
initSensorChart();
#endif /* EFI_SENSOR_CHART */
2016-09-04 21:02:31 -07:00
#if EFI_PROD_CODE || EFI_SIMULATOR || defined(__DOXYGEN__)
2015-07-10 06:01:56 -07:00
// todo: this is a mess, remove code duplication with simulator
2017-05-07 17:40:10 -07:00
initSettings();
2015-07-10 06:01:56 -07:00
#endif
#if EFI_TUNER_STUDIO || defined(__DOXYGEN__)
if (engineConfiguration->isTunerStudioEnabled) {
startTunerStudioConnectivity();
}
#endif
if (hasFirmwareError()) {
return;
}
2017-05-15 20:28:49 -07:00
initSensors(sharedLogger PASS_ENGINE_PARAMETER_SIGNATURE);
2015-07-10 06:01:56 -07:00
2016-01-12 19:01:53 -08:00
#if EFI_FSIO || defined(__DOXYGEN__)
2017-05-15 20:28:49 -07:00
initFsioImpl(sharedLogger PASS_ENGINE_PARAMETER_SUFFIX);
2016-01-12 19:01:53 -08:00
#endif
2016-03-11 09:04:08 -08:00
initAccelEnrichment(sharedLogger);
2016-01-12 19:01:53 -08:00
}
2017-05-15 20:28:49 -07:00
void initEngineContoller(Logging *sharedLogger DECLARE_ENGINE_PARAMETER_SUFFIX) {
2016-01-12 19:01:53 -08:00
addConsoleAction("analoginfo", printAnalogInfo);
commonInitEngineController(sharedLogger);
2015-07-10 06:01:56 -07:00
#if EFI_PROD_CODE || defined(__DOXYGEN__)
initPwmGenerator();
#endif
2017-05-07 17:40:10 -07:00
initAlgo(sharedLogger);
2015-07-10 06:01:56 -07:00
#if EFI_WAVE_ANALYZER || defined(__DOXYGEN__)
if (engineConfiguration->isWaveAnalyzerEnabled) {
initWaveAnalyzer(sharedLogger);
}
#endif /* EFI_WAVE_ANALYZER */
2018-01-22 09:24:03 -08:00
#if EFI_CJ125 || defined(__DOXYGEN__)
/**
* this uses SimplePwm which depends on scheduler, has to be initialized after scheduler
*/
initCJ125(sharedLogger);
#endif
2015-07-10 06:01:56 -07:00
#if EFI_SHAFT_POSITION_INPUT || defined(__DOXYGEN__)
/**
* there is an implicit dependency on the fact that 'tachometer' listener is the 1st listener - this case
* other listeners can access current RPM value
*/
initRpmCalculator(sharedLogger, engine);
#endif /* EFI_SHAFT_POSITION_INPUT */
2016-08-25 21:01:55 -07:00
#if (EFI_PROD_CODE && EFI_ENGINE_CONTROL) || defined(__DOXYGEN__)
initInjectorCentral(sharedLogger);
#endif /* EFI_PROD_CODE && EFI_ENGINE_CONTROL */
2015-07-10 06:01:56 -07:00
// multiple issues with this initMapAdjusterThread();
2016-08-25 21:01:55 -07:00
// periodic events need to be initialized after fuel&spark pins to avoid a warning
2017-05-15 20:28:49 -07:00
initPeriodicEvents(PASS_ENGINE_PARAMETER_SIGNATURE);
2015-07-10 06:01:56 -07:00
2016-06-01 17:01:36 -07:00
if (hasFirmwareError()) {
return;
}
2015-07-10 06:01:56 -07:00
chThdCreateStatic(csThreadStack, sizeof(csThreadStack), LOWPRIO, (tfunc_t) csThread, NULL);
#if (EFI_PROD_CODE && EFI_ENGINE_CONTROL) || defined(__DOXYGEN__)
/**
* This has to go after 'initInjectorCentral' and 'initInjectorCentral' in order to
* properly detect un-assigned output pins
*/
2017-05-15 20:28:49 -07:00
prepareShapes(PASS_ENGINE_PARAMETER_SIGNATURE);
2016-08-25 21:01:55 -07:00
#endif /* EFI_PROD_CODE && EFI_ENGINE_CONTROL */
2015-07-10 06:01:56 -07:00
#if EFI_PWM_TESTER || defined(__DOXYGEN__)
initPwmTester();
2017-03-19 14:42:15 -07:00
#endif /* EFI_PWM_TESTER */
2015-07-10 06:01:56 -07:00
initMalfunctionCentral();
#if EFI_ALTERNATOR_CONTROL || defined(__DOXYGEN__)
initAlternatorCtrl(sharedLogger);
#endif
2016-06-27 19:02:41 -07:00
#if EFI_AUX_PID || defined(__DOXYGEN__)
initAuxPid(sharedLogger);
#endif
2015-07-10 06:01:56 -07:00
#if EFI_ELECTRONIC_THROTTLE_BODY || defined(__DOXYGEN__)
initElectronicThrottle();
#endif /* EFI_ELECTRONIC_THROTTLE_BODY */
#if EFI_MALFUNCTION_INDICATOR || defined(__DOXYGEN__)
2016-12-27 21:02:03 -08:00
initMalfunctionIndicator();
2015-07-10 06:01:56 -07:00
#endif /* EFI_MALFUNCTION_INDICATOR */
#if EFI_MAP_AVERAGING || defined(__DOXYGEN__)
if (engineConfiguration->isMapAveragingEnabled) {
initMapAveraging(sharedLogger, engine);
}
#endif /* EFI_MAP_AVERAGING */
initEgoAveraging(PASS_ENGINE_PARAMETER_SIGNATURE);
2015-07-10 06:01:56 -07:00
#if EFI_ENGINE_CONTROL || defined(__DOXYGEN__)
if (boardConfiguration->isEngineControlEnabled) {
/**
* This method initialized the main listener which actually runs injectors & ignition
*/
2017-05-25 19:28:04 -07:00
initMainEventListener(sharedLogger DECLARE_ENGINE_PARAMETER_SUFFIX);
2015-07-10 06:01:56 -07:00
}
#endif /* EFI_ENGINE_CONTROL */
#if EFI_IDLE_CONTROL || defined(__DOXYGEN__)
startIdleThread(sharedLogger);
2017-03-19 14:42:15 -07:00
#endif /* EFI_IDLE_CONTROL */
2015-07-10 06:01:56 -07:00
if (engineConfiguration->externalKnockSenseAdc != EFI_ADC_NONE) {
addConsoleAction("knockinfo", getKnockInfo);
}
2017-06-11 11:59:03 -07:00
#if EFI_PROD_CODE || defined(__DOXYGEN__)
2015-07-10 06:01:56 -07:00
addConsoleAction("reset_accel", resetAccel);
2017-03-19 14:42:15 -07:00
#endif /* EFI_PROD_CODE */
2015-07-10 06:01:56 -07:00
#if EFI_HD44780_LCD || defined(__DOXYGEN__)
initLcdController();
2017-03-19 14:42:15 -07:00
#endif /* EFI_HD44780_LCD */
2015-08-19 13:01:36 -07:00
#if EFI_PROD_CODE || defined(__DOXYGEN__)
initTachometer();
2017-03-19 14:42:15 -07:00
#endif /* EFI_PROD_CODE */
2015-07-10 06:01:56 -07:00
}