manual sync

This commit is contained in:
rusefi 2014-05-19 10:10:56 -05:00
parent c4061aa46f
commit e39e080551
149 changed files with 3672 additions and 2827 deletions

View File

@ -43,6 +43,7 @@
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/config/boards}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/controllers}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/controllers/algo}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/controllers/core}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/controllers/trigger}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/controllers/sensors}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/controllers/system}&quot;"/>
@ -102,6 +103,7 @@
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/config/boards}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/controllers}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/controllers/algo}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/controllers/core}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/controllers/trigger}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/controllers/sensors}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/controllers/system}&quot;"/>

View File

@ -743,8 +743,9 @@ INPUT = . \
util \
console \
controllers \
controllers/math \
controllers/algo \
controllers/core \
controllers/math \
controllers/sensors \
controllers/system \
controllers/trigger \

View File

@ -95,6 +95,7 @@ include controllers/controllers.mk
include $(PROJECT_DIR)/util/util.mk
include $(PROJECT_DIR)/config/engines/engines.mk
include $(PROJECT_DIR)/controllers/algo/algo.mk
include $(PROJECT_DIR)/controllers/core/core.mk
include $(PROJECT_DIR)/controllers/math/math.mk
include $(PROJECT_DIR)/controllers/sensors/sensors.mk
include $(PROJECT_DIR)/controllers/system/system.mk
@ -125,6 +126,7 @@ CSRC = $(PORTSRC) \
$(HW_LAYERSRC) \
$(CONTROLLERSSRC) \
$(CONTROLLERS_ALGO_SRC) \
$(CONTROLLERS_CORE_SRC) \
$(CONTROLLERS_MATH_SRC) \
$(CONTROLLERS_SENSORS_SRC) \
$(PLATFORMSRC) \
@ -137,6 +139,7 @@ CSRC = $(PORTSRC) \
# setting.
CPPSRC = $(CHCPPSRC) \
$(TRIGGER_SRC_CPP) \
$(TRIGGER_DECODERS_SRC_CPP) \
$(EMULATIONSRC_CPP) \
$(CONTROLLERS_ALGO_SRC_CPP) \
$(SYSTEMSRC_CPP) \
@ -146,6 +149,7 @@ CPPSRC = $(CHCPPSRC) \
$(CONTROLLERS_SENSORS_SRC_CPP) \
$(CONTROLLERS_SRC_CPP) \
$(UTILSRC_CPP) \
$(CONTROLLERS_CORE_SRC_CPP) \
$(CONTROLLERS_MATH_SRC_CPP) \
rusefi.cpp \
main.cpp
@ -198,6 +202,7 @@ INCDIR = $(PORTINC) $(KERNINC) $(TESTINC) \
controllers/sensors \
controllers/system \
controllers/algo \
controllers/core \
controllers/math \
controllers/trigger

View File

@ -59,6 +59,17 @@
#define CH_TRACE_BUFFER_SIZE 64
#endif
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
void chDbgPanic3(const char *msg, const char * file, int line);
#ifdef __cplusplus
}
#endif /* __cplusplus */
/**
* @brief Fill value for thread stack area in debug mode.
*/

View File

@ -34,7 +34,7 @@
* Imports the Cortex-Mx configuration headers.
*/
#define _FROM_ASM_
#include "chconf.h"
#include "config\system\chconf.h"
#include "chcore.h"
CONTEXT_OFFSET SET 12

View File

@ -18,17 +18,17 @@ if errorlevel 1 goto error
echo Build complete success.
svn info > ../firmware_binary/version.txt
cp config/features.h ../firmware_binary
cp build/rusefi.hex ../firmware_binary
cp build/rusefi.elf ../firmware_binary
rem svn info > ../firmware_binary/version.txt
rem cp config/features.h ../firmware_binary
rem cp build/rusefi.hex ../firmware_binary
rem cp build/rusefi.elf ../firmware_binary
cp tunerstudio/rusefi.ini ../firmware_binary
rem cp tunerstudio/rusefi.ini ../firmware_binary
cd ../firmware_binary
del firmaware_binary.zip
7z a firmaware_binary.zip rusefi.hex rusefi.ini features.h flash.bat
cd ../firmware
rem cd ../firmware_binary
rem del firmaware_binary.zip
rem 7z a firmaware_binary.zip rusefi.hex rusefi.ini features.h flash.bat
rem cd ../firmware
cd build

View File

@ -126,23 +126,6 @@
#define EFI_I2C_SDA_PIN 7
#define EFI_I2C_AF 4
#define EFI_ADC_SLOW_CHANNELS_COUNT 10
#define EFI_USE_ADC_CHANNEL_IN0 TRUE
#define EFI_USE_ADC_CHANNEL_IN1 TRUE
#define EFI_USE_ADC_CHANNEL_IN2 TRUE
#define EFI_USE_ADC_CHANNEL_IN3 TRUE
#define EFI_USE_ADC_CHANNEL_IN4 TRUE
#define EFI_USE_ADC_CHANNEL_IN6 TRUE
#define EFI_USE_ADC_CHANNEL_IN7 TRUE
#define EFI_USE_ADC_CHANNEL_IN11 TRUE
#define EFI_USE_ADC_CHANNEL_IN12 TRUE
#define EFI_USE_ADC_CHANNEL_IN13 TRUE
#define EFI_USE_ADC_CHANNEL_IN14 FALSE
#define EFI_USE_ADC_CHANNEL_IN15 FALSE
/**
* Patched version of ChibiOS/RT support extra details in the system error messages
*/
@ -183,35 +166,6 @@
* PE5
*/
/**
* Primary shaft position input
* TODO: ? rename to PRIMARY_TRIGGER?
*/
#define PRIMARY_SHAFT_POSITION_INPUT_DRIVER ICUD3
#define PRIMARY_SHAFT_POSITION_INPUT_PORT GPIOC
#define PRIMARY_SHAFT_POSITION_INPUT_PIN 6
#define PRIMARY_SHAFT_POSITION_INPUT_CHANNEL ICU_CHANNEL_1
/**
* Secondary shaft position input
* TODO: ? rename to SECONDARY_TRIGGER? *
*/
#define SECONDARY_SHAFT_POSITION_INPUT_DRIVER ICUD2
#define SECONDARY_SHAFT_POSITION_INPUT_PORT GPIOA
#define SECONDARY_SHAFT_POSITION_INPUT_PIN 5
#define SECONDARY_SHAFT_POSITION_INPUT_CHANNEL ICU_CHANNEL_1
/* Logic analyzer */
#define LOGIC_ANALYZER_1_DRIVER ICUD1
#define LOGIC_ANALYZER_1_PORT GPIOA
#define LOGIC_ANALYZER_1_PIN 8
#define LOGIC_ANALYZER_2_DRIVER ICUD9
#define LOGIC_ANALYZER_2_PORT GPIOE
#define LOGIC_ANALYZER_2_PIN 7
//#define ETB_CONTROL_LINE_1_PORT GPIOE
//#define ETB_CONTROL_LINE_1_PIN 0
//

View File

@ -17,6 +17,7 @@
#define EFI_WAVE_CHART TRUE
#define EFI_ANALOG_CHART TRUE
//#define SERIAL_SPEED (8 * 115200)
//#define SERIAL_SPEED (2 * 115200)
@ -43,12 +44,22 @@
*/
#define EFI_CLI_SUPPORT TRUE
#define EFI_INTERNAL_FLASH TRUE
/**
* Usually you need shaft position input, but maybe you do not need it?
*/
#define EFI_SHAFT_POSITION_INPUT TRUE
#define EFI_ANALOG_INPUTS TRUE
/**
* Maybe we are just sniffing what's going on?
*/
#define EFI_ENGINE_CONTROL TRUE
#define EFI_SPEED_DENSITY TRUE
/**
* MCP42010 digital potentiometer support. This could be useful if you are stimulating some
* stock ECU
@ -66,6 +77,8 @@
#define EFI_IDLE_CONTROL FALSE
#define EFI_FUEL_PUMP TRUE
#define EFI_ENGINE_EMULATOR TRUE
#define EFI_EMULATE_POSITION_SENSORS TRUE
@ -121,4 +134,10 @@
//#define EFI_ELECTRONIC_THROTTLE_BODY TRUE
#define EFI_ELECTRONIC_THROTTLE_BODY FALSE
#define EFI_MALFUNCTION_INDICATOR TRUE
//#define EFI_MALFUNCTION_INDICATOR FALSE
#define EFI_MAP_AVERAGING TRUE
//#define EFI_MAP_AVERAGING FALSE
#endif /* EFIFEATURES_H_ */

View File

@ -1,6 +1,8 @@
/**
* @file MiniCooperR50.cpp
*
* MINI_COOPER_R50 = 13
*
* @date Apr 9, 2014
* @author Andrey Belomutskiy, (c) 2012-2014
*/

View File

@ -4,7 +4,7 @@
* CITROEN_TU3JP 15
*
* @date Apr 15, 2014
* @author Andrey Belomutskiy, (c) 2012-2013
* @author Andrey Belomutskiy, (c) 2012-2014
*/
#include "citroenBerlingoTU3JP.h"

View File

@ -2,7 +2,7 @@
* @file citroenBerlingoTU3JP.h
*
* @date Apr 15, 2014
* @author Andrey Belomutskiy, (c) 2012-2013
* @author Andrey Belomutskiy, (c) 2012-2014
*/
#ifndef CITROENBERLINGOTU3JP_H_

View File

