From e39e0805511cea43d7f1eae1850ecb89a2507ffd Mon Sep 17 00:00:00 2001 From: rusefi Date: Mon, 19 May 2014 10:10:56 -0500 Subject: [PATCH] manual sync --- firmware/.cproject | 2 + firmware/Doxyfile | 3 +- firmware/Makefile | 5 + firmware/chibios/os/kernel/include/chdebug.h | 11 + .../os/ports/IAR/ARMCMx/chcoreasm_v7m.s | 2 +- firmware/compile.bat | 18 +- firmware/config/boards/arro_board.h | 46 - firmware/config/efifeatures.h | 19 + firmware/config/engines/MiniCooperR50.cpp | 2 + .../config/engines/citroenBerlingoTU3JP.cpp | 2 +- .../config/engines/citroenBerlingoTU3JP.h | 2 +- .../config/engines/ford_1995_inline_6.cpp | 25 +- firmware/config/engines/ford_aspire.cpp | 12 +- firmware/config/engines/ford_escort_gt.cpp | 2 +- firmware/config/engines/mazda_323.cpp | 2 +- firmware/config/system/chconf.h | 11 +- firmware/config/system/halconf.h | 2 +- firmware/config/system/mcuconf.h | 4 +- firmware/console/console_io.c | 27 +- firmware/console/console_io.h | 4 +- firmware/console/eficonsole.c | 8 +- firmware/console/status_loop.cpp | 36 +- firmware/console/status_loop.h | 2 - firmware/console/tunerstudio/tunerstudio.c | 10 +- firmware/console_util/datalogging.c | 66 +- firmware/console_util/datalogging.h | 9 +- firmware/console_util/rfiutil.c | 2 + firmware/controllers/PwmTester.cpp | 30 +- firmware/controllers/PwmTester.h | 2 +- .../controllers/algo/accel_enrichment.cpp | 8 +- firmware/controllers/algo/advance_map.c | 2 + firmware/controllers/algo/algo.mk | 4 +- firmware/controllers/algo/ec2.h | 15 +- .../controllers/algo/engine_configuration.cpp | 80 +- .../controllers/algo/engine_configuration.h | 21 +- firmware/controllers/algo/error_handling.h | 8 +- firmware/controllers/algo/event_queue.cpp | 89 -- firmware/controllers/algo/fuel_math.cpp | 6 + firmware/controllers/algo/idle_controller.c | 18 +- firmware/controllers/algo/idle_controller.h | 4 - .../controllers/algo/malfunction_central.c | 2 +- firmware/controllers/algo/obd_error_codes.h | 2 +- firmware/controllers/algo/rusefi_enums.h | 10 +- firmware/controllers/algo/signal_executor.c | 26 +- firmware/controllers/algo/signal_executor.h | 32 +- firmware/controllers/algo/wave_chart.c | 10 +- firmware/controllers/core/EfiWave.cpp | 43 + firmware/controllers/core/EfiWave.h | 51 + .../controllers/{math => core}/avg_values.c | 124 +-- .../controllers/{math => core}/avg_values.h | 60 +- firmware/controllers/core/core.mk | 6 + .../{algo => core}/interpolation.c | 440 ++++----- .../{algo => core}/interpolation.h | 52 +- .../{math => core}/signal_filtering.c | 128 +-- .../{math => core}/signal_filtering.h | 50 +- firmware/controllers/engine_controller.cpp | 35 +- firmware/controllers/error_handling.c | 33 +- firmware/controllers/flash_main.cpp | 56 +- firmware/controllers/flash_main.h | 9 +- firmware/controllers/injector_central.cpp | 2 + firmware/controllers/malfunction_indicator.c | 4 + firmware/controllers/map_averaging.c | 63 +- firmware/controllers/map_averaging.h | 2 - firmware/controllers/math/engine_math.cpp | 45 +- firmware/controllers/math/math.mk | 2 +- firmware/controllers/sensors/map.c | 31 +- firmware/controllers/sensors/map.h | 2 + firmware/controllers/sensors/sensor_types.h | 17 +- firmware/controllers/sensors/thermistors.cpp | 11 +- firmware/controllers/settings.cpp | 60 +- firmware/controllers/settings.h | 1 + .../system/SingleTimerExecutor.cpp | 64 +- .../controllers/system/SingleTimerExecutor.h | 20 +- firmware/controllers/system/event_queue.cpp | 130 +++ .../{algo => system}/event_queue.h | 62 +- .../system/pwm_generator_logic.cpp | 28 +- .../controllers/system/pwm_generator_logic.h | 4 +- firmware/controllers/system/scheduler.h | 40 + .../controllers/system/signal_executor_gpt.c | 28 - .../system/signal_executor_hw_timer.c | 37 - .../system/signal_executor_hw_timer.h | 17 - .../system/signal_executor_sleep.c | 11 +- .../system/signal_executor_sleep.h | 3 - firmware/controllers/system/system.mk | 7 +- .../trigger/main_trigger_callback.cpp | 63 +- .../controllers/trigger/rpm_calculator.cpp | 72 +- firmware/controllers/trigger/rpm_calculator.h | 7 +- firmware/controllers/trigger/trigger.mk | 14 +- firmware/controllers/trigger/trigger_bmw.cpp | 41 + firmware/controllers/trigger/trigger_bmw.h | 16 + .../controllers/trigger/trigger_central.cpp | 4 + .../controllers/trigger/trigger_chrysler.cpp | 4 +- .../controllers/trigger/trigger_chrysler.h | 9 - .../controllers/trigger/trigger_decoder.cpp | 28 +- .../controllers/trigger/trigger_decoder.h | 4 +- .../trigger_emulator_algo.cpp | 142 +-- .../trigger_emulator_algo.h | 56 +- firmware/controllers/trigger/trigger_gm.cpp | 2 +- firmware/controllers/trigger/trigger_gm.h | 10 - .../controllers/trigger/trigger_mazda.cpp | 8 +- firmware/controllers/trigger/trigger_mazda.h | 10 - .../controllers/trigger/trigger_structure.cpp | 70 +- .../controllers/trigger/trigger_structure.h | 55 +- firmware/emulation/analog_chart.c | 7 +- firmware/emulation/engine_emulator.cpp | 2 + firmware/emulation/rfi_perftest.cpp | 9 +- firmware/emulation/wave_analyzer.c | 7 +- firmware/global.h | 3 + firmware/hw_layer/AdcConfiguration.h | 29 + .../hw_layer/{adc_inputs.c => adc_inputs.cpp} | 913 +++++++++--------- firmware/hw_layer/adc_inputs.h | 8 +- .../hw_layer/{board_test.c => board_test.cpp} | 298 +++--- firmware/hw_layer/flash.c | 6 + firmware/hw_layer/hardware.cpp | 41 +- firmware/hw_layer/hardware.h | 4 +- firmware/hw_layer/hw_layer.mk | 6 +- firmware/hw_layer/io_pins.c | 22 +- firmware/hw_layer/lcd/lcd_HD44780.c | 74 +- firmware/hw_layer/microsecond_timer.c | 105 +- firmware/hw_layer/microsecond_timer.h | 4 +- firmware/hw_layer/mmc_card.c | 6 +- firmware/hw_layer/mmc_card.h | 2 - firmware/hw_layer/neo6m.c | 5 +- firmware/hw_layer/pin_repository.c | 10 +- firmware/hw_layer/rtc_helper.c | 16 + .../hw_layer/serial_over_usb/usbconsole.c | 2 +- firmware/hw_layer/trigger_input.cpp | 57 +- firmware/hw_layer/wave_analyzer_hw.c | 47 +- firmware/hw_layer/wave_analyzer_hw.h | 1 + firmware/iar/ch.ewp | 747 ++++++++------ firmware/iar/ch.eww | 5 - firmware/main.h | 4 +- firmware/rusefi.cpp | 59 +- firmware/svnversion.h | 2 +- firmware/tunerstudio/rusefi.ini | 79 +- firmware/util/LocalVersionHolder.cpp | 2 +- .../{eficonsole_logic.c => cli_registry.c} | 575 ++++++----- .../{eficonsole_logic.h => cli_registry.h} | 134 ++- firmware/util/crc.c | 4 +- firmware/util/crc.h | 4 +- firmware/util/efilib.cpp | 25 +- firmware/util/efilib.h | 17 +- firmware/util/efilib2.cpp | 2 +- firmware/util/efilib2.h | 2 +- firmware/util/histogram.c | 4 + firmware/util/readme.txt | 3 + firmware/util/util.mk | 2 +- firmware/util/wave_math.c | 40 +- firmware/util/wave_math.h | 9 +- 149 files changed, 3672 insertions(+), 2827 deletions(-) delete mode 100644 firmware/controllers/algo/event_queue.cpp create mode 100644 firmware/controllers/core/EfiWave.cpp create mode 100644 firmware/controllers/core/EfiWave.h rename firmware/controllers/{math => core}/avg_values.c (95%) rename firmware/controllers/{math => core}/avg_values.h (95%) create mode 100644 firmware/controllers/core/core.mk rename firmware/controllers/{algo => core}/interpolation.c (96%) rename firmware/controllers/{algo => core}/interpolation.h (96%) rename firmware/controllers/{math => core}/signal_filtering.c (95%) rename firmware/controllers/{math => core}/signal_filtering.h (95%) create mode 100644 firmware/controllers/system/event_queue.cpp rename firmware/controllers/{algo => system}/event_queue.h (73%) create mode 100644 firmware/controllers/system/scheduler.h delete mode 100644 firmware/controllers/system/signal_executor_gpt.c delete mode 100644 firmware/controllers/system/signal_executor_hw_timer.c delete mode 100644 firmware/controllers/system/signal_executor_hw_timer.h create mode 100644 firmware/controllers/trigger/trigger_bmw.cpp create mode 100644 firmware/controllers/trigger/trigger_bmw.h rename firmware/controllers/{system => trigger}/trigger_emulator_algo.cpp (90%) rename firmware/controllers/{system => trigger}/trigger_emulator_algo.h (94%) create mode 100644 firmware/hw_layer/AdcConfiguration.h rename firmware/hw_layer/{adc_inputs.c => adc_inputs.cpp} (68%) rename firmware/hw_layer/{board_test.c => board_test.cpp} (94%) rename firmware/util/{eficonsole_logic.c => cli_registry.c} (94%) rename firmware/util/{eficonsole_logic.h => cli_registry.h} (85%) create mode 100644 firmware/util/readme.txt diff --git a/firmware/.cproject b/firmware/.cproject index b36275c517..dce069900e 100644 --- a/firmware/.cproject +++ b/firmware/.cproject @@ -43,6 +43,7 @@ + @@ -102,6 +103,7 @@ + diff --git a/firmware/Doxyfile b/firmware/Doxyfile index 97bcc6f8cd..17a7226eb9 100644 --- a/firmware/Doxyfile +++ b/firmware/Doxyfile @@ -743,8 +743,9 @@ INPUT = . \ util \ console \ controllers \ - controllers/math \ controllers/algo \ + controllers/core \ + controllers/math \ controllers/sensors \ controllers/system \ controllers/trigger \ diff --git a/firmware/Makefile b/firmware/Makefile index b6e9b09aad..3361d87d85 100644 --- a/firmware/Makefile +++ b/firmware/Makefile @@ -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 diff --git a/firmware/chibios/os/kernel/include/chdebug.h b/firmware/chibios/os/kernel/include/chdebug.h index ef929e66d4..0ee1adc483 100644 --- a/firmware/chibios/os/kernel/include/chdebug.h +++ b/firmware/chibios/os/kernel/include/chdebug.h @@ -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. */ diff --git a/firmware/chibios/os/ports/IAR/ARMCMx/chcoreasm_v7m.s b/firmware/chibios/os/ports/IAR/ARMCMx/chcoreasm_v7m.s index 634f75d78f..e1cc5ff92b 100644 --- a/firmware/chibios/os/ports/IAR/ARMCMx/chcoreasm_v7m.s +++ b/firmware/chibios/os/ports/IAR/ARMCMx/chcoreasm_v7m.s @@ -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 diff --git a/firmware/compile.bat b/firmware/compile.bat index 707ae30bcb..cb574eb87c 100644 --- a/firmware/compile.bat +++ b/firmware/compile.bat @@ -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 diff --git a/firmware/config/boards/arro_board.h b/firmware/config/boards/arro_board.h index 2656e1e6df..bfc7eb63eb 100644 --- a/firmware/config/boards/arro_board.h +++ b/firmware/config/boards/arro_board.h @@ -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 // diff --git a/firmware/config/efifeatures.h b/firmware/config/efifeatures.h index 264b798940..a6a59bcad0 100644 --- a/firmware/config/efifeatures.h +++ b/firmware/config/efifeatures.h @@ -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_ */ diff --git a/firmware/config/engines/MiniCooperR50.cpp b/firmware/config/engines/MiniCooperR50.cpp index 5ed6a79c48..b11026056f 100644 --- a/firmware/config/engines/MiniCooperR50.cpp +++ b/firmware/config/engines/MiniCooperR50.cpp @@ -1,6 +1,8 @@ /** * @file MiniCooperR50.cpp * + * MINI_COOPER_R50 = 13 + * * @date Apr 9, 2014 * @author Andrey Belomutskiy, (c) 2012-2014 */ diff --git a/firmware/config/engines/citroenBerlingoTU3JP.cpp b/firmware/config/engines/citroenBerlingoTU3JP.cpp index 116d157de8..cb94335732 100644 --- a/firmware/config/engines/citroenBerlingoTU3JP.cpp +++ b/firmware/config/engines/citroenBerlingoTU3JP.cpp @@ -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" diff --git a/firmware/config/engines/citroenBerlingoTU3JP.h b/firmware/config/engines/citroenBerlingoTU3JP.h index a05b8c5ad4..09f2d42736 100644 --- a/firmware/config/engines/citroenBerlingoTU3JP.h +++ b/firmware/config/engines/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_ diff --git a/firmware/config/engines/ford_1995_inline_6.cpp b/firmware/config/engines/ford_1995_inline_6.cpp index b3e74c29a4..5d85eb9a0f 100644 --- a/firmware/config/engines/ford_1995_inline_6.cpp +++ b/firmware/config/engines/ford_1995_inline_6.cpp @@ -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 */ diff --git a/firmware/config/engines/ford_aspire.cpp b/firmware/config/engines/ford_aspire.cpp index 7902d6be70..e92079c238 100644 --- a/firmware/config/engines/ford_aspire.cpp +++ b/firmware/config/engines/ford_aspire.cpp @@ -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 */ diff --git a/firmware/config/engines/ford_escort_gt.cpp b/firmware/config/engines/ford_escort_gt.cpp index 85268ba9a9..3eb4a1ebcf 100644 --- a/firmware/config/engines/ford_escort_gt.cpp +++ b/firmware/config/engines/ford_escort_gt.cpp @@ -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" diff --git a/firmware/config/engines/mazda_323.cpp b/firmware/config/engines/mazda_323.cpp index 075d44a09a..568a167f1b 100644 --- a/firmware/config/engines/mazda_323.cpp +++ b/firmware/config/engines/mazda_323.cpp @@ -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" diff --git a/firmware/config/system/chconf.h b/firmware/config/system/chconf.h index 89ccd78a98..f649138817 100644 --- a/firmware/config/system/chconf.h +++ b/firmware/config/system/chconf.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 /** diff --git a/firmware/config/system/halconf.h b/firmware/config/system/halconf.h index 7cf85cefac..f51a2ed6df 100644 --- a/firmware/config/system/halconf.h +++ b/firmware/config/system/halconf.h @@ -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 /** diff --git a/firmware/config/system/mcuconf.h b/firmware/config/system/mcuconf.h index 20f8d2409c..e7387825f4 100644 --- a/firmware/config/system/mcuconf.h +++ b/firmware/config/system/mcuconf.h @@ -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 diff --git a/firmware/console/console_io.c b/firmware/console/console_io.c index 14f906a9da..b02900e81a 100644 --- a/firmware/console/console_io.c +++ b/firmware/console/console_io.c @@ -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) { diff --git a/firmware/console/console_io.h b/firmware/console/console_io.h index 67df8aae7b..d7dd52355a 100644 --- a/firmware/console/console_io.h +++ b/firmware/console/console_io.h @@ -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 } diff --git a/firmware/console/eficonsole.c b/firmware/console/eficonsole.c index c2dba98ed4..627e2d0d69 100644 --- a/firmware/console/eficonsole.c +++ b/firmware/console/eficonsole.c @@ -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"); diff --git a/firmware/console/status_loop.cpp b/firmware/console/status_loop.cpp index a8b7b9a279..2cb0cd184b 100644 --- a/firmware/console/status_loop.cpp +++ b/firmware/console/status_loop.cpp @@ -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'); diff --git a/firmware/console/status_loop.h b/firmware/console/status_loop.h index 18a378fa1e..5fecb76093 100644 --- a/firmware/console/status_loop.h +++ b/firmware/console/status_loop.h @@ -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 } diff --git a/firmware/console/tunerstudio/tunerstudio.c b/firmware/console/tunerstudio/tunerstudio.c index 23ad3852f0..46c046d28a 100644 --- a/firmware/console/tunerstudio/tunerstudio.c +++ b/firmware/console/tunerstudio/tunerstudio.c @@ -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(); } diff --git a/firmware/console_util/datalogging.c b/firmware/console_util/datalogging.c index 27eff17222..bea72eb8b8 100644 --- a/firmware/console_util/datalogging.c +++ b/firmware/console_util/datalogging.c @@ -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; diff --git a/firmware/console_util/datalogging.h b/firmware/console_util/datalogging.h index 7eb7998af7..a960f2c2c2 100644 --- a/firmware/console_util/datalogging.h +++ b/firmware/console_util/datalogging.h @@ -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 diff --git a/firmware/console_util/rfiutil.c b/firmware/console_util/rfiutil.c index ea11b5a6d5..82874c8229 100644 --- a/firmware/console_util/rfiutil.c +++ b/firmware/console_util/rfiutil.c @@ -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 */ } diff --git a/firmware/controllers/PwmTester.cpp b/firmware/controllers/PwmTester.cpp index ccba4eb9e1..0945fa4b5d 100644 --- a/firmware/controllers/PwmTester.cpp +++ b/firmware/controllers/PwmTester.cpp @@ -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); } diff --git a/firmware/controllers/PwmTester.h b/firmware/controllers/PwmTester.h index a5d99a4f31..e376961b80 100644 --- a/firmware/controllers/PwmTester.h +++ b/firmware/controllers/PwmTester.h @@ -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_ diff --git a/firmware/controllers/algo/accel_enrichment.cpp b/firmware/controllers/algo/accel_enrichment.cpp index c7ebd74ba7..6cbe515041 100644 --- a/firmware/controllers/algo/accel_enrichment.cpp +++ b/firmware/controllers/algo/accel_enrichment.cpp @@ -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); } diff --git a/firmware/controllers/algo/advance_map.c b/firmware/controllers/algo/advance_map.c index 2419300b05..09c6e2fd01 100644 --- a/firmware/controllers/algo/advance_map.c +++ b/firmware/controllers/algo/advance_map.c @@ -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); diff --git a/firmware/controllers/algo/algo.mk b/firmware/controllers/algo/algo.mk index 6ad8a3594b..6871e4e553 100644 --- a/firmware/controllers/algo/algo.mk +++ b/firmware/controllers/algo/algo.mk @@ -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 diff --git a/firmware/controllers/algo/ec2.h b/firmware/controllers/algo/ec2.h index 966e015c43..f03910c61a 100644 --- a/firmware/controllers/algo/ec2.h +++ b/firmware/controllers/algo/ec2.h @@ -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); diff --git a/firmware/controllers/algo/engine_configuration.cpp b/firmware/controllers/algo/engine_configuration.cpp index 30ae07b945..0d8631ac59 100644 --- a/firmware/controllers/algo/engine_configuration.cpp +++ b/firmware/controllers/algo/engine_configuration.cpp @@ -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]); } diff --git a/firmware/controllers/algo/engine_configuration.h b/firmware/controllers/algo/engine_configuration.h index e850d48c49..f7ca04c757 100644 --- a/firmware/controllers/algo/engine_configuration.h +++ b/firmware/controllers/algo/engine_configuration.h @@ -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" { diff --git a/firmware/controllers/algo/error_handling.h b/firmware/controllers/algo/error_handling.h index 9b6976ba81..a090d25534 100644 --- a/firmware/controllers/algo/error_handling.h +++ b/firmware/controllers/algo/error_handling.h @@ -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 diff --git a/firmware/controllers/algo/event_queue.cpp b/firmware/controllers/algo/event_queue.cpp deleted file mode 100644 index 9896fea3bf..0000000000 --- a/firmware/controllers/algo/event_queue.cpp +++ /dev/null @@ -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; -} diff --git a/firmware/controllers/algo/fuel_math.cpp b/firmware/controllers/algo/fuel_math.cpp index f357c96060..313212ad45 100644 --- a/firmware/controllers/algo/fuel_math.cpp +++ b/firmware/controllers/algo/fuel_math.cpp @@ -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; } diff --git a/firmware/controllers/algo/idle_controller.c b/firmware/controllers/algo/idle_controller.c index a86771a547..d172a00ef0 100644 --- a/firmware/controllers/algo/idle_controller.c +++ b/firmware/controllers/algo/idle_controller.c @@ -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); diff --git a/firmware/controllers/algo/idle_controller.h b/firmware/controllers/algo/idle_controller.h index 20c6d5d12a..29596654e6 100644 --- a/firmware/controllers/algo/idle_controller.h +++ b/firmware/controllers/algo/idle_controller.h @@ -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 diff --git a/firmware/controllers/algo/malfunction_central.c b/firmware/controllers/algo/malfunction_central.c index 7dcd58bbbf..7ea1dadc43 100644 --- a/firmware/controllers/algo/malfunction_central.c +++ b/firmware/controllers/algo/malfunction_central.c @@ -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 } } diff --git a/firmware/controllers/algo/obd_error_codes.h b/firmware/controllers/algo/obd_error_codes.h index 775d88d9cb..5c97d112dd 100644 --- a/firmware/controllers/algo/obd_error_codes.h +++ b/firmware/controllers/algo/obd_error_codes.h @@ -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 diff --git a/firmware/controllers/algo/rusefi_enums.h b/firmware/controllers/algo/rusefi_enums.h index c16f4343ab..5143e0ad91 100644 --- a/firmware/controllers/algo/rusefi_enums.h +++ b/firmware/controllers/algo/rusefi_enums.h @@ -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_ */ diff --git a/firmware/controllers/algo/signal_executor.c b/firmware/controllers/algo/signal_executor.c index 8c915bbf48..05edc17060 100644 --- a/firmware/controllers/algo/signal_executor.c +++ b/firmware/controllers/algo/signal_executor.c @@ -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: diff --git a/firmware/controllers/algo/signal_executor.h b/firmware/controllers/algo/signal_executor.h index 33c51f9b60..adfb53ee0b 100644 --- a/firmware/controllers/algo/signal_executor.h +++ b/firmware/controllers/algo/signal_executor.h @@ -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 diff --git a/firmware/controllers/algo/wave_chart.c b/firmware/controllers/algo/wave_chart.c index 3d0e413890..b5478d0ea0 100644 --- a/firmware/controllers/algo/wave_chart.c +++ b/firmware/controllers/algo/wave_chart.c @@ -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) { diff --git a/firmware/controllers/core/EfiWave.cpp b/firmware/controllers/core/EfiWave.cpp new file mode 100644 index 0000000000..a2c6b783f9 --- /dev/null +++ b/firmware/controllers/core/EfiWave.cpp @@ -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"); + } + } +} diff --git a/firmware/controllers/core/EfiWave.h b/firmware/controllers/core/EfiWave.h new file mode 100644 index 0000000000..3f86ee4df9 --- /dev/null +++ b/firmware/controllers/core/EfiWave.h @@ -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_ */ diff --git a/firmware/controllers/math/avg_values.c b/firmware/controllers/core/avg_values.c similarity index 95% rename from firmware/controllers/math/avg_values.c rename to firmware/controllers/core/avg_values.c index 920dbd4c17..65bd1b1c9e 100644 --- a/firmware/controllers/math/avg_values.c +++ b/firmware/controllers/core/avg_values.c @@ -1,62 +1,62 @@ -/* - * avg_values.c - * - * @date Jul 23, 2013 - * @author Andrey Belomutskiy, (c) 2012-2014 - */ - -#include "avg_values.h" -#include - -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 + +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]; +} diff --git a/firmware/controllers/math/avg_values.h b/firmware/controllers/core/avg_values.h similarity index 95% rename from firmware/controllers/math/avg_values.h rename to firmware/controllers/core/avg_values.h index 935b581e96..8c80237284 100644 --- a/firmware/controllers/math/avg_values.h +++ b/firmware/controllers/core/avg_values.h @@ -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_ */ diff --git a/firmware/controllers/core/core.mk b/firmware/controllers/core/core.mk new file mode 100644 index 0000000000..a4f3a689bf --- /dev/null +++ b/firmware/controllers/core/core.mk @@ -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 + diff --git a/firmware/controllers/algo/interpolation.c b/firmware/controllers/core/interpolation.c similarity index 96% rename from firmware/controllers/algo/interpolation.c rename to firmware/controllers/core/interpolation.c index f13767d854..2d1a1f80d7 100644 --- a/firmware/controllers/algo/interpolation.c +++ b/firmware/controllers/core/interpolation.c @@ -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 -#endif - -#include - -#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 +#endif + +#include + +#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; +} + diff --git a/firmware/controllers/algo/interpolation.h b/firmware/controllers/core/interpolation.h similarity index 96% rename from firmware/controllers/algo/interpolation.h rename to firmware/controllers/core/interpolation.h index dfb330d9be..5f61f23b76 100644 --- a/firmware/controllers/algo/interpolation.h +++ b/firmware/controllers/core/interpolation.h @@ -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_ */ diff --git a/firmware/controllers/math/signal_filtering.c b/firmware/controllers/core/signal_filtering.c similarity index 95% rename from firmware/controllers/math/signal_filtering.c rename to firmware/controllers/core/signal_filtering.c index 5bd84c043b..2daf480c17 100644 --- a/firmware/controllers/math/signal_filtering.c +++ b/firmware/controllers/core/signal_filtering.c @@ -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_ */ diff --git a/firmware/controllers/math/signal_filtering.h b/firmware/controllers/core/signal_filtering.h similarity index 95% rename from firmware/controllers/math/signal_filtering.h rename to firmware/controllers/core/signal_filtering.h index 650b907f9f..63ea15592f 100644 --- a/firmware/controllers/math/signal_filtering.h +++ b/firmware/controllers/core/signal_filtering.h @@ -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_ */ diff --git a/firmware/controllers/engine_controller.cpp b/firmware/controllers/engine_controller.cpp index 1181f2446d..4c3d36fe83 100644 --- a/firmware/controllers/engine_controller.cpp +++ b/firmware/controllers/engine_controller.cpp @@ -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); } diff --git a/firmware/controllers/error_handling.c b/firmware/controllers/error_handling.c index adf987f42e..5a137a7871 100644 --- a/firmware/controllers/error_handling.c +++ b/firmware/controllers/error_handling.c @@ -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"); - } diff --git a/firmware/controllers/flash_main.cpp b/firmware/controllers/flash_main.cpp index f5af055062..318ed47bc6 100644 --- a/firmware/controllers/flash_main.cpp +++ b/firmware/controllers/flash_main.cpp @@ -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); diff --git a/firmware/controllers/flash_main.h b/firmware/controllers/flash_main.h index fab13fce87..43864ce013 100644 --- a/firmware/controllers/flash_main.h +++ b/firmware/controllers/flash_main.h @@ -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" diff --git a/firmware/controllers/injector_central.cpp b/firmware/controllers/injector_central.cpp index 2e763012fb..d6017b99c8 100644 --- a/firmware/controllers/injector_central.cpp +++ b/firmware/controllers/injector_central.cpp @@ -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) { diff --git a/firmware/controllers/malfunction_indicator.c b/firmware/controllers/malfunction_indicator.c index 101e95eb88..3b66480900 100644 --- a/firmware/controllers/malfunction_indicator.c +++ b/firmware/controllers/malfunction_indicator.c @@ -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 */ diff --git a/firmware/controllers/map_averaging.c b/firmware/controllers/map_averaging.c index fc378b4ae2..0f30f3bade 100644 --- a/firmware/controllers/map_averaging.c +++ b/firmware/controllers/map_averaging.c @@ -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 */ diff --git a/firmware/controllers/map_averaging.h b/firmware/controllers/map_averaging.h index 2ffd939b98..f5d556e3c3 100644 --- a/firmware/controllers/map_averaging.h +++ b/firmware/controllers/map_averaging.h @@ -13,10 +13,8 @@ extern "C" { #endif /* __cplusplus */ - void mapAveragingCallback(adcsample_t newValue); void initMapAveraging(void); -float getAtmosphericPressure(void); #ifdef __cplusplus } diff --git a/firmware/controllers/math/engine_math.cpp b/firmware/controllers/math/engine_math.cpp index 5f50ad6f26..e054aa7c78 100644 --- a/firmware/controllers/math/engine_math.cpp +++ b/firmware/controllers/math/engine_math.cpp @@ -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 }; diff --git a/firmware/controllers/math/math.mk b/firmware/controllers/math/math.mk index 885c99b201..66e9d2a71f 100644 --- a/firmware/controllers/math/math.mk +++ b/firmware/controllers/math/math.mk @@ -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 diff --git a/firmware/controllers/sensors/map.c b/firmware/controllers/sensors/map.c index 6e227d3019..cb0b52bc21 100644 --- a/firmware/controllers/sensors/map.c +++ b/firmware/controllers/sensors/map.c @@ -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); +} diff --git a/firmware/controllers/sensors/map.h b/firmware/controllers/sensors/map.h index 03e23eaac3..ed6a3cfd63 100644 --- a/firmware/controllers/sensors/map.h +++ b/firmware/controllers/sensors/map.h @@ -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); diff --git a/firmware/controllers/sensors/sensor_types.h b/firmware/controllers/sensors/sensor_types.h index 7319a2e47f..998d7874be 100644 --- a/firmware/controllers/sensors/sensor_types.h +++ b/firmware/controllers/sensors/sensor_types.h @@ -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; /** diff --git a/firmware/controllers/sensors/thermistors.cpp b/firmware/controllers/sensors/thermistors.cpp index 3f65262b73..de3bf2bddf 100644 --- a/firmware/controllers/sensors/thermistors.cpp +++ b/firmware/controllers/sensors/thermistors.cpp @@ -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); diff --git a/firmware/controllers/settings.cpp b/firmware/controllers/settings.cpp index e8a3948c30..9159472f8b 100644 --- a/firmware/controllers/settings.cpp +++ b/firmware/controllers/settings.cpp @@ -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); diff --git a/firmware/controllers/settings.h b/firmware/controllers/settings.h index b3b1eb274d..9454133ae1 100644 --- a/firmware/controllers/settings.h +++ b/firmware/controllers/settings.h @@ -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); diff --git a/firmware/controllers/system/SingleTimerExecutor.cpp b/firmware/controllers/system/SingleTimerExecutor.cpp index adc54d0bfd..2022a14ad9 100644 --- a/firmware/controllers/system/SingleTimerExecutor.cpp +++ b/firmware/controllers/system/SingleTimerExecutor.cpp @@ -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 diff --git a/firmware/controllers/system/SingleTimerExecutor.h b/firmware/controllers/system/SingleTimerExecutor.h index b3438640e3..44744108a6 100644 --- a/firmware/controllers/system/SingleTimerExecutor.h +++ b/firmware/controllers/system/SingleTimerExecutor.h @@ -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_ */ diff --git a/firmware/controllers/system/event_queue.cpp b/firmware/controllers/system/event_queue.cpp new file mode 100644 index 0000000000..47b333bf18 --- /dev/null +++ b/firmware/controllers/system/event_queue.cpp @@ -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 */ + diff --git a/firmware/controllers/algo/event_queue.h b/firmware/controllers/system/event_queue.h similarity index 73% rename from firmware/controllers/algo/event_queue.h rename to firmware/controllers/system/event_queue.h index bfa68228be..652955e19d 100644 --- a/firmware/controllers/algo/event_queue.h +++ b/firmware/controllers/system/event_queue.h @@ -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_ */ diff --git a/firmware/controllers/system/pwm_generator_logic.cpp b/firmware/controllers/system/pwm_generator_logic.cpp index cd56aab32a..bc43619a6e 100644 --- a/firmware/controllers/system/pwm_generator_logic.cpp +++ b/firmware/controllers/system/pwm_generator_logic.cpp @@ -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; diff --git a/firmware/controllers/system/pwm_generator_logic.h b/firmware/controllers/system/pwm_generator_logic.h index a4d427291e..f7efaea2cb 100644 --- a/firmware/controllers/system/pwm_generator_logic.h +++ b/firmware/controllers/system/pwm_generator_logic.h @@ -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 { /** diff --git a/firmware/controllers/system/scheduler.h b/firmware/controllers/system/scheduler.h new file mode 100644 index 0000000000..a1cd0303cb --- /dev/null +++ b/firmware/controllers/system/scheduler.h @@ -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_ */ diff --git a/firmware/controllers/system/signal_executor_gpt.c b/firmware/controllers/system/signal_executor_gpt.c deleted file mode 100644 index f98ce1ca67..0000000000 --- a/firmware/controllers/system/signal_executor_gpt.c +++ /dev/null @@ -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); -// -//} -// diff --git a/firmware/controllers/system/signal_executor_hw_timer.c b/firmware/controllers/system/signal_executor_hw_timer.c deleted file mode 100644 index 48ff8149e5..0000000000 --- a/firmware/controllers/system/signal_executor_hw_timer.c +++ /dev/null @@ -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 . - */ - -#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 */ diff --git a/firmware/controllers/system/signal_executor_hw_timer.h b/firmware/controllers/system/signal_executor_hw_timer.h deleted file mode 100644 index 80d48adb44..0000000000 --- a/firmware/controllers/system/signal_executor_hw_timer.h +++ /dev/null @@ -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_ */ diff --git a/firmware/controllers/system/signal_executor_sleep.c b/firmware/controllers/system/signal_executor_sleep.c index 89f1efc002..51af8eef87 100644 --- a/firmware/controllers/system/signal_executor_sleep.c +++ b/firmware/controllers/system/signal_executor_sleep.c @@ -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) { } diff --git a/firmware/controllers/system/signal_executor_sleep.h b/firmware/controllers/system/signal_executor_sleep.h index a579a20368..d7a7292520 100644 --- a/firmware/controllers/system/signal_executor_sleep.h +++ b/firmware/controllers/system/signal_executor_sleep.h @@ -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_ */ diff --git a/firmware/controllers/system/system.mk b/firmware/controllers/system/system.mk index 6af78d6682..35ea5933bb 100644 --- a/firmware/controllers/system/system.mk +++ b/firmware/controllers/system/system.mk @@ -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 \ No newline at end of file diff --git a/firmware/controllers/trigger/main_trigger_callback.cpp b/firmware/controllers/trigger/main_trigger_callback.cpp index adf395213a..a295d7a78b 100644 --- a/firmware/controllers/trigger/main_trigger_callback.cpp +++ b/firmware/controllers/trigger/main_trigger_callback.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 */ diff --git a/firmware/controllers/trigger/rpm_calculator.cpp b/firmware/controllers/trigger/rpm_calculator.cpp index 947cd560aa..62ae09c22f 100644 --- a/firmware/controllers/trigger/rpm_calculator.cpp +++ b/firmware/controllers/trigger/rpm_calculator.cpp @@ -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 */ diff --git a/firmware/controllers/trigger/rpm_calculator.h b/firmware/controllers/trigger/rpm_calculator.h index 073eed95ae..89f323ae4a 100644 --- a/firmware/controllers/trigger/rpm_calculator.h +++ b/firmware/controllers/trigger/rpm_calculator.h @@ -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 } diff --git a/firmware/controllers/trigger/trigger.mk b/firmware/controllers/trigger/trigger.mk index fc364ae6a0..91560eb8f1 100644 --- a/firmware/controllers/trigger/trigger.mk +++ b/firmware/controllers/trigger/trigger.mk @@ -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 diff --git a/firmware/controllers/trigger/trigger_bmw.cpp b/firmware/controllers/trigger/trigger_bmw.cpp new file mode 100644 index 0000000000..73d5d46999 --- /dev/null +++ b/firmware/controllers/trigger/trigger_bmw.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; +} diff --git a/firmware/controllers/trigger/trigger_bmw.h b/firmware/controllers/trigger/trigger_bmw.h new file mode 100644 index 0000000000..91b4de6cd3 --- /dev/null +++ b/firmware/controllers/trigger/trigger_bmw.h @@ -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_ */ diff --git a/firmware/controllers/trigger/trigger_central.cpp b/firmware/controllers/trigger/trigger_central.cpp index f9093e2782..dfe3f39183 100644 --- a/firmware/controllers/trigger/trigger_central.cpp +++ b/firmware/controllers/trigger/trigger_central.cpp @@ -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); } diff --git a/firmware/controllers/trigger/trigger_chrysler.cpp b/firmware/controllers/trigger/trigger_chrysler.cpp index eaf4c57036..ccc01ff288 100644 --- a/firmware/controllers/trigger/trigger_chrysler.cpp +++ b/firmware/controllers/trigger/trigger_chrysler.cpp @@ -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; diff --git a/firmware/controllers/trigger/trigger_chrysler.h b/firmware/controllers/trigger/trigger_chrysler.h index 7bd26b09ad..4cea93ce97 100644 --- a/firmware/controllers/trigger/trigger_chrysler.h +++ b/firmware/controllers/trigger/trigger_chrysler.h @@ -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_ */ diff --git a/firmware/controllers/trigger/trigger_decoder.cpp b/firmware/controllers/trigger/trigger_decoder.cpp index dd31cbcca2..c9c07c2212 100644 --- a/firmware/controllers/trigger/trigger_decoder.cpp +++ b/firmware/controllers/trigger/trigger_decoder.cpp @@ -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); diff --git a/firmware/controllers/trigger/trigger_decoder.h b/firmware/controllers/trigger/trigger_decoder.h index eddafbd914..c46dab305e 100644 --- a/firmware/controllers/trigger/trigger_decoder.h +++ b/firmware/controllers/trigger/trigger_decoder.h @@ -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); diff --git a/firmware/controllers/system/trigger_emulator_algo.cpp b/firmware/controllers/trigger/trigger_emulator_algo.cpp similarity index 90% rename from firmware/controllers/system/trigger_emulator_algo.cpp rename to firmware/controllers/trigger/trigger_emulator_algo.cpp index d1bcb93484..0cc65a29be 100644 --- a/firmware/controllers/system/trigger_emulator_algo.cpp +++ b/firmware/controllers/trigger/trigger_emulator_algo.cpp @@ -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); + +} diff --git a/firmware/controllers/system/trigger_emulator_algo.h b/firmware/controllers/trigger/trigger_emulator_algo.h similarity index 94% rename from firmware/controllers/system/trigger_emulator_algo.h rename to firmware/controllers/trigger/trigger_emulator_algo.h index adcb25f23d..e5f884fbb3 100644 --- a/firmware/controllers/system/trigger_emulator_algo.h +++ b/firmware/controllers/trigger/trigger_emulator_algo.h @@ -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_ */ diff --git a/firmware/controllers/trigger/trigger_gm.cpp b/firmware/controllers/trigger/trigger_gm.cpp index 4570eb85ef..b234a5436f 100644 --- a/firmware/controllers/trigger/trigger_gm.cpp +++ b/firmware/controllers/trigger/trigger_gm.cpp @@ -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; diff --git a/firmware/controllers/trigger/trigger_gm.h b/firmware/controllers/trigger/trigger_gm.h index cbb2aae163..10aedf680d 100644 --- a/firmware/controllers/trigger/trigger_gm.h +++ b/firmware/controllers/trigger/trigger_gm.h @@ -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_ */ diff --git a/firmware/controllers/trigger/trigger_mazda.cpp b/firmware/controllers/trigger/trigger_mazda.cpp index 6b1e7ead3d..eef73f1f69 100644 --- a/firmware/controllers/trigger/trigger_mazda.cpp +++ b/firmware/controllers/trigger/trigger_mazda.cpp @@ -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; diff --git a/firmware/controllers/trigger/trigger_mazda.h b/firmware/controllers/trigger/trigger_mazda.h index ea6b9c89ae..0d53b6d255 100644 --- a/firmware/controllers/trigger/trigger_mazda.h +++ b/firmware/controllers/trigger/trigger_mazda.h @@ -8,22 +8,12 @@ #ifndef TRIGGER_MAZDA_H_ #define TRIGGER_MAZDA_H_ -#ifdef __cplusplus -extern "C" -{ -#endif /* __cplusplus */ - #include "trigger_structure.h" #include "engine_configuration.h" #include "ec2.h" - void initializeMazdaMiataNbShape(trigger_shape_s *s); void configureMazdaProtegeLx(engine_configuration_s *engineConfiguration, engine_configuration2_s *engineConfiguration2); -#ifdef __cplusplus -} -#endif /* __cplusplus */ - #endif /* TRIGGER_MAZDA_H_ */ diff --git a/firmware/controllers/trigger/trigger_structure.cpp b/firmware/controllers/trigger/trigger_structure.cpp index a6c9adec4b..8354e659b2 100644 --- a/firmware/controllers/trigger/trigger_structure.cpp +++ b/firmware/controllers/trigger/trigger_structure.cpp @@ -21,27 +21,19 @@ #include "main.h" #include "trigger_structure.h" -single_wave_s::single_wave_s(int *ps) { - this->pinStates = ps; -} - -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]; +trigger_shape_helper::trigger_shape_helper() { + waves[0].init(pinStates0); + waves[1].init(pinStates1); } trigger_shape_s::trigger_shape_s() : - wave(switchTimes, h.waves) { + wave(switchTimes, NULL) { reset(); + wave.waves = h.waves; +} + +int trigger_shape_s::getSize() { + return size; } void trigger_shape_s::reset() { @@ -68,42 +60,42 @@ void clearTriggerState(trigger_state_s *state) { state->current_index = 0; } -void triggerShapeInit(trigger_shape_s *trigger) { - // todo: inline & remove method - trigger->reset(); -} - -void triggerAddEvent(trigger_shape_s *trigger, float angle, trigger_wheel_e waveIndex, trigger_value_e state) { +void trigger_shape_s::addEvent(float angle, trigger_wheel_e waveIndex, trigger_value_e state) { angle /= 720; - if (trigger->size == 0) { - trigger->size = 1; + if (size == 0) { + size = 1; for (int i = 0; i < PWM_PHASE_MAX_WAVE_PER_PWM; i++) { - single_wave_s *wave = &trigger->wave.waves[i]; + single_wave_s *wave = &this->wave.waves[i]; - efiAssert(wave!=NULL, "wave is NULL"); - efiAssert(wave->pinStates!=NULL, "wave pinStates is NULL"); - wave->pinStates[0] = trigger->initialState[i]; + if (wave == NULL) { + firmwareError("wave is NULL"); + return; + } + if (wave->pinStates == NULL) { + firmwareError("wave pinStates is NULL"); + return; + } + wave->pinStates[0] = initialState[i]; } - trigger->wave.setSwitchTime(0, angle); - trigger->wave.waves[waveIndex].pinStates[0] = state; + wave.setSwitchTime(0, angle); + wave.waves[waveIndex].pinStates[0] = state; return; } // if(angle!=trigger->wave.switchTimes[trigger->currentIndex]) - int index = trigger->size++; + int index = size++; for (int i = 0; i < PWM_PHASE_MAX_WAVE_PER_PWM; i++) - trigger->wave.waves[i].pinStates[index] = trigger->wave.getChannelState(i, index - 1); - trigger->wave.setSwitchTime(index, angle); - trigger->wave.waves[waveIndex].pinStates[index] = state; + wave.waves[i].pinStates[index] = wave.getChannelState(i, index - 1); + wave.setSwitchTime(index, angle); + wave.waves[waveIndex].pinStates[index] = state; } -void checkSwitchTimes2(int size, float *switchTimes) { - - for (int i = 0; i < size - 1; i++) - chDbgCheck(switchTimes[i] < switchTimes[i + 1], "invalid switchTimes"); +void triggerAddEvent(trigger_shape_s *trigger, float angle, trigger_wheel_e waveIndex, trigger_value_e state) { + // todo: inline this method + trigger->addEvent(angle, waveIndex, state); } void multi_wave_s::checkSwitchTimes(int size) { diff --git a/firmware/controllers/trigger/trigger_structure.h b/firmware/controllers/trigger/trigger_structure.h index 9d0df67d76..95a2db0960 100644 --- a/firmware/controllers/trigger/trigger_structure.h +++ b/firmware/controllers/trigger/trigger_structure.h @@ -8,11 +8,10 @@ #ifndef TRIGGER_STRUCTURE_H_ #define TRIGGER_STRUCTURE_H_ -#include "rusefi_enums.h" -#include "stdint.h" +#include -#define PWM_PHASE_MAX_COUNT 150 -#define PWM_PHASE_MAX_WAVE_PER_PWM 2 +#include "rusefi_enums.h" +#include "EfiWave.h" typedef struct { /** @@ -27,40 +26,6 @@ typedef struct { } trigger_state_s; -/** - * @brief PWM configuration for the specific output pin - */ -class single_wave_s { -public: - single_wave_s(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; -}; - typedef enum { TV_LOW = 0, TV_HIGH = 1 @@ -72,20 +37,24 @@ typedef enum { } trigger_wheel_e; class trigger_shape_helper { + int pinStates0[PWM_PHASE_MAX_COUNT]; int pinStates1[PWM_PHASE_MAX_COUNT]; - int pinStates2[PWM_PHASE_MAX_COUNT]; public: - single_wave_s waves[2] = {single_wave_s(pinStates1), single_wave_s(pinStates2)}; + trigger_shape_helper(); + + single_wave_s waves[2]; }; class trigger_shape_s { private: trigger_shape_helper h; + int size; public: trigger_shape_s(); + void addEvent(float angle, trigger_wheel_e waveIndex, trigger_value_e state); void reset(); + int getSize(); multi_wave_s wave; - int size; /** * Total count of shaft events per CAM or CRANK shaft revolution. @@ -103,16 +72,12 @@ private: float switchTimes[PWM_PHASE_MAX_COUNT]; }; - -void checkSwitchTimes2(int size, float *switchTimes); - #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ void clearTriggerState(trigger_state_s *state); -void triggerShapeInit(trigger_shape_s *trigger); void triggerAddEvent(trigger_shape_s *trigger, float angle, trigger_wheel_e waveIndex, trigger_value_e state); #ifdef __cplusplus diff --git a/firmware/emulation/analog_chart.c b/firmware/emulation/analog_chart.c index 34766766cb..03d3bf80a9 100644 --- a/firmware/emulation/analog_chart.c +++ b/firmware/emulation/analog_chart.c @@ -11,6 +11,8 @@ #include "status_loop.h" #include "engine_configuration.h" +#if EFI_ANALOG_CHART + static char LOGGING_BUFFER[5000]; static Logging logging; @@ -43,8 +45,7 @@ void acAddData(float angle, float value) { pendingData = TRUE; resetLogging(&logging); // message header - appendPrintf(&logging, "msg%s", DELIMETER); - appendPrintf(&logging, "analog_chart|"); + appendPrintf(&logging, "analog_chart%s", DELIMETER); } if (loggingSize(&logging) < sizeof(LOGGING_BUFFER) - 100) @@ -55,3 +56,5 @@ void initAnalogChart(void) { initLoggingExt(&logging, "analog chart", LOGGING_BUFFER, sizeof(LOGGING_BUFFER)); initialized = TRUE; } + +#endif /* EFI_ANALOG_CHART */ diff --git a/firmware/emulation/engine_emulator.cpp b/firmware/emulation/engine_emulator.cpp index b3434309cd..2f4e32a673 100644 --- a/firmware/emulation/engine_emulator.cpp +++ b/firmware/emulation/engine_emulator.cpp @@ -94,6 +94,8 @@ static void initECUstimulator(void) { } void initEngineEmulator(void) { + if (hasFirmwareError()) + return; #if EFI_PERF_METRICS initTimePerfActions(); #endif diff --git a/firmware/emulation/rfi_perftest.cpp b/firmware/emulation/rfi_perftest.cpp index cc67f88001..d286469677 100644 --- a/firmware/emulation/rfi_perftest.cpp +++ b/firmware/emulation/rfi_perftest.cpp @@ -193,7 +193,9 @@ static void runTests(const int count) { extern Overflow64Counter halTime; -int rtcStartTime; +#if EFI_RTC +static int rtcStartTime; +#endif #include "chrtclib.h" @@ -201,13 +203,16 @@ static void timeInfo(void) { scheduleMsg(&logger, "chTimeNow as seconds = %d", getTimeNowSeconds()); scheduleMsg(&logger, "hal seconds = %d", halTime.get() / 168000000LL); +#if EFI_RTC int unix = rtcGetTimeUnixSec(&RTCD1) - rtcStartTime; scheduleMsg(&logger, "unix seconds = %d", unix); - +#endif } void initTimePerfActions() { +#if EFI_RTC rtcStartTime = rtcGetTimeUnixSec(&RTCD1); +#endif initLogging(&logger, "perftest"); diff --git a/firmware/emulation/wave_analyzer.c b/firmware/emulation/wave_analyzer.c index 62e0f2a63d..fc31ec0fcf 100644 --- a/firmware/emulation/wave_analyzer.c +++ b/firmware/emulation/wave_analyzer.c @@ -21,8 +21,11 @@ #include "trigger_central.h" #include "rfiutil.h" + #define CHART_RESET_DELAY 1 +extern board_configuration_s *boardConfiguration; + extern engine_configuration_s *engineConfiguration; static volatile uint32_t ckpPeriodUs; // difference between current crank signal and previous crank signal @@ -237,8 +240,8 @@ void initWaveAnalyzer(void) { #ifdef EFI_WAVE_ANALYZER initLogging(&logger, "wave"); - initWave("input1 A8", 0, &LOGIC_ANALYZER_1_DRIVER, LOGIC_ANALYZER_1_PORT, LOGIC_ANALYZER_1_PIN, 1); - initWave("input2 E5", 1, &LOGIC_ANALYZER_2_DRIVER, LOGIC_ANALYZER_2_PORT, LOGIC_ANALYZER_2_PIN, 1); + initWave("input1 A8", 0, getInputCaptureDriver(boardConfiguration->primaryLogicAnalyzerPin), getHwPort(boardConfiguration->primaryLogicAnalyzerPin), getHwPin(boardConfiguration->primaryLogicAnalyzerPin), 1); + initWave("input2 E5", 1, getInputCaptureDriver(boardConfiguration->secondaryLogicAnalyzerPin), getHwPort(boardConfiguration->secondaryLogicAnalyzerPin), getHwPin(boardConfiguration->secondaryLogicAnalyzerPin), 1); // initWave("input0 C6", 2, &WAVE_TIMER, WAVE_INPUT_PORT, WAVE_INPUT_PIN, 0); addTriggerEventListener(&onWaveShaftSignal, "wave analyzer"); diff --git a/firmware/global.h b/firmware/global.h index c61bc0c4f3..d58450b3f7 100644 --- a/firmware/global.h +++ b/firmware/global.h @@ -23,6 +23,9 @@ #define VAR_NAME_VALUE(var) #var "=" VALUE(var) // project-wide default thread stack size +// todo: adjust +// #define PORT_INT_REQUIRED_STACK 128 +// todo: and decrease this size accordingly #define UTILITY_THREAD_STACK_SIZE 384 #endif /* GLOBAL_H_ */ diff --git a/firmware/hw_layer/AdcConfiguration.h b/firmware/hw_layer/AdcConfiguration.h new file mode 100644 index 0000000000..84248d18cc --- /dev/null +++ b/firmware/hw_layer/AdcConfiguration.h @@ -0,0 +1,29 @@ +/** + * @file AdcConfiguration.h + * + * @date May 3, 2014 + * @author Andrey Belomutskiy, (c) 2012-2014 + */ +#ifndef ADCCONFIGURATION_H_ +#define ADCCONFIGURATION_H_ + +class AdcConfiguration { +public: + AdcConfiguration(ADCConversionGroup* hwConfig); + void addChannel(int hwChannelIndex); + int getAdcHardwareIndexByInternalIndex(int index); + int internalAdcIndexByHardwareIndex[20]; + int size(); + void init(void); +private: + ADCConversionGroup* hwConfig; + /** + * Number of ADC channels in use + */ + int channelCount; + + int hardwareIndexByIndernalAdcIndex[20]; +}; + + +#endif /* ADCCONFIGURATION_H_ */ diff --git a/firmware/hw_layer/adc_inputs.c b/firmware/hw_layer/adc_inputs.cpp similarity index 68% rename from firmware/hw_layer/adc_inputs.c rename to firmware/hw_layer/adc_inputs.cpp index d512bffb84..f2aec15f83 100644 --- a/firmware/hw_layer/adc_inputs.c +++ b/firmware/hw_layer/adc_inputs.cpp @@ -1,442 +1,471 @@ -/** - * @file adc_inputs.c - * @brief Low level ADC code - * - * @date Jan 14, 2013 - * @author Andrey Belomutskiy, (c) 2012-2014 - */ - -#include "main.h" -#include "adc_inputs.h" - -#include "pin_repository.h" -#include "engine_math.h" -#include "map_averaging.h" -#include "engine_configuration.h" - - -#define ADC_GRP1_BUF_DEPTH_FAST 1 - -#define ADC_NUMBER_CHANNELS_FAST 1 - -#define PWM_FREQ_SLOW 5000 /* PWM clock frequency. I wonder what does this setting mean? */ -#define PWM_PERIOD_SLOW 500 /* PWM period (in PWM ticks). */ - -#define PWM_FREQ_FAST 1500000 /* PWM clock frequency. I wonder what does this setting mean? */ -#define PWM_PERIOD_FAST 50 /* PWM period (in PWM ticks). */ - -#define ADC_SLOW ADCD1 - -#define ADC_FAST ADCD2 - -#define ADC_DEBUG_KEY "adcDebug" - -static char LOGGING_BUFFER[500]; -static Logging logger; -static int adcCallbackCounter_slow = 0; - -static int adcDebugReporting = FALSE; - -static int internalAdcIndexByHardwareIndex[20]; -static int hardwareIndexByIndernalAdcIndex[20]; - -static int fastAdcValue; -extern engine_configuration_s *engineConfiguration; - -static adc_hw_helper_s slowAdcState; - -/* - * ADC samples buffer. - */ -static adcsample_t samples_fast[ADC_NUMBER_CHANNELS_FAST * ADC_GRP1_BUF_DEPTH_FAST]; - -static adcsample_t getAvgAdcValue(int index, adcsample_t *samples, int bufDepth, int numChannels) { - adcsample_t result = 0; - int i; - for (i = 0; i < bufDepth; i++) { - result += samples[index]; - index += numChannels; - } - return result / bufDepth; -} - -static adc_state newState; - -static void adc_callback_slow(ADCDriver *adcp, adcsample_t *buffer, size_t n) { - (void) buffer; - (void) n; - /* Note, only in the ADC_COMPLETE state because the ADC driver fires an - intermediate callback when the buffer is half full.*/ - if (adcp->state == ADC_COMPLETE) { - /* Calculates the average values from the ADC samples.*/ - - adcCallbackCounter_slow++; - -// newState.time = chimeNow(); - for (int i = 0; i < EFI_ADC_SLOW_CHANNELS_COUNT; i++) { - int value = getAvgAdcValue(i, slowAdcState.samples, ADC_GRP1_BUF_DEPTH_SLOW, EFI_ADC_SLOW_CHANNELS_COUNT); - newState.adc_data[i] = value; - } - } -} - -static void adc_callback_fast(ADCDriver *adcp, adcsample_t *buffer, size_t n) { - (void) buffer; - (void) n; -// /* Note, only in the ADC_COMPLETE state because the ADC driver fires an -// intermediate callback when the buffer is half full.*/ - if (adcp->state == ADC_COMPLETE) { - fastAdcValue = getAvgAdcValue(0, samples_fast, ADC_GRP1_BUF_DEPTH_FAST, ADC_NUMBER_CHANNELS_FAST); - mapAveragingCallback(fastAdcValue); - } -} - -#define MY_SAMPLING_SLOW ADC_SAMPLE_480 -#define MY_SAMPLING_FAST ADC_SAMPLE_28 - -/* - * ADC conversion group. - */ -static ADCConversionGroup adcgrpcfg_slow = { FALSE, EFI_ADC_SLOW_CHANNELS_COUNT, adc_callback_slow, NULL, -/* HW dependent part.*/ -ADC_TwoSamplingDelay_20Cycles, // cr1 - ADC_CR2_SWSTART, // cr2 - - ADC_SMPR1_SMP_AN10(MY_SAMPLING_SLOW) | - ADC_SMPR1_SMP_AN11(MY_SAMPLING_SLOW) | - ADC_SMPR1_SMP_AN12(MY_SAMPLING_SLOW) | - ADC_SMPR1_SMP_AN13(MY_SAMPLING_SLOW), // sample times for channels 10...18 - ADC_SMPR2_SMP_AN0(MY_SAMPLING_SLOW) | - ADC_SMPR2_SMP_AN1(MY_SAMPLING_SLOW) | - ADC_SMPR2_SMP_AN3(MY_SAMPLING_SLOW) | - ADC_SMPR2_SMP_AN4(MY_SAMPLING_SLOW) | - ADC_SMPR2_SMP_AN5(MY_SAMPLING_SLOW) | - ADC_SMPR2_SMP_AN6(MY_SAMPLING_SLOW) | - ADC_SMPR2_SMP_AN7(MY_SAMPLING_SLOW) | - ADC_SMPR2_SMP_AN8(MY_SAMPLING_SLOW) | - ADC_SMPR2_SMP_AN9(MY_SAMPLING_SLOW) - - , // In this field must be specified the sample times for channels 0...9 - - ADC_SQR1_NUM_CH(EFI_ADC_SLOW_CHANNELS_COUNT), // Conversion group sequence 13...16 + sequence length - - 0 -// | ADC_SQR2_SQ7_N(ADC_CHANNEL_IN12) /* PC2 - green */ -// | ADC_SQR2_SQ8_N(ADC_CHANNEL_IN13) /* PC3 - yellow maf? */ - - ,// Conversion group sequence 7...12 - 0 -// | ADC_SQR3_SQ1_N(ADC_CHANNEL_IN6) /* PA6 - white */ -// | ADC_SQR3_SQ2_N(ADC_CHANNEL_IN7) /* PA7 - blue */ -// | ADC_SQR3_SQ3_N(ADC_CHANNEL_IN14) /* PC4 - green */ -// | ADC_SQR3_SQ4_N(ADC_CHANNEL_IN15) /* PC5 - yellow */ -// | ADC_SQR3_SQ5_N(ADC_CHANNEL_IN8) /* PB0 - blue */ -// | ADC_SQR3_SQ6_N(ADC_CHANNEL_IN9) /* PB1 - white */ -// Conversion group sequence 1...6 - }; - -static const ADCConversionGroup adcgrpcfg_fast = { FALSE, ADC_NUMBER_CHANNELS_FAST, adc_callback_fast, NULL, -/* HW dependent part.*/ -ADC_TwoSamplingDelay_5Cycles, // cr1 - ADC_CR2_SWSTART, // cr2 - - 0, // sample times for channels 10...18 - ADC_SMPR2_SMP_AN0(MY_SAMPLING_FAST), // In this field must be specified the sample times for channels 0...9 - - ADC_SQR1_NUM_CH(ADC_NUMBER_CHANNELS_FAST), // Conversion group sequence 13...16 + sequence length - - 0, // Conversion group sequence 7...12 - 0 | ADC_SQR3_SQ1_N(ADC_CHANNEL_IN3) /* PA3 */ -// maf | ADC_SQR3_SQ1_N(ADC_CHANNEL_IN13) /* PC3 */ - - // Conversion group sequence 1...6 - }; - -static void pwmpcb_slow(PWMDriver *pwmp) { -#ifdef EFI_INTERNAL_ADC - (void) pwmp; - - /* Starts an asynchronous ADC conversion operation, the conversion - will be executed in parallel to the current PWM cycle and will - terminate before the next PWM cycle.*/chSysLockFromIsr() - ; - adcStartConversionI(&ADC_SLOW, &adcgrpcfg_slow, slowAdcState.samples, ADC_GRP1_BUF_DEPTH_SLOW); - chSysUnlockFromIsr() - ; -#endif -} - -static void pwmpcb_fast(PWMDriver *pwmp) { -#ifdef EFI_INTERNAL_ADC - (void) pwmp; - - /* Starts an asynchronous ADC conversion operation, the conversion - will be executed in parallel to the current PWM cycle and will - terminate before the next PWM cycle.*/chSysLockFromIsr() - ; - adcStartConversionI(&ADC_FAST, &adcgrpcfg_fast, samples_fast, ADC_GRP1_BUF_DEPTH_FAST); - chSysUnlockFromIsr() - ; -#endif -} - -int getAdcValueByIndex(int internalIndex) { - return newState.adc_data[internalIndex]; -} - -int getInternalAdcValue(int hwChannel) { -// if (hwIndex==ADC_NUMBER_CHANNELS_FAST) -// return fastAdcValue; - - int internalIndex = internalAdcIndexByHardwareIndex[hwChannel]; - return getAdcValueByIndex(internalIndex); -} - -static PWMConfig pwmcfg_slow = { PWM_FREQ_SLOW, PWM_PERIOD_SLOW, pwmpcb_slow, { { -PWM_OUTPUT_DISABLED, NULL }, { PWM_OUTPUT_DISABLED, NULL }, { -PWM_OUTPUT_DISABLED, NULL }, { PWM_OUTPUT_DISABLED, NULL } }, -/* HW dependent part.*/ -0 }; - -static PWMConfig pwmcfg_fast = { PWM_FREQ_FAST, PWM_PERIOD_FAST, pwmpcb_fast, { { -PWM_OUTPUT_DISABLED, NULL }, { PWM_OUTPUT_DISABLED, NULL }, { -PWM_OUTPUT_DISABLED, NULL }, { PWM_OUTPUT_DISABLED, NULL } }, -/* HW dependent part.*/ -0 }; - -static void initAdcPin(ioportid_t port, int pin, char *msg) { - print("adc %s\r\n", msg); - mySetPadMode("adc input", port, pin, PAL_MODE_INPUT_ANALOG); -} - -GPIO_TypeDef* getAdcChannelPort(int hwChannel) { - // todo: replace this with an array :) - switch (hwChannel) { - case ADC_CHANNEL_IN0: - return GPIOA; - case ADC_CHANNEL_IN1: - return GPIOA; - case ADC_CHANNEL_IN2: - return GPIOA; - case ADC_CHANNEL_IN3: - return GPIOA; - case ADC_CHANNEL_IN4: - return GPIOA; - case ADC_CHANNEL_IN5: - return GPIOA; - case ADC_CHANNEL_IN6: - return GPIOA; - case ADC_CHANNEL_IN7: - return GPIOA; - case ADC_CHANNEL_IN8: - return GPIOB; - case ADC_CHANNEL_IN9: - return GPIOB; - case ADC_CHANNEL_IN10: - return GPIOC; - case ADC_CHANNEL_IN11: - return GPIOC; - case ADC_CHANNEL_IN12: - return GPIOC; - case ADC_CHANNEL_IN13: - return GPIOC; - case ADC_CHANNEL_IN14: - return GPIOC; - case ADC_CHANNEL_IN15: - return GPIOC; - default: - fatal("Unknown hw channel"); - return NULL; - } -} - -int getAdcChannelPin(int hwChannel) { - // todo: replace this with an array :) - switch (hwChannel) { - case ADC_CHANNEL_IN0: - return 0; - case ADC_CHANNEL_IN1: - return 1; - case ADC_CHANNEL_IN2: - return 2; - case ADC_CHANNEL_IN3: - return 3; - case ADC_CHANNEL_IN4: - return 4; - case ADC_CHANNEL_IN5: - return 5; - break; - case ADC_CHANNEL_IN6: - return 6; - case ADC_CHANNEL_IN7: - return 7; - case ADC_CHANNEL_IN8: - return 0; - case ADC_CHANNEL_IN9: - return 1; - case ADC_CHANNEL_IN10: - return 0; - case ADC_CHANNEL_IN11: - return 1; - case ADC_CHANNEL_IN12: - return 2; - case ADC_CHANNEL_IN13: - return 3; - case ADC_CHANNEL_IN14: - return 4; - case ADC_CHANNEL_IN15: - return 5; - default: - fatal("Unknown hw channel"); - return -1; - } -} - -static void initAdcHwChannel(int hwChannel) { - GPIO_TypeDef* port = getAdcChannelPort(hwChannel); - int pin = getAdcChannelPin(hwChannel); - - initAdcPin(port, pin, "hw"); -} - -void initSlowChannel(int logicChannel, int hwChannel) { - internalAdcIndexByHardwareIndex[hwChannel] = logicChannel; - hardwareIndexByIndernalAdcIndex[logicChannel] = hwChannel; - if (logicChannel < 6) { - adcgrpcfg_slow.sqr3 += (hwChannel) << (5 * logicChannel); - } else { - adcgrpcfg_slow.sqr2 += (hwChannel) << (5 * (logicChannel - 6)); - } - - initAdcHwChannel(hwChannel); -} - -static void printAdcValue(int channel) { - int value = getAdcValue(channel); - float volts = adcToVoltsDivided(value); - scheduleMsg(&logger, "adc voltage : %f", volts); -} - -int getAdcHardwareIndexByInternalIndex(int index) { - return hardwareIndexByIndernalAdcIndex[index]; -} - -static void printFullAdcReport(void) { - - for (int index = 0; index < EFI_ADC_SLOW_CHANNELS_COUNT; index++) { - appendMsgPrefix(&logger); - - int hwIndex = getAdcHardwareIndexByInternalIndex(index); - GPIO_TypeDef* port = getAdcChannelPort(hwIndex); - int pin = getAdcChannelPin(hwIndex); - - int adcValue = getAdcValueByIndex(index); - appendPrintf(&logger, " ch%d %s%d", index, portname(port), pin); - appendPrintf(&logger, " ADC%d 12bit=%d", hwIndex, adcValue); - float volts = adcToVolts(adcValue); - appendPrintf(&logger, " v=%f", volts); - - appendMsgPostfix(&logger); - scheduleLogging(&logger); - } -} - -static void printStatus(void) { - scheduleIntValue(&logger, ADC_DEBUG_KEY, adcDebugReporting); -} - -static void setAdcDebugReporting(int value) { - adcDebugReporting = value; - printStatus(); -} - -void initAdcInputs() { - - initLoggingExt(&logger, "ADC", LOGGING_BUFFER, sizeof(LOGGING_BUFFER)); - - printStatus(); - - addConsoleActionI(ADC_DEBUG_KEY, &setAdcDebugReporting); - -#ifdef EFI_INTERNAL_ADC - /* - * Initializes the ADC driver. - */ - adcStart(&ADC_SLOW, NULL); - adcStart(&ADC_FAST, NULL); - - adcgrpcfg_slow.sqr2 = 0; - adcgrpcfg_slow.sqr3 = 0; - - int index = 0; - -#if EFI_USE_ADC_CHANNEL_IN0 - initSlowChannel(index++, ADC_CHANNEL_IN0); // PA0 -#endif -#if EFI_USE_ADC_CHANNEL_IN1 - initSlowChannel(index++, ADC_CHANNEL_IN1); // PA1 -#endif -#if EFI_USE_ADC_CHANNEL_IN2 - initSlowChannel(index++, ADC_CHANNEL_IN2); // PA2 -#endif -#if EFI_USE_ADC_CHANNEL_IN3 - initSlowChannel(index++, ADC_CHANNEL_IN3); // PA3 -#endif -#if EFI_USE_ADC_CHANNEL_IN4 - initSlowChannel(index++, ADC_CHANNEL_IN4); // PA4 -#endif -#if EFI_USE_ADC_CHANNEL_IN5 - initSlowChannel(index++, ADC_CHANNEL_IN5); // PA5 - this is also TIM2_CH1 -#endif -#if EFI_USE_ADC_CHANNEL_IN6 - initSlowChannel(index++, ADC_CHANNEL_IN6); // PA6 -#endif -#if EFI_USE_ADC_CHANNEL_IN7 - initSlowChannel(index++, ADC_CHANNEL_IN7); // PA7 -#endif -#if EFI_USE_ADC_CHANNEL_IN8 - initSlowChannel(index++, ADC_CHANNEL_IN8); // PB0 -#endif -#if EFI_USE_ADC_CHANNEL_IN9 - initSlowChannel(index++, ADC_CHANNEL_IN9); // PB1 -#endif -#if EFI_USE_ADC_CHANNEL_IN10 - initSlowChannel(index++, ADC_CHANNEL_IN10); // PC0 -#endif -#if EFI_USE_ADC_CHANNEL_IN11 - initSlowChannel(index++, ADC_CHANNEL_IN11); // PC1 -#endif -#if EFI_USE_ADC_CHANNEL_IN12 - initSlowChannel(index++, ADC_CHANNEL_IN12); // PC2 -#endif -#if EFI_USE_ADC_CHANNEL_IN13 - initSlowChannel(index++, ADC_CHANNEL_IN13); // PC3 -#endif -#if EFI_USE_ADC_CHANNEL_IN14 - initSlowChannel(index++, ADC_CHANNEL_IN14); // PC4 -#endif -#if EFI_USE_ADC_CHANNEL_IN15 - initSlowChannel(index++, ADC_CHANNEL_IN15); // PC5 -#endif - - if (index != EFI_ADC_SLOW_CHANNELS_COUNT) - fatal("Invalud internal ADC config"); - - /* - * Initializes the PWM driver. - */ - pwmStart(EFI_INTERNAL_SLOW_ADC_PWM, &pwmcfg_slow); - pwmStart(EFI_INTERNAL_FAST_ADC_PWM, &pwmcfg_fast); - addConsoleActionI("adc", printAdcValue); - addConsoleAction("fadc", printFullAdcReport); -#else - printSimpleMsg(&logger, "ADC disabled", 0); -#endif -} - -void pokeAdcInputs() { - if (!adcDebugReporting) - return; - printFullAdcReport(); -} - +/** + * @file adc_inputs.c + * @brief Low level ADC code + * + * @date Jan 14, 2013 + * @author Andrey Belomutskiy, (c) 2012-2014 + */ + +#include "main.h" +#include "engine_configuration.h" +#include "adc_inputs.h" +#include "AdcConfiguration.h" + +#include "pin_repository.h" +#include "engine_math.h" + +#if EFI_SPEED_DENSITY +#include "map_averaging.h" +#endif /* EFI_SPEED_DENSITY */ + +AdcConfiguration::AdcConfiguration(ADCConversionGroup* hwConfig) { + this->hwConfig = hwConfig; + channelCount = 0; + + hwConfig->sqr1 = 0; + hwConfig->sqr2 = 0; + hwConfig->sqr3 = 0; +} + +#define ADC_GRP1_BUF_DEPTH_FAST 1 + +#define ADC_NUMBER_CHANNELS_FAST 1 + +// todo: migrate from hardware timer to software ADC conversion triggering +#define PWM_FREQ_SLOW 5000 /* PWM clock frequency. I wonder what does this setting mean? */ +#define PWM_PERIOD_SLOW 500 /* PWM period (in PWM ticks). */ + +// todo: migrate to continues ADC mode? +#define PWM_FREQ_FAST 1500000 /* PWM clock frequency. I wonder what does this setting mean? */ +#define PWM_PERIOD_FAST 50 /* PWM period (in PWM ticks). */ + +#define ADC_SLOW_DEVICE ADCD1 + +#define ADC_FAST_DEVICE ADCD2 + +#define ADC_DEBUG_KEY "adcDebug" + +static char LOGGING_BUFFER[500]; +static Logging logger; +static int adcCallbackCounter_slow = 0; + +static int adcDebugReporting = FALSE; + +static int fastAdcValue; +extern engine_configuration_s *engineConfiguration; +extern board_configuration_s *boardConfiguration; + +static adc_hw_helper_s slowAdcState; + +/* + * ADC samples buffer. + */ +static adcsample_t samples_fast[ADC_NUMBER_CHANNELS_FAST * ADC_GRP1_BUF_DEPTH_FAST]; + +static adcsample_t getAvgAdcValue(int index, adcsample_t *samples, int bufDepth, int numChannels) { + adcsample_t result = 0; + int i; + for (i = 0; i < bufDepth; i++) { + result += samples[index]; + index += numChannels; + } + return result / bufDepth; +} + +static adc_state newState; + +static void adc_callback_slow(ADCDriver *adcp, adcsample_t *buffer, size_t n); +static void adc_callback_fast(ADCDriver *adcp, adcsample_t *buffer, size_t n); + +#define MY_SAMPLING_SLOW ADC_SAMPLE_480 +#define MY_SAMPLING_FAST ADC_SAMPLE_28 + +/* + * ADC conversion group. + */ +static ADCConversionGroup adcgrpcfgSlow = { FALSE, 0, adc_callback_slow, NULL, +/* HW dependent part.*/ +ADC_TwoSamplingDelay_20Cycles, // cr1 + ADC_CR2_SWSTART, // cr2 + + ADC_SMPR1_SMP_AN10(MY_SAMPLING_SLOW) | + ADC_SMPR1_SMP_AN11(MY_SAMPLING_SLOW) | + ADC_SMPR1_SMP_AN12(MY_SAMPLING_SLOW) | + ADC_SMPR1_SMP_AN13(MY_SAMPLING_SLOW), // sample times for channels 10...18 + ADC_SMPR2_SMP_AN0(MY_SAMPLING_SLOW) | + ADC_SMPR2_SMP_AN1(MY_SAMPLING_SLOW) | + ADC_SMPR2_SMP_AN3(MY_SAMPLING_SLOW) | + ADC_SMPR2_SMP_AN4(MY_SAMPLING_SLOW) | + ADC_SMPR2_SMP_AN5(MY_SAMPLING_SLOW) | + ADC_SMPR2_SMP_AN6(MY_SAMPLING_SLOW) | + ADC_SMPR2_SMP_AN7(MY_SAMPLING_SLOW) | + ADC_SMPR2_SMP_AN8(MY_SAMPLING_SLOW) | + ADC_SMPR2_SMP_AN9(MY_SAMPLING_SLOW) + + , // In this field must be specified the sample times for channels 0...9 + + 0, // Conversion group sequence 13...16 + sequence length + + 0 +// | ADC_SQR2_SQ7_N(ADC_CHANNEL_IN12) /* PC2 - green */ +// | ADC_SQR2_SQ8_N(ADC_CHANNEL_IN13) /* PC3 - yellow maf? */ + + ,// Conversion group sequence 7...12 + 0 +// | ADC_SQR3_SQ1_N(ADC_CHANNEL_IN6) /* PA6 - white */ +// | ADC_SQR3_SQ2_N(ADC_CHANNEL_IN7) /* PA7 - blue */ +// | ADC_SQR3_SQ3_N(ADC_CHANNEL_IN14) /* PC4 - green */ +// | ADC_SQR3_SQ4_N(ADC_CHANNEL_IN15) /* PC5 - yellow */ +// | ADC_SQR3_SQ5_N(ADC_CHANNEL_IN8) /* PB0 - blue */ +// | ADC_SQR3_SQ6_N(ADC_CHANNEL_IN9) /* PB1 - white */ +// Conversion group sequence 1...6 + }; + +static AdcConfiguration slowAdc(&adcgrpcfgSlow); + +static ADCConversionGroup adcgrpcfg_fast = { FALSE, 0 /* num_channels */, adc_callback_fast, NULL, +/* HW dependent part.*/ +ADC_TwoSamplingDelay_5Cycles, // cr1 + ADC_CR2_SWSTART, // cr2 + + 0, // sample times for channels 10...18 + ADC_SMPR2_SMP_AN0(MY_SAMPLING_FAST), // In this field must be specified the sample times for channels 0...9 + + ADC_SQR1_NUM_CH(ADC_NUMBER_CHANNELS_FAST), // Conversion group sequence 13...16 + sequence length + + 0, // Conversion group sequence 7...12 + 0 + +// Conversion group sequence 1...6 + }; + +static AdcConfiguration fastAdc(&adcgrpcfg_fast); + +static void pwmpcb_slow(PWMDriver *pwmp) { +#ifdef EFI_INTERNAL_ADC + (void) pwmp; + + /* Starts an asynchronous ADC conversion operation, the conversion + will be executed in parallel to the current PWM cycle and will + terminate before the next PWM cycle.*/ + chSysLockFromIsr() + ; + if (ADC_FAST_DEVICE.state != ADC_READY && + ADC_FAST_DEVICE.state != ADC_COMPLETE && + ADC_FAST_DEVICE.state != ADC_ERROR) { + firmwareError("ADC slow not ready?"); + chSysUnlockFromIsr() + ; + return; + } + adcStartConversionI(&ADC_SLOW_DEVICE, &adcgrpcfgSlow, slowAdcState.samples, ADC_GRP1_BUF_DEPTH_SLOW); + chSysUnlockFromIsr() + ; +#endif +} + +static void pwmpcb_fast(PWMDriver *pwmp) { +#ifdef EFI_INTERNAL_ADC + (void) pwmp; + + /* + * Starts an asynchronous ADC conversion operation, the conversion + * will be executed in parallel to the current PWM cycle and will + * terminate before the next PWM cycle. + */ + chSysLockFromIsr() + ; + if (ADC_FAST_DEVICE.state != ADC_READY && + ADC_FAST_DEVICE.state != ADC_COMPLETE && + ADC_FAST_DEVICE.state != ADC_ERROR) { + firmwareError("ADC fast not ready?"); + chSysUnlockFromIsr() + ; + return; + } + adcStartConversionI(&ADC_FAST_DEVICE, &adcgrpcfg_fast, samples_fast, ADC_GRP1_BUF_DEPTH_FAST); + chSysUnlockFromIsr() + ; +#endif +} + +int getAdcValueByIndex(int internalIndex) { + return newState.adc_data[internalIndex]; +} + +int getInternalAdcValue(int hwChannel) { + if (boardConfiguration->adcHwChannelEnabled[hwChannel] == ADC_FAST) + return fastAdcValue; + + int internalIndex = slowAdc.internalAdcIndexByHardwareIndex[hwChannel]; + return getAdcValueByIndex(internalIndex); +} + +static PWMConfig pwmcfg_slow = { PWM_FREQ_SLOW, PWM_PERIOD_SLOW, pwmpcb_slow, { { +PWM_OUTPUT_DISABLED, NULL }, { PWM_OUTPUT_DISABLED, NULL }, { +PWM_OUTPUT_DISABLED, NULL }, { PWM_OUTPUT_DISABLED, NULL } }, +/* HW dependent part.*/ +0 }; + +static PWMConfig pwmcfg_fast = { PWM_FREQ_FAST, PWM_PERIOD_FAST, pwmpcb_fast, { { +PWM_OUTPUT_DISABLED, NULL }, { PWM_OUTPUT_DISABLED, NULL }, { +PWM_OUTPUT_DISABLED, NULL }, { PWM_OUTPUT_DISABLED, NULL } }, +/* HW dependent part.*/ +0 }; + +static void initAdcPin(ioportid_t port, int pin, char *msg) { + print("adc %s\r\n", msg); + mySetPadMode("adc input", port, pin, PAL_MODE_INPUT_ANALOG); +} + +GPIO_TypeDef* getAdcChannelPort(int hwChannel) { + // todo: replace this with an array :) + switch (hwChannel) { + case ADC_CHANNEL_IN0: + return GPIOA; + case ADC_CHANNEL_IN1: + return GPIOA; + case ADC_CHANNEL_IN2: + return GPIOA; + case ADC_CHANNEL_IN3: + return GPIOA; + case ADC_CHANNEL_IN4: + return GPIOA; + case ADC_CHANNEL_IN5: + return GPIOA; + case ADC_CHANNEL_IN6: + return GPIOA; + case ADC_CHANNEL_IN7: + return GPIOA; + case ADC_CHANNEL_IN8: + return GPIOB; + case ADC_CHANNEL_IN9: + return GPIOB; + case ADC_CHANNEL_IN10: + return GPIOC; + case ADC_CHANNEL_IN11: + return GPIOC; + case ADC_CHANNEL_IN12: + return GPIOC; + case ADC_CHANNEL_IN13: + return GPIOC; + case ADC_CHANNEL_IN14: + return GPIOC; + case ADC_CHANNEL_IN15: + return GPIOC; + default: + fatal("Unknown hw channel") + ; + return NULL; + } +} + +int getAdcChannelPin(int hwChannel) { + // todo: replace this with an array :) + switch (hwChannel) { + case ADC_CHANNEL_IN0: + return 0; + case ADC_CHANNEL_IN1: + return 1; + case ADC_CHANNEL_IN2: + return 2; + case ADC_CHANNEL_IN3: + return 3; + case ADC_CHANNEL_IN4: + return 4; + case ADC_CHANNEL_IN5: + return 5; + case ADC_CHANNEL_IN6: + return 6; + case ADC_CHANNEL_IN7: + return 7; + case ADC_CHANNEL_IN8: + return 0; + case ADC_CHANNEL_IN9: + return 1; + case ADC_CHANNEL_IN10: + return 0; + case ADC_CHANNEL_IN11: + return 1; + case ADC_CHANNEL_IN12: + return 2; + case ADC_CHANNEL_IN13: + return 3; + case ADC_CHANNEL_IN14: + return 4; + case ADC_CHANNEL_IN15: + return 5; + default: + fatal("Unknown hw channel") + ; + return -1; + } +} + +static void initAdcHwChannel(int hwChannel) { + GPIO_TypeDef* port = getAdcChannelPort(hwChannel); + int pin = getAdcChannelPin(hwChannel); + + initAdcPin(port, pin, "hw"); +} + +int AdcConfiguration::size() { + return channelCount; +} + +void AdcConfiguration::init(void) { + hwConfig->num_channels = size(); + hwConfig->sqr1 += ADC_SQR1_NUM_CH(size()); +} + +void AdcConfiguration::addChannel(int hwChannel) { + int logicChannel = channelCount++; + + internalAdcIndexByHardwareIndex[hwChannel] = logicChannel; + hardwareIndexByIndernalAdcIndex[logicChannel] = hwChannel; + if (logicChannel < 6) { + hwConfig->sqr3 += (hwChannel) << (5 * logicChannel); + } else { + hwConfig->sqr2 += (hwChannel) << (5 * (logicChannel - 6)); + } + // todo: support for more then 12 channels? not sure how needed it would be + + initAdcHwChannel(hwChannel); +} + +static void printAdcValue(int channel) { + int value = getAdcValue(channel); + float volts = adcToVoltsDivided(value); + scheduleMsg(&logger, "adc voltage : %f", volts); +} + +int AdcConfiguration::getAdcHardwareIndexByInternalIndex(int index) { + return hardwareIndexByIndernalAdcIndex[index]; +} + +static void printFullAdcReport(void) { + + for (int index = 0; index < slowAdc.size(); index++) { + appendMsgPrefix(&logger); + + int hwIndex = slowAdc.getAdcHardwareIndexByInternalIndex(index); + GPIO_TypeDef* port = getAdcChannelPort(hwIndex); + int pin = getAdcChannelPin(hwIndex); + + int adcValue = getAdcValueByIndex(index); + appendPrintf(&logger, " ch%d %s%d", index, portname(port), pin); + appendPrintf(&logger, " ADC%d 12bit=%d", hwIndex, adcValue); + float volts = adcToVolts(adcValue); + appendPrintf(&logger, " v=%f", volts); + + appendMsgPostfix(&logger); + scheduleLogging(&logger); + } +} + +static void printStatus(void) { + scheduleIntValue(&logger, ADC_DEBUG_KEY, adcDebugReporting); +} + +static void setAdcDebugReporting(int value) { + adcDebugReporting = value; + printStatus(); +} + +static void adc_callback_slow(ADCDriver *adcp, adcsample_t *buffer, size_t n) { + (void) buffer; + (void) n; + /* Note, only in the ADC_COMPLETE state because the ADC driver fires + * an intermediate callback when the buffer is half full. */ + if (adcp->state == ADC_COMPLETE) { + /* Calculates the average values from the ADC samples.*/ + + adcCallbackCounter_slow++; + +// newState.time = chimeNow(); + for (int i = 0; i < slowAdc.size(); i++) { + int value = getAvgAdcValue(i, slowAdcState.samples, ADC_GRP1_BUF_DEPTH_SLOW, slowAdc.size()); + newState.adc_data[i] = value; + } + } +} + +static void adc_callback_fast(ADCDriver *adcp, adcsample_t *buffer, size_t n) { + (void) buffer; + (void) n; +// /* Note, only in the ADC_COMPLETE state because the ADC driver fires an +// intermediate callback when the buffer is half full.*/ + if (adcp->state == ADC_COMPLETE) { + fastAdcValue = getAvgAdcValue(0, samples_fast, ADC_GRP1_BUF_DEPTH_FAST, fastAdc.size()); +#if EFI_MAP_AVERAGING + mapAveragingCallback(fastAdcValue); +#endif /* EFI_MAP_AVERAGING */ + } +} + +void initAdcInputs() { + + initLoggingExt(&logger, "ADC", LOGGING_BUFFER, sizeof(LOGGING_BUFFER)); + printMsg(&logger, "initAdcInputs()"); + + printStatus(); + + addConsoleActionI(ADC_DEBUG_KEY, &setAdcDebugReporting); + +#ifdef EFI_INTERNAL_ADC + /* + * Initializes the ADC driver. + */ + adcStart(&ADC_SLOW_DEVICE, NULL); + adcStart(&ADC_FAST_DEVICE, NULL); + + for (int adc = 0; adc < HW_MAX_ADC_INDEX; adc++) { + adc_channel_mode_e mode = boardConfiguration->adcHwChannelEnabled[adc]; + + if (mode == ADC_SLOW) { + slowAdc.addChannel(ADC_CHANNEL_IN0 + adc); + } else if (mode == ADC_FAST) { + fastAdc.addChannel(ADC_CHANNEL_IN0 + adc); + } + } + + slowAdc.init(); + fastAdc.init(); + + // ADC_CHANNEL_IN0 // PA0 + // ADC_CHANNEL_IN1 // PA1 + // ADC_CHANNEL_IN2 // PA2 + // ADC_CHANNEL_IN3 // PA3 + // ADC_CHANNEL_IN4 // PA4 + // ADC_CHANNEL_IN5 // PA5 - this is also TIM2_CH1 + // ADC_CHANNEL_IN6 // PA6 + // ADC_CHANNEL_IN7 // PA7 + // ADC_CHANNEL_IN8 // PB0 + // ADC_CHANNEL_IN9 // PB1 + // ADC_CHANNEL_IN10 // PC0 + // ADC_CHANNEL_IN11 // PC1 + // ADC_CHANNEL_IN12 // PC2 + // ADC_CHANNEL_IN13 // PC3 + // ADC_CHANNEL_IN14 // PC4 + // ADC_CHANNEL_IN15 // PC5 + + //if(slowAdcChannelCount > ADC_MAX_SLOW_CHANNELS_COUNT) // todo: do we need this logic? do we need this check + + /* + * Initializes the PWM driver. + */ + pwmStart(EFI_INTERNAL_SLOW_ADC_PWM, &pwmcfg_slow); + pwmStart(EFI_INTERNAL_FAST_ADC_PWM, &pwmcfg_fast); + addConsoleActionI("adc", printAdcValue); + addConsoleAction("fadc", printFullAdcReport); +#else + printSimpleMsg(&logger, "ADC disabled", 0); +#endif +} + +void pokeAdcInputs() { + if (!adcDebugReporting) + return; + printFullAdcReport(); +} + diff --git a/firmware/hw_layer/adc_inputs.h b/firmware/hw_layer/adc_inputs.h index 20dcf311a3..9a0fd695b7 100644 --- a/firmware/hw_layer/adc_inputs.h +++ b/firmware/hw_layer/adc_inputs.h @@ -32,16 +32,18 @@ int getInternalAdcValue(int index); /* Depth of the conversion buffer, channels are sampled X times each.*/ #define ADC_GRP1_BUF_DEPTH_SLOW 1 -#define ADC_MAX_SLOW_CHANNELS_COUNT 12 +#define ADC_MAX_CHANNELS_COUNT 16 + +//typedef struct // this structure contains one multi-channel ADC state snapshot typedef struct { - volatile adcsample_t adc_data[ADC_MAX_SLOW_CHANNELS_COUNT]; + volatile adcsample_t adc_data[ADC_MAX_CHANNELS_COUNT]; // time_t time; } adc_state; typedef struct { - adcsample_t samples[ADC_MAX_SLOW_CHANNELS_COUNT * ADC_GRP1_BUF_DEPTH_SLOW]; + adcsample_t samples[ADC_MAX_CHANNELS_COUNT * ADC_GRP1_BUF_DEPTH_SLOW]; } adc_hw_helper_s; diff --git a/firmware/hw_layer/board_test.c b/firmware/hw_layer/board_test.cpp similarity index 94% rename from firmware/hw_layer/board_test.c rename to firmware/hw_layer/board_test.cpp index 3e232d1d47..3a7342dfcf 100644 --- a/firmware/hw_layer/board_test.c +++ b/firmware/hw_layer/board_test.cpp @@ -1,146 +1,152 @@ -/** - * @file board_test.c - * @brief This is a simple board testing utility - * - * @date Mar 12, 2014 - * @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 . - */ - -#include "main.h" -#include "rusefi_enums.h" -#include "pin_repository.h" -#include "gpio_helper.h" -#include "adc_inputs.h" - -static volatile int stepCoutner = 0; -static volatile brain_pin_e currentPin; -static volatile int currentIndex = 0; - -static int isTimeForNextStep(int copy) { - return copy != stepCoutner; -} - -static void waitForKey(void) { - print("Please hit N to continue\r\n"); - int copy = stepCoutner; - while (!isTimeForNextStep(copy)) - chThdSleepMilliseconds(10); -} - -static void nextStep(void) { - stepCoutner++; -} - -static void setIndex(int index) { - currentIndex = index; - nextStep(); -} - -static brain_pin_e BLINK_PINS[] = { GPIOE_8, // HIGH DRIVER 1 - GPIOE_10, // HIGH DRIVER 2 - GPIOE_12, // HIGH DRIVER 3 - GPIOE_14, // HIGH DRIVER 4 - GPIOC_9, // HIGH DRIVER 5 - GPIOC_7, // HIGH DRIVER 6 - // index = 6 - GPIOC_14, // OUT 1 - GPIOC_15, // OUT2 - GPIOE_6, // OUT3 - GPIOC_13, // OUT4 - GPIOE_4, // OUT5 - GPIOE_5, // OUT6 - GPIOE_2, // OUT7 - GPIOE_3, // OUT8 - GPIOE_0, // OUT9 - GPIOE_1, // OUT10 - GPIOB_8, // OUT11 - GPIOB_9, // OUT12 - }; - -static WORKING_AREA(btThreadStack, UTILITY_THREAD_STACK_SIZE); - -static msg_t ivThread(int param) { - chRegSetThreadName("board test blinking"); - - int value = 0; - - while (TRUE) { - chThdSleepMilliseconds(250); - value = 1 - value; - GPIO_TypeDef *hwPort = getHwPort(currentPin); - uint32_t hwPin = getHwPin(currentPin); - palWritePad(hwPort, hwPin, value); - } - return 0; -} - -void initBoardTest(void) { - // todo: add a command to go into board test mode after reboot - if (1 == 1) - return; - - addConsoleAction("n", nextStep); - addConsoleActionI("set", setIndex); - - chThdCreateStatic(btThreadStack, sizeof(btThreadStack), NORMALPRIO, (tfunc_t) ivThread, NULL); - - // this code is ugly as hell, I had no time to think. Todo: refactor - - int pinsCount = sizeof(BLINK_PINS) / sizeof(brain_pin_e); - - while (currentIndex < EFI_ADC_SLOW_CHANNELS_COUNT) { - int hwIndex = getAdcHardwareIndexByInternalIndex(currentIndex); - GPIO_TypeDef* port = getAdcChannelPort(hwIndex); - int pin = getAdcChannelPin(hwIndex); - - int value = getAdcValueByIndex(currentIndex); - - int copy = stepCoutner; - - int c = 0; - - while (!isTimeForNextStep(copy)) { - - print("ch%d hwIndex=%d %s%d\r\n", currentIndex, hwIndex, portname(port), pin); - - int adcValue = getAdcValueByIndex(currentIndex); - -// print("ADC%d val= %d%s", hwIndex, value, DELIMETER); - float volts = adcToVolts(adcValue) * 2; - print("v=%f adc=%d c=%d\r\n", volts, adcValue, c++); - - chThdSleepMilliseconds(300); - - } - currentIndex++; - } - - currentIndex = 0; - - while (currentIndex < pinsCount) { - currentPin = BLINK_PINS[currentIndex]; - - GPIO_TypeDef *hwPort = getHwPort(currentPin); - uint32_t hwPin = getHwPin(currentPin); - - print("currentIndex=%d\r\n", currentIndex); - print("Let's test %s%d\r\n", portname(hwPort), hwPin); - mySetPadMode("test", hwPort, hwPin, PAL_STM32_MODE_OUTPUT); - - currentIndex++; - waitForKey(); - } -} +/** + * @file board_test.c + * @brief This is a simple board testing utility + * + * @date Mar 12, 2014 + * @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 . + */ + +#include "main.h" +#include "board_test.h" +#include "rusefi_enums.h" +#include "pin_repository.h" +#include "gpio_helper.h" +#include "adc_inputs.h" +#include "AdcConfiguration.h" + +static volatile int stepCoutner = 0; +static volatile brain_pin_e currentPin; +static volatile int currentIndex = 0; + +extern AdcConfiguration slowAdc; + +static int isTimeForNextStep(int copy) { + return copy != stepCoutner; +} + +static void waitForKey(void) { + print("Please hit N to continue\r\n"); + int copy = stepCoutner; + while (!isTimeForNextStep(copy)) + chThdSleepMilliseconds(10); +} + +static void nextStep(void) { + stepCoutner++; +} + +static void setIndex(int index) { + currentIndex = index; + nextStep(); +} + +static brain_pin_e BLINK_PINS[] = { GPIOE_8, // HIGH DRIVER 1 + GPIOE_10, // HIGH DRIVER 2 + GPIOE_12, // HIGH DRIVER 3 + GPIOE_14, // HIGH DRIVER 4 + GPIOC_9, // HIGH DRIVER 5 + GPIOC_7, // HIGH DRIVER 6 + // index = 6 + GPIOC_14, // OUT 1 + GPIOC_15, // OUT2 + GPIOE_6, // OUT3 + GPIOC_13, // OUT4 + GPIOE_4, // OUT5 + GPIOE_5, // OUT6 + GPIOE_2, // OUT7 + GPIOE_3, // OUT8 + GPIOE_0, // OUT9 + GPIOE_1, // OUT10 + GPIOB_8, // OUT11 + GPIOB_9, // OUT12 + }; + +static WORKING_AREA(btThreadStack, UTILITY_THREAD_STACK_SIZE); + +static msg_t ivThread(int param) { + chRegSetThreadName("board test blinking"); + + int value = 0; + + while (TRUE) { + chThdSleepMilliseconds(250); + value = 1 - value; + GPIO_TypeDef *hwPort = getHwPort(currentPin); + uint32_t hwPin = getHwPin(currentPin); + palWritePad(hwPort, hwPin, value); + } +#if defined __GNUC__ + return 0; +#endif +} + +void initBoardTest(void) { + // todo: add a command to go into board test mode after reboot + if (1 == 1) + return; + + addConsoleAction("n", nextStep); + addConsoleActionI("set", setIndex); + + chThdCreateStatic(btThreadStack, sizeof(btThreadStack), NORMALPRIO, (tfunc_t) ivThread, NULL); + + // this code is ugly as hell, I had no time to think. Todo: refactor + + int pinsCount = sizeof(BLINK_PINS) / sizeof(brain_pin_e); + + while (currentIndex < slowAdc.size()) { + int hwIndex = getAdcHardwareIndexByInternalIndex(currentIndex); + GPIO_TypeDef* port = getAdcChannelPort(hwIndex); + int pin = getAdcChannelPin(hwIndex); + + int value = getAdcValueByIndex(currentIndex); + + int copy = stepCoutner; + + int c = 0; + + while (!isTimeForNextStep(copy)) { + + print("ch%d hwIndex=%d %s%d\r\n", currentIndex, hwIndex, portname(port), pin); + + int adcValue = getAdcValueByIndex(currentIndex); + +// print("ADC%d val= %d%s", hwIndex, value, DELIMETER); + float volts = adcToVolts(adcValue) * 2; + print("v=%f adc=%d c=%d\r\n", volts, adcValue, c++); + + chThdSleepMilliseconds(300); + + } + currentIndex++; + } + + currentIndex = 0; + + while (currentIndex < pinsCount) { + currentPin = BLINK_PINS[currentIndex]; + + GPIO_TypeDef *hwPort = getHwPort(currentPin); + uint32_t hwPin = getHwPin(currentPin); + + print("currentIndex=%d\r\n", currentIndex); + print("Let's test %s%d\r\n", portname(hwPort), hwPin); + mySetPadMode("test", hwPort, hwPin, PAL_STM32_MODE_OUTPUT); + + currentIndex++; + waitForKey(); + } +} diff --git a/firmware/hw_layer/flash.c b/firmware/hw_layer/flash.c index 65c4f9a02b..dd3987a14a 100644 --- a/firmware/hw_layer/flash.c +++ b/firmware/hw_layer/flash.c @@ -3,6 +3,10 @@ * @brief Lower-level code related to internal flash memory */ +#include "main.h" + +#if EFI_INTERNAL_FLASH + #include "flash.h" #include @@ -260,3 +264,5 @@ int flashWrite(flashaddr_t address, const char* buffer, size_t size) { return FLASH_RETURN_SUCCESS; } + +#endif /* EFI_INTERNAL_FLASH */ diff --git a/firmware/hw_layer/hardware.cpp b/firmware/hw_layer/hardware.cpp index 3ad3a1f4ce..013fa92eb8 100644 --- a/firmware/hw_layer/hardware.cpp +++ b/firmware/hw_layer/hardware.cpp @@ -6,6 +6,7 @@ * @author Andrey Belomutskiy, (c) 2012-2014 */ +#include "main.h" #include "hardware.h" #include "pin_repository.h" #include "io_pins.h" @@ -25,13 +26,23 @@ #include "mmc_card.h" #include "neo6m.h" #include "lcd_HD44780.h" -#include "eficonsole_logic.h" +#include "settings.h" + +#if EFI_INTERNAL_FLASH #include "flash_main.h" +#endif /* EFI_INTERNAL_FLASH */ + #include "trigger_central.h" #include "svnversion.h" +#include "engine_configuration.h" +#include "ec2.h" McpAdcState adcState; +extern engine_configuration_s *engineConfiguration; +extern engine_configuration2_s * engineConfiguration2; +extern board_configuration_s *boardConfiguration; + static void initSpiModule(SPIDriver *driver, ioportid_t sckPort, ioportmask_t sckPin, ioportid_t misoPort, ioportmask_t misoPin, ioportid_t mosiPort, ioportmask_t mosiPin, int af) { mySetPadMode("SPI clock", sckPort, sckPin, PAL_MODE_ALTERNATE(af)); @@ -72,7 +83,7 @@ void initI2Cmodule(void) { PAL_MODE_ALTERNATE(EFI_I2C_AF) | PAL_STM32_OTYPE_OPENDRAIN); } -static char txbuf[1]; +//static char txbuf[1]; static void sendI2Cbyte(int addr, int data) { // i2cAcquireBus(&I2CD1); @@ -81,16 +92,18 @@ static void sendI2Cbyte(int addr, int data) { // i2cReleaseBus(&I2CD1); } -void initHardware() { +void initHardware(Logging *logger) { + printMsg(logger, "initHardware()"); // todo: enable protection. it's disabled because it takes // 10 extra seconds to re-flash the chip //flashProtect(); +#if EFI_HISTOGRAMS /** * histograms is a data structure for CPU monitor, it does not depend on configuration */ initHistogramsModule(); - +#endif /* EFI_HISTOGRAMS */ /** @@ -98,11 +111,22 @@ void initHardware() { */ initPrimaryPins(); + if (hasFirmwareError()) + return; + +#if EFI_INTERNAL_FLASH /** * this call reads configuration from flash memory or sets default configuration * if flash state does not look right. */ initFlash(); +#else + engineConfiguration->engineType = FORD_ASPIRE_1996; + resetConfigurationExt(logger, engineConfiguration->engineType, engineConfiguration, engineConfiguration2, boardConfiguration); +#endif /* EFI_INTERNAL_FLASH */ + + if (hasFirmwareError()) + return; initRtc(); @@ -123,7 +147,10 @@ void initHardware() { // todo: figure out better startup logic initTriggerCentral(); + +#if EFI_SHAFT_POSITION_INPUT initShaftPositionInputCapture(); +#endif /* EFI_SHAFT_POSITION_INPUT */ initSpiModules(); @@ -146,12 +173,14 @@ void initHardware() { #if EFI_HD44780_LCD // initI2Cmodule(); lcd_HD44780_init(); + if (hasFirmwareError()) + return; char buffer[16]; itoa10((uint8_t*)buffer, SVN_VERSION); lcd_HD44780_print_string(buffer); -#endif +#endif /* EFI_HD44780_LCD */ addConsoleActionII("i2c", sendI2Cbyte); @@ -167,5 +196,5 @@ void initHardware() { // } initBoardTest(); - + printMsg(logger, "initHardware() OK!"); } diff --git a/firmware/hw_layer/hardware.h b/firmware/hw_layer/hardware.h index 577804d493..7863bb897f 100644 --- a/firmware/hw_layer/hardware.h +++ b/firmware/hw_layer/hardware.h @@ -8,12 +8,14 @@ #ifndef HARDWARE_H_ #define HARDWARE_H_ +#include "main.h" + #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ -void initHardware(void); +void initHardware(Logging *logging); #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/firmware/hw_layer/hw_layer.mk b/firmware/hw_layer/hw_layer.mk index 5fa23b6fac..c74db06e10 100644 --- a/firmware/hw_layer/hw_layer.mk +++ b/firmware/hw_layer/hw_layer.mk @@ -1,6 +1,5 @@ -HW_LAYERSRC = $(PROJECT_DIR)/hw_layer/adc_inputs.c \ - $(PROJECT_DIR)/hw_layer/pin_repository.c \ +HW_LAYERSRC = $(PROJECT_DIR)/hw_layer/pin_repository.c \ $(PROJECT_DIR)/hw_layer/io_pins.c \ $(PROJECT_DIR)/hw_layer/mcp3208.c \ $(PROJECT_DIR)/hw_layer/lcd/lcd_HD44780.c \ @@ -14,9 +13,10 @@ HW_LAYERSRC = $(PROJECT_DIR)/hw_layer/adc_inputs.c \ $(PROJECT_DIR)/hw_layer/mmc_card.c \ $(PROJECT_DIR)/hw_layer/neo6m.c \ $(PROJECT_DIR)/hw_layer/gpio_helper.c \ - $(PROJECT_DIR)/hw_layer/board_test.c \ $(PROJECT_DIR)/hw_layer/wave_analyzer_hw.c HW_LAYER_SRC_CPP = $(PROJECT_DIR)/hw_layer/hardware.cpp \ + $(PROJECT_DIR)/hw_layer/adc_inputs.cpp \ + $(PROJECT_DIR)/hw_layer/board_test.cpp \ $(PROJECT_DIR)/hw_layer/pwm_generator.cpp \ $(PROJECT_DIR)/hw_layer/trigger_input.cpp diff --git a/firmware/hw_layer/io_pins.c b/firmware/hw_layer/io_pins.c index dcb6f652c6..4d59d12fe5 100644 --- a/firmware/hw_layer/io_pins.c +++ b/firmware/hw_layer/io_pins.c @@ -13,10 +13,13 @@ #include "pin_repository.h" #include "gpio_helper.h" #include "status_loop.h" -#include "main_trigger_callback.h" #include "engine_configuration.h" #include "console_io.h" +#if EFI_ENGINE_CONTROL +#include "main_trigger_callback.h" +#endif /* EFI_ENGINE_CONTROL */ + extern board_configuration_s *boardConfiguration; static pin_output_mode_e *pinDefaultState[IO_PIN_COUNT]; @@ -76,7 +79,7 @@ void setDefaultPinState(io_pin_e pin, pin_output_mode_e *outputMode) { static void comBlinkingThread(void *arg) { chRegSetThreadName("comm blinking"); while (TRUE) { - int delay = is_serial_ready() ? 100 : 33; + int delay = isConsoleReady() ? 100 : 33; setOutputPinValue(LED_COMMUNICATION_1, 0); setOutputPinValue(LED_EXT_1, 1); @@ -97,6 +100,7 @@ int isTriggerDecoderError(void); static void errBlinkingThread(void *arg) { chRegSetThreadName("err blinking"); +#if EFI_ENGINE_CONTROL while (TRUE) { int delay = 33; if (isTriggerDecoderError() || isIgnitionTimingError()) @@ -106,9 +110,11 @@ static void errBlinkingThread(void *arg) { setOutputPinValue(LED_ERROR, 0); chThdSleepMilliseconds(delay); } +#endif /* EFI_ENGINE_CONTROL */ } -static void outputPinRegisterExt(const char *msg, io_pin_e ioPin, GPIO_TypeDef *port, uint32_t pin, pin_output_mode_e *outputMode) { +static void outputPinRegisterExt(const char *msg, io_pin_e ioPin, GPIO_TypeDef *port, uint32_t pin, + pin_output_mode_e *outputMode) { if (port == GPIO_NULL) { // that's for GRIO_NONE outputs[ioPin].port = port; @@ -128,12 +134,20 @@ static void outputPinRegisterExt(const char *msg, io_pin_e ioPin, GPIO_TypeDef * GPIO_TypeDef * getHwPort(brain_pin_e brainPin) { if (brainPin == GPIO_NONE) return GPIO_NULL; + if (brainPin > GPIO_NONE) { + firmwareError("Invalid brain_pin_e: %d", brainPin); + return GPIO_NULL; + } return PORTS[brainPin / 16]; } int getHwPin(brain_pin_e brainPin) { if (brainPin == GPIO_NONE) return -1; + if (brainPin > GPIO_NONE) { + firmwareError("Invalid brain_pin_e: %d", brainPin); + return -1; + } return brainPin % 16; } @@ -163,7 +177,7 @@ static void initialLedsBlink(void) { } void initPrimaryPins(void) { - outputPinRegister("error", LED_ERROR, LED_ERROR_PORT, LED_ERROR_PIN); + outputPinRegister("LED_ERROR", LED_ERROR, LED_ERROR_PORT, LED_ERROR_PIN); } void initOutputPins(void) { diff --git a/firmware/hw_layer/lcd/lcd_HD44780.c b/firmware/hw_layer/lcd/lcd_HD44780.c index 66bce7601a..ed952c431f 100644 --- a/firmware/hw_layer/lcd/lcd_HD44780.c +++ b/firmware/hw_layer/lcd/lcd_HD44780.c @@ -71,16 +71,20 @@ static void lcdSleep(int period) { } } -static char txbuf[1]; +//static char txbuf[1]; #define LCD_PORT_EXP_ADDR 0x20 //----------------------------------------------------------------------------- static void lcd_HD44780_write(uint8_t data) { if (engineConfiguration->displayMode == DM_HD44780) { - palWritePad(getHwPort(boardConfiguration->HD44780_db7), getHwPin(boardConfiguration->HD44780_db7), data & 0x80 ? 1 : 0); - palWritePad(getHwPort(boardConfiguration->HD44780_db6), getHwPin(boardConfiguration->HD44780_db6), data & 0x40 ? 1 : 0); - palWritePad(getHwPort(boardConfiguration->HD44780_db5), getHwPin(boardConfiguration->HD44780_db5), data & 0x20 ? 1 : 0); - palWritePad(getHwPort(boardConfiguration->HD44780_db4), getHwPin(boardConfiguration->HD44780_db4), data & 0x10 ? 1 : 0); + palWritePad(getHwPort(boardConfiguration->HD44780_db7), getHwPin(boardConfiguration->HD44780_db7), + data & 0x80 ? 1 : 0); + palWritePad(getHwPort(boardConfiguration->HD44780_db6), getHwPin(boardConfiguration->HD44780_db6), + data & 0x40 ? 1 : 0); + palWritePad(getHwPort(boardConfiguration->HD44780_db5), getHwPin(boardConfiguration->HD44780_db5), + data & 0x20 ? 1 : 0); + palWritePad(getHwPort(boardConfiguration->HD44780_db4), getHwPin(boardConfiguration->HD44780_db4), + data & 0x10 ? 1 : 0); palSetPad(getHwPort(boardConfiguration->HD44780_e), getHwPin(boardConfiguration->HD44780_e)); // En high lcdSleep(10); // enable pulse must be >450ns @@ -96,16 +100,17 @@ static void lcd_HD44780_write(uint8_t data) { // LCD Pin RW -> P1 // LCD Pin E -> P2 - i2cAcquireBus(&I2CD1); - - txbuf[0] = 4; - i2cMasterTransmit(&I2CD1, LCD_PORT_EXP_ADDR, txbuf, 1, NULL, 0); - lcdSleep(10); // enable pulse must be >450ns - - txbuf[0] = 0; - i2cMasterTransmit(&I2CD1, LCD_PORT_EXP_ADDR, txbuf, 1, NULL, 0); - - i2cReleaseBus(&I2CD1); + // todo: finish all this stuff +// i2cAcquireBus(&I2CD1); +// +// txbuf[0] = 4; +// i2cMasterTransmit(&I2CD1, LCD_PORT_EXP_ADDR, txbuf, 1, NULL, 0); +// lcdSleep(10); // enable pulse must be >450ns +// +// txbuf[0] = 0; +// i2cMasterTransmit(&I2CD1, LCD_PORT_EXP_ADDR, txbuf, 1, NULL, 0); +// +// i2cReleaseBus(&I2CD1); } } @@ -149,9 +154,15 @@ void lcd_HD44780_print_string(char* string) { } //getHwPin(boardConfiguration->HD44780_db7) static void lcdInfo(void) { - scheduleMsg(&logger, "HD44780 RS=%s%d E=%s%d", portname(getHwPort(boardConfiguration->HD44780_rs)), getHwPin(boardConfiguration->HD44780_rs), portname(getHwPort(boardConfiguration->HD44780_e)), getHwPin(boardConfiguration->HD44780_e)); - scheduleMsg(&logger, "HD44780 D4=%s%d D5=%s%d", portname(getHwPort(boardConfiguration->HD44780_db4)), getHwPin(boardConfiguration->HD44780_db4), portname(getHwPort(boardConfiguration->HD44780_db5)), getHwPin(boardConfiguration->HD44780_db5)); - scheduleMsg(&logger, "HD44780 D6=%s%d D7=%s%d", portname(getHwPort(boardConfiguration->HD44780_db6)), getHwPin(boardConfiguration->HD44780_db6), portname(getHwPort(boardConfiguration->HD44780_db7)), getHwPin(boardConfiguration->HD44780_db7)); + scheduleMsg(&logger, "HD44780 RS=%s%d E=%s%d", portname(getHwPort(boardConfiguration->HD44780_rs)), + getHwPin(boardConfiguration->HD44780_rs), portname(getHwPort(boardConfiguration->HD44780_e)), + getHwPin(boardConfiguration->HD44780_e)); + scheduleMsg(&logger, "HD44780 D4=%s%d D5=%s%d", portname(getHwPort(boardConfiguration->HD44780_db4)), + getHwPin(boardConfiguration->HD44780_db4), portname(getHwPort(boardConfiguration->HD44780_db5)), + getHwPin(boardConfiguration->HD44780_db5)); + scheduleMsg(&logger, "HD44780 D6=%s%d D7=%s%d", portname(getHwPort(boardConfiguration->HD44780_db6)), + getHwPin(boardConfiguration->HD44780_db6), portname(getHwPort(boardConfiguration->HD44780_db7)), + getHwPin(boardConfiguration->HD44780_db7)); } void lcd_HD44780_init(void) { @@ -159,14 +170,27 @@ void lcd_HD44780_init(void) { addConsoleAction("lcdinfo", lcdInfo); + if (engineConfiguration->displayMode > DM_HD44780_OVER_PCF8574) { + firmwareError("Unexpected displayMode %d", engineConfiguration->displayMode); + return; + } + + printMsg(&logger, "lcd_HD44780_init %d", engineConfiguration->displayMode); + if (engineConfiguration->displayMode == DM_HD44780) { // initialize hardware lines - mySetPadMode("lcd RS", getHwPort(boardConfiguration->HD44780_rs), getHwPin(boardConfiguration->HD44780_rs), PAL_MODE_OUTPUT_PUSHPULL); - mySetPadMode("lcd E", getHwPort(boardConfiguration->HD44780_e), getHwPin(boardConfiguration->HD44780_e), PAL_MODE_OUTPUT_PUSHPULL); - mySetPadMode("lcd DB4", getHwPort(boardConfiguration->HD44780_db4), getHwPin(boardConfiguration->HD44780_db4), PAL_MODE_OUTPUT_PUSHPULL); - mySetPadMode("lcd DB6", getHwPort(boardConfiguration->HD44780_db5), getHwPin(boardConfiguration->HD44780_db5), PAL_MODE_OUTPUT_PUSHPULL); - mySetPadMode("lcd DB7", getHwPort(boardConfiguration->HD44780_db6), getHwPin(boardConfiguration->HD44780_db6), PAL_MODE_OUTPUT_PUSHPULL); - mySetPadMode("lcd DB8", getHwPort(boardConfiguration->HD44780_db7), getHwPin(boardConfiguration->HD44780_db7), PAL_MODE_OUTPUT_PUSHPULL); + mySetPadMode("lcd RS", getHwPort(boardConfiguration->HD44780_rs), getHwPin(boardConfiguration->HD44780_rs), + PAL_MODE_OUTPUT_PUSHPULL); + mySetPadMode("lcd E", getHwPort(boardConfiguration->HD44780_e), getHwPin(boardConfiguration->HD44780_e), + PAL_MODE_OUTPUT_PUSHPULL); + mySetPadMode("lcd DB4", getHwPort(boardConfiguration->HD44780_db4), getHwPin(boardConfiguration->HD44780_db4), + PAL_MODE_OUTPUT_PUSHPULL); + mySetPadMode("lcd DB6", getHwPort(boardConfiguration->HD44780_db5), getHwPin(boardConfiguration->HD44780_db5), + PAL_MODE_OUTPUT_PUSHPULL); + mySetPadMode("lcd DB7", getHwPort(boardConfiguration->HD44780_db6), getHwPin(boardConfiguration->HD44780_db6), + PAL_MODE_OUTPUT_PUSHPULL); + mySetPadMode("lcd DB8", getHwPort(boardConfiguration->HD44780_db7), getHwPin(boardConfiguration->HD44780_db7), + PAL_MODE_OUTPUT_PUSHPULL); // and zero values palWritePad(getHwPort(boardConfiguration->HD44780_rs), getHwPin(boardConfiguration->HD44780_rs), 0); palWritePad(getHwPort(boardConfiguration->HD44780_e), getHwPin(boardConfiguration->HD44780_e), 0); @@ -176,7 +200,6 @@ void lcd_HD44780_init(void) { palWritePad(getHwPort(boardConfiguration->HD44780_db7), getHwPin(boardConfiguration->HD44780_db7), 0); } - chThdSleepMilliseconds(20); // LCD needs some time to wake up lcd_HD44780_write(LCD_HD44780_RESET); // reset 1x chThdSleepMilliseconds(1); @@ -202,6 +225,7 @@ void lcd_HD44780_init(void) { lcd_HD44780_write_command(LCD_HD44780_DISPLAY_ON); lcd_HD44780_set_position(0, 0); + printMsg(&logger, "lcd_HD44780_init() done"); } void lcdShowFatalMessage(char *message) { diff --git a/firmware/hw_layer/microsecond_timer.c b/firmware/hw_layer/microsecond_timer.c index 068baac96d..be37efc7a9 100644 --- a/firmware/hw_layer/microsecond_timer.c +++ b/firmware/hw_layer/microsecond_timer.c @@ -5,56 +5,117 @@ * so this timer can schedule events up to 4B/100M ~ 4000 seconds ~ 1 hour from current time. * * @date Apr 14, 2014 - * @author Andrey Belomutskiy, (c) 2012-2013 + * @author Andrey Belomutskiy, (c) 2012-2014 */ #include "main.h" #include "signal_executor.h" #include "microsecond_timer.h" +#include "rfiutil.h" // https://my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Flat.aspx?RootFolder=https%3a%2f%2fmy.st.com%2fpublic%2fSTe2ecommunities%2fmcu%2fLists%2fcortex_mx_stm32%2fInterrupt%20on%20CEN%20bit%20setting%20in%20TIM7&FolderCTID=0x01200200770978C69A1141439FE559EB459D7580009C4E14902C3CDE46A77F0FFD06506F5B¤tviews=474 #if EFI_PROD_CODE -static TIM_TypeDef *TIM = TIM5; +#define GPTDEVICE GPTD5 + +static volatile int64_t lastSetTimerTime; +static int lastSetTimerValue; +static volatile bool_t isTimerPending = FALSE; + +static volatile int timerCallbackCounter = 0; +static volatile int timerRestartCounter = 0; schfunc_t globalTimerCallback; /** - * sets the alarm to the specified number of microseconds from now + * sets the alarm to the specified number of microseconds from now. + * This function should be invoked under kernel lock which would disable interrupts. */ -void setHardwareUsTimer(int timeUs) { - TIM->ARR = timeUs - 1; - TIM->EGR |= TIM_EGR_UG; // generate an update event to reload timer's counter value - TIM->CR1 |= TIM_CR1_CEN; // restart timer +void setHardwareUsTimer(int32_t timeUs) { + if (timeUs == 1) + timeUs = 2; // for some reason '1' does not really work + efiAssert(timeUs > 0, "neg timeUs"); + efiAssert(timeUs < 10 * US_PER_SECOND, "invld time prmtr"); + + if (GPTDEVICE.state == GPT_ONESHOT) + gptStopTimerI(&GPTDEVICE); + gptStartOneShotI(&GPTDEVICE, timeUs); + + lastSetTimerTime = getTimeNowUs(); + lastSetTimerValue = timeUs; + isTimerPending = TRUE; + timerRestartCounter++; } -static void callback(void) { +static void callback(GPTDriver *gptp) { + timerCallbackCounter++; if (globalTimerCallback == NULL) { firmwareError("NULL globalTimerCallback"); return; } + isTimerPending = FALSE; + +// // test code +// setOutputPinValue(LED_CRANKING, timerCallbackCounter % 2); +// int mod = timerCallbackCounter % 400; +// chSysLockFromIsr() +// ; +// setHardwareUsTimer(400 - mod); +// chSysUnlockFromIsr() +// ; + globalTimerCallback(NULL); } -// if you decide to move this to .cpp do not forget to make that a C method -CH_IRQ_HANDLER(STM32_TIM5_HANDLER) { - CH_IRQ_PROLOGUE(); - if (((TIM->SR & 0x0001) != 0) && ((TIM->DIER & 0x0001) != 0)) { - callback(); +static WORKING_AREA(mwThreadStack, UTILITY_THREAD_STACK_SIZE); + +static const char * msg; + +static char buff[12]; + +static msg_t mwThread(int param) { + chRegSetThreadName("timer watchdog"); + + while (TRUE) { + chThdSleepMilliseconds(1000); // once a second is enough + + if (getTimeNowUs() >= lastSetTimerTime + 2 * US_PER_SECOND) { + buff[0] = 'c'; + buff[1] = 'l'; + itoa10(&buff[2], lastSetTimerValue); + fatal(buff); + return -1; + } + + msg = isTimerPending ? "No_cb too long" : "Timer not awhile"; + // 2 seconds of inactivity would not look right + efiAssert(getTimeNowUs() < lastSetTimerTime + 2 * US_PER_SECOND, msg); } - TIM->SR = (int) ~STM32_TIM_SR_UIF; // Interrupt has been handled - CH_IRQ_EPILOGUE(); +#if defined __GNUC__ + return -1; +#endif } -void initMicrosecondTimer(void) { - RCC ->APB1ENR |= RCC_APB1ENR_TIM5EN; // Enable TIM5 clock - nvicEnableVector(TIM5_IRQn, CORTEX_PRIORITY_MASK(12)); - TIM->DIER |= TIM_DIER_UIE; // Enable interrupt on update event - TIM->CR1 |= TIM_CR1_OPM; // one pulse mode: count down ARR and stop - TIM->CR1 &= ~TIM_CR1_ARPE; /* ARR register is NOT buffered, allows to update timer's period on-fly. */ +//static const GPTConfig gpt5cfg; - TIM->PSC = 84 - 1; // 168MHz / 2 / 84 = 1MHz, each tick is a microsecond +static const GPTConfig gpt5cfg = { 1000000, /* 1 MHz timer clock.*/ +callback, /* Timer callback.*/ +0 }; + +void initMicrosecondTimer(void) { + + gptStart(&GPTDEVICE, &gpt5cfg); + + lastSetTimerTime = getTimeNowUs(); + chThdCreateStatic(mwThreadStack, sizeof(mwThreadStack), NORMALPRIO, (tfunc_t) mwThread, NULL); + +// // test code +// chSysLock() +// ; +// setHardwareUsTimer(300); +// chSysUnlock() +// ; } #endif /* EFI_PROD_CODE */ diff --git a/firmware/hw_layer/microsecond_timer.h b/firmware/hw_layer/microsecond_timer.h index 3f2893583f..ab226d5e3b 100644 --- a/firmware/hw_layer/microsecond_timer.h +++ b/firmware/hw_layer/microsecond_timer.h @@ -2,7 +2,7 @@ * @file microsecond_timer.h * * @date Apr 14, 2014 - * @author Andrey Belomutskiy, (c) 2012-2013 + * @author Andrey Belomutskiy, (c) 2012-2014 */ #ifndef SIGNAL_TEMP_H_ @@ -14,7 +14,7 @@ extern "C" #endif /* __cplusplus */ void initMicrosecondTimer(void); -void setHardwareUsTimer(int timeUs); +void setHardwareUsTimer(int32_t timeUs); #ifdef __cplusplus } diff --git a/firmware/hw_layer/mmc_card.c b/firmware/hw_layer/mmc_card.c index 2f2e661bee..6cc4eece30 100644 --- a/firmware/hw_layer/mmc_card.c +++ b/firmware/hw_layer/mmc_card.c @@ -11,14 +11,14 @@ */ #include "main.h" -#include "mmc_card.h" -#include "eficonsole_logic.h" -#include "pin_repository.h" #if EFI_FILE_LOGGING #include #include +#include "mmc_card.h" +#include "pin_repository.h" +#include "ff.h" #define PUSHPULLDELAY 500 diff --git a/firmware/hw_layer/mmc_card.h b/firmware/hw_layer/mmc_card.h index 830c117fdf..f9c310a2ef 100644 --- a/firmware/hw_layer/mmc_card.h +++ b/firmware/hw_layer/mmc_card.h @@ -10,8 +10,6 @@ #ifndef MMC_CARD_H_ #define MMC_CARD_H_ -#include "ff.h" - #ifdef __cplusplus extern "C" { diff --git a/firmware/hw_layer/neo6m.c b/firmware/hw_layer/neo6m.c index 9f7e3f516b..12c5d00bac 100644 --- a/firmware/hw_layer/neo6m.c +++ b/firmware/hw_layer/neo6m.c @@ -13,6 +13,9 @@ #include #include "main.h" + +#if EFI_UART_GPS + #include "console_io.h" #include "eficonsole.h" #include "pin_repository.h" @@ -20,8 +23,6 @@ #include "neo6m.h" #include "rtc_helper.h" -#if EFI_UART_GPS - static Logging logging; static SerialConfig GPSserialConfig = { GPS_SERIAL_SPEED, 0, USART_CR2_STOP1_BITS | USART_CR2_LINEN, 0 }; diff --git a/firmware/hw_layer/pin_repository.c b/firmware/hw_layer/pin_repository.c index 150816d9b0..bdfd5c0e04 100644 --- a/firmware/hw_layer/pin_repository.c +++ b/firmware/hw_layer/pin_repository.c @@ -12,7 +12,6 @@ #include "main.h" #include "pin_repository.h" #include "eficonsole.h" -#include "eficonsole_logic.h" #include "memstreams.h" #include "chprintf.h" #include "rusefi.h" @@ -108,8 +107,10 @@ static inline void markUsed(int index, const char *msg) { * This method would set an error condition if pin is already used */ void mySetPadMode(const char *msg, ioportid_t port, ioportmask_t pin, iomode_t mode) { - if (!initialized) - fatal("repo not initialized"); + if (!initialized) { + firmwareError("repository not initialized"); + return; + } print("%s on %s:%d\r\n", msg, portname(port), pin); appendPrintf(&logger, "msg,%s", msg); @@ -121,9 +122,6 @@ void mySetPadMode(const char *msg, ioportid_t port, ioportmask_t pin, iomode_t m if (PIN_USED[index] != NULL) { firmwareError("Pin %s%d requested by %s but already used by %s", portname(port), pin, msg, PIN_USED[index]); -// print("!!!!!!!!!!!!! Already used [%s] %d\r\n", msg, pin); -// print("!!!!!!!!!!!!! Already used by [%s]\r\n", PIN_USED[index]); -// fatal("pin already used"); return; } markUsed(index, msg); diff --git a/firmware/hw_layer/rtc_helper.c b/firmware/hw_layer/rtc_helper.c index c39fca4b6d..e067a213c9 100644 --- a/firmware/hw_layer/rtc_helper.c +++ b/firmware/hw_layer/rtc_helper.c @@ -23,14 +23,19 @@ static void date_help(void) { } void date_set_tm(struct tm *timp) { +#if EFI_RTC rtcSetTimeTm(&RTCD1, timp); +#endif /* EFI_RTC */ } void date_get_tm(struct tm *timp) { +#if EFI_RTC rtcGetTimeTm(&RTCD1, timp); +#endif /* EFI_RTC */ } void dateToString(char *lcd_str) { +#if EFI_RTC // todo: // re-implement this along the lines of chvprintf("%04u-%02u-%02u %02u:%02u:%02u\r\n", timp.tm_year + 1900, timp.tm_mon + 1, timp.tm_mday, timp.tm_hour, // timp.tm_min, timp.tm_sec); @@ -81,9 +86,13 @@ void dateToString(char *lcd_str) { lcd_str[12] = buff[0]; lcd_str[13] = buff[1]; } +#else + lcd_str[0] = 0; +#endif /* EFI_RTC */ } static void date_get(void) { +#if EFI_RTC static time_t unix_time; struct tm timp; @@ -100,9 +109,11 @@ static void date_get(void) { appendMsgPostfix(&logger); scheduleLogging(&logger); } +#endif } static void date_set(char *strDate) { +#if EFI_RTC if (strlen(strDate) > 0) { time_t unix_time = (double) atoff(strDate); if (unix_time > 0) { @@ -112,13 +123,18 @@ static void date_set(char *strDate) { } } scheduleMsg(&logger, "date_set Date parameter %s is wrong\r\n", strDate); +#endif } void initRtc(void) { initLogging(&logger, "rtc"); +#if EFI_RTC + printMsg(&logger, "initRtc()"); + // yes, it's my begin time and we always start from this one 1391894433 - 2014-02-08 21:20:03 rtcSetTimeUnixSec(&RTCD1, 1391894433); addConsoleAction("date_get", date_get); addConsoleActionS("date_set", date_set); addConsoleAction("date_help", date_help); +#endif } diff --git a/firmware/hw_layer/serial_over_usb/usbconsole.c b/firmware/hw_layer/serial_over_usb/usbconsole.c index af3f93b103..a2ab61f6be 100644 --- a/firmware/hw_layer/serial_over_usb/usbconsole.c +++ b/firmware/hw_layer/serial_over_usb/usbconsole.c @@ -51,7 +51,7 @@ int is_usb_serial_ready(void) { #endif #if EFI_SERIAL_OVER_USB -int is_serial_ready(void) { +int isConsoleReady(void) { return is_usb_serial_ready(); } #endif diff --git a/firmware/hw_layer/trigger_input.cpp b/firmware/hw_layer/trigger_input.cpp index 1563fbab13..493344f982 100644 --- a/firmware/hw_layer/trigger_input.cpp +++ b/firmware/hw_layer/trigger_input.cpp @@ -6,27 +6,39 @@ * @author Andrey Belomutskiy, (c) 2012-2014 */ -#include "trigger_input.h" +#include "main.h" +#if EFI_SHAFT_POSITION_INPUT + +#include "trigger_input.h" #include "wave_analyzer_hw.h" #include "pin_repository.h" #include "trigger_structure.h" #include "trigger_central.h" #include "engine_configuration.h" +#include "wave_analyzer_hw.h" static WaveReaderHw primaryCrankInput; static WaveReaderHw secondaryCrankInput; extern engine_configuration_s *engineConfiguration; +extern board_configuration_s *boardConfiguration; -#if EFI_SHAFT_POSITION_INPUT + +static inline ICUDriver *getPrimaryInputCaptureDriver(void) { + return getInputCaptureDriver(boardConfiguration->primaryTriggerInputPin); +} + +static inline ICUDriver *getSecondaryInputCaptureDriver(void) { + return getInputCaptureDriver(boardConfiguration->secondaryTriggerInputPin); +} /** * that's hardware timer input capture IRQ entry point * 'width' events happens before the 'period' event */ static void shaft_icu_width_callback(ICUDriver *icup) { - int isPrimary = icup == &PRIMARY_SHAFT_POSITION_INPUT_DRIVER; + int isPrimary = icup == getPrimaryInputCaptureDriver(); if (!isPrimary && !engineConfiguration->needSecondTriggerInput) return; // icucnt_t last_width = icuGetWidth(icup); so far we are fine with system time @@ -36,7 +48,7 @@ static void shaft_icu_width_callback(ICUDriver *icup) { } static void shaft_icu_period_callback(ICUDriver *icup) { - int isPrimary = icup == &PRIMARY_SHAFT_POSITION_INPUT_DRIVER; + int isPrimary = icup == getPrimaryInputCaptureDriver(); if (!isPrimary && !engineConfiguration->needSecondTriggerInput) return; @@ -50,36 +62,35 @@ static void shaft_icu_period_callback(ICUDriver *icup) { */ static ICUConfig shaft_icucfg = { ICU_INPUT_ACTIVE_LOW, 100000, /* 100kHz ICU clock frequency. */ shaft_icu_width_callback, shaft_icu_period_callback }; -#endif void initShaftPositionInputCapture(void) { -#if EFI_SHAFT_POSITION_INPUT // initialize primary Input Capture Unit pin - initWaveAnalyzerDriver(&primaryCrankInput, &PRIMARY_SHAFT_POSITION_INPUT_DRIVER, PRIMARY_SHAFT_POSITION_INPUT_PORT, - PRIMARY_SHAFT_POSITION_INPUT_PIN); + initWaveAnalyzerDriver(&primaryCrankInput, getPrimaryInputCaptureDriver(), + getHwPort(boardConfiguration->primaryTriggerInputPin), + getHwPin(boardConfiguration->primaryTriggerInputPin)); /** * Start primary Input Capture Unit using given configuration * @see shaft_icucfg for callback entry points */ - shaft_icucfg.channel = PRIMARY_SHAFT_POSITION_INPUT_CHANNEL; - print("initShaftPositionInputCapture 1 %s:%d\r\n", portname(PRIMARY_SHAFT_POSITION_INPUT_PORT), - PRIMARY_SHAFT_POSITION_INPUT_PIN); - icuStart(&PRIMARY_SHAFT_POSITION_INPUT_DRIVER, &shaft_icucfg); - icuEnable(&PRIMARY_SHAFT_POSITION_INPUT_DRIVER); + shaft_icucfg.channel = ICU_CHANNEL_1; + print("initShaftPositionInputCapture 1 %s:%d\r\n", portname(getHwPort(boardConfiguration->primaryTriggerInputPin)), + getHwPin(boardConfiguration->primaryTriggerInputPin)); + icuStart(getPrimaryInputCaptureDriver(), &shaft_icucfg); + icuEnable(getPrimaryInputCaptureDriver()); // initialize secondary Input Capture Unit pin - initWaveAnalyzerDriver(&secondaryCrankInput, &SECONDARY_SHAFT_POSITION_INPUT_DRIVER, - SECONDARY_SHAFT_POSITION_INPUT_PORT, - SECONDARY_SHAFT_POSITION_INPUT_PIN); - shaft_icucfg.channel = SECONDARY_SHAFT_POSITION_INPUT_CHANNEL; - print("initShaftPositionInputCapture 2 %s:%d\r\n", portname(SECONDARY_SHAFT_POSITION_INPUT_PORT), - SECONDARY_SHAFT_POSITION_INPUT_PIN); - icuStart(&SECONDARY_SHAFT_POSITION_INPUT_DRIVER, &shaft_icucfg); - icuEnable(&SECONDARY_SHAFT_POSITION_INPUT_DRIVER); + initWaveAnalyzerDriver(&secondaryCrankInput, getSecondaryInputCaptureDriver(), + getHwPort(boardConfiguration->secondaryTriggerInputPin), + getHwPin(boardConfiguration->secondaryTriggerInputPin)); + shaft_icucfg.channel = ICU_CHANNEL_1; + print("initShaftPositionInputCapture 2 %s:%d\r\n", portname(getHwPort(boardConfiguration->secondaryTriggerInputPin)), + getHwPin(boardConfiguration->secondaryTriggerInputPin)); + icuStart(getSecondaryInputCaptureDriver(), &shaft_icucfg); + icuEnable(getSecondaryInputCaptureDriver()); -#else print("crank input disabled\r\n"); -#endif } + +#endif /* EFI_SHAFT_POSITION_INPUT */ diff --git a/firmware/hw_layer/wave_analyzer_hw.c b/firmware/hw_layer/wave_analyzer_hw.c index 626374c445..4b94fd2802 100644 --- a/firmware/hw_layer/wave_analyzer_hw.c +++ b/firmware/hw_layer/wave_analyzer_hw.c @@ -18,8 +18,7 @@ static void icuPeriordCallBack(ICUDriver *driver); * CORE_CLOCK / 33.33333 = TICKS * 65536 * 168000000 / 33.333333 / 65536 = 76.90 */ -static ICUConfig wave_icucfg = { ICU_INPUT_ACTIVE_LOW, CORE_CLOCK / 100, - icuWidthCallback, icuPeriordCallBack }; +static ICUConfig wave_icucfg = { ICU_INPUT_ACTIVE_LOW, CORE_CLOCK / 100, icuWidthCallback, icuPeriordCallBack }; static int registeredIcuCount = 0; static WaveReaderHw* registeredIcus[8]; @@ -35,24 +34,28 @@ static WaveReaderHw * findWaveReaderHw(ICUDriver *driver) { static void icuWidthCallback(ICUDriver *driver) { /* * see comment in icuPeriordCallBack - int rowWidth = icuGetWidth(driver); - */ + int rowWidth = icuGetWidth(driver); + */ WaveReaderHw * hw = findWaveReaderHw(driver); invokeJustArgCallbacks(&hw->widthListeners); } static void icuPeriordCallBack(ICUDriver *driver) { -/* - * we do not use timer period at all - we just need the event. For all time characteristics, - * we use system time - * int period = icuGetPeriod(driver); - */ + /* + * we do not use timer period at all - we just need the event. For all time characteristics, + * we use system time + * int period = icuGetPeriod(driver); + */ WaveReaderHw * hw = findWaveReaderHw(driver); invokeJustArgCallbacks(&hw->periodListeners); } static int getAlternateFunctions(ICUDriver *driver) { + if (driver == NULL) { + firmwareError("getAlternateFunctions(NULL)"); + return -1; + } #if STM32_ICU_USE_TIM1 if (driver == &ICUD1) return GPIO_AF_TIM1; @@ -71,14 +74,34 @@ static int getAlternateFunctions(ICUDriver *driver) { #endif #if STM32_ICU_USE_TIM9 if (driver == &ICUD9) - return GPIO_AF_TIM9; + return GPIO_AF_TIM9; #endif fatal("No such driver"); return -1; } -void initWaveAnalyzerDriver(WaveReaderHw *hw, ICUDriver *driver, - ioportid_t port, int pin) { +ICUDriver * getInputCaptureDriver(brain_pin_e hwPin) { +#if STM32_ICU_USE_TIM1 + if (hwPin == GPIOA_8) + return &ICUD1; +#endif +#if STM32_ICU_USE_TIM2 + if (hwPin == GPIOA_5) + return &ICUD2; +#endif +#if STM32_ICU_USE_TIM3 + if (hwPin == GPIOC_6) + return &ICUD3; +#endif +#if STM32_ICU_USE_TIM9 + if (hwPin == GPIOE_7) + return &ICUD9; +#endif + + return NULL; +} + +void initWaveAnalyzerDriver(WaveReaderHw *hw, ICUDriver *driver, ioportid_t port, int pin) { hw->driver = driver; hw->port = port; hw->pin = pin; diff --git a/firmware/hw_layer/wave_analyzer_hw.h b/firmware/hw_layer/wave_analyzer_hw.h index 7e9bb4b6e8..f559d01b72 100644 --- a/firmware/hw_layer/wave_analyzer_hw.h +++ b/firmware/hw_layer/wave_analyzer_hw.h @@ -30,6 +30,7 @@ extern "C" void initWaveAnalyzerDriver(WaveReaderHw *hw, ICUDriver *driver, ioportid_t port, int pin); void setWaveReaderMode(WaveReaderHw *hw, int mode); +ICUDriver * getInputCaptureDriver(brain_pin_e hwPin); #ifdef __cplusplus } diff --git a/firmware/iar/ch.ewp b/firmware/iar/ch.ewp index 4465960817..eb0257c0ec 100644 --- a/firmware/iar/ch.ewp +++ b/firmware/iar/ch.ewp @@ -39,20 +39,20 @@ - @@ -590,8 +586,9 @@ - - @@ -1415,7 +1429,7 @@ - - - chibios - - boards - - ST_STM32F4_DISCOVERY - - $PROJ_DIR$\..\chibios\boards\ST_STM32F4_DISCOVERY\board.c - - - $PROJ_DIR$\..\chibios\boards\ST_STM32F4_DISCOVERY\board.h - - - - - ext - - fatfs - - src - - option - - $PROJ_DIR$\..\chibios\ext\fatfs\src\option\ccsbcs.c - - - - $PROJ_DIR$\..\chibios\ext\fatfs\src\ff.c - - - - - config @@ -1930,52 +1913,94 @@ engines - $PROJ_DIR$\..\config\engines\audi_aan.c + $PROJ_DIR$\..\config\engines\audi_aan.cpp $PROJ_DIR$\..\config\engines\audi_aan.h - $PROJ_DIR$\..\config\engines\dodge_neon.c + $PROJ_DIR$\..\config\engines\citroenBerlingoTU3JP.cpp + + + $PROJ_DIR$\..\config\engines\citroenBerlingoTU3JP.h + + + $PROJ_DIR$\..\config\engines\dodge_neon.cpp $PROJ_DIR$\..\config\engines\dodge_neon.h - $PROJ_DIR$\..\config\engines\engine.h + $PROJ_DIR$\..\config\engines\engines.h - $PROJ_DIR$\..\config\engines\ford_1995_inline_6.c + $PROJ_DIR$\..\config\engines\ford_1995_inline_6.cpp $PROJ_DIR$\..\config\engines\ford_1995_inline_6.h - $PROJ_DIR$\..\config\engines\ford_aspire.c + $PROJ_DIR$\..\config\engines\ford_aspire.cpp $PROJ_DIR$\..\config\engines\ford_aspire.h - $PROJ_DIR$\..\config\engines\ford_fiesta.c + $PROJ_DIR$\..\config\engines\ford_escort_gt.cpp + + + $PROJ_DIR$\..\config\engines\ford_escort_gt.h + + + $PROJ_DIR$\..\config\engines\ford_fiesta.cpp $PROJ_DIR$\..\config\engines\ford_fiesta.h - $PROJ_DIR$\..\config\engines\honda_accord.c + $PROJ_DIR$\..\config\engines\GY6_139QMB.cpp + + + $PROJ_DIR$\..\config\engines\GY6_139QMB.h + + + $PROJ_DIR$\..\config\engines\honda_accord.cpp $PROJ_DIR$\..\config\engines\honda_accord.h - $PROJ_DIR$\..\config\engines\nissan_primera.c + $PROJ_DIR$\..\config\engines\mazda_323.cpp + + + $PROJ_DIR$\..\config\engines\mazda_323.h + + + $PROJ_DIR$\..\config\engines\mazda_miata_nb.cpp + + + $PROJ_DIR$\..\config\engines\mazda_miata_nb.h + + + $PROJ_DIR$\..\config\engines\MiniCooperR50.cpp + + + $PROJ_DIR$\..\config\engines\MiniCooperR50.h + + + $PROJ_DIR$\..\config\engines\nissan_primera.cpp $PROJ_DIR$\..\config\engines\nissan_primera.h - $PROJ_DIR$\..\config\engines\snow_blower.c + $PROJ_DIR$\..\config\engines\saturn_ion.cpp + + + $PROJ_DIR$\..\config\engines\saturn_ion.h + + + $PROJ_DIR$\..\config\engines\snow_blower.cpp $PROJ_DIR$\..\config\engines\snow_blower.h @@ -1993,16 +2018,28 @@ $PROJ_DIR$\..\config\system\mcuconf.h + + $PROJ_DIR$\..\config\efifeatures.h + console - algo + tunerstudio - $PROJ_DIR$\..\console\algo\tunerstudio_algo.c + $PROJ_DIR$\..\console\tunerstudio\tunerstudio.c - $PROJ_DIR$\..\console\algo\tunerstudio_algo.h + $PROJ_DIR$\..\console\tunerstudio\tunerstudio.h + + + $PROJ_DIR$\..\console\tunerstudio\tunerstudio_algo.c + + + $PROJ_DIR$\..\console\tunerstudio\tunerstudio_algo.h + + + $PROJ_DIR$\..\console\tunerstudio\tunerstudio_configuration.h @@ -2012,35 +2049,17 @@ $PROJ_DIR$\..\console\console_io.h - $PROJ_DIR$\..\console\rficonsole.c + $PROJ_DIR$\..\console\eficonsole.c - $PROJ_DIR$\..\console\rficonsole.h + $PROJ_DIR$\..\console\eficonsole.h - $PROJ_DIR$\..\console\status_loop.c + $PROJ_DIR$\..\console\status_loop.cpp $PROJ_DIR$\..\console\status_loop.h - - $PROJ_DIR$\..\console\tunerstudio.c - - - $PROJ_DIR$\..\console\tunerstudio.h - - - $PROJ_DIR$\..\console\usbcfg.c - - - $PROJ_DIR$\..\console\usbcfg.h - - - $PROJ_DIR$\..\console\usbconsole.c - - - $PROJ_DIR$\..\console\usbconsole.h - console_util @@ -2050,12 +2069,6 @@ $PROJ_DIR$\..\console_util\datalogging.h - - $PROJ_DIR$\..\util\rficonsole_logic.c - - - $PROJ_DIR$\..\util\rficonsole_logic.h - $PROJ_DIR$\..\console_util\rfiutil.c @@ -2067,6 +2080,12 @@ controllers algo + + $PROJ_DIR$\..\controllers\algo\accel_enrichment.cpp + + + $PROJ_DIR$\..\controllers\algo\accel_enrichment.h + $PROJ_DIR$\..\controllers\algo\advance_map.c @@ -2074,11 +2093,29 @@ $PROJ_DIR$\..\controllers\algo\advance_map.h - $PROJ_DIR$\..\controllers\algo\engine_configuration.c + $PROJ_DIR$\..\controllers\algo\algo.cpp + + + $PROJ_DIR$\..\controllers\algo\algo.h + + + $PROJ_DIR$\..\controllers\algo\can_header.h + + + $PROJ_DIR$\..\controllers\algo\ec2.h + + + $PROJ_DIR$\..\controllers\algo\engine_configuration.cpp $PROJ_DIR$\..\controllers\algo\engine_configuration.h + + $PROJ_DIR$\..\controllers\algo\engine_state.h + + + $PROJ_DIR$\..\controllers\algo\error_handling.h + $PROJ_DIR$\..\controllers\algo\event_registry.c @@ -2086,7 +2123,7 @@ $PROJ_DIR$\..\controllers\algo\event_registry.h - $PROJ_DIR$\..\controllers\algo\fuel_math.c + $PROJ_DIR$\..\controllers\algo\fuel_math.cpp $PROJ_DIR$\..\controllers\algo\fuel_math.h @@ -2097,15 +2134,12 @@ $PROJ_DIR$\..\controllers\algo\idle_controller.h - - $PROJ_DIR$\..\controllers\algo\interpolation.c - - - $PROJ_DIR$\..\controllers\algo\interpolation.h - $PROJ_DIR$\..\controllers\algo\io_pins.h + + $PROJ_DIR$\..\controllers\algo\main_trigger_callback.h + $PROJ_DIR$\..\controllers\algo\malfunction_central.c @@ -2113,10 +2147,19 @@ $PROJ_DIR$\..\controllers\algo\malfunction_central.h - $PROJ_DIR$\..\controllers\algo\map_adjuster.c + $PROJ_DIR$\..\controllers\algo\nmea.c - $PROJ_DIR$\..\controllers\algo\map_adjuster.h + $PROJ_DIR$\..\controllers\algo\nmea.h + + + $PROJ_DIR$\..\controllers\algo\obd_error_codes.h + + + $PROJ_DIR$\..\controllers\algo\OutputSignalArray.cpp + + + $PROJ_DIR$\..\controllers\algo\OutputSignalList.h $PROJ_DIR$\..\controllers\algo\rusefi_enums.h @@ -2125,44 +2168,41 @@ $PROJ_DIR$\..\controllers\algo\signal_executor.c - $PROJ_DIR$\..\controllers\algo\signal_executor_single_timer_algo.c + $PROJ_DIR$\..\controllers\algo\signal_executor.h - $PROJ_DIR$\..\controllers\algo\signal_executor_single_timer_algo.h + $PROJ_DIR$\..\controllers\algo\wave_chart.c - $PROJ_DIR$\..\controllers\algo\trigger_decoder.c + $PROJ_DIR$\..\controllers\algo\wave_chart.h + + + + core + + $PROJ_DIR$\..\controllers\core\EfiWave.cpp - $PROJ_DIR$\..\controllers\algo\trigger_decoder.h + $PROJ_DIR$\..\controllers\core\EfiWave.h - $PROJ_DIR$\..\controllers\algo\trigger_structure.c + $PROJ_DIR$\..\controllers\core\interpolation.c - $PROJ_DIR$\..\controllers\algo\trigger_structure.h + $PROJ_DIR$\..\controllers\core\interpolation.h math - $PROJ_DIR$\..\controllers\math\avg_values.c + $PROJ_DIR$\..\controllers\math\efitime.h - $PROJ_DIR$\..\controllers\math\avg_values.h - - - $PROJ_DIR$\..\controllers\math\engine_math.c + $PROJ_DIR$\..\controllers\math\engine_math.cpp $PROJ_DIR$\..\controllers\math\engine_math.h - - $PROJ_DIR$\..\controllers\math\signal_filtering.c - - - $PROJ_DIR$\..\controllers\math\signal_filtering.h - sensors @@ -2191,10 +2231,10 @@ $PROJ_DIR$\..\controllers\sensors\map.h - $PROJ_DIR$\..\controllers\sensors\sensors.h + $PROJ_DIR$\..\controllers\sensors\sensor_types.h - $PROJ_DIR$\..\controllers\sensors\thermistors.c + $PROJ_DIR$\..\controllers\sensors\thermistors.cpp $PROJ_DIR$\..\controllers\sensors\thermistors.h @@ -2215,16 +2255,19 @@ system - $PROJ_DIR$\..\controllers\system\signal_executor_hw_timer.c + $PROJ_DIR$\..\controllers\system\event_queue.cpp - $PROJ_DIR$\..\controllers\system\signal_executor_hw_timer.h + $PROJ_DIR$\..\controllers\system\event_queue.h - $PROJ_DIR$\..\controllers\system\signal_executor_single_timer.c + $PROJ_DIR$\..\controllers\system\pwm_generator_logic.cpp - $PROJ_DIR$\..\controllers\system\signal_executor_single_timer.h + $PROJ_DIR$\..\controllers\system\pwm_generator_logic.h + + + $PROJ_DIR$\..\controllers\system\scheduler.h $PROJ_DIR$\..\controllers\system\signal_executor_sleep.c @@ -2232,27 +2275,102 @@ $PROJ_DIR$\..\controllers\system\signal_executor_sleep.h + + $PROJ_DIR$\..\controllers\system\SingleTimerExecutor.cpp + + + $PROJ_DIR$\..\controllers\system\SingleTimerExecutor.h + + + + trigger + + $PROJ_DIR$\..\controllers\trigger\main_trigger_callback.cpp + + + $PROJ_DIR$\..\controllers\trigger\rpm_calculator.cpp + + + $PROJ_DIR$\..\controllers\trigger\rpm_calculator.h + + + $PROJ_DIR$\..\controllers\trigger\trigger_bmw.cpp + + + $PROJ_DIR$\..\controllers\trigger\trigger_bmw.h + + + $PROJ_DIR$\..\controllers\trigger\trigger_central.cpp + + + $PROJ_DIR$\..\controllers\trigger\trigger_central.h + + + $PROJ_DIR$\..\controllers\trigger\trigger_chrysler.cpp + + + $PROJ_DIR$\..\controllers\trigger\trigger_chrysler.h + + + $PROJ_DIR$\..\controllers\trigger\trigger_decoder.cpp + + + $PROJ_DIR$\..\controllers\trigger\trigger_decoder.h + + + $PROJ_DIR$\..\controllers\trigger\trigger_emulator_algo.cpp + + + $PROJ_DIR$\..\controllers\trigger\trigger_emulator_algo.h + + + $PROJ_DIR$\..\controllers\trigger\trigger_gm.cpp + + + $PROJ_DIR$\..\controllers\trigger\trigger_gm.h + + + $PROJ_DIR$\..\controllers\trigger\trigger_mazda.cpp + + + $PROJ_DIR$\..\controllers\trigger\trigger_mazda.h + + + $PROJ_DIR$\..\controllers\trigger\trigger_structure.cpp + + + $PROJ_DIR$\..\controllers\trigger\trigger_structure.h + - $PROJ_DIR$\..\controllers\electronic_throttle.c + $PROJ_DIR$\..\controllers\alternatorController.cpp + + + $PROJ_DIR$\..\controllers\alternatorController.h + + + $PROJ_DIR$\..\controllers\electronic_throttle.cpp $PROJ_DIR$\..\controllers\electronic_throttle.h - $PROJ_DIR$\..\controllers\engine_controller.c + $PROJ_DIR$\..\controllers\engine_controller.cpp $PROJ_DIR$\..\controllers\engine_controller.h - $PROJ_DIR$\..\controllers\flash_main.c + $PROJ_DIR$\..\controllers\error_handling.c + + + $PROJ_DIR$\..\controllers\flash_main.cpp $PROJ_DIR$\..\controllers\flash_main.h - $PROJ_DIR$\..\controllers\idle_thread.c + $PROJ_DIR$\..\controllers\idle_thread.cpp $PROJ_DIR$\..\controllers\idle_thread.h @@ -2264,17 +2382,11 @@ $PROJ_DIR$\..\controllers\ignition_central.h - $PROJ_DIR$\..\controllers\injector_central.c + $PROJ_DIR$\..\controllers\injector_central.cpp $PROJ_DIR$\..\controllers\injector_central.h - - $PROJ_DIR$\..\controllers\main_trigger_callback.c - - - $PROJ_DIR$\..\controllers\main_trigger_callback.h - $PROJ_DIR$\..\controllers\malfunction_indicator.c @@ -2294,31 +2406,25 @@ $PROJ_DIR$\..\controllers\map_multiplier_thread.h - $PROJ_DIR$\..\controllers\rpm_calculator.c + $PROJ_DIR$\..\controllers\obd2viaCAN.c - $PROJ_DIR$\..\controllers\rpm_calculator.h + $PROJ_DIR$\..\controllers\PwmTester.cpp - $PROJ_DIR$\..\controllers\settings.c + $PROJ_DIR$\..\controllers\PwmTester.h + + + $PROJ_DIR$\..\controllers\settings.cpp $PROJ_DIR$\..\controllers\settings.h - - $PROJ_DIR$\..\controllers\signal_executor.h - emulation hw_layer - - $PROJ_DIR$\..\emulation\hw_layer\poten.c - - - $PROJ_DIR$\..\emulation\hw_layer\poten.h - $PROJ_DIR$\..\emulation\analog_chart.c @@ -2327,25 +2433,19 @@ $PROJ_DIR$\..\emulation\analog_chart.h - $PROJ_DIR$\..\emulation\engine_emulator.c + $PROJ_DIR$\..\emulation\engine_emulator.cpp $PROJ_DIR$\..\emulation\engine_emulator.h - $PROJ_DIR$\..\emulation\rfi_perftest.c + $PROJ_DIR$\..\emulation\rfi_perftest.cpp $PROJ_DIR$\..\emulation\rfi_perftest.h - $PROJ_DIR$\..\emulation\toothed_wheel_emulator.c - - - $PROJ_DIR$\..\emulation\toothed_wheel_emulator.h - - - $PROJ_DIR$\..\emulation\trigger_emulator.c + $PROJ_DIR$\..\emulation\trigger_emulator.cpp $PROJ_DIR$\..\emulation\trigger_emulator.h @@ -2356,18 +2456,18 @@ $PROJ_DIR$\..\emulation\wave_analyzer.h - - $PROJ_DIR$\..\emulation\wave_chart.c - - - $PROJ_DIR$\..\emulation\wave_chart.h - ext + + $PROJ_DIR$\..\chibios\ext\fatfs\src\option\ccsbcs.c + $PROJ_DIR$\..\ext\diskio.h + + $PROJ_DIR$\..\chibios\ext\fatfs\src\ff.c + $PROJ_DIR$\..\ext\ff.h @@ -2378,32 +2478,56 @@ $PROJ_DIR$\..\ext\integer.h - - ext_algo - - $PROJ_DIR$\..\ext_algo\utlist.h - - hw_layer + + algo + + $PROJ_DIR$\..\hw_layer\algo\adc_math.h + + lcd - $PROJ_DIR$\..\hw_layer\lcd\lcd_2x16.c + $PROJ_DIR$\..\hw_layer\lcd\lcd_HD44780.c - $PROJ_DIR$\..\hw_layer\lcd\lcd_2x16.h + $PROJ_DIR$\..\hw_layer\lcd\lcd_HD44780.h + + + + serial_over_usb + + $PROJ_DIR$\..\hw_layer\serial_over_usb\usbcfg.c + + + $PROJ_DIR$\..\hw_layer\serial_over_usb\usbcfg.h + + + $PROJ_DIR$\..\hw_layer\serial_over_usb\usbconsole.c + + + $PROJ_DIR$\..\hw_layer\serial_over_usb\usbconsole.h $PROJ_DIR$\..\hw_layer\adc_external.h - $PROJ_DIR$\..\hw_layer\adc_inputs.c + $PROJ_DIR$\..\hw_layer\adc_inputs.cpp $PROJ_DIR$\..\hw_layer\adc_inputs.h + + $PROJ_DIR$\..\hw_layer\AdcConfiguration.h + + + $PROJ_DIR$\..\hw_layer\board_test.cpp + + + $PROJ_DIR$\..\hw_layer\board_test.h + $PROJ_DIR$\..\hw_layer\can_hw.c @@ -2423,7 +2547,7 @@ $PROJ_DIR$\..\hw_layer\gpio_helper.h - $PROJ_DIR$\..\hw_layer\hardware.c + $PROJ_DIR$\..\hw_layer\hardware.cpp $PROJ_DIR$\..\hw_layer\hardware.h @@ -2443,12 +2567,24 @@ $PROJ_DIR$\..\hw_layer\mcp3208.h + + $PROJ_DIR$\..\hw_layer\microsecond_timer.c + + + $PROJ_DIR$\..\hw_layer\microsecond_timer.h + $PROJ_DIR$\..\hw_layer\mmc_card.c $PROJ_DIR$\..\hw_layer\mmc_card.h + + $PROJ_DIR$\..\hw_layer\neo6m.c + + + $PROJ_DIR$\..\hw_layer\neo6m.h + $PROJ_DIR$\..\hw_layer\pin_repository.c @@ -2456,7 +2592,7 @@ $PROJ_DIR$\..\hw_layer\pin_repository.h - $PROJ_DIR$\..\hw_layer\pwm_generator.c + $PROJ_DIR$\..\hw_layer\pwm_generator.cpp $PROJ_DIR$\..\hw_layer\pwm_generator.h @@ -2471,7 +2607,7 @@ $PROJ_DIR$\..\hw_layer\stm32f4xx_specific.h - $PROJ_DIR$\..\hw_layer\trigger_input.c + $PROJ_DIR$\..\hw_layer\trigger_input.cpp $PROJ_DIR$\..\hw_layer\trigger_input.h @@ -2485,6 +2621,15 @@ os + + board + + $PROJ_DIR$\..\chibios\boards\ST_STM32F4_DISCOVERY\board.c + + + $PROJ_DIR$\..\chibios\boards\ST_STM32F4_DISCOVERY\board.h + + hal @@ -2501,9 +2646,6 @@ $PROJ_DIR$\..\chibios\os\hal\include\gpt.h - - $PROJ_DIR$\..\chibios\os\hal\platforms\STM32\TIMv1\gpt_lld.h - $PROJ_DIR$\..\chibios\os\hal\include\hal.h @@ -2513,9 +2655,6 @@ $PROJ_DIR$\..\chibios\os\hal\include\icu.h - - $PROJ_DIR$\..\chibios\os\hal\platforms\STM32\TIMv1\icu_lld.h - $PROJ_DIR$\..\chibios\os\hal\include\mac.h @@ -2546,12 +2685,6 @@ $PROJ_DIR$\..\chibios\os\hal\include\spi.h - - $PROJ_DIR$\..\chibios\os\hal\platforms\STM32\OTGv1\stm32_otg.h - - - $PROJ_DIR$\..\chibios\os\hal\platforms\STM32\TIMv1\stm32_tim.h - $PROJ_DIR$\..\chibios\os\hal\include\uart.h @@ -2561,9 +2694,6 @@ $PROJ_DIR$\..\chibios\os\hal\include\usb_cdc.h - - $PROJ_DIR$\..\chibios\os\hal\platforms\STM32\OTGv1\usb_lld.h - src @@ -2579,9 +2709,6 @@ $PROJ_DIR$\..\chibios\os\hal\src\gpt.c - - $PROJ_DIR$\..\chibios\os\hal\platforms\STM32\TIMv1\gpt_lld.c - $PROJ_DIR$\..\chibios\os\hal\src\hal.c @@ -2591,9 +2718,6 @@ $PROJ_DIR$\..\chibios\os\hal\src\icu.c - - $PROJ_DIR$\..\chibios\os\hal\platforms\STM32\TIMv1\icu_lld.c - $PROJ_DIR$\..\chibios\os\hal\src\mac.c @@ -2630,9 +2754,6 @@ $PROJ_DIR$\..\chibios\os\hal\src\usb.c - - $PROJ_DIR$\..\chibios\os\hal\platforms\STM32\OTGv1\usb_lld.c - @@ -2766,15 +2887,6 @@ platform - - STM32 - - $PROJ_DIR$\..\chibios\os\hal\platforms\STM32\RTCv2\rtc_lld.c - - - $PROJ_DIR$\..\chibios\os\hal\platforms\STM32\RTCv2\rtc_lld.h - - $PROJ_DIR$\..\chibios\os\hal\platforms\STM32F4xx\adc_lld.c @@ -2787,6 +2899,12 @@ $PROJ_DIR$\..\chibios\os\hal\platforms\STM32\can_lld.h + + $PROJ_DIR$\..\chibios\os\hal\platforms\STM32\TIMv1\gpt_lld.c + + + $PROJ_DIR$\..\chibios\os\hal\platforms\STM32\TIMv1\gpt_lld.h + $PROJ_DIR$\..\chibios\os\hal\platforms\STM32F4xx\hal_lld.c @@ -2799,6 +2917,12 @@ $PROJ_DIR$\..\chibios\os\hal\platforms\STM32\I2Cv1\i2c_lld.h + + $PROJ_DIR$\..\chibios\os\hal\platforms\STM32\TIMv1\icu_lld.c + + + $PROJ_DIR$\..\chibios\os\hal\platforms\STM32\TIMv1\icu_lld.h + $PROJ_DIR$\..\chibios\os\hal\platforms\STM32\GPIOv2\pal_lld.c @@ -2811,6 +2935,12 @@ $PROJ_DIR$\..\chibios\os\hal\platforms\STM32\TIMv1\pwm_lld.h + + $PROJ_DIR$\..\chibios\os\hal\platforms\STM32\RTCv2\rtc_lld.c + + + $PROJ_DIR$\..\chibios\os\hal\platforms\STM32\RTCv2\rtc_lld.h + $PROJ_DIR$\..\chibios\os\hal\platforms\STM32\USARTv1\serial_lld.c @@ -2829,12 +2959,24 @@ $PROJ_DIR$\..\chibios\os\hal\platforms\STM32F4xx\stm32_dma.h + + $PROJ_DIR$\..\chibios\os\hal\platforms\STM32\OTGv1\stm32_otg.h + $PROJ_DIR$\..\chibios\os\hal\platforms\STM32F4xx\stm32_rcc.h + + $PROJ_DIR$\..\chibios\os\hal\platforms\STM32\TIMv1\stm32_tim.h + $PROJ_DIR$\..\chibios\os\hal\platforms\STM32F4xx\stm32f4xx.h + + $PROJ_DIR$\..\chibios\os\hal\platforms\STM32\OTGv1\usb_lld.c + + + $PROJ_DIR$\..\chibios\os\hal\platforms\STM32\OTGv1\usb_lld.h + port @@ -2877,21 +3019,18 @@ various - - fatfs_bindings - - $PROJ_DIR$\..\chibios\os\various\fatfs_bindings\fatfs_diskio.c - - - $PROJ_DIR$\..\chibios\os\various\fatfs_bindings\fatfs_syscall.c - - $PROJ_DIR$\..\chibios\os\various\chprintf.c $PROJ_DIR$\..\chibios\os\various\chprintf.h + + $PROJ_DIR$\..\chibios\os\various\fatfs_bindings\fatfs_diskio.c + + + $PROJ_DIR$\..\chibios\os\various\fatfs_bindings\fatfs_syscall.c + $PROJ_DIR$\..\chibios\os\various\memstreams.c @@ -2902,6 +3041,12 @@ util + + $PROJ_DIR$\..\util\cli_registry.c + + + $PROJ_DIR$\..\util\cli_registry.h + $PROJ_DIR$\..\util\crc.c @@ -2909,7 +3054,7 @@ $PROJ_DIR$\..\util\crc.h - $PROJ_DIR$\..\util\cyclic_buffer.c + $PROJ_DIR$\..\util\cyclic_buffer.cpp $PROJ_DIR$\..\util\cyclic_buffer.h @@ -2921,13 +3066,16 @@ $PROJ_DIR$\..\util\data_buffer.h - $PROJ_DIR$\..\util\efilib.c + $PROJ_DIR$\..\util\efilib.cpp $PROJ_DIR$\..\util\efilib.h - $PROJ_DIR$\..\util\global.h + $PROJ_DIR$\..\util\efilib2.cpp + + + $PROJ_DIR$\..\util\efilib2.h $PROJ_DIR$\..\util\histogram.c @@ -2941,6 +3089,12 @@ $PROJ_DIR$\..\util\listener_array.h + + $PROJ_DIR$\..\util\LocalVersionHolder.cpp + + + $PROJ_DIR$\..\util\LocalVersionHolder.h + $PROJ_DIR$\..\util\wave_math.c @@ -2949,17 +3103,32 @@ - $PROJ_DIR$\..\main.c + $PROJ_DIR$\..\chconf.h + + + $PROJ_DIR$\..\global.h + + + $PROJ_DIR$\..\halconf.h + + + $PROJ_DIR$\..\main.cpp $PROJ_DIR$\..\main.h - $PROJ_DIR$\..\rusefi.c + $PROJ_DIR$\..\mcuconf.h + + + $PROJ_DIR$\..\rusefi.cpp $PROJ_DIR$\..\rusefi.h + + $PROJ_DIR$\..\svnversion.h + diff --git a/firmware/iar/ch.eww b/firmware/iar/ch.eww index 92960f5290..f9b3b20004 100644 --- a/firmware/iar/ch.eww +++ b/firmware/iar/ch.eww @@ -3,11 +3,6 @@ $WS_DIR$\ch.ewp - - Subversion - notused - notused - diff --git a/firmware/main.h b/firmware/main.h index 144c2f6d33..e5094eca7e 100644 --- a/firmware/main.h +++ b/firmware/main.h @@ -18,7 +18,7 @@ extern "C" #include "global.h" #include "eficonsole.h" -#include "eficonsole_logic.h" +#include "cli_registry.h" #include "efilib.h" #include "rusefi.h" @@ -51,7 +51,7 @@ extern "C" void updateHD44780lcd(void); int systicks2ms(int systicks); -int lockAnyContext(void); +bool_t lockAnyContext(void); void unlockAnyContext(void); #ifdef __cplusplus diff --git a/firmware/rusefi.cpp b/firmware/rusefi.cpp index bb1085779e..183373d333 100644 --- a/firmware/rusefi.cpp +++ b/firmware/rusefi.cpp @@ -1,5 +1,5 @@ /** - * @file rusefi.c + * @file rusefi.cpp * @brief Initialization code and main status reporting look * * @date Dec 25, 2013 @@ -91,7 +91,6 @@ extern "C" { #include "engine_controller.h" #include "ec2.h" #include "trigger_structure.h" -#include "lcd_HD44780.h" #include "status_loop.h" #include "pin_repository.h" @@ -99,6 +98,10 @@ extern "C" { #include "memstreams.h" } +#if EFI_HD44780_LCD +#include "lcd_HD44780.h" +#endif /* EFI_HD44780_LCD */ + #if EFI_ENGINE_EMULATOR #include "engine_emulator.h" #endif /* EFI_ENGINE_EMULATOR */ @@ -109,7 +112,7 @@ int main_loop_started = FALSE; static MemoryStream errorMessageStream; uint8_t errorMessageBuffer[200]; -bool hasFirmwareError = FALSE; +static bool hasFirmwareErrorFlag = FALSE; void runRusEfi(void) { msObjectInit(&errorMessageStream, errorMessageBuffer, sizeof(errorMessageBuffer), 0); @@ -132,7 +135,7 @@ void runRusEfi(void) { /** * Initialize hardware drivers */ - initHardware(); + initHardware(&logging); initStatusLoop(); /** @@ -182,20 +185,6 @@ void scheduleReset(void) { unlockAnyContext(); } -extern "C" { -void onFatalError(const char *msg, const char * file, int line); -} - -void onFatalError(const char *msg, const char * file, int line) { - onDbgPanic(); - lcdShowFatalMessage((char *) msg); - if (!main_loop_started) { - print("fatal %s %s:%d\r\n", msg, file, line); - chThdSleepSeconds(1); - chSysHalt(); - } -} - void DebugMonitorVector(void) { chDbgPanic3("DebugMonitorVector", __FILE__, __LINE__); @@ -228,44 +217,28 @@ void HardFaultVector(void) { ; } - extern int main_loop_started; -int hasFatalError(void); - void onFatalError(const char *msg, char * file, int line); -const char *dbg_panic_file; -int dbg_panic_line; - -extern "C" { -void chDbgPanic3(const char *msg, const char * file, int 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; - onFatalError(dbg_panic_msg, dbg_panic_file, dbg_panic_line); -} - static char panicMessage[200]; void chDbgStackOverflowPanic(Thread *otp) { - strcpy(panicMessage, "stack overflow: "); + strcpy(panicMessage, "stack overflow: "); #ifdef CH_USE_REGISTRY - strcat(panicMessage, otp->p_name); + strcat(panicMessage, otp->p_name); #endif - chDbgPanic3(panicMessage, __FILE__, __LINE__); + chDbgPanic3(panicMessage, __FILE__, __LINE__); } +bool_t hasFirmwareError(void) { + return hasFirmwareErrorFlag; +} void firmwareError(const char *fmt, ...) { - if (hasFirmwareError) + if (hasFirmwareErrorFlag) return; - hasFirmwareError = TRUE; + hasFirmwareErrorFlag = TRUE; errorMessageStream.eos = 0; // reset va_list ap; va_start(ap, fmt); @@ -276,5 +249,5 @@ void firmwareError(const char *fmt, ...) { } int getRusEfiVersion(void) { - return 20140430; + return 20140515; } diff --git a/firmware/svnversion.h b/firmware/svnversion.h index 9c2a90db65..529909c208 100644 --- a/firmware/svnversion.h +++ b/firmware/svnversion.h @@ -1,4 +1,4 @@ // This file was generated by Version2Header #ifndef SVN_VERSION -#define SVN_VERSION 2936 +#define SVN_VERSION 3173 #endif diff --git a/firmware/tunerstudio/rusefi.ini b/firmware/tunerstudio/rusefi.ini index 730cd7a288..82112a1226 100644 --- a/firmware/tunerstudio/rusefi.ini +++ b/firmware/tunerstudio/rusefi.ini @@ -12,7 +12,7 @@ pageIdentifier = "\x00\x00", "\x01\x00" pageReadCommand = "C\x00\x00", "C\x01\x00" burnCommand = "B\x00\x00", "B\x01\x00" - pageSize = 3196,144 + pageSize = 3216,284 pageValueWrite = "W\x00\x00%2o%v", "W\x01\x00%2o%v" @@ -58,8 +58,8 @@ mapMin = scalar, F32, 484, "kpa", 1, 0, 0, 450, 2; size 4 mapMax = scalar, F32, 488, "kpa", 1, 0, 0, 450, 2; size 4 - ;mapRange - ;channel + mapSensorType = bits, U32, 492, [0:1] "Custom", "DENSO183", "MPX4250", "Invalid" + mapAdcInput = bits, U32, 496, [0:4] "PA0", "PA1", "PA2", "PA3", "PA4", "PA5", "PA6", "PA7", "PB0", "PB1", "PB0", "PB1", "PB2", "PB3", "PB4", "PB5" clt_t1 = scalar, F32, 500, "°C", 1, 0, -40, 200, 1; size 4 clt_t2 = scalar, F32, 504, "°C", 1, 0, -40, 200, 1; size 4 @@ -120,7 +120,7 @@ firmwareVersion = scalar, U32, 3052, "index", 1, 0, 0, 300, 0 ; size 4 HD44780width = scalar, U32, 3056, "index", 1, 0, 0, 300, 0 ; size 4 HD44780height = scalar, U32, 3060, "index", 1, 0, 0, 300, 0 ; size 4 - tpsAdcChannel = scalar, U32, 3064, "index", 1, 0, 0, 300, 0 ; size 4 + tpsAdcInput = bits, U32, 3064, [0:4] "PA0", "PA1", "PA2", "PA3", "PA4", "PA5", "PA6", "PA7", "PB0", "PB1", "PB0", "PB1", "PB2", "PB3", "PB4", "PB5" unusedDwellBins = array, F32, 3068, [12], "RPM", 1, 0.0, 0.0, 18000, 2; size 32 trigger_type = bits, U32, 3116, [0:1], "toothed wheel", "ford aspire", "dodge neon", invalid isSynchronizationNeeded = bits, U32, 3120, [0:0], "false", "true" @@ -130,18 +130,26 @@ syncRatioTo = scalar, F32, 3136, "RPM", 1, 0.0, 0, 1000.0, 2 ; size 4 useRiseEdge = bits, U32, 3140, [0:0], "false", "true" needSecondTriggerInput = bits, U32, 3144, [0:0], "false", "true" - vBattAdcChannel = scalar, U32, 3148, "channel", 1, 0, 0, 16, 0 ; size 4 + vBattAdcInput = bits, U32, 3148, [0:4] "PA0", "PA1", "PA2", "PA3", "PA4", "PA5", "PA6", "PA7", "PB0", "PB1", "PB0", "PB1", "PB2", "PB3", "PB4", "PB5" globalFuelCorrection = scalar, F32, 3152, "RPM", 1, 0.0, 0, 1000.0, 2 ; size 4 - cltAdcChannel = scalar, U32, 3156, "channel", 1, 0, 0, 16, 0 ; size 4 - iatAdcChannel = scalar, U32, 3160, "channel", 1, 0, 0, 16, 0 ; size 4 - mafAdcChannel = scalar, U32, 3164, "channel", 1, 0, 0, 16, 0 ; size 4 - afrAdcChannel = scalar, U32, 3168, "channel", 1, 0, 0, 16, 0 ; size 4 + cltAdcInput = bits, U32, 3156, [0:4] "PA0", "PA1", "PA2", "PA3", "PA4", "PA5", "PA6", "PA7", "PB0", "PB1", "PB0", "PB1", "PB2", "PB3", "PB4", "PB5" + iatAdcInput = bits, U32, 3160, [0:4] "PA0", "PA1", "PA2", "PA3", "PA4", "PA5", "PA6", "PA7", "PB0", "PB1", "PB0", "PB1", "PB2", "PB3", "PB4", "PB5" + mafAdcInput = bits, U32, 3164, [0:4] "PA0", "PA1", "PA2", "PA3", "PA4", "PA5", "PA6", "PA7", "PB0", "PB1", "PB0", "PB1", "PB2", "PB3", "PB4", "PB5" + afrAdcInput = bits, U32, 3168, [0:4] "PA0", "PA1", "PA2", "PA3", "PA4", "PA5", "PA6", "PA7", "PB0", "PB1", "PB0", "PB1", "PB2", "PB3", "PB4", "PB5" afr_v1 = scalar, F32, 3172, "RPM", 1, 0.0, 0, 1000.0, 2 ; size 4 afr_value1 = scalar, F32, 3176, "RPM", 1, 0.0, 0, 1000.0, 2 ; size 4 afr_v2 = scalar, F32, 3180, "RPM", 1, 0.0, 0, 1000.0, 2 ; size 4 afr_value2 = scalar, F32, 3184, "RPM", 1, 0.0, 0, 1000.0, 2 ; size 4 injectionOffset = scalar, F32, 3188, "RPM", 1, 0.0, 0, 1000.0, 2 ; size 4 crankingTimingAngle = scalar, F32, 3192, "RPM", 1, 0.0, 0, 1000.0, 2 ; size 4 + + ; + + ;baroMin = scalar, F32, 484, "kpa", 1, 0, 0, 450, 2; size 4 + ;baroMax = scalar, F32, 488, "kpa", 1, 0, 0, 450, 2; size 4 + baroSensorType = bits, U32, 3208, [0:1] "Custom", "DENSO183", "MPX4250", "Invalid" + baroAdcInput = bits, U32, 3212, [0:4] "PA0", "PA1", "PA2", "PA3", "PA4", "PA5", "PA6", "PA7", "PB0", "PB1", "PB0", "PB1", "PB2", "PB3", "PB4", "PB5" + page = 2 @@ -183,6 +191,23 @@ fanPinMode = bits, U32, 132, [0:1], "default", "default inverted", "open", "open inverted" electronicThrottlePin1 = bits, U32, 136, [0:6], "GPIOA_0", "GPIOA_1", "GPIOA_2", "GPIOA_3", "GPIOA_4", "GPIOA_5", "GPIOA_6", "GPIOA_7", "GPIOA_8", "GPIOA_9", "GPIOA_10", "GPIOA_11", "GPIOA_12", "GPIOA_13", "GPIOA_14", "GPIOA_15", "GPIOB_0", "GPIOB_1", "GPIOB_2", "GPIOB_3", "GPIOB_4", "GPIOB_5", "GPIOB_6", "GPIOB_7", "GPIOB_8", "GPIOB_9", "GPIOB_10", "GPIOB_11", "GPIOB_12", "GPIOB_13", "GPIOB_14", "GPIOB_15", "GPIOC_0", "GPIOC_1", "GPIOC_2", "GPIOC_3", "GPIOC_4", "GPIOC_5", "GPIOC_6", "GPIOC_7", "GPIOC_8", "GPIOC_9", "GPIOC_10", "GPIOC_11", "GPIOC_12", "GPIOC_13", "GPIOC_14", "GPIOC_15", "GPIOD_0", "GPIOD_1", "GPIOD_2", "GPIOD_3", "GPIOD_4", "GPIOD_5", "GPIOD_6", "GPIOD_7", "GPIOD_8", "GPIOD_9", "GPIOD_10", "GPIOD_11", "GPIOD_12", "GPIOD_13", "GPIOD_14", "GPIOD_15", "GPIOE_0", "GPIOE_1", "GPIOE_2", "GPIOE_3", "GPIOE_4", "GPIOE_5", "GPIOE_6", "GPIOE_7", "GPIOE_8", "GPIOE_9", "GPIOE_10", "GPIOE_11", "GPIOE_12", "GPIOE_13", "GPIOE_14", "GPIOE_15", invalid, invalid, invalid, invalid, invalid, invalid, invalid, invalid, invalid, invalid, invalid, invalid, invalid, invalid, invalid, invalid, invalid, invalid, invalid, invalid, invalid, invalid, invalid, invalid, invalid, invalid, invalid, invalid, invalid, invalid, invalid, invalid, invalid, invalid, invalid, invalid, invalid, invalid, invalid, invalid, invalid, invalid, invalid, invalid, invalid, invalid, invalid, invalid electronicThrottlePin1Mode = bits, U32, 140, [0:1], "default", "default inverted", "open", "open inverted" + + adcModePA0 = bits, U32, 220, [0:1], "Off", "Slow", "Fast", "invalid" + adcModePA1 = bits, U32, 224, [0:1], "Off", "Slow", "Fast", "invalid" + adcModePA2 = bits, U32, 228, [0:1], "Off", "Slow", "Fast", "invalid" + adcModePA3 = bits, U32, 232, [0:1], "Off", "Slow", "Fast", "invalid" + adcModePA4 = bits, U32, 236, [0:1], "Off", "Slow", "Fast", "invalid" + adcModePA5 = bits, U32, 240, [0:1], "Off", "Slow", "Fast", "invalid" + adcModePA6 = bits, U32, 244, [0:1], "Off", "Slow", "Fast", "invalid" + adcModePA7 = bits, U32, 248, [0:1], "Off", "Slow", "Fast", "invalid" + adcModePB0 = bits, U32, 252, [0:1], "Off", "Slow", "Fast", "invalid" + adcModePB1 = bits, U32, 256, [0:1], "Off", "Slow", "Fast", "invalid" + adcModePC0 = bits, U32, 260, [0:1], "Off", "Slow", "Fast", "invalid" + adcModePC1 = bits, U32, 264, [0:1], "Off", "Slow", "Fast", "invalid" + adcModePC2 = bits, U32, 268, [0:1], "Off", "Slow", "Fast", "invalid" + adcModePC3 = bits, U32, 272, [0:1], "Off", "Slow", "Fast", "invalid" + adcModePC4 = bits, U32, 274, [0:1], "Off", "Slow", "Fast", "invalid" + adcModePC5 = bits, U32, 280, [0:1], "Off", "Slow", "Fast", "invalid" @@ -332,8 +357,9 @@ menu = "&Engine" subMenu = engineChars, "&Engine Characteristics" subMenu = boardInputs, "&Board inputs" - subMenu = boardOutputs1, "&Board outputs #1" - subMenu = boardOutputs2, "&Board outputs #2" + subMenu = boardInputMode, "Board inputs mode" + subMenu = boardOutputs1, "Board outputs #1" + subMenu = boardOutputs2, "Board outputs #2" subMenu = injChars, "&injector Characteristicks" subMenu = injectorsDeadTime, "&Injectors Dead Time" menu = "&Sensors" @@ -393,11 +419,32 @@ dialog = boardInputs, "Board inputs" field = "Analog Input Divider Coefficient", analogInputDividerCoefficient field = "Battery Input Divider Coefficient", VBattDividerCoefficient - field = "TPS ADC channel", tpsAdcChannel - field = "CLT ADC channel", cltAdcChannel - field = "IAT ADC channel", iatAdcChannel - field = "MAF ADC channel", mafAdcChannel - field = "vBatt ADC channel", vBattAdcChannel + field = "TPS ADC input", tpsAdcInput + field = "CLT ADC input", cltAdcInput + field = "IAT ADC input", iatAdcInput + field = "MAF ADC input", mafAdcInput + field = "MAP ADC input", mapAdcInput + field = "Baro ADC input", baroAdcInput + field = "vBatt ADC input", vBattAdcInput + + dialog = boardInputMode, "Board inputs Mode" + field = "ADC on PA0", adcModePA0 + field = "ADC on PA1", adcModePA1 + field = "ADC on PA2", adcModePA2 + field = "ADC on PA3", adcModePA3 + field = "ADC on PA4", adcModePA4 + field = "ADC on PA5", adcModePA5 + field = "ADC on PA6", adcModePA6 + field = "ADC on PA7", adcModePA7 + field = "ADC on PB0", adcModePB0 + field = "ADC on PB1", adcModePB1 + field = "ADC on PC0", adcModePC0 + field = "ADC on PC1", adcModePC1 + field = "ADC on PC2", adcModePC2 + field = "ADC on PC3", adcModePC3 + field = "ADC on PC4", adcModePC4 + field = "ADC on PC5", adcModePC5 + dialog = boardOutputs1, "Board properties #1" field = "Injection Pin 1", injectionPin1 diff --git a/firmware/util/LocalVersionHolder.cpp b/firmware/util/LocalVersionHolder.cpp index 6b97bb6c99..8047567596 100644 --- a/firmware/util/LocalVersionHolder.cpp +++ b/firmware/util/LocalVersionHolder.cpp @@ -2,7 +2,7 @@ * @file LocalVersionHolder.cpp * * @date Mar 19, 2014 - * @author Andrey Belomutskiy, (c) 2012-2013 + * @author Andrey Belomutskiy, (c) 2012-2014 */ #include "LocalVersionHolder.h" diff --git a/firmware/util/eficonsole_logic.c b/firmware/util/cli_registry.c similarity index 94% rename from firmware/util/eficonsole_logic.c rename to firmware/util/cli_registry.c index 1fd9413032..e7d09a0d19 100644 --- a/firmware/util/eficonsole_logic.c +++ b/firmware/util/cli_registry.c @@ -1,288 +1,287 @@ -/* - * @date Nov 15, 2012 - * @author Andrey Belomutskiy, (c) 2012-2014 - */ - -/** - * @file eficonsole_logic.c - * @brief Console interactive shell code - * - * Here we have a data structure which holds all the dynamically-registered - * command line interface action names & callback. This logic is invoked in - * user context by the console thread - see consoleThreadThreadEntryPoint - */ - -#include -#include -#include -#include "main.h" -#include "eficonsole_logic.h" -#include "efilib.h" -#if EFI_PROD_CODE || EFI_SIMULATOR -#include "eficonsole.h" -static Logging logging; -#endif /* EFI_PROD_CODE */ - -static int consoleActionCount = 0; -static TokenCallback consoleActions[CONSOLE_MAX_ACTIONS]; - -void resetConsoleActions(void) { - consoleActionCount = 0; -} - -static void doAddAction(const char *token, int type, Void callback) { - if (consoleActionCount == CONSOLE_MAX_ACTIONS) { - fatal("Too many console actions\r\n"); - return; - } - TokenCallback *current = &consoleActions[consoleActionCount++]; - current->token = token; - current->parameterType = type; - current->callback = callback; -} - -/** - * @brief Register console action without parameters - */ -void addConsoleAction(const char *token, Void callback) { - doAddAction(token, NO_PARAMETER, callback); -} - -/** - * @brief Register a console command with one Integer parameter - */ -void addConsoleActionI(const char *token, VoidInt callback) { - doAddAction(token, ONE_PARAMETER, (Void) callback); -} - -/** - * @brief Register a console command with two Integer parameters - */ -void addConsoleActionII(const char *token, VoidIntInt callback) { - doAddAction(token, TWO_INTS_PARAMETER, (Void) callback); -} - -void addConsoleActionS(const char *token, VoidCharPtr callback) { - doAddAction(token, STRING_PARAMETER, (Void) callback); -} - -void addConsoleActionSSS(const char *token, VoidCharPtrCharPtrCharPtr callback) { - doAddAction(token, STRING3_PARAMETER, (Void) callback); -} - -void addConsoleActionF(const char *token, VoidFloat callback) { - doAddAction(token, FLOAT_PARAMETER, (Void) callback); -} - -/** - * @brief This function prints out a list of all available commands - */ -void helpCommand(void) { -#if EFI_PROD_CODE || EFI_SIMULATOR - scheduleMsg(&logging, "%d actions available", consoleActionCount); - for (int i = 0; i < consoleActionCount; i++) { - TokenCallback *current = &consoleActions[i]; - scheduleMsg(&logging, " %s: %d parameters", current->token, current->parameterType); - } -#endif -} - -/** - * @brief This is just a test function - */ -static void echo(int value) { - print("got value: %d\r\n", value); -} - -void handleActionWithParameter(TokenCallback *current, char *parameter) { - if (current->parameterType == STRING_PARAMETER) { - VoidCharPtr callbackS = (VoidCharPtr) current->callback; - (*callbackS)(parameter); - return; - } - - if (current->parameterType == STRING3_PARAMETER) { - int spaceIndex = indexOf(parameter, ' '); - if (spaceIndex == -1) - return; - parameter[spaceIndex] = 0; - char * firstParam = parameter; - - parameter += spaceIndex + 1; - spaceIndex = indexOf(parameter, ' '); - if (spaceIndex == -1) - return; - parameter[spaceIndex] = 0; - char * secondParam = parameter; - parameter += spaceIndex + 1; - char * thirdParam = parameter; - - VoidCharPtrCharPtrCharPtr callbackS = (VoidCharPtrCharPtrCharPtr) current->callback; - (*callbackS)(firstParam, secondParam, thirdParam); - return; - - } - - if (current->parameterType == TWO_INTS_PARAMETER) { - int spaceIndex = indexOf(parameter, ' '); - if (spaceIndex == -1) - return; - parameter[spaceIndex] = 0; - int value1 = atoi(parameter); - parameter += spaceIndex + 1; - int value2 = atoi(parameter); - VoidIntInt callbackS = (VoidIntInt) current->callback; - (*callbackS)(value1, value2); - return; - } - - if (current->parameterType == FLOAT_PARAMETER) { - float value = atoff(parameter); - VoidFloat callbackF = (VoidFloat) current->callback; - - // invoke callback function by reference - (*callbackF)(value); - return; - } - - int value = atoi(parameter); - if (value == ERROR_CODE) { - print("invalid integer [%s]\r\n", parameter); - return; - } - - VoidInt callback1 = (VoidInt) current->callback; - - // invoke callback function by reference - (*callback1)(value); - -} - -/** - * @return Number of space-separated tokens in the string - */ -int tokenLength(char *msgp) { - int result = 0; - while (*msgp) { - char ch = *msgp++; - if (ch == ' ') - break; - result++; - } - return result; -} - -int strEqual(const char *str1, const char *str2) { - // todo: there must be a standard function?! - int len1 = strlen(str1); - int len2 = strlen(str2); - if (len1 != len2) - return FALSE; - for (int i = 0; i < len1; i++) - if (str1[i] != str2[i]) - return FALSE; - return TRUE; -} - -void initConsoleLogic() { -#if EFI_PROD_CODE || EFI_SIMULATOR - initLogging(&logging, "rfi console"); -#endif /* EFI_PROD_CODE */ - resetConsoleActions(); - addConsoleAction("help", helpCommand); - addConsoleActionI("echo", echo); -} - -char *validateSecureLine(char *line) { - if (line == NULL) - return NULL; - if (strncmp("sec!", line, 4) == 0) { - // COM protocol looses bytes, this is a super-naive error detection - -// print("Got secure mode request header [%s]\r\n", line); - line += 4; -// print("Got secure mode request command [%s]\r\n", line); - - char *divider = line; - while (*divider != '!') { - if (*divider == '\0') { - print("Divider not found [%s]\r\n", line); - return NULL; - } - divider++; - } - *divider++ = 0; // replacing divider symbol with zero - int expectedLength = atoi(line); - line = divider; - int actualLength = strlen(line); - if (expectedLength != actualLength) { - print("Error detected: expected %d but got %d in [%s]\r\n", expectedLength, actualLength, line); - return NULL; - } - } - return line; -} - -static char confirmation[200]; - -void sendOutConfirmation(char *value, int i); - -static bool_t handleConsoleLineInternal(char *line, int lineLength) { - int firstTokenLength = tokenLength(line); - -// print("processing [%s] with %d actions\r\n", line, consoleActionCount); - - if (firstTokenLength == lineLength) { - // no-param actions are processed here - for (int i = 0; i < consoleActionCount; i++) { - TokenCallback *current = &consoleActions[i]; - if (strEqual(line, current->token)) { - // invoke callback function by reference - (*current->callback)(); - return TRUE; - } - } - } else { - char *ptr = line + firstTokenLength; - ptr[0] = 0; // change space into line end - ptr++; // start from next symbol - - for (int i = 0; i < consoleActionCount; i++) { - TokenCallback *current = &consoleActions[i]; - if (strEqual(line, current->token)) { - handleActionWithParameter(current, ptr); - return TRUE; - } - } - } - return FALSE; -} - -/** - * @brief This function takes care of one command line once we have it - */ -void handleConsoleLine(char *line) { - line = validateSecureLine(line); - if (line == NULL) - return; // error detected - - int lineLength = strlen(line); - if (lineLength > 100) { - // todo: better max size logic - // todo: better reaction to excessive line - print("Long line?\r\n"); - return; - } - - strcpy(confirmation, "confirmation_"); - strcat(confirmation, line); - strcat(confirmation, ":"); - - bool_t isKnownComman = handleConsoleLineInternal(line, lineLength); - - // confirmation happens after the command to avoid conflict with command own output - sendOutConfirmation(confirmation, lineLength); - - if (!isKnownComman) - helpCommand(); -} +/** + * @file cli_registry.c + * @brief Command-line interface commands registry + * + * Here we have a data structure which holds all the dynamically-registered + * command line interface action names & callback. This logic is invoked in + * user context by the console thread - see consoleThreadThreadEntryPoint + * + * + * @date Nov 15, 2012 + * @author Andrey Belomutskiy, (c) 2012-2014 + */ + +#include +#include +#include +#include "main.h" +#include "cli_registry.h" +#include "efilib.h" +#if EFI_PROD_CODE || EFI_SIMULATOR +#include "eficonsole.h" +static Logging logging; +#endif /* EFI_PROD_CODE */ + +static int consoleActionCount = 0; +static TokenCallback consoleActions[CONSOLE_MAX_ACTIONS]; + +void resetConsoleActions(void) { + consoleActionCount = 0; +} + +static void doAddAction(const char *token, int type, Void callback) { + if (consoleActionCount == CONSOLE_MAX_ACTIONS) { + fatal("Too many console actions\r\n"); + return; + } + TokenCallback *current = &consoleActions[consoleActionCount++]; + current->token = token; + current->parameterType = type; + current->callback = callback; +} + +/** + * @brief Register console action without parameters + */ +void addConsoleAction(const char *token, Void callback) { + doAddAction(token, NO_PARAMETER, callback); +} + +/** + * @brief Register a console command with one Integer parameter + */ +void addConsoleActionI(const char *token, VoidInt callback) { + doAddAction(token, ONE_PARAMETER, (Void) callback); +} + +/** + * @brief Register a console command with two Integer parameters + */ +void addConsoleActionII(const char *token, VoidIntInt callback) { + doAddAction(token, TWO_INTS_PARAMETER, (Void) callback); +} + +void addConsoleActionS(const char *token, VoidCharPtr callback) { + doAddAction(token, STRING_PARAMETER, (Void) callback); +} + +void addConsoleActionSSS(const char *token, VoidCharPtrCharPtrCharPtr callback) { + doAddAction(token, STRING3_PARAMETER, (Void) callback); +} + +void addConsoleActionF(const char *token, VoidFloat callback) { + doAddAction(token, FLOAT_PARAMETER, (Void) callback); +} + +/** + * @brief This function prints out a list of all available commands + */ +void helpCommand(void) { +#if EFI_PROD_CODE || EFI_SIMULATOR + scheduleMsg(&logging, "%d actions available", consoleActionCount); + for (int i = 0; i < consoleActionCount; i++) { + TokenCallback *current = &consoleActions[i]; + scheduleMsg(&logging, " %s: %d parameters", current->token, current->parameterType); + } +#endif +} + +/** + * @brief This is just a test function + */ +static void echo(int value) { + print("got value: %d\r\n", value); +} + +void handleActionWithParameter(TokenCallback *current, char *parameter) { + if (current->parameterType == STRING_PARAMETER) { + VoidCharPtr callbackS = (VoidCharPtr) current->callback; + (*callbackS)(parameter); + return; + } + + if (current->parameterType == STRING3_PARAMETER) { + int spaceIndex = indexOf(parameter, ' '); + if (spaceIndex == -1) + return; + parameter[spaceIndex] = 0; + char * firstParam = parameter; + + parameter += spaceIndex + 1; + spaceIndex = indexOf(parameter, ' '); + if (spaceIndex == -1) + return; + parameter[spaceIndex] = 0; + char * secondParam = parameter; + parameter += spaceIndex + 1; + char * thirdParam = parameter; + + VoidCharPtrCharPtrCharPtr callbackS = (VoidCharPtrCharPtrCharPtr) current->callback; + (*callbackS)(firstParam, secondParam, thirdParam); + return; + + } + + if (current->parameterType == TWO_INTS_PARAMETER) { + int spaceIndex = indexOf(parameter, ' '); + if (spaceIndex == -1) + return; + parameter[spaceIndex] = 0; + int value1 = atoi(parameter); + parameter += spaceIndex + 1; + int value2 = atoi(parameter); + VoidIntInt callbackS = (VoidIntInt) current->callback; + (*callbackS)(value1, value2); + return; + } + + if (current->parameterType == FLOAT_PARAMETER) { + float value = atoff(parameter); + VoidFloat callbackF = (VoidFloat) current->callback; + + // invoke callback function by reference + (*callbackF)(value); + return; + } + + int value = atoi(parameter); + if (value == ERROR_CODE) { + print("invalid integer [%s]\r\n", parameter); + return; + } + + VoidInt callback1 = (VoidInt) current->callback; + + // invoke callback function by reference + (*callback1)(value); + +} + +/** + * @return Number of space-separated tokens in the string + */ +int tokenLength(char *msgp) { + int result = 0; + while (*msgp) { + char ch = *msgp++; + if (ch == ' ') + break; + result++; + } + return result; +} + +int strEqual(const char *str1, const char *str2) { + // todo: there must be a standard function?! + int len1 = strlen(str1); + int len2 = strlen(str2); + if (len1 != len2) + return FALSE; + for (int i = 0; i < len1; i++) + if (str1[i] != str2[i]) + return FALSE; + return TRUE; +} + +void initConsoleLogic() { +#if EFI_PROD_CODE || EFI_SIMULATOR + initLogging(&logging, "rfi console"); +#endif /* EFI_PROD_CODE */ + resetConsoleActions(); + addConsoleAction("help", helpCommand); + addConsoleActionI("echo", echo); +} + +char *validateSecureLine(char *line) { + if (line == NULL) + return NULL; + if (strncmp("sec!", line, 4) == 0) { + // COM protocol looses bytes, this is a super-naive error detection + +// print("Got secure mode request header [%s]\r\n", line); + line += 4; +// print("Got secure mode request command [%s]\r\n", line); + + char *divider = line; + while (*divider != '!') { + if (*divider == '\0') { + print("Divider not found [%s]\r\n", line); + return NULL; + } + divider++; + } + *divider++ = 0; // replacing divider symbol with zero + int expectedLength = atoi(line); + line = divider; + int actualLength = strlen(line); + if (expectedLength != actualLength) { + print("Error detected: expected %d but got %d in [%s]\r\n", expectedLength, actualLength, line); + return NULL; + } + } + return line; +} + +static char confirmation[200]; + +void sendOutConfirmation(char *value, int i); + +static bool_t handleConsoleLineInternal(char *line, int lineLength) { + int firstTokenLength = tokenLength(line); + +// print("processing [%s] with %d actions\r\n", line, consoleActionCount); + + if (firstTokenLength == lineLength) { + // no-param actions are processed here + for (int i = 0; i < consoleActionCount; i++) { + TokenCallback *current = &consoleActions[i]; + if (strEqual(line, current->token)) { + // invoke callback function by reference + (*current->callback)(); + return TRUE; + } + } + } else { + char *ptr = line + firstTokenLength; + ptr[0] = 0; // change space into line end + ptr++; // start from next symbol + + for (int i = 0; i < consoleActionCount; i++) { + TokenCallback *current = &consoleActions[i]; + if (strEqual(line, current->token)) { + handleActionWithParameter(current, ptr); + return TRUE; + } + } + } + return FALSE; +} + +/** + * @brief This function takes care of one command line once we have it + */ +void handleConsoleLine(char *line) { + line = validateSecureLine(line); + if (line == NULL) + return; // error detected + + int lineLength = strlen(line); + if (lineLength > 100) { + // todo: better max size logic + // todo: better reaction to excessive line + print("Long line?\r\n"); + return; + } + + strcpy(confirmation, "confirmation_"); + strcat(confirmation, line); + strcat(confirmation, ":"); + + bool_t isKnownComman = handleConsoleLineInternal(line, lineLength); + + // confirmation happens after the command to avoid conflict with command own output + sendOutConfirmation(confirmation, lineLength); + + if (!isKnownComman) + helpCommand(); +} diff --git a/firmware/util/eficonsole_logic.h b/firmware/util/cli_registry.h similarity index 85% rename from firmware/util/eficonsole_logic.h rename to firmware/util/cli_registry.h index 9b1735a386..6f8c0fc9ca 100644 --- a/firmware/util/eficonsole_logic.h +++ b/firmware/util/cli_registry.h @@ -1,72 +1,62 @@ -/* - * @date Nov 15, 2012 - * @author Andrey Belomutskiy, (c) 2012-2014 - */ - -/** - * @file eficonsole_logic.h - * @brief Console interactive shell header - */ - -#ifndef RFICONSOLE_LOGIC_H_ -#define RFICONSOLE_LOGIC_H_ - -#ifdef __cplusplus -extern "C" -{ -#endif /* __cplusplus */ - -#define CONSOLE_MAX_ACTIONS 96 - -#ifndef FALSE -#define FALSE 0 -#endif -#ifndef TRUE -#define TRUE (!FALSE) -#endif - -typedef enum { - NO_PARAMETER, - ONE_PARAMETER, - FLOAT_PARAMETER, - STRING_PARAMETER, - STRING3_PARAMETER, - TWO_INTS_PARAMETER, -} ACTION_PARAMETER_TYPE; - -typedef struct { - const char *token; - int parameterType; - void (*callback)(void); -} TokenCallback; - -//void addDefaultConsoleActions(void); -//void handleActionWithParameter(TokenCallback *current, char *parameter); -int tokenLength(char *msgp); - -typedef void (*Void)(void); -typedef void (*VoidInt)(int); -typedef void (*VoidFloat)(float); -typedef void (*VoidIntInt)(int, int); -typedef void (*VoidCharPtr)(char *); -typedef void (*VoidCharPtrCharPtrCharPtr)(char *, char *, char *); - -char *validateSecureLine(char *line); -int strEqual(const char *str1, const char *str2); -void resetConsoleActions(void); -void helpCommand(void); -void initConsoleLogic(void); -void handleConsoleLine(char *line); -void addConsoleAction(const char *token, Void callback); -void addConsoleActionI(const char *token, VoidInt callback); -void addConsoleActionII(const char *token, VoidIntInt callback); -void addConsoleActionF(const char *token, VoidFloat callback); -void addConsoleActionS(const char *token, VoidCharPtr callback); -void addConsoleActionSSS(const char *token, VoidCharPtrCharPtrCharPtr callback); - - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* RFICONSOLE_H_ */ +/** + * @file cli_registry.h + * @brief Command-line interface commands registry + * + * @date Nov 15, 2012 + * @author Andrey Belomutskiy, (c) 2012-2014 + */ + +#ifndef RFICONSOLE_LOGIC_H_ +#define RFICONSOLE_LOGIC_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +#define CONSOLE_MAX_ACTIONS 96 + +typedef enum { + NO_PARAMETER, + ONE_PARAMETER, + FLOAT_PARAMETER, + STRING_PARAMETER, + STRING3_PARAMETER, + TWO_INTS_PARAMETER, +} ACTION_PARAMETER_TYPE; + +typedef struct { + const char *token; + int parameterType; + void (*callback)(void); +} TokenCallback; + +//void addDefaultConsoleActions(void); +//void handleActionWithParameter(TokenCallback *current, char *parameter); +int tokenLength(char *msgp); + +typedef void (*Void)(void); +typedef void (*VoidInt)(int); +typedef void (*VoidFloat)(float); +typedef void (*VoidIntInt)(int, int); +typedef void (*VoidCharPtr)(char *); +typedef void (*VoidCharPtrCharPtrCharPtr)(char *, char *, char *); + +char *validateSecureLine(char *line); +int strEqual(const char *str1, const char *str2); +void resetConsoleActions(void); +void helpCommand(void); +void initConsoleLogic(void); +void handleConsoleLine(char *line); +void addConsoleAction(const char *token, Void callback); +void addConsoleActionI(const char *token, VoidInt callback); +void addConsoleActionII(const char *token, VoidIntInt callback); +void addConsoleActionF(const char *token, VoidFloat callback); +void addConsoleActionS(const char *token, VoidCharPtr callback); +void addConsoleActionSSS(const char *token, VoidCharPtrCharPtrCharPtr callback); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* RFICONSOLE_H_ */ diff --git a/firmware/util/crc.c b/firmware/util/crc.c index 2257e72289..cb889420ec 100644 --- a/firmware/util/crc.c +++ b/firmware/util/crc.c @@ -10,8 +10,8 @@ #define TOPBIT (1 << (WIDTH - 1)) #define POLYNOMIAL 0xD8 -crc calc_crc(const crc message[], int nBytes) { - crc remainder = 0; +crc_t calc_crc(const crc_t message[], int nBytes) { + crc_t remainder = 0; /* * Perform modulo-2 division, a byte at a time. diff --git a/firmware/util/crc.h b/firmware/util/crc.h index a50bee5f44..a0533e02f3 100644 --- a/firmware/util/crc.h +++ b/firmware/util/crc.h @@ -8,14 +8,14 @@ #ifndef CRC_H_ #define CRC_H_ -typedef unsigned char crc; +typedef unsigned char crc_t; #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ -crc calc_crc(const crc message[], int nBytes); +crc_t calc_crc(const crc_t message[], int nBytes); #ifdef __cplusplus } diff --git a/firmware/util/efilib.cpp b/firmware/util/efilib.cpp index e7f33b78fb..d80f12f86e 100644 --- a/firmware/util/efilib.cpp +++ b/firmware/util/efilib.cpp @@ -11,6 +11,29 @@ #include #include "efilib.h" +/** + * 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; +} + +int minI(int i1, int i2) { + return i1 < i2 ? i1 : i2; +} + +int absI(int32_t value) { + return value >= 0 ? value : -value; +} + +int maxI(int i1, int i2) { + return i1 > i2 ? i1 : i2; +} + +float maxF(float i1, float i2) { + return i1 > i2 ? i1 : i2; +} + int indexOf(const char *string, char ch) { // todo: there should be a standard function for this int len = strlen(string); @@ -49,7 +72,7 @@ static char todofixthismesswithcopy[100]; float atoff(const char *param) { int totallen = strlen(param); if (totallen > sizeof(todofixthismesswithcopy) - 1) - return (float)NAN; + return (float) NAN; strcpy(todofixthismesswithcopy, param); char *string = todofixthismesswithcopy; diff --git a/firmware/util/efilib.h b/firmware/util/efilib.h index 7b97f80519..64701966ca 100644 --- a/firmware/util/efilib.h +++ b/firmware/util/efilib.h @@ -8,13 +8,23 @@ #ifndef EFILIB_H_ #define EFILIB_H_ +#include "stdint.h" + +// number of milliseconds in one period of given frequency (per second) +#define frequency2period(freq) (((float)1000) / (freq)) + +#ifndef FALSE +#define FALSE 0 +#endif +#ifndef TRUE +#define TRUE (!FALSE) +#endif #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ - #define ERROR_CODE -11223344 int indexOf(const char *string, char ch); @@ -22,6 +32,11 @@ float atoff(const char *string); int atoi(const char *string); int cisnan(float f); +int absI(int32_t value); +int maxI(int i1, int i2); +int minI(int i1, int i2); +float maxF(float i1, float i2); + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/firmware/util/efilib2.cpp b/firmware/util/efilib2.cpp index 6c6fbe349e..ece87fc5c0 100644 --- a/firmware/util/efilib2.cpp +++ b/firmware/util/efilib2.cpp @@ -2,7 +2,7 @@ * @file efilib2.cpp * * @date Apr 14, 2014 - * @author Andrey Belomutskiy, (c) 2012-2013 + * @author Andrey Belomutskiy, (c) 2012-2014 */ #include "efilib2.h" diff --git a/firmware/util/efilib2.h b/firmware/util/efilib2.h index ae1bdc136d..5dda38dc20 100644 --- a/firmware/util/efilib2.h +++ b/firmware/util/efilib2.h @@ -2,7 +2,7 @@ * @file efilib2.h * * @date Apr 14, 2014 - * @author Andrey Belomutskiy, (c) 2012-2013 + * @author Andrey Belomutskiy, (c) 2012-2014 */ #ifndef EFILIB2_H_ diff --git a/firmware/util/histogram.c b/firmware/util/histogram.c index 22ef4887e8..f28bac4aac 100644 --- a/firmware/util/histogram.c +++ b/firmware/util/histogram.c @@ -13,6 +13,8 @@ #include "histogram.h" #include "main.h" +#if EFI_HISTOGRAMS + #define H_ACCURACY 0.05 #define H_CONFIDENCE 0.8 #define LONG_MAX_INT 0x7fffffffffffffffL @@ -152,3 +154,5 @@ int hsReport(histogram_s *h, int* report) { return index; } + +#endif /* EFI_HISTOGRAMS */ diff --git a/firmware/util/readme.txt b/firmware/util/readme.txt new file mode 100644 index 0000000000..6588b85056 --- /dev/null +++ b/firmware/util/readme.txt @@ -0,0 +1,3 @@ +In this folder we have all the tiny utility stuff. + +Ideally, code from this fould should not depend on code from any other folder. \ No newline at end of file diff --git a/firmware/util/util.mk b/firmware/util/util.mk index c134f0b83f..e6125e9830 100644 --- a/firmware/util/util.mk +++ b/firmware/util/util.mk @@ -3,7 +3,7 @@ UTILSRC = $(PROJECT_DIR)/util/data_buffer.c \ $(PROJECT_DIR)/util/listener_array.c \ $(PROJECT_DIR)/util/crc.c \ $(PROJECT_DIR)/util/histogram.c \ - $(PROJECT_DIR)/util/eficonsole_logic.c \ + $(PROJECT_DIR)/util/cli_registry.c \ $(PROJECT_DIR)/util/wave_math.c UTILSRC_CPP = $(PROJECT_DIR)/util/cyclic_buffer.cpp \ diff --git a/firmware/util/wave_math.c b/firmware/util/wave_math.c index 1c4f044ef2..d69ba560fb 100644 --- a/firmware/util/wave_math.c +++ b/firmware/util/wave_math.c @@ -9,24 +9,24 @@ //#define LOOPS_TIME(value, divider) (((int)((value) / (divider))) * (divider)) -float floatmod(float value, float divider) { - // number of full cycles - int loopsNumber = (int)(value / divider); - // total time of full cycles - float loopsTime = loopsNumber * divider; +//float floatmod(float value, float divider) { +// // number of full cycles +// int loopsNumber = (int)(value / divider); +// // total time of full cycles +// float loopsTime = loopsNumber * divider; +// +// return value - loopsTime; +//} - return value - loopsTime; -} - -/** - * @param waveLen length of each wave, in ticks - */ -int waveState(time_t start, time_t now, float waveLen, float leftSide, - float rightSide) { - /** - * number of ticks since start of thread - */ - float time = now - start; - float mod = floatmod(time, waveLen); - return mod >= waveLen * leftSide && mod < waveLen * rightSide; -} +///** +// * @param waveLen length of each wave, in ticks +// */ +//int waveState(time_t start, time_t now, float waveLen, float leftSide, +// float rightSide) { +// /** +// * number of ticks since start of thread +// */ +// float time = now - start; +// float mod = floatmod(time, waveLen); +// return mod >= waveLen * leftSide && mod < waveLen * rightSide; +//} diff --git a/firmware/util/wave_math.h b/firmware/util/wave_math.h index eddd777389..24beddd01a 100644 --- a/firmware/util/wave_math.h +++ b/firmware/util/wave_math.h @@ -12,11 +12,10 @@ #include "global.h" -// number of milliseconds in one period of given frequency (per second) -#define frequency2period(freq) (((float)1000) / (freq)) +// todo: looks like it's time to remove this file? -float floatmod(float value, float divider); -int waveState(time_t start, time_t now, float waveLen, float leftSide, - float rightSide); +//float floatmod(float value, float divider); +//int waveState(time_t start, time_t now, float waveLen, float leftSide, +// float rightSide); #endif /* WAVE_MATH_H_ */