manual sync
This commit is contained in:
parent
c4061aa46f
commit
e39e080551
|
@ -43,6 +43,7 @@
|
|||
<listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/config/boards}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/controllers}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/controllers/algo}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/controllers/core}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/controllers/trigger}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/controllers/sensors}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/controllers/system}""/>
|
||||
|
@ -102,6 +103,7 @@
|
|||
<listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/config/boards}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/controllers}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/controllers/algo}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/controllers/core}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/controllers/trigger}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/controllers/sensors}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/controllers/system}""/>
|
||||
|
|
|
@ -743,8 +743,9 @@ INPUT = . \
|
|||
util \
|
||||
console \
|
||||
controllers \
|
||||
controllers/math \
|
||||
controllers/algo \
|
||||
controllers/core \
|
||||
controllers/math \
|
||||
controllers/sensors \
|
||||
controllers/system \
|
||||
controllers/trigger \
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
//
|
||||
|
|
|
@ -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_ */
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
/**
|
||||
* @file MiniCooperR50.cpp
|
||||
*
|
||||
* MINI_COOPER_R50 = 13
|
||||
*
|
||||
* @date Apr 9, 2014
|
||||
* @author Andrey Belomutskiy, (c) 2012-2014
|
||||
*/
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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_
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
||||
/**
|
||||
|
|
|
@ -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
|
||||
|
||||
/**
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
|
||||
|
|
|
@ -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');
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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_
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
||||
|
|
|
@ -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]);
|
||||
|
||||
}
|
||||
|
|
|
@ -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" {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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_ */
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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_ */
|
|
@ -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];
|
||||
}
|
|
@ -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_ */
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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_ */
|
|
@ -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_ */
|
|
@ -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_ */
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -13,10 +13,8 @@ extern "C"
|
|||
{
|
||||
#endif /* __cplusplus */
|
||||
|
||||
|
||||
void mapAveragingCallback(adcsample_t newValue);
|
||||
void initMapAveraging(void);
|
||||
float getAtmosphericPressure(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -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 };
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
||||
/**
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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_ */
|
||||
|
|
|
@ -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 */
|
||||
|
|
@ -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_ */
|
|
@ -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;
|
||||
|
|
|
@ -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 {
|
||||
/**
|
||||
|
|
|
@ -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_ */
|
|
@ -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);
|
||||
//
|
||||
//}
|
||||
//
|
|
@ -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 */
|
|
@ -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_ */
|
|
@ -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) {
|
||||
|
||||
}
|
||||
|
|
|
@ -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_ */
|
||||
|
|
|
@ -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
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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_ */
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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_ */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
}
|
|
@ -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_ */
|
|
@ -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;
|
||||
|
|
|
@ -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_ */
|
||||
|
|
|
@ -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
Loading…
Reference in New Issue