@ -67,11 +67,27 @@ void setFordInline6(engine_configuration_s *engineConfiguration, board_configura
// input channel 10 is PC3, that's ADC13
// input channel 12 is PC1, that's ADC11
memset(boardConfiguration->adcHwChannelEnabled, 0, sizeof(boardConfiguration->adcHwChannelEnabled));
boardConfiguration->adcHwChannelEnabled[1] = ADC_SLOW;
boardConfiguration->adcHwChannelEnabled[2] = ADC_SLOW;
boardConfiguration->adcHwChannelEnabled[3] = ADC_SLOW;
boardConfiguration->adcHwChannelEnabled[4] = ADC_SLOW;
boardConfiguration->adcHwChannelEnabled[7] = ADC_SLOW;
boardConfiguration->adcHwChannelEnabled[11] = ADC_SLOW;
boardConfiguration->adcHwChannelEnabled[15] = ADC_FAST;
engineConfiguration->tpsAdcChannel = 4;
engineConfiguration->iatAdcChannel = 2;
engineConfiguration->cltAdcChannel = 1;
engineConfiguration->afrSensor.afrAdcChannel = 11;
engineConfiguration->map.sensor.sensorType = MT_MPX4250;
engineConfiguration->map.sensor.hwChannel = 15;
engineConfiguration->baroSensor.sensorType = MT_MPX4250;
engineConfiguration->baroSensor.hwChannel = 7;
// 6 channel output board
// output 1 is PB9
// output 3 is PE3
@ -89,12 +105,15 @@ void setFordInline6(engine_configuration_s *engineConfiguration, board_configura
engineConfiguration->tpsMin = convertVoltageTo10bitADC(1.250);
engineConfiguration->tpsMax = convertVoltageTo10bitADC(4.538);
engineConfiguration->map.config.mapType = MT_MPX4250;
engineConfiguration->map.channel = 2; // input channel 8 is ADC2
// engineConfiguration->vBattAdcChannel = 0; //
// engineConfiguration->mafAdcChannel = 1;
boardConfiguration->primaryTriggerInputPin = GPIOA_8;
boardConfiguration->secondaryTriggerInputPin = GPIOA_5;
boardConfiguration->primaryLogicAnalyzerPin = GPIOC_6;
boardConfiguration->secondaryLogicAnalyzerPin = GPIOE_7;
}
#endif /* EFI_SUPPORT_1995_FORD_INLINE_6 */

View File

@ -86,8 +86,8 @@ static void setDefaultMaps(engine_configuration_s *engineConfiguration) {
}
void setFordAspireEngineConfiguration(engine_configuration_s *engineConfiguration, board_configuration_s *boardConfiguration) {
engineConfiguration->tpsMin = 1;
engineConfiguration->tpsMax = 1000;
engineConfiguration->tpsMin = 100;
engineConfiguration->tpsMax = 750;
engineConfiguration->rpmHardLimit = 7000;
@ -139,14 +139,14 @@ void setFordAspireEngineConfiguration(engine_configuration_s *engineConfiguratio
// Frankenstein analog input #12: adc
engineConfiguration->tpsAdcChannel = 3; // 15 is the old value
engineConfiguration->vBattAdcChannel = 0; // 1 is the old value
// engineConfiguration->map.channel = 1;
engineConfiguration->tpsAdcChannel = 3;
engineConfiguration->vBattAdcChannel = 0;
engineConfiguration->map.sensor.hwChannel = 4;
engineConfiguration->mafAdcChannel = 1;
engineConfiguration->cltAdcChannel = 11;
// engineConfiguration->iatAdcChannel =
engineConfiguration->map.config.mapType = MT_DENSO183;
engineConfiguration->map.sensor.sensorType = MT_DENSO183;
}
#endif /* EFI_SUPPORT_FORD_ASPIRE */

View File

@ -4,7 +4,7 @@
* FORD_ESCORT_GT = 14
*
* @date Apr 11, 2014
* @author Andrey Belomutskiy, (c) 2012-2013
* @author Andrey Belomutskiy, (c) 2012-2014
*/
#include "ford_escort_gt.h"

View File

@ -2,7 +2,7 @@
* @file mazda_323.c
*
* @date Mar 8, 2014
* @author Andrey Belomutskiy, (c) 2012-2013
* @author Andrey Belomutskiy, (c) 2012-2014
*/
#include "mazda_323.h"

View File

@ -39,15 +39,6 @@
#ifndef _CHCONF_H_
#define _CHCONF_H_
#ifdef __cplusplus
extern "C"
{
#endif
void chDbgPanic3(const char *msg, const char * file, int line);
#ifdef __cplusplus
}
#endif
#define chDbgCheck(c, func) { \
if (!(c)) \
chDbgPanic3(__QUOTE_THIS(func)"()", __FILE__, __LINE__); \
@ -56,6 +47,8 @@ void chDbgPanic3(const char *msg, const char * file, int line);
#define PORT_IDLE_THREAD_STACK_SIZE 256
#define PORT_INT_REQUIRED_STACK 128
#define CHPRINTF_USE_FLOAT TRUE
/**

View File

@ -80,7 +80,7 @@
* @brief Enables the GPT subsystem.
*/
#if !defined(HAL_USE_GPT) || defined(__DOXYGEN__)
#define HAL_USE_GPT FALSE
#define HAL_USE_GPT TRUE
#endif
/**

View File

@ -123,7 +123,7 @@
#define STM32_GPT_USE_TIM2 FALSE
#define STM32_GPT_USE_TIM3 FALSE
#define STM32_GPT_USE_TIM4 FALSE
#define STM32_GPT_USE_TIM5 FALSE
#define STM32_GPT_USE_TIM5 TRUE
#define STM32_GPT_USE_TIM6 FALSE
#define STM32_GPT_USE_TIM7 FALSE
#define STM32_GPT_USE_TIM8 FALSE
@ -135,7 +135,7 @@
#define STM32_GPT_TIM2_IRQ_PRIORITY 7
#define STM32_GPT_TIM3_IRQ_PRIORITY 7
#define STM32_GPT_TIM4_IRQ_PRIORITY 7
#define STM32_GPT_TIM5_IRQ_PRIORITY 7
#define STM32_GPT_TIM5_IRQ_PRIORITY 3
#define STM32_GPT_TIM6_IRQ_PRIORITY 7
#define STM32_GPT_TIM7_IRQ_PRIORITY 7
#define STM32_GPT_TIM8_IRQ_PRIORITY 7

View File

@ -26,6 +26,8 @@
#endif
#include "rfiutil.h"
static bool_t isSerialConsoleStarted = FALSE;
/**
* @brief Reads a whole line from the input channel.
*
@ -40,7 +42,7 @@ static bool_t getConsoleLine(BaseSequentialStream *chp, char *line, unsigned siz
char *p = line;
while (TRUE) {
if (!is_serial_ready()) {
if (!isConsoleReady()) {
// we better do not read from USB serial before it is ready
chThdSleepMilliseconds(10);
continue;
@ -96,7 +98,9 @@ static msg_t consoleThreadThreadEntryPoint(void *arg) {
(console_line_callback)(consoleInput);
}
#if defined __GNUC__
return FALSE;
#endif
}
#if EFI_SERIAL_OVER_USB
@ -107,8 +111,8 @@ static SerialConfig serialConfig = {SERIAL_SPEED, 0, USART_CR2_STOP1_BITS | USAR
#endif /* EFI_SERIAL_OVER_USB */
#if ! EFI_SERIAL_OVER_USB && ! EFI_SIMULATOR
int is_serial_ready(void) {
return TRUE;
int isConsoleReady(void) {
return isSerialConsoleStarted;
}
#endif
@ -120,7 +124,7 @@ void consoleOutputBuffer(const int8_t *buf, int size) {
chSequentialStreamWrite(CONSOLE_CHANNEL, buf, size);
}
void startChibiosConsole(void (*console_line_callback_p)(char *)) {
void startConsole(void (*console_line_callback_p)(char *)) {
console_line_callback = console_line_callback_p;
#if EFI_SERIAL_OVER_USB
usb_serial_start();
@ -136,6 +140,8 @@ void startChibiosConsole(void (*console_line_callback_p)(char *)) {
// cannot use pin repository here because pin repository prints to console
palSetPadMode(EFI_CONSOLE_RX_PORT, EFI_CONSOLE_RX_PIN, PAL_MODE_ALTERNATE(EFI_CONSOLE_AF));
palSetPadMode(EFI_CONSOLE_TX_PORT, EFI_CONSOLE_TX_PIN, PAL_MODE_ALTERNATE(EFI_CONSOLE_AF));
isSerialConsoleStarted = TRUE;
#endif /* EFI_SERIAL_OVER_UART */
#endif /* EFI_SERIAL_OVER_USB */
chThdCreateStatic(consoleThreadStack, sizeof(consoleThreadStack), NORMALPRIO, consoleThreadThreadEntryPoint, NULL);
@ -143,9 +149,12 @@ void startChibiosConsole(void (*console_line_callback_p)(char *)) {
extern cnt_t dbg_isr_cnt;
int lockAnyContext(void) {
int is_locked = isLocked();
if (is_locked)
/**
* @return TRUE if already in locked context
*/
bool_t lockAnyContext(void) {
int alreadyLocked = isLocked();
if (alreadyLocked)
return TRUE;
if (isIsrContext()) {
chSysLockFromIsr()
@ -157,8 +166,8 @@ int lockAnyContext(void) {
return FALSE;
}
void lockOutputBuffer(void) {
lockAnyContext();
bool_t lockOutputBuffer(void) {
return lockAnyContext();
}
void unlockAnyContext(void) {

View File

@ -36,8 +36,8 @@ extern "C"
void consolePutChar(int x);
void consoleOutputBuffer(const int8_t *buf, int size);
void startChibiosConsole(void (*console_line_callback_p)(char *));
int is_serial_ready(void);
void startConsole(void (*console_line_callback_p)(char *));
int isConsoleReady(void);
#ifdef __cplusplus
}

View File

@ -57,6 +57,10 @@ static void sayHello(void) {
printMsg(&logger, "SERIAL_SPEED=%d", SERIAL_SPEED);
#endif
#ifdef CORTEX_MAX_KERNEL_PRIORITY
printMsg(&logger, "CORTEX_MAX_KERNEL_PRIORITY=%d", CORTEX_MAX_KERNEL_PRIORITY);
#endif
#ifdef STM32_ADCCLK
printMsg(&logger, "STM32_ADCCLK=%d", STM32_ADCCLK);
printMsg(&logger, "STM32_TIMCLK1=%d", STM32_TIMCLK1);
@ -136,7 +140,7 @@ void sendOutConfirmation(char *value, int i) {
* This methods prints the message to whatever is configured as our primary console
*/
void print(const char *format, ...) {
if (!is_serial_ready())
if (!isConsoleReady())
return;
va_list ap;
va_start(ap, format);
@ -148,7 +152,7 @@ void initializeConsole() {
initIntermediateLoggingBuffer();
initConsoleLogic();
startChibiosConsole(&handleConsoleLine);
startConsole(&handleConsoleLine);
initLogging(&logger, "console");

View File

@ -39,6 +39,10 @@
#include "mmc_card.h"
#include "console_io.h"
#define PRINT_FIRMWARE_ONCE TRUE
static bool_t firmwareErrorReported = FALSE;
#include "advance_map.h"
#if EFI_TUNER_STUDIO
#include "tunerstudio.h"
@ -83,7 +87,7 @@ static void setWarningEnabled(int value) {
static Logging fileLogger;
#endif /* EFI_FILE_LOGGING */
static void reportSensorF(char *caption, float value, int precision) {
static void reportSensorF(const char *caption, float value, int precision) {
#if EFI_PROD_CODE || EFI_SIMULATOR
debugFloat(&logger, caption, value, precision);
#endif /* EFI_PROD_CODE || EFI_SIMULATOR */
@ -125,7 +129,9 @@ void printSensors(void) {
if (engineConfiguration2->hasMapSensor) {
reportSensorF(getCaption(LP_MAP), getMap(), 2);
reportSensorF("map_r", getRawMap(), 2);
}
reportSensorF("baro", getBaroPressure(), 2);
reportSensorF("afr", getAfr(), 2);
reportSensorF("vref", getVRef(), 2);
@ -200,11 +206,7 @@ extern char *dbg_panic_file;
extern int dbg_panic_line;
#endif
void onDbgPanic(void) {
setOutputPinValue(LED_ERROR, 1);
}
int hasFatalError(void) {
bool_t hasFatalError(void) {
return dbg_panic_msg != NULL;
}
@ -236,31 +238,34 @@ static void printVersion(systime_t nowSeconds) {
if (overflowDiff(nowSeconds, timeOfPreviousPrintVersion) < 4)
return;
timeOfPreviousPrintVersion = nowSeconds;
appendPrintf(&logger, "rusEfiVersion%s%d@%d %s%s", DELIMETER, getRusEfiVersion(), SVN_VERSION, getConfigurationName(engineConfiguration),
appendPrintf(&logger, "rusEfiVersion%s%d@%d %s%s", DELIMETER, getRusEfiVersion(), SVN_VERSION,
getConfigurationName(engineConfiguration),
DELIMETER);
}
static systime_t timeOfPreviousReport = (systime_t) -1;
extern bool hasFirmwareError;
extern char errorMessageBuffer[200];
/**
* @brief Sends all pending data to dev console
*/
void updateDevConsoleState(void) {
if (!is_serial_ready())
if (!isConsoleReady())
return;
checkIfShouldHalt();
printPending();
pokeAdcInputs();
if (hasFirmwareError) {
printMsg(&logger, "firmware error: %s", errorMessageBuffer);
if (hasFirmwareError()) {
if (!firmwareErrorReported || !PRINT_FIRMWARE_ONCE)
printMsg(&logger, "firmware error: %s", errorMessageBuffer);
firmwareErrorReported = TRUE;
warningEnabled = FALSE;
return;
}
pokeAdcInputs();
if (!fullLog)
return;
@ -273,12 +278,10 @@ void updateDevConsoleState(void) {
timeOfPreviousReport = nowSeconds;
prevCkpEventCounter = currentCkpEventCounter;
printState(currentCkpEventCounter);
#if EFI_WAVE_ANALYZER
// printWave(&logger);
#endif
@ -321,7 +324,7 @@ void updateHD44780lcd(void) {
lcd_HD44780_print_char('R');
lcd_HD44780_set_position(0, 10);
char * ptr = itoa10((uint8_t*)buffer, getRpm());
char * ptr = itoa10((uint8_t*) buffer, getRpm());
ptr[0] = 0;
int len = ptr - buffer;
for (int i = 0; i < 6 - len; i++)
@ -329,7 +332,6 @@ void updateHD44780lcd(void) {
lcd_HD44780_print_string(buffer);
lcd_HD44780_set_position(2, 0);
lcd_HD44780_print_char('C');

View File

@ -23,8 +23,6 @@ void finishStatusLine(void);
void setFullLog(int value);
void startStatusThreads(void);
void sayOsHello(void);
int hasFatalError(void);
void onDbgPanic(void);
#ifdef __cplusplus
}

View File

@ -45,7 +45,7 @@ static Logging logger;
extern engine_configuration_s *engineConfiguration;
extern board_configuration_s *boardConfiguration;
extern persistent_config_s configWorkingCopy;
extern FlashState flashState;
extern persistent_config_container_s persistentState;
extern SerialUSBDriver SDU1;
#define CONSOLE_DEVICE &SDU1
@ -195,10 +195,10 @@ void handleBurnCommand(void) {
#endif
// todo: how about some multi-threading?
memcpy(&flashState.persistentConfiguration, &configWorkingCopy, sizeof(persistent_config_s));
memcpy(&persistentState.persistentConfiguration, &configWorkingCopy, sizeof(persistent_config_s));
scheduleMsg(&logger, "va1=%d", configWorkingCopy.boardConfiguration.idleValvePin);
scheduleMsg(&logger, "va2=%d", flashState.persistentConfiguration.boardConfiguration.idleValvePin);
scheduleMsg(&logger, "va2=%d", persistentState.persistentConfiguration.boardConfiguration.idleValvePin);
writeToFlash();
incrementGlobalConfigurationVersion();
@ -236,7 +236,7 @@ static msg_t tsThreadEntryPoint(void *arg) {
extern engine_configuration_s *engineConfiguration;
void syncTunerStudioCopy(void) {
memcpy(&configWorkingCopy, &flashState.persistentConfiguration, sizeof(persistent_config_s));
memcpy(&configWorkingCopy, &persistentState.persistentConfiguration, sizeof(persistent_config_s));
}
void startTunerStudioConnectivity(void) {
@ -268,7 +268,7 @@ void updateTunerStudioState() {
tsOutputChannels.air_fuel_ratio = getAfr();
tsOutputChannels.v_batt = getVBatt();
tsOutputChannels.tpsADC = getTPS10bitAdc();
tsOutputChannels.atmospherePressure = getAtmosphericPressure();
tsOutputChannels.atmospherePressure = getBaroPressure();
tsOutputChannels.manifold_air_pressure = getMap();
tsOutputChannels.checkEngine = hasErrorCodes();
}

View File

@ -50,7 +50,11 @@
/**
* This is the buffer into which all the data providers write
*/
#if defined __GNUC__
static char pendingBuffer[OUTPUT_BUFFER] __attribute__((section(".ccm")));
#else
static char pendingBuffer[OUTPUT_BUFFER];
#endif
/**
* We copy all the pending data into this buffer once we are ready to push it out
*/
@ -60,13 +64,9 @@ static MemoryStream intermediateLoggingBuffer;
static uint8_t intermediateLoggingBufferData[INTERMEDIATE_LOGGING_BUFFER_SIZE]; //todo define max-printf-buffer
static bool intermediateLoggingBufferInited = FALSE;
static int validateBuffer(Logging *logging, int extraLen, char *text) {
static int validateBuffer(Logging *logging, int extraLen, const char *text) {
if (logging->buffer == NULL) {
strcpy(logging->SMALL_BUFFER, "Logging not initialized: ");
strcat(logging->SMALL_BUFFER, logging->name);
strcat(logging->SMALL_BUFFER, "/");
strcat(logging->SMALL_BUFFER, text);
fatal(logging->SMALL_BUFFER);
firmwareError("Logging not initialized: %s", logging->name);
return TRUE;
}
@ -84,7 +84,7 @@ static int validateBuffer(Logging *logging, int extraLen, char *text) {
return FALSE;
}
void append(Logging *logging, char *text) {
void append(Logging *logging, const char *text) {
chDbgCheck(text!=NULL, "append NULL");
int extraLen = strlen(text);
int errcode = validateBuffer(logging, extraLen, text);
@ -181,7 +181,7 @@ static char* get2ndCaption(int loggingPoint) {
}
void initLoggingExt(Logging *logging, const char *name, char *buffer, int bufferSize) {
print("Init logging\r\n");
print("Init logging %s\r\n", name);
logging->name = name;
logging->buffer = buffer;
logging->bufferSize = bufferSize;
@ -197,7 +197,7 @@ void initLogging(Logging *logging, const char *name) {
initLoggingExt(logging, name, logging->DEFAULT_BUFFER, sizeof(logging->DEFAULT_BUFFER));
}
void debugInt(Logging *logging, char *caption, int value) {
void debugInt(Logging *logging, const char *caption, int value) {
append(logging, caption);
append(logging, DELIMETER);
appendPrintf(logging, "%d%s", value, DELIMETER);
@ -207,30 +207,30 @@ void appendFloat(Logging *logging, float value, int precision) {
// todo: this implementation is less than perfect
switch (precision) {
case 1:
appendPrintf(logging, "%..10f", value);
break;
appendPrintf(logging, "%..10f", value);
break;
case 2:
appendPrintf(logging, "%..100f", value);
break;
appendPrintf(logging, "%..100f", value);
break;
case 3:
appendPrintf(logging, "%..1000f", value);
break;
appendPrintf(logging, "%..1000f", value);
break;
case 4:
appendPrintf(logging, "%..10000f", value);
break;
appendPrintf(logging, "%..10000f", value);
break;
case 5:
appendPrintf(logging, "%..100000f", value);
break;
appendPrintf(logging, "%..100000f", value);
break;
case 6:
appendPrintf(logging, "%..1000000f", value);
break;
appendPrintf(logging, "%..1000000f", value);
break;
default:
appendPrintf(logging, "%f", value);
appendPrintf(logging, "%f", value);
}
}
void debugFloat(Logging *logging, char *caption, float value, int precision) {
void debugFloat(Logging *logging, const char *caption, float value, int precision) {
append(logging, caption);
append(logging, DELIMETER);
@ -265,10 +265,10 @@ static void printWithLength(char *line) {
*p++ = '\r';
*p++ = '\n';
if (!is_serial_ready())
if (!isConsoleReady())
return;
consoleOutputBuffer((const int8_t *)header, strlen(header));
consoleOutputBuffer((const int8_t *)line, p - line);
consoleOutputBuffer((const int8_t *) header, strlen(header));
consoleOutputBuffer((const int8_t *) line, p - line);
}
void printLine(Logging *logging) {
@ -286,7 +286,10 @@ void appendMsgPostfix(Logging *logging) {
void resetLogging(Logging *logging) {
char *buffer = logging->buffer;
chDbgCheck(buffer!=NULL, "null buffer");
if (buffer == NULL) {
firmwareError("Null buffer: %s", logging->name);
return;
}
logging->linePointer = buffer;
}
@ -336,7 +339,7 @@ void scheduleLogging(Logging *logging) {
// this could be done without locking
int newLength = strlen(logging->buffer);
lockOutputBuffer();
bool_t alreadyLocked = lockOutputBuffer();
// I hope this is fast enough to operate under sys lock
int curLength = strlen(pendingBuffer);
if (curLength + newLength >= OUTPUT_BUFFER) {
@ -348,13 +351,15 @@ void scheduleLogging(Logging *logging) {
// strcpy(fatalMessage, "datalogging.c: output buffer overflow: ");
// strcat(fatalMessage, logging->name);
// fatal(fatalMessage);
unlockOutputBuffer();
if (!alreadyLocked)
unlockOutputBuffer();
resetLogging(logging);
return;
}
strcat(pendingBuffer, logging->buffer);
unlockOutputBuffer();
if (!alreadyLocked)
unlockOutputBuffer();
resetLogging(logging);
}
@ -376,7 +381,6 @@ void printPending() {
printWithLength(outputBuffer);
}
void initIntermediateLoggingBuffer(void) {
msObjectInit(&intermediateLoggingBuffer, intermediateLoggingBufferData, INTERMEDIATE_LOGGING_BUFFER_SIZE, 0);
intermediateLoggingBufferInited = TRUE;

View File

@ -43,8 +43,7 @@ extern "C"
{
#endif /* __cplusplus */
void lockOutputBuffer(void);
bool_t lockOutputBuffer(void);
void unlockOutputBuffer(void);
void initIntermediateLoggingBuffer(void);
@ -55,10 +54,10 @@ int isInitialized(Logging *logging);
void initLogging(Logging *logging, const char *name);
void initLoggingExt(Logging *logging, const char *name, char *buffer, int bufferSize);
void debugInt(Logging *logging, char *caption, int value);
void debugInt(Logging *logging, const char *caption, int value);
void logInt(Logging *logging, LoggingPoints loggingPoint, int value);
void debugFloat(Logging *logging, char *text, float value, int precision);
void debugFloat(Logging *logging, const char *text, float value, int precision);
void logFloat(Logging *logging, LoggingPoints loggingPoint, float value);
void appendFloat(Logging *logging, float value, int precision);
@ -74,7 +73,7 @@ void printMsg(Logging *logging, const char *fmt, ...);
char* getCaption(LoggingPoints loggingPoint);
void appendPrintf(Logging *logging, const char *fmt, ...);
void vappendPrintf(Logging *logging, const char *fmt, va_list arg);
void append(Logging *logging, char *text);
void append(Logging *logging, const char *text);
/**
* this method copies the line into the intermediate buffer for later output by
* the main thread

View File

@ -129,6 +129,7 @@ void chVTSetAny(VirtualTimer *vtp, systime_t time, vtfunc_t vtfunc, void *par) {
* @brief This function knows how to print a histogram_s summary
*/
void printHistogram(Logging *logging, histogram_s *histogram) {
#if EFI_HISTOGRAMS
int report[5];
int len = hsReport(histogram, report);
@ -140,4 +141,5 @@ void printHistogram(Logging *logging, histogram_s *histogram) {
appendPrintf(logging, "*");
appendMsgPostfix(logging);
scheduleLogging(logging);
#endif /* EFI_HISTOGRAMS */
}

View File

@ -1,13 +1,14 @@
/**
* @file PwmTester.cpp
* This is a tool to measure rusEfi PWM generation quality
*
* @date Apr 29, 2014
* @author Andrey Belomutskiy, (c) 2012-2013
* @author Andrey Belomutskiy, (c) 2012-2014
*/
#include "main.h"
#include "PwmTester.h"
#include "trigger_structure.h"
#include "EfiWave.h"
#include "pwm_generator_logic.h"
#include "engine_configuration.h"
#include "pwm_generator.h"
@ -21,7 +22,8 @@ static int pinStates[2];
static single_wave_s wave(pinStates);
static single_wave_s sr[1] = { wave };
static PwmConfig pwmTest[4] = { PwmConfig(_switchTimes, sr),
static PwmConfig pwmTest[5] = { PwmConfig(_switchTimes, sr),
PwmConfig(_switchTimes, sr),
PwmConfig(_switchTimes, sr),
PwmConfig(_switchTimes, sr),
PwmConfig(_switchTimes, sr)};
@ -31,17 +33,25 @@ extern board_configuration_s *boardConfiguration;
static void startPwmTest(int freq) {
scheduleMsg(&logger, "running pwm test @%d", freq);
startSimplePwm(&pwmTest[0], "tester", boardConfiguration->injectionPins[0],
INJECTOR_1_OUTPUT, 0.5, freq / 1000, FALSE);
startSimplePwm(&pwmTest[1], "tester", boardConfiguration->injectionPins[1],
INJECTOR_2_OUTPUT, 0.5, freq / 100, FALSE);
startSimplePwm(&pwmTest[2], "tester", boardConfiguration->injectionPins[2],
// PD13, GPIO_NONE because pin is initialized elsewhere already
startSimplePwm(&pwmTest[0], "tester", GPIO_NONE,
LED_CRANKING, 0.5, 10, FALSE);
// currently this is PB9 by default
startSimplePwm(&pwmTest[1], "tester", boardConfiguration->injectionPins[0],
INJECTOR_1_OUTPUT, 0.5, freq / 1.3333333333, FALSE);
// currently this is PB8 by default
startSimplePwm(&pwmTest[2], "tester", GPIO_NONE,
INJECTOR_2_OUTPUT, 0.5, freq / 1000, FALSE);
// currently this is PE3 by default
startSimplePwm(&pwmTest[3], "tester", GPIO_NONE,
INJECTOR_3_OUTPUT, 0.5, freq, FALSE);
startSimplePwm(&pwmTest[3], "tester", boardConfiguration->injectionPins[3],
INJECTOR_4_OUTPUT, 0.5, freq / 33.3, FALSE);
// currently this is PE5 by default
startSimplePwm(&pwmTest[4], "tester", GPIO_NONE,
INJECTOR_4_OUTPUT, 0.5, freq / 33.33333333333, FALSE);
}
void initPwmTester(void) {
initLogging(&logger, "pwm test");
addConsoleActionI("pwmtest", startPwmTest);
// un-comment this to start pwm test on start up startPwmTest(1000);
}

View File

@ -2,7 +2,7 @@
* @file PwmTester.h
*
* @date Apr 29, 2014
* @author Andrey Belomutskiy, (c) 2012-2013
* @author Andrey Belomutskiy, (c) 2012-2014
*/
#ifndef PWMTESTER_H_
#define PWMTESTER_H_

View File

@ -18,12 +18,12 @@ extern engine_configuration_s *engineConfiguration;
static AccelEnrichmemnt instance;
void AccelEnrichmemnt::updateDiffEnrichment(engine_configuration_s *engineConfiguration, float engineLoad) {
for (int i = 0; i == 4; i++) {
engineLoadD[i] = engineLoadD[i + 1];
for (int i = 1; i < 4; i++) {
engineLoadD[i] = engineLoadD[i - 1];
}
engineLoadD[0] = engineLoad;
float Dcurr = engineLoadD[1] - engineLoadD[0];
float Dold = engineLoadD[3] - engineLoadD[2];
float Dcurr = engineLoadD[0] - engineLoadD[1];
float Dold = engineLoadD[2] - engineLoadD[3];
diffEnrichment = ((3 * Dcurr + Dold) / 4) * (engineConfiguration->diffLoadEnrichmentCoef);
}

View File

@ -34,6 +34,8 @@ static int initialized = FALSE;
float getBaseAdvance(int rpm, float engineLoad) {
chDbgAssert(initialized, "fuel map initialized", NULL);
efiAssert(!cisnan(engineLoad), "invalid el");
efiAssert(!cisnan(engineLoad), "invalid rpm");
return interpolate3d(engineLoad, engineConfiguration->ignitionLoadBins, AD_LOAD_COUNT, rpm,
engineConfiguration->ignitionRpmBins,
AD_RPM_COUNT, timing_ptrs);

View File

@ -2,7 +2,6 @@
CONTROLLERS_ALGO_SRC = $(PROJECT_DIR)/controllers/algo/map_adjuster.c \
$(PROJECT_DIR)/controllers/algo/advance_map.c \
$(PROJECT_DIR)/controllers/algo/signal_executor.c \
$(PROJECT_DIR)/controllers/algo/interpolation.c \
$(PROJECT_DIR)/controllers/algo/malfunction_central.c \
$(PROJECT_DIR)/controllers/algo/event_registry.c \
$(PROJECT_DIR)/controllers/algo/idle_controller.c \
@ -13,6 +12,5 @@ CONTROLLERS_ALGO_SRC_CPP = $(PROJECT_DIR)/controllers/algo/OutputSignalArray.cpp
$(PROJECT_DIR)/controllers/algo/fuel_math.cpp \
$(PROJECT_DIR)/controllers/algo/accel_enrichment.cpp \
$(PROJECT_DIR)/controllers/algo/engine_configuration.cpp \
$(PROJECT_DIR)/controllers/algo/algo.cpp \
$(PROJECT_DIR)/controllers/algo/event_queue.cpp
$(PROJECT_DIR)/controllers/algo/algo.cpp

View File

@ -1,11 +1,12 @@
/**
* ec2.h
* @file ec2.h
*
* this is a mess because some code is still in C and some is
* already in C++. trigger structure is C++
* TODO: rename? merge? Do something with this file
*
* Created on: Apr 26, 2014
* Author: Andrey
* @date Apr 26, 2014
* @author Andrey Belomutskiy, (c) 2012-2014
*/
#ifndef EC2_H_
@ -46,18 +47,16 @@ public:
void prepareOutputSignals(engine_configuration_s *engineConfiguration,
engine_configuration2_s *engineConfiguration2);
void initializeIgnitionActions(float baseAngle, engine_configuration_s *engineConfiguration, engine_configuration2_s *engineConfiguration2);
void initializeIgnitionActions(float baseAngle, engine_configuration_s *engineConfiguration, engine_configuration2_s *engineConfiguration2, float dwellMs, ActuatorEventList *list);
void addFuelEvents(engine_configuration_s const *e, engine_configuration2_s *engineConfiguration2, ActuatorEventList *list, injection_mode_e mode);
void registerActuatorEventExt(engine_configuration_s const *engineConfiguration, trigger_shape_s * s, ActuatorEventList *list, OutputSignal *actuator, float angleOffset);
void resetConfigurationExt(engine_type_e engineType,
void resetConfigurationExt(Logging * logger, engine_type_e engineType,
engine_configuration_s *engineConfiguration,
engine_configuration2_s *engineConfiguration2,
board_configuration_s *boardConfiguration);
void applyNonPersistentConfiguration(engine_configuration_s *engineConfiguration,
void applyNonPersistentConfiguration(Logging * logger, engine_configuration_s *engineConfiguration,
engine_configuration2_s *engineConfiguration2, engine_type_e engineType);

View File

@ -31,7 +31,6 @@
#include "tunerstudio.h"
#endif
#include "audi_aan.h"
#include "dodge_neon.h"
#include "ford_aspire.h"
@ -48,8 +47,6 @@
#include "ford_escort_gt.h"
#include "citroenBerlingoTU3JP.h"
#define ADC_CHANNEL_FAST_ADC 256
static volatile int globalConfigurationVersion = 0;
int getGlobalConfigurationVersion(void) {
@ -60,7 +57,6 @@ void incrementGlobalConfigurationVersion(void) {
globalConfigurationVersion++;
}
/**
* @brief Sets the same dwell time across the whole getRpm() range
*/
@ -94,8 +90,7 @@ void setWholeFuelMap(engine_configuration_s *engineConfiguration, float value) {
* This method sets the default global engine configuration. These values are later overridden by engine-specific defaults
* and the settings saves in flash memory.
*/
void setDefaultConfiguration(engine_configuration_s *engineConfiguration,
board_configuration_s *boardConfiguration) {
void setDefaultConfiguration(engine_configuration_s *engineConfiguration, board_configuration_s *boardConfiguration) {
memset(engineConfiguration, 0, sizeof(engine_configuration_s));
memset(boardConfiguration, 0, sizeof(board_configuration_s));
@ -136,14 +131,14 @@ void setDefaultConfiguration(engine_configuration_s *engineConfiguration,
setTimingLoadBin(engineConfiguration, 1.2, 4.4);
setTimingRpmBin(engineConfiguration, 800, 7000);
setTableBin(engineConfiguration->map.config.samplingAngleBins, MAP_ANGLE_SIZE, 800, 7000);
setTableBin(engineConfiguration->map.config.samplingWindowBins, MAP_ANGLE_SIZE, 800, 7000);
setTableBin(engineConfiguration->map.samplingAngleBins, MAP_ANGLE_SIZE, 800, 7000);
setTableBin(engineConfiguration->map.samplingWindowBins, MAP_ANGLE_SIZE, 800, 7000);
// set_whole_timing_map 3
setWholeFuelMap(engineConfiguration, 3);
setThermistorConfiguration(&engineConfiguration->cltThermistorConf, 0, 9500, 23.8889, 2100, 48.8889, 1000);
engineConfiguration->cltThermistorConf.bias_resistor = 1500;
engineConfiguration->cltThermistorConf.bias_resistor = 1500;
setThermistorConfiguration(&engineConfiguration->iatThermistorConf, 32, 9500, 75, 2100, 120, 1000);
// todo: this value is way off! I am pretty sure temp coeffs are off also
@ -160,7 +155,6 @@ void setDefaultConfiguration(engine_configuration_s *engineConfiguration,
engineConfiguration->crankingSettings.coolantTempMinC = -40; // 6ms at -40C
engineConfiguration->crankingSettings.fuelAtMinTempMs = 6;
engineConfiguration->analogInputDividerCoefficient = 2;
engineConfiguration->crankingChargeAngle = 70;
@ -169,7 +163,8 @@ void setDefaultConfiguration(engine_configuration_s *engineConfiguration,
engineConfiguration->analogChartMode = AC_TRIGGER;
engineConfiguration->map.channel = ADC_CHANNEL_FAST_ADC;
engineConfiguration->map.sensor.hwChannel = 4;
engineConfiguration->baroSensor.hwChannel = 4;
engineConfiguration->firingOrder = FO_1_THEN_3_THEN_4_THEN2;
engineConfiguration->crankingInjectionMode = IM_SIMULTANEOUS;
@ -184,7 +179,7 @@ void setDefaultConfiguration(engine_configuration_s *engineConfiguration,
engineConfiguration->engineLoadMode = LM_MAF;
engineConfiguration->vbattDividerCoeff = ((float)(15 + 65)) / 15;
engineConfiguration->vbattDividerCoeff = ((float) (15 + 65)) / 15;
engineConfiguration->fanOnTemperature = 75;
engineConfiguration->fanOffTemperature = 70;
@ -203,7 +198,6 @@ void setDefaultConfiguration(engine_configuration_s *engineConfiguration,
engineConfiguration->rpmMultiplier = 0.5;
engineConfiguration->cylindersCount = 4;
engineConfiguration->displayMode = DM_HD44780;
engineConfiguration->logFormat = LF_NATIVE;
@ -214,11 +208,9 @@ void setDefaultConfiguration(engine_configuration_s *engineConfiguration,
engineConfiguration->triggerConfig.isSynchronizationNeeded = TRUE;
engineConfiguration->triggerConfig.useRiseEdge = TRUE;
engineConfiguration->HD44780width = 16;
engineConfiguration->HD44780height = 2;
engineConfiguration->tpsAdcChannel = 3;
engineConfiguration->vBattAdcChannel = 5;
engineConfiguration->cltAdcChannel = 6;
@ -232,9 +224,11 @@ void setDefaultConfiguration(engine_configuration_s *engineConfiguration,
engineConfiguration->needSecondTriggerInput = TRUE;
engineConfiguration->map.config.mapType = MT_CUSTOM;
engineConfiguration->map.config.Min = 0;
engineConfiguration->map.config.Max = 500;
engineConfiguration->map.sensor.sensorType = MT_MPX4250;
engineConfiguration->baroSensor.sensorType = MT_CUSTOM;
engineConfiguration->baroSensor.Min = 0;
engineConfiguration->baroSensor.Max = 500;
engineConfiguration->diffLoadEnrichmentCoef = 1;
@ -278,6 +272,25 @@ void setDefaultConfiguration(engine_configuration_s *engineConfiguration,
boardConfiguration->HD44780_db5 = GPIOE_15;
boardConfiguration->HD44780_db6 = GPIOB_11;
boardConfiguration->HD44780_db7 = GPIOB_13;
memset(boardConfiguration->adcHwChannelEnabled, 0, sizeof(boardConfiguration->adcHwChannelEnabled));
boardConfiguration->adcHwChannelEnabled[0] = ADC_SLOW;
boardConfiguration->adcHwChannelEnabled[1] = ADC_SLOW;
boardConfiguration->adcHwChannelEnabled[2] = ADC_SLOW;
boardConfiguration->adcHwChannelEnabled[3] = ADC_SLOW;
boardConfiguration->adcHwChannelEnabled[4] = ADC_FAST;
boardConfiguration->adcHwChannelEnabled[6] = ADC_SLOW;
boardConfiguration->adcHwChannelEnabled[7] = ADC_SLOW;
boardConfiguration->adcHwChannelEnabled[11] = ADC_SLOW;
boardConfiguration->adcHwChannelEnabled[12] = ADC_SLOW;
boardConfiguration->adcHwChannelEnabled[13] = ADC_SLOW;
boardConfiguration->primaryTriggerInputPin = GPIOC_6;
boardConfiguration->secondaryTriggerInputPin = GPIOA_5;
boardConfiguration->primaryLogicAnalyzerPin = GPIOA_8;
boardConfiguration->secondaryLogicAnalyzerPin = GPIOE_7;
}
void setDefaultNonPersistentConfiguration(engine_configuration2_s *engineConfiguration2) {
@ -290,10 +303,8 @@ void setDefaultNonPersistentConfiguration(engine_configuration2_s *engineConfigu
engineConfiguration2->hasCltSensor = TRUE;
}
void resetConfigurationExt(engine_type_e engineType,
engine_configuration_s *engineConfiguration,
engine_configuration2_s *engineConfiguration2,
board_configuration_s *boardConfiguration) {
void resetConfigurationExt(Logging * logger, engine_type_e engineType, engine_configuration_s *engineConfiguration,
engine_configuration2_s *engineConfiguration2, board_configuration_s *boardConfiguration) {
/**
* Let's apply global defaults first
*/
@ -356,7 +367,7 @@ void resetConfigurationExt(engine_type_e engineType,
firmwareError("Unexpected engine type: %d", engineType);
}
applyNonPersistentConfiguration(engineConfiguration, engineConfiguration2, engineType);
applyNonPersistentConfiguration(logger, engineConfiguration, engineConfiguration2, engineType);
#if EFI_TUNER_STUDIO
syncTunerStudioCopy();
@ -366,18 +377,27 @@ void resetConfigurationExt(engine_type_e engineType,
engine_configuration2_s::engine_configuration2_s() {
}
void applyNonPersistentConfiguration(engine_configuration_s *engineConfiguration, engine_configuration2_s *engineConfiguration2, engine_type_e engineType) {
void applyNonPersistentConfiguration(Logging * logger, engine_configuration_s *engineConfiguration,
engine_configuration2_s *engineConfiguration2, engine_type_e engineType) {
// todo: this would require 'initThermistors() to re-establish a reference, todo: fix
// memset(engineConfiguration2, 0, sizeof(engine_configuration2_s));
#if EFI_PROD_CODE
printMsg(logger, "applyNonPersistentConfiguration()");
#endif
engineConfiguration2->isInjectionEnabledFlag = TRUE;
initializeTriggerShape(engineConfiguration, engineConfiguration2);
chDbgCheck(engineConfiguration2->triggerShape.size != 0, "size is zero");
chDbgCheck(engineConfiguration2->triggerShape.shaftPositionEventCount, "shaftPositionEventCount is zero");
initializeTriggerShape(logger, engineConfiguration, engineConfiguration2);
if (engineConfiguration2->triggerShape.getSize() == 0) {
firmwareError("size is zero");
return;
}
if (engineConfiguration2->triggerShape.shaftPositionEventCount == 0) {
firmwareError("shaftPositionEventCount is zero");
return;
}
prepareOutputSignals(engineConfiguration, engineConfiguration2);
initializeIgnitionActions(0, engineConfiguration, engineConfiguration2);
// todo: looks like this is here only for unit tests. todo: remove
initializeIgnitionActions(0, engineConfiguration, engineConfiguration2, 0, &engineConfiguration2->engineEventConfiguration.ignitionEvents[0]);
}

View File

@ -10,6 +10,7 @@
#define ENGINE_CONFIGURATION_H_
#include "efifeatures.h"
#include "crc.h"
#include "sensor_types.h"
#include "can_header.h"
#include "event_registry.h"
@ -34,7 +35,7 @@ typedef struct {
typedef struct {
ActuatorEventList crankingInjectionEvents;
ActuatorEventList injectionEvents;
ActuatorEventList ignitionEvents;
ActuatorEventList ignitionEvents[2];
} EventHandlerConfiguration;
#define FUEL_RPM_COUNT 16
@ -135,7 +136,7 @@ typedef struct {
cranking_parameters_s crankingSettings;
map_s map;
MAP_sensor_config_s map;
// todo: merge with channel settings, use full-scale Thermistor here!
ThermistorConf cltThermistorConf; // size 40 (10*4), offset 336
@ -267,8 +268,12 @@ typedef struct {
float crankingTimingAngle;
float diffLoadEnrichmentCoef;
air_pressure_sensor_config_s baroSensor;
} engine_configuration_s;
#define HW_MAX_ADC_INDEX 16
typedef struct {
// WARNING: by default, our small enums are ONE BYTE. this one is made 4-byte with the 'ENUM_SIZE_HACK' hack
brain_pin_e idleValvePin;
@ -314,6 +319,12 @@ typedef struct {
spi_device_e digitalPotentiometerSpiDevice;
brain_pin_e digitalPotentiometerChipSelect[4];
adc_channel_mode_e adcHwChannelEnabled[HW_MAX_ADC_INDEX];
brain_pin_e primaryTriggerInputPin;
brain_pin_e secondaryTriggerInputPin;
brain_pin_e primaryLogicAnalyzerPin;
brain_pin_e secondaryLogicAnalyzerPin;
} board_configuration_s;
@ -322,6 +333,12 @@ typedef struct {
board_configuration_s boardConfiguration;
} persistent_config_s;
typedef struct {
int version;
int size;
persistent_config_s persistentConfiguration;
crc_t value;
} persistent_config_container_s;
#ifdef __cplusplus
extern "C" {

View File

@ -14,6 +14,7 @@ extern "C"
#endif /* __cplusplus */
#include "obd_error_codes.h"
#include "stdbool.h"
/**
* Something is wrong, but we can live with it: some minor sensor is disconnected
@ -27,8 +28,9 @@ int warning(obd_code_e code, const char *fmt, ...);
* todo: better method name?
*/
void firmwareError(const char *fmt, ...);
bool_t hasFirmwareError(void);
int hasFatalError(void);
bool_t hasFatalError(void);
void fatal3(char *msg, char *file, int line);
#define fatal(x) (fatal3(x, __FILE__, __LINE__));
@ -39,6 +41,10 @@ void initErrorHandling(void);
// todo: better place for this shared declaration?
int getRusEfiVersion(void);
/**
* @deprecated Global panic is inconvenient because it's hard to deliver the error message while whole instance
* is stopped. Please use firmwareWarning() instead
*/
#define efiAssert(x, y) chDbgAssert(x, y, NULL)
#ifdef __cplusplus

View File

@ -1,89 +0,0 @@
/**
* @file event_queue.cpp
* This is a data structure which keeps track of all pending events
* Implemented as a linked list, which is fine since the number of
* pending events is pretty low
* todo: MAYBE migrate to a better data structure, but that's low priority
*
* this data structure is NOT thread safe
*
* @date Apr 17, 2014
* @author Andrey Belomutskiy, (c) 2012-2014
*/
#include "event_queue.h"
#include "efitime.h"
#include "utlist.h"
EventQueue::EventQueue() {
head = NULL;
}
void EventQueue::insertTask(scheduling_s *scheduling, uint64_t nowUs, int delayUs, schfunc_t callback, void *param) {
if (callback == NULL)
firmwareError("NULL callback");
uint64_t time = nowUs + delayUs;
scheduling->momentUs = time;
#if EFI_SIGNAL_EXECUTOR_ONE_TIMER
scheduling->callback = callback;
scheduling->param = param;
#endif
scheduling_s * elt;
LL_FOREACH(head, elt)
{
if (elt == scheduling) {
firmwareError("re-adding element");
return;
}
}
LL_PREPEND(head, scheduling);
}
void EventQueue::insertTask(scheduling_s *scheduling, int delayUs, schfunc_t callback, void *param) {
insertTask(scheduling, getTimeNowUs(), delayUs, callback, param);
}
/**
* Get the timestamp of the soonest pending action
*/
uint64_t EventQueue::getNextEventTime(uint64_t nowUs) {
scheduling_s * elt;
// this is a large value which is expected to be larger than any real time
uint64_t result = EMPTY_QUEUE;
LL_FOREACH(head, elt)
{
if (elt->momentUs <= nowUs) {
// todo: I am not so sure about this branch
continue;
}
if (elt->momentUs < result)
result = elt->momentUs;
}
return result;
}
/**
* Invoke all pending actions prior to specified timestamp
*/
void EventQueue::executeAll(uint64_t now) {
scheduling_s * elt, *tmp;
// here we need safe iteration because we are removing elements
LL_FOREACH_SAFE(head, elt, tmp)
{
if (elt->momentUs <= now) {
LL_DELETE(head, elt);
#if EFI_SIGNAL_EXECUTOR_ONE_TIMER
elt->callback(elt->param);
#endif /* EFI_SIGNAL_EXECUTOR_ONE_TIMER */
}
}
}
void EventQueue::clear(void) {
head = NULL;
}

View File

@ -36,7 +36,9 @@
#include "allsensors.h"
#include "engine_math.h"
#include "rpm_calculator.h"
#if EFI_ACCEL_ENRICHMENT
#include "accel_enrichment.h"
#endif /* EFI_ACCEL_ENRICHMENT */
static float *fuel_ptrs[FUEL_LOAD_COUNT];
static int initialized = FALSE;
@ -85,6 +87,8 @@ float getInjectorLag(float vBatt) {
float getBaseFuel(int rpm, float engineLoad) {
chDbgCheck(initialized, "fuel map initialized");
efiAssert(!cisnan(engineLoad), "invalid el");
efiAssert(!cisnan(engineLoad), "invalid rpm");
return interpolate3d(engineLoad, engineConfiguration->fuelLoadBins, FUEL_LOAD_COUNT, rpm,
engineConfiguration->fuelRpmBins, FUEL_RPM_COUNT, fuel_ptrs);
}
@ -116,8 +120,10 @@ float getRunningFuel(int rpm, float engineLoad) {
float cltCorrection = getCltCorrection(getCoolantTemperature());
float injectorLag = getInjectorLag(getVBatt());
#if EFI_ACCEL_ENRICHMENT
float accelEnrichment = getAccelEnrichment();
// todo: accelEnrichment
#endif /* EFI_ACCEL_ENRICHMENT */
return baseFuel * cltCorrection * iatCorrection + injectorLag;
}

View File

@ -14,6 +14,7 @@
*/
#include "idle_controller.h"
#include "efilib.h"
// todo: move this to "idle_controller.h"
int isCranking(void);
@ -31,25 +32,12 @@ void setIdleRpm(IdleValveState *idle, int targetRpm) {
idle->targetRpmRangeRight = (int)(targetRpm * 1.07);
}
int min(int i1, int i2) {
return i1 < i2 ? i1 : i2;
}
int max(int i1, int i2) {
return i1 > i2 ? i1 : i2;
}
float maxF(float i1, float i2) {
return i1 > i2 ? i1 : i2;
}
/**
* @brief sets new idle valve duty cycle: checks the bounds and reports new value
*/
static int setNewValue(IdleValveState *idle, int currentRpm, int now, char * msg, int newValue) {
newValue = max(newValue, MIN_IDLE);
newValue = min(newValue, MAX_IDLE);
newValue = maxI(newValue, MIN_IDLE);
newValue = minI(newValue, MAX_IDLE);
if (idle->value != newValue) {
idleDebug(msg, currentRpm);

View File

@ -41,10 +41,6 @@ void idleInit(IdleValveState *idle);
int getIdle(IdleValveState *idle, int currentRpm, int time);
void setIdleRpm(IdleValveState *idle, int targetRpm);
// todo: move these somewhere else!
int max(int i1, int i2);
int min(int i1, int i2);
float maxF(float i1, float i2);
void idleDebug(char *msg, int value);
#ifdef __cplusplus

View File

@ -38,7 +38,7 @@ void removeError(obd_code_e errorCode) {
if (pos >= 0) {
for (int t = pos; t < error_codes_set.count; t++) // shift all right elements to one pos left
error_codes_set.error_codes[t] = error_codes_set.error_codes[t + 1];
error_codes_set.error_codes[--error_codes_set.count] = 0; // place 0
error_codes_set.error_codes[--error_codes_set.count] = (obd_code_e)0; // place 0
}
}

View File

@ -359,7 +359,7 @@ typedef enum {
//P0338 Crankshaft Position Sensor A Circuit High Input
//P0339 Crankshaft Position Sensor A Circuit Intermittent
//P0340 Camshaft Position Sensor Circuit Malfunction
//P0341 Camshaft Position Sensor Circuit Range/Performance
OBD_Camshaft_Position_Sensor_Circuit_Range_Performance = 341,
//P0342 Camshaft Position Sensor Circuit Low Input
//P0343 Camshaft Position Sensor Circuit High Input
//P0344 Camshaft Position Sensor Circuit Intermittent

View File

@ -84,6 +84,14 @@ typedef enum {
Internal_ForceMyEnumIntSize_trigger_type = ENUM_SIZE_HACK,
} trigger_type_e;
typedef enum {
ADC_OFF = 0,
ADC_SLOW = 1,
ADC_FAST = 2,
Internal_ForceMyEnumIntSize_adc_channel_mode = ENUM_SIZE_HACK,
} adc_channel_mode_e;
typedef enum {
SHAFT_PRIMARY_UP = 0,
SHAFT_PRIMARY_DOWN = 1,
@ -315,6 +323,6 @@ typedef enum {
MT_MPX4250 = 2,
Internal_ForceMyEnumIntSize_cranking_map_type = ENUM_SIZE_HACK,
} map_type_e;
} air_pressure_sensor_type_e;
#endif /* RUSEFI_ENUMS_H_ */

View File

@ -39,7 +39,7 @@
#endif /* EFI_WAVE_ANALYZER */
#if EFI_PROD_CODE || EFI_SIMULATOR
static Logging logger;
static Logging logger;
#endif
void initSignalExecutor(void) {
@ -49,6 +49,12 @@ void initSignalExecutor(void) {
initSignalExecutorImpl();
}
void initOutputSignal(OutputSignal *signal, io_pin_e ioPin) {
signal->io_pin = ioPin;
signal->name = getPinName(ioPin);
initOutputSignalBase(signal);
}
void initOutputSignalBase(OutputSignal *signal) {
signal->status = IDLE;
// signal->last_scheduling_time = 0;
@ -66,9 +72,7 @@ static void turnHigh(OutputSignal *signal) {
// sleep for the needed duration
#if EFI_PROD_CODE || EFI_SIMULATOR
if(
pin == SPARKOUT_1_OUTPUT ||
pin == SPARKOUT_3_OUTPUT) {
if (pin == SPARKOUT_1_OUTPUT || pin == SPARKOUT_3_OUTPUT) {
// time_t now = hTimeNow();
// float an = getCrankshaftAngle(now);
// scheduleMsg(&logger, "spark up%d %d", pin, now);
@ -97,6 +101,8 @@ static void turnLow(OutputSignal *signal) {
#endif /* EFI_WAVE_ANALYZER */
}
int getRevolutionCounter(void);
/**
*
* @param delay the number of ticks before the output signal
@ -104,14 +110,15 @@ static void turnLow(OutputSignal *signal) {
* @param dwell the number of ticks of output duration
*
*/
int getRevolutionCounter(void);
void scheduleOutput(OutputSignal *signal, float delayMs, float durationMs) {
if (durationMs < 0) {
firmwareError("duration cannot be negative: %d", durationMs);
return;
}
if (cisnan(durationMs)) {
firmwareError("NaN in scheduleOutput", durationMs);
return;
}
scheduleOutputBase(signal, delayMs, durationMs);
@ -119,8 +126,8 @@ void scheduleOutput(OutputSignal *signal, float delayMs, float durationMs) {
scheduling_s * sUp = &signal->signalTimerUp[index];
scheduling_s * sDown = &signal->signalTimerDown[index];
scheduleTask(sUp, MS2US(delayMs), (schfunc_t) &turnHigh, (void *) signal);
scheduleTask(sDown, MS2US(delayMs + durationMs), (schfunc_t) &turnLow, (void*)signal);
scheduleTask(sUp, (int)MS2US(delayMs), (schfunc_t) &turnHigh, (void *) signal);
scheduleTask(sDown, (int)MS2US(delayMs + durationMs), (schfunc_t) &turnLow, (void*) signal);
// signal->last_scheduling_time = now;
}
@ -135,7 +142,6 @@ void scheduleOutputBase(OutputSignal *signal, float delayMs, float durationMs) {
// signal->duration = duration;
}
char *getPinName(io_pin_e io_pin) {
switch (io_pin) {
case SPARKOUT_1_OUTPUT:

View File

@ -13,6 +13,7 @@
#include "global.h"
#include "efifeatures.h"
#include "io_pins.h"
#include "scheduler.h"
#if EFI_PROD_CODE
#include "datalogging.h"
@ -22,24 +23,6 @@
#include "signal_executor_sleep.h"
#endif /* EFI_SIGNAL_EXECUTOR_SLEEP */
typedef void (*schfunc_t)(void *);
typedef struct scheduling_struct scheduling_s;
struct scheduling_struct {
//int initialized;
#if EFI_SIGNAL_EXECUTOR_SLEEP
VirtualTimer timer;
#endif /* EFI_SIGNAL_EXECUTOR_SLEEP */
volatile uint64_t momentUs;
#if EFI_SIGNAL_EXECUTOR_ONE_TIMER
schfunc_t callback;
void *param;
#endif
scheduling_s *next;
};
typedef enum {
IDLE = 0, ACTIVE
} executor_status_t;
@ -54,17 +37,8 @@ struct OutputSignal_struct {
*/
char *name;
io_pin_e io_pin;
#if 0 // depricated
// time in system ticks
volatile int offset;
// time in system ticks
volatile int duration;
#endif
int initialized;
// time_t last_scheduling_time;
// time_t hi_time;
/**
* We are alternating instances so that events which extend into next revolution are not overriden while
* scheduling next revolution events
@ -78,10 +52,9 @@ struct OutputSignal_struct {
// todo
#endif
OutputSignal *next;
// OutputSignal *next;
};
#ifdef __cplusplus
extern "C"
{
@ -94,7 +67,6 @@ void scheduleOutputBase(OutputSignal *signal, float delayMs, float durationMs);
void initSignalExecutor(void);
void initSignalExecutorImpl(void);
void scheduleTask(scheduling_s *scheduling, int delayUs, schfunc_t callback, void *param);
void scheduleByAngle(scheduling_s *timer, float angle, schfunc_t callback, void *param);
#ifdef __cplusplus

View File

@ -32,7 +32,6 @@
#include "eficonsole.h"
#include "status_loop.h"
#define CHART_DELIMETER "!"
/**
@ -66,7 +65,11 @@ void resetWaveChart(WaveChart *chart) {
appendPrintf(&chart->logging, "wave_chart%s", DELIMETER);
}
#if defined __GNUC__
static char WAVE_LOGGING_BUFFER[5000] __attribute__((section(".ccm")));
#else
static char WAVE_LOGGING_BUFFER[5000];
#endif
static void printStatus(void) {
scheduleIntValue(&logger, "chart", isChartActive);
@ -116,12 +119,13 @@ void addWaveChartEvent3(WaveChart *chart, const char *name, const char * msg, co
#endif
if (isWaveChartFull(chart))
return;
lockOutputBuffer(); // we have multiple threads writing to the same output buffer
bool_t alreadyLocked = lockOutputBuffer(); // we have multiple threads writing to the same output buffer
appendPrintf(&chart->logging, "%s%s%s%s", name, CHART_DELIMETER, msg, CHART_DELIMETER);
int time100 = getTimeNowUs() / 10;
appendPrintf(&chart->logging, "%d%s%s", time100, msg2, CHART_DELIMETER);
chart->counter++;
unlockOutputBuffer();
if (!alreadyLocked)
unlockOutputBuffer();
}
void initWaveChart(WaveChart *chart) {

View File

@ -0,0 +1,43 @@
/**
* @file EfiWave.cpp
*
* @date May 18, 2014
* @author Andrey Belomutskiy, (c) 2012-2014
*/
#include "main.h"
#include "EfiWave.h"
single_wave_s::single_wave_s() {
init(NULL);
}
single_wave_s::single_wave_s(int *ps) {
init(ps);
}
void single_wave_s::init(int *pinStates) {
this->pinStates = pinStates;
}
multi_wave_s::multi_wave_s(float *switchTimes, single_wave_s *waves) {
this->switchTimes = switchTimes;
this->waves = waves;
}
void multi_wave_s::reset(void) {
phaseCount = 0;
waveCount = 0;
}
float multi_wave_s::getSwitchTime(int index) const {
return switchTimes[index];
}
void checkSwitchTimes2(int size, float *switchTimes) {
for (int i = 0; i < size - 1; i++) {
if (switchTimes[i] >= switchTimes[i + 1]) {
firmwareError("invalid switchTimes");
}
}
}

View File

@ -0,0 +1,51 @@
/**
* @file EfiWave.h
*
* @date May 18, 2014
* @author Andrey Belomutskiy, (c) 2012-2014
*/
#ifndef EFI_WAVE_H_
#define EFI_WAVE_H_
#define PWM_PHASE_MAX_COUNT 150
#define PWM_PHASE_MAX_WAVE_PER_PWM 2
/**
* @brief PWM configuration for the specific output pin
*/
class single_wave_s {
public:
single_wave_s();
single_wave_s(int *pinStates);
void init(int *pinStates);
int *pinStates;
};
class multi_wave_s {
public:
multi_wave_s(float *st, single_wave_s *waves);
void reset(void);
float getSwitchTime(int phaseIndex) const;
void setSwitchTime(int phaseIndex, float value);
void checkSwitchTimes(int size);
int getChannelState(int channelIndex, int phaseIndex) const;
/**
* Number of events in the cycle
*/
int phaseCount;
/**
* Number of signal wires
*/
int waveCount;
single_wave_s *waves;
//private:
/**
* values in the (0..1] range which refer to points within the period at at which pin state should be changed
* So, in the simplest case we turn pin off at 0.3 and turn it on at 1 - that would give us a 70% duty cycle PWM
*/
float *switchTimes;
};
void checkSwitchTimes2(int size, float *switchTimes);
#endif /* EFI_WAVE_H_ */

View File

@ -1,62 +1,62 @@
/*
* avg_values.c
*
* @date Jul 23, 2013
* @author Andrey Belomutskiy, (c) 2012-2014
*/
#include "avg_values.h"
#include <math.h>
void avgFill(AvgTable *table, int count, float value) {
for (int i = 0; i < AVG_TAB_SIZE; i++) {
for (int j = 0; j < AVG_TAB_SIZE; j++) {
table->counts[i][j] = count;
table->values[i][j] = value;
}
}
}
void avgReset(AvgTable *table) {
avgFill(table, 0, 0);
}
void avgAddValue(AvgTable *table, int rpm, float key, float value) {
if (rpm >= MAX_RPM)
return;
if (key >= MAX_KEY)
return;
int i = (int)(AVG_TAB_SIZE * rpm / MAX_RPM);
int j = (int)(AVG_TAB_SIZE * key / MAX_KEY);
table->values[i][j] += value;
table->counts[i][j]++;
}
float avgGetValueByIndexes(AvgTable *table, int i, int j) {
int count = table->counts[i][j];
if (count == 0)
return NAN;
return table->values[i][j] / count;
}
float avgGetValue(AvgTable *table, int rpm, float key) {
if (rpm >= MAX_RPM)
return NAN;
if (key >= MAX_KEY)
return NAN;
int i = (int)(AVG_TAB_SIZE * rpm / MAX_RPM);
int j = (int)(AVG_TAB_SIZE * key / MAX_KEY);
return avgGetValueByIndexes(table, i, j);
}
int avgGetValuesCount(AvgTable *table, int rpm, float key) {
if (rpm >= MAX_RPM)
return 0;
if (key >= MAX_KEY)
return 0;
int i = (int)(AVG_TAB_SIZE * rpm / MAX_RPM);
int j = (int)(AVG_TAB_SIZE * key / MAX_KEY);
return table->counts[i][j];
}
/*
* avg_values.c
*
* @date Jul 23, 2013
* @author Andrey Belomutskiy, (c) 2012-2014
*/
#include "avg_values.h"
#include <math.h>
void avgFill(AvgTable *table, int count, float value) {
for (int i = 0; i < AVG_TAB_SIZE; i++) {
for (int j = 0; j < AVG_TAB_SIZE; j++) {
table->counts[i][j] = count;
table->values[i][j] = value;
}
}
}
void avgReset(AvgTable *table) {
avgFill(table, 0, 0);
}
void avgAddValue(AvgTable *table, int rpm, float key, float value) {
if (rpm >= MAX_RPM)
return;
if (key >= MAX_KEY)
return;
int i = (int)(AVG_TAB_SIZE * rpm / MAX_RPM);
int j = (int)(AVG_TAB_SIZE * key / MAX_KEY);
table->values[i][j] += value;
table->counts[i][j]++;
}
float avgGetValueByIndexes(AvgTable *table, int i, int j) {
int count = table->counts[i][j];
if (count == 0)
return NAN;
return table->values[i][j] / count;
}
float avgGetValue(AvgTable *table, int rpm, float key) {
if (rpm >= MAX_RPM)
return NAN;
if (key >= MAX_KEY)
return NAN;
int i = (int)(AVG_TAB_SIZE * rpm / MAX_RPM);
int j = (int)(AVG_TAB_SIZE * key / MAX_KEY);
return avgGetValueByIndexes(table, i, j);
}
int avgGetValuesCount(AvgTable *table, int rpm, float key) {
if (rpm >= MAX_RPM)
return 0;
if (key >= MAX_KEY)
return 0;
int i = (int)(AVG_TAB_SIZE * rpm / MAX_RPM);
int j = (int)(AVG_TAB_SIZE * key / MAX_KEY);
return table->counts[i][j];
}

View File

@ -1,30 +1,30 @@
/*
* avg_values.h
*
* @date Jul 23, 2013
* @author Andrey Belomutskiy, (c) 2012-2014
*/
#ifndef AVG_VALUES_H_
#define AVG_VALUES_H_
#define AVG_TAB_SIZE 48
#define MAX_RPM 8000
#define MAX_KEY 5
typedef struct {
float values[AVG_TAB_SIZE][AVG_TAB_SIZE];
int counts[AVG_TAB_SIZE][AVG_TAB_SIZE];
} AvgTable;
void avgReset(AvgTable *table);
void avgFill(AvgTable *table, int count, float value);
void avgAddValue(AvgTable *table, int rpm, float key, float value);
float avgGetValueByIndexes(AvgTable *table, int i, int j);
float avgGetValue(AvgTable *table, int rpm, float key);
int avgGetValuesCount(AvgTable *table, int rpm, float key);
#endif /* AVG_VALUES_H_ */
/*
* avg_values.h
*
* @date Jul 23, 2013
* @author Andrey Belomutskiy, (c) 2012-2014
*/
#ifndef AVG_VALUES_H_
#define AVG_VALUES_H_
#define AVG_TAB_SIZE 48
#define MAX_RPM 8000
#define MAX_KEY 5
typedef struct {
float values[AVG_TAB_SIZE][AVG_TAB_SIZE];
int counts[AVG_TAB_SIZE][AVG_TAB_SIZE];
} AvgTable;
void avgReset(AvgTable *table);
void avgFill(AvgTable *table, int count, float value);
void avgAddValue(AvgTable *table, int rpm, float key, float value);
float avgGetValueByIndexes(AvgTable *table, int i, int j);
float avgGetValue(AvgTable *table, int rpm, float key);
int avgGetValuesCount(AvgTable *table, int rpm, float key);
#endif /* AVG_VALUES_H_ */

View File

@ -0,0 +1,6 @@
CONTROLLERS_CORE_SRC = $(PROJECT_DIR)/controllers/core/interpolation.c \
$(PROJECT_DIR)/controllers/core/avg_values.c
CONTROLLERS_CORE_SRC_CPP = $(PROJECT_DIR)/controllers/core/EfiWave.cpp

View File

@ -1,220 +1,220 @@
/**
* @file interpolation.c
* @brief Linear interpolation algorithms
*
* @date Oct 17, 2013
* @author Andrey Belomutskiy, (c) 2012-2014
*/
#if DEBUG_FUEL
#include <stdio.h>
#endif
#include <math.h>
#include "main.h"
#include "interpolation.h"
//#include "engine_math.h"
#define INTERPOLATION_A(x1, y1, x2, y2) ((y1 - y2) / (x1 - x2))
int needInterpolationLogging = TRUE;
/** @brief Linear interpolation by two points
*
* @param x1 key of the first point
* @param y1 value of the first point
* @param x2 key of the second point
* @param y2 value of the second point
* @param X key to be interpolated
*
* @note For example, "interpolate(engineConfiguration.tpsMin, 0, engineConfiguration.tpsMax, 100, adc);"
*/
float interpolate(float x1, float y1, float x2, float y2, float x) {
// todo: double comparison using EPS
if (x1 == x2) {
firmwareError("Same x1 and x2 in interpolate: %f/%f", x1, x2);
return NAN;
}
// a*x1 + b = y1
// a*x2 + b = y2
// chDbgCheck(x1 != x2, "no way we can interpolate");
float a = INTERPOLATION_A(x1, y1, x2, y2);
float b = y1 - a * x1;
float result = a * x + b;
#if DEBUG_FUEL
printf("x1=%f y1=%f x2=%f y2=%f\r\n", x1, y1, x2, y2);
printf("a=%f b=%f result=%f\r\n", a, b, result);
#endif
return result;
}
/** @brief Binary search
* @returns the highest index within sorted array such that array[i] is greater than or equal to the parameter
* @note If the parameter is smaller than the first element of the array, -1 is returned.
*/
int findIndex(float array[], int size, float value) {
if (cisnan(value))
fatal("NaN in findIndex\r\n");
if (value < array[0])
return -1;
int middle;
int left = 0;
int right = size;
while (1) {
if (size-- == 0)
fatal("Unexpected state in binary search.");
middle = (left + right) / 2;
// print("left=%d middle=%d right=%d: %f\r\n", left, middle, right, array[middle]);
if (middle == left)
break;
if (value < array[middle]) {
right = middle;
} else if (value > array[middle]) {
left = middle;
} else {
break;
}
}
return middle;
}
/**
* @brief One-dimensional table lookup with linear interpolation
*/
float interpolate2d(float value, float bin[], float values[], int size) {
int index = findIndex(bin, size, value);
if (index == -1)
return values[0];
if (index == size - 1)
return values[size - 1];
return interpolate(bin[index], values[index], bin[index + 1], values[index + 1], value);
}
/**
* @brief Two-dimensional table lookup with linear interpolation
*/
float interpolate3d(float x, float xBin[], int xBinSize, float y, float yBin[], int yBinSize, float* map[]) {
if (cisnan(y)) {
warning(OBD_PCM_Processor_Fault, "%f: x is NaN in interpolate3d", x);
return NAN;
}
if (cisnan(y)) {
warning(OBD_PCM_Processor_Fault, "%f: y is NaN in interpolate3d", y);
return NAN;
}
int xIndex = findIndex(xBin, xBinSize, x);
#if DEBUG_INTERPOLATION
if (needInterpolationLogging)
printf("X index=%d\r\n", xIndex);
#endif
int yIndex = findIndex(yBin, yBinSize, y);
if (xIndex < 0 && yIndex < 0) {
#if DEBUG_INTERPOLATION
if (needInterpolationLogging)
printf("X and Y are smaller than smallest cell in table: %d\r\n", xIndex);
#endif
return map[0][0];
}
if (xIndex < 0) {
#if DEBUG_INTERPOLATION
if (needInterpolationLogging)
printf("X is smaller than smallest cell in table: %dr\n", xIndex);
#endif
// no interpolation should be fine here.
return map[0][yIndex];
}
if (yIndex < 0) {
#if DEBUG_INTERPOLATION
if (needInterpolationLogging)
printf("Y is smaller than smallest cell in table: %d\r\n", yIndex);
#endif
// no interpolation should be fine here.
return map[xIndex][0];
}
if (xIndex == xBinSize - 1 && yIndex == yBinSize - 1) {
#if DEBUG_INTERPOLATION
if (needInterpolationLogging)
printf("X and Y are larger than largest cell in table: %d %d\r\n", xIndex, yIndex);
#endif
return map[xBinSize - 1][yBinSize - 1];
}
if (xIndex == xBinSize - 1) {
#if DEBUG_INTERPOLATION
if (needInterpolationLogging)
printf("TODO BETTER LOGGING x overflow %d\r\n", yIndex);
#endif
// todo: implement better handling - y interpolation
return map[xBinSize - 1][yIndex];
}
if (yIndex == yBinSize - 1) {
#if DEBUG_INTERPOLATION
if (needInterpolationLogging)
printf("Y is larger than largest cell in table: %d\r\n", yIndex);
#endif
// todo: implement better handling - x interpolation
return map[xIndex][yBinSize - 1];
}
/*
* first we find the interpolated value for this RPM
*/
int rpmMaxIndex = xIndex + 1;
float xMin = xBin[xIndex];
float xMax = xBin[xIndex + 1];
float rpmMinKeyMinValue = map[xIndex][yIndex];
float rpmMaxKeyMinValue = map[xIndex + 1][yIndex];
float keyMinValue = interpolate(xMin, rpmMinKeyMinValue, xMax, rpmMaxKeyMinValue, x);
#if DEBUG_INTERPOLATION
if (needInterpolationLogging) {
printf("X=%f:\r\nrange %f - %f\r\n", x, xMin, xMax);
printf("X interpolation range %f %f result %f\r\n", rpmMinKeyMinValue, rpmMaxKeyMinValue, keyMinValue);
}
#endif
int keyMaxIndex = yIndex + 1;
float keyMin = yBin[yIndex];
float keyMax = yBin[keyMaxIndex];
float rpmMinKeyMaxValue = map[xIndex][keyMaxIndex];
float rpmMaxKeyMaxValue = map[rpmMaxIndex][keyMaxIndex];
float keyMaxValue = interpolate(xMin, rpmMinKeyMaxValue, xMax, rpmMaxKeyMaxValue, x);
#if DEBUG_INTERPOLATION
if (needInterpolationLogging) {
printf("key=%f:\r\nrange %f - %f\r\n", y, keyMin, keyMax);
printf("key interpolation range %f %f result %f\r\n", rpmMinKeyMaxValue, rpmMaxKeyMaxValue, keyMaxValue);
}
#endif
float result = interpolate(keyMin, keyMinValue, keyMax, keyMaxValue, y);
return result;
}
void setTableValue(float bins[], float values[], int size, float key, float value) {
int index = findIndex(bins, size, key);
if (index == -1)
index = 0;
values[index] = value;
}
/**
* @file interpolation.c
* @brief Linear interpolation algorithms
*
* @date Oct 17, 2013
* @author Andrey Belomutskiy, (c) 2012-2014
*/
#if DEBUG_FUEL
#include <stdio.h>
#endif
#include <math.h>
#include "main.h"
#include "interpolation.h"
//#include "engine_math.h"
#define INTERPOLATION_A(x1, y1, x2, y2) ((y1 - y2) / (x1 - x2))
int needInterpolationLogging = TRUE;
/** @brief Linear interpolation by two points
*
* @param x1 key of the first point
* @param y1 value of the first point
* @param x2 key of the second point
* @param y2 value of the second point
* @param X key to be interpolated
*
* @note For example, "interpolate(engineConfiguration.tpsMin, 0, engineConfiguration.tpsMax, 100, adc);"
*/
float interpolate(float x1, float y1, float x2, float y2, float x) {
// todo: double comparison using EPS
if (x1 == x2) {
firmwareError("Same x1 and x2 in interpolate: %f/%f", x1, x2);
return NAN;
}
// a*x1 + b = y1
// a*x2 + b = y2
// chDbgCheck(x1 != x2, "no way we can interpolate");
float a = INTERPOLATION_A(x1, y1, x2, y2);
float b = y1 - a * x1;
float result = a * x + b;
#if DEBUG_FUEL
printf("x1=%f y1=%f x2=%f y2=%f\r\n", x1, y1, x2, y2);
printf("a=%f b=%f result=%f\r\n", a, b, result);
#endif
return result;
}
/** @brief Binary search
* @returns the highest index within sorted array such that array[i] is greater than or equal to the parameter
* @note If the parameter is smaller than the first element of the array, -1 is returned.
*/
int findIndex(float array[], int size, float value) {
if (cisnan(value))
fatal("NaN in findIndex\r\n");
if (value < array[0])
return -1;
int middle;
int left = 0;
int right = size;
while (1) {
if (size-- == 0)
fatal("Unexpected state in binary search.");
middle = (left + right) / 2;
// print("left=%d middle=%d right=%d: %f\r\n", left, middle, right, array[middle]);
if (middle == left)
break;
if (value < array[middle]) {
right = middle;
} else if (value > array[middle]) {
left = middle;
} else {
break;
}
}
return middle;
}
/**
* @brief One-dimensional table lookup with linear interpolation
*/
float interpolate2d(float value, float bin[], float values[], int size) {
int index = findIndex(bin, size, value);
if (index == -1)
return values[0];
if (index == size - 1)
return values[size - 1];
return interpolate(bin[index], values[index], bin[index + 1], values[index + 1], value);
}
/**
* @brief Two-dimensional table lookup with linear interpolation
*/
float interpolate3d(float x, float xBin[], int xBinSize, float y, float yBin[], int yBinSize, float* map[]) {
if (cisnan(y)) {
warning(OBD_PCM_Processor_Fault, "%f: x is NaN in interpolate3d", x);
return NAN;
}
if (cisnan(y)) {
warning(OBD_PCM_Processor_Fault, "%f: y is NaN in interpolate3d", y);
return NAN;
}
int xIndex = findIndex(xBin, xBinSize, x);
#if DEBUG_INTERPOLATION
if (needInterpolationLogging)
printf("X index=%d\r\n", xIndex);
#endif
int yIndex = findIndex(yBin, yBinSize, y);
if (xIndex < 0 && yIndex < 0) {
#if DEBUG_INTERPOLATION
if (needInterpolationLogging)
printf("X and Y are smaller than smallest cell in table: %d\r\n", xIndex);
#endif
return map[0][0];
}
if (xIndex < 0) {
#if DEBUG_INTERPOLATION
if (needInterpolationLogging)
printf("X is smaller than smallest cell in table: %dr\n", xIndex);
#endif
// no interpolation should be fine here.
return map[0][yIndex];
}
if (yIndex < 0) {
#if DEBUG_INTERPOLATION
if (needInterpolationLogging)
printf("Y is smaller than smallest cell in table: %d\r\n", yIndex);
#endif
// no interpolation should be fine here.
return map[xIndex][0];
}
if (xIndex == xBinSize - 1 && yIndex == yBinSize - 1) {
#if DEBUG_INTERPOLATION
if (needInterpolationLogging)
printf("X and Y are larger than largest cell in table: %d %d\r\n", xIndex, yIndex);
#endif
return map[xBinSize - 1][yBinSize - 1];
}
if (xIndex == xBinSize - 1) {
#if DEBUG_INTERPOLATION
if (needInterpolationLogging)
printf("TODO BETTER LOGGING x overflow %d\r\n", yIndex);
#endif
// todo: implement better handling - y interpolation
return map[xBinSize - 1][yIndex];
}
if (yIndex == yBinSize - 1) {
#if DEBUG_INTERPOLATION
if (needInterpolationLogging)
printf("Y is larger than largest cell in table: %d\r\n", yIndex);
#endif
// todo: implement better handling - x interpolation
return map[xIndex][yBinSize - 1];
}
/*
* first we find the interpolated value for this RPM
*/
int rpmMaxIndex = xIndex + 1;
float xMin = xBin[xIndex];
float xMax = xBin[xIndex + 1];
float rpmMinKeyMinValue = map[xIndex][yIndex];
float rpmMaxKeyMinValue = map[xIndex + 1][yIndex];
float keyMinValue = interpolate(xMin, rpmMinKeyMinValue, xMax, rpmMaxKeyMinValue, x);
#if DEBUG_INTERPOLATION
if (needInterpolationLogging) {
printf("X=%f:\r\nrange %f - %f\r\n", x, xMin, xMax);
printf("X interpolation range %f %f result %f\r\n", rpmMinKeyMinValue, rpmMaxKeyMinValue, keyMinValue);
}
#endif
int keyMaxIndex = yIndex + 1;
float keyMin = yBin[yIndex];
float keyMax = yBin[keyMaxIndex];
float rpmMinKeyMaxValue = map[xIndex][keyMaxIndex];
float rpmMaxKeyMaxValue = map[rpmMaxIndex][keyMaxIndex];
float keyMaxValue = interpolate(xMin, rpmMinKeyMaxValue, xMax, rpmMaxKeyMaxValue, x);
#if DEBUG_INTERPOLATION
if (needInterpolationLogging) {
printf("key=%f:\r\nrange %f - %f\r\n", y, keyMin, keyMax);
printf("key interpolation range %f %f result %f\r\n", rpmMinKeyMaxValue, rpmMaxKeyMaxValue, keyMaxValue);
}
#endif
float result = interpolate(keyMin, keyMinValue, keyMax, keyMaxValue, y);
return result;
}
void setTableValue(float bins[], float values[], int size, float key, float value) {
int index = findIndex(bins, size, key);
if (index == -1)
index = 0;
values[index] = value;
}

View File

@ -1,26 +1,26 @@
/**
* @file interpolation.h
*
* @date Oct 17, 2013
* @author Andrey Belomutskiy, (c) 2012-2014
*/
#ifndef INTERPOLATION_3D_H_
#define INTERPOLATION_3D_H_
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
int findIndex(float array[], int size, float value);
float interpolate(float x1, float y1, float x2, float y2, float x);
float interpolate2d(float value, float bin[], float values[], int size);
float interpolate3d(float x, float xBin[], int xBinSize, float y, float yBin[], int yBinSize, float* map[]);
void setTableValue(float bins[], float values[], int size, float key, float value);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* INTERPOLATION_3D_H_ */
/**
* @file interpolation.h
*
* @date Oct 17, 2013
* @author Andrey Belomutskiy, (c) 2012-2014
*/
#ifndef INTERPOLATION_3D_H_
#define INTERPOLATION_3D_H_
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
int findIndex(float array[], int size, float value);
float interpolate(float x1, float y1, float x2, float y2, float x);
float interpolate2d(float value, float bin[], float values[], int size);
float interpolate3d(float x, float xBin[], int xBinSize, float y, float yBin[], int yBinSize, float* map[]);
void setTableValue(float bins[], float values[], int size, float key, float value);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* INTERPOLATION_3D_H_ */

View File

@ -1,64 +1,64 @@
/*
* signal_filtering.c
*
* @date Aug 5, 2013
* @author pc
*/
#ifndef SIGNAL_FILTERING_C_
#define SIGNAL_FILTERING_C_
#include "signal_filtering.h"
void sfInit(SignalFiltering *fs, float K, float initialValue) {
fs->pointer = 0;
fs->K = K;
fs->Vout = initialValue;
fs->Vacc = initialValue * K;
}
static void addCopyAndSort(SignalFiltering *fs, float value) {
fs->values[fs->pointer] = value;
fs->pointer = ++fs->pointer == FILTER_SIZE ? 0 : fs->pointer;
for (int i = 0; i < FILTER_SIZE; i++)
fs->sorted[i] = fs->values[i];
for (int i = 0; i < FILTER_SIZE; i++)
for (int j = i + 1; j < FILTER_SIZE; j++)
if (fs->sorted[i] < fs->sorted[j]) {
float temp = fs->sorted[i];
fs->sorted[i] = fs->sorted[j];
fs->sorted[j] = temp;
}
}
void sfAddValue(SignalFiltering *fs, float value) {
addCopyAndSort(fs, value);
float Vin = fs->sorted[FILTER_SIZE / 2];
fs->Vacc += Vin - fs->Vout;
fs->Vout = fs->Vacc / fs->K;
}
void sfAddValue2(SignalFiltering *fs, float value) {
addCopyAndSort(fs, value);
int fromIndex = FILTER_SIZE / 4;
int toIndex = FILTER_SIZE / 4 + FILTER_SIZE / 2;
/**
* this implementation takes the average of the middle hald of the sorted values
*/
float result = 0;
for (int i = fromIndex; i < toIndex; i++)
result += fs->sorted[i];
fs->Vout = result / (FILTER_SIZE / 2);
}
float sfGetValue(SignalFiltering *fs) {
return fs->Vout;
}
#endif /* SIGNAL_FILTERING_C_ */
/*
* signal_filtering.c
*
* @date Aug 5, 2013
* @author pc
*/
#ifndef SIGNAL_FILTERING_C_
#define SIGNAL_FILTERING_C_
#include "signal_filtering.h"
void sfInit(SignalFiltering *fs, float K, float initialValue) {
fs->pointer = 0;
fs->K = K;
fs->Vout = initialValue;
fs->Vacc = initialValue * K;
}
static void addCopyAndSort(SignalFiltering *fs, float value) {
fs->values[fs->pointer] = value;
fs->pointer = ++fs->pointer == FILTER_SIZE ? 0 : fs->pointer;
for (int i = 0; i < FILTER_SIZE; i++)
fs->sorted[i] = fs->values[i];
for (int i = 0; i < FILTER_SIZE; i++)
for (int j = i + 1; j < FILTER_SIZE; j++)
if (fs->sorted[i] < fs->sorted[j]) {
float temp = fs->sorted[i];
fs->sorted[i] = fs->sorted[j];
fs->sorted[j] = temp;
}
}
void sfAddValue(SignalFiltering *fs, float value) {
addCopyAndSort(fs, value);
float Vin = fs->sorted[FILTER_SIZE / 2];
fs->Vacc += Vin - fs->Vout;
fs->Vout = fs->Vacc / fs->K;
}
void sfAddValue2(SignalFiltering *fs, float value) {
addCopyAndSort(fs, value);
int fromIndex = FILTER_SIZE / 4;
int toIndex = FILTER_SIZE / 4 + FILTER_SIZE / 2;
/**
* this implementation takes the average of the middle hald of the sorted values
*/
float result = 0;
for (int i = fromIndex; i < toIndex; i++)
result += fs->sorted[i];
fs->Vout = result / (FILTER_SIZE / 2);
}
float sfGetValue(SignalFiltering *fs) {
return fs->Vout;
}
#endif /* SIGNAL_FILTERING_C_ */

View File

@ -1,25 +1,25 @@
/*
* signal_filtering.h
*
* @date Aug 5, 2013
* @author pc
*/
#ifndef SIGNAL_FILTERING_H_
#define SIGNAL_FILTERING_H_
#define FILTER_SIZE 5
typedef struct {
float values[FILTER_SIZE];
float sorted[FILTER_SIZE];
int pointer;
float K, Vacc, Vout;
} SignalFiltering;
void sfInit(SignalFiltering *fs, float K, float initialValue);
void sfAddValue(SignalFiltering *fs, float value);
void sfAddValue2(SignalFiltering *fs, float value);
float sfGetValue(SignalFiltering *fs);
#endif /* SIGNAL_FILTERING_H_ */
/*
* signal_filtering.h
*
* @date Aug 5, 2013
* @author pc
*/
#ifndef SIGNAL_FILTERING_H_
#define SIGNAL_FILTERING_H_
#define FILTER_SIZE 5
typedef struct {
float values[FILTER_SIZE];
float sorted[FILTER_SIZE];
int pointer;
float K, Vacc, Vout;
} SignalFiltering;
void sfInit(SignalFiltering *fs, float K, float initialValue);
void sfAddValue(SignalFiltering *fs, float value);
void sfAddValue2(SignalFiltering *fs, float value);
float sfGetValue(SignalFiltering *fs);
#endif /* SIGNAL_FILTERING_H_ */

View File

@ -54,8 +54,14 @@
#define _10_MILLISECONDS (10 * TICKS_IN_MS)
extern engine_configuration_s *engineConfiguration;
extern board_configuration_s *boardConfiguration;
#if defined __GNUC__
persistent_config_container_s persistentState __attribute__((section(".ccm")));
#else
persistent_config_container_s persistentState;
#endif
engine_configuration_s *engineConfiguration = &persistentState.persistentConfiguration.engineConfiguration;
board_configuration_s *boardConfiguration = &persistentState.persistentConfiguration.boardConfiguration;
/**
* CH_FREQUENCY is the number of system ticks in a second
@ -213,6 +219,8 @@ static void printAnalogInfo(void) {
printAnalogChannelInfo("IAT", engineConfiguration->iatAdcChannel);
printAnalogChannelInfo("MAF", engineConfiguration->mafAdcChannel);
printAnalogChannelInfo("AFR", engineConfiguration->afrSensor.afrAdcChannel);
printAnalogChannelInfo("MAP", engineConfiguration->map.sensor.hwChannel);
printAnalogChannelInfo("BARO", engineConfiguration->baroSensor.hwChannel);
printAnalogChannelInfoExt("Vbatt", engineConfiguration->vBattAdcChannel,
getVBatt());
}
@ -220,19 +228,23 @@ static void printAnalogInfo(void) {
static WORKING_AREA(csThreadStack, UTILITY_THREAD_STACK_SIZE);// declare thread stack
void initEngineContoller(void) {
if (hasFirmwareError())
return;
initLogging(&logger, "Engine Controller");
initSensors();
initPwmGenerator();
#if EFI_ANALOG_CHART
initAnalogChart();
#endif /* EFI_ANALOG_CHART */
initAlgo();
#ifdef EFI_WAVE_ANALYZER
#if EFI_WAVE_ANALYZER
initWaveAnalyzer();
#endif
#endif /* EFI_WAVE_ANALYZER */
/**
* there is an implicit dependency on the fact that 'tachometer' listener is the 1st listener - this case
@ -258,13 +270,21 @@ void initEngineContoller(void) {
#if EFI_ELECTRONIC_THROTTLE_BODY
initElectronicThrottle();
#endif /* EFI_ELECTRONIC_THROTTLE_BODY */
initMalfunctionIndicator();
initMapAveraging();
#if EFI_MALFUNCTION_INDICATOR
initMalfunctionIndicator();
#endif /* EFI_MALFUNCTION_INDICATOR */
#if EFI_MAP_AVERAGING
initMapAveraging();
#endif /* EFI_MAP_AVERAGING */
#if EFI_ENGINE_CONTROL
/**
* This method initialized the main listener which actually runs injectors & ignition
*/
initMainEventListener();
#endif /* EFI_ENGINE_CONTROL */
#if EFI_IDLE_CONTROL
startIdleThread();
@ -272,7 +292,10 @@ void initEngineContoller(void) {
scheduleMsg(&logger, "no idle control");
#endif
#if EFI_FUEL_PUMP
initFuelPump();
#endif
addConsoleAction("analoginfo", printAnalogInfo);
}

View File

@ -7,20 +7,46 @@
#include "main.h"
#include "error_handling.h"
#include "wave_math.h"
#include "io_pins.h"
#if EFI_HD44780_LCD
#include "lcd_HD44780.h"
#endif /* EFI_HD44780_LCD */
static time_t timeOfPreviousWarning = -10;
static Logging logger;
extern int warningEnabled;
extern int main_loop_started;
const char *dbg_panic_file;
int dbg_panic_line;
void chDbgPanic3(const char *msg, const char * file, int line) {
if (hasFatalError())
return;
dbg_panic_file = file;
dbg_panic_line = line;
dbg_panic_msg = msg;
setOutputPinValue(LED_ERROR, 1);
#if EFI_HD44780_LCD
lcdShowFatalMessage((char *) msg);
#endif /* EFI_HD44780_LCD */
if (!main_loop_started) {
print("fatal %s %s:%d\r\n", msg, file, line);
chThdSleepSeconds(1);
chSysHalt();
}
}
/**
* @returns TRUE in case there are too many warnings
*/
int warning(obd_code_e code, const char *fmt, ...) {
int now = getTimeNowSeconds();
if (now == timeOfPreviousWarning || !warningEnabled)
if (absI(now - timeOfPreviousWarning) < 10 || !warningEnabled)
return TRUE; // we just had another warning, let's not spam
timeOfPreviousWarning = now;
@ -38,5 +64,4 @@ int warning(obd_code_e code, const char *fmt, ...) {
void initErrorHandling(void) {
initLogging(&logger, "error handling");
}

View File

@ -36,45 +36,42 @@ static engine_type_e defaultEngineType = FORD_ASPIRE_1996;
static Logging logger;
#if defined __GNUC__
FlashState flashState __attribute__((section(".ccm")));
#else
FlashState flashState;
#endif
extern persistent_config_container_s persistentState;
engine_configuration_s *engineConfiguration = &flashState.persistentConfiguration.engineConfiguration;
board_configuration_s *boardConfiguration = &flashState.persistentConfiguration.boardConfiguration;
extern engine_configuration_s *engineConfiguration;
extern board_configuration_s *boardConfiguration;
extern engine_configuration2_s * engineConfiguration2;
#define FLASH_ADDR 0x08060000
#define FLASH_USAGE sizeof(FlashState)
#define PERSISTENT_SIZE sizeof(persistent_config_container_s)
crc flashStateCrc(FlashState *state) {
return calc_crc((const crc*) &state->persistentConfiguration, sizeof(persistent_config_s));
crc_t flashStateCrc(persistent_config_container_s *state) {
return calc_crc((const crc_t*) &state->persistentConfiguration, sizeof(persistent_config_s));
}
void writeToFlash(void) {
flashState.version = FLASH_DATA_VERSION;
scheduleMsg(&logger, "FLASH_DATA_VERSION=%d", flashState.version);
crc result = flashStateCrc(&flashState);
flashState.value = result;
scheduleMsg(&logger, "Reseting flash=%d", FLASH_USAGE);
flashErase(FLASH_ADDR, FLASH_USAGE);
persistentState.size = PERSISTENT_SIZE;
persistentState.version = FLASH_DATA_VERSION;
scheduleMsg(&logger, "FLASH_DATA_VERSION=%d", persistentState.version);
crc_t result = flashStateCrc(&persistentState);
persistentState.value = result;
scheduleMsg(&logger, "Reseting flash, size=%d", PERSISTENT_SIZE);
flashErase(FLASH_ADDR, PERSISTENT_SIZE);
scheduleMsg(&logger, "Flashing with CRC=%d", result);
efitimems_t nowMs = currentTimeMillis();
result = flashWrite(FLASH_ADDR, (const char *) &flashState, FLASH_USAGE);
result = flashWrite(FLASH_ADDR, (const char *) &persistentState, PERSISTENT_SIZE);
scheduleMsg(&logger, "Flash programmed in (ms): %d", currentTimeMillis() - nowMs);
scheduleMsg(&logger, "Flashed: %d", result);
}
static int isValidCrc(FlashState *state) {
static int isValidCrc(persistent_config_container_s *state) {
if (state->version != FLASH_DATA_VERSION) {
scheduleMsg(&logger, "Unexpected flash version: %d", state->version);
return FALSE;
}
crc result = flashStateCrc(state);
crc_t result = flashStateCrc(state);
int isValidCrc = result == state->value;
if (!isValidCrc)
scheduleMsg(&logger, "CRC got %d while %d expected", result, state->value);
@ -82,30 +79,33 @@ static int isValidCrc(FlashState *state) {
}
static void doResetConfiguration(void) {
resetConfigurationExt(engineConfiguration->engineType, engineConfiguration, engineConfiguration2, boardConfiguration);
resetConfigurationExt(&logger, engineConfiguration->engineType, engineConfiguration, engineConfiguration2,
boardConfiguration);
}
static void readFromFlash(void) {
printMsg(&logger, "readFromFlash()");
flashRead(FLASH_ADDR, (char *) &flashState, FLASH_USAGE);
flashRead(FLASH_ADDR, (char *) &persistentState, PERSISTENT_SIZE);
setDefaultNonPersistentConfiguration(engineConfiguration2);
if (!isValidCrc(&flashState)) {
scheduleMsg(&logger, "Need to reset flash to default");
resetConfigurationExt(defaultEngineType, engineConfiguration, engineConfiguration2, boardConfiguration);
if (!isValidCrc(&persistentState) || persistentState.size != PERSISTENT_SIZE) {
printMsg(&logger, "Need to reset flash to default");
resetConfigurationExt(&logger, defaultEngineType, engineConfiguration, engineConfiguration2,
boardConfiguration);
} else {
scheduleMsg(&logger, "Got valid configuration from flash!");
applyNonPersistentConfiguration(engineConfiguration, engineConfiguration2, engineConfiguration->engineType);
printMsg(&logger, "Got valid configuration from flash!");
applyNonPersistentConfiguration(&logger, engineConfiguration, engineConfiguration2,
engineConfiguration->engineType);
}
// we can only change the state after the CRC check
engineConfiguration->firmwareVersion = getRusEfiVersion();
}
void initFlash(void) {
initLogging(&logger, "Flash memory");
print("initFlash()\r\n");
initLogging(&logger, "Flash memory");
addConsoleAction("readconfig", readFromFlash);
addConsoleAction("writeconfig", writeToFlash);

View File

@ -10,15 +10,8 @@
#define FLASH_MAIN_H_
#include "engine_configuration.h"
#include "crc.h"
#define FLASH_DATA_VERSION 2727
typedef struct {
int version;
persistent_config_s persistentConfiguration;
crc value;
} FlashState;
#define FLASH_DATA_VERSION 3002
#ifdef __cplusplus
extern "C"

View File

@ -133,7 +133,9 @@ static msg_t benchThread(int param) {
needToRunBench = FALSE;
runBench(brainPin, pin, onTime, offTime, count);
}
#if defined __GNUC__
return 0;
#endif
}
void initInjectorCentral(void) {

View File

@ -30,6 +30,8 @@
#include "malfunction_central.h"
#include "malfunction_indicator.h"
#if EFI_MALFUNCTION_INDICATOR
#define MFI_LONG_BLINK 1500
#define MFI_SHORT_BLINK 400
#define MFI_BLINK_SEPARATOR 400
@ -102,3 +104,5 @@ void initMalfunctionIndicator(void) {
addError(OBD_Engine_Coolant_Temperature_Circuit_Malfunction);
addError(OBD_Intake_Air_Temperature_Circuit_Malfunction);
}
#endif /* EFI_MALFUNCTION_INDICATOR */

View File

@ -19,17 +19,23 @@
*/
#include "main.h"
#if EFI_MAP_AVERAGING
#include "map_averaging.h"
#include "idle_controller.h" // that's for min/max. todo: move these somewhere?
#include "trigger_central.h"
#include "adc_inputs.h"
#include "map.h"
#include "analog_chart.h"
#include "engine_state.h"
#include "engine_configuration.h"
#include "interpolation.h"
#include "signal_executor.h"
#if EFI_ANALOG_CHART
#include "analog_chart.h"
#endif /* EFI_ANALOG_CHART */
#define FAST_MAP_CHART_SKIP_FACTOR 16
static Logging logger;
@ -52,7 +58,6 @@ static volatile float v_mapAccumulator = 0;
*/
static volatile int mapMeasurementsCounter = 0;
static float atmosphericPressure;
static float currentMaxPressure;
/**
@ -62,12 +67,8 @@ static float v_averagedMapValue;
extern engine_configuration_s *engineConfiguration;
static scheduling_s startTimer;
static scheduling_s endTimer;
float getAtmosphericPressure(void) {
return atmosphericPressure;
}
static scheduling_s startTimer[2];
static scheduling_s endTimer[2];
static void startAveraging(void*arg) {
chSysLockFromIsr()
@ -119,36 +120,64 @@ static void endAveraging(void *arg) {
*/
static void shaftPositionCallback(ShaftEvents ckpEventType, int index) {
// this callback is invoked on interrupt thread
if (index != 0)
return;
int rpm = getRpm();
if(!isValidRpm(rpm))
return;
perRevolution = perRevolutionCounter;
perRevolutionCounter = 0;
atmosphericPressure = currentMaxPressure;
currentMaxPressure = 0;
MapConf_s * config = &engineConfiguration->map.config;
MAP_sensor_config_s * config = &engineConfiguration->map;
float a_samplingStart = interpolate2d(getRpm(), config->samplingAngleBins, config->samplingAngle,
MAP_ANGLE_SIZE);
float a_samplingWindow = interpolate2d(getRpm(), config->samplingWindowBins, config->samplingWindow,
MAP_WINDOW_SIZE);
float startAngle = interpolate2d(rpm, config->samplingAngleBins, config->samplingAngle, MAP_ANGLE_SIZE);
float windowAngle = interpolate2d(rpm, config->samplingWindowBins, config->samplingWindow, MAP_WINDOW_SIZE);
scheduleByAngle(&startTimer, a_samplingStart, startAveraging, NULL);
scheduleByAngle(&endTimer, a_samplingStart + a_samplingWindow, endAveraging, NULL);
int structIndex = getRevolutionCounter() % 2;
// todo: schedule this based on closest trigger event, same as ignition works
scheduleByAngle(&startTimer[structIndex], startAngle, startAveraging, NULL);
scheduleByAngle(&endTimer[structIndex], startAngle + windowAngle, endAveraging, NULL);
}
static void showMapStats(void) {
scheduleMsg(&logger, "per revolution %d", perRevolution);
}
float getMapVoltage(void) {
return v_averagedMapValue;
}
/**
* because of MAP window averaging, MAP is only available while engine is spinning
*/
float getMap(void) {
if (getRpm() == 0)
return getRawMap(); // maybe return NaN and have a
return getMapByVoltage(v_averagedMapValue);
}
void initMapAveraging(void) {
initLogging(&logger, "Map Averaging");
startTimer[0].name = "map start0";
startTimer[1].name = "map start1";
endTimer[0].name = "map end0";
endTimer[1].name = "map end1";
addTriggerEventListener(&shaftPositionCallback, "rpm reporter");
addConsoleAction("faststat", showMapStats);
}
#else
float getMap(void) {
return getRawMap();
}
#endif /* EFI_MAP_AVERAGING */

View File

@ -13,10 +13,8 @@ extern "C"
{
#endif /* __cplusplus */
void mapAveragingCallback(adcsample_t newValue);
void initMapAveraging(void);
float getAtmosphericPressure(void);
#ifdef __cplusplus
}

View File

@ -136,13 +136,20 @@ int isCrankingRT(engine_configuration_s *engineConfiguration, int rpm) {
OutputSignalList ignitionSignals;
OutputSignalList injectonSignals;
static void registerSparkEvent(engine_configuration_s const *engineConfiguration, trigger_shape_s * s,
ActuatorEventList *list, OutputSignal *actuator, float angleOffset) {
registerActuatorEventExt(engineConfiguration, s, list,
actuator, angleOffset);
}
void initializeIgnitionActions(float baseAngle, engine_configuration_s *engineConfiguration,
engine_configuration2_s *engineConfiguration2) {
engine_configuration2_s *engineConfiguration2, float dwellMs, ActuatorEventList *list) {
chDbgCheck(engineConfiguration->cylindersCount > 0, "cylindersCount");
ignitionSignals.clear();
EventHandlerConfiguration *config = &engineConfiguration2->engineEventConfiguration;
resetEventList(&config->ignitionEvents);
resetEventList(list);
switch (engineConfiguration->ignitionMode) {
case IM_ONE_COIL:
@ -150,7 +157,7 @@ void initializeIgnitionActions(float baseAngle, engine_configuration_s *engineCo
// todo: extract method
float angle = baseAngle + 720.0 * i / engineConfiguration->cylindersCount;
registerActuatorEventExt(engineConfiguration, &engineConfiguration2->triggerShape, &config->ignitionEvents,
registerSparkEvent(engineConfiguration, &engineConfiguration2->triggerShape, list,
ignitionSignals.add(SPARKOUT_1_OUTPUT), angle);
}
break;
@ -160,10 +167,10 @@ void initializeIgnitionActions(float baseAngle, engine_configuration_s *engineCo
int wastedIndex = i % (engineConfiguration->cylindersCount / 2);
int id = (getCylinderId(engineConfiguration->firingOrder, wastedIndex) - 1);
int id = getCylinderId(engineConfiguration->firingOrder, wastedIndex) - 1;
io_pin_e ioPin = (io_pin_e) (SPARKOUT_1_OUTPUT + id);
registerActuatorEventExt(engineConfiguration, &engineConfiguration2->triggerShape, &config->ignitionEvents,
registerSparkEvent(engineConfiguration, &engineConfiguration2->triggerShape, list,
ignitionSignals.add(ioPin), angle);
}
@ -174,7 +181,7 @@ void initializeIgnitionActions(float baseAngle, engine_configuration_s *engineCo
float angle = baseAngle + 720.0 * i / engineConfiguration->cylindersCount;
io_pin_e pin = (io_pin_e) ((int) SPARKOUT_1_OUTPUT + getCylinderId(engineConfiguration->firingOrder, i) - 1);
registerActuatorEventExt(engineConfiguration, &engineConfiguration2->triggerShape, &config->ignitionEvents,
registerSparkEvent(engineConfiguration, &engineConfiguration2->triggerShape, list,
ignitionSignals.add(pin), angle);
}
break;
@ -231,13 +238,14 @@ float getSparkDwellMsT(engine_configuration_s *engineConfiguration, int rpm) {
float angle = engineConfiguration->crankingChargeAngle;
return getOneDegreeTimeMs(rpm) * angle;
}
efiAssert(!cisnan(rpm), "invalid rpm");
return interpolate2d(rpm, engineConfiguration->sparkDwellBins, engineConfiguration->sparkDwell, DWELL_CURVE_SIZE);
}
void registerActuatorEventExt(engine_configuration_s const *engineConfiguration, trigger_shape_s * s,
ActuatorEventList *list, OutputSignal *actuator, float angleOffset) {
chDbgCheck(s->size > 0, "uninitialized trigger_shape_s");
chDbgCheck(s->getSize() > 0, "uninitialized trigger_shape_s");
angleOffset = fixAngle(angleOffset + engineConfiguration->globalTriggerAngleOffset);
@ -248,17 +256,23 @@ void registerActuatorEventExt(engine_configuration_s const *engineConfiguration,
// let's find the last trigger angle which is less or equal to the desired angle
int i;
for (i = 0; i < s->size - 1; i++) {
for (i = 0; i < s->getSize() - 1; i++) {
// todo: we need binary search here
float angle = fixAngle(s->wave.getSwitchTime((triggerIndexOfZeroEvent + i + 1) % s->size) * 720 - firstAngle);
float angle = fixAngle(
s->wave.getSwitchTime((triggerIndexOfZeroEvent + i + 1) % s->getSize()) * 720 - firstAngle);
if (angle > angleOffset)
break;
}
// explicit check for zero to avoid issues where logical zero is not exactly zero due to float nature
float angle =
i == 0 ? 0 : fixAngle(s->wave.getSwitchTime((triggerIndexOfZeroEvent + i) % s->size) * 720 - firstAngle);
i == 0 ?
0 :
fixAngle(s->wave.getSwitchTime((triggerIndexOfZeroEvent + i) % s->getSize()) * 720 - firstAngle);
chDbgCheck(angleOffset >= angle, "angle constraint violation in registerActuatorEventExt()");
if (angleOffset < angle) {
firmwareError("angle constraint violation in registerActuatorEventExt(): %f/%f", angleOffset, angle);
return;
}
registerActuatorEvent(list, i, actuator, angleOffset - angle);
}
@ -267,13 +281,6 @@ void registerActuatorEventExt(engine_configuration_s const *engineConfiguration,
// return 0;
//}
/**
* there is some BS related to isnan in MinGW, so let's have all the issues in one place
*/
int cisnan(float f) {
return *(((int*) (&f))) == 0x7FC00000;
}
static int order_1_THEN_3_THEN_4_THEN2[] = { 1, 3, 4, 2 };
static int order_1_THEN_5_THEN_3_THEN_6_THEN_2_THEN_4[] = { 1, 5, 3, 6, 2, 4 };

View File

@ -1,4 +1,4 @@
CONTROLLERS_MATH_SRC = $(PROJECT_DIR)/controllers/math/avg_values.c
CONTROLLERS_MATH_SRC =
CONTROLLERS_MATH_SRC_CPP = $(PROJECT_DIR)/controllers/math/engine_math.cpp

View File

@ -5,6 +5,7 @@
#include "adc_inputs.h"
#include "interpolation.h"
#include "error_handling.h"
#include "map.h"
extern engine_configuration_s * engineConfiguration;
@ -23,13 +24,8 @@ float getMAPValueMPX_4250(float voltage) {
return interpolate(0, 8, 5, 260, voltage);
}
/**
* @brief MAP value decoded according to current settings
* @returns kPa value
*/
float getMapByVoltage(float voltage) {
MapConf_s * config = &engineConfiguration->map.config;
switch (config->mapType) {
float decodePressure(float voltage, air_pressure_sensor_config_s * config) {
switch (config->sensorType) {
case MT_CUSTOM:
return interpolate(0, config->Min, 5, config->Max, voltage);
case MT_DENSO183:
@ -37,15 +33,26 @@ float getMapByVoltage(float voltage) {
case MT_MPX4250:
return getMAPValueMPX_4250(voltage);
default:
firmwareError("Unknown MAP type: %d", config->mapType);
firmwareError("Unknown MAP type: %d", config->sensorType);
return NAN;
}
// todo: here is the place where we should read the settings and decide
// todo: how to translate voltage into pressure
// return getMAPValueHonda_Denso183(voltage);
}
/**
* @brief MAP value decoded according to current settings
* @returns kPa value
*/
float getMapByVoltage(float voltage) {
air_pressure_sensor_config_s * config = &engineConfiguration->map.sensor;
return decodePressure(voltage, config);
}
float getRawMap(void) {
float voltage = getVoltageDivided(engineConfiguration->map.channel);
float voltage = getVoltageDivided(engineConfiguration->map.sensor.hwChannel);
return getMapByVoltage(voltage);
}
float getBaroPressure(void) {
float voltage = getVoltageDivided(engineConfiguration->baroSensor.hwChannel);
return decodePressure(voltage, &engineConfiguration->baroSensor);
}

View File

@ -10,10 +10,12 @@ extern "C"
* @return Raw MAP sensor value right now
*/
float getRawMap(void);
float getBaroPressure(void);
/**
* @return MAP value averaged within a window of measurement
*/
float getMap(void);
float getMapVoltage(void);
float getMapByVoltage(float voltage);
float getMAPValueHonda_Denso183(float volts);
float getMAPValueMPX_4250(float volts);

View File

@ -13,6 +13,13 @@
#include "rusefi_enums.h"
typedef struct {
float Min;
float Max;
air_pressure_sensor_type_e sensorType;
int hwChannel;
} air_pressure_sensor_config_s;
/**
* @brief MAP averaging configuration
*/
@ -29,15 +36,9 @@ typedef struct {
*/
float samplingWindow[MAP_WINDOW_SIZE];
float Min;
float Max;
map_type_e mapType;
} MapConf_s;
air_pressure_sensor_config_s sensor;
typedef struct {
MapConf_s config;
int channel;
} map_s;
} MAP_sensor_config_s;
/**

View File

@ -17,7 +17,6 @@
#include "engine_math.h"
#include "ec2.h"
extern engine_configuration_s *engineConfiguration;
extern engine_configuration2_s *engineConfiguration2;
@ -71,7 +70,10 @@ float convertKelvinToFahrenheit(float kelvin) {
}
float getKelvinTemperature(float resistance, ThermistorConf *thermistor) {
chDbgCheck(thermistor!=NULL, "thermistor pointer is NULL");
if (thermistor == NULL) {
firmwareError("thermistor pointer is NULL");
return NAN;
}
float kelvinTemperature = convertResistanceToKelvinTemperature(resistance, thermistor);
return kelvinTemperature;
@ -85,7 +87,10 @@ float getResistance(Thermistor *thermistor) {
}
float getTemperatureC(Thermistor *thermistor) {
chDbgCheck(initialized, "initialized");
if (!initialized) {
firmwareError("thermstr not initialized");
return NAN;
}
float resistance = getResistance(thermistor);
float kelvinTemperature = getKelvinTemperature(resistance, thermistor->config);

View File

@ -8,10 +8,8 @@
#include "main.h"
#include "settings.h"
#include "eficonsole.h"
#include "engine_configuration.h"
#include "flash_main.h"
#include "adc_inputs.h"
#include "engine_controller.h"
#include "thermistors.h"
@ -19,12 +17,17 @@
#include "interpolation.h"
#include "tps.h"
#include "ec2.h"
#include "map.h"
#if EFI_PROD_CODE
#include "rusefi.h"
#include "pin_repository.h"
#endif /* EFI_PROD_CODE */
#if EFI_INTERNAL_FLASH
#include "flash_main.h"
#endif /* EFI_INTERNAL_FLASH */
static Logging logger;
static char LOGGING_BUFFER[1000];
@ -150,12 +153,10 @@ void printConfiguration(engine_configuration_s *engineConfiguration, engine_conf
scheduleMsg(&logger, "needSecondTriggerInput: %d", engineConfiguration->needSecondTriggerInput);
#if EFI_PROD_CODE
scheduleMsg(&logger, "idleValvePin: %s", hwPortname(boardConfiguration->idleValvePin));
scheduleMsg(&logger, "fuelPumpPin: mode %d @ %s", boardConfiguration->fuelPumpPinMode, hwPortname(boardConfiguration->fuelPumpPin));
scheduleMsg(&logger, "fuelPumpPin: mode %d @ %s", boardConfiguration->fuelPumpPinMode,
hwPortname(boardConfiguration->fuelPumpPin));
scheduleMsg(&logger, "injectionPins: mode %d", boardConfiguration->injectionPinMode);
for (int i = 0; i < engineConfiguration->cylindersCount; i++) {
@ -171,8 +172,10 @@ void printConfiguration(engine_configuration_s *engineConfiguration, engine_conf
scheduleMsg(&logger, "ignition %d @ %s", i, hwPortname(brainPin));
}
scheduleMsg(&logger, "primary trigger simulator: %s %d", hwPortname(boardConfiguration->triggerSimulatorPins[0]), boardConfiguration->triggerSimulatorPinModes[0]);
scheduleMsg(&logger, "secondary trigger simulator: %s %d", hwPortname(boardConfiguration->triggerSimulatorPins[1]), boardConfiguration->triggerSimulatorPinModes[1]);
scheduleMsg(&logger, "primary trigger simulator: %s %d", hwPortname(boardConfiguration->triggerSimulatorPins[0]),
boardConfiguration->triggerSimulatorPinModes[0]);
scheduleMsg(&logger, "secondary trigger simulator: %s %d", hwPortname(boardConfiguration->triggerSimulatorPins[1]),
boardConfiguration->triggerSimulatorPinModes[1]);
#endif /* EFI_PROD_CODE */
scheduleMsg(&logger, "isInjectionEnabledFlag %d", engineConfiguration2->isInjectionEnabledFlag);
@ -193,10 +196,10 @@ static void setTimingMode(int value) {
incrementGlobalConfigurationVersion();
}
static void setEngineType(int value) {
engineConfiguration->engineType = (engine_type_e) value;
resetConfigurationExt((engine_type_e) value, engineConfiguration, engineConfiguration2, boardConfiguration);
#if EFI_PROD_CODE
void setEngineType(int value) {
engineConfiguration->engineType = (engine_type_e)value;
resetConfigurationExt(&logger, (engine_type_e) value, engineConfiguration, engineConfiguration2, boardConfiguration);
#if EFI_INTERNAL_FLASH
writeToFlash();
// scheduleReset();
#endif /* EFI_PROD_CODE */
@ -268,17 +271,35 @@ static void printThermistor(char *msg, Thermistor *thermistor) {
scheduleMsg(&logger, "%s v=%f C=%f R=%f on channel %d", msg, voltage, t, r, adcChannel);
scheduleMsg(&logger, "bias=%f A=%f B=%f C=%f", thermistor->config->bias_resistor, thermistor->config->s_h_a,
thermistor->config->s_h_b, thermistor->config->s_h_c);
#if EFI_PROD_CODE
#if EFI_ANALOG_INPUTS
scheduleMsg(&logger, "@%s", getPinNameByAdcChannel(adcChannel, pinNameBuffer));
#endif
}
static void printMAPInfo(void) {
#if EFI_PROD_CODE
scheduleMsg(&logger, "map type=%d raw=%f MAP=%f", engineConfiguration->map.sensor.sensorType, getRawMap(), getMap());
if (engineConfiguration->map.sensor.sensorType == MT_CUSTOM) {
scheduleMsg(&logger, "min=%f max=%f", engineConfiguration->map.sensor.Min,
engineConfiguration->map.sensor.Max);
}
scheduleMsg(&logger, "baro type=%d value=%f", engineConfiguration->baroSensor.sensorType, getBaroPressure());
if (engineConfiguration->baroSensor.sensorType == MT_CUSTOM) {
scheduleMsg(&logger, "min=%f max=%f", engineConfiguration->baroSensor.Min,
engineConfiguration->baroSensor.Max);
}
#endif
}
static void printTPSInfo(void) {
#if EFI_PROD_CODE
GPIO_TypeDef* port = getAdcChannelPort(engineConfiguration->tpsAdcChannel);
int pin = getAdcChannelPin(engineConfiguration->tpsAdcChannel);
scheduleMsg(&logger, "tps min %d/max %d v=%f @%s%d", engineConfiguration->tpsMin, engineConfiguration->tpsMax, getTPSVoltage(), portname(port), pin);
scheduleMsg(&logger, "tps min %d/max %d v=%f @%s%d", engineConfiguration->tpsMin, engineConfiguration->tpsMax,
getTPSVoltage(), portname(port), pin);
#endif
scheduleMsg(&logger, "current 10bit=%d value=%f rate=%f", getTPS10bitAdc(), getTPS(), getTpsRateOfChange());
}
@ -290,7 +311,7 @@ static void printTemperatureInfo(void) {
float rClt = getResistance(&engineConfiguration2->clt);
float rIat = getResistance(&engineConfiguration2->iat);
#if EFI_PROD_CODE
#if EFI_ANALOG_INPUTS
int cltChannel = engineConfiguration2->clt.channel;
scheduleMsg(&logger, "CLT R=%f on channel %d@%s", rClt, cltChannel,
getPinNameByAdcChannel(cltChannel, pinNameBuffer));
@ -322,7 +343,7 @@ static void setCrankingRpm(int value) {
}
static void setFiringOrder(int value) {
engineConfiguration->firingOrder = (firing_order_e)value;
engineConfiguration->firingOrder = (firing_order_e) value;
doPrintConfiguration();
}
@ -350,19 +371,19 @@ static void setCrankingTimingAngle(float value) {
}
static void setCrankingInjectionMode(int value) {
engineConfiguration->crankingInjectionMode = (injection_mode_e)value;
engineConfiguration->crankingInjectionMode = (injection_mode_e) value;
incrementGlobalConfigurationVersion();
doPrintConfiguration();
}
static void setInjectionMode(int value) {
engineConfiguration->injectionMode = (injection_mode_e)value;
engineConfiguration->injectionMode = (injection_mode_e) value;
incrementGlobalConfigurationVersion();
doPrintConfiguration();
}
static void setIgnitionMode(int value) {
engineConfiguration->ignitionMode = (ignition_mode_e)value;
engineConfiguration->ignitionMode = (ignition_mode_e) value;
incrementGlobalConfigurationVersion();
doPrintConfiguration();
}
@ -438,6 +459,7 @@ void initSettings(void) {
addConsoleAction("showconfig", doPrintConfiguration);
addConsoleAction("tempinfo", printTemperatureInfo);
addConsoleAction("tpsinfo", printTPSInfo);
addConsoleAction("mapinfo", printMAPInfo);
addConsoleActionI("set_ignition_offset", setIgnitionOffset);
addConsoleActionI("set_injection_offset", setInjectionOffset);

View File

@ -16,6 +16,7 @@ extern "C"
void initSettings(void);
void pokeControl(void);
void setEngineType(int value);
int getInjectionPeriod(void);
int getInjectionOffset(void);
int getInjectionDivider(void);

View File

@ -12,6 +12,8 @@
#include "SingleTimerExecutor.h"
#include "efitime.h"
#include "rfiutil.h"
#if EFI_PROD_CODE
#include "microsecond_timer.h"
#endif
@ -26,28 +28,60 @@ static void executorCallback(void *arg) {
instance.execute(getTimeNowUs());
}
void Executor::setTimer(uint64_t nowUs) {
uint64_t nextEventTime = queue.getNextEventTime(nowUs);
setHardwareUsTimer(nextEventTime - nowUs);
Executor::Executor() {
reentrantLock = FALSE;
}
Executor::Executor() {
void Executor::lock(void) {
lockAnyContext();
}
void Executor::unlock(void) {
unlockAnyContext();
}
void Executor::schedule(scheduling_s *scheduling, uint64_t nowUs, int delayUs, schfunc_t callback, void *param) {
if (!reentrantLock) {
// this would guard the queue and disable interrupts
lock();
}
queue.insertTask(scheduling, nowUs, delayUs, callback, param);
setTimer(nowUs);
if (!reentrantLock) {
doExecute(nowUs);
unlock();
}
}
void Executor::execute(uint64_t now) {
void Executor::execute(uint64_t nowUs) {
lock();
doExecute(nowUs);
unlock();
}
/*
* this private method is executed under lock
*/
void Executor::doExecute(uint64_t nowUs) {
/**
* Let's execute actions we should execute at this point
* Let's execute actions we should execute at this point.
* reentrantLock takes care of the use case where the actions we are executing are scheduling
* further invocations
*/
queue.executeAll(now);
reentrantLock = TRUE;
queue.executeAll(nowUs);
if (!isLocked()) {
firmwareError("Someone has stolen my lock");
return;
}
reentrantLock = FALSE;
/**
* Let's set up the timer for the next execution
*/
setTimer(now);
uint64_t nextEventTime = queue.getNextEventTime(nowUs);
efiAssert(nextEventTime > nowUs, "setTimer constraint");
if (nextEventTime == EMPTY_QUEUE)
return; // no pending events in the queue
setHardwareUsTimer(nextEventTime - nowUs);
}
/**
@ -60,20 +94,18 @@ void Executor::execute(uint64_t now) {
* @param [in] dwell the number of ticks of output duration.
*/
void scheduleTask(scheduling_s *scheduling, int delayUs, schfunc_t callback, void *param) {
efiAssert(delayUs >= 0, "delayUs"); // todo: remove this line?
if (delayUs < 0) {
firmwareError("Negative delayUs");
return;
}
if (delayUs == 0) {
callback(param);
return;
}
// todo: eliminate this /100. Times still come as systick times here
instance.schedule(scheduling, getTimeNowUs(), delayUs, callback, param);
}
void initOutputSignal(OutputSignal *signal, io_pin_e ioPin) {
signal->io_pin = ioPin;
signal->name = getPinName(ioPin);
initOutputSignalBase(signal);
}
void initSignalExecutorImpl(void) {
globalTimerCallback = executorCallback;
#if EFI_PROD_CODE

View File

@ -8,17 +8,31 @@
#ifndef SINGLETIMEREXECUTOR_H_
#define SINGLETIMEREXECUTOR_H_
#include "signal_executor.h"
#include "scheduler.h"
#include "event_queue.h"
class Executor {
public:
Executor();
void schedule(scheduling_s *scheduling, uint64_t nowUs, int delayUs, schfunc_t callback, void *param);
void execute(uint64_t now);
void execute(uint64_t nowUs);
private:
EventQueue queue;
void setTimer(uint64_t now);
bool_t reentrantLock;
void doExecute(uint64_t nowUs);
void lock(void);
void unlock(void);
};
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
void initSignalExecutorImpl(void);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* SINGLETIMEREXECUTOR_H_ */

View File

@ -0,0 +1,130 @@
/**
* @file event_queue.cpp
* This is a data structure which keeps track of all pending events
* Implemented as a linked list, which is fine since the number of
* pending events is pretty low
* todo: MAYBE migrate to a better data structure, but that's low priority
*
* this data structure is NOT thread safe
*
* @date Apr 17, 2014
* @author Andrey Belomutskiy, (c) 2012-2014
*/
#include "event_queue.h"
#include "efitime.h"
#include "utlist.h"
#if EFI_SIGNAL_EXECUTOR_ONE_TIMER
#define QUEUE_LENGTH_LIMIT 1000
EventQueue::EventQueue() {
head = NULL;
}
bool_t EventQueue::checkIfPending(scheduling_s *scheduling) {
// this code is just to validate state, no functional load
scheduling_s * current;
int counter = 0;
LL_FOREACH(head, current)
{
if (++counter > QUEUE_LENGTH_LIMIT) {
firmwareError("Looped queue?");
return FALSE;
}
if (current == scheduling) {
warning(OBD_PCM_Processor_Fault, "re-adding element into event_queue: [%s]", scheduling->name);
return TRUE;
}
}
return FALSE;
}
void EventQueue::insertTask(scheduling_s *scheduling, uint64_t nowUs, int delayUs, schfunc_t callback, void *param) {
if (callback == NULL)
firmwareError("NULL callback");
uint64_t time = nowUs + delayUs;
int alreadyPending = checkIfPending(scheduling);
if (alreadyPending || hasFirmwareError())
return;
scheduling->momentUs = time;
scheduling->callback = callback;
scheduling->param = param;
LL_PREPEND(head, scheduling);
}
//void EventQueue::insertTask(scheduling_s *scheduling, int delayUs, schfunc_t callback, void *param) {
// insertTask(scheduling, getTimeNowUs(), delayUs, callback, param);
//}
/**
* Get the timestamp of the soonest pending action
*/
uint64_t EventQueue::getNextEventTime(uint64_t nowUs) {
scheduling_s * current;
// this is a large value which is expected to be larger than any real time
uint64_t result = EMPTY_QUEUE;
int counter = 0;
LL_FOREACH(head, current)
{
if (++counter > QUEUE_LENGTH_LIMIT) {
firmwareError("Is this list looped #2?");
return EMPTY_QUEUE;
}
efiAssert(current->momentUs > nowUs, "executeAll should have been called");
if (current->momentUs < result)
result = current->momentUs;
}
return result;
}
/**
* Invoke all pending actions prior to specified timestamp
*/
void EventQueue::executeAll(uint64_t now) {
scheduling_s * current, *tmp;
scheduling_s * executionList = NULL;
int counter = 0;
// we need safe iteration because we are removing elements inside the loop
LL_FOREACH_SAFE(head, current, tmp)
{
if (++counter > QUEUE_LENGTH_LIMIT) {
firmwareError("Is this list looped?");
return;
}
if (current->momentUs <= now) {
LL_DELETE(head, current);
LL_PREPEND(executionList, current);
}
}
/*
* we need safe iteration here because 'callback' might change change 'current->next'
* while re-inserting it into the queue from within the callback
*/
LL_FOREACH_SAFE(executionList, current, tmp)
current->callback(current->param);
}
int EventQueue::size(void) {
scheduling_s *tmp;
int result;
LL_COUNT(head, tmp, result);
return result;
}
void EventQueue::clear(void) {
head = NULL;
}
#endif /* EFI_SIGNAL_EXECUTOR_ONE_TIMER */

View File

@ -1,30 +1,32 @@
/**
* @file event_queue.h
*
* @date Apr 17, 2014
* @author Andrey Belomutskiy, (c) 2012-2014
*/
#include "signal_executor.h"
#ifndef EVENT_SCHEDULER_H_
#define EVENT_SCHEDULER_H_
#define EMPTY_QUEUE 0x0FFFFFFFFFFFFFFFLL
class EventQueue {
public:
EventQueue();
void insertTask(scheduling_s *scheduling, int delayUs, schfunc_t callback, void *param);
void insertTask(scheduling_s *scheduling, uint64_t nowUs, int delayUs, schfunc_t callback, void *param);
void executeAll(uint64_t now);
uint64_t getNextEventTime(uint64_t nowUs);
void clear(void);
private:
scheduling_s *head;
};
#endif /* EVENT_SCHEDULER_H_ */
/**
* @file event_queue.h
*
* @date Apr 17, 2014
* @author Andrey Belomutskiy, (c) 2012-2014
*/
#include "scheduler.h"
#ifndef EVENT_SCHEDULER_H_
#define EVENT_SCHEDULER_H_
#define EMPTY_QUEUE 0x0FFFFFFFFFFFFFFFLL
class EventQueue {
public:
EventQueue();
// void insertTask(scheduling_s *scheduling, int delayUs, schfunc_t callback, void *param);
void insertTask(scheduling_s *scheduling, uint64_t nowUs, int delayUs, schfunc_t callback, void *param);
void executeAll(uint64_t now);
uint64_t getNextEventTime(uint64_t nowUs);
void clear(void);
int size(void);
private:
bool_t checkIfPending(scheduling_s *scheduling);
scheduling_s *head;
};
#endif /* EVENT_SCHEDULER_H_ */

View File

@ -1,14 +1,18 @@
/*
/**
* @file pwm_generator_logic.c
*
* This PWM implementation keep track of when it would be the next time to toggle the signal.
* It constantly sets timer to that next toggle time, then sets the timer again from the callback, and so on.
*
* @date Mar 2, 2014
* @author Andrey Belomutskiy, (c) 2012-2014
*/
#include "pwm_generator_logic.h"
#include "engine_math.h"
PwmConfig::PwmConfig(float *st, single_wave_s *waves) : multiWave(st, waves) {
PwmConfig::PwmConfig(float *st, single_wave_s *waves) :
multiWave(st, waves) {
scheduling.name = "PwmConfig";
}
static uint64_t getNextSwitchTimeUs(PwmConfig *state) {
@ -28,6 +32,9 @@ static uint64_t getNextSwitchTimeUs(PwmConfig *state) {
return state->safe.startUs + timeToSwitchUs;
}
/**
* @return Next time for signal toggle
*/
static uint64_t togglePwmState(PwmConfig *state) {
#if DEBUG_PWM
scheduleMsg(&logger, "togglePwmState phaseIndex=%d iteration=%d", state->safe.phaseIndex, state->safe.iteration);
@ -64,10 +71,11 @@ static uint64_t togglePwmState(PwmConfig *state) {
#if DEBUG_PWM
scheduleMsg(&logger, "%s: nextSwitchTime %d", state->name, nextSwitchTime);
#endif
uint64_t timeToSwitch = nextSwitchTimeUs - getTimeNowUs();
// signed value is needed here
int64_t timeToSwitch = nextSwitchTimeUs - getTimeNowUs();
if (timeToSwitch < 1) {
//todo: introduce error and test this error handling warning(OBD_PCM_Processor_Fault, "PWM: negative switch time");
timeToSwitch = 10;
timeToSwitch = 1000;
}
state->safe.phaseIndex++;
@ -80,7 +88,6 @@ static uint64_t togglePwmState(PwmConfig *state) {
static void timerCallback(PwmConfig *state) {
time_t timeToSleepUs = togglePwmState(state);
// parameter here is still in systicks
scheduleTask(&state->scheduling, timeToSleepUs, (schfunc_t) timerCallback, state);
}
@ -102,11 +109,14 @@ void copyPwmParameters(PwmConfig *state, int phaseCount, float *switchTimes, int
}
}
void weComplexInit(const char *msg, PwmConfig *state, int phaseCount, float *switchTimes, int waveCount, int **pinStates,
pwm_cycle_callback *cycleCallback, pwm_gen_callback *stateChangeCallback) {
void weComplexInit(const char *msg, PwmConfig *state, int phaseCount, float *switchTimes, int waveCount,
int **pinStates, pwm_cycle_callback *cycleCallback, pwm_gen_callback *stateChangeCallback) {
chDbgCheck(state->periodMs != 0, "period is not initialized");
chDbgCheck(phaseCount > 1, "count is too small");
if (phaseCount == 0) {
firmwareError("signal length cannot be zero");
return;
}
if (phaseCount > PWM_PHASE_MAX_COUNT) {
firmwareError("too many phases in PWM");
return;

View File

@ -9,9 +9,9 @@
#define PWM_GENERATOR_LOGIC_H_
#include "global.h"
#include "trigger_structure.h"
#include "EfiWave.h"
#include "io_pins.h"
#include "signal_executor.h"
#include "scheduler.h"
typedef struct {
/**

View File

@ -0,0 +1,40 @@
/**
* @file scheduler.h
*
* @date May 18, 2014
* @author Andrey Belomutskiy, (c) 2012-2014
*/
#ifndef SCHEDULER_H_
#define SCHEDULER_H_
#include "main.h"
typedef void (*schfunc_t)(void *);
typedef struct scheduling_struct scheduling_s;
struct scheduling_struct {
#if EFI_SIGNAL_EXECUTOR_SLEEP
VirtualTimer timer;
#endif /* EFI_SIGNAL_EXECUTOR_SLEEP */
#if EFI_SIGNAL_EXECUTOR_ONE_TIMER
volatile uint64_t momentUs;
schfunc_t callback;
void *param;
scheduling_s *next;
#endif
char *name;
};
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
void scheduleTask(scheduling_s *scheduling, int delayUs, schfunc_t callback, void *param);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* SCHEDULER_H_ */

View File

@ -1,28 +0,0 @@
/**
* @file signal_executor_gpt.c
*
* @date Apr 14, 2014
* @author Andrey Belomutskiy, (c) 2012-2014
*
* 32 bit timers in stm32f4: TIM2, TIM5
*
* Output resolution in general is discussed @ http://rusefi.com/forum/viewtopic.php?t=2
*/
//#include "main.h"
//static void gptCallback(GPTDriver *gptp) {
//
//}
//
//static const GPTConfig gpt3cfg = {
// 60000000, /* 60 MHz timer clock.*/
// gpt3cb /* Timer callback.*/
//};
//
//void initGptExecutor(void) {
//
// gptStart(&GPTD5, &gptCfg);
//
//}
//

View File

@ -1,37 +0,0 @@
/*
* @file signal_executor_hw_timer.c
*
* this is a future home of hardware TIM signal executor https://sourceforge.net/p/rusefi/tickets/6/
*
* @date Oct 28, 2013
* @author Andrey Belomutskiy, (c) 2012-2014
*
* 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/>.
*/
#include "main.h"
#include "signal_executor.h"
#include "signal_executor_hw_timer.h"
#if EFI_SIGNAL_EXECUTOR_HW_TIMER || defined(__DOXYGEN__)
void initOutputSignal(char *name, OutputSignal *signal, int led, int xor) {
// todo
}
void scheduleOutput(OutputSignal *signal, int delay, int dwell) {
// todo
}
#endif /* EFI_SIGNAL_EXECUTOR_HW_TIMER */

View File

@ -1,17 +0,0 @@
/*
* @file signal_executor_hw_timer.h
*
*
* @date Oct 28, 2013
* @author Andrey Belomutskiy, (c) 2012-2014
*/
#ifndef SIGNAL_EXECUTOR_HW_TIMER_H_
#define SIGNAL_EXECUTOR_HW_TIMER_H_
#include "main.h"
#if EFI_SIGNAL_EXECUTOR_HW_TIMER || defined(__DOXYGEN__)
#endif /* EFI_SIGNAL_EXECUTOR_HW_TIMER */
#endif /* SIGNAL_EXECUTOR_HW_TIMER_H_ */

View File

@ -23,10 +23,8 @@
*/
#include "main.h"
#include "signal_executor.h"
#include "scheduler.h"
#include "datalogging.h"
//#include "rpm_calculator.h"
//#include "engine_math.h"
#if EFI_SIGNAL_EXECUTOR_SLEEP || defined(__DOXYGEN__)
@ -49,13 +47,6 @@ void scheduleTask(scheduling_s *scheduling, int delayUs, schfunc_t callback, voi
unlockAnyContext();
}
void initOutputSignal(OutputSignal *signal, io_pin_e ioPin) {
signal->io_pin = ioPin;
signal->name = getPinName(ioPin);
// signal->duration = 0;
initOutputSignalBase(signal);
}
void initSignalExecutorImpl(void) {
}

View File

@ -8,7 +8,4 @@
#ifndef SIGNAL_EXECUTOR_SLEEP_H_
#define SIGNAL_EXECUTOR_SLEEP_H_
#include "global.h"
#include "efifeatures.h"
#endif /* SIGNAL_EXECUTOR_SLEEP_H_ */

View File

@ -1,8 +1,7 @@
SYSTEMSRC = \
$(PROJECT_DIR)/controllers/system/signal_executor_sleep.c \
$(PROJECT_DIR)/controllers/system/signal_executor_hw_timer.c
$(PROJECT_DIR)/controllers/system/signal_executor_sleep.c
SYSTEMSRC_CPP = $(PROJECT_DIR)/controllers/system/trigger_emulator_algo.cpp \
$(PROJECT_DIR)/controllers/system/pwm_generator_logic.cpp \
SYSTEMSRC_CPP = $(PROJECT_DIR)/controllers/system/pwm_generator_logic.cpp \
$(PROJECT_DIR)/controllers/system/event_queue.cpp \
$(PROJECT_DIR)/controllers/system/SingleTimerExecutor.cpp

View File

@ -22,18 +22,18 @@
*/
#include "main.h"
#if EFI_ENGINE_CONTROL
#include "main_trigger_callback.h"
#include "ec2.h"
extern "C" {
//#include "settings.h"
#include "trigger_central.h"
#include "rpm_calculator.h"
#include "signal_executor.h"
#include "eficonsole.h"
#include "engine_math.h"
//#include "injector_central.h"
//#include "ignition_central.h"
#include "engine_configuration.h"
#include "interpolation.h"
#include "advance_map.h"
@ -51,8 +51,6 @@ int isInjectionEnabled(void);
}
// todo: move this to engine_configuration2_s for now
extern engine_configuration_s *engineConfiguration;
extern engine_configuration2_s *engineConfiguration2;
@ -81,7 +79,7 @@ static void handleFuelInjectionEvent(ActuatorEvent *event, int rpm) {
scheduleOutput(event->actuator, delay, fuelMs);
}
static void handleFuel(int eventIndex) {
static void handleFuel(int eventIndex, int rpm) {
if (!isInjectionEnabled())
return;
chDbgCheck(eventIndex < engineConfiguration2->triggerShape.shaftPositionEventCount, "event index");
@ -99,10 +97,6 @@ static void handleFuel(int eventIndex) {
if (events.size == 0)
return;
// scheduleSimpleMsg(&logger, "eventId size=", events.size);
int rpm = getRpm();
for (int i = 0; i < events.size; i++) {
ActuatorEvent *event = &events.events[i];
handleFuelInjectionEvent(event, rpm);
@ -110,15 +104,11 @@ static void handleFuel(int eventIndex) {
}
static void handleSparkEvent(ActuatorEvent *event, int rpm) {
efiAssert(rpm != 0, "non-zero RPM expected here");
// float advance = getAdvance(rpm, getEngineLoad());
// float sparkAdvanceMs = getOneDegreeTimeMs(rpm) * advance;
float dwellMs = getSparkDwellMs(rpm);
if (dwellMs < 0)
if (cisnan(dwellMs) || dwellMs < 0) {
firmwareError("invalid dwell: %f at %d", dwellMs, rpm);
return;
}
float sparkDelay = getOneDegreeTimeMs(rpm) * event->angleOffset;
int isIgnitionError = sparkDelay < 0;
@ -132,14 +122,15 @@ static void handleSparkEvent(ActuatorEvent *event, int rpm) {
scheduleOutput(event->actuator, sparkDelay, dwellMs);
}
static void handleSpark(int eventIndex) {
int rpm = getRpm();
static void handleSpark(int eventIndex, int rpm, ActuatorEventList *list) {
if (!isValidRpm(rpm))
return; // this might happen for instance in case of a single trigger event after a pause
/**
* Ignition schedule is defined once per revolution
* See initializeIgnitionActions()
*/
findEvents(eventIndex, &engineConfiguration2->engineEventConfiguration.ignitionEvents, &events);
findEvents(eventIndex, list, &events);
if (events.size == 0)
return;
@ -158,9 +149,10 @@ void showMainHistogram(void) {
}
/**
* This is the main entry point into the primary shaft signal handler signal. Both injection and ignition are controlled from this method.
* This is the main trigger event handler.
* Both injection and ignition are controlled from this method.
*/
static void onShaftSignal(ShaftEvents ckpSignalType, int eventIndex) {
static void onTriggerEvent(ShaftEvents ckpSignalType, int eventIndex) {
chDbgCheck(eventIndex < engineConfiguration2->triggerShape.shaftPositionEventCount, "event index");
int rpm = getRpm();
@ -170,7 +162,7 @@ static void onShaftSignal(ShaftEvents ckpSignalType, int eventIndex) {
return;
}
if (rpm == NOISY_RPM) {
scheduleMsg(&logger, "noisy trigger");
warning(OBD_Camshaft_Position_Sensor_Circuit_Range_Performance, "noisy trigger");
return;
}
if (rpm > engineConfiguration->rpmHardLimit) {
@ -179,6 +171,9 @@ static void onShaftSignal(ShaftEvents ckpSignalType, int eventIndex) {
}
int beforeCallback = hal_lld_get_counter_value();
int revolutionIndex = getRevolutionCounter() % 2;
if (eventIndex == 0) {
if (localVersion.isOld())
prepareOutputSignals(engineConfiguration, engineConfiguration2);
@ -191,19 +186,29 @@ static void onShaftSignal(ShaftEvents ckpSignalType, int eventIndex) {
* are not affecting that space in memory. todo: use two instances of 'ignitionSignals'
*/
/**
* Within one engine cycle all cylinders are fired with same timing advance.
* todo: one day we can control cylinders individually
*/
float dwellMs = getSparkDwellMs(rpm);
if (cisnan(dwellMs) || dwellMs < 0) {
firmwareError("invalid dwell: %f at %d", dwellMs, rpm);
return;
}
float advance = getAdvance(rpm, getEngineLoad());
float dwellAngle = dwellMs / getOneDegreeTimeMs(rpm);
initializeIgnitionActions(advance - dwellAngle, engineConfiguration, engineConfiguration2);
initializeIgnitionActions(advance - dwellAngle, engineConfiguration, engineConfiguration2, dwellMs, &engineConfiguration2->engineEventConfiguration.ignitionEvents[revolutionIndex]);
}
handleFuel(eventIndex);
handleSpark(eventIndex);
handleFuel(eventIndex, rpm);
handleSpark(eventIndex, rpm, &engineConfiguration2->engineEventConfiguration.ignitionEvents[revolutionIndex]);
#if EFI_HISTOGRAMS
int diff = hal_lld_get_counter_value() - beforeCallback;
if (diff > 0)
hsAdd(&mainLoopHisto, diff);
#endif /* EFI_HISTOGRAMS */
}
static void showTriggerHistogram(void) {
@ -224,14 +229,18 @@ void initMainEventListener() {
initLogging(&logger, "main event handler");
printMsg(&logger, "initMainLoop: %d", currentTimeMillis());
#if EFI_HISTOGRAMS
initHistogram(&mainLoopHisto, "main callback");
#endif /* EFI_HISTOGRAMS */
if (!isInjectionEnabled())
printMsg(&logger, "!!!!!!!!!!!!!!!!!!! injection disabled");
addTriggerEventListener(&onShaftSignal, "main loop");
addTriggerEventListener(&onTriggerEvent, "main loop");
}
int isIgnitionTimingError(void) {
return ignitionErrorDetection.sum(6) > 4;
}
#endif /* EFI_ENGINE_CONTROL */

View File

@ -11,17 +11,24 @@
*/
#include "main.h"
#if EFI_SHAFT_POSITION_INPUT
#include "rpm_calculator.h"
#include "trigger_central.h"
#include "engine_configuration.h"
#include "ec2.h"
#include "engine_math.h"
#if EFI_PROD_CODE || EFI_SIMULATOR
#include "rfiutil.h"
#if EFI_ANALOG_CHART
#include "analog_chart.h"
#endif /* EFI_PROD_CODE */
#if EFI_WAVE_CHART
#include "wave_chart.h"
#include "rfiutil.h"
extern WaveChart waveChart;
#endif /* EFI_WAVE_CHART */
static rpm_s rpmState;
@ -31,23 +38,26 @@ static rpm_s rpmState;
extern engine_configuration_s *engineConfiguration;
extern engine_configuration2_s *engineConfiguration2;
extern WaveChart waveChart;
static Logging logger;
/**
* @return true if there was a full shaft revolution within the last second
*/
int isRunning() {
bool_t isRunning(void) {
uint64_t nowUs = getTimeNowUs();
return nowUs - rpmState.lastRpmEventTimeUs < US_PER_SECOND;
}
bool_t isValidRpm(int rpm) {
return rpm > 0 && rpm < UNREALISTIC_RPM;
}
uint64_t getLastRpmEventTime(void) {
return rpmState.lastRpmEventTimeUs;
}
int isCranking(void) {
bool_t isCranking(void) {
int rpm = getRpm();
return isCrankingR(rpm);
}
@ -89,31 +99,33 @@ static int isNoisySignal(rpm_s * rpmState, uint64_t nowUs) {
static uint8_t shaft_signal_msg_index[15];
void addWaveChartEvent(char *name, char * msg, char *msg2) {
void addWaveChartEvent(const char *name, const char * msg, const char *msg2) {
#if EFI_WAVE_CHART
addWaveChartEvent3(&waveChart, name, msg, msg2);
#endif /* EFI_WAVE_CHART */
}
/**
* @brief Shaft position callback used by RPM calculation logic.
*
* This callback should always be the first of trigger callbacks because other callbacks depend of values
* updated here.
* This callback is invoked on interrupt thread.
*/
static void shaftPositionCallback(ShaftEvents ckpSignalType, int index) {
itoa10(&shaft_signal_msg_index[1], index);
if (ckpSignalType == SHAFT_PRIMARY_UP) {
addWaveChartEvent("crank", "up", (char*)shaft_signal_msg_index);
addWaveChartEvent("crank", "up", (char*) shaft_signal_msg_index);
} else if (ckpSignalType == SHAFT_PRIMARY_DOWN) {
addWaveChartEvent("crank", "down", (char*)shaft_signal_msg_index);
addWaveChartEvent("crank", "down", (char*) shaft_signal_msg_index);
} else if (ckpSignalType == SHAFT_SECONDARY_UP) {
addWaveChartEvent("crank2", "up", (char*)shaft_signal_msg_index);
addWaveChartEvent("crank2", "up", (char*) shaft_signal_msg_index);
} else if (ckpSignalType == SHAFT_SECONDARY_DOWN) {
addWaveChartEvent("crank2", "down", (char*)shaft_signal_msg_index);
addWaveChartEvent("crank2", "down", (char*) shaft_signal_msg_index);
}
if (index != 0) {
#if EFI_PROD_CODE || EFI_SIMULATOR
#if EFI_ANALOG_CHART
if (engineConfiguration->analogChartMode == AC_TRIGGER)
acAddData(getCrankshaftAngle(getTimeNowUs()), 1000 * ckpSignalType + index);
#endif
@ -136,41 +148,45 @@ static void shaftPositionCallback(ShaftEvents ckpSignalType, int index) {
// / 4 because each cylinder sends a signal
// need to measure time from the previous non-skipped event
int rpm = (int)(60 * US_PER_SECOND / engineConfiguration->rpmMultiplier / diff);
int rpm = (int) (60 * US_PER_SECOND / engineConfiguration->rpmMultiplier / diff);
rpmState.rpm = rpm > UNREALISTIC_RPM ? NOISY_RPM : rpm;
}
}
rpmState.lastRpmEventTimeUs = nowUs;
#if EFI_PROD_CODE || EFI_SIMULATOR
#if EFI_ANALOG_CHART
if (engineConfiguration->analogChartMode == AC_TRIGGER)
acAddData(getCrankshaftAngle(nowUs), index);
#endif
}
static scheduling_s tdcScheduler;
static scheduling_s tdcScheduler[2];
static uint8_t rpmBuffer[10];
static void onTdcCallback(void) {
itoa10(rpmBuffer, getRpm());
addWaveChartEvent(TOP_DEAD_CENTER_MESSAGE, (char*)rpmBuffer, "");
addWaveChartEvent(TOP_DEAD_CENTER_MESSAGE, (char*) rpmBuffer, "");
}
static void tdcMarkCallback(ShaftEvents ckpSignalType, int index) {
if (index == 0) {
scheduleByAngle(&tdcScheduler, engineConfiguration->globalTriggerAngleOffset, (schfunc_t) onTdcCallback, NULL);
int index = getRevolutionCounter() % 2;
scheduleByAngle(&tdcScheduler[index], engineConfiguration->globalTriggerAngleOffset, (schfunc_t) onTdcCallback, NULL);
}
}
void initRpmCalculator(void) {
initLogging(&logger, "rpm calc");
strcpy((char*)shaft_signal_msg_index, "_");
tdcScheduler[0].name = "tdc0";
tdcScheduler[1].name = "tdc1";
strcpy((char*) shaft_signal_msg_index, "_");
rpmState.rpm = 0;
// we need this initial to have not_running at first invocation
rpmState.lastRpmEventTimeUs = (uint64_t)-10 * US_PER_SECOND;
rpmState.lastRpmEventTimeUs = (uint64_t) -10 * US_PER_SECOND;
addTriggerEventListener(&shaftPositionCallback, "rpm reporter");
addTriggerEventListener(&tdcMarkCallback, "chart TDC mark");
@ -182,6 +198,18 @@ void initRpmCalculator(void) {
* it takes the crankshaft to rotate to the specified angle.
*/
void scheduleByAngle(scheduling_s *timer, float angle, schfunc_t callback, void *param) {
float delayMs = getOneDegreeTimeMs(getRpm()) * angle;
scheduleTask(timer, MS2US(delayMs), callback, param);
int rpm = getRpm();
if (!isValidRpm(rpm)) {
// this might happen in case of a single trigger event after a pause
warning(OBD_PCM_Processor_Fault, "Invalid rpm: %d", rpm);
return;
}
float delayMs = getOneDegreeTimeMs(rpm) * angle;
if (cisnan(delayMs)) {
firmwareError("NaN delay?");
return;
}
scheduleTask(timer, (int)MS2US(delayMs), callback, param);
}
#endif /* EFI_SHAFT_POSITION_INPUT */

View File

@ -36,13 +36,14 @@ void initRpmCalculator(void);
* @brief Current RPM
*/
int getRpm(void);
int isCranking(void);
bool_t isCranking(void);
uint64_t getLastRpmEventTime(void);
int getRevolutionCounter(void);
float getCrankshaftAngle(uint64_t timeUs);
int isRunning(void);
void addWaveChartEvent(char *name, char *msg, char *msg2);
bool_t isRunning(void);
bool_t isValidRpm(int rpm);
void addWaveChartEvent(const char *name, const char *msg, const char *msg2);
#ifdef __cplusplus
}

View File

@ -1,12 +1,16 @@
TRIGGER_SRC =
TRIGGER_SRC_CPP = \
$(PROJECT_DIR)/controllers/trigger/rpm_calculator.cpp \
$(PROJECT_DIR)/controllers/trigger/trigger_central.cpp \
TRIGGER_DECODERS_SRC_CPP = \
$(PROJECT_DIR)/controllers/trigger/trigger_bmw.cpp \
$(PROJECT_DIR)/controllers/trigger/trigger_mazda.cpp \
$(PROJECT_DIR)/controllers/trigger/trigger_chrysler.cpp \
$(PROJECT_DIR)/controllers/trigger/trigger_structure.cpp \
$(PROJECT_DIR)/controllers/trigger/trigger_decoder.cpp \
$(PROJECT_DIR)/controllers/trigger/trigger_chrysler.cpp \
$(PROJECT_DIR)/controllers/trigger/trigger_gm.cpp \
$(PROJECT_DIR)/controllers/trigger/trigger_gm.cpp
TRIGGER_SRC_CPP = \
$(PROJECT_DIR)/controllers/trigger/trigger_emulator_algo.cpp \
$(PROJECT_DIR)/controllers/trigger/rpm_calculator.cpp \
$(PROJECT_DIR)/controllers/trigger/trigger_central.cpp \
$(PROJECT_DIR)/controllers/trigger/main_trigger_callback.cpp

View File

@ -0,0 +1,41 @@
/**
* @file trigger_bmw.cpp
*
* @date May 11, 2014
* @author Andrey Belomutskiy, (c) 2012-2014
*/
#include "trigger_bmw.h"
void configureMiniCooperTriggerShape(engine_configuration_s *engineConfiguration,
engine_configuration2_s *engineConfiguration2) {
trigger_shape_s *s = &engineConfiguration2->triggerShape;
s->reset();
s->initialState[0] = 1;
float w = 2.96;
float a = w / 2;
for (int i = 0; i < 19; i++) {
a += w;
s->addEvent(a, T_SECONDARY, TV_HIGH);
a += w;
s->addEvent(a, T_SECONDARY, TV_LOW);
}
a += 3 * w;
s->addEvent(a, T_SECONDARY, TV_HIGH);
a += 2 * w;
s->addEvent(a, T_SECONDARY, TV_LOW);
s->addEvent(376.4444444, T_PRIMARY, TV_LOW);
s->addEvent(720, T_PRIMARY, TV_HIGH);
s->shaftPositionEventCount = s->getSize();
/**
* With just one tooth on camshaft synchronization is not needed
*/
engineConfiguration->triggerConfig.isSynchronizationNeeded = FALSE;
}

View File

@ -0,0 +1,16 @@
/**
* @file trigger_bmw.h
*
* @date May 11, 2014
* @author Andrey Belomutskiy, (c) 2012-2014
*/
#ifndef TRIGGER_BMW_H_
#define TRIGGER_BMW_H_
#include "engine_configuration.h"
#include "ec2.h"
void configureMiniCooperTriggerShape(engine_configuration_s *engineConfiguration,
engine_configuration2_s *engineConfiguration2);
#endif /* TRIGGER_BMW_H_ */

View File

@ -100,10 +100,12 @@ void hwHandleShaftSignal(ShaftEvents signal) {
invokeIntIntCallbacks(&triggerListeneres, signal, triggerState.current_index);
}
int afterCallback = hal_lld_get_counter_value();
#if EFI_HISTOGRAMS
int diff = afterCallback - beforeCallback;
// this counter is only 32 bits so it overflows every minute, let's ignore the value in case of the overflow for simplicity
if (diff > 0)
hsAdd(&triggerCallback, diff);
#endif /* EFI_HISTOGRAMS */
}
void printAllCallbacksHistogram(void) {
@ -115,7 +117,9 @@ void initTriggerCentral(void) {
memset(hwEventCounters, 0, sizeof(hwEventCounters));
#if EFI_HISTOGRAMS
initHistogram(&triggerCallback, "all callbacks");
#endif /* EFI_HISTOGRAMS */
initTriggerDecoder();
clearTriggerState(&triggerState);
}

View File

@ -2,13 +2,13 @@
* @file trigger_chrysler.cpp
*
* @date Mar 24, 2014
* @author Andrey Belomutskiy, (c) 2012-2013
* @author Andrey Belomutskiy, (c) 2012-2014
*/
#include "trigger_chrysler.h"
void configureNeonTriggerShape(trigger_shape_s *s) {
triggerShapeInit(s);
s->reset();
// voodoo magic - we always need 720 at the end
int base = 720 - 560;

View File

@ -8,17 +8,8 @@
#ifndef TRIGGER_CHRYSLER_H_
#define TRIGGER_CHRYSLER_H_
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
#include "trigger_structure.h"
void configureNeonTriggerShape(trigger_shape_s *s);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* TRIGGER_CHRYSLER_H_ */

View File

@ -22,10 +22,12 @@
#include "obd_error_codes.h"
#include "trigger_decoder.h"
#include "cyclic_buffer.h"
extern "C" {
#include "trigger_mazda.h"
#include "trigger_chrysler.h"
#include "trigger_gm.h"
#include "trigger_bmw.h"
extern "C" {
#include "trigger_structure.h"
#include "wave_math.h"
}
@ -142,11 +144,11 @@ void initializeSkippedToothTriggerShapeExt(engine_configuration2_s *engineConfig
initializeSkippedToothTriggerShape(s, totalTeethCount, skippedCount);
s->shaftPositionEventCount = ((totalTeethCount - skippedCount) * 2);
s->wave.checkSwitchTimes(s->size);
s->wave.checkSwitchTimes(s->getSize());
}
static void configureFordAspireTriggerShape(trigger_shape_s * s) {
triggerShapeInit(s);
s->reset();
s->shaftPositionEventCount = 10;
@ -163,8 +165,14 @@ static void configureFordAspireTriggerShape(trigger_shape_s * s) {
triggerAddEvent(s, 720, T_PRIMARY, TV_LOW);
}
void initializeTriggerShape(engine_configuration_s *engineConfiguration,
/**
* External logger is needed because at this point our logger is not yet initialized
*/
void initializeTriggerShape(Logging *logger, engine_configuration_s *engineConfiguration,
engine_configuration2_s *engineConfiguration2) {
#if EFI_PROD_CODE
printMsg(logger, "initializeTriggerShape()");
#endif
trigger_config_s *tt = &engineConfiguration->triggerConfig;
switch (tt->triggerType) {
@ -192,13 +200,17 @@ void initializeTriggerShape(engine_configuration_s *engineConfiguration,
configureMazdaProtegeLx(engineConfiguration, engineConfiguration2);
return;
case TT_MINI_COOPER_R50:
configureMiniCooperTriggerShape(engineConfiguration, engineConfiguration2);
return;
default:
firmwareError("initializeTriggerShape() not implemented: %d", tt->triggerType);
;
}
}
int findTriggerZeroEventIndex(trigger_shape_s const * shape, trigger_config_s const*triggerConfig) {
int findTriggerZeroEventIndex(trigger_shape_s * shape, trigger_config_s const*triggerConfig) {
trigger_state_s state;
clearTriggerState(&state);
@ -209,11 +221,11 @@ int findTriggerZeroEventIndex(trigger_shape_s const * shape, trigger_config_s co
for (int i = 0; i < 100; i++) {
int stateIndex = i % shape->size;
int stateIndex = i % shape->getSize();
int loopIndex = i / shape->size;
int loopIndex = i / shape->getSize();
int time = 10000 * (loopIndex + shape->wave.getSwitchTime(stateIndex));
int time = (int)(10000 * (loopIndex + shape->wave.getSwitchTime(stateIndex)));
int newPrimaryWheelState = shape->wave.getChannelState(0, stateIndex);
int newSecondaryWheelState = shape->wave.getChannelState(1, stateIndex);

View File

@ -23,8 +23,8 @@ extern "C"
int isTriggerDecoderError(void);
void processTriggerEvent(trigger_state_s *shaftPositionState, trigger_shape_s const*triggerShape, trigger_config_s const*triggerConfig, ShaftEvents signal, uint64_t nowUs);
void initializeSkippedToothTriggerShapeExt(engine_configuration2_s *engineConfiguration2, int totalTeethCount, int skippedCount);
void initializeTriggerShape(engine_configuration_s *engineConfiguration, engine_configuration2_s *engineConfiguration2);
int findTriggerZeroEventIndex(trigger_shape_s const * shape, trigger_config_s const*triggerConfig);
void initializeTriggerShape(Logging *logger, engine_configuration_s *engineConfiguration, engine_configuration2_s *engineConfiguration2);
int findTriggerZeroEventIndex(trigger_shape_s * shape, trigger_config_s const*triggerConfig);
void initTriggerDecoder(void);

View File

@ -1,71 +1,71 @@
/**
* @file trigger_emulator_algo.c
*
* @date Mar 3, 2014
* @author Andrey Belomutskiy, (c) 2012-2014
*/
#include "main.h"
#include "trigger_emulator_algo.h"
#include "engine_configuration.h"
#include "wave_math.h"
#include "LocalVersionHolder.h"
#include "ec2.h"
extern engine_configuration_s *engineConfiguration;
extern engine_configuration2_s *engineConfiguration2;
/*
* todo: should we simply re-use instances used by trigger_decoder?
* todo: since we are emulating same shape we are decoding
*/
static int pinStates1[PWM_PHASE_MAX_COUNT];
static int pinStates2[PWM_PHASE_MAX_COUNT];
static single_wave_s waves[2] = {single_wave_s(pinStates1), single_wave_s(pinStates2)};
static single_wave_s sr[2] = {waves[0], waves[1]};
static float swtchTms[PWM_PHASE_MAX_COUNT];
PwmConfig triggerSignal(swtchTms, sr);
static Logging logger;
static LocalVersionHolder localVersion;
void setTriggerEmulatorRPM(int rpm) {
/**
* All we need to do here is to change the periodMs
* togglePwmState() would see that the periodMs has changed and act accordingly
*/
if (rpm == 0) {
triggerSignal.periodMs = NAN;
} else {
float gRpm = rpm * engineConfiguration->rpmMultiplier / 60.0; // per minute converted to per second
triggerSignal.periodMs = frequency2period(gRpm);
}
scheduleMsg(&logger, "Emulating position sensor(s). RPM=%d", rpm);
}
static void updateTriggerShapeIfNeeded(PwmConfig *state) {
if(localVersion.isOld()) {
scheduleMsg(&logger, "Stimulator: updating trigger shape: %d/%d %d", localVersion.getVersion(), getGlobalConfigurationVersion(), currentTimeMillis());
trigger_shape_s *s = &engineConfiguration2->triggerShape;
int *pinStates[2] = {s->wave.waves[0].pinStates, s->wave.waves[1].pinStates};
copyPwmParameters(state, s->size, s->wave.switchTimes, 2, pinStates);
state->safe.periodMs = -1; // this would cause loop re-initialization
}
}
void initTriggerEmulatorLogic(pwm_gen_callback *stateChangeCallback) {
initLogging(&logger, "position sensor(s) emulator");
trigger_shape_s *s = &engineConfiguration2->triggerShape;
setTriggerEmulatorRPM(DEFAULT_EMULATION_RPM);
int *pinStates[2] = {s->wave.waves[0].pinStates, s->wave.waves[1].pinStates};
weComplexInit("position sensor", &triggerSignal, s->size, s->wave.switchTimes, 2, pinStates,
updateTriggerShapeIfNeeded,
stateChangeCallback);
addConsoleActionI("rpm", &setTriggerEmulatorRPM);
}
/**
* @file trigger_emulator_algo.c
*
* @date Mar 3, 2014
* @author Andrey Belomutskiy, (c) 2012-2014
*/
#include "main.h"
#include "trigger_emulator_algo.h"
#include "engine_configuration.h"
#include "wave_math.h"
#include "LocalVersionHolder.h"
#include "ec2.h"
extern engine_configuration_s *engineConfiguration;
extern engine_configuration2_s *engineConfiguration2;
/*
* todo: should we simply re-use instances used by trigger_decoder?
* todo: since we are emulating same shape we are decoding
*/
static int pinStates1[PWM_PHASE_MAX_COUNT];
static int pinStates2[PWM_PHASE_MAX_COUNT];
static single_wave_s waves[2] = {single_wave_s(pinStates1), single_wave_s(pinStates2)};
static single_wave_s sr[2] = {waves[0], waves[1]};
static float swtchTms[PWM_PHASE_MAX_COUNT];
PwmConfig triggerSignal(swtchTms, sr);
static Logging logger;
static LocalVersionHolder localVersion;
void setTriggerEmulatorRPM(int rpm) {
/**
* All we need to do here is to change the periodMs
* togglePwmState() would see that the periodMs has changed and act accordingly
*/
if (rpm == 0) {
triggerSignal.periodMs = NAN;
} else {
float gRpm = rpm * engineConfiguration->rpmMultiplier / 60.0; // per minute converted to per second
triggerSignal.periodMs = frequency2period(gRpm);
}
scheduleMsg(&logger, "Emulating position sensor(s). RPM=%d", rpm);
}
static void updateTriggerShapeIfNeeded(PwmConfig *state) {
if(localVersion.isOld()) {
scheduleMsg(&logger, "Stimulator: updating trigger shape: %d/%d %d", localVersion.getVersion(), getGlobalConfigurationVersion(), currentTimeMillis());
trigger_shape_s *s = &engineConfiguration2->triggerShape;
int *pinStates[2] = {s->wave.waves[0].pinStates, s->wave.waves[1].pinStates};
copyPwmParameters(state, s->getSize(), s->wave.switchTimes, 2, pinStates);
state->safe.periodMs = -1; // this would cause loop re-initialization
}
}
void initTriggerEmulatorLogic(pwm_gen_callback *stateChangeCallback) {
initLogging(&logger, "position sensor(s) emulator");
trigger_shape_s *s = &engineConfiguration2->triggerShape;
setTriggerEmulatorRPM(DEFAULT_EMULATION_RPM);
int *pinStates[2] = {s->wave.waves[0].pinStates, s->wave.waves[1].pinStates};
weComplexInit("position sensor", &triggerSignal, s->getSize(), s->wave.switchTimes, 2, pinStates,
updateTriggerShapeIfNeeded,
stateChangeCallback);
addConsoleActionI("rpm", &setTriggerEmulatorRPM);
}

View File

@ -1,28 +1,28 @@
/**
* @file trigger_emulator_algo.h
*
* @date Mar 3, 2014
* @author Andrey Belomutskiy, (c) 2012-2014
*/
#ifndef TRIGGER_EMULATOR_ALGO_H_
#define TRIGGER_EMULATOR_ALGO_H_
#include "pwm_generator_logic.h"
/**
* this is RPM. 10000 rpm is only 166Hz, 800 rpm is 13Hz
*/
#define DEFAULT_EMULATION_RPM 1200
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
void initTriggerEmulatorLogic(pwm_gen_callback *callback);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* TRIGGER_EMULATOR_ALGO_H_ */
/**
* @file trigger_emulator_algo.h
*
* @date Mar 3, 2014
* @author Andrey Belomutskiy, (c) 2012-2014
*/
#ifndef TRIGGER_EMULATOR_ALGO_H_
#define TRIGGER_EMULATOR_ALGO_H_
#include "pwm_generator_logic.h"
/**
* this is RPM. 10000 rpm is only 166Hz, 800 rpm is 13Hz
*/
#define DEFAULT_EMULATION_RPM 1200
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
void initTriggerEmulatorLogic(pwm_gen_callback *callback);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* TRIGGER_EMULATOR_ALGO_H_ */

View File

@ -8,7 +8,7 @@
#include "trigger_gm.h"
void configureGmTriggerShape(trigger_shape_s *s) {
triggerShapeInit(s);
s->reset();
// all angles are x2 here - so, 5 degree width is 10
float w = 10;

View File

@ -8,18 +8,8 @@
#ifndef TRIGGER_GM_H_
#define TRIGGER_GM_H_
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
#include "trigger_structure.h"
void configureGmTriggerShape(trigger_shape_s *s);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* TRIGGER_GM_H_ */

View File

@ -21,7 +21,7 @@
#include "trigger_mazda.h"
void initializeMazdaMiataNbShape(trigger_shape_s *s) {
triggerShapeInit(s);
s->reset();
/**
* cam sensor is primary, crank sensor is secondary
@ -62,7 +62,7 @@ void configureMazdaProtegeLx(engine_configuration_s *engineConfiguration,
trigger_shape_s *s = &engineConfiguration2->triggerShape;
triggerShapeInit(s);
s->reset();
// s->initialState[0] = 1;
float w = 720 / 4 * 0.215;
@ -94,8 +94,8 @@ void configureMazdaProtegeLx(engine_configuration_s *engineConfiguration,
triggerAddEvent(s, a, T_PRIMARY, TV_LOW);
a += 180;
triggerAddEvent(s, a - z * 720, T_PRIMARY, TV_HIGH);
triggerAddEvent(s, a, T_PRIMARY, TV_LOW);
s->addEvent(a - z * 720, T_PRIMARY, TV_HIGH);
s->addEvent(a, T_PRIMARY, TV_LOW);
// s->shaftPositionEventCount = 2 + 8;

Some files were not shown because too many files have changed in this diff Show More