diff --git a/firmware/.cproject b/firmware/.cproject
index 86ebb61d2e..e01fca04ca 100644
--- a/firmware/.cproject
+++ b/firmware/.cproject
@@ -140,6 +140,10 @@
+
+
@@ -299,6 +303,10 @@
+
+
diff --git a/firmware/.gitignore b/firmware/.gitignore
deleted file mode 100644
index 4bc7ebb9e9..0000000000
--- a/firmware/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-.dep
-build
\ No newline at end of file
diff --git a/firmware/Makefile b/firmware/Makefile
index ad6e471136..3fcf139b46 100644
--- a/firmware/Makefile
+++ b/firmware/Makefile
@@ -293,7 +293,8 @@ ULIBS = -lm
##############################################################################
ifeq ($(USE_FPU),yes)
- USE_OPT += -mfloat-abi=hard -mfpu=fpv4-sp-d16 -fsingle-precision-constant
+ USE_OPT += -mfloat-abi=hard -mfpu=fpv4-sp-d16 -fsingle-precision-constant
+ USE_CPPOPT += -mfloat-abi=hard -mfpu=fpv4-sp-d16 -fsingle-precision-constant
DDEFS += -DCORTEX_USE_FPU=TRUE
else
DDEFS += -DCORTEX_USE_FPU=FALSE
diff --git a/firmware/config/boards/arro_board.h b/firmware/config/boards/arro_board.h
index f2da18c654..2d480c0859 100644
--- a/firmware/config/boards/arro_board.h
+++ b/firmware/config/boards/arro_board.h
@@ -60,19 +60,11 @@
#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6)
#define EFI_CAN_DEVICE CAND2
-#define EFI_CAN_RX_PORT GPIOB
-#define EFI_CAN_RX_PIN 12
#define EFI_CAN_RX_AF 9
-#define EFI_CAN_TX_PORT GPIOB
-#define EFI_CAN_TX_PIN 6
#define EFI_CAN_TX_AF 9
//#define EFI_CAN_DEVICE CAND1
-//#define EFI_CAN_RX_PORT GPIOB
-//#define EFI_CAN_RX_PIN 8
//#define EFI_CAN_RX_AF 9
-//#define EFI_CAN_TX_PORT GPIOB
-//#define EFI_CAN_TX_PIN 9
//#define EFI_CAN_TX_AF 9
/**
@@ -230,4 +222,10 @@
#define GPS_SERIAL_TX_PIN 6
#define GPS_SERIAL_RX_PIN 7
+#define CONSOLE_MODE_SWITCH_PORT GPIOB
+#define CONSOLE_MODE_SWITCH_PIN 1
+
+#define CONFIG_RESET_SWITCH_PORT GPIOD
+#define CONFIG_RESET_SWITCH_PIN 6
+
#endif /*ARRO_BOARD_H_*/
diff --git a/firmware/config/efifeatures.h b/firmware/config/efifeatures.h
index 11cc662b57..0bb4526766 100644
--- a/firmware/config/efifeatures.h
+++ b/firmware/config/efifeatures.h
@@ -105,17 +105,17 @@
#define EFI_SUPPORT_NISSAN_PRIMERA TRUE
#define EFI_SUPPORT_1995_FORD_INLINE_6 TRUE
+#define EFI_WAVE_CHART TRUE
+
+#define EFI_HISTOGRAMS TRUE
+#define EFI_ANALOG_CHART TRUE
+
#if defined __GNUC__
#define EFI_PERF_METRICS TRUE
-#define EFI_ANALOG_CHART TRUE
-#define EFI_WAVE_CHART TRUE
#define DL_OUTPUT_BUFFER 9000
#else
-// todo: CCM usage for IAR?
#define EFI_PERF_METRICS FALSE
-#define EFI_ANALOG_CHART FALSE
-#define EFI_WAVE_CHART FALSE
-#define DL_OUTPUT_BUFFER 6000
+#define DL_OUTPUT_BUFFER 9000
#endif
/**
diff --git a/firmware/config/engines/GY6_139QMB.cpp b/firmware/config/engines/GY6_139QMB.cpp
index 59994cbe8e..82257d2bdf 100644
--- a/firmware/config/engines/GY6_139QMB.cpp
+++ b/firmware/config/engines/GY6_139QMB.cpp
@@ -14,7 +14,7 @@ void setGy6139qmbDefaultEngineConfiguration(engine_configuration_s *engineConfig
engineConfiguration->rpmHardLimit = 9000;
engineConfiguration->crankingSettings.crankingRpm = 800;
engineConfiguration->analogInputDividerCoefficient = 1.52;
- engineConfiguration->engineLoadMode = LM_MAP;
+ engineConfiguration->algorithm = LM_MAP;
engineConfiguration->globalTriggerAngleOffset = 15;
engineConfiguration->analogChartMode = AC_MAP;
engineConfiguration->cylindersCount = 1;
@@ -27,6 +27,6 @@ void setGy6139qmbDefaultEngineConfiguration(engine_configuration_s *engineConfig
*/
engineConfiguration->triggerConfig.totalToothCount = 1;
engineConfiguration->triggerConfig.skippedToothCount = 0;
- engineConfiguration->triggerConfig.isSynchronizationNeeded = FALSE;
- engineConfiguration->needSecondTriggerInput = FALSE;
+ engineConfiguration->triggerConfig.isSynchronizationNeeded = false;
+ engineConfiguration->needSecondTriggerInput = false;
}
diff --git a/firmware/config/engines/audi_aan.cpp b/firmware/config/engines/audi_aan.cpp
index 1b299d356a..720bd3818b 100644
--- a/firmware/config/engines/audi_aan.cpp
+++ b/firmware/config/engines/audi_aan.cpp
@@ -28,7 +28,7 @@
extern engine_configuration2_s engineConfiguration2;
-void configureShaftPositionEmulatorShape(PwmConfig *state) {
+static void configureShaftPositionEmulatorShapeWhat(PwmConfig *state) {
/**
* One signal per cam shaft revolution
*/
@@ -40,11 +40,6 @@ void configureShaftPositionEmulatorShape(PwmConfig *state) {
weComplexInit("distributor", state, 0, 2, switchTimes, 1, pinStates);
}
-void configureEngineEventHandler(EventHandlerConfiguration *config) {
- registerActuatorEvent(&config->ignitionEvents, 0, 1, 0);
- registerActuatorEvent(&config->ignitionEvents, 0, 2, 90);
-}
-
void setDefaultEngineConfiguration(EngineConfiguration *engineConfiguration) {
engineConfiguration2.shaftPositionEventCount = 2;
}
diff --git a/firmware/config/engines/citroenBerlingoTU3JP.cpp b/firmware/config/engines/citroenBerlingoTU3JP.cpp
index cb94335732..ff28d5f41a 100644
--- a/firmware/config/engines/citroenBerlingoTU3JP.cpp
+++ b/firmware/config/engines/citroenBerlingoTU3JP.cpp
@@ -1,7 +1,10 @@
/**
* @file citroenBerlingoTU3JP.cpp
*
- * CITROEN_TU3JP 15
+ * CITROEN_TU3JP: engine_type 15
+ *
+ * This config overrides some values of the default configuration which is set by setDefaultConfiguration() method
+ *
*
* @date Apr 15, 2014
* @author Andrey Belomutskiy, (c) 2012-2014
@@ -12,9 +15,11 @@
void setCitroenBerlingoTU3JPConfiguration(engine_configuration_s *engineConfiguration, board_configuration_s *boardConfiguration) {
engineConfiguration->engineType = CITROEN_TU3JP;
- engineConfiguration->triggerConfig.triggerType = TT_TOOTHED_WHEEL;
- engineConfiguration->triggerConfig.totalToothCount = 60;
- engineConfiguration->triggerConfig.skippedToothCount = 2;
+ //engineConfiguration->triggerConfig.triggerType = todo 60_2
+
+ setToothedWheelConfiguration(engineConfiguration, 60, 2);
+
+ setTriggerSynchronizationGap(&engineConfiguration->triggerConfig, 2.5);
// set_cranking_injection_mode 0
diff --git a/firmware/config/engines/dodge_neon.cpp b/firmware/config/engines/dodge_neon.cpp
index 68e2290391..7a8b918ee6 100644
--- a/firmware/config/engines/dodge_neon.cpp
+++ b/firmware/config/engines/dodge_neon.cpp
@@ -3,6 +3,8 @@
*
* DODGE_NEON_1995 = 2
*
+ * This config overrides some values of the default configuration which is set by setDefaultConfiguration() method
+ *
* @date Dec 16, 2013
* @author Andrey Belomutskiy, (c) 2012-2014
*/
@@ -21,7 +23,7 @@ void setDodgeNeonEngineConfiguration(engine_configuration_s *engineConfiguration
engineConfiguration->triggerConfig.triggerType = TT_DODGE_NEON;
- engineConfiguration->engineLoadMode = LM_TPS;
+ engineConfiguration->algorithm = LM_TPS;
// set_rpm_hard_limit 4000
engineConfiguration->rpmHardLimit = 4000; // yes, 4k. let's play it safe for now
@@ -40,10 +42,10 @@ void setDodgeNeonEngineConfiguration(engine_configuration_s *engineConfiguration
// set_whole_fuel_map 3
setWholeFuelMap(engineConfiguration, 3);
- setTriggerSynchronizationGap(engineConfiguration, 0.72);
+ setTriggerSynchronizationGap(&engineConfiguration->triggerConfig, 0.72);
- engineConfiguration->triggerConfig.useRiseEdge = FALSE;
- engineConfiguration->needSecondTriggerInput = TRUE;
+ engineConfiguration->triggerConfig.useRiseEdge = false;
+ engineConfiguration->needSecondTriggerInput = true;
// set_cranking_injection_mode 0
engineConfiguration->crankingInjectionMode = IM_SIMULTANEOUS;
diff --git a/firmware/config/engines/ford_1995_inline_6.cpp b/firmware/config/engines/ford_1995_inline_6.cpp
index 18b670125c..29c5106f45 100644
--- a/firmware/config/engines/ford_1995_inline_6.cpp
+++ b/firmware/config/engines/ford_1995_inline_6.cpp
@@ -4,6 +4,8 @@
*
* http://rusefi.com/forum/viewtopic.php?f=3&t=469
*
+ * This config overrides some values of the default configuration which is set by setDefaultConfiguration() method
+ *
* FORD_INLINE_6_1995 = 7
*
* @date Feb 12, 2014
@@ -38,12 +40,9 @@ void setFordInline6(engine_configuration_s *engineConfiguration, board_configura
/**
* We treat the trigger as 6/0 toothed wheel
*/
- engineConfiguration->triggerConfig.triggerType = TT_TOOTHED_WHEEL;
- engineConfiguration->triggerConfig.totalToothCount = 6;
- engineConfiguration->triggerConfig.skippedToothCount = 0;
- engineConfiguration->triggerConfig.isSynchronizationNeeded = FALSE;
+ setToothedWheelConfiguration(engineConfiguration, 6, 0);
engineConfiguration->triggerConfig.useRiseEdge = TRUE;
- engineConfiguration->needSecondTriggerInput = FALSE;
+ engineConfiguration->needSecondTriggerInput = false;
engineConfiguration->globalTriggerAngleOffset = 0;
engineConfiguration->ignitionOffset = 13;
diff --git a/firmware/config/engines/ford_aspire.cpp b/firmware/config/engines/ford_aspire.cpp
index 24459b1f4d..85994be13e 100644
--- a/firmware/config/engines/ford_aspire.cpp
+++ b/firmware/config/engines/ford_aspire.cpp
@@ -119,8 +119,7 @@ void setFordAspireEngineConfiguration(engine_configuration_s *engineConfiguratio
setSingleCoilDwell(engineConfiguration);
engineConfiguration->ignitionMode = IM_ONE_COIL;
engineConfiguration->triggerConfig.triggerType = TT_FORD_ASPIRE;
- engineConfiguration->triggerConfig.isSynchronizationNeeded = FALSE;
-
+ engineConfiguration->triggerConfig.isSynchronizationNeeded = false;
boardConfiguration->injectionPins[4] = GPIO_NONE;
boardConfiguration->injectionPins[5] = GPIO_NONE;
diff --git a/firmware/config/engines/ford_escort_gt.cpp b/firmware/config/engines/ford_escort_gt.cpp
index 3eb4a1ebcf..0c905feb3d 100644
--- a/firmware/config/engines/ford_escort_gt.cpp
+++ b/firmware/config/engines/ford_escort_gt.cpp
@@ -23,8 +23,6 @@ void setFordEscortGt(engine_configuration_s *engineConfiguration, board_configur
// set_injection_offset 510
engineConfiguration->injectionOffset = 59;
-
-
setSingleCoilDwell(engineConfiguration);
engineConfiguration->ignitionMode = IM_ONE_COIL;
diff --git a/firmware/config/engines/ford_fiesta.cpp b/firmware/config/engines/ford_fiesta.cpp
index ef6bc214e8..47132ac390 100644
--- a/firmware/config/engines/ford_fiesta.cpp
+++ b/firmware/config/engines/ford_fiesta.cpp
@@ -20,8 +20,7 @@ void setFordFiestaDefaultEngineConfiguration(engine_configuration_s *engineConfi
engineConfiguration->rpmHardLimit = 7000;
setOperationMode(engineConfiguration, FOUR_STROKE_CRANK_SENSOR);
- engineConfiguration->triggerConfig.totalToothCount = 36;
- engineConfiguration->triggerConfig.skippedToothCount = 1;
+ setToothedWheelConfiguration(engineConfiguration, 36, 1);
engineConfiguration->ignitionMode = IM_WASTED_SPARK;
engineConfiguration->firingOrder = FO_1_THEN_3_THEN_4_THEN2;
diff --git a/firmware/config/engines/mazda_323.cpp b/firmware/config/engines/mazda_323.cpp
index be62f2406b..cce9d64e9a 100644
--- a/firmware/config/engines/mazda_323.cpp
+++ b/firmware/config/engines/mazda_323.cpp
@@ -16,8 +16,5 @@ void setMazda323EngineConfiguration(engine_configuration_s *engineConfiguration)
/**
* We treat the trigger as 4/0 toothed wheel
*/
- engineConfiguration->triggerConfig.totalToothCount = 4;
- engineConfiguration->triggerConfig.skippedToothCount = 0;
- engineConfiguration->triggerConfig.isSynchronizationNeeded = FALSE;
-
+ setToothedWheelConfiguration(engineConfiguration, 4, 0);
}
diff --git a/firmware/config/engines/mazda_miata_nb.cpp b/firmware/config/engines/mazda_miata_nb.cpp
index fc130e9bd3..ef9478f1a0 100644
--- a/firmware/config/engines/mazda_miata_nb.cpp
+++ b/firmware/config/engines/mazda_miata_nb.cpp
@@ -17,8 +17,8 @@ void setMazdaMiataNbEngineConfiguration(engine_configuration_s *engineConfigurat
engineConfiguration->triggerConfig.triggerType = TT_MAZDA_MIATA_NB;
- setTriggerSynchronizationGap(engineConfiguration, 0.11);
- engineConfiguration->triggerConfig.useRiseEdge = FALSE;
+ setTriggerSynchronizationGap(&engineConfiguration->triggerConfig, 0.11);
+ engineConfiguration->triggerConfig.useRiseEdge = false;
engineConfiguration->globalTriggerAngleOffset = 276;
// set_cranking_injection_mode 0
diff --git a/firmware/config/engines/nissan_primera.cpp b/firmware/config/engines/nissan_primera.cpp
index 0f8ca08670..460d559d1e 100644
--- a/firmware/config/engines/nissan_primera.cpp
+++ b/firmware/config/engines/nissan_primera.cpp
@@ -13,8 +13,7 @@
#include "nissan_primera.h"
void setNissanPrimeraEngineConfiguration(engine_configuration_s *engineConfiguration) {
- engineConfiguration->triggerConfig.totalToothCount = 60;
- engineConfiguration->triggerConfig.skippedToothCount = 2;
+ setToothedWheelConfiguration(engineConfiguration, 60, 2);
}
#endif /* EFI_SUPPORT_NISSAN_PRIMERA */
diff --git a/firmware/config/engines/rover_v8.cpp b/firmware/config/engines/rover_v8.cpp
index 1e33f1ec27..10f8665cb6 100644
--- a/firmware/config/engines/rover_v8.cpp
+++ b/firmware/config/engines/rover_v8.cpp
@@ -3,6 +3,8 @@
*
* V8, firing order 18436572
*
+ * This config overrides some values of the default configuration which is set by setDefaultConfiguration() method
+ *
* ROVER_V8 = 10
*
* @date Jun 27, 2014
@@ -16,11 +18,9 @@ void setRoverv8(engine_configuration_s *engineConfiguration,
board_configuration_s *boardConfiguration) {
setOperationMode(engineConfiguration, FOUR_STROKE_CRANK_SENSOR);
- engineConfiguration->triggerConfig.totalToothCount = 36;
- engineConfiguration->triggerConfig.skippedToothCount = 1;
+ setToothedWheelConfiguration(engineConfiguration, 36, 1);
- // todo: displacement? 4 liters?
- engineConfiguration->displacement = 4;
+ engineConfiguration->displacement = 3.528;
engineConfiguration->cylindersCount = 8;
engineConfiguration->firingOrder = FO_1_8_4_3_6_5_7_2;
@@ -33,8 +33,8 @@ void setRoverv8(engine_configuration_s *engineConfiguration,
setWholeFuelMap(engineConfiguration, 3);
- // set_cranking_injection_mode 0
- engineConfiguration->crankingInjectionMode = IM_SEQUENTIAL;
+ // set_cranking_injection_mode 0
+ engineConfiguration->crankingInjectionMode = IM_SIMULTANEOUS;
// set_injection_mode 1
engineConfiguration->injectionMode = IM_SEQUENTIAL;
diff --git a/firmware/console/console_io.c b/firmware/console/console_io.c
index 445d4f6871..a6b8fd472d 100644
--- a/firmware/console/console_io.c
+++ b/firmware/console/console_io.c
@@ -31,7 +31,7 @@ extern SerialUSBDriver SDU1;
int lastWriteSize;
int lastWriteActual;
-static bool_t isSerialConsoleStarted = FALSE;
+static bool isSerialConsoleStarted = false;
static EventListener consoleEventListener;
@@ -99,7 +99,7 @@ static bool getConsoleLine(BaseSequentialStream *chp, char *line, unsigned size)
consolePutChar('\r');
consolePutChar('\n');
*p = 0;
- return FALSE;
+ return false;
}
if (c < 0x20)
continue;
@@ -136,7 +136,7 @@ static msg_t consoleThreadThreadEntryPoint(void *arg) {
(console_line_callback)(consoleInput);
}
#if defined __GNUC__
- return FALSE;
+ return false;
#endif
}
@@ -182,7 +182,10 @@ void startConsole(void (*console_line_callback_p)(char *)) {
console_line_callback = console_line_callback_p;
#if EFI_PROD_CODE
- is_serial_over_uart = palReadPad(GPIOA, GPIOA_BUTTON) != EFI_USE_UART_FOR_CONSOLE;
+
+ palSetPadMode(CONSOLE_MODE_SWITCH_PORT, CONSOLE_MODE_SWITCH_PIN, PAL_MODE_INPUT_PULLUP);
+
+ is_serial_over_uart = GET_CONSOLE_MODE_VALUE() == EFI_USE_UART_FOR_CONSOLE;
if (isSerialOverUart()) {
/*
@@ -221,10 +224,10 @@ bool lockAnyContext(void) {
chSysLock()
;
}
- return FALSE;
+ return false;
}
-bool_t lockOutputBuffer(void) {
+bool lockOutputBuffer(void) {
return lockAnyContext();
}
diff --git a/firmware/console/console_io.h b/firmware/console/console_io.h
index c36dd8395a..935751fad2 100644
--- a/firmware/console/console_io.h
+++ b/firmware/console/console_io.h
@@ -21,6 +21,9 @@
#include "efifeatures.h"
#include "boards.h"
+#define GET_CONSOLE_MODE_VALUE() palReadPad(CONSOLE_MODE_SWITCH_PORT, CONSOLE_MODE_SWITCH_PIN)
+#define SHOULD_INGORE_FLASH() (palReadPad(CONFIG_RESET_SWITCH_PORT, CONFIG_RESET_SWITCH_PIN) == 0)
+
#ifdef __cplusplus
extern "C"
{
diff --git a/firmware/console/status_loop.cpp b/firmware/console/status_loop.cpp
index 8b1aea486a..d71b48fb1b 100644
--- a/firmware/console/status_loop.cpp
+++ b/firmware/console/status_loop.cpp
@@ -161,7 +161,6 @@ void printState(int currentCkpEventCounter) {
int rpm = getRpm();
debugInt(&logger, "ckp_c", currentCkpEventCounter);
- debugInt(&logger, "fuel_lag", getRevolutionCounter());
// debugInt(&logger, "idl", getIdleSwitch());
@@ -171,7 +170,7 @@ void printState(int currentCkpEventCounter) {
debugFloat(&logger, "fuel_base", getBaseFuel(rpm, engineLoad), 2);
// debugFloat(&logger, "fuel_iat", getIatCorrection(getIntakeAirTemperature()), 2);
// debugFloat(&logger, "fuel_clt", getCltCorrection(getCoolantTemperature()), 2);
-// debugFloat(&logger, "fuel_lag", getInjectorLag(getVBatt()), 2);
+ debugFloat(&logger, "fuel_lag", getInjectorLag(getVBatt()), 2);
debugFloat(&logger, "fuel", getRunningFuel(rpm, engineLoad), 2);
debugFloat(&logger, "timing", getAdvance(rpm, engineLoad), 2);
@@ -298,26 +297,27 @@ void updateDevConsoleState(void) {
* that would be 'show fuel for rpm 3500 maf 4.0'
*/
-static void showFuelMap(int rpm, int key100) {
- float engineLoad = key100 / 100.0;
-
+static void showFuelMap2(float rpm, float engineLoad) {
float baseFuel = getBaseFuel(rpm, engineLoad);
float iatCorrection = getIatCorrection(getIntakeAirTemperature());
float cltCorrection = getCltCorrection(getCoolantTemperature());
float injectorLag = getInjectorLag(getVBatt());
- print("baseFuel=%f\r\n", baseFuel);
+ scheduleMsg(&logger2, "rpm=%f engineLoad=%f", rpm, engineLoad);
+ scheduleMsg(&logger2, "baseFuel=%f", baseFuel);
- print("iatCorrection=%f cltCorrection=%f injectorLag=%d\r\n", iatCorrection, cltCorrection,
- (int) (100 * injectorLag));
+ scheduleMsg(&logger2, "iatCorrection=%f cltCorrection=%f injectorLag=%f", iatCorrection, cltCorrection,
+ injectorLag);
float value = getRunningFuel(rpm, engineLoad);
-
- print("fuel map rpm=%d, key=%f: %d\r\n", rpm, engineLoad, (int) (100 * value));
-
- scheduleMsg(&logger2, "fuel map value = %f", value);
+ scheduleMsg(&logger2, "injection pulse width: %f", value);
}
+static void showFuelMap(void) {
+ showFuelMap2(getRpm(), getEngineLoad());
+}
+
+
static char buffer[10];
static char dateBuffer[30];
@@ -415,7 +415,8 @@ void initStatusLoop(void) {
#if EFI_PROD_CODE
initLogging(&logger2, "main event handler");
- addConsoleActionII("sfm", showFuelMap);
+ addConsoleActionFF("fuelinfo2", showFuelMap2);
+ addConsoleAction("fuelinfo", showFuelMap);
addConsoleAction("status", printStatus);
#endif /* EFI_PROD_CODE */
diff --git a/firmware/console/tunerstudio/tunerstudio.c b/firmware/console/tunerstudio/tunerstudio.c
index 2d9e7cfdc2..af6edc1ee5 100644
--- a/firmware/console/tunerstudio/tunerstudio.c
+++ b/firmware/console/tunerstudio/tunerstudio.c
@@ -26,12 +26,9 @@
#include "engine_state.h"
#include "tunerstudio.h"
-#include "pin_repository.h"
#include "main_trigger_callback.h"
#include "flash_main.h"
-#include "usbconsole.h"
-#include "map_averaging.h"
#include "tunerstudio_algo.h"
#include "tunerstudio_configuration.h"
@@ -42,27 +39,40 @@
#if EFI_TUNER_STUDIO
-#define MAX_PAGE_ID 5
-#define PAGE_0_SIZE 1356
-
-// in MS, that's 10 seconds
-#define TS_READ_TIMEOUT 10000
+#if EFI_PROD_CODE
+#include "pin_repository.h"
+#include "usbconsole.h"
+#include "map_averaging.h"
+extern SerialUSBDriver SDU1;
+#define CONSOLE_DEVICE &SDU1
#define TS_SERIAL_UART_DEVICE &SD3
//#define TS_SERIAL_SPEED 115200
#define TS_SERIAL_SPEED 38400
+static SerialConfig tsSerialConfig = { TS_SERIAL_SPEED, 0, USART_CR2_STOP1_BITS | USART_CR2_LINEN, 0 };
+#endif /* EFI_PROD_CODE */
+
+#define MAX_PAGE_ID 0
+#define PAGE_0_SIZE 5804
+
+// in MS, that's 10 seconds
+#define TS_READ_TIMEOUT 10000
+
#define PROTOCOL "001"
-extern SerialUSBDriver SDU1;
BaseChannel * getTsSerialDevice(void) {
+#if EFI_PROD_CODE
if (isSerialOverUart()) {
// if console uses UART then TS uses USB
return (BaseChannel *) &SDU1;
} else {
return (BaseChannel *) TS_SERIAL_UART_DEVICE;
}
+#else
+ return (BaseChannel *) TS_SIMULATOR_PORT;
+#endif
}
static Logging logger;
@@ -71,12 +81,10 @@ extern engine_configuration_s *engineConfiguration;
extern persistent_config_s configWorkingCopy;
extern persistent_config_container_s persistentState;
-extern SerialUSBDriver SDU1;
-#define CONSOLE_DEVICE &SDU1
-
static efitimems_t previousWriteReportMs = 0;
static int ts_serail_ready(void) {
+#if EFI_PROD_CODE
if (isSerialOverUart()) {
// TS uses USB when console uses serial
return is_usb_serial_ready();
@@ -84,10 +92,11 @@ static int ts_serail_ready(void) {
// TS uses serial when console uses USB
return TRUE;
}
+#else
+ return TRUE;
+#endif
}
-static SerialConfig tsSerialConfig = { TS_SERIAL_SPEED, 0, USART_CR2_STOP1_BITS | USART_CR2_LINEN, 0 };
-
static THD_WORKING_AREA(TS_WORKING_AREA, UTILITY_THREAD_STACK_SIZE);
static int tsCounter = 0;
@@ -100,10 +109,12 @@ extern TunerStudioOutputChannels tsOutputChannels;
extern TunerStudioState tsState;
static void printStats(void) {
+#if EFI_PROD_CODE
if (!isSerialOverUart()) {
scheduleMsg(&logger, "TS RX on %s%d", portname(TS_SERIAL_RX_PORT), TS_SERIAL_RX_PIN);
scheduleMsg(&logger, "TS TX on %s%d", portname(TS_SERIAL_TX_PORT), TS_SERIAL_TX_PIN);
}
+#endif /* EFI_PROD_CODE */
scheduleMsg(&logger, "TunerStudio total/error counter=%d/%d", tsCounter, tsState.errorCounter);
scheduleMsg(&logger, "TunerStudio H counter=%d", tsState.queryCommandCounter);
scheduleMsg(&logger, "TunerStudio O counter=%d size=%d", tsState.outputChannelsCommandCounter,
@@ -113,15 +124,34 @@ static void printStats(void) {
scheduleMsg(&logger, "TunerStudio W counter=%d", tsState.writeValueCommandCounter);
scheduleMsg(&logger, "TunerStudio C counter=%d", tsState.writeChunkCommandCounter);
scheduleMsg(&logger, "TunerStudio P counter=%d current page %d", tsState.pageCommandCounter, tsState.currentPageId);
+ scheduleMsg(&logger, "pages total size=%d", sizeof(engine_configuration_s));
scheduleMsg(&logger, "page 0 size=%d", getTunerStudioPageSize(0));
scheduleMsg(&logger, "page 1 size=%d", getTunerStudioPageSize(1));
+
+// scheduleMsg(&logger, "timingMode %d", (int)(&engineConfiguration->timingMode) - (int)engineConfiguration);
+// scheduleMsg(&logger, "cylindersCount %d", (int)(&engineConfiguration->cylindersCount) - (int)engineConfiguration);
+ scheduleMsg(&logger, "analogChartFrequency %d",
+ (int) (&engineConfiguration->analogChartFrequency) - (int) engineConfiguration);
+
+ int fuelMapOffset = (int) (&engineConfiguration->fuelTable) - (int) engineConfiguration;
+ scheduleMsg(&logger, "fuelTable %d", fuelMapOffset);
+
+ int offset = (int) (&engineConfiguration->bc.injectionPinMode) - (int) engineConfiguration;
+ scheduleMsg(&logger, "injectionPinMode %d", offset);
+
+ offset = (int) (&engineConfiguration->bc.idleThreadPeriod) - (int) engineConfiguration;
+ scheduleMsg(&logger, "idleThreadPeriod %d", offset);
+
+
+ if (sizeof(engine_configuration_s) != getTunerStudioPageSize(0))
+ firmwareError("TS page size mismatch");
}
void tunerStudioWriteData(const uint8_t * buffer, int size) {
chSequentialStreamWrite(getTsSerialDevice(), buffer, size);
}
-void tunerStudioDebug(char *msg) {
+void tunerStudioDebug(const char *msg) {
#if EFI_TUNER_STUDIO_VERBOSE
scheduleMsg(&logger, "%s", msg);
printStats();
@@ -132,13 +162,13 @@ char *getWorkingPageAddr(int pageIndex) {
switch (pageIndex) {
case 0:
return (char*) &configWorkingCopy.engineConfiguration;
- case 1:
- return (char*) &configWorkingCopy.boardConfiguration;
- case 2: // fuelTable
- case 3: // ignitionTable
- case 4: // veTable
- case 5: // afrTable
- return (char*) &configWorkingCopy.engineConfiguration + PAGE_0_SIZE + (pageIndex - 2) * 1024;
+// case 1:
+// return (char*) &configWorkingCopy.boardConfiguration;
+// case 2: // fuelTable
+// case 3: // ignitionTable
+// case 4: // veTable
+// case 5: // afrTable
+// return (char*) &configWorkingCopy.engineConfiguration + PAGE_0_SIZE + (pageIndex - 2) * 1024;
}
return NULL;
}
@@ -147,58 +177,56 @@ int getTunerStudioPageSize(int pageIndex) {
switch (pageIndex) {
case 0:
return PAGE_0_SIZE;
- case 1:
- return sizeof(configWorkingCopy.boardConfiguration);
- case 2:
- case 3:
- case 4:
- return 1024;
+// case 1:
+// return sizeof(configWorkingCopy.boardConfiguration);
+// case 2:
+// case 3:
+// case 4:
+// return 1024;
}
return 0;
}
-void handlePageSelectCommand(uint16_t pageId) {
+void handlePageSelectCommand(ts_response_format_e mode, uint16_t pageId) {
tsState.pageCommandCounter++;
tsState.currentPageId = pageId;
scheduleMsg(&logger, "page %d selected", tsState.currentPageId);
- tunerStudioWriteCrcPacket(TS_RESPONSE_OK, NULL, 0);
+ tsSendResponse(mode, NULL, 0);
}
/**
* This command is needed to make the whole transfer a bit faster
* @note See also handleWriteValueCommand
*/
-void handleWriteChunkCommand(short offset, short count, void *content) {
+void handleWriteChunkCommand(ts_response_format_e mode, short offset, short count, void *content) {
tsState.writeChunkCommandCounter++;
scheduleMsg(&logger, "receiving page %d chunk offset %d size %d", tsState.currentPageId, offset, count);
if (offset > getTunerStudioPageSize(tsState.currentPageId)) {
scheduleMsg(&logger, "ERROR offset %d", offset);
- // out of range
- tsState.errorCounter++;
+ tunerStudioError("ERROR: out of range");
offset = 0;
}
if (count > getTunerStudioPageSize(tsState.currentPageId)) {
+ tunerStudioError("ERROR: unexpected count");
scheduleMsg(&logger, "ERROR count %d", count);
- // out of range
- tsState.errorCounter++;
count = 0;
}
uint8_t * addr = (uint8_t *) (getWorkingPageAddr(tsState.currentPageId) + offset);
-// memcpy(addr, content, count);
+ memcpy(addr, content, count);
- tunerStudioWriteCrcPacket(TS_RESPONSE_OK, NULL, 0);
+ tsSendResponse(mode, NULL, 0);
}
/**
* 'Write' command receives a single value at a given offset
* @note Writing values one by one is pretty slow
*/
-void handleWriteValueCommand(uint16_t page, uint16_t offset, uint8_t value) {
+void handleWriteValueCommand(ts_response_format_e mode, uint16_t page, uint16_t offset, uint8_t value) {
tsState.writeValueCommandCounter++;
tsState.currentPageId = page;
@@ -213,9 +241,8 @@ void handleWriteValueCommand(uint16_t page, uint16_t offset, uint8_t value) {
// scheduleMsg(&logger, "Reading %d\r\n", size);
if (offset > getTunerStudioPageSize(tsState.currentPageId)) {
+ tunerStudioError("ERROR: out of range2");
scheduleMsg(&logger, "ERROR offset %d", offset);
- // out of range
- tsState.errorCounter++;
offset = 0;
return;
}
@@ -235,7 +262,7 @@ static void sendErrorCode(void) {
tunerStudioWriteCrcPacket(TS_RESPONSE_CRC_FAILURE, NULL, 0);
}
-void handlePageReadCommand(uint16_t pageId, uint16_t offset, uint16_t count) {
+void handlePageReadCommand(ts_response_format_e mode, uint16_t pageId, uint16_t offset, uint16_t count) {
tsState.readPageCommandsCounter++;
tunerStudioDebug("got R (Read page)");
tsState.currentPageId = pageId;
@@ -249,7 +276,7 @@ void handlePageReadCommand(uint16_t pageId, uint16_t offset, uint16_t count) {
// something is not right here
tsState.currentPageId = 0;
- tsState.errorCounter++;
+ tunerStudioError("ERROR: invalid page");
return;
}
@@ -262,16 +289,16 @@ void handlePageReadCommand(uint16_t pageId, uint16_t offset, uint16_t count) {
}
const uint8_t *addr = (const uint8_t *) (getWorkingPageAddr(tsState.currentPageId) + offset);
- tunerStudioWriteCrcPacket(TS_RESPONSE_OK, addr, count);
+ tsSendResponse(mode, addr, count);
#if EFI_TUNER_STUDIO_VERBOSE
- scheduleMsg(&logger, "Sending %d done", size);
+ scheduleMsg(&logger, "Sending %d done", count);
#endif
}
/**
* 'Burn' command is a command to commit the changes
*/
-void handleBurnCommand(uint16_t page) {
+void handleBurnCommand(ts_response_format_e mode, uint16_t page) {
tsState.burnCommandCounter++;
tunerStudioDebug("got B (Burn)");
@@ -285,14 +312,59 @@ void handleBurnCommand(uint16_t page) {
// todo: how about some multi-threading?
memcpy(&persistentState.persistentConfiguration, &configWorkingCopy, sizeof(persistent_config_s));
- scheduleMsg(&logger, "va1=%d", configWorkingCopy.boardConfiguration.idleValvePin);
- scheduleMsg(&logger, "va2=%d", persistentState.persistentConfiguration.boardConfiguration.idleValvePin);
+ scheduleMsg(&logger, "va1=%d", configWorkingCopy.engineConfiguration.bc.idleValvePin);
+ scheduleMsg(&logger, "va2=%d", persistentState.persistentConfiguration.engineConfiguration.bc.idleValvePin);
+#if EFI_INTERNAL_FLASH
writeToFlash();
+#endif
incrementGlobalConfigurationVersion();
tunerStudioWriteCrcPacket(TS_RESPONSE_BURN_OK, NULL, 0);
}
+static TunerStudioReadRequest readRequest;
+static short int pageIn;
+
+static bool handlePlainCommand(uint8_t command) {
+ if (command == TS_HELLO_COMMAND) {
+ scheduleMsg(&logger, "Got naked Query command");
+ handleQueryCommand(TS_PLAIN);
+ return true;
+ } else if (command == 't' || command == 'T') {
+ handleTestCommand();
+ return true;
+ } else if (command == TS_PAGE_COMMAND) {
+ int recieved = chSequentialStreamRead(getTsSerialDevice(), (uint8_t *)&pageIn, sizeof(pageIn));
+ handlePageSelectCommand(TS_PLAIN, pageIn);
+ return true;
+ } else if (command == TS_READ_COMMAND) {
+ //scheduleMsg(&logger, "Got naked READ PAGE???");
+ int recieved = chSequentialStreamRead(getTsSerialDevice(), (uint8_t *)&readRequest, sizeof(readRequest));
+ if (recieved != sizeof(readRequest)) {
+ // todo: handler error
+ return true;
+ }
+ handlePageReadCommand(TS_PLAIN, readRequest.page, readRequest.offset, readRequest.count);
+ return true;
+ } else if (command == TS_OUTPUT_COMMAND) {
+ //scheduleMsg(&logger, "Got naked Channels???");
+ handleOutputChannelsCommand(TS_PLAIN);
+ return true;
+ } else if (command == 'F') {
+ tunerStudioDebug("not ignoring F");
+ tunerStudioWriteData((const uint8_t *) PROTOCOL, strlen(PROTOCOL));
+ return true;
+ } else {
+ return false;
+ }
+}
+
+static bool isKnownCommand(char command) {
+ return command == TS_HELLO_COMMAND || command == TS_READ_COMMAND || command == TS_OUTPUT_COMMAND
+ || command == TS_PAGE_COMMAND || command == TS_BURN_COMMAND || command == TS_SINGLE_WRITE_COMMAND
+ || command == TS_CHUNK_WRITE_COMMAND;
+}
+
static uint8_t firstByte;
static uint8_t secondByte;
@@ -303,12 +375,12 @@ static msg_t tsThreadEntryPoint(void *arg) {
(void) arg;
chRegSetThreadName("tunerstudio thread");
- int wasReady = FALSE;
+ int wasReady = false;
while (true) {
int isReady = ts_serail_ready();
if (!isReady) {
chThdSleepMilliseconds(10);
- wasReady = FALSE;
+ wasReady = false;
continue;
}
@@ -321,32 +393,16 @@ static msg_t tsThreadEntryPoint(void *arg) {
int recieved = chSequentialStreamRead(getTsSerialDevice(), &firstByte, 1);
if (recieved != 1) {
- tsState.errorCounter++;
+ tunerStudioError("ERROR: no command");
continue;
}
// scheduleMsg(&logger, "Got first=%x=[%c]", firstByte, firstByte);
- if (firstByte == TS_HELLO_COMMAND) {
- scheduleMsg(&logger, "Got naked Query command");
- handleQueryCommand(FALSE);
+ if (handlePlainCommand(firstByte))
continue;
- } else if (firstByte == 't' || firstByte == 'T') {
- handleTestCommand();
- continue;
- } else if (firstByte == TS_READ_COMMAND) {
- scheduleMsg(&logger, "Got naked READ PAGE???");
- continue;
- } else if (firstByte == TS_OUTPUT_COMMAND) {
- scheduleMsg(&logger, "Got naked Channels???");
- continue;
- } else if (firstByte == 'F') {
- tunerStudioDebug("not ignoring F");
- tunerStudioWriteData((const uint8_t *) PROTOCOL, strlen(PROTOCOL));
- continue;
- }
recieved = chSequentialStreamRead(getTsSerialDevice(), &secondByte, 1);
if (recieved != 1) {
- tsState.errorCounter++;
+ tunerStudioError("ERROR: no second");
continue;
}
// scheduleMsg(&logger, "Got secondByte=%x=[%c]", secondByte, secondByte);
@@ -355,22 +411,19 @@ static msg_t tsThreadEntryPoint(void *arg) {
if (incomingPacketSize == 0 || incomingPacketSize > sizeof(crcIoBuffer)) {
scheduleMsg(&logger, "TunerStudio: invalid size: %d", incomingPacketSize);
- tsState.errorCounter++;
+ tunerStudioError("ERROR: size");
sendErrorCode();
continue;
}
recieved = chnReadTimeout(getTsSerialDevice(), crcIoBuffer, 1, MS2ST(TS_READ_TIMEOUT));
if (recieved != 1) {
- scheduleMsg(&logger, "did not receive command");
- tsState.errorCounter++;
+ tunerStudioError("ERROR: did not receive command");
continue;
}
char command = crcIoBuffer[0];
- if (command != TS_HELLO_COMMAND && command != TS_READ_COMMAND && command != TS_OUTPUT_COMMAND
- && command != TS_PAGE_COMMAND && command != TS_BURN_COMMAND && command != TS_SINGLE_WRITE_COMMAND
- && command != TS_CHUNK_WRITE_COMMAND) {
+ if (!isKnownCommand(command)) {
scheduleMsg(&logger, "unexpected command %x", command);
sendErrorCode();
continue;
@@ -380,9 +433,11 @@ static msg_t tsThreadEntryPoint(void *arg) {
recieved = chnReadTimeout(getTsSerialDevice(), (void * ) (crcIoBuffer + 1), incomingPacketSize + 4 - 1,
MS2ST(TS_READ_TIMEOUT));
- if (recieved != incomingPacketSize + 4 - 1) {
- scheduleMsg(&logger, "got ONLY %d", recieved);
- tsState.errorCounter++;
+ int expectedSize = incomingPacketSize + 4 - 1;
+ if (recieved != expectedSize) {
+ scheduleMsg(&logger, "got ONLY %d for packet size %d/%d for command %c", recieved, incomingPacketSize,
+ expectedSize, command);
+ tunerStudioError("ERROR: not enough");
continue;
}
@@ -398,14 +453,14 @@ static msg_t tsThreadEntryPoint(void *arg) {
scheduleMsg(&logger, "TunerStudio: command %c actual CRC %x/expected %x", crcIoBuffer[0], actualCrc,
expectedCrc);
- tsState.errorCounter++;
+ tunerStudioError("ERROR: CRC issue");
continue;
}
// scheduleMsg(&logger, "TunerStudio: P00-07 %x %x %x %x %x %x %x %x", crcIoBuffer[0], crcIoBuffer[1],
// crcIoBuffer[2], crcIoBuffer[3], crcIoBuffer[4], crcIoBuffer[5], crcIoBuffer[6], crcIoBuffer[7]);
- int success = tunerStudioHandleCommand(crcIoBuffer, incomingPacketSize);
+ int success = tunerStudioHandleCrcCommand(crcIoBuffer, incomingPacketSize);
if (!success)
print("got unexpected TunerStudio command %x:%c\r\n", command, command);
@@ -422,6 +477,7 @@ void syncTunerStudioCopy(void) {
void startTunerStudioConnectivity(void) {
initLogging(&logger, "tuner studio");
memset(&tsState, 0, sizeof(tsState));
+#if EFI_PROD_CODE
if (isSerialOverUart()) {
print("TunerStudio over USB serial");
usb_serial_start();
@@ -433,7 +489,7 @@ void startTunerStudioConnectivity(void) {
sdStart(TS_SERIAL_UART_DEVICE, &tsSerialConfig);
}
-
+#endif /* EFI_PROD_CODE */
syncTunerStudioCopy();
addConsoleAction("tsinfo", printStats);
diff --git a/firmware/console/tunerstudio/tunerstudio.h b/firmware/console/tunerstudio/tunerstudio.h
index b81b5114a0..219012b86a 100644
--- a/firmware/console/tunerstudio/tunerstudio.h
+++ b/firmware/console/tunerstudio/tunerstudio.h
@@ -10,39 +10,46 @@
#include "tunerstudio_configuration.h"
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+void startTunerStudioConnectivity(void);
+void syncTunerStudioCopy(void);
+void updateTunerStudioState(TunerStudioOutputChannels *tsOutputChannels);
+void tunerStudioWriteCrcPacket(const uint8_t command, const void *buf, const uint16_t size);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
#if defined __GNUC__
-typedef struct
- __attribute__((packed)) {
+// GCC
+#define pre_packed
+#define post_packed __attribute__((packed))
#else
- typedef __packed struct {
+// IAR
+#define pre_packed __packed
+#define post_packed
#endif
+
+typedef pre_packed struct
+ post_packed {
+ short int offset;
+ short int count;
+ } TunerStudioWriteChunkRequest;
+
+ typedef pre_packed struct
+ post_packed {
+ short int page;
short int offset;
short int count;
+ } TunerStudioReadRequest;
- } TunerStudioWriteChunkRequest;
-
-#if defined __GNUC__
-typedef struct
- __attribute__((packed)) {
-#else
- typedef __packed struct {
-#endif
-
- short int offset;
- unsigned char value;
- } TunerStudioWriteValueRequest;
-
-#ifdef __cplusplus
- extern "C" {
-#endif /* __cplusplus */
-
- void startTunerStudioConnectivity(void);
- void syncTunerStudioCopy(void);
- void updateTunerStudioState(TunerStudioOutputChannels *tsOutputChannels);
- void tunerStudioWriteCrcPacket(const uint8_t command, const void *buf, const uint16_t size);
-
-#ifdef __cplusplus
- }
-#endif /* __cplusplus */
+ typedef pre_packed struct
+ post_packed {
+ short int offset;
+ unsigned char value;
+ } TunerStudioWriteValueRequest;
#endif /* TUNERSTUDIO_H_ */
diff --git a/firmware/console/tunerstudio/tunerstudio.mk b/firmware/console/tunerstudio/tunerstudio.mk
index f347ca05cb..03cc87deda 100644
--- a/firmware/console/tunerstudio/tunerstudio.mk
+++ b/firmware/console/tunerstudio/tunerstudio.mk
@@ -1,3 +1,3 @@
-TUNERSTUDIOSRC = console/tunerstudio/tunerstudio_algo.c \
- console/tunerstudio/tunerstudio.c
+TUNERSTUDIOSRC = $(PROJECT_DIR)/console/tunerstudio/tunerstudio_algo.c \
+ $(PROJECT_DIR)/console/tunerstudio/tunerstudio.c
diff --git a/firmware/console/tunerstudio/tunerstudio_algo.c b/firmware/console/tunerstudio/tunerstudio_algo.c
index 7282d372db..a6e018f66b 100644
--- a/firmware/console/tunerstudio/tunerstudio_algo.c
+++ b/firmware/console/tunerstudio/tunerstudio_algo.c
@@ -65,34 +65,39 @@ TunerStudioOutputChannels tsOutputChannels;
*/
persistent_config_s configWorkingCopy;
-int tunerStudioHandleCommand(char *data, int incomingPacketSize) {
+void tunerStudioError(const char *msg) {
+ tunerStudioDebug(msg);
+ tsState.errorCounter++;
+}
+
+int tunerStudioHandleCrcCommand(char *data, int incomingPacketSize) {
char command = data[0];
data++;
if (command == TS_HELLO_COMMAND) {
tunerStudioDebug("got CRC Query");
- handleQueryCommand(TRUE);
+ handleQueryCommand(TS_CRC);
} else if (command == TS_OUTPUT_COMMAND) {
- handleOutputChannelsCommand();
+ handleOutputChannelsCommand(TS_CRC);
} else if (command == TS_PAGE_COMMAND) {
uint16_t page = *(uint16_t *) data;
- handlePageSelectCommand(page);
+ handlePageSelectCommand(TS_CRC, page);
} else if (command == TS_CHUNK_WRITE_COMMAND) {
uint16_t offset = *(uint16_t *) data;
uint16_t count = *(uint16_t *) (data + 2);
- handleWriteChunkCommand(offset, count, data + 4);
+ handleWriteChunkCommand(TS_CRC, offset, count, data + 4);
} else if (command == TS_SINGLE_WRITE_COMMAND) {
uint16_t page = *(uint16_t *) data;
uint16_t offset = *(uint16_t *) (data + 2);
uint8_t value = data[4];
- handleWriteValueCommand(page, offset, value);
+ handleWriteValueCommand(TS_CRC, page, offset, value);
} else if (command == TS_BURN_COMMAND) {
uint16_t page = *(uint16_t *) data;
- handleBurnCommand(page);
+ handleBurnCommand(TS_CRC, page);
} else if (command == TS_READ_COMMAND) {
uint16_t page = *(uint16_t *) data;
uint16_t offset = *(uint16_t *) (data + 2);
uint16_t count = *(uint16_t *) (data + 4);
- handlePageReadCommand(page, offset, count);
+ handlePageReadCommand(TS_CRC, page, offset, count);
} else if (command == 't' || command == 'T') {
handleTestCommand();
} else if (command == 'F') {
@@ -105,32 +110,38 @@ int tunerStudioHandleCommand(char *data, int incomingPacketSize) {
* Currently on some firmware versions the F command is not used and is just ignored by the firmware as a unknown command."
*/
} else {
- tunerStudioDebug("ignoring unexpected");
- tsState.errorCounter++;
+ tunerStudioError("ERROR: ignoring unexpected command");
return FALSE;
}
return TRUE;
}
-void handleQueryCommand(int needCrc) {
+void tsSendResponse(ts_response_format_e mode, const uint8_t * buffer, int size) {
+ if (mode == TS_CRC) {
+ tunerStudioWriteCrcPacket(TS_RESPONSE_OK, buffer, size);
+ } else {
+ if (size > 0)
+ tunerStudioWriteData(buffer, size);
+ }
+}
+
+/**
+ * Query with CRC takes place while re-establishing connection
+ * Query without CRC takes place on TunerStudio startup
+ */
+void handleQueryCommand(ts_response_format_e mode) {
tsState.queryCommandCounter++;
tunerStudioDebug("got H (queryCommand)");
- if (needCrc) {
- // Query with CRC takes place while re-establishing connection
- tunerStudioWriteCrcPacket(TS_RESPONSE_OK, (const uint8_t *) TS_SIGNATURE, strlen(TS_SIGNATURE) + 1);
- } else {
- // Query without CRC takes place on TunerStudio startup
- tunerStudioWriteData((const uint8_t *) TS_SIGNATURE, strlen(TS_SIGNATURE) + 1);
- }
+ tsSendResponse(mode, (const uint8_t *) TS_SIGNATURE, strlen(TS_SIGNATURE) + 1);
}
/**
* @brief 'Output' command sends out a snapshot of current values
*/
-void handleOutputChannelsCommand(void) {
+void handleOutputChannelsCommand(ts_response_format_e mode) {
tsState.outputChannelsCommandCounter++;
// this method is invoked too often to print any debug information
- tunerStudioWriteCrcPacket(TS_RESPONSE_OK, (const uint8_t *) &tsOutputChannels, sizeof(TunerStudioOutputChannels));
+ tsSendResponse(mode, (const uint8_t *) &tsOutputChannels, sizeof(TunerStudioOutputChannels));
}
void handleTestCommand(void) {
diff --git a/firmware/console/tunerstudio/tunerstudio_algo.h b/firmware/console/tunerstudio/tunerstudio_algo.h
index 478b9c6dab..1b57c2f9dd 100644
--- a/firmware/console/tunerstudio/tunerstudio_algo.h
+++ b/firmware/console/tunerstudio/tunerstudio_algo.h
@@ -24,6 +24,11 @@
#define TS_RESPONSE_BURN_OK 0x04
#define TS_RESPONSE_CRC_FAILURE 0x82
+typedef enum {
+ TS_PLAIN = 0,
+ TS_CRC = 1
+} ts_response_format_e;
+
typedef struct {
int queryCommandCounter;
int outputChannelsCommandCounter;
@@ -37,22 +42,25 @@ typedef struct {
short currentPageId;
} TunerStudioState;
-int tunerStudioHandleCommand(char *data, int incomingPacketSize);
+int tunerStudioHandleCrcCommand(char *data, int incomingPacketSize);
void handleTestCommand(void);
-void handleQueryCommand(int needCrc);
-void handleOutputChannelsCommand(void);
+void handleQueryCommand(ts_response_format_e mode);
+void tsSendResponse(ts_response_format_e mode, const uint8_t * buffer, int size);
+void handleOutputChannelsCommand(ts_response_format_e mode);
char *getWorkingPageAddr(int pageIndex);
int getTunerStudioPageSize(int pageIndex);
-void handleWriteValueCommand(uint16_t page, uint16_t offset, uint8_t value);
-void handleWriteChunkCommand(short offset, short count, void *content);
-void handlePageSelectCommand(uint16_t pageId);
-void handlePageReadCommand(uint16_t pageId, uint16_t offset, uint16_t count);
-void handleBurnCommand(uint16_t page);
+void handleWriteValueCommand(ts_response_format_e mode, uint16_t page, uint16_t offset, uint8_t value);
+void handleWriteChunkCommand(ts_response_format_e mode, short offset, short count, void *content);
+void handlePageSelectCommand(ts_response_format_e mode, uint16_t pageId);
+void handlePageReadCommand(ts_response_format_e mode, uint16_t pageId, uint16_t offset, uint16_t count);
+void handleBurnCommand(ts_response_format_e mode, uint16_t page);
void tunerStudioWriteData(const uint8_t * buffer, int size);
-void tunerStudioDebug(char *msg);
+void tunerStudioDebug(const char *msg);
+
+void tunerStudioError(const char *msg);
#define TS_HELLO_COMMAND 'H'
#define TS_OUTPUT_COMMAND 'O'
diff --git a/firmware/console_util/datalogging.c b/firmware/console_util/datalogging.c
index 8f6da7f70e..642ec658cb 100644
--- a/firmware/console_util/datalogging.c
+++ b/firmware/console_util/datalogging.c
@@ -66,8 +66,7 @@ static int validateBuffer(Logging *logging, int extraLen, const char *text) {
return TRUE;
}
- int currentLen = loggingSize(logging);
- if (currentLen + extraLen > logging->bufferSize - 1) {
+ if (remainingSize(logging) < extraLen + 1) {
strcpy(logging->SMALL_BUFFER, "Logging buffer overflow: ");
strcat(logging->SMALL_BUFFER, logging->name);
strcat(logging->SMALL_BUFFER, "/");
@@ -90,6 +89,22 @@ void append(Logging *logging, const char *text) {
logging->linePointer += extraLen;
}
+/**
+ * @note This method if fast because it does not validate much, be sure what you are doing
+ */
+void appendFast(Logging *logging, const char *text) {
+// todo: fix this implementation? this would be a one-pass implementation instead of a two-pass
+// char c;
+// char *s = (char *) text;
+// do {
+// c = *s++;
+// *logging->linePointer++ = c;
+// } while (c != '\0');
+ int extraLen = strlen(text);
+ strcpy(logging->linePointer, text);
+ logging->linePointer += extraLen;
+}
+
static void vappendPrintfI(Logging *logging, const char *fmt, va_list arg) {
intermediateLoggingBuffer.eos = 0; // reset
chvprintf((BaseSequentialStream *) &intermediateLoggingBuffer, fmt, arg);
@@ -365,8 +380,8 @@ void scheduleLogging(Logging *logging) {
resetLogging(logging);
}
-uint32_t loggingSize(Logging *logging) {
- return (int) logging->linePointer - (int) (logging->buffer);
+uint32_t remainingSize(Logging *logging) {
+ return logging->bufferSize - loggingSize(logging);
}
/**
diff --git a/firmware/console_util/datalogging.h b/firmware/console_util/datalogging.h
index 74aebbbbdc..3246ca0a63 100644
--- a/firmware/console_util/datalogging.h
+++ b/firmware/console_util/datalogging.h
@@ -43,11 +43,13 @@ extern "C"
{
#endif /* __cplusplus */
-bool_t lockOutputBuffer(void);
+bool lockOutputBuffer(void);
void unlockOutputBuffer(void);
void initIntermediateLoggingBuffer(void);
-uint32_t loggingSize(Logging *logging);
+uint32_t remainingSize(Logging *logging);
+
+#define loggingSize(logging) ((int) (logging)->linePointer - (int) ((logging)->buffer))
int isInitialized(Logging *logging);
@@ -74,6 +76,7 @@ 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, const char *text);
+void appendFast(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/controllers/algo/OutputSignalList.h b/firmware/controllers/algo/OutputSignalList.h
index f87455d608..6d89a710c6 100644
--- a/firmware/controllers/algo/OutputSignalList.h
+++ b/firmware/controllers/algo/OutputSignalList.h
@@ -25,7 +25,7 @@
#include "io_pins.h"
// todo: this value is too low for 6 cyl engine, get it back to 60
-#define OUTPUT_SIGNAL_MAX_SIZE 60
+#define OUTPUT_SIGNAL_MAX_SIZE 90
class OutputSignalList {
public:
diff --git a/firmware/controllers/algo/algo.cpp b/firmware/controllers/algo/algo.cpp
index a893fd2a78..34fe9c50c3 100644
--- a/firmware/controllers/algo/algo.cpp
+++ b/firmware/controllers/algo/algo.cpp
@@ -21,16 +21,22 @@
#include "global.h"
#include "algo.h"
-//#include "rpm_calculator.h"
#include "advance_map.h"
#include "fuel_math.h"
#include "wave_chart.h"
#include "settings.h"
#include "signal_executor.h"
+#include "speed_density.h"
WaveChart waveChart;
-void initAlgo(void) {
+void initDataStructures(engine_configuration_s *engineConfiguration) {
+ prepareFuelMap();
+ prepareTimingMap();
+ initSpeedDensity(engineConfiguration);
+}
+
+void initAlgo(engine_configuration_s *engineConfiguration) {
#if EFI_PROD_CODE || EFI_SIMULATOR
initSettings();
initSignalExecutor();
@@ -39,10 +45,4 @@ void initAlgo(void) {
#if EFI_WAVE_CHART
initWaveChart(&waveChart);
#endif
-
-
- prepareFuelMap();
- prepareTimingMap();
-
-
}
diff --git a/firmware/controllers/algo/algo.h b/firmware/controllers/algo/algo.h
index b091c1851f..1b938990c7 100644
--- a/firmware/controllers/algo/algo.h
+++ b/firmware/controllers/algo/algo.h
@@ -8,12 +8,15 @@
#ifndef ALGO_H_
#define ALGO_H_
+#include "engine_configuration.h"
+
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
-void initAlgo(void);
+void initDataStructures(engine_configuration_s *engineConfiguration);
+void initAlgo(engine_configuration_s *engineConfiguration);
#ifdef __cplusplus
}
diff --git a/firmware/controllers/algo/ec2.h b/firmware/controllers/algo/ec2.h
index 6987070e8f..deb6723208 100644
--- a/firmware/controllers/algo/ec2.h
+++ b/firmware/controllers/algo/ec2.h
@@ -22,6 +22,10 @@
typedef struct {
ActuatorEventList crankingInjectionEvents;
ActuatorEventList injectionEvents;
+ /**
+ * We are alternating two event lists in order to avoid a potential issue around revolution boundary
+ * when an event is scheduled within the next revolution.
+ */
IgnitionEventList ignitionEvents[2];
} EventHandlerConfiguration;
diff --git a/firmware/controllers/algo/engine.cpp b/firmware/controllers/algo/engine.cpp
index 95bf303510..3122f29cb3 100644
--- a/firmware/controllers/algo/engine.cpp
+++ b/firmware/controllers/algo/engine.cpp
@@ -9,5 +9,15 @@
* @author Andrey Belomutskiy, (c) 2012-2014
*/
+#include "main.h"
+#include "engine.h"
+#include "engine_state.h"
+/**
+ * We are executing these heavy (logarithm) methods from outside the trigger callbacks for performance reasons.
+ */
+void Engine::updateSlowSensors() {
+ engineState.iat = getIntakeAirTemperature();
+ engineState.clt = getCoolantTemperature();
+}
diff --git a/firmware/controllers/algo/engine.h b/firmware/controllers/algo/engine.h
index d1e92cf06b..18b9959d11 100644
--- a/firmware/controllers/algo/engine.h
+++ b/firmware/controllers/algo/engine.h
@@ -10,12 +10,26 @@
#include "main.h"
#include "engine_configuration.h"
+class EngineState {
+public:
+ /**
+ * Access to these two fields is not synchronized in any way - that should work since float read/write are atomic.
+ */
+ float iat;
+ float clt;
+};
+
class RpmCalculator;
class Engine {
public:
RpmCalculator *rpmCalculator;
engine_configuration_s *engineConfiguration;
+
+
+ EngineState engineState;
+
+ void updateSlowSensors();
};
#endif /* ENGINE_H_ */
diff --git a/firmware/controllers/algo/engine_configuration.cpp b/firmware/controllers/algo/engine_configuration.cpp
index 418090ca9b..cd3ba56611 100644
--- a/firmware/controllers/algo/engine_configuration.cpp
+++ b/firmware/controllers/algo/engine_configuration.cpp
@@ -26,8 +26,9 @@
#include "interpolation.h"
#include "trigger_decoder.h"
#include "engine_math.h"
+#include "speed_density.h"
-#if EFI_PROD_CODE
+#if EFI_TUNER_STUDIO
#include "tunerstudio.h"
#endif
@@ -94,11 +95,18 @@ void setWholeFuelMap(engine_configuration_s *engineConfiguration, float value) {
}
}
-void setTriggerSynchronizationGap(engine_configuration_s *engineConfiguration, float synchGap) {
- engineConfiguration->triggerConfig.isSynchronizationNeeded = TRUE;
+void setToothedWheelConfiguration(engine_configuration_s *engineConfiguration, int total, int skipped) {
+ engineConfiguration->triggerConfig.triggerType = TT_TOOTHED_WHEEL;
+ engineConfiguration->triggerConfig.isSynchronizationNeeded = (skipped != 0);
- engineConfiguration->triggerConfig.syncRatioFrom = synchGap * 0.75;
- engineConfiguration->triggerConfig.syncRatioTo = synchGap * 1.25;
+ engineConfiguration->triggerConfig.totalToothCount = total;
+ engineConfiguration->triggerConfig.skippedToothCount = skipped;
+}
+
+void setTriggerSynchronizationGap(trigger_config_s *triggerConfig, float synchGap) {
+ triggerConfig->isSynchronizationNeeded = TRUE;
+ triggerConfig->syncRatioFrom = synchGap * 0.75;
+ triggerConfig->syncRatioTo = synchGap * 1.25;
}
/**
@@ -110,6 +118,8 @@ void setDefaultConfiguration(engine_configuration_s *engineConfiguration, board_
memset(engineConfiguration, 0, sizeof(engine_configuration_s));
memset(boardConfiguration, 0, sizeof(board_configuration_s));
+ setDetaultVETable(engineConfiguration);
+
engineConfiguration->injectorLag = 0.0;
for (int i = 0; i < IAT_CURVE_SIZE; i++) {
@@ -147,8 +157,8 @@ void setDefaultConfiguration(engine_configuration_s *engineConfiguration, board_
setTimingLoadBin(engineConfiguration, 1.2, 4.4);
setTimingRpmBin(engineConfiguration, 800, 7000);
- setTableBin(engineConfiguration->map.samplingAngleBins, MAP_ANGLE_SIZE, 800, 7000);
- setTableBin(engineConfiguration->map.samplingWindowBins, MAP_ANGLE_SIZE, 800, 7000);
+ setTableBin2(engineConfiguration->map.samplingAngleBins, MAP_ANGLE_SIZE, 800, 7000, 1);
+ setTableBin2(engineConfiguration->map.samplingWindowBins, MAP_ANGLE_SIZE, 800, 7000, 1);
// set_whole_timing_map 3
setWholeFuelMap(engineConfiguration, 3);
@@ -193,7 +203,7 @@ void setDefaultConfiguration(engine_configuration_s *engineConfiguration, board_
engineConfiguration->overrideCrankingIgnition = TRUE;
engineConfiguration->analogChartFrequency = 20;
- engineConfiguration->engineLoadMode = LM_MAF;
+ engineConfiguration->algorithm = LM_MAF;
engineConfiguration->vbattDividerCoeff = ((float) (15 + 65)) / 15;
@@ -206,7 +216,7 @@ void setDefaultConfiguration(engine_configuration_s *engineConfiguration, board_
engineConfiguration->can_nbc_type = CAN_BUS_NBC_BMW;
engineConfiguration->can_sleep_period = 50;
engineConfiguration->canReadEnabled = TRUE;
- engineConfiguration->canWriteEnabled = FALSE;
+ engineConfiguration->canWriteEnabled = false;
setOperationMode(engineConfiguration, FOUR_STROKE_CAM_SENSOR);
engineConfiguration->cylindersCount = 4;
@@ -221,7 +231,7 @@ void setDefaultConfiguration(engine_configuration_s *engineConfiguration, board_
engineConfiguration->logFormat = LF_NATIVE;
engineConfiguration->triggerConfig.triggerType = TT_TOOTHED_WHEEL;
- setTriggerSynchronizationGap(engineConfiguration, 2);
+ setTriggerSynchronizationGap(&engineConfiguration->triggerConfig, 2);
engineConfiguration->triggerConfig.useRiseEdge = TRUE;
engineConfiguration->HD44780width = 16;
@@ -260,12 +270,26 @@ void setDefaultConfiguration(engine_configuration_s *engineConfiguration, board_
boardConfiguration->injectionPins[3] = GPIOE_5;
boardConfiguration->injectionPins[4] = GPIOE_6;
boardConfiguration->injectionPins[5] = GPIOC_12;
+ boardConfiguration->injectionPins[6] = GPIO_NONE;
+ boardConfiguration->injectionPins[7] = GPIO_NONE;
+ boardConfiguration->injectionPins[8] = GPIO_NONE;
+ boardConfiguration->injectionPins[9] = GPIO_NONE;
+ boardConfiguration->injectionPins[10] = GPIO_NONE;
+ boardConfiguration->injectionPins[11] = GPIO_NONE;
boardConfiguration->injectionPinMode = OM_DEFAULT;
boardConfiguration->ignitionPins[0] = GPIOC_7;
boardConfiguration->ignitionPins[1] = GPIOE_4; // todo: update this value
boardConfiguration->ignitionPins[2] = GPIOE_0; // todo: update this value
boardConfiguration->ignitionPins[3] = GPIOE_1; // todo: update this value
+ boardConfiguration->ignitionPins[4] = GPIO_NONE;
+ boardConfiguration->ignitionPins[5] = GPIO_NONE;
+ boardConfiguration->ignitionPins[6] = GPIO_NONE;
+ boardConfiguration->ignitionPins[7] = GPIO_NONE;
+ boardConfiguration->ignitionPins[8] = GPIO_NONE;
+ boardConfiguration->ignitionPins[9] = GPIO_NONE;
+ boardConfiguration->ignitionPins[10] = GPIO_NONE;
+ boardConfiguration->ignitionPins[11] = GPIO_NONE;
boardConfiguration->ignitionPinMode = OM_DEFAULT;
boardConfiguration->malfunctionIndicatorPin = GPIOC_9;
@@ -314,6 +338,12 @@ void setDefaultConfiguration(engine_configuration_s *engineConfiguration, board_
boardConfiguration->generalPeriodicThreadPeriod = 200;
boardConfiguration->tunerStudioSerialSpeed = 38400;
+
+ boardConfiguration->boardTestModeJumperPin = GPIOB_0;
+
+ boardConfiguration->canDeviceMode = CD_USE_CAN2;
+ boardConfiguration->canTxPin = GPIOB_0;
+ boardConfiguration->canRxPin = GPIOB_12;
}
void setDefaultNonPersistentConfiguration(engine_configuration2_s *engineConfiguration2) {
@@ -438,8 +468,8 @@ void setOperationMode(engine_configuration_s *engineConfiguration, operation_mod
}
}
-operation_mode_e getOperationMode( engine_configuration_s const *engineConfiguration) {
- if(engineConfiguration->rpmMultiplier == 1)
+operation_mode_e getOperationMode(engine_configuration_s const *engineConfiguration) {
+ if (engineConfiguration->rpmMultiplier == 1)
return FOUR_STROKE_CRANK_SENSOR;
return FOUR_STROKE_CAM_SENSOR;
diff --git a/firmware/controllers/algo/engine_configuration.h b/firmware/controllers/algo/engine_configuration.h
index 71c16bf78d..e4e249a836 100644
--- a/firmware/controllers/algo/engine_configuration.h
+++ b/firmware/controllers/algo/engine_configuration.h
@@ -68,6 +68,14 @@ typedef enum {
Internal_ForceMyEnumIntSize_timing_mode = ENUM_SIZE_HACK,
} timing_mode_e;
+typedef enum {
+ CD_OFF = 0,
+ CD_USE_CAN1 = 1,
+ CD_USE_CAN2 = 2,
+
+ Internal_ForceMyEnumIntSize_can_device_mode = ENUM_SIZE_HACK,
+} can_device_mode_e;
+
typedef struct {
int afrAdcChannel;
float v1;
@@ -97,202 +105,6 @@ typedef struct {
} trigger_config_s;
-/**
- * @brief Engine configuration.
- * Values in this data structure are adjustable and persisted in on-board flash RAM.
- *
- * The offsets are tracked using
- * https://docs.google.com/spreadsheet/ccc?key=0AiAmAn6tn3L_dGJXZDZOcVVhaG9SaHZKU1dyMjhEV0E
- *
- * todo: currently the fields here are simply in the order in which they were implemented
- * todo: re-arrange this structure one we have a stable code version
- */
-typedef struct {
- float injectorLag; // size 4, offset 0
- /**
- * cc/min, cubic centimeter per minute
- *
- * By the way, g/s = 0.125997881 * (lb/hr)
- * g/s = 0.125997881 * (cc/min)/10.5
- * g/s = 0.0119997981 * cc/min
- *
- */
- float injectorFlow; // size 4, offset 4
- float battInjectorLagCorrBins[VBAT_INJECTOR_CURVE_SIZE]; // size 32, offset 8
- float battInjectorLagCorr[VBAT_INJECTOR_CURVE_SIZE]; // size 32, offset 40
-
- float cltFuelCorrBins[CLT_CURVE_SIZE]; // size 64, offset 72
- float cltFuelCorr[CLT_CURVE_SIZE]; // size 64, offset 136
-
- float iatFuelCorrBins[IAT_CURVE_SIZE]; // size 64, offset 200
- float iatFuelCorr[IAT_CURVE_SIZE]; // size 64, offset 264
-
- short int rpmHardLimit; // size 2, offset 328
-
- // todo: extract these two fields into a structure
- // todo: we need two sets of TPS parameters - modern ETBs have to sensors
- short int tpsMin; // size 2, offset 330
- // tpsMax value as 10 bit ADC value. Not Voltage!
- short int tpsMax; // size 2, offset 332
- short int analogChartMode;
-
- cranking_parameters_s crankingSettings;
-
- MAP_sensor_config_s map;
-
- // todo: merge with channel settings, use full-scale Thermistor here!
- ThermistorConf cltThermistorConf; // size 40 (10*4), offset 336
- ThermistorConf iatThermistorConf; // size 40, offset 376
-
- float sparkDwellBins[DWELL_COUNT]; // offset 580
- float sparkDwell[DWELL_COUNT];
-
- float ignitionLoadBins[IGN_LOAD_COUNT];
- float ignitionRpmBins[IGN_RPM_COUNT];
-
- /**
- * this value could be used to offset the whole ignition timing table by a constant
- */
- float ignitionOffset;
-
- /**
- * While cranking (which causes battery voltage to drop) we can calculate dwell time in shaft
- * degrees, not in absolute time as in running mode.
- */
- float crankingChargeAngle;
-
- timing_mode_e timingMode;
- /**
- * This value is used in 'fixed timing' mode, i.e. constant timing
- * This mode is useful for instance while adjusting distributor location
- */
- float fixedModeTiming;
-
- // WARNING: by default, our small enums are ONE BYTE. but if the are surrounded by non-enums - alignments do the trick
- engine_type_e engineType;
-
- float fuelLoadBins[FUEL_LOAD_COUNT]; //
- // RPM is float and not integer in order to use unified methods for interpolation
- float fuelRpmBins[FUEL_RPM_COUNT]; //
-
- /**
- * Engine displacement, in liters
- * see also cylindersCount
- */
- float displacement;
- int unused[2];
-
- injection_mode_e crankingInjectionMode;
- injection_mode_e injectionMode;
-
-
- /**
- * Inside rusEfi all the angles are handled in relation to the trigger synchronization event
- * which depends on the trigger shape and has nothing to do wit Top Dead Center (TDC)
- *
- * For engine configuration humans need angles from TDC.
- *
- * This field is the angle between Top Dead Center (TDC) and the first trigger event.
- * Knowing this angle allows us to control timing and other angles in reference to TDC.
- */
- float globalTriggerAngleOffset;
- /**
- * We have 3.3V ADC and most of the analog input signals are 5V, this forces us to use
- * voltage dividers on the input circuits. This parameter holds the coefficient of these dividers.
- * see also vbattDividerCoeff
- */
- float analogInputDividerCoefficient;
-
- /**
- * This setting controls which algorithm is used for ENGINE LOAD
- */
- engine_load_mode_e engineLoadMode;
-
- /**
- * see
- */
- float vbattDividerCoeff;
- /**
- * Cooling fan turn-on temperature threshold, in Celsuis
- */
- float fanOnTemperature;
- /**
- * Cooling fan turn-off temperature threshold, in Celsuis
- */
- float fanOffTemperature;
-
- int canReadEnabled;
- int canWriteEnabled;
- can_nbc_e can_nbc_type;
- int can_sleep_period;
-
- int cylindersCount;
-
- ignition_mode_e ignitionMode;
- firing_order_e firingOrder;
-
- /**
- * This magic constant is about four-stroke engines with camshaft position sensors.
- * On any four stroke engine, each revolution of the camshaft is two revolutions
- * of the crankshaft. If camshaft position is our primary sensor, we use this multiplier
- * to convert from camshaft angles to crankshaft angles. All angels across the system
- * should be crankshaft angles.
- */
-
- float rpmMultiplier;
-
- display_mode_e displayMode;
-
- log_format_e logFormat;
-
- int firmwareVersion;
- int HD44780width;
- int HD44780height;
-
- int tpsAdcChannel;
- int overrideCrankingIgnition;
- int analogChartFrequency;
- int unused5[10];
-
- trigger_config_s triggerConfig;
-
- int needSecondTriggerInput;
- int vBattAdcChannel;
-
- float globalFuelCorrection;
-
- // todo: merge with channel settings, use full-scale Thermistor!
- int cltAdcChannel;
- int iatAdcChannel;
- int mafAdcChannel;
-
- afr_sensor_s afrSensor;
-
- float injectionOffset;
-
- float crankingTimingAngle;
-
- float diffLoadEnrichmentCoef;
-
- air_pressure_sensor_config_s baroSensor;
-
- float veLoadBins[VE_LOAD_COUNT];
- float veRpmBins[VE_RPM_COUNT];
- float afrLoadBins[AFR_LOAD_COUNT];
- float afrRpmBins[AFR_RPM_COUNT];
-
- // the large tables are always in the end - that's related to TunerStudio paging implementation
- float fuelTable[FUEL_LOAD_COUNT][FUEL_RPM_COUNT]; // size 1024
- float ignitionTable[IGN_LOAD_COUNT][IGN_RPM_COUNT]; // size 1024
-
- float veTable[VE_LOAD_COUNT][VE_RPM_COUNT]; // size 1024
- float afrTable[AFR_LOAD_COUNT][AFR_RPM_COUNT]; // size 1024
-
-} engine_configuration_s;
-
-void setOperationMode(engine_configuration_s *engineConfiguration, operation_mode_e mode);
-operation_mode_e getOperationMode(engine_configuration_s const *engineConfiguration);
-
#define HW_MAX_ADC_INDEX 16
typedef struct {
@@ -355,11 +167,216 @@ typedef struct {
int tunerStudioSerialSpeed;
+ brain_pin_e boardTestModeJumperPin;
+
+ can_device_mode_e canDeviceMode;
+ brain_pin_e canTxPin;
+ brain_pin_e canRxPin;
+
} board_configuration_s;
+
+
+/**
+ * @brief Engine configuration.
+ * Values in this data structure are adjustable and persisted in on-board flash RAM.
+ *
+ * The offsets are tracked using
+ * https://docs.google.com/spreadsheet/ccc?key=0AiAmAn6tn3L_dGJXZDZOcVVhaG9SaHZKU1dyMjhEV0E
+ *
+ * todo: currently the fields here are simply in the order in which they were implemented
+ * todo: re-arrange this structure one we have a stable code version
+ */
+typedef struct {
+ float injectorLag; // size 4, offset 0
+ /**
+ * cc/min, cubic centimeter per minute
+ *
+ * By the way, g/s = 0.125997881 * (lb/hr)
+ * g/s = 0.125997881 * (cc/min)/10.5
+ * g/s = 0.0119997981 * cc/min
+ *
+ */
+ float injectorFlow; // size 4, offset 4
+ float battInjectorLagCorrBins[VBAT_INJECTOR_CURVE_SIZE]; // size 32, offset 8
+ float battInjectorLagCorr[VBAT_INJECTOR_CURVE_SIZE]; // size 32, offset 40
+
+ float cltFuelCorrBins[CLT_CURVE_SIZE]; // size 64, offset 72
+ float cltFuelCorr[CLT_CURVE_SIZE]; // size 64, offset 136
+
+ float iatFuelCorrBins[IAT_CURVE_SIZE]; // size 64, offset 200
+ float iatFuelCorr[IAT_CURVE_SIZE]; // size 64, offset 264
+
+ short int unused2; // size 2, offset 328
+
+ // todo: extract these two fields into a structure
+ // todo: we need two sets of TPS parameters - modern ETBs have to sensors
+ short int tpsMin; // size 2, offset 330
+ // tpsMax value as 10 bit ADC value. Not Voltage!
+ short int tpsMax; // size 2, offset 332
+ short int analogChartMode;
+
+ cranking_parameters_s crankingSettings;
+
+ MAP_sensor_config_s map;
+
+ // todo: merge with channel settings, use full-scale Thermistor here!
+ ThermistorConf cltThermistorConf; // size 40 (10*4), offset 336
+ ThermistorConf iatThermistorConf; // size 40, offset 376
+
+ float sparkDwellBins[DWELL_COUNT]; // offset 580
+ float sparkDwell[DWELL_COUNT];
+
+ float ignitionLoadBins[IGN_LOAD_COUNT];
+ float ignitionRpmBins[IGN_RPM_COUNT];
+
+ /**
+ * this value could be used to offset the whole ignition timing table by a constant
+ */
+ float ignitionOffset;
+
+ /**
+ * While cranking (which causes battery voltage to drop) we can calculate dwell time in shaft
+ * degrees, not in absolute time as in running mode.
+ */
+ float crankingChargeAngle;
+
+ timing_mode_e timingMode;
+ /**
+ * This value is used in 'fixed timing' mode, i.e. constant timing
+ * This mode is useful for instance while adjusting distributor location
+ */
+ float fixedModeTiming;
+
+ // WARNING: by default, our small enums are ONE BYTE. but if the are surrounded by non-enums - alignments do the trick
+ engine_type_e engineType;
+
+ float fuelLoadBins[FUEL_LOAD_COUNT]; //
+ // RPM is float and not integer in order to use unified methods for interpolation
+ float fuelRpmBins[FUEL_RPM_COUNT]; //
+
+ /**
+ * Engine displacement, in liters
+ * see also cylindersCount
+ */
+ float displacement;
+ int rpmHardLimit;
+
+ injection_mode_e crankingInjectionMode;
+ injection_mode_e injectionMode;
+
+
+ /**
+ * Inside rusEfi all the angles are handled in relation to the trigger synchronization event
+ * which depends on the trigger shape and has nothing to do wit Top Dead Center (TDC)
+ *
+ * For engine configuration humans need angles from TDC.
+ *
+ * This field is the angle between Top Dead Center (TDC) and the first trigger event.
+ * Knowing this angle allows us to control timing and other angles in reference to TDC.
+ */
+ float globalTriggerAngleOffset;
+ /**
+ * We have 3.3V ADC and most of the analog input signals are 5V, this forces us to use
+ * voltage dividers on the input circuits. This parameter holds the coefficient of these dividers.
+ * see also vbattDividerCoeff
+ */
+ float analogInputDividerCoefficient;
+
+ /**
+ * This setting controls which algorithm is used for ENGINE LOAD
+ */
+ engine_load_mode_e algorithm;
+
+ /**
+ * see
+ */
+ float vbattDividerCoeff;
+ /**
+ * Cooling fan turn-on temperature threshold, in Celsuis
+ */
+ float fanOnTemperature;
+ /**
+ * Cooling fan turn-off temperature threshold, in Celsuis
+ */
+ float fanOffTemperature;
+
+ int canReadEnabled;
+ int canWriteEnabled;
+ can_nbc_e can_nbc_type;
+ int can_sleep_period;
+
+ int cylindersCount;
+
+ ignition_mode_e ignitionMode;
+ firing_order_e firingOrder;
+
+ /**
+ * This magic constant is about four-stroke engines with camshaft position sensors.
+ * On any four stroke engine, each revolution of the camshaft is two revolutions
+ * of the crankshaft. If camshaft position is our primary sensor, we use this multiplier
+ * to convert from camshaft angles to crankshaft angles. All angels across the system
+ * should be crankshaft angles.
+ */
+
+ float rpmMultiplier;
+
+ display_mode_e displayMode;
+
+ log_format_e logFormat;
+
+ int firmwareVersion;
+ int HD44780width;
+ int HD44780height;
+
+ int tpsAdcChannel;
+ int overrideCrankingIgnition;
+ int analogChartFrequency;
+
+ trigger_config_s triggerConfig;
+
+ int needSecondTriggerInput;
+ int vBattAdcChannel;
+
+ float globalFuelCorrection;
+
+ // todo: merge with channel settings, use full-scale Thermistor!
+ int cltAdcChannel;
+ int iatAdcChannel;
+ int mafAdcChannel;
+
+ afr_sensor_s afrSensor;
+
+ float injectionOffset;
+
+ float crankingTimingAngle;
+
+ float diffLoadEnrichmentCoef;
+
+ air_pressure_sensor_config_s baroSensor;
+
+ float veLoadBins[VE_LOAD_COUNT];
+ float veRpmBins[VE_RPM_COUNT];
+ float afrLoadBins[AFR_LOAD_COUNT];
+ float afrRpmBins[AFR_RPM_COUNT];
+
+ // the large tables are always in the end - that's related to TunerStudio paging implementation
+ float fuelTable[FUEL_LOAD_COUNT][FUEL_RPM_COUNT]; // size 1024
+ float ignitionTable[IGN_LOAD_COUNT][IGN_RPM_COUNT]; // size 1024
+
+ float veTable[VE_LOAD_COUNT][VE_RPM_COUNT]; // size 1024
+ float afrTable[AFR_LOAD_COUNT][AFR_RPM_COUNT]; // size 1024
+
+
+ board_configuration_s bc;
+
+} engine_configuration_s;
+
+void setOperationMode(engine_configuration_s *engineConfiguration, operation_mode_e mode);
+operation_mode_e getOperationMode(engine_configuration_s const *engineConfiguration);
+
typedef struct {
engine_configuration_s engineConfiguration;
- board_configuration_s boardConfiguration;
} persistent_config_s;
typedef struct {
@@ -379,7 +396,8 @@ void setWholeFuelMap(engine_configuration_s *engineConfiguration, float value);
void setConstantDwell(engine_configuration_s *engineConfiguration, float dwellMs);
void printFloatArray(const char *prefix, float array[], int size);
-void setTriggerSynchronizationGap(engine_configuration_s *engineConfiguration, float synchGap);
+void setTriggerSynchronizationGap(trigger_config_s *triggerConfig, float synchGap);
+void setToothedWheelConfiguration(engine_configuration_s *engineConfiguration, int total, int skipped);
void incrementGlobalConfigurationVersion(void);
int getGlobalConfigurationVersion(void);
diff --git a/firmware/controllers/algo/error_handling.h b/firmware/controllers/algo/error_handling.h
index 47e7b0421d..e9176c57ee 100644
--- a/firmware/controllers/algo/error_handling.h
+++ b/firmware/controllers/algo/error_handling.h
@@ -55,10 +55,8 @@ int getRusEfiVersion(void);
#define efiAssertVoid(condition, message) { if (!(condition)) { firmwareError(message); return; } }
-
#ifdef __cplusplus
}
#endif /* __cplusplus */
-
#endif /* ERROR_HANDLING_H_ */
diff --git a/firmware/controllers/algo/event_registry.cpp b/firmware/controllers/algo/event_registry.cpp
index 82407f11a3..2091ea189c 100644
--- a/firmware/controllers/algo/event_registry.cpp
+++ b/firmware/controllers/algo/event_registry.cpp
@@ -24,11 +24,11 @@
#include "main.h"
#include "engine_math.h"
-void registerActuatorEvent(ActuatorEventList *list, int eventIndex, OutputSignal *actuator, float angleOffset) {
- ActuatorEvent *e = list->getNextActuatorEvent();
- if (e == NULL)
- return; // error already reported
- e->position.eventIndex = eventIndex;
- e->actuator = actuator;
- e->position.angleOffset = angleOffset;
-}
+//void registerActuatorEventWhat(ActuatorEventList *list, int eventIndex, OutputSignal *actuator, float angleOffset) {
+// ActuatorEvent *e = list->getNextActuatorEvent();
+// if (e == NULL)
+// return; // error already reported
+// e->position.eventIndex = eventIndex;
+// e->actuator = actuator;
+// e->position.angleOffset = angleOffset;
+//}
diff --git a/firmware/controllers/algo/event_registry.h b/firmware/controllers/algo/event_registry.h
index 1a8fb94a73..1d455eb8a2 100644
--- a/firmware/controllers/algo/event_registry.h
+++ b/firmware/controllers/algo/event_registry.h
@@ -11,7 +11,7 @@
#include "global.h"
#include "signal_executor.h"
-#define MAX_EVENT_COUNT 40
+#define MAX_EVENT_COUNT 80
/**
* This structure defines an angle position within the trigger
@@ -31,13 +31,15 @@ typedef struct {
typedef struct {
event_trigger_position_s position;
OutputSignal *actuator;
- scheduling_s signalTimer;
} ActuatorEvent;
typedef struct IgnitionEvent_struct IgnitionEvent;
struct IgnitionEvent_struct {
- ActuatorEvent actuator;
+ io_pin_e io_pin;
+ scheduling_s signalTimerUp;
+ scheduling_s signalTimerDown;
+ event_trigger_position_s dwellPosition;
float advance;
event_trigger_position_s sparkPosition;
IgnitionEvent *next;
@@ -68,14 +70,14 @@ typedef ArrayList ActuatorEventList;
typedef ArrayList IgnitionEventList;
-/**
- * this is an intermediate implementation of flexible event handling.
- *
- * In the future implementation we will drop the 'eventIndex' parameter and everything will be
- * angle-driven. But that's just a plan for next iteration.
- *
- * @param actuator injector or coil OutputSignal
- */
-void registerActuatorEvent(ActuatorEventList *list, int eventIndex, OutputSignal *actuator, float angleOffset);
+///**
+// * this is an intermediate implementation of flexible event handling.
+// *
+// * In the future implementation we will drop the 'eventIndex' parameter and everything will be
+// * angle-driven. But that's just a plan for next iteration.
+// *
+// * @param actuator injector or coil OutputSignal
+// */
+//void registerActuatorEvent(ActuatorEventList *list, int eventIndex, OutputSignal *actuator, float angleOffset);
#endif /* EVENT_REGISTRY_H_ */
diff --git a/firmware/controllers/algo/fuel_math.cpp b/firmware/controllers/algo/fuel_math.cpp
index f1c448f02a..d0d3c78688 100644
--- a/firmware/controllers/algo/fuel_math.cpp
+++ b/firmware/controllers/algo/fuel_math.cpp
@@ -1,5 +1,5 @@
/**
- * @file fuel_math.c
+ * @file fuel_math.cpp
* @brief Fuel amount calculation logic
*
* While engine running, fuel amount is an interpolated value from the fuel map by getRpm() and getEngineLoad()
diff --git a/firmware/controllers/algo/io_pins.h b/firmware/controllers/algo/io_pins.h
index a1d869c206..317853aacf 100644
--- a/firmware/controllers/algo/io_pins.h
+++ b/firmware/controllers/algo/io_pins.h
@@ -111,7 +111,7 @@ extern "C"
void initPrimaryPins(void);
void initOutputPins(void);
-char *getPinName(io_pin_e io_pin);
+const char *getPinName(io_pin_e io_pin);
void turnOutputPinOn(io_pin_e pin);
void turnOutputPinOff(io_pin_e pin);
void setOutputPinValue(io_pin_e pin, int logicValue);
diff --git a/firmware/controllers/algo/rusefi_enums.h b/firmware/controllers/algo/rusefi_enums.h
index 34e450cd25..45fd936bd3 100644
--- a/firmware/controllers/algo/rusefi_enums.h
+++ b/firmware/controllers/algo/rusefi_enums.h
@@ -80,6 +80,7 @@ typedef enum {
TT_GM_7X = 5,
TT_MINI_COOPER_R50 = 6,
TT_FORD_ESCORT_GT = 7,
+ TT_TT_TOOTHED_WHEEL_60_2 = 8,
Internal_ForceMyEnumIntSize_trigger_type = ENUM_SIZE_HACK,
} trigger_type_e;
@@ -170,19 +171,20 @@ typedef enum {
} pin_input_mode_e;
typedef enum {
- FO_ONE_CYLINDER = 1,
- FO_1_THEN_3_THEN_4_THEN2 = 2,
- FO_1_THEN_2_THEN_4_THEN3 = 3,
- FO_1_THEN_3_THEN_2_THEN4 = 4,
- FO_1_THEN_5_THEN_3_THEN_6_THEN_2_THEN_4 = 5,
- FO_1_8_4_3_6_5_7_2 = 6,
+ FO_ONE_CYLINDER = 0,
+ FO_1_THEN_3_THEN_4_THEN2 = 1,
+ FO_1_THEN_2_THEN_4_THEN3 = 2,
+ FO_1_THEN_3_THEN_2_THEN4 = 3,
+ FO_1_THEN_5_THEN_3_THEN_6_THEN_2_THEN_4 = 4,
+ FO_1_8_4_3_6_5_7_2 = 5,
Internal_ForceMyEnumIntSize_firing_order = ENUM_SIZE_HACK,
} firing_order_e;
// todo: better enum name
typedef enum {
- FOUR_STROKE_CRANK_SENSOR = 0,
- FOUR_STROKE_CAM_SENSOR = 1,
+ OM_NONE = 0,
+ FOUR_STROKE_CRANK_SENSOR = 1,
+ FOUR_STROKE_CAM_SENSOR = 2,
Internal_ForceMyEnumIntSize_operation_mode_e = ENUM_SIZE_HACK,
} operation_mode_e;
@@ -191,7 +193,13 @@ typedef enum {
* @brief Ignition Mode
*/
typedef enum {
+ /**
+ * in this mode only SPARKOUT_1_OUTPUT is used
+ */
IM_ONE_COIL = 0,
+ /**
+ * in this mode we use as many coils as we have cylinders
+ */
IM_INDIVIDUAL_COILS = 1,
IM_WASTED_SPARK = 2,
diff --git a/firmware/controllers/algo/signal_executor.c b/firmware/controllers/algo/signal_executor.c
index 3beb39b8b4..9adc1b8814 100644
--- a/firmware/controllers/algo/signal_executor.c
+++ b/firmware/controllers/algo/signal_executor.c
@@ -51,19 +51,12 @@ void initSignalExecutor(void) {
void initOutputSignal(OutputSignal *signal, io_pin_e ioPin) {
signal->io_pin = ioPin;
- signal->name = getPinName(ioPin);
- initOutputSignalBase(signal);
}
-void initOutputSignalBase(OutputSignal *signal) {
- signal->initialized = TRUE;
-}
-
-void turnPinHigh(OutputSignal *signal) {
+void turnPinHigh(io_pin_e pin) {
#if EFI_DEFAILED_LOGGING
// signal->hi_time = hTimeNow();
#endif /* EFI_DEFAILED_LOGGING */
- io_pin_e pin = signal->io_pin;
// turn the output level ACTIVE
// todo: this XOR should go inside the setOutputPinValue method
setOutputPinValue(pin, TRUE);
@@ -79,14 +72,14 @@ void turnPinHigh(OutputSignal *signal) {
#endif
#if EFI_WAVE_CHART
- addWaveChartEvent(signal->name, "up", "");
+ addWaveChartEvent(getPinName(pin), WC_UP, "");
#endif /* EFI_WAVE_ANALYZER */
}
-void turnPinLow(OutputSignal *signal) {
+void turnPinLow(io_pin_e pin) {
// turn off the output
// todo: this XOR should go inside the setOutputPinValue method
- setOutputPinValue(signal->io_pin, FALSE);
+ setOutputPinValue(pin, false);
#if EFI_DEFAILED_LOGGING
systime_t after = hTimeNow();
@@ -95,7 +88,7 @@ void turnPinLow(OutputSignal *signal) {
#endif /* EFI_DEFAILED_LOGGING */
#if EFI_WAVE_CHART
- addWaveChartEvent(signal->name, "down", "");
+ addWaveChartEvent(getPinName(pin), WC_DOWN, "");
#endif /* EFI_WAVE_ANALYZER */
}
@@ -118,50 +111,67 @@ void scheduleOutput(OutputSignal *signal, float delayMs, float durationMs) {
return;
}
- scheduleOutputBase(signal, delayMs, durationMs);
-
int index = getRevolutionCounter() % 2;
scheduling_s * sUp = &signal->signalTimerUp[index];
scheduling_s * sDown = &signal->signalTimerDown[index];
- scheduleTask(sUp, (int)MS2US(delayMs), (schfunc_t) &turnPinHigh, (void *) signal);
- scheduleTask(sDown, (int)MS2US(delayMs + durationMs), (schfunc_t) &turnPinLow, (void*) signal);
-
-// signal->last_scheduling_time = now;
+ scheduleTask(sUp, (int)MS2US(delayMs), (schfunc_t) &turnPinHigh, (void *) signal->io_pin);
+ scheduleTask(sDown, (int)MS2US(delayMs + durationMs), (schfunc_t) &turnPinLow, (void*) signal->io_pin);
}
-void scheduleOutputBase(OutputSignal *signal, float delayMs, float durationMs) {
- /**
- * it's better to check for the exact 'TRUE' value since otherwise
- * we would accept any memory garbage
- */
- efiAssertVoid(signal->initialized == TRUE, "Signal not initialized");
-// signal->offset = offset;
-// signal->duration = duration;
-}
-
-char *getPinName(io_pin_e io_pin) {
+const char *getPinName(io_pin_e io_pin) {
switch (io_pin) {
+ // todo: refactor this hell - introduce arrays & checks?
case SPARKOUT_1_OUTPUT:
- return "Spark 1";
+ return "spa1";
case SPARKOUT_2_OUTPUT:
- return "Spark 2";
+ return "spa2";
case SPARKOUT_3_OUTPUT:
- return "Spark 3";
+ return "spa3";
case SPARKOUT_4_OUTPUT:
- return "Spark 4";
+ return "spa4";
+ case SPARKOUT_5_OUTPUT:
+ return "spa5";
+ case SPARKOUT_6_OUTPUT:
+ return "spa6";
+ case SPARKOUT_7_OUTPUT:
+ return "spa7";
+ case SPARKOUT_8_OUTPUT:
+ return "spa8";
+ case SPARKOUT_9_OUTPUT:
+ return "spa9";
+ case SPARKOUT_10_OUTPUT:
+ return "spa10";
+ case SPARKOUT_11_OUTPUT:
+ return "spa11";
+ case SPARKOUT_12_OUTPUT:
+ return "spa12";
case INJECTOR_1_OUTPUT:
- return "Injector 1";
+ return "inj1";
case INJECTOR_2_OUTPUT:
- return "Injector 2";
+ return "inj2";
case INJECTOR_3_OUTPUT:
- return "Injector 3";
+ return "inj3";
case INJECTOR_4_OUTPUT:
- return "Injector 4";
+ return "inj4";
case INJECTOR_5_OUTPUT:
- return "Injector 5";
+ return "inj5";
+ case INJECTOR_6_OUTPUT:
+ return "inj6";
+ case INJECTOR_7_OUTPUT:
+ return "inj7";
+ case INJECTOR_8_OUTPUT:
+ return "inj8";
+ case INJECTOR_9_OUTPUT:
+ return "inj9";
+ case INJECTOR_10_OUTPUT:
+ return "inj10";
+ case INJECTOR_11_OUTPUT:
+ return "inj11";
+ case INJECTOR_12_OUTPUT:
+ return "inj12";
default:
- return "No name";
+ return "Pin needs name";
}
}
diff --git a/firmware/controllers/algo/signal_executor.h b/firmware/controllers/algo/signal_executor.h
index 919e63a17d..086a3cdc86 100644
--- a/firmware/controllers/algo/signal_executor.h
+++ b/firmware/controllers/algo/signal_executor.h
@@ -28,12 +28,7 @@
*/
typedef struct OutputSignal_struct OutputSignal;
struct OutputSignal_struct {
- /**
- * name of this signal
- */
- char *name;
io_pin_e io_pin;
- int initialized;
/**
* We are alternating instances so that events which extend into next revolution are not reused while
@@ -41,9 +36,6 @@ struct OutputSignal_struct {
*/
scheduling_s signalTimerUp[2];
scheduling_s signalTimerDown[2];
-
- scheduling_s triggerEvent;
- float angleOffsetParam;
};
#ifdef __cplusplus
@@ -56,8 +48,8 @@ void scheduleOutput(OutputSignal *signal, float delayMs, float durationMs);
void initOutputSignalBase(OutputSignal *signal);
void scheduleOutputBase(OutputSignal *signal, float delayMs, float durationMs);
-void turnPinHigh(OutputSignal *signal);
-void turnPinLow(OutputSignal *signal);
+void turnPinHigh(io_pin_e pin);
+void turnPinLow(io_pin_e pin);
void initSignalExecutor(void);
void initSignalExecutorImpl(void);
diff --git a/firmware/controllers/algo/wave_chart.c b/firmware/controllers/algo/wave_chart.c
index e32e40683a..18d809cbb8 100644
--- a/firmware/controllers/algo/wave_chart.c
+++ b/firmware/controllers/algo/wave_chart.c
@@ -34,12 +34,19 @@
#define CHART_DELIMETER "!"
+#if EFI_HISTOGRAMS
+#include "rfiutil.h"
+#include "histogram.h"
+static histogram_s waveChartHisto;
+#endif
+
/**
* This is the number of events in the digital chart which would be displayed
* on the 'digital sniffer' pane
*/
#if EFI_PROD_CODE
-static volatile int chartSize = 100;
+// todo: does it really need to be a variable? maybe a constant should be enough?
+static volatile int chartSize = 300;
#define WAVE_LOGGING_SIZE 5000
#else
// need more events for automated test
@@ -47,6 +54,8 @@ static volatile int chartSize = 400;
#define WAVE_LOGGING_SIZE 35000
#endif
+int waveChartUsedSize;
+
static int isChartActive = TRUE;
//static int isChartActive = FALSE;
@@ -67,7 +76,12 @@ void resetWaveChart(WaveChart *chart) {
appendPrintf(&chart->logging, "wave_chart%s", DELIMETER);
}
-static char WAVE_LOGGING_BUFFER[WAVE_LOGGING_SIZE] CCM_OPTIONAL;
+static char WAVE_LOGGING_BUFFER[WAVE_LOGGING_SIZE] CCM_OPTIONAL
+;
+
+int isWaveChartFull(WaveChart *chart) {
+ return chart->counter >= chartSize;
+}
static void printStatus(void) {
scheduleIntValue(&logger, "chart", isChartActive);
@@ -93,12 +107,9 @@ void publishChartIfFull(WaveChart *chart) {
}
}
-int isWaveChartFull(WaveChart *chart) {
- return chart->counter >= chartSize;
-}
-
void publishChart(WaveChart *chart) {
appendPrintf(&chart->logging, DELIMETER);
+ waveChartUsedSize = loggingSize(&chart->logging);
#if DEBUG_WAVE
Logging *l = &chart->logging;
scheduleSimpleMsg(&debugLogging, "IT'S TIME", strlen(l->buffer));
@@ -107,8 +118,10 @@ void publishChart(WaveChart *chart) {
scheduleLogging(&chart->logging);
}
+static char timeBuffer[10];
+
/**
- * @brief Register a change in sniffed signal
+ * @brief Register an event for digital sniffer
*/
void addWaveChartEvent3(WaveChart *chart, const char *name, const char * msg, const char * msg2) {
efiAssertVoid(chart->isInitialized, "chart not initialized");
@@ -117,13 +130,52 @@ void addWaveChartEvent3(WaveChart *chart, const char *name, const char * msg, co
#endif
if (isWaveChartFull(chart))
return;
- bool 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);
+
+#if EFI_HISTOGRAMS && EFI_PROD_CODE
+ int beforeCallback = hal_lld_get_counter_value();
+#endif
+
+
int time100 = getTimeNowUs() / 10;
- appendPrintf(&chart->logging, "%d%s%s", time100, msg2, CHART_DELIMETER);
+
+ bool alreadyLocked = lockOutputBuffer(); // we have multiple threads writing to the same output buffer
+
+ if (chart->counter == 0)
+ chart->startTime = time100;
chart->counter++;
+ if (remainingSize(&chart->logging) > 30) {
+ /**
+ * printf is a heavy method, append is used here as a performance optimization
+ */
+ appendFast(&chart->logging, name);
+ appendFast(&chart->logging, CHART_DELIMETER);
+ appendFast(&chart->logging, msg);
+ appendFast(&chart->logging, CHART_DELIMETER);
+ /**
+ * We want smaller times within a chart in order to reduce packet size.
+ */
+ time100 -= chart->startTime;
+
+ itoa10(timeBuffer, time100);
+ appendFast(&chart->logging, timeBuffer);
+ appendFast(&chart->logging, msg2);
+ appendFast(&chart->logging, CHART_DELIMETER);
+ }
if (!alreadyLocked)
unlockOutputBuffer();
+
+#if EFI_HISTOGRAMS && EFI_PROD_CODE
+ int diff = hal_lld_get_counter_value() - beforeCallback;
+ if (diff > 0)
+ hsAdd(&waveChartHisto, diff);
+#endif /* EFI_HISTOGRAMS */
+
+}
+
+void showWaveChartHistogram(void) {
+#if EFI_PROD_CODE
+ printHistogram(&logger, &waveChartHisto);
+#endif
}
void initWaveChart(WaveChart *chart) {
@@ -140,6 +192,10 @@ void initWaveChart(WaveChart *chart) {
initLoggingExt(&debugLogging, "wave chart debug", &debugLogging.DEFAULT_BUFFER, sizeof(debugLogging.DEFAULT_BUFFER));
#endif
+#if EFI_HISTOGRAMS
+ initHistogram(&waveChartHisto, "wave chart");
+#endif /* EFI_HISTOGRAMS */
+
resetWaveChart(chart);
addConsoleActionI("chartsize", setChartSize);
addConsoleActionI("chart", setChartActive);
diff --git a/firmware/controllers/algo/wave_chart.h b/firmware/controllers/algo/wave_chart.h
index ee81532e12..37746435f4 100644
--- a/firmware/controllers/algo/wave_chart.h
+++ b/firmware/controllers/algo/wave_chart.h
@@ -23,6 +23,7 @@ typedef struct {
Logging logging;
#endif /* EFI_WAVE_CHART */
int counter;
+ int startTime;
volatile int isInitialized;
} WaveChart;
@@ -34,9 +35,10 @@ extern "C"
void addWaveChartEvent3(WaveChart *chart, const char *name, const char *msg, const char *msg2);
void publishChart(WaveChart *chart);
void initWaveChart(WaveChart *chart);
+void showWaveChartHistogram(void);
void resetWaveChart(WaveChart *chart);
void setChartSize(int newSize);
-int isWaveChartFull(WaveChart *chart);
+//int isWaveChartFull(WaveChart *chart);
void publishChartIfFull(WaveChart *chart);
#ifdef __cplusplus
diff --git a/firmware/controllers/core/EfiWave.cpp b/firmware/controllers/core/EfiWave.cpp
index c86175c925..d67e822b9e 100644
--- a/firmware/controllers/core/EfiWave.cpp
+++ b/firmware/controllers/core/EfiWave.cpp
@@ -37,24 +37,6 @@ void multi_wave_s::reset(void) {
waveCount = 0;
}
-float multi_wave_s::getAngle(int index, engine_configuration_s const *engineConfiguration, trigger_shape_s * s) const {
- if (getOperationMode(engineConfiguration) == FOUR_STROKE_CAM_SENSOR)
- return getSwitchTime(index) * 720.0;
- /**
- * FOUR_STROKE_CRANK_SENSOR magic:
- * We have two crank shaft revolutions for each engine cycle
- * See also trigger_central.cpp
- * See also getEngineCycleEventCount()
- */
- int triggerEventCounter = s->getSize();
-
- if (index < triggerEventCounter) {
- return getSwitchTime(index) * 360.0;
- } else {
- return 360 + getSwitchTime(index - triggerEventCounter) * 360.0;
- }
-}
-
float multi_wave_s::getSwitchTime(int index) const {
return switchTimes[index];
}
diff --git a/firmware/controllers/core/EfiWave.h b/firmware/controllers/core/EfiWave.h
index 7489498b46..fbe52c6d06 100644
--- a/firmware/controllers/core/EfiWave.h
+++ b/firmware/controllers/core/EfiWave.h
@@ -32,7 +32,6 @@ public:
void init(float *st, single_wave_s *waves);
void reset(void);
float getSwitchTime(int phaseIndex) const;
- float getAngle(int phaseIndex, engine_configuration_s const *engineConfiguration, trigger_shape_s * s) const;
void setSwitchTime(int phaseIndex, float value);
void checkSwitchTimes(int size);
int getChannelState(int channelIndex, int phaseIndex) const;
diff --git a/firmware/controllers/core/core.mk b/firmware/controllers/core/core.mk
index 9c12789e90..52b47c90a5 100644
--- a/firmware/controllers/core/core.mk
+++ b/firmware/controllers/core/core.mk
@@ -2,5 +2,6 @@
CONTROLLERS_CORE_SRC = $(PROJECT_DIR)/controllers/core/avg_values.c
CONTROLLERS_CORE_SRC_CPP = $(PROJECT_DIR)/controllers/core/EfiWave.cpp \
+ $(PROJECT_DIR)/controllers/core/table_helper.cpp \
$(PROJECT_DIR)/controllers/core/interpolation.cpp \
diff --git a/firmware/controllers/core/fl_stack.h b/firmware/controllers/core/fl_stack.h
new file mode 100644
index 0000000000..42edd42915
--- /dev/null
+++ b/firmware/controllers/core/fl_stack.h
@@ -0,0 +1,45 @@
+/**
+ * @file fl_stack.h
+ * @brief Fixed-length stack
+ *
+ * @date Jul 9, 2014
+ * @author Andrey Belomutskiy, (c) 2012-2014
+ */
+
+#ifndef FL_STACK_H_
+#define FL_STACK_H_
+
+template
+class FLStack {
+public:
+ FLStack();
+ void push(T value);
+ T pop();
+ int size();
+ bool isEmpty();
+private:
+ int index;
+ T values[MAXSIZE];
+};
+
+template
+FLStack::FLStack() {
+ index = 0;
+}
+
+template
+bool FLStack::isEmpty() {
+ return index == 0;
+}
+
+template
+void FLStack::push(T value) {
+ values[index++] = value;
+}
+
+template
+int FLStack::size() {
+ return index;
+}
+
+#endif /* FL_STACK_H_ */
diff --git a/firmware/controllers/core/interpolation.cpp b/firmware/controllers/core/interpolation.cpp
index 776d2f33b9..d8aaa87357 100644
--- a/firmware/controllers/core/interpolation.cpp
+++ b/firmware/controllers/core/interpolation.cpp
@@ -82,9 +82,13 @@ int findIndex(float array[], int size, float value) {
int left = 0;
int right = size;
- while (1) {
- if (size-- == 0)
- efiAssert(FALSE, "Unexpected state in binary search", 0);
+ // todo: extract binary search as template method?
+ while (true) {
+#if 0
+ // that's an assertion to make sure we do not loop here
+ size--;
+ efiAssert(size > 0, "Unexpected state in binary search", 0);
+#endif
middle = (left + right) / 2;
diff --git a/firmware/controllers/core/table_helper.cpp b/firmware/controllers/core/table_helper.cpp
new file mode 100644
index 0000000000..71615930ff
--- /dev/null
+++ b/firmware/controllers/core/table_helper.cpp
@@ -0,0 +1,29 @@
+/**
+ * @file table_helper.cpp
+ * @brief Helper methods related to 3D & 2D tables manipulation (maps and curves)
+ *
+ * @date Jul 6, 2014
+ * @author Andrey Belomutskiy, (c) 2012-2014
+ */
+
+#include "table_helper.h"
+#include "efilib.h"
+#include "interpolation.h"
+
+void setTableBin2(float array[], int size, float l, float r, float precision) {
+ for (int i = 0; i < size; i++) {
+ float value = interpolate(0, l, size - 1, r, i);
+ /**
+ * rounded values look nicer, also we want to avoid precision mismatch with Tuner Studio
+ */
+ array[i] = efiRound(value, precision);
+ }
+}
+
+void setTableBin(float array[], int size, float l, float r) {
+ setTableBin2(array, size, l, r, 0.01);
+}
+
+void setRpmTableBin(float array[], int size) {
+ setTableBin2(array, size, 800, 7000, 1);
+}
diff --git a/firmware/controllers/core/table_helper.h b/firmware/controllers/core/table_helper.h
new file mode 100644
index 0000000000..5eee3266d1
--- /dev/null
+++ b/firmware/controllers/core/table_helper.h
@@ -0,0 +1,56 @@
+/**
+ * @file table_helper.h
+ *
+ * @date Jul 6, 2014
+ * @author Andrey Belomutskiy, (c) 2012-2014
+ */
+#ifndef TABLE_HELPER_H_
+#define TABLE_HELPER_H_
+
+#include
+#include "error_handling.h"
+
+// 'random' value to be sure we are not treating any non-zero trash as TRUE
+#define MAGIC_TRUE_VALUE 153351512
+
+template
+class Map3D {
+public:
+ void init(float table[RPM_BIN_SIZE][LOAD_BIN_SIZE]);
+ float getValue(float x, float xBin[], float y, float yBin[]);
+ void setAll(float value);
+private:
+ float *pointers[LOAD_BIN_SIZE];
+ int initialized;
+};
+
+template
+void Map3D::init(float table[RPM_BIN_SIZE][LOAD_BIN_SIZE]) {
+ for (int k = 0; k < LOAD_BIN_SIZE; k++)
+ pointers[k] = table[k];
+ initialized = MAGIC_TRUE_VALUE;
+}
+
+template
+float Map3D::getValue(float x, float xBin[], float y, float yBin[]) {
+ efiAssert(initialized == MAGIC_TRUE_VALUE, "map initialized", NAN);
+ return interpolate3d(x, xBin, LOAD_BIN_SIZE, y, yBin, RPM_BIN_SIZE, pointers);
+}
+
+template
+void Map3D::setAll(float value) {
+ efiAssertVoid(initialized == MAGIC_TRUE_VALUE, "map initialized");
+ for (int l = 0; l < LOAD_BIN_SIZE; l++) {
+ for (int r = 0; r < RPM_BIN_SIZE; r++) {
+ pointers[l][r] = value;
+ }
+ }
+}
+
+typedef Map3D<16, 16> Map3D1616;
+
+void setTableBin(float array[], int size, float l, float r);
+void setTableBin2(float array[], int size, float l, float r, float precision);
+void setRpmTableBin(float array[], int size);
+
+#endif /* TABLE_HELPER_H_ */
diff --git a/firmware/controllers/engine_controller.cpp b/firmware/controllers/engine_controller.cpp
index 66f2f7c43f..fe964b26c8 100644
--- a/firmware/controllers/engine_controller.cpp
+++ b/firmware/controllers/engine_controller.cpp
@@ -57,7 +57,7 @@ extern board_configuration_s *boardConfiguration;
persistent_config_container_s persistentState CCM_OPTIONAL;
engine_configuration_s *engineConfiguration = &persistentState.persistentConfiguration.engineConfiguration;
-board_configuration_s *boardConfiguration = &persistentState.persistentConfiguration.boardConfiguration;
+board_configuration_s *boardConfiguration = &persistentState.persistentConfiguration.engineConfiguration.bc;
/**
* CH_FREQUENCY is the number of system ticks in a second
@@ -244,7 +244,7 @@ void initEngineContoller(void) {
initAnalogChart();
#endif /* EFI_ANALOG_CHART */
- initAlgo();
+ initAlgo(engineConfiguration);
#if EFI_WAVE_ANALYZER
initWaveAnalyzer();
diff --git a/firmware/controllers/engine_controller.h b/firmware/controllers/engine_controller.h
index 2452d32adb..89dae2505c 100644
--- a/firmware/controllers/engine_controller.h
+++ b/firmware/controllers/engine_controller.h
@@ -13,16 +13,7 @@
#include "signal_executor.h"
#include "engine_configuration.h"
-#ifdef __cplusplus
-extern "C"
-{
-#endif /* __cplusplus */
-
char * getPinNameByAdcChannel(int hwChannel, char *buffer);
void initEngineContoller(void);
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
#endif /* ENGINE_STATUS_H_ */
diff --git a/firmware/controllers/flash_main.cpp b/firmware/controllers/flash_main.cpp
index cb5a4e4513..6af3a630bc 100644
--- a/firmware/controllers/flash_main.cpp
+++ b/firmware/controllers/flash_main.cpp
@@ -15,7 +15,6 @@
#include "flash.h"
#include "rusefi.h"
-//#include "tunerstudio.h"
#include "engine_controller.h"
#include "datalogging.h"
@@ -55,7 +54,7 @@ void writeToFlash(void) {
#if EFI_INTERNAL_FLASH
persistentState.size = PERSISTENT_SIZE;
persistentState.version = FLASH_DATA_VERSION;
- scheduleMsg(&logger, "FLASH_DATA_VERSION=%d", persistentState.version);
+ scheduleMsg(&logger, "flash compatible with %d", persistentState.version);
crc_t result = flashStateCrc(&persistentState);
persistentState.value = result;
scheduleMsg(&logger, "Reseting flash, size=%d", PERSISTENT_SIZE);
@@ -85,7 +84,7 @@ static void doResetConfiguration(void) {
boardConfiguration);
}
-static void readFromFlash(void) {
+void readFromFlash(void) {
printMsg(&logger, "readFromFlash()");
flashRead(FLASH_ADDR, (char *) &persistentState, PERSISTENT_SIZE);
@@ -112,6 +111,4 @@ void initFlash(void) {
addConsoleAction("readconfig", readFromFlash);
addConsoleAction("writeconfig", writeToFlash);
addConsoleAction("resetconfig", doResetConfiguration);
-
- readFromFlash();
}
diff --git a/firmware/controllers/flash_main.h b/firmware/controllers/flash_main.h
index d6c1594b28..1e127034eb 100644
--- a/firmware/controllers/flash_main.h
+++ b/firmware/controllers/flash_main.h
@@ -11,13 +11,14 @@
#include "engine_configuration.h"
-#define FLASH_DATA_VERSION 3601
+#define FLASH_DATA_VERSION 3880
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
+void readFromFlash(void);
void initFlash(void);
void writeToFlash(void);
diff --git a/firmware/controllers/ignition_central.c b/firmware/controllers/ignition_central.c
index 1aa6f724a3..9a5668a5a5 100644
--- a/firmware/controllers/ignition_central.c
+++ b/firmware/controllers/ignition_central.c
@@ -34,8 +34,8 @@ extern board_configuration_s *boardConfiguration;
void initIgnitionCentral(void) {
initLogging(&logger, "IgnitionCentral");
- outputPinRegisterExt2("sparkout1", SPARKOUT_1_OUTPUT, boardConfiguration->ignitionPins[0], &boardConfiguration->ignitionPinMode);
- outputPinRegisterExt2("sparkout2", SPARKOUT_2_OUTPUT, boardConfiguration->ignitionPins[1], &boardConfiguration->ignitionPinMode);
- outputPinRegisterExt2("sparkout3", SPARKOUT_3_OUTPUT, boardConfiguration->ignitionPins[2], &boardConfiguration->ignitionPinMode);
- outputPinRegisterExt2("sparkout4", SPARKOUT_4_OUTPUT, boardConfiguration->ignitionPins[3], &boardConfiguration->ignitionPinMode);
+ for (int i = 0; i < engineConfiguration->cylindersCount; i++) {
+ io_pin_e pin = (io_pin_e)((int)INJECTOR_1_OUTPUT + i);
+ outputPinRegisterExt2(getPinName(pin), pin, boardConfiguration->ignitionPins[i], &boardConfiguration->ignitionPinMode);
+ }
}
diff --git a/firmware/controllers/injector_central.cpp b/firmware/controllers/injector_central.cpp
index bce7c23299..c083bb58a3 100644
--- a/firmware/controllers/injector_central.cpp
+++ b/firmware/controllers/injector_central.cpp
@@ -139,24 +139,16 @@ void initInjectorCentral(void) {
for (int i = 0; i < engineConfiguration->cylindersCount; i++)
is_injector_enabled[i] = true;
- printStatus();
// todo: should we move this code closer to the injection logic?
- // todo: dynamic initialization
- // todo: consider actual cylinders count
- outputPinRegisterExt2("injector1", INJECTOR_1_OUTPUT, boardConfiguration->injectionPins[0],
- &boardConfiguration->injectionPinMode);
- outputPinRegisterExt2("injector2", INJECTOR_2_OUTPUT, boardConfiguration->injectionPins[1],
- &boardConfiguration->injectionPinMode);
- outputPinRegisterExt2("injector3", INJECTOR_3_OUTPUT, boardConfiguration->injectionPins[2],
- &boardConfiguration->injectionPinMode);
- outputPinRegisterExt2("injector4", INJECTOR_4_OUTPUT, boardConfiguration->injectionPins[3],
- &boardConfiguration->injectionPinMode);
- outputPinRegisterExt2("injector5", INJECTOR_5_OUTPUT, boardConfiguration->injectionPins[4],
- &boardConfiguration->injectionPinMode);
- outputPinRegisterExt2("injector5", INJECTOR_6_OUTPUT, boardConfiguration->injectionPins[5],
- &boardConfiguration->injectionPinMode);
+ for (int i = 0; i < engineConfiguration->cylindersCount; i++) {
+ io_pin_e pin = (io_pin_e)((int)INJECTOR_1_OUTPUT + i);
+ outputPinRegisterExt2(getPinName(pin), pin,
+ boardConfiguration->injectionPins[i], &boardConfiguration->injectionPinMode);
+ }
+
+ printStatus();
addConsoleActionII("injector", setInjectorEnabled);
addConsoleActionSSS("fuelbench", &fuelbench);
diff --git a/firmware/controllers/math/engine_math.cpp b/firmware/controllers/math/engine_math.cpp
index 9c74451971..aa9b7d12dc 100644
--- a/firmware/controllers/math/engine_math.cpp
+++ b/firmware/controllers/math/engine_math.cpp
@@ -42,14 +42,14 @@
* @deprecated
*/
float getOneDegreeTimeMs(int rpm) {
- return 1000.0 * 60 / 360 / rpm;
+ return 1000.0f * 60 / 360 / rpm;
}
/**
* @return time needed to rotate crankshaft by one degree, in microseconds.
*/
float getOneDegreeTimeUs(int rpm) {
- return 1000000.0 * 60 / 360 / rpm;
+ return 1000000.0f * 60 / 360 / rpm;
}
/**
@@ -67,7 +67,7 @@ float fixAngle(float angle) {
// I guess this implementation would be faster than 'angle % 720'
while (angle < 0)
angle += 720;
- while (angle > 720)
+ while (angle >= 720)
angle -= 720;
return angle;
}
@@ -77,7 +77,7 @@ float fixAngle(float angle) {
*
*/
float getEngineLoadT(engine_configuration_s *engineConfiguration) {
- switch (engineConfiguration->engineLoadMode) {
+ switch (engineConfiguration->algorithm) {
case LM_MAF:
return getMaf();
case LM_MAP:
@@ -88,7 +88,7 @@ float getEngineLoadT(engine_configuration_s *engineConfiguration) {
// TODO: real implementation
return getMap();
default:
- firmwareError("Unexpected engine load parameter: %d", engineConfiguration->engineLoadMode);
+ firmwareError("Unexpected engine load parameter: %d", engineConfiguration->algorithm);
return -1;
}
}
@@ -113,26 +113,26 @@ int isCrankingRT(engine_configuration_s *engineConfiguration, int rpm) {
return rpm > 0 && rpm < engineConfiguration->crankingSettings.crankingRpm;
}
-OutputSignalList ignitionSignals;
-OutputSignalList injectonSignals;
+OutputSignalList injectonSignals CCM_OPTIONAL;
static void registerSparkEvent(engine_configuration_s const *engineConfiguration, trigger_shape_s * s,
- IgnitionEventList *list, OutputSignal *actuator, float localAdvance, float dwell) {
+ IgnitionEventList *list, io_pin_e pin, float localAdvance, float dwell) {
IgnitionEvent *event = list->getNextActuatorEvent();
if (event == NULL)
return; // error already reported
+ event->io_pin = pin;
+
event->advance = localAdvance;
- registerActuatorEventExt(engineConfiguration, s, &event->actuator, actuator, localAdvance - dwell);
+ findTriggerPosition(engineConfiguration, s, &event->dwellPosition, localAdvance - dwell);
}
void initializeIgnitionActions(float advance, float dwellAngle, engine_configuration_s *engineConfiguration,
engine_configuration2_s *engineConfiguration2, IgnitionEventList *list) {
efiAssertVoid(engineConfiguration->cylindersCount > 0, "cylindersCount");
- ignitionSignals.clear();
list->resetEventList();
@@ -140,15 +140,15 @@ void initializeIgnitionActions(float advance, float dwellAngle, engine_configura
case IM_ONE_COIL:
for (int i = 0; i < engineConfiguration->cylindersCount; i++) {
// todo: extract method
- float localAdvance = advance + 720.0 * i / engineConfiguration->cylindersCount;
+ float localAdvance = advance + 720.0f * i / engineConfiguration->cylindersCount;
registerSparkEvent(engineConfiguration, &engineConfiguration2->triggerShape, list,
- ignitionSignals.add(SPARKOUT_1_OUTPUT), localAdvance, dwellAngle);
+ SPARKOUT_1_OUTPUT, localAdvance, dwellAngle);
}
break;
case IM_WASTED_SPARK:
for (int i = 0; i < engineConfiguration->cylindersCount; i++) {
- float localAdvance = advance + 720.0 * i / engineConfiguration->cylindersCount;
+ float localAdvance = advance + 720.0f * i / engineConfiguration->cylindersCount;
int wastedIndex = i % (engineConfiguration->cylindersCount / 2);
@@ -156,17 +156,17 @@ void initializeIgnitionActions(float advance, float dwellAngle, engine_configura
io_pin_e ioPin = (io_pin_e) (SPARKOUT_1_OUTPUT + id);
registerSparkEvent(engineConfiguration, &engineConfiguration2->triggerShape, list,
- ignitionSignals.add(ioPin), localAdvance, dwellAngle);
+ ioPin, localAdvance, dwellAngle);
}
break;
case IM_INDIVIDUAL_COILS:
for (int i = 0; i < engineConfiguration->cylindersCount; i++) {
- float localAdvance = advance + 720.0 * i / engineConfiguration->cylindersCount;
+ float localAdvance = advance + 720.0f * i / engineConfiguration->cylindersCount;
io_pin_e pin = (io_pin_e) ((int) SPARKOUT_1_OUTPUT + getCylinderId(engineConfiguration->firingOrder, i) - 1);
- registerSparkEvent(engineConfiguration, &engineConfiguration2->triggerShape, list, ignitionSignals.add(pin),
+ registerSparkEvent(engineConfiguration, &engineConfiguration2->triggerShape, list, pin,
localAdvance, dwellAngle);
}
break;
@@ -176,6 +176,16 @@ void initializeIgnitionActions(float advance, float dwellAngle, engine_configura
}
}
+static void registerInjectionEvent(engine_configuration_s const *e,
+ trigger_shape_s *s,
+ ActuatorEventList *list,
+ io_pin_e pin,
+ float angle
+ ) {
+ registerActuatorEventExt(e, s, list->getNextActuatorEvent(), injectonSignals.add(pin), angle);
+
+}
+
void addFuelEvents(engine_configuration_s const *e, engine_configuration2_s *engineConfiguration2,
ActuatorEventList *list, injection_mode_e mode) {
list->resetEventList();
@@ -189,7 +199,7 @@ void addFuelEvents(engine_configuration_s const *e, engine_configuration2_s *eng
for (int i = 0; i < e->cylindersCount; i++) {
io_pin_e pin = (io_pin_e) ((int) INJECTOR_1_OUTPUT + getCylinderId(e->firingOrder, i) - 1);
float angle = baseAngle + i * 720.0 / e->cylindersCount;
- registerActuatorEventExt(e, s, list->getNextActuatorEvent(), injectonSignals.add(pin), angle);
+ registerInjectionEvent(e, s, list, pin, angle);
}
break;
case IM_SIMULTANEOUS:
@@ -198,7 +208,7 @@ void addFuelEvents(engine_configuration_s const *e, engine_configuration2_s *eng
for (int j = 0; j < e->cylindersCount; j++) {
io_pin_e pin = (io_pin_e) ((int) INJECTOR_1_OUTPUT + j);
- registerActuatorEventExt(e, s, list->getNextActuatorEvent(), injectonSignals.add(pin), angle);
+ registerInjectionEvent(e, s, list, pin, angle);
}
}
break;
@@ -206,7 +216,7 @@ void addFuelEvents(engine_configuration_s const *e, engine_configuration2_s *eng
for (int i = 0; i < e->cylindersCount; i++) {
io_pin_e pin = (io_pin_e) ((int) INJECTOR_1_OUTPUT + (i % 2));
float angle = baseAngle + i * 720.0 / e->cylindersCount;
- registerActuatorEventExt(e, s, list->getNextActuatorEvent(), injectonSignals.add(pin), angle);
+ registerInjectionEvent(e, s, list, pin, angle);
}
break;
default:
@@ -228,12 +238,16 @@ float getSparkDwellMsT(engine_configuration_s *engineConfiguration, int rpm) {
return interpolate2d(rpm, engineConfiguration->sparkDwellBins, engineConfiguration->sparkDwell, DWELL_CURVE_SIZE);
}
+int getEngineCycleEventCount2(operation_mode_e mode, trigger_shape_s * s) {
+ return mode == FOUR_STROKE_CAM_SENSOR ? s->getSize() : 2 * s->getSize();
+}
+
/**
* Trigger event count equals engine cycle event count if we have a cam sensor.
* Two trigger cycles make one engine cycle in case of a four stroke engine If we only have a cranksensor.
*/
int getEngineCycleEventCount(engine_configuration_s const *engineConfiguration, trigger_shape_s * s) {
- return getOperationMode(engineConfiguration) == FOUR_STROKE_CAM_SENSOR ? s->getSize() : 2 * s->getSize();
+ return getEngineCycleEventCount2(getOperationMode(engineConfiguration), s);
}
void findTriggerPosition(engine_configuration_s const *engineConfiguration, trigger_shape_s * s,
@@ -241,37 +255,40 @@ void findTriggerPosition(engine_configuration_s const *engineConfiguration, trig
angleOffset = fixAngle(angleOffset + engineConfiguration->globalTriggerAngleOffset);
- // todo: migrate to crankAngleRange?
- float firstAngle = s->wave.getAngle(s->triggerShapeSynchPointIndex, engineConfiguration, s);
-
int engineCycleEventCount = getEngineCycleEventCount(engineConfiguration, s);
- // let's find the last trigger angle which is less or equal to the desired angle
- int i;
- for (i = 0; i < engineCycleEventCount - 1; i++) {
- // todo: we need binary search here
- float angle = fixAngle(
- s->wave.getAngle((s->triggerShapeSynchPointIndex + i + 1) % engineCycleEventCount, engineConfiguration, s)
- - firstAngle);
- if (angle > angleOffset)
+ int middle;
+ int left = 0;
+ int right = engineCycleEventCount - 1;
+
+ /**
+ * Let's find the last trigger angle which is less or equal to the desired angle
+ * todo: extract binary search as template method?
+ */
+ while (true) {
+ middle = (left + right) / 2;
+
+ if (middle == left)
break;
+
+ if (angleOffset < s->eventAngles[middle]) {
+ right = middle;
+ } else if (angleOffset > s->eventAngles[middle]) {
+ left = middle;
+ } else {
+ break;
+ }
+
}
- // explicit check for zero to avoid issues where logical zero is not exactly zero due to float nature
- float eventAngle;
- if (i == 0) {
- eventAngle = 0;
- } else {
- eventAngle = fixAngle(
- s->wave.getAngle((s->triggerShapeSynchPointIndex + i) % engineCycleEventCount, engineConfiguration, s)
- - firstAngle);
- }
+
+ float eventAngle = s->eventAngles[middle];
if (angleOffset < eventAngle) {
firmwareError("angle constraint violation in registerActuatorEventExt(): %f/%f", angleOffset, eventAngle);
return;
}
- position->eventIndex = i;
+ position->eventIndex = middle;
position->eventAngle = eventAngle;
position->angleOffset = angleOffset - eventAngle;
}
@@ -318,8 +335,8 @@ int getCylinderId(firing_order_e firingOrder, int index) {
void prepareOutputSignals(engine_configuration_s *engineConfiguration, engine_configuration2_s *engineConfiguration2) {
// todo: move this reset into decoder
- engineConfiguration2->triggerShape.triggerShapeSynchPointIndex = findTriggerZeroEventIndex(
- &engineConfiguration2->triggerShape, &engineConfiguration->triggerConfig);
+ engineConfiguration2->triggerShape.setTriggerShapeSynchPointIndex(findTriggerZeroEventIndex(
+ &engineConfiguration2->triggerShape, &engineConfiguration->triggerConfig));
injectonSignals.clear();
EventHandlerConfiguration *config = &engineConfiguration2->engineEventConfiguration;
@@ -329,16 +346,6 @@ void prepareOutputSignals(engine_configuration_s *engineConfiguration, engine_co
engineConfiguration->injectionMode);
}
-void setTableBin(float array[], int size, float l, float r) {
- for (int i = 0; i < size; i++) {
- float value = interpolate(0, l, size - 1, r, i);
- /**
- * rounded values look nicer, also we want to avoid precision mismatch with Tuner Studio
- */
- array[i] = efiRound(value, 0.01);
- }
-}
-
void setFuelRpmBin(engine_configuration_s *engineConfiguration, float l, float r) {
setTableBin(engineConfiguration->fuelRpmBins, FUEL_RPM_COUNT, l, r);
}
diff --git a/firmware/controllers/math/engine_math.h b/firmware/controllers/math/engine_math.h
index abc5ac50cb..6a2409535d 100644
--- a/firmware/controllers/math/engine_math.h
+++ b/firmware/controllers/math/engine_math.h
@@ -13,48 +13,14 @@
#ifdef __cplusplus
#include "ec2.h"
#include "trigger_structure.h"
+#include "table_helper.h"
+
void findTriggerPosition(engine_configuration_s const *engineConfiguration, trigger_shape_s * s,
event_trigger_position_s *position, float angleOffset);
int isInjectionEnabled(engine_configuration2_s const *engineConfiguration2);
-// 'random' value to be sure we are not treating any non-zero trash as TRUE
-#define MAGIC_TRUE_VALUE 153351512
-
-template
-class Map3D {
-public:
- void init(float table[RPM_BIN_SIZE][LOAD_BIN_SIZE]);
- float getValue(float x, float xBin[], float y, float yBin[]);
- void setAll(float value);
-private:
- float *pointers[LOAD_BIN_SIZE];
- int initialized;
-};
-
-template
-void Map3D::init(float table[RPM_BIN_SIZE][LOAD_BIN_SIZE]) {
- for (int k = 0; k < LOAD_BIN_SIZE; k++)
- pointers[k] = table[k];
- initialized = MAGIC_TRUE_VALUE;
-}
-
-template
-float Map3D::getValue(float x, float xBin[], float y, float yBin[]) {
- efiAssert(initialized == MAGIC_TRUE_VALUE, "fuel map initialized", NAN);
- return interpolate3d(x, xBin, LOAD_BIN_SIZE, y, yBin, RPM_BIN_SIZE, pointers);
-}
-
-template
-void Map3D::setAll(float value) {
- for (int l = 0; l < LOAD_BIN_SIZE; l++) {
- for (int r = 0; r < RPM_BIN_SIZE; r++) {
- pointers[l][r] = value;
- }
- }
-}
-
-typedef Map3D<16, 16> Map3D1616;
+float fixAngle(float angle);
#endif
@@ -63,8 +29,6 @@ extern "C"
{
#endif /* __cplusplus */
-//float getDefaultVE(int rpm);
-
float getDefaultFuel(int rpm, float map);
float getOneDegreeTimeMs(int rpm);
@@ -74,19 +38,14 @@ float getCrankshaftRevolutionTimeMs(int rpm);
int isCrankingRT(engine_configuration_s *engineConfiguration, int rpm);
#define isCrankingR(rpm) isCrankingRT(engineConfiguration, rpm)
-float fixAngle(float angle);
-float getTriggerEventAngle(int triggerEventIndex);
-
float getEngineLoadT(engine_configuration_s *engineConfiguration);
#define getEngineLoad() getEngineLoadT(engineConfiguration)
float getSparkDwellMsT(engine_configuration_s *engineConfiguration, int rpm);
#define getSparkDwellMs(rpm) getSparkDwellMsT(engineConfiguration, rpm)
-
int getCylinderId(firing_order_e firingOrder, int index);
-void setTableBin(float array[], int size, float l, float r);
void setFuelRpmBin(engine_configuration_s *engineConfiguration, float l, float r);
void setFuelLoadBin(engine_configuration_s *engineConfiguration, float l, float r);
void setTimingRpmBin(engine_configuration_s *engineConfiguration, float l, float r);
diff --git a/firmware/controllers/math/speed_density.cpp b/firmware/controllers/math/speed_density.cpp
index 53f2d51b3d..afbd26631a 100644
--- a/firmware/controllers/math/speed_density.cpp
+++ b/firmware/controllers/math/speed_density.cpp
@@ -45,34 +45,48 @@ float getTCharge(int rpm, int tps, float coolantTemp, float airTemp) {
*/
#define GAS_R 0.28705
+/**
+ * @return value in seconds
+ */
float sdMath(engine_configuration_s *engineConfiguration, float VE, float MAP, float AFR, float temp) {
float injectorFlowRate = cc_minute_to_gramm_second(engineConfiguration->injectorFlow);
float Vol = engineConfiguration->displacement / engineConfiguration->cylindersCount;
return (Vol * VE * MAP) / (AFR * injectorFlowRate * GAS_R * temp);
}
+/**
+ * @return value in Milliseconds
+ */
float getSpeedDensityFuel(Engine *engine) {
int rpm = engine->rpmCalculator->rpm();
+ engine_configuration_s *engineConfiguration = engine->engineConfiguration;
+
float tps = getTPS();
float coolantC = getCoolantTemperature();
float intakeC = getIntakeAirTemperature();
- float tChargeK = convertCelciusToKelvin(getTCharge(rpm, tps, coolantC, intakeC));
- float MAP = getMap();
- float VE = 0.8;//veMap.getValue(rpm)
- float AFR = 14.7;
-
- return sdMath(engine->engineConfiguration, VE, MAP, AFR, tChargeK);
+ float tChargeK = convertCelsiusToKelvin(getTCharge(rpm, tps, coolantC, intakeC));
+ float map = getMap();
+ float VE = veMap.getValue(map, engineConfiguration->veLoadBins, rpm,
+ engineConfiguration->veRpmBins);
+ float AFR = afrMap.getValue(map, engineConfiguration->afrLoadBins, rpm,
+ engineConfiguration->afrRpmBins);
+ return sdMath(engine->engineConfiguration, VE, map, AFR, tChargeK) * 1000;
}
void setDetaultVETable(engine_configuration_s *engineConfiguration) {
- setTableBin(engineConfiguration->veRpmBins, FUEL_RPM_COUNT, 800, 7000);
+ setRpmTableBin(engineConfiguration->veRpmBins, VE_RPM_COUNT);
+ setTableBin2(engineConfiguration->veLoadBins, VE_LOAD_COUNT, 10, 300, 1);
+
+ setRpmTableBin(engineConfiguration->afrRpmBins, AFR_RPM_COUNT);
+ setTableBin2(engineConfiguration->afrLoadBins, VE_LOAD_COUNT, 10, 300, 1);
veMap.setAll(0.8);
+ afrMap.setAll(14.7);
}
-void initSpeedDensity(configuration_s *config) {
- veMap.init(config->engineConfiguration->veTable);
- afrMap.init(config->engineConfiguration->afrTable);
+void initSpeedDensity(engine_configuration_s *engineConfiguration) {
+ veMap.init(engineConfiguration->veTable);
+ afrMap.init(engineConfiguration->afrTable);
}
diff --git a/firmware/controllers/math/speed_density.h b/firmware/controllers/math/speed_density.h
index 8ee631bc85..c612d2cda7 100644
--- a/firmware/controllers/math/speed_density.h
+++ b/firmware/controllers/math/speed_density.h
@@ -18,6 +18,7 @@ float sdMath(engine_configuration_s *engineConfiguration, float VE, float MAP, f
#define cc_minute_to_gramm_second(ccm) ((ccm) * 0.0119997981)
-void initSpeedDensity(configuration_s *config);
+void setDetaultVETable(engine_configuration_s *engineConfiguration);
+void initSpeedDensity(engine_configuration_s *engineConfiguration);
#endif /* SPEED_DENSITY_H_ */
diff --git a/firmware/controllers/sensors/thermistors.cpp b/firmware/controllers/sensors/thermistors.cpp
index fe99f85901..c2be6ca4b3 100644
--- a/firmware/controllers/sensors/thermistors.cpp
+++ b/firmware/controllers/sensors/thermistors.cpp
@@ -17,10 +17,14 @@
#include "engine_math.h"
#include "ec2.h"
+// Celsius
+#define LIMPING_MODE_IAT_TEMPERATURE 30
+#define LIMPING_MODE_CLT_TEMPERATURE 70
+
extern engine_configuration_s *engineConfiguration;
extern engine_configuration2_s *engineConfiguration2;
-static bool_t initialized = FALSE;
+static bool initialized = false;
/**
* http://en.wikipedia.org/wiki/Voltage_divider
@@ -44,29 +48,21 @@ float convertResistanceToKelvinTemperature(float resistance, ThermistorConf *the
//warning("Invalid resistance in convertResistanceToKelvinTemperature=", resistance);
return 0;
}
- float logR = log(resistance);
+ float logR = logf(resistance);
return 1 / (thermistor->s_h_a + thermistor->s_h_b * logR + thermistor->s_h_c * logR * logR * logR);
}
-float convertKelvinToC(float tempK) {
- return tempK - KELV;
-}
-
-float convertCelciusToKelvin(float tempC) {
- return tempC + KELV;
-}
-
-float convertCelciustoF(float tempC) {
+float convertCelsiustoF(float tempC) {
return tempC * 9 / 5 + 32;
}
-float convertFtoCelcius(float tempF) {
+float convertFtoCelsius(float tempF) {
return (tempF - 32) / 9 * 5;
}
float convertKelvinToFahrenheit(float kelvin) {
- float tempC = convertKelvinToC(kelvin);
- return convertCelciustoF(tempC);
+ float tempC = convertKelvinToCelcius(kelvin);
+ return convertCelsiustoF(tempC);
}
float getKelvinTemperature(float resistance, ThermistorConf *thermistor) {
@@ -94,7 +90,7 @@ float getTemperatureC(Thermistor *thermistor) {
float resistance = getResistance(thermistor);
float kelvinTemperature = getKelvinTemperature(resistance, thermistor->config);
- return convertKelvinToC(kelvinTemperature);
+ return convertKelvinToCelcius(kelvinTemperature);
}
int isValidCoolantTemperature(float temperature) {
@@ -108,12 +104,14 @@ int isValidIntakeAirTemperature(float temperature) {
}
/**
- * @return coolant temperature, in Celcius
+ * @return coolant temperature, in Celsius
*/
float getCoolantTemperature(void) {
float temperature = getTemperatureC(&engineConfiguration2->clt);
- if (!isValidCoolantTemperature(temperature))
- return NAN;
+ if (!isValidCoolantTemperature(temperature)) {
+ warning(OBD_PCM_Processor_Fault, "unrealistic coolant temperature %f", temperature);
+ return LIMPING_MODE_CLT_TEMPERATURE;
+ }
return temperature;
}
@@ -134,9 +132,9 @@ void prepareThermistorCurve(ThermistorConf * config) {
float T2 = config->tempC_2 + KELV;
float T3 = config->tempC_3 + KELV;
- float L1 = log(config->resistance_1);
- float L2 = log(config->resistance_2);
- float L3 = log(config->resistance_3);
+ float L1 = logf(config->resistance_1);
+ float L2 = logf(config->resistance_2);
+ float L3 = logf(config->resistance_3);
float Y1 = 1 / T1;
float Y2 = 1 / T2;
@@ -150,11 +148,14 @@ void prepareThermistorCurve(ThermistorConf * config) {
config->s_h_a = Y1 - (config->s_h_b + L1 * L1 * config->s_h_c) * L1;
}
+/**
+ * @return Celsius value
+ */
float getIntakeAirTemperature(void) {
float temperature = getTemperatureC(&engineConfiguration2->iat);
if (!isValidIntakeAirTemperature(temperature)) {
warning(OBD_PCM_Processor_Fault, "unrealistic intake temperature %f", temperature);
- return NAN;
+ return LIMPING_MODE_IAT_TEMPERATURE;
}
return temperature;
}
diff --git a/firmware/controllers/sensors/thermistors.h b/firmware/controllers/sensors/thermistors.h
index 9bbc2f99ef..2dd6fad8b8 100644
--- a/firmware/controllers/sensors/thermistors.h
+++ b/firmware/controllers/sensors/thermistors.h
@@ -26,10 +26,10 @@ float getR1InVoltageDividor(float Vout, float Vin, float r2);
float getR2InVoltageDividor(float Vout, float Vin, float r1);
float getTempK(float resistance);
/**
- * converts Kelvin temperature into Celcius temperature
+ * converts Kelvin temperature into Celsius temperature
*/
-float convertKelvinToCelcius(float tempK);
-float convertCelciusToKelvin(float tempC);
+#define convertKelvinToCelcius(tempK) ((tempK) - KELV)
+#define convertCelsiusToKelvin(tempC) ((tempC) + KELV)
float convertCelciustoF(float tempC);
float convertFtoCelcius(float tempF);
diff --git a/firmware/controllers/settings.cpp b/firmware/controllers/settings.cpp
index 1f47b43277..5fd3bfb01d 100644
--- a/firmware/controllers/settings.cpp
+++ b/firmware/controllers/settings.cpp
@@ -19,10 +19,12 @@
#include "ec2.h"
#include "map.h"
#include "trigger_decoder.h"
+#include "console_io.h"
#if EFI_PROD_CODE
#include "rusefi.h"
#include "pin_repository.h"
+#include "hardware.h"
#endif /* EFI_PROD_CODE */
#if EFI_INTERNAL_FLASH
@@ -114,7 +116,7 @@ static const char * pinModeToString(pin_output_mode_e mode) {
}
}
-static const char * boolToString(bool_t value) {
+static const char * boolToString(bool value) {
return value ? "Yes" : "No";
}
@@ -201,6 +203,7 @@ void printConfiguration(engine_configuration_s *engineConfiguration, engine_conf
scheduleMsg(&logger, "primary trigger input: %s", hwPortname(boardConfiguration->primaryTriggerInputPin));
+ scheduleMsg(&logger, "boardTestModeJumperPin: %s", hwPortname(boardConfiguration->boardTestModeJumperPin));
#endif /* EFI_PROD_CODE */
scheduleMsg(&logger, "isInjectionEnabledFlag %s", boolToString(engineConfiguration2->isInjectionEnabledFlag));
@@ -412,8 +415,8 @@ static void setIgnitionMode(int value) {
doPrintConfiguration();
}
-static void setTotalToothCount(int value) {
- engineConfiguration->triggerConfig.totalToothCount = value;
+static void setToothedWheel(int total, int skipped) {
+ setToothedWheelConfiguration(engineConfiguration, total, skipped);
initializeTriggerShape(&logger, engineConfiguration, engineConfiguration2);
incrementGlobalConfigurationVersion();
doPrintConfiguration();
@@ -484,6 +487,23 @@ static void disableInjection(void) {
scheduleMsg(&logger, "injection disabled");
}
+#if EFI_WAVE_CHART
+extern int waveChartUsedSize;
+#endif
+
+static void printAllInfo(void) {
+ printTemperatureInfo();
+ printTPSInfo();
+ printMAPInfo();
+#if EFI_WAVE_CHART
+ scheduleMsg(&logger, "waveChartUsedSize=%d", waveChartUsedSize);
+#endif
+#if EFI_PROD_CODE
+ scheduleMsg(&logger, "console mode jumper: %s", boolToString(!GET_CONSOLE_MODE_VALUE()));
+ scheduleMsg(&logger, "board test mode jumper: %s", boolToString(GET_BOARD_TEST_MODE_VALUE()));
+#endif
+}
+
void initSettings(void) {
initLoggingExt(&logger, "settings control", LOGGING_BUFFER, sizeof(LOGGING_BUFFER));
@@ -491,6 +511,7 @@ void initSettings(void) {
addConsoleAction("tempinfo", printTemperatureInfo);
addConsoleAction("tpsinfo", printTPSInfo);
addConsoleAction("mapinfo", printMAPInfo);
+ addConsoleAction("info", printAllInfo);
addConsoleActionI("set_ignition_offset", setIgnitionOffset);
addConsoleActionI("set_injection_offset", setInjectionOffset);
@@ -531,6 +552,6 @@ void initSettings(void) {
addConsoleAction("enable_injection", enableInjection);
addConsoleAction("disable_injection", disableInjection);
- addConsoleActionI("set_total_tooth_count", setTotalToothCount);
+ addConsoleActionII("set_toothed_wheel", setToothedWheel);
}
diff --git a/firmware/controllers/system/SingleTimerExecutor.cpp b/firmware/controllers/system/SingleTimerExecutor.cpp
index 3ec65e8b8d..a198935186 100644
--- a/firmware/controllers/system/SingleTimerExecutor.cpp
+++ b/firmware/controllers/system/SingleTimerExecutor.cpp
@@ -32,7 +32,7 @@ static void executorCallback(void *arg) {
}
Executor::Executor() {
- reentrantLock = FALSE;
+ reentrantLock = false;
}
void Executor::lock(void) {
@@ -76,7 +76,7 @@ void Executor::doExecute(uint64_t nowUs) {
firmwareError("Someone has stolen my lock");
return;
}
- reentrantLock = FALSE;
+ reentrantLock = false;
/**
* Let's set up the timer for the next execution
*/
diff --git a/firmware/controllers/system/SingleTimerExecutor.h b/firmware/controllers/system/SingleTimerExecutor.h
index 44744108a6..61d023c010 100644
--- a/firmware/controllers/system/SingleTimerExecutor.h
+++ b/firmware/controllers/system/SingleTimerExecutor.h
@@ -18,7 +18,7 @@ public:
void execute(uint64_t nowUs);
private:
EventQueue queue;
- bool_t reentrantLock;
+ bool reentrantLock;
void doExecute(uint64_t nowUs);
void lock(void);
void unlock(void);
diff --git a/firmware/controllers/system/event_queue.cpp b/firmware/controllers/system/event_queue.cpp
index f62204c347..aa88621c5f 100644
--- a/firmware/controllers/system/event_queue.cpp
+++ b/firmware/controllers/system/event_queue.cpp
@@ -18,7 +18,7 @@ EventQueue::EventQueue() {
head = NULL;
}
-bool_t EventQueue::checkIfPending(scheduling_s *scheduling) {
+bool EventQueue::checkIfPending(scheduling_s *scheduling) {
return assertNotInList(head, scheduling);
}
diff --git a/firmware/controllers/system/event_queue.h b/firmware/controllers/system/event_queue.h
index 398b0a832b..e46fa16326 100644
--- a/firmware/controllers/system/event_queue.h
+++ b/firmware/controllers/system/event_queue.h
@@ -16,7 +16,7 @@
#define QUEUE_LENGTH_LIMIT 1000
template
-bool_t assertNotInList(T *head, T*element) {
+bool assertNotInList(T *head, T*element) {
// this code is just to validate state, no functional load
T * current;
int counter = 0;
@@ -48,7 +48,7 @@ public:
int size(void);
scheduling_s *getForUnitText(int index);
private:
- bool_t checkIfPending(scheduling_s *scheduling);
+ bool checkIfPending(scheduling_s *scheduling);
scheduling_s *head;
};
diff --git a/firmware/controllers/system/pwm_generator_logic.cpp b/firmware/controllers/system/pwm_generator_logic.cpp
index 8d62c6a739..5a65515ad6 100644
--- a/firmware/controllers/system/pwm_generator_logic.cpp
+++ b/firmware/controllers/system/pwm_generator_logic.cpp
@@ -46,7 +46,7 @@ void SimplePwm::setSimplePwmDutyCycle(float dutyCycle) {
static uint64_t getNextSwitchTimeUs(PwmConfig *state) {
efiAssert(state->safe.phaseIndex < PWM_PHASE_MAX_COUNT, "phaseIndex range", 0);
int iteration = state->safe.iteration;
- float switchTime = state->multiWave.switchTimes[state->safe.phaseIndex];
+ float switchTime = state->multiWave.getSwitchTime(state->safe.phaseIndex);
float periodMs = state->safe.periodMs;
#if DEBUG_PWM
scheduleMsg(&logger, "iteration=%d switchTime=%f period=%f", iteration, switchTime, period);
@@ -131,7 +131,7 @@ void copyPwmParameters(PwmConfig *state, int phaseCount, float *switchTimes, int
state->phaseCount = phaseCount;
for (int phaseIndex = 0; phaseIndex < phaseCount; phaseIndex++) {
- state->multiWave.switchTimes[phaseIndex] = switchTimes[phaseIndex];
+ state->multiWave.setSwitchTime(phaseIndex, switchTimes[phaseIndex]);
for (int waveIndex = 0; waveIndex < waveCount; waveIndex++) {
// print("output switch time index (%d/%d) at %f to %d\r\n", phaseIndex,waveIndex,
diff --git a/firmware/controllers/trigger/main_trigger_callback.cpp b/firmware/controllers/trigger/main_trigger_callback.cpp
index f9578f46fe..06b4d9bf9f 100644
--- a/firmware/controllers/trigger/main_trigger_callback.cpp
+++ b/firmware/controllers/trigger/main_trigger_callback.cpp
@@ -79,10 +79,12 @@ static Logging logger;
static void handleFuelInjectionEvent(MainTriggerCallback *mainTriggerCallback, ActuatorEvent *event, int rpm) {
float fuelMs = getFuelMs(rpm) * mainTriggerCallback->engineConfiguration->globalFuelCorrection;
+ if (cisnan(fuelMs)) {
+ warning(OBD_PCM_Processor_Fault, "NaN injection pulse");
+ return;
+ }
if (fuelMs < 0) {
-#if EFI_PROD_CODE
- scheduleMsg(&logger, "ERROR: negative injectionPeriod %f", fuelMs);
-#endif
+ warning(OBD_PCM_Processor_Fault, "Negative injection pulse %f", fuelMs);
return;
}
@@ -128,8 +130,7 @@ static void handleSparkEvent(MainTriggerCallback *mainTriggerCallback, int event
return;
}
- ActuatorEvent *event = &iEvent->actuator;
- float sparkDelay = getOneDegreeTimeMs(rpm) * event->position.angleOffset;
+ float sparkDelay = getOneDegreeTimeMs(rpm) * iEvent->dwellPosition.angleOffset;
int isIgnitionError = sparkDelay < 0;
ignitionErrorDetection.add(isIgnitionError);
if (isIgnitionError) {
@@ -140,9 +141,6 @@ static void handleSparkEvent(MainTriggerCallback *mainTriggerCallback, int event
return;
}
- OutputSignal *signal = event->actuator;
- //scheduleOutput(event->actuator, sparkDelay, dwellMs);
-
if (cisnan(dwellMs)) {
firmwareError("NaN in scheduleOutput", dwellMs);
return;
@@ -152,13 +150,13 @@ static void handleSparkEvent(MainTriggerCallback *mainTriggerCallback, int event
* We are alternating two event lists in order to avoid a potential issue around revolution boundary
* when an event is scheduled within the next revolution.
*/
- scheduling_s * sUp = &signal->signalTimerUp[0];
- scheduling_s * sDown = &signal->signalTimerDown[0];
+ scheduling_s * sUp = &iEvent->signalTimerUp;
+ scheduling_s * sDown = &iEvent->signalTimerDown;
/**
* The start of charge is always within the current trigger event range, so just plain time-based scheduling
*/
- scheduleTask(sUp, (int) MS2US(sparkDelay), (schfunc_t) &turnPinHigh, (void *) signal);
+ scheduleTask(sUp, (int) MS2US(sparkDelay), (schfunc_t) &turnPinHigh, (void *) iEvent->io_pin);
/**
* Spark event is often happening during a later trigger event timeframe
* TODO: improve precision
@@ -173,7 +171,7 @@ static void handleSparkEvent(MainTriggerCallback *mainTriggerCallback, int event
*/
float timeTillIgnitionUs = getOneDegreeTimeUs(rpm) * iEvent->sparkPosition.angleOffset;
- scheduleTask(sDown, (int) timeTillIgnitionUs, (schfunc_t) &turnPinLow, (void*) signal);
+ scheduleTask(sDown, (int) timeTillIgnitionUs, (schfunc_t) &turnPinLow, (void*) iEvent->io_pin);
} else {
/**
* Spark should be scheduled in relation to some future trigger event, this way we get better firing precision
@@ -183,8 +181,6 @@ static void handleSparkEvent(MainTriggerCallback *mainTriggerCallback, int event
return;
LL_APPEND(iHead, iEvent);
-
- //scheduleTask(sDown, (int) MS2US(sparkDelay + dwellMs), (schfunc_t) &turnPinLow, (void*) signal);
}
}
@@ -205,19 +201,17 @@ static void handleSpark(MainTriggerCallback *mainTriggerCallback, int eventIndex
// time to fire a spark which was scheduled previously
LL_DELETE(iHead, current);
- ActuatorEvent *event = ¤t->actuator;
- OutputSignal *signal = event->actuator;
- scheduling_s * sDown = &signal->signalTimerDown[0];
+ scheduling_s * sDown = ¤t->signalTimerDown;
float timeTillIgnitionUs = getOneDegreeTimeUs(rpm) * current->sparkPosition.angleOffset;
- scheduleTask(sDown, (int) timeTillIgnitionUs, (schfunc_t) &turnPinLow, (void*) signal);
+ scheduleTask(sDown, (int) timeTillIgnitionUs, (schfunc_t) &turnPinLow, (void*) current->io_pin);
}
}
// scheduleSimpleMsg(&logger, "eventId spark ", eventIndex);
for (int i = 0; i < list->size; i++) {
IgnitionEvent *event = &list->events[i];
- if (event->actuator.position.eventIndex != eventIndex)
+ if (event->dwellPosition.eventIndex != eventIndex)
continue;
handleSparkEvent(mainTriggerCallback, eventIndex, event, rpm);
}
@@ -303,9 +297,14 @@ void onTriggerEvent(trigger_event_e ckpSignalType, int eventIndex, MainTriggerCa
#endif /* EFI_HISTOGRAMS */
}
+#include "wave_chart.h"
+
static void showTriggerHistogram(void) {
printAllCallbacksHistogram();
showMainHistogram();
+#if EFI_PROD_CODE
+ showWaveChartHistogram();
+#endif
}
static void showMainInfo(void) {
diff --git a/firmware/controllers/trigger/rpm_calculator.cpp b/firmware/controllers/trigger/rpm_calculator.cpp
index edab831516..f1209a22b1 100644
--- a/firmware/controllers/trigger/rpm_calculator.cpp
+++ b/firmware/controllers/trigger/rpm_calculator.cpp
@@ -131,16 +131,16 @@ static char shaft_signal_msg_index[15];
* updated here.
* This callback is invoked on interrupt thread.
*/
-void shaftPositionCallback(trigger_event_e ckpSignalType, int index, RpmCalculator *rpmState) {
+void rpmShaftPositionCallback(trigger_event_e ckpSignalType, int index, RpmCalculator *rpmState) {
itoa10(&shaft_signal_msg_index[1], index);
if (ckpSignalType == SHAFT_PRIMARY_UP) {
- addWaveChartEvent("crank", "up", (char*) shaft_signal_msg_index);
+ addWaveChartEvent(WC_CRANK1, WC_UP, (char*) shaft_signal_msg_index);
} else if (ckpSignalType == SHAFT_PRIMARY_DOWN) {
- addWaveChartEvent("crank", "down", (char*) shaft_signal_msg_index);
+ addWaveChartEvent(WC_CRANK1, WC_DOWN, (char*) shaft_signal_msg_index);
} else if (ckpSignalType == SHAFT_SECONDARY_UP) {
- addWaveChartEvent("crank2", "up", (char*) shaft_signal_msg_index);
+ addWaveChartEvent(WC_CRANK2, WC_UP, (char*) shaft_signal_msg_index);
} else if (ckpSignalType == SHAFT_SECONDARY_DOWN) {
- addWaveChartEvent("crank2", "down", (char*) shaft_signal_msg_index);
+ addWaveChartEvent(WC_CRANK2, WC_DOWN, (char*) shaft_signal_msg_index);
}
if (index != 0) {
@@ -154,7 +154,7 @@ void shaftPositionCallback(trigger_event_e ckpSignalType, int index, RpmCalculat
uint64_t nowUs = getTimeNowUs();
- bool_t hadRpmRecently = rpmState->isRunning();
+ bool hadRpmRecently = rpmState->isRunning();
if (hadRpmRecently) {
if (isNoisySignal(rpmState, nowUs)) {
@@ -210,7 +210,7 @@ void initRpmCalculator(void) {
strcpy((char*) shaft_signal_msg_index, "_");
- addTriggerEventListener((ShaftPositionListener)&shaftPositionCallback, "rpm reporter", &rpmState);
+ addTriggerEventListener((ShaftPositionListener)&rpmShaftPositionCallback, "rpm reporter", &rpmState);
}
#if EFI_PROD_CODE || EFI_SIMULATOR
diff --git a/firmware/controllers/trigger/rpm_calculator.h b/firmware/controllers/trigger/rpm_calculator.h
index 275366fd3d..9e6d33ceb2 100644
--- a/firmware/controllers/trigger/rpm_calculator.h
+++ b/firmware/controllers/trigger/rpm_calculator.h
@@ -11,6 +11,11 @@
#include
+#define WC_DOWN "d"
+#define WC_UP "u"
+#define WC_CRANK1 "c1"
+#define WC_CRANK2 "c2"
+
#define NOISY_RPM -1
#ifdef __cplusplus
@@ -36,7 +41,7 @@ public:
* @brief Current RPM
*/
int getRpmE(Engine *engine);
-void shaftPositionCallback(trigger_event_e ckpSignalType, int index, RpmCalculator *rpmState);
+void rpmShaftPositionCallback(trigger_event_e ckpSignalType, int index, RpmCalculator *rpmState);
#endif
#ifdef __cplusplus
diff --git a/firmware/controllers/trigger/trigger_bmw.cpp b/firmware/controllers/trigger/trigger_bmw.cpp
index fee005e3b1..06b48feaa2 100644
--- a/firmware/controllers/trigger/trigger_bmw.cpp
+++ b/firmware/controllers/trigger/trigger_bmw.cpp
@@ -15,11 +15,10 @@ static inline float addPair(trigger_shape_s *s, float a, float w) {
return a;
}
-void configureMiniCooperTriggerShape(engine_configuration_s *engineConfiguration,
- engine_configuration2_s *engineConfiguration2) {
- trigger_shape_s *s = &engineConfiguration2->triggerShape;
+void configureMiniCooperTriggerShape(trigger_config_s *triggerConfig,
+ trigger_shape_s *s) {
- s->reset();
+ s->reset(FOUR_STROKE_CAM_SENSOR);
// s->initialState[0] = 1;
@@ -68,5 +67,5 @@ void configureMiniCooperTriggerShape(engine_configuration_s *engineConfiguration
/**
* With just one tooth on camshaft synchronization is not needed
*/
- engineConfiguration->triggerConfig.isSynchronizationNeeded = FALSE;
+ triggerConfig->isSynchronizationNeeded = FALSE;
}
diff --git a/firmware/controllers/trigger/trigger_bmw.h b/firmware/controllers/trigger/trigger_bmw.h
index 91b4de6cd3..29a8c4c4fd 100644
--- a/firmware/controllers/trigger/trigger_bmw.h
+++ b/firmware/controllers/trigger/trigger_bmw.h
@@ -10,7 +10,7 @@
#include "engine_configuration.h"
#include "ec2.h"
-void configureMiniCooperTriggerShape(engine_configuration_s *engineConfiguration,
- engine_configuration2_s *engineConfiguration2);
+void configureMiniCooperTriggerShape(trigger_config_s *triggerConfig,
+ trigger_shape_s *s);
#endif /* TRIGGER_BMW_H_ */
diff --git a/firmware/controllers/trigger/trigger_central.cpp b/firmware/controllers/trigger/trigger_central.cpp
index c11d787ac0..6270f943b7 100644
--- a/firmware/controllers/trigger/trigger_central.cpp
+++ b/firmware/controllers/trigger/trigger_central.cpp
@@ -88,9 +88,9 @@ void TriggerCentral::handleShaftSignal(configuration_s *configuration, trigger_e
trigger_shape_s * triggerShape = &configuration->engineConfiguration2->triggerShape;
/**
- * This invocation changes the state of
+ * This invocation changes the state of triggerState
*/
- triggerState.processTriggerEvent(triggerShape, &configuration->engineConfiguration->triggerConfig, signal, nowUs);
+ triggerState.decodeTriggerEvent(triggerShape, &configuration->engineConfiguration->triggerConfig, signal, nowUs);
if (!triggerState.shaft_is_synchronized)
return; // we should not propagate event if we do not know where we are
diff --git a/firmware/controllers/trigger/trigger_central.h b/firmware/controllers/trigger/trigger_central.h
index 7f81372920..44550a7e13 100644
--- a/firmware/controllers/trigger/trigger_central.h
+++ b/firmware/controllers/trigger/trigger_central.h
@@ -30,17 +30,19 @@ private:
};
#endif
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-void addTriggerEventListener(ShaftPositionListener handler, const char *name, void *arg);
uint64_t getCrankEventCounter(void);
uint64_t getStartOfRevolutionIndex(void);
-int isSignalDecoderError(void);
void hwHandleShaftSignal(trigger_event_e signal);
void initTriggerCentral(void);
void printAllCallbacksHistogram(void);
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+void addTriggerEventListener(ShaftPositionListener handler, const char *name, void *arg);
+int isSignalDecoderError(void);
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
diff --git a/firmware/controllers/trigger/trigger_chrysler.cpp b/firmware/controllers/trigger/trigger_chrysler.cpp
index ccc01ff288..986e0b56a7 100644
--- a/firmware/controllers/trigger/trigger_chrysler.cpp
+++ b/firmware/controllers/trigger/trigger_chrysler.cpp
@@ -7,59 +7,59 @@
#include "trigger_chrysler.h"
-void configureNeonTriggerShape(trigger_shape_s *s) {
- s->reset();
+void configureNeonTriggerShape(trigger_config_s *triggerConfig, trigger_shape_s *s) {
+ s->reset(FOUR_STROKE_CAM_SENSOR);
// voodoo magic - we always need 720 at the end
int base = 720 - 560;
s->initialState[0] = 1;
- triggerAddEvent(s, base - 720 + 600, T_SECONDARY, TV_HIGH);
- triggerAddEvent(s, base - 720 + 604, T_SECONDARY, TV_LOW);
- triggerAddEvent(s, base - 720 + 616, T_SECONDARY, TV_HIGH);
- triggerAddEvent(s, base - 720 + 620, T_SECONDARY, TV_LOW);
- triggerAddEvent(s, base - 720 + 643, T_SECONDARY, TV_HIGH);
- triggerAddEvent(s, base - 720 + 648, T_SECONDARY, TV_LOW);
- triggerAddEvent(s, base - 720 + 671, T_SECONDARY, TV_HIGH);
- triggerAddEvent(s, base - 720 + 676, T_SECONDARY, TV_LOW);
+ s->addEvent(base - 720 + 600, T_SECONDARY, TV_HIGH);
+ s->addEvent(base - 720 + 604, T_SECONDARY, TV_LOW);
+ s->addEvent(base - 720 + 616, T_SECONDARY, TV_HIGH);
+ s->addEvent(base - 720 + 620, T_SECONDARY, TV_LOW);
+ s->addEvent(base - 720 + 643, T_SECONDARY, TV_HIGH);
+ s->addEvent(base - 720 + 648, T_SECONDARY, TV_LOW);
+ s->addEvent(base - 720 + 671, T_SECONDARY, TV_HIGH);
+ s->addEvent(base - 720 + 676, T_SECONDARY, TV_LOW);
- triggerAddEvent(s, base + 0, T_PRIMARY, TV_LOW);
+ s->addEvent(base + 0, T_PRIMARY, TV_LOW);
- triggerAddEvent(s, base + 20, T_SECONDARY, TV_HIGH);
- triggerAddEvent(s, base + 60, T_SECONDARY, TV_LOW);
- triggerAddEvent(s, base + 75, T_SECONDARY, TV_HIGH);
- triggerAddEvent(s, base + 79, T_SECONDARY, TV_LOW);
- triggerAddEvent(s, base + 101, T_SECONDARY, TV_HIGH);
- triggerAddEvent(s, base + 106, T_SECONDARY, TV_LOW);
- triggerAddEvent(s, base + 130, T_SECONDARY, TV_HIGH);
- triggerAddEvent(s, base + 135, T_SECONDARY, TV_LOW);
+ s->addEvent(base + 20, T_SECONDARY, TV_HIGH);
+ s->addEvent(base + 60, T_SECONDARY, TV_LOW);
+ s->addEvent(base + 75, T_SECONDARY, TV_HIGH);
+ s->addEvent(base + 79, T_SECONDARY, TV_LOW);
+ s->addEvent(base + 101, T_SECONDARY, TV_HIGH);
+ s->addEvent(base + 106, T_SECONDARY, TV_LOW);
+ s->addEvent(base + 130, T_SECONDARY, TV_HIGH);
+ s->addEvent(base + 135, T_SECONDARY, TV_LOW);
- triggerAddEvent(s, base + 200, T_PRIMARY, TV_HIGH); // width = 150
+ s->addEvent(base + 200, T_PRIMARY, TV_HIGH); // width = 150
- triggerAddEvent(s, base + 236, T_SECONDARY, TV_HIGH);
- triggerAddEvent(s, base + 239, T_SECONDARY, TV_LOW);
- triggerAddEvent(s, base + 250, T_SECONDARY, TV_HIGH);
- triggerAddEvent(s, base + 255, T_SECONDARY, TV_LOW);
- triggerAddEvent(s, base + 277, T_SECONDARY, TV_HIGH);
- triggerAddEvent(s, base + 282, T_SECONDARY, TV_LOW);
- triggerAddEvent(s, base + 305, T_SECONDARY, TV_HIGH);
- triggerAddEvent(s, base + 310, T_SECONDARY, TV_LOW);
+ s->addEvent(base + 236, T_SECONDARY, TV_HIGH);
+ s->addEvent(base + 239, T_SECONDARY, TV_LOW);
+ s->addEvent(base + 250, T_SECONDARY, TV_HIGH);
+ s->addEvent(base + 255, T_SECONDARY, TV_LOW);
+ s->addEvent(base + 277, T_SECONDARY, TV_HIGH);
+ s->addEvent(base + 282, T_SECONDARY, TV_LOW);
+ s->addEvent(base + 305, T_SECONDARY, TV_HIGH);
+ s->addEvent(base + 310, T_SECONDARY, TV_LOW);
- triggerAddEvent(s, base + 374, T_SECONDARY, TV_HIGH);
+ s->addEvent(base + 374, T_SECONDARY, TV_HIGH);
- triggerAddEvent(s, base + 395, T_PRIMARY, TV_LOW); // width =
+ s->addEvent(base + 395, T_PRIMARY, TV_LOW); // width =
- triggerAddEvent(s, base + 418, T_SECONDARY, TV_LOW);
- triggerAddEvent(s, base + 436, T_SECONDARY, TV_HIGH);
- triggerAddEvent(s, base + 441, T_SECONDARY, TV_LOW);
- triggerAddEvent(s, base + 463, T_SECONDARY, TV_HIGH);
- triggerAddEvent(s, base + 468, T_SECONDARY, TV_LOW);
- triggerAddEvent(s, base + 492, T_SECONDARY, TV_HIGH);
- triggerAddEvent(s, base + 497, T_SECONDARY, TV_LOW);
+ s->addEvent(base + 418, T_SECONDARY, TV_LOW);
+ s->addEvent(base + 436, T_SECONDARY, TV_HIGH);
+ s->addEvent(base + 441, T_SECONDARY, TV_LOW);
+ s->addEvent(base + 463, T_SECONDARY, TV_HIGH);
+ s->addEvent(base + 468, T_SECONDARY, TV_LOW);
+ s->addEvent(base + 492, T_SECONDARY, TV_HIGH);
+ s->addEvent(base + 497, T_SECONDARY, TV_LOW);
- triggerAddEvent(s, base + 560, T_PRIMARY, TV_HIGH); // width =
+ s->addEvent(base + 560, T_PRIMARY, TV_HIGH); // width =
s->shaftPositionEventCount = 4 + 8 + 8 + 8 + 8;
}
diff --git a/firmware/controllers/trigger/trigger_chrysler.h b/firmware/controllers/trigger/trigger_chrysler.h
index 4cea93ce97..66fbf3bcfa 100644
--- a/firmware/controllers/trigger/trigger_chrysler.h
+++ b/firmware/controllers/trigger/trigger_chrysler.h
@@ -10,6 +10,6 @@
#include "trigger_structure.h"
-void configureNeonTriggerShape(trigger_shape_s *s);
+void configureNeonTriggerShape(trigger_config_s *triggerConfig, trigger_shape_s *s);
#endif /* TRIGGER_CHRYSLER_H_ */
diff --git a/firmware/controllers/trigger/trigger_decoder.cpp b/firmware/controllers/trigger/trigger_decoder.cpp
index 3c4ae8b02b..d341766095 100644
--- a/firmware/controllers/trigger/trigger_decoder.cpp
+++ b/firmware/controllers/trigger/trigger_decoder.cpp
@@ -1,5 +1,5 @@
/**
- * @file trigger_decoder.c
+ * @file trigger_decoder.cpp
*
* @date Dec 24, 2013
* @author Andrey Belomutskiy, (c) 2012-2014
@@ -48,7 +48,7 @@ int isTriggerDecoderError(void) {
static inline int isSynchronizationGap(TriggerState const *shaftPositionState, trigger_shape_s const *triggerShape,
trigger_config_s const *triggerConfig, const int currentDuration) {
if (!triggerConfig->isSynchronizationNeeded)
- return FALSE;
+ return false;
return currentDuration > shaftPositionState->toothed_previous_duration * triggerConfig->syncRatioFrom
&& currentDuration < shaftPositionState->toothed_previous_duration * triggerConfig->syncRatioTo;
@@ -57,7 +57,7 @@ static inline int isSynchronizationGap(TriggerState const *shaftPositionState, t
static inline int noSynchronizationResetNeeded(TriggerState *shaftPositionState, trigger_shape_s const *triggerShape,
trigger_config_s const*triggerConfig) {
if (triggerConfig->isSynchronizationNeeded)
- return FALSE;
+ return false;
if (!shaftPositionState->shaft_is_synchronized)
return TRUE;
/**
@@ -67,9 +67,10 @@ static inline int noSynchronizationResetNeeded(TriggerState *shaftPositionState,
}
/**
- * @brief This method changes the state of trigger_state_s data structure according to the trigger event
+ * @brief Trigger decoding happends here
+ * This method changes the state of trigger_state_s data structure according to the trigger event
*/
-void TriggerState::processTriggerEvent(trigger_shape_s const*triggerShape, trigger_config_s const*triggerConfig,
+void TriggerState::decodeTriggerEvent(trigger_shape_s const*triggerShape, trigger_config_s const*triggerConfig,
trigger_event_e signal, uint64_t nowUs) {
int isLessImportant = (triggerConfig->useRiseEdge && signal != SHAFT_PRIMARY_UP)
@@ -83,7 +84,8 @@ void TriggerState::processTriggerEvent(trigger_shape_s const*triggerShape, trigg
return;
}
- int64_t currentDuration = nowUs - toothed_previous_time;
+ int64_t currentDuration = isFirstEvent ? 0 : nowUs - toothed_previous_time;
+ isFirstEvent = false;
efiAssertVoid(currentDuration >= 0, "negative duration?");
// todo: skip a number of signal from the beginning
@@ -119,51 +121,51 @@ void TriggerState::processTriggerEvent(trigger_shape_s const*triggerShape, trigg
toothed_previous_time = nowUs;
}
-static void initializeSkippedToothTriggerShape(trigger_shape_s *s, int totalTeethCount, int skippedCount) {
+static void initializeSkippedToothTriggerShape(trigger_shape_s *s, int totalTeethCount, int skippedCount, operation_mode_e operationMode) {
efiAssertVoid(s != NULL, "trigger_shape_s is NULL");
- s->reset();
+ s->reset(operationMode);
float toothWidth = 0.5;
for (int i = 0; i < totalTeethCount - skippedCount - 1; i++) {
float angleDown = 720.0 / totalTeethCount * (i + toothWidth);
float angleUp = 720.0 / totalTeethCount * (i + 1);
- triggerAddEvent(s, angleDown, T_PRIMARY, TV_HIGH);
- triggerAddEvent(s, angleUp, T_PRIMARY, TV_LOW);
+ s->addEvent(angleDown, T_PRIMARY, TV_HIGH);
+ s->addEvent(angleUp, T_PRIMARY, TV_LOW);
}
float angleDown = 720.0 / totalTeethCount * (totalTeethCount - skippedCount - 1 + toothWidth);
- triggerAddEvent(s, angleDown, T_PRIMARY, TV_HIGH);
- triggerAddEvent(s, 720, T_PRIMARY, TV_LOW);
+ s->addEvent(angleDown, T_PRIMARY, TV_HIGH);
+ s->addEvent(720, T_PRIMARY, TV_LOW);
}
void initializeSkippedToothTriggerShapeExt(engine_configuration2_s *engineConfiguration2, int totalTeethCount,
- int skippedCount) {
+ int skippedCount, operation_mode_e operationMode) {
efiAssertVoid(totalTeethCount > 0, "totalTeethCount is zero");
trigger_shape_s *s = &engineConfiguration2->triggerShape;
- initializeSkippedToothTriggerShape(s, totalTeethCount, skippedCount);
+ initializeSkippedToothTriggerShape(s, totalTeethCount, skippedCount, operationMode);
s->shaftPositionEventCount = ((totalTeethCount - skippedCount) * 2);
s->wave.checkSwitchTimes(s->getSize());
}
-static void configureFordAspireTriggerShape(trigger_shape_s * s) {
- s->reset();
+static void configureFordAspireTriggerShape(trigger_config_s *triggerConfig, trigger_shape_s * s) {
+ s->reset(FOUR_STROKE_CAM_SENSOR);
s->shaftPositionEventCount = 10;
- triggerAddEvent(s, 53.747, T_SECONDARY, TV_HIGH);
- triggerAddEvent(s, 121.90, T_SECONDARY, TV_LOW); // delta = 68.153
- triggerAddEvent(s, 232.76, T_SECONDARY, TV_HIGH); // delta = 110.86
- triggerAddEvent(s, 300.54, T_SECONDARY, TV_LOW); // delta = 67.78
- triggerAddEvent(s, 360, T_PRIMARY, TV_HIGH);
+ s->addEvent(53.747, T_SECONDARY, TV_HIGH);
+ s->addEvent(121.90, T_SECONDARY, TV_LOW); // delta = 68.153
+ s->addEvent(232.76, T_SECONDARY, TV_HIGH); // delta = 110.86
+ s->addEvent(300.54, T_SECONDARY, TV_LOW); // delta = 67.78
+ s->addEvent(360, T_PRIMARY, TV_HIGH);
- triggerAddEvent(s, 409.8412, T_SECONDARY, TV_HIGH); // delta = 49.8412
- triggerAddEvent(s, 478.6505, T_SECONDARY, TV_LOW); // delta = 68.8093
- triggerAddEvent(s, 588.045, T_SECONDARY, TV_HIGH); // delta = 109.3945
- triggerAddEvent(s, 657.03, T_SECONDARY, TV_LOW);
- triggerAddEvent(s, 720, T_PRIMARY, TV_LOW);
+ s->addEvent(409.8412, T_SECONDARY, TV_HIGH); // delta = 49.8412
+ s->addEvent(478.6505, T_SECONDARY, TV_LOW); // delta = 68.8093
+ s->addEvent(588.045, T_SECONDARY, TV_HIGH); // delta = 109.3945
+ s->addEvent(657.03, T_SECONDARY, TV_LOW);
+ s->addEvent(720, T_PRIMARY, TV_LOW);
}
/**
@@ -174,45 +176,75 @@ void initializeTriggerShape(Logging *logger, engine_configuration_s *engineConfi
#if EFI_PROD_CODE
printMsg(logger, "initializeTriggerShape()");
#endif
- trigger_config_s *tt = &engineConfiguration->triggerConfig;
- switch (tt->triggerType) {
+ trigger_config_s *triggerConfig = &engineConfiguration->triggerConfig;
+ trigger_shape_s *triggerShape = &engineConfiguration2->triggerShape;
+ switch (triggerConfig->triggerType) {
case TT_TOOTHED_WHEEL:
- initializeSkippedToothTriggerShapeExt(engineConfiguration2, tt->totalToothCount, tt->skippedToothCount);
+ initializeSkippedToothTriggerShapeExt(engineConfiguration2, triggerConfig->totalToothCount, triggerConfig->skippedToothCount,
+ getOperationMode(engineConfiguration));
return;
case TT_MAZDA_MIATA_NB:
- initializeMazdaMiataNbShape(&engineConfiguration2->triggerShape);
+ initializeMazdaMiataNbShape(triggerConfig, triggerShape);
return;
case TT_DODGE_NEON:
- configureNeonTriggerShape(&engineConfiguration2->triggerShape);
+ configureNeonTriggerShape(triggerConfig, triggerShape);
return;
case TT_FORD_ASPIRE:
- configureFordAspireTriggerShape(&engineConfiguration2->triggerShape);
+ configureFordAspireTriggerShape(triggerConfig, triggerShape);
return;
case TT_GM_7X:
- configureGmTriggerShape(&engineConfiguration2->triggerShape);
+ configureGmTriggerShape(triggerConfig, triggerShape);
return;
case TT_FORD_ESCORT_GT:
- configureMazdaProtegeLx(engineConfiguration, engineConfiguration2);
+ configureMazdaProtegeLx(triggerConfig, triggerShape);
return;
case TT_MINI_COOPER_R50:
- configureMiniCooperTriggerShape(engineConfiguration, engineConfiguration2);
+ configureMiniCooperTriggerShape(triggerConfig, triggerShape);
return;
default:
- firmwareError("initializeTriggerShape() not implemented: %d", tt->triggerType);
+ firmwareError("initializeTriggerShape() not implemented: %d", triggerConfig->triggerType);
;
}
if (engineConfiguration2->triggerShape.shaftPositionEventCount != engineConfiguration2->triggerShape.getSize())
firmwareError("trigger size or shaftPositionEventCount?");
}
+TriggerStimulatorHelper::TriggerStimulatorHelper() {
+ primaryWheelState = false;
+ secondaryWheelState = false;
+}
+
+void TriggerStimulatorHelper::nextStep(TriggerState *state, trigger_shape_s * shape, int i, trigger_config_s const*triggerConfig) {
+ int stateIndex = i % shape->getSize();
+
+ int loopIndex = i / shape->getSize();
+
+ int time = (int) (10000 * (loopIndex + shape->wave.getSwitchTime(stateIndex)));
+
+ bool newPrimaryWheelState = shape->wave.getChannelState(0, stateIndex);
+ bool newSecondaryWheelState = shape->wave.getChannelState(1, stateIndex);
+
+ if (primaryWheelState != newPrimaryWheelState) {
+ primaryWheelState = newPrimaryWheelState;
+ trigger_event_e s = primaryWheelState ? SHAFT_PRIMARY_UP : SHAFT_PRIMARY_DOWN;
+ state->decodeTriggerEvent(shape, triggerConfig, s, time);
+ }
+
+ if (secondaryWheelState != newSecondaryWheelState) {
+ secondaryWheelState = newSecondaryWheelState;
+ trigger_event_e s = secondaryWheelState ? SHAFT_SECONDARY_UP : SHAFT_SECONDARY_DOWN;
+ state->decodeTriggerEvent(shape, triggerConfig, s, time);
+ }
+}
+
/**
* Trigger shape is defined in a way which is convenient for trigger shape definition
* On the other hand, trigger decoder indexing begins from synchronization event.
@@ -224,34 +256,13 @@ int findTriggerZeroEventIndex(trigger_shape_s * shape, trigger_config_s const*tr
TriggerState state;
errorDetection.clear();
- int primaryWheelState = FALSE;
- int secondaryWheelState = FALSE;
+ TriggerStimulatorHelper helper;
for (int i = 0; i < 4 * PWM_PHASE_MAX_COUNT; i++) {
-
- int stateIndex = i % shape->getSize();
-
- int loopIndex = i / shape->getSize();
-
- int time = (int) (10000 * (loopIndex + shape->wave.getSwitchTime(stateIndex)));
-
- int newPrimaryWheelState = shape->wave.getChannelState(0, stateIndex);
- int newSecondaryWheelState = shape->wave.getChannelState(1, stateIndex);
-
- if (primaryWheelState != newPrimaryWheelState) {
- primaryWheelState = newPrimaryWheelState;
- trigger_event_e s = primaryWheelState ? SHAFT_PRIMARY_UP : SHAFT_PRIMARY_DOWN;
- state.processTriggerEvent(shape, triggerConfig, s, time);
- }
-
- if (secondaryWheelState != newSecondaryWheelState) {
- secondaryWheelState = newSecondaryWheelState;
- trigger_event_e s = secondaryWheelState ? SHAFT_SECONDARY_UP : SHAFT_SECONDARY_DOWN;
- state.processTriggerEvent(shape, triggerConfig, s, time);
- }
+ helper.nextStep(&state, shape, i, triggerConfig);
if (state.shaft_is_synchronized)
- return stateIndex;
+ return i % shape->getSize();;
}
firmwareError("findTriggerZeroEventIndex() failed");
return -1;
diff --git a/firmware/controllers/trigger/trigger_decoder.h b/firmware/controllers/trigger/trigger_decoder.h
index 2887b9cd06..f31c25e97f 100644
--- a/firmware/controllers/trigger/trigger_decoder.h
+++ b/firmware/controllers/trigger/trigger_decoder.h
@@ -14,19 +14,29 @@
#include "engine_configuration.h"
#include "ec2.h"
+class TriggerStimulatorHelper {
+public:
+ TriggerStimulatorHelper();
+ void nextStep(TriggerState *state, trigger_shape_s * shape, int i, trigger_config_s const*triggerConfig);
+private:
+ bool primaryWheelState;
+ bool secondaryWheelState;
+};
+
+void initializeSkippedToothTriggerShapeExt(engine_configuration2_s *engineConfiguration2, int totalTeethCount, int skippedCount, operation_mode_e operationMode);
+int findTriggerZeroEventIndex(trigger_shape_s * shape, trigger_config_s const*triggerConfig);
+void initializeTriggerShape(Logging *logger, engine_configuration_s *engineConfiguration, engine_configuration2_s *engineConfiguration2);
+void initTriggerDecoder(void);
+
#ifdef __cplusplus
extern "C"
{
#endif
int isTriggerDecoderError(void);
-void initializeSkippedToothTriggerShapeExt(engine_configuration2_s *engineConfiguration2, int totalTeethCount, int skippedCount);
-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);
#ifdef __cplusplus
}
#endif
+
#endif /* TRIGGER_DECODER_H_ */
diff --git a/firmware/controllers/trigger/trigger_emulator_algo.cpp b/firmware/controllers/trigger/trigger_emulator_algo.cpp
index 0cc65a29be..8f5039b085 100644
--- a/firmware/controllers/trigger/trigger_emulator_algo.cpp
+++ b/firmware/controllers/trigger/trigger_emulator_algo.cpp
@@ -1,5 +1,5 @@
/**
- * @file trigger_emulator_algo.c
+ * @file trigger_emulator_algo.cpp
*
* @date Mar 3, 2014
* @author Andrey Belomutskiy, (c) 2012-2014
@@ -61,7 +61,7 @@ void initTriggerEmulatorLogic(pwm_gen_callback *stateChangeCallback) {
trigger_shape_s *s = &engineConfiguration2->triggerShape;
setTriggerEmulatorRPM(DEFAULT_EMULATION_RPM);
- int *pinStates[2] = {s->wave.waves[0].pinStates, s->wave.waves[1].pinStates};
+ 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);
diff --git a/firmware/controllers/trigger/trigger_gm.cpp b/firmware/controllers/trigger/trigger_gm.cpp
index b234a5436f..0283cd6a10 100644
--- a/firmware/controllers/trigger/trigger_gm.cpp
+++ b/firmware/controllers/trigger/trigger_gm.cpp
@@ -7,34 +7,34 @@
#include "trigger_gm.h"
-void configureGmTriggerShape(trigger_shape_s *s) {
- s->reset();
+void configureGmTriggerShape(trigger_config_s *triggerConfig, trigger_shape_s *s) {
+ s->reset(FOUR_STROKE_CAM_SENSOR);
// all angles are x2 here - so, 5 degree width is 10
float w = 10;
s->shaftPositionEventCount = 14;
- triggerAddEvent(s, 120 - w, T_PRIMARY, TV_HIGH);
- triggerAddEvent(s, 120, T_PRIMARY, TV_LOW);
+ s->addEvent(120 - w, T_PRIMARY, TV_HIGH);
+ s->addEvent(120, T_PRIMARY, TV_LOW);
- triggerAddEvent(s, 240 - w, T_PRIMARY, TV_HIGH);
- triggerAddEvent(s, 240, T_PRIMARY, TV_LOW);
+ s->addEvent(240 - w, T_PRIMARY, TV_HIGH);
+ s->addEvent(240, T_PRIMARY, TV_LOW);
- triggerAddEvent(s, 360 - w, T_PRIMARY, TV_HIGH);
- triggerAddEvent(s, 360, T_PRIMARY, TV_LOW);
+ s->addEvent(360 - w, T_PRIMARY, TV_HIGH);
+ s->addEvent(360, T_PRIMARY, TV_LOW);
- triggerAddEvent(s, 480 - w, T_PRIMARY, TV_HIGH);
- triggerAddEvent(s, 480, T_PRIMARY, TV_LOW);
+ s->addEvent(480 - w, T_PRIMARY, TV_HIGH);
+ s->addEvent(480, T_PRIMARY, TV_LOW);
- triggerAddEvent(s, 600 - w, T_PRIMARY, TV_HIGH);
- triggerAddEvent(s, 600, T_PRIMARY, TV_LOW);
+ s->addEvent(600 - w, T_PRIMARY, TV_HIGH);
+ s->addEvent(600, T_PRIMARY, TV_LOW);
- triggerAddEvent(s, 700 - w, T_PRIMARY, TV_HIGH);
- triggerAddEvent(s, 700, T_PRIMARY, TV_LOW);
+ s->addEvent(700 - w, T_PRIMARY, TV_HIGH);
+ s->addEvent(700, T_PRIMARY, TV_LOW);
- triggerAddEvent(s, 720 - w, T_PRIMARY, TV_HIGH);
- triggerAddEvent(s, 720, T_PRIMARY, TV_LOW);
+ s->addEvent(720 - w, T_PRIMARY, TV_HIGH);
+ s->addEvent(720, T_PRIMARY, TV_LOW);
}
diff --git a/firmware/controllers/trigger/trigger_gm.h b/firmware/controllers/trigger/trigger_gm.h
index 10aedf680d..98b4bd857c 100644
--- a/firmware/controllers/trigger/trigger_gm.h
+++ b/firmware/controllers/trigger/trigger_gm.h
@@ -10,6 +10,6 @@
#include "trigger_structure.h"
-void configureGmTriggerShape(trigger_shape_s *s);
+void configureGmTriggerShape(trigger_config_s *triggerConfig, trigger_shape_s *s);
#endif /* TRIGGER_GM_H_ */
diff --git a/firmware/controllers/trigger/trigger_mazda.cpp b/firmware/controllers/trigger/trigger_mazda.cpp
index eef73f1f69..98702868fd 100644
--- a/firmware/controllers/trigger/trigger_mazda.cpp
+++ b/firmware/controllers/trigger/trigger_mazda.cpp
@@ -1,5 +1,5 @@
/**
- * @file trigger_mazda.c
+ * @file trigger_mazda.cpp
*
* @date Feb 18, 2014
* @author Andrey Belomutskiy, (c) 2012-2014
@@ -20,78 +20,75 @@
#include "trigger_mazda.h"
-void initializeMazdaMiataNbShape(trigger_shape_s *s) {
- s->reset();
+void initializeMazdaMiataNbShape(trigger_config_s *triggerConfig, trigger_shape_s *s) {
+ s->reset(FOUR_STROKE_CAM_SENSOR);
/**
* cam sensor is primary, crank sensor is secondary
*/
- triggerAddEvent(s, 20, T_PRIMARY, TV_HIGH);
+ s->addEvent(20, T_PRIMARY, TV_HIGH);
- triggerAddEvent(s, 66, T_SECONDARY, TV_LOW);
- triggerAddEvent(s, 70, T_SECONDARY, TV_HIGH);
- triggerAddEvent(s, 136, T_SECONDARY, TV_LOW);
- triggerAddEvent(s, 140, T_SECONDARY, TV_HIGH);
- triggerAddEvent(s, 246, T_SECONDARY, TV_LOW);
- triggerAddEvent(s, 250, T_SECONDARY, TV_HIGH);
- triggerAddEvent(s, 316, T_SECONDARY, TV_LOW);
- triggerAddEvent(s, 320, T_SECONDARY, TV_HIGH);
+ s->addEvent(66, T_SECONDARY, TV_LOW);
+ s->addEvent(70, T_SECONDARY, TV_HIGH);
+ s->addEvent(136, T_SECONDARY, TV_LOW);
+ s->addEvent(140, T_SECONDARY, TV_HIGH);
+ s->addEvent(246, T_SECONDARY, TV_LOW);
+ s->addEvent(250, T_SECONDARY, TV_HIGH);
+ s->addEvent(316, T_SECONDARY, TV_LOW);
+ s->addEvent(320, T_SECONDARY, TV_HIGH);
- triggerAddEvent(s, 340, T_PRIMARY, TV_LOW);
- triggerAddEvent(s, 360, T_PRIMARY, TV_HIGH);
+ s->addEvent(340, T_PRIMARY, TV_LOW);
+ s->addEvent(360, T_PRIMARY, TV_HIGH);
- triggerAddEvent(s, 380, T_PRIMARY, TV_LOW);
- triggerAddEvent(s, 400, T_PRIMARY, TV_HIGH);
+ s->addEvent(380, T_PRIMARY, TV_LOW);
+ s->addEvent(400, T_PRIMARY, TV_HIGH);
- triggerAddEvent(s, 426, T_SECONDARY, TV_LOW);
- triggerAddEvent(s, 430, T_SECONDARY, TV_HIGH);
- triggerAddEvent(s, 496, T_SECONDARY, TV_LOW);
- triggerAddEvent(s, 500, T_SECONDARY, TV_HIGH);
- triggerAddEvent(s, 606, T_SECONDARY, TV_LOW);
- triggerAddEvent(s, 610, T_SECONDARY, TV_HIGH);
- triggerAddEvent(s, 676, T_SECONDARY, TV_LOW);
- triggerAddEvent(s, 680, T_SECONDARY, TV_HIGH);
+ s->addEvent(426, T_SECONDARY, TV_LOW);
+ s->addEvent(430, T_SECONDARY, TV_HIGH);
+ s->addEvent(496, T_SECONDARY, TV_LOW);
+ s->addEvent(500, T_SECONDARY, TV_HIGH);
+ s->addEvent(606, T_SECONDARY, TV_LOW);
+ s->addEvent(610, T_SECONDARY, TV_HIGH);
+ s->addEvent(676, T_SECONDARY, TV_LOW);
+ s->addEvent(680, T_SECONDARY, TV_HIGH);
- triggerAddEvent(s, 720, T_PRIMARY, TV_LOW);
+ s->addEvent(720, T_PRIMARY, TV_LOW);
s->shaftPositionEventCount = 6 + 16;
}
-void configureMazdaProtegeLx(engine_configuration_s *engineConfiguration,
- engine_configuration2_s *engineConfiguration2) {
+void configureMazdaProtegeLx(trigger_config_s *triggerConfig, trigger_shape_s *s) {
- trigger_shape_s *s = &engineConfiguration2->triggerShape;
-
- s->reset();
+ s->reset(FOUR_STROKE_CAM_SENSOR);
// s->initialState[0] = 1;
float w = 720 / 4 * 0.215;
float a = 5;
-// triggerAddEvent(s, a, T_SECONDARY, TV_LOW);
-// triggerAddEvent(s, a + w, T_SECONDARY, TV_HIGH);
+// s->addEvent(a, T_SECONDARY, TV_LOW);
+// s->addEvent(a + w, T_SECONDARY, TV_HIGH);
// a += 180;
-// triggerAddEvent(s, a, T_SECONDARY, TV_LOW);
-// triggerAddEvent(s, a + w, T_SECONDARY, TV_HIGH);
+// s->addEvent(a, T_SECONDARY, TV_LOW);
+// s->addEvent(a + w, T_SECONDARY, TV_HIGH);
// a += 180;
-// triggerAddEvent(s, a, T_SECONDARY, TV_LOW);
-// triggerAddEvent(s, a + w, T_SECONDARY, TV_HIGH);
+// s->addEvent(a, T_SECONDARY, TV_LOW);
+// s->addEvent(a + w, T_SECONDARY, TV_HIGH);
// a += 180;
-// triggerAddEvent(s, a, T_SECONDARY, TV_LOW);
-// triggerAddEvent(s, a + w, T_SECONDARY, TV_HIGH);
+// s->addEvent(a, T_SECONDARY, TV_LOW);
+// s->addEvent(a + w, T_SECONDARY, TV_HIGH);
float z = 0.093;
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);
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);
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);
a += 180;
s->addEvent(a - z * 720, T_PRIMARY, TV_HIGH);
@@ -100,5 +97,5 @@ void configureMazdaProtegeLx(engine_configuration_s *engineConfiguration,
// s->shaftPositionEventCount = 2 + 8;
s->shaftPositionEventCount = 8;
- engineConfiguration->triggerConfig.isSynchronizationNeeded = FALSE;
+ triggerConfig->isSynchronizationNeeded = false;
}
diff --git a/firmware/controllers/trigger/trigger_mazda.h b/firmware/controllers/trigger/trigger_mazda.h
index 0d53b6d255..0cc01f3d17 100644
--- a/firmware/controllers/trigger/trigger_mazda.h
+++ b/firmware/controllers/trigger/trigger_mazda.h
@@ -12,8 +12,7 @@
#include "engine_configuration.h"
#include "ec2.h"
-void initializeMazdaMiataNbShape(trigger_shape_s *s);
-void configureMazdaProtegeLx(engine_configuration_s *engineConfiguration,
- engine_configuration2_s *engineConfiguration2);
+void initializeMazdaMiataNbShape(trigger_config_s *triggerConfig, trigger_shape_s *s);
+void configureMazdaProtegeLx(trigger_config_s *triggerConfig, trigger_shape_s *s);
#endif /* TRIGGER_MAZDA_H_ */
diff --git a/firmware/controllers/trigger/trigger_structure.cpp b/firmware/controllers/trigger/trigger_structure.cpp
index a6106e3a14..215f942fc3 100644
--- a/firmware/controllers/trigger/trigger_structure.cpp
+++ b/firmware/controllers/trigger/trigger_structure.cpp
@@ -29,7 +29,7 @@ trigger_shape_helper::trigger_shape_helper() {
trigger_shape_s::trigger_shape_s() :
wave(switchTimes, NULL) {
- reset();
+ reset(OM_NONE);
wave.waves = h.waves;
}
@@ -37,7 +37,33 @@ int trigger_shape_s::getSize() {
return size;
}
-void trigger_shape_s::reset() {
+int trigger_shape_s::getTriggerShapeSynchPointIndex() {
+ return triggerShapeSynchPointIndex;
+}
+
+// todo: clean-up!
+int getEngineCycleEventCount2(operation_mode_e mode, trigger_shape_s * s);
+float fixAngle(float angle);
+
+void trigger_shape_s::setTriggerShapeSynchPointIndex(int triggerShapeSynchPointIndex) {
+ this->triggerShapeSynchPointIndex = triggerShapeSynchPointIndex;
+
+ int engineCycleEventCount = getEngineCycleEventCount2(operationMode, this);
+
+ float firstAngle = getAngle(triggerShapeSynchPointIndex);
+
+ for (int i = 0; i < engineCycleEventCount; i++) {
+ if (i == 0) {
+ // explicit check for zero to avoid issues where logical zero is not exactly zero due to float nature
+ eventAngles[i] = 0;
+ } else {
+ eventAngles[i] = fixAngle(getAngle((triggerShapeSynchPointIndex + i) % engineCycleEventCount) - firstAngle);
+ }
+ }
+}
+
+void trigger_shape_s::reset(operation_mode_e operationMode) {
+ this->operationMode = operationMode;
size = 0;
shaftPositionEventCount = 0;
triggerShapeSynchPointIndex = 0;
@@ -58,6 +84,7 @@ void multi_wave_s::setSwitchTime(int index, float value) {
TriggerState::TriggerState() {
clear();
totalEventCountBase = 0;
+ isFirstEvent = true;
}
int TriggerState::getCurrentIndex() {
@@ -74,7 +101,7 @@ uint64_t TriggerState::getTotalEventCounter() {
void TriggerState::nextRevolution(int triggerEventCount) {
current_index = 0;
- totalRevolutionCounter ++;
+ totalRevolutionCounter++;
totalEventCountBase += triggerEventCount;
}
@@ -94,7 +121,30 @@ void TriggerState::clear() {
totalRevolutionCounter = 0;
}
+float trigger_shape_s::getAngle(int index) const {
+ if (operationMode == FOUR_STROKE_CAM_SENSOR)
+ return switchAngles[index];
+ /**
+ * FOUR_STROKE_CRANK_SENSOR magic:
+ * We have two crank shaft revolutions for each engine cycle
+ * See also trigger_central.cpp
+ * See also getEngineCycleEventCount()
+ */
+ int triggerEventCounter = size;
+
+ if (index < triggerEventCounter) {
+ return switchAngles[index];
+ } else {
+ return 360 + switchAngles[index - triggerEventCounter];
+ }
+}
+
void trigger_shape_s::addEvent(float angle, trigger_wheel_e waveIndex, trigger_value_e state) {
+ efiAssertVoid(operationMode != OM_NONE, "operationMode not set");
+ /**
+ * While '720' value works perfectly it has not much sense for crank sensor-only scenario.
+ * todo: accept angle as a value in the 0..1 range?
+ */
angle /= 720;
efiAssertVoid(angle > previousAngle, "invalid angle order");
previousAngle = angle;
@@ -114,7 +164,7 @@ void trigger_shape_s::addEvent(float angle, trigger_wheel_e waveIndex, trigger_v
wave->pinStates[0] = initialState[i];
}
- wave.setSwitchTime(0, angle);
+ setSwitchTime(0, angle);
wave.waves[waveIndex].pinStates[0] = state;
return;
}
@@ -125,13 +175,14 @@ void trigger_shape_s::addEvent(float angle, trigger_wheel_e waveIndex, trigger_v
for (int i = 0; i < PWM_PHASE_MAX_WAVE_PER_PWM; i++)
wave.waves[i].pinStates[index] = wave.getChannelState(i, index - 1);
- wave.setSwitchTime(index, angle);
+ setSwitchTime(index, angle);
wave.waves[waveIndex].pinStates[index] = state;
}
-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 trigger_shape_s::setSwitchTime(int index, float angle) {
+ int cycleDuration = (operationMode == FOUR_STROKE_CAM_SENSOR) ? 720 : 360;
+ switchAngles[index] = cycleDuration * angle;
+ wave.setSwitchTime(index, angle);
}
void multi_wave_s::checkSwitchTimes(int size) {
diff --git a/firmware/controllers/trigger/trigger_structure.h b/firmware/controllers/trigger/trigger_structure.h
index fa226a2205..ede13a3e8b 100644
--- a/firmware/controllers/trigger/trigger_structure.h
+++ b/firmware/controllers/trigger/trigger_structure.h
@@ -25,7 +25,7 @@ public:
uint64_t getStartOfRevolutionIndex();
void nextRevolution(int triggerEventCount);
void nextTriggerEvent();
- void processTriggerEvent(trigger_shape_s const*triggerShape, trigger_config_s const*triggerConfig, trigger_event_e signal, uint64_t nowUs);
+ void decodeTriggerEvent(trigger_shape_s const*triggerShape, trigger_config_s const*triggerConfig, trigger_event_e signal, uint64_t nowUs);
/**
@@ -43,6 +43,7 @@ private:
int current_index;
uint64_t totalEventCountBase;
int totalRevolutionCounter;
+ bool isFirstEvent;
};
typedef enum {
@@ -66,12 +67,14 @@ public:
class trigger_shape_s {
private:
+ void setSwitchTime(int index, float angle);
trigger_shape_helper h;
int size;
public:
trigger_shape_s();
void addEvent(float angle, trigger_wheel_e waveIndex, trigger_value_e state);
- void reset();
+ float getAngle(int phaseIndex) const;
+ void reset(operation_mode_e operationMode);
int getSize();
multi_wave_s wave;
@@ -86,25 +89,38 @@ public:
// tood: maybe even automate this flag calculation?
int initialState[PWM_PHASE_MAX_WAVE_PER_PWM];
+
+ int getTriggerShapeSynchPointIndex();
+
+ void setTriggerShapeSynchPointIndex(int triggerShapeSynchPointIndex);
+ /**
+ * These angles are in event coordinates - with synchronization point located at angle zero.
+ */
+ float eventAngles[PWM_PHASE_MAX_COUNT];
+
+private:
/**
* index of synchronization event within trigger_shape_s
* See findTriggerZeroEventIndex()
*/
int triggerShapeSynchPointIndex;
-private:
+ /**
+ * Values are in the 0..1 range
+ */
float switchTimes[PWM_PHASE_MAX_COUNT];
+ /**
+ * These are the same values as in switchTimes, but these are angles in the 0..360 or 0..720 range.
+ * That's a performance optimization - this should save as one multiplication in a critical spot.
+ *
+ * These angles are in trigger DESCRIPTION coordinates - i.e. the way you add events while declaring trigger shape
+ */
+ float switchAngles[PWM_PHASE_MAX_COUNT];
+
float previousAngle;
+ /**
+ * this is part of performance optimization
+ */
+ operation_mode_e operationMode;
};
-#ifdef __cplusplus
-extern "C"
-{
-#endif /* __cplusplus */
-
-void triggerAddEvent(trigger_shape_s *trigger, float angle, trigger_wheel_e waveIndex, trigger_value_e state);
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
#endif /* TRIGGER_STRUCTURE_H_ */
diff --git a/firmware/dump.bat b/firmware/dump.bat
new file mode 100644
index 0000000000..af791acb5a
--- /dev/null
+++ b/firmware/dump.bat
@@ -0,0 +1 @@
+arm-none-eabi-objdump -S build/rusefi.elf > build.dump
\ No newline at end of file
diff --git a/firmware/emulation/analog_chart.c b/firmware/emulation/analog_chart.c
index 03d3bf80a9..ed832a1aaa 100644
--- a/firmware/emulation/analog_chart.c
+++ b/firmware/emulation/analog_chart.c
@@ -48,7 +48,7 @@ void acAddData(float angle, float value) {
appendPrintf(&logging, "analog_chart%s", DELIMETER);
}
- if (loggingSize(&logging) < sizeof(LOGGING_BUFFER) - 100)
+ if (remainingSize(&logging) > 100)
appendPrintf(&logging, "%f|%f|", angle, value);
}
diff --git a/firmware/emulation/rfi_perftest.cpp b/firmware/emulation/rfi_perftest.cpp
index 6e6ed4ff17..a071c80324 100644
--- a/firmware/emulation/rfi_perftest.cpp
+++ b/firmware/emulation/rfi_perftest.cpp
@@ -16,6 +16,7 @@
#include "gpio_helper.h"
#include "efilib2.h"
#include "console_io.h"
+#include "engine.h"
#if EFI_PERF_METRICS
@@ -66,6 +67,8 @@ static void testSystemCalls(const int count) {
scheduleMsg(&logger, "Finished %d iterations of 'currentTimeMillis' in %dms", count, time);
}
+static Engine testEngine;
+
static void testRusefiMethods(const int count) {
time_t start, time;
int tempi = 1;
@@ -79,12 +82,20 @@ static void testRusefiMethods(const int count) {
scheduleMsg(&logger, "Finished %d iterations of getBaseFuel in %dms", count, time);
start = currentTimeMillis();
+ for (int i = 0; i < count; i++)
+ tempi += getFuelMs(1200);
+ time = currentTimeMillis() - start;
+ if (tempi != 0)
+ scheduleMsg(&logger, "Finished %d iterations of getFuelMs in %dms", count, time);
-// for (int i = 0; i < count; i++)
-// tempi += getDefaultFuel(4020, 2.21111);
-// time = currentTimeMillis() - start;
-// if (tempi == 0)
-// rint("Finished %d iterations of getDefaultFuel in %dms\r\n", count, time);
+ start = currentTimeMillis();
+ for (int i = 0; i < count; i++) {
+ testEngine.updateSlowSensors();
+ tempi += testEngine.engineState.clt;
+ }
+ time = currentTimeMillis() - start;
+ if (tempi != 0)
+ scheduleMsg(&logger, "Finished %d iterations of updateSlowSensors in %dms", count, time);
}
static void testMath(const int count) {
@@ -165,6 +176,14 @@ static void testMath(const int count) {
scheduleMsg(&logger, "Finished %d iterations of float division in %dms", count, time);
}
+ start = currentTimeMillis();
+ tempf = 1;
+ for (int i = 0; i < count; i++)
+ tempf += logf(tempf);
+ time = currentTimeMillis() - start;
+ if (tempf != 0)
+ scheduleMsg(&logger, "Finished %d iterations of float log in %dms", count, time);
+
start = currentTimeMillis();
double tempd = 1;
for (int i = 0; i < count; i++)
@@ -181,9 +200,17 @@ static void testMath(const int count) {
if (tempd != 0)
scheduleMsg(&logger, "Finished %d iterations of double division in %dms", count, time);
+ start = currentTimeMillis();
+ tempd = 1;
+ for (int i = 0; i < count; i++)
+ tempd += log(tempd);
+ time = currentTimeMillis() - start;
+ if (tempd != 0)
+ scheduleMsg(&logger, "Finished %d iterations of double log in %dms", count, time);
}
static void runTests(const int count) {
+ scheduleMsg(&logger, "Running tests: %d", count);
testRusefiMethods(count / 10);
testSystemCalls(count);
testMath(count);
diff --git a/firmware/emulation/wave_analyzer.c b/firmware/emulation/wave_analyzer.c
index 549d808712..b2d0e18a31 100644
--- a/firmware/emulation/wave_analyzer.c
+++ b/firmware/emulation/wave_analyzer.c
@@ -49,7 +49,7 @@ static void waAnaWidthCallback(WaveReader *reader) {
uint64_t nowUs = getTimeNowUs();
reader->eventCounter++;
reader->lastActivityTimeUs = nowUs;
- addWaveChartEvent(reader->name, "up", "");
+ addWaveChartEvent(reader->name, WC_UP, "");
uint64_t width = nowUs - reader->periodEventTimeUs;
reader->last_wave_low_widthUs = width;
@@ -62,7 +62,7 @@ static void waIcuPeriodCallback(WaveReader *reader) {
uint64_t nowUs = getTimeNowUs();
reader->eventCounter++;
reader->lastActivityTimeUs = nowUs;
- addWaveChartEvent(reader->name, "down", "");
+ addWaveChartEvent(reader->name, WC_DOWN, "");
uint64_t width = nowUs - reader->widthEventTimeUs;
reader->last_wave_high_widthUs = width;
diff --git a/firmware/global.h b/firmware/global.h
index fadb2d02fb..c32c258924 100644
--- a/firmware/global.h
+++ b/firmware/global.h
@@ -30,7 +30,7 @@
#if EFI_USE_CCM && defined __GNUC__
#define CCM_OPTIONAL __attribute__((section(".ccm")));
#else
-#define CCM_OPTIONAL
+#define CCM_OPTIONAL @ ".ccm"
#endif
// this stuff is about ChibiOS 2.6 > Migration
diff --git a/firmware/hw_layer/adc_inputs.cpp b/firmware/hw_layer/adc_inputs.cpp
index 76201d5de0..b9c93a6ce0 100644
--- a/firmware/hw_layer/adc_inputs.cpp
+++ b/firmware/hw_layer/adc_inputs.cpp
@@ -261,8 +261,7 @@ GPIO_TypeDef* getAdcChannelPort(int hwChannel) {
case ADC_CHANNEL_IN15:
return GPIOC;
default:
- firmwareError("Unknown hw channel")
- ;
+ firmwareError("Unknown hw channel");
return NULL;
}
}
@@ -303,8 +302,7 @@ int getAdcChannelPin(int hwChannel) {
case ADC_CHANNEL_IN15:
return 5;
default:
- firmwareError("Unknown hw channel")
- ;
+ firmwareError("Unknown hw channel");
return -1;
}
}
@@ -411,7 +409,7 @@ static void adc_callback_fast(ADCDriver *adcp, adcsample_t *buffer, size_t n) {
}
}
-void initAdcInputs() {
+void initAdcInputs(bool isBoardTestMode) {
initLoggingExt(&logger, "ADC", LOGGING_BUFFER, sizeof(LOGGING_BUFFER));
printMsg(&logger, "initAdcInputs()");
@@ -430,7 +428,7 @@ void initAdcInputs() {
for (int adc = 0; adc < HW_MAX_ADC_INDEX; adc++) {
adc_channel_mode_e mode = boardConfiguration->adcHwChannelEnabled[adc];
- if (mode == ADC_SLOW) {
+ if (mode == ADC_SLOW || (isBoardTestMode && mode == ADC_FAST)) {
slowAdc.addChannel(ADC_CHANNEL_IN0 + adc);
} else if (mode == ADC_FAST) {
fastAdc.addChannel(ADC_CHANNEL_IN0 + adc);
@@ -438,7 +436,14 @@ void initAdcInputs() {
}
slowAdc.init();
- fastAdc.init();
+ pwmStart(EFI_INTERNAL_SLOW_ADC_PWM, &pwmcfg_slow);
+ if (!isBoardTestMode) {
+ fastAdc.init();
+ /*
+ * Initializes the PWM driver.
+ */
+ pwmStart(EFI_INTERNAL_FAST_ADC_PWM, &pwmcfg_fast);
+ }
// ADC_CHANNEL_IN0 // PA0
// ADC_CHANNEL_IN1 // PA1
@@ -459,11 +464,6 @@ void initAdcInputs() {
//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
diff --git a/firmware/hw_layer/adc_inputs.h b/firmware/hw_layer/adc_inputs.h
index a283320d76..ca76417640 100644
--- a/firmware/hw_layer/adc_inputs.h
+++ b/firmware/hw_layer/adc_inputs.h
@@ -19,7 +19,7 @@ extern "C"
GPIO_TypeDef* getAdcChannelPort(int hwChannel);
int getAdcChannelPin(int hwChannel);
-void initAdcInputs(void);
+void initAdcInputs(bool isBoardTestMode);
int getAdcHardwareIndexByInternalIndex(int index);
int getAdcValueByIndex(int internalIndex);
void pokeAdcInputs(void);
diff --git a/firmware/hw_layer/board_test.cpp b/firmware/hw_layer/board_test.cpp
index 2688817117..ebb385ea93 100644
--- a/firmware/hw_layer/board_test.cpp
+++ b/firmware/hw_layer/board_test.cpp
@@ -28,7 +28,7 @@
#include "AdcConfiguration.h"
static volatile int stepCoutner = 0;
-static volatile brain_pin_e currentPin;
+static volatile brain_pin_e currentPin = GPIO_NONE;
static volatile int currentIndex = 0;
extern AdcConfiguration slowAdc;
@@ -93,11 +93,25 @@ static msg_t ivThread(int param) {
#endif
}
-void initBoardTest(void) {
- // todo: add a command to go into board test mode after reboot
- if (1 == 1)
- return;
+static bool is_board_test_mode = false;
+bool isBoardTestMode(void) {
+ return is_board_test_mode;
+}
+
+void printBoardTestState(void) {
+ print("Current index=%d\r\n", currentIndex);
+ print("'n' for next step and 'set X' to return to step X\r\n");
+ print("ADC count: %d\r\n", slowAdc.size());
+
+ if (currentPin != GPIO_NONE) {
+ print("Blinking %s\r\n", hwPortname(currentPin));
+ }
+
+}
+
+void initBoardTest(void) {
+ is_board_test_mode = true;
addConsoleAction("n", nextStep);
addConsoleActionI("set", setIndex);
@@ -142,8 +156,7 @@ void initBoardTest(void) {
GPIO_TypeDef *hwPort = getHwPort(currentPin);
uint32_t hwPin = getHwPin(currentPin);
- print("currentIndex=%d\r\n", currentIndex);
- print("Let's blink %s%d\r\n", portname(hwPort), hwPin);
+ printBoardTestState();
mySetPadMode("test", hwPort, hwPin, PAL_STM32_MODE_OUTPUT);
currentIndex++;
diff --git a/firmware/hw_layer/board_test.h b/firmware/hw_layer/board_test.h
index 3447c156b7..d3f263972c 100644
--- a/firmware/hw_layer/board_test.h
+++ b/firmware/hw_layer/board_test.h
@@ -28,6 +28,8 @@ extern "C"
#endif /* __cplusplus */
void initBoardTest(void);
+bool isBoardTestMode(void);
+void printBoardTestState(void);
#ifdef __cplusplus
}
diff --git a/firmware/hw_layer/can_hw.cpp b/firmware/hw_layer/can_hw.cpp
index 41020248a2..46c52f226c 100644
--- a/firmware/hw_layer/can_hw.cpp
+++ b/firmware/hw_layer/can_hw.cpp
@@ -25,6 +25,7 @@ static THD_WORKING_AREA(canTreadStack, UTILITY_THREAD_STACK_SIZE);
extern engine_configuration_s *engineConfiguration;
extern engine_configuration2_s *engineConfiguration2;
+extern board_configuration_s *board_configuration;
/*
* 500KBaud
@@ -175,6 +176,10 @@ static void canInfo(void) {
scheduleMsg(&logger, "CAN rx count %d", canReadCounter);
}
+static CANDriver *getCanDevice() {
+ if(board)
+}
+
void initCan(void) {
initLogging(&logger, "CAN driver");
diff --git a/firmware/hw_layer/flash.c b/firmware/hw_layer/flash.c
index 4c4be79e11..88e4eb480a 100644
--- a/firmware/hw_layer/flash.c
+++ b/firmware/hw_layer/flash.c
@@ -50,7 +50,7 @@ flashsector_t flashSectorAt(flashaddr_t address) {
* @return CH_SUCCESS Unlock was successful.
* @return CH_FAILED Unlock failed.
*/
-static bool_t flashUnlock(void) {
+static bool flashUnlock(void) {
/* Check if unlock is really needed */
if (!(FLASH->CR & FLASH_CR_LOCK))
return CH_SUCCESS;
@@ -141,13 +141,13 @@ bool flashIsErased(flashaddr_t address, size_t size) {
* then, fallback to byte per byte comparison. */
while (size >= sizeof(flashdata_t)) {
if (*(volatile flashdata_t*) address != (flashdata_t) (-1)) // flashdata_t being unsigned, -1 is 0xFF..FF
- return FALSE;
+ return false;
address += sizeof(flashdata_t);
size -= sizeof(flashdata_t);
}
while (size > 0) {
if (*(char*) address != 0xff)
- return FALSE;
+ return false;
++address;
--size;
}
diff --git a/firmware/hw_layer/hardware.cpp b/firmware/hw_layer/hardware.cpp
index f2ba53a7ca..8ef625b95b 100644
--- a/firmware/hw_layer/hardware.cpp
+++ b/firmware/hw_layer/hardware.cpp
@@ -1,5 +1,5 @@
/**
- * @file hardware.c
+ * @file hardware.cpp
* @brief Hardware package entry point
*
* @date May 27, 2013
@@ -12,6 +12,7 @@
#include "io_pins.h"
#include "rtc_helper.h"
#include "rfiutil.h"
+#include "console_io.h"
#include "adc_inputs.h"
@@ -27,6 +28,7 @@
#include "neo6m.h"
#include "lcd_HD44780.h"
#include "settings.h"
+#include "algo.h"
#if EFI_INTERNAL_FLASH
#include "flash_main.h"
@@ -55,10 +57,10 @@ void initSpiModules(void) {
#if STM32_SPI_USE_SPI2
// scheduleMsg(&logging, "Turning on SPI2 pins");
initSpiModule(&SPID2,
- EFI_SPI2_SCK_PORT, EFI_SPI2_SCK_PIN,
- EFI_SPI2_MISO_PORT, EFI_SPI2_MISO_PIN,
- EFI_SPI2_MOSI_PORT, EFI_SPI2_MOSI_PIN,
- EFI_SPI2_AF);
+ EFI_SPI2_SCK_PORT, EFI_SPI2_SCK_PIN,
+ EFI_SPI2_MISO_PORT, EFI_SPI2_MISO_PIN,
+ EFI_SPI2_MOSI_PORT, EFI_SPI2_MOSI_PIN,
+ EFI_SPI2_AF);
#endif
#if STM32_SPI_USE_SPI3
// scheduleMsg(&logging, "Turning on SPI3 pins");
@@ -78,9 +80,9 @@ void initI2Cmodule(void) {
i2cStart(&I2CD1, &i2cfg);
mySetPadMode("I2C clock", EFI_I2C_SCL_PORT, EFI_I2C_SCL_PIN,
- PAL_MODE_ALTERNATE(EFI_I2C_AF) | PAL_STM32_OTYPE_OPENDRAIN);
+ PAL_MODE_ALTERNATE(EFI_I2C_AF) | PAL_STM32_OTYPE_OPENDRAIN);
mySetPadMode("I2C data", EFI_I2C_SDA_PORT, EFI_I2C_SDA_PIN,
- PAL_MODE_ALTERNATE(EFI_I2C_AF) | PAL_STM32_OTYPE_OPENDRAIN);
+ PAL_MODE_ALTERNATE(EFI_I2C_AF) | PAL_STM32_OTYPE_OPENDRAIN);
}
//static char txbuf[1];
@@ -105,7 +107,6 @@ void initHardware(Logging *logger) {
initHistogramsModule();
#endif /* EFI_HISTOGRAMS */
-
/**
* We need the LED_ERROR pin even before we read configuration
*/
@@ -114,12 +115,25 @@ void initHardware(Logging *logger) {
if (hasFirmwareError())
return;
+ initDataStructures(engineConfiguration);
+
#if EFI_INTERNAL_FLASH
+
+ palSetPadMode(CONFIG_RESET_SWITCH_PORT, CONFIG_RESET_SWITCH_PIN, PAL_MODE_INPUT_PULLUP);
+
+ initFlash();
/**
* this call reads configuration from flash memory or sets default configuration
* if flash state does not look right.
*/
- initFlash();
+ if (SHOULD_INGORE_FLASH()) {
+ engineConfiguration->engineType = FORD_ASPIRE_1996;
+ resetConfigurationExt(logger, engineConfiguration->engineType, engineConfiguration, engineConfiguration2,
+ boardConfiguration);
+ writeToFlash();
+ } else {
+ readFromFlash();
+ }
#else
engineConfiguration->engineType = FORD_ASPIRE_1996;
resetConfigurationExt(logger, engineConfiguration->engineType, engineConfiguration, engineConfiguration2, boardConfiguration);
@@ -128,10 +142,20 @@ void initHardware(Logging *logger) {
if (hasFirmwareError())
return;
+ mySetPadMode("board test", getHwPort(boardConfiguration->boardTestModeJumperPin),
+ getHwPin(boardConfiguration->boardTestModeJumperPin), PAL_MODE_INPUT_PULLUP);
+ bool isBoardTestMode = GET_BOARD_TEST_MODE_VALUE();
+
+ initAdcInputs(isBoardTestMode);
+
+ if (isBoardTestMode) {
+ initBoardTest();
+ efiAssertVoid(FALSE, "board test done");
+ }
+
initRtc();
initOutputPins();
- initAdcInputs();
#if EFI_HIP_9011
initHip9011();
@@ -144,7 +168,6 @@ void initHardware(Logging *logger) {
// init_adc_mcp3208(&adcState, &SPID2);
// requestAdcValue(&adcState, 0);
-
// todo: figure out better startup logic
initTriggerCentral();
@@ -195,6 +218,5 @@ void initHardware(Logging *logger) {
// }
// }
- initBoardTest();
printMsg(logger, "initHardware() OK!");
}
diff --git a/firmware/hw_layer/hardware.h b/firmware/hw_layer/hardware.h
index 7863bb897f..7e024b24ad 100644
--- a/firmware/hw_layer/hardware.h
+++ b/firmware/hw_layer/hardware.h
@@ -10,14 +10,8 @@
#include "main.h"
-#ifdef __cplusplus
-extern "C"
-{
-#endif /* __cplusplus */
+#define GET_BOARD_TEST_MODE_VALUE() (!palReadPad(getHwPort(boardConfiguration->boardTestModeJumperPin), getHwPin(boardConfiguration->boardTestModeJumperPin)))
void initHardware(Logging *logging);
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
#endif /* HARDWARE_H_ */
diff --git a/firmware/hw_layer/io_pins.c b/firmware/hw_layer/io_pins.c
index 0e31d6152c..6a386fd6c4 100644
--- a/firmware/hw_layer/io_pins.c
+++ b/firmware/hw_layer/io_pins.c
@@ -180,7 +180,7 @@ void initPrimaryPins(void) {
}
void initOutputPins(void) {
- outputPinRegister("is cranking status", LED_WARNING, LED_WARNING_PORT, LED_WARNING_PIN);
+ outputPinRegister("warning", LED_WARNING, LED_WARNING_PORT, LED_WARNING_PIN);
outputPinRegister("is running status", LED_RUNNING, LED_RUNNING_STATUS_PORT, LED_RUNNING_STATUS_PIN);
outputPinRegister("communication status 1", LED_COMMUNICATION_1, LED_COMMUNICATION_PORT, LED_COMMUNICATION_PIN);
diff --git a/firmware/hw_layer/lcd/lcd_HD44780.c b/firmware/hw_layer/lcd/lcd_HD44780.c
index 5c878e29af..2a9945f18a 100644
--- a/firmware/hw_layer/lcd/lcd_HD44780.c
+++ b/firmware/hw_layer/lcd/lcd_HD44780.c
@@ -10,6 +10,8 @@
#include "main.h"
+#if EFI_HD44780_LCD
+
#include "lcd_HD44780.h"
#include "pin_repository.h"
#include "string.h"
@@ -154,15 +156,9 @@ 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 E=%s", hwPortname(boardConfiguration->HD44780_rs), hwPortname(boardConfiguration->HD44780_e));
+ scheduleMsg(&logger, "HD44780 D4=%s D5=%s", hwPortname(boardConfiguration->HD44780_db4), hwPortname(boardConfiguration->HD44780_db5));
+ scheduleMsg(&logger, "HD44780 D6=%s D7=%s", hwPortname(boardConfiguration->HD44780_db6), hwPortname(boardConfiguration->HD44780_db7));
}
void lcd_HD44780_init(void) {
@@ -234,3 +230,5 @@ void lcdShowFatalMessage(char *message) {
lcd_HD44780_print_string("fatal\n");
lcd_HD44780_print_string(message);
}
+
+#endif /* EFI_HD44780_LCD */
diff --git a/firmware/hw_layer/microsecond_timer.c b/firmware/hw_layer/microsecond_timer.c
index c90c6b097c..e1fed3814d 100644
--- a/firmware/hw_layer/microsecond_timer.c
+++ b/firmware/hw_layer/microsecond_timer.c
@@ -21,7 +21,7 @@
static volatile int64_t lastSetTimerTime;
static int lastSetTimerValue;
-static volatile bool_t isTimerPending = FALSE;
+static volatile bool isTimerPending = FALSE;
static volatile int timerCallbackCounter = 0;
static volatile int timerRestartCounter = 0;
@@ -54,7 +54,7 @@ static void callback(GPTDriver *gptp) {
firmwareError("NULL globalTimerCallback");
return;
}
- isTimerPending = FALSE;
+ isTimerPending = false;
// // test code
// setOutputPinValue(LED_CRANKING, timerCallbackCounter % 2);
diff --git a/firmware/hw_layer/mmc_card.c b/firmware/hw_layer/mmc_card.c
index 418432351f..813e7814dc 100644
--- a/firmware/hw_layer/mmc_card.c
+++ b/firmware/hw_layer/mmc_card.c
@@ -48,7 +48,7 @@ SPI_BaudRatePrescaler_256 };
// don't forget check if STM32_SPI_USE_SPI2 defined and spi has init with correct GPIO in hardware.c
static MMCConfig mmccfg = { &MMC_CARD_SPI, &ls_spicfg, &hs_spicfg };
-static bool_t fs_ready = FALSE;
+static bool fs_ready = FALSE;
#define PUSHPULLDELAY 500
@@ -57,14 +57,15 @@ static bool_t fs_ready = FALSE;
*/
static FATFS MMC_FS;
+static Logging logger;
+
// print FAT error function
static void printError(char *str, FRESULT f_error) {
- print("FATfs Error \"%s\" %d\r\n", str, f_error);
+ scheduleMsg(&logger, "FATfs Error \"%s\" %d", str, f_error);
}
static FIL FDLogFile;
-static Logging logger;
static int totalLoggedBytes = 0;
static void printMmcPinout(void) {
@@ -109,14 +110,14 @@ static void ff_cmd_dir(char *path) {
char *fn;
if (!fs_ready) {
- print("Error: No File system is mounted.\r\n");
+ scheduleMsg(&logger, "Error: No File system is mounted");
return;
}
FRESULT res = f_opendir(&dir, path);
if (res != FR_OK) {
- print("Error opening directory %s\r\n", path);
+ scheduleMsg(&logger, "Error opening directory %s", path);
return;
}
@@ -137,7 +138,7 @@ static void ff_cmd_dir(char *path) {
break;
path[i] = 0;
} else {
- print("%c%c%c%c%c %u/%02u/%02u %02u:%02u %9lu %-12s\r\n", (fno.fattrib & AM_DIR) ? 'D' : '-',
+ scheduleMsg(&logger, "%c%c%c%c%c %u/%02u/%02u %02u:%02u %9lu %-12s", (fno.fattrib & AM_DIR) ? 'D' : '-',
(fno.fattrib & AM_RDO) ? 'R' : '-', (fno.fattrib & AM_HID) ? 'H' : '-',
(fno.fattrib & AM_SYS) ? 'S' : '-', (fno.fattrib & AM_ARC) ? 'A' : '-', (fno.fdate >> 9) + 1980,
(fno.fdate >> 5) & 15, fno.fdate & 31, (fno.ftime >> 11), (fno.ftime >> 5) & 63, fno.fsize,
@@ -156,7 +157,7 @@ void appendToLog(char *line) {
if (!fs_ready) {
if (!errorReported)
- print("appendToLog Error: No File system is mounted.\r\n");
+ scheduleMsg(&logger, "appendToLog Error: No File system is mounted");
errorReported = TRUE;
return;
}
@@ -174,7 +175,7 @@ void appendToLog(char *line) {
*/
static void MMCumount(void) {
if (!fs_ready) {
- print("Error: No File system is mounted. \"mountsd\" first.\r\n");
+ scheduleMsg(&logger, "Error: No File system is mounted. \"mountsd\" first");
return;
}
f_close(&FDLogFile); // close file
@@ -183,8 +184,8 @@ static void MMCumount(void) {
mmcStop(&MMCD1); // Disables the MMC peripheral.
f_mount(0, NULL); // FATFS: Unregister work area prior to discard it
memset(&FDLogFile, 0, sizeof(FIL)); // clear FDLogFile
- fs_ready = FALSE; // status = false
- print("MMC/SD card removed.\r\n");
+ fs_ready = false; // status = false
+ scheduleMsg(&logger, "MMC/SD card removed");
}
/*
@@ -194,7 +195,7 @@ static void MMCmount(void) {
// printMmcPinout();
if (fs_ready) {
- print("Error: Already mounted. \"umountsd\" first\r\n");
+ scheduleMsg(&logger, "Error: Already mounted. \"umountsd\" first");
return;
}
// start to initialize MMC/SD
@@ -203,7 +204,7 @@ static void MMCmount(void) {
// Performs the initialization procedure on the inserted card.
if (mmcConnect(&MMCD1) != CH_SUCCESS) {
- print("Can't connect or mount MMC/SD\r\n");
+ scheduleMsg(&logger, "Can't connect or mount MMC/SD");
return;
}
@@ -211,7 +212,7 @@ static void MMCmount(void) {
memset(&MMC_FS, 0, sizeof(FATFS)); // reserve the memory
if (f_mount(0, &MMC_FS) == FR_OK) {
createLogFile();
- print("MMC/SD mounted!\r\nDon't forget umountsd before remove to prevent lost your data.\r\n");
+ scheduleMsg(&logger, "MMC/SD mounted!\r\nDon't forget umountsd before remove to prevent lost your data");
}
}
diff --git a/firmware/hw_layer/pin_repository.c b/firmware/hw_layer/pin_repository.c
index c746b9e996..80e42b68d2 100644
--- a/firmware/hw_layer/pin_repository.c
+++ b/firmware/hw_layer/pin_repository.c
@@ -23,6 +23,9 @@ static int initialized = FALSE;
static Logging logger;
static int totalPinsUsed = 0;
+/**
+ * @deprecated - use hwPortname() instead
+ */
char *portname(GPIO_TypeDef* GPIOx) {
if (GPIOx == GPIOA)
return "PA";
diff --git a/firmware/hw_layer/trigger_input.cpp b/firmware/hw_layer/trigger_input.cpp
index ccd5add77f..4aba3f5d41 100644
--- a/firmware/hw_layer/trigger_input.cpp
+++ b/firmware/hw_layer/trigger_input.cpp
@@ -75,8 +75,7 @@ void initShaftPositionInputCapture(void) {
* @see shaft_icucfg for callback entry points
*/
shaft_icucfg.channel = ICU_CHANNEL_1;
- print("initShaftPositionInputCapture 1 %s:%d\r\n", portname(getHwPort(boardConfiguration->primaryTriggerInputPin)),
- getHwPin(boardConfiguration->primaryTriggerInputPin));
+ print("initShaftPositionInputCapture 1 %s\r\n", hwPortname(boardConfiguration->primaryTriggerInputPin));
icuStart(getPrimaryInputCaptureDriver(), &shaft_icucfg);
icuEnable(getPrimaryInputCaptureDriver());
@@ -85,8 +84,7 @@ void initShaftPositionInputCapture(void) {
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));
+ print("initShaftPositionInputCapture 2 %s\r\n", hwPortname(boardConfiguration->secondaryTriggerInputPin));
icuStart(getSecondaryInputCaptureDriver(), &shaft_icucfg);
icuEnable(getSecondaryInputCaptureDriver());
diff --git a/firmware/rusefi.cpp b/firmware/rusefi.cpp
index c5e4185814..81435cef0f 100644
--- a/firmware/rusefi.cpp
+++ b/firmware/rusefi.cpp
@@ -83,23 +83,21 @@
#include "main.h"
#include "trigger_structure.h"
#include "ec2.h"
-
-extern "C" {
-
-#include "global.h"
-#include "rfi_perftest.h"
-
-#include "rusefi.h"
-#include "eficonsole.h"
#include "hardware.h"
#include "engine_controller.h"
-#include "status_loop.h"
-#include "pin_repository.h"
-#include "status_loop.h"
+#include "global.h"
+extern "C" {
+
+#include "rfi_perftest.h"
+#include "rusefi.h"
#include "memstreams.h"
}
+#include "eficonsole.h"
+#include "status_loop.h"
+#include "pin_repository.h"
+
#if EFI_HD44780_LCD
#include "lcd_HD44780.h"
#endif /* EFI_HD44780_LCD */
@@ -255,5 +253,5 @@ void firmwareError(const char *fmt, ...) {
}
int getRusEfiVersion(void) {
- return 20140627;
+ return 20140709;
}
diff --git a/firmware/svnversion.h b/firmware/svnversion.h
index 609f13b98d..4b61c21238 100644
--- a/firmware/svnversion.h
+++ b/firmware/svnversion.h
@@ -1,5 +1,5 @@
// This file was generated by Version2Header
-// Fri Jun 27 20:16:32 EDT 2014
+// Sat Jul 05 19:09:48 EDT 2014
#ifndef SVN_VERSION
-#define SVN_VERSION 3701
+#define SVN_VERSION 3860
#endif
diff --git a/firmware/update_version.bat b/firmware/update_version.bat
index 28f8c4b53b..2dd3705dab 100644
--- a/firmware/update_version.bat
+++ b/firmware/update_version.bat
@@ -1,2 +1,3 @@
rem Let's regemerate 'svnversion.h'
+rem TODO: handle std err - for example, in case svn needs upgrade
java -jar ../java_tools/version2header.jar
\ No newline at end of file
diff --git a/firmware/util/cli_registry.c b/firmware/util/cli_registry.c
index ef8324633a..b7831b1871 100644
--- a/firmware/util/cli_registry.c
+++ b/firmware/util/cli_registry.c
@@ -6,6 +6,7 @@
* command line interface action names & callback. This logic is invoked in
* user context by the console thread - see consoleThreadThreadEntryPoint
*
+ * TODO: there is too much copy-paste here, this class needs some refactoring :)
*
* @date Nov 15, 2012
* @author Andrey Belomutskiy, (c) 2012-2014
@@ -17,6 +18,11 @@
#include "main.h"
#include "cli_registry.h"
#include "efilib.h"
+
+#if EFI_PROD_CODE
+#include "board_test.h"
+#endif
+
#if EFI_PROD_CODE || EFI_SIMULATOR
#include "eficonsole.h"
static Logging logging;
@@ -25,6 +31,8 @@ static Logging logging;
static int consoleActionCount = 0;
static TokenCallback consoleActions[CONSOLE_MAX_ACTIONS];
+#define SECURE_LINE_PREFIX "sec!"
+
void resetConsoleActions(void) {
consoleActionCount = 0;
}
@@ -70,10 +78,21 @@ void addConsoleActionF(const char *token, VoidFloat callback) {
doAddAction(token, FLOAT_PARAMETER, (Void) callback);
}
+void addConsoleActionFF(const char *token, VoidFloatFloat callback) {
+ doAddAction(token, FLOAT_FLOAT_PARAMETER, (Void) callback);
+}
+
/**
* @brief This function prints out a list of all available commands
*/
void helpCommand(void) {
+#if EFI_PROD_CODE
+ if (isBoardTestMode()) {
+ printBoardTestState();
+ return;
+ }
+#endif /* EFI_PROD_CODE */
+
#if EFI_PROD_CODE || EFI_SIMULATOR
scheduleMsg(&logging, "%d actions available", consoleActionCount);
for (int i = 0; i < consoleActionCount; i++) {
@@ -141,6 +160,19 @@ void handleActionWithParameter(TokenCallback *current, char *parameter) {
return;
}
+ if (current->parameterType == FLOAT_FLOAT_PARAMETER) {
+ int spaceIndex = indexOf(parameter, ' ');
+ if (spaceIndex == -1)
+ return;
+ parameter[spaceIndex] = 0;
+ float value1 = atoff(parameter);
+ parameter += spaceIndex + 1;
+ float value2 = atoff(parameter);
+ VoidFloatFloat callbackS = (VoidFloatFloat) current->callback;
+ (*callbackS)(value1, value2);
+ return;
+ }
+
int value = atoi(parameter);
if (value == ERROR_CODE) {
print("invalid integer [%s]\r\n", parameter);
@@ -173,10 +205,10 @@ int strEqual(const char *str1, const char *str2) {
int len1 = strlen(str1);
int len2 = strlen(str2);
if (len1 != len2)
- return FALSE;
+ return false;
for (int i = 0; i < len1; i++)
if (str1[i] != str2[i])
- return FALSE;
+ return false;
return TRUE;
}
@@ -189,10 +221,14 @@ void initConsoleLogic() {
addConsoleActionI("echo", echo);
}
+/**
+ * @return NULL if input line validation failed, reference to line payload if validation succeeded.
+ * @see sendOutConfirmation() for command confirmation processing.
+ */
char *validateSecureLine(char *line) {
if (line == NULL)
return NULL;
- if (strncmp("sec!", line, 4) == 0) {
+ if (strncmp(SECURE_LINE_PREFIX, line, 4) == 0) {
// COM protocol looses bytes, this is a super-naive error detection
// print("Got secure mode request header [%s]\r\n", line);
@@ -223,7 +259,7 @@ static char confirmation[200];
void sendOutConfirmation(char *value, int i);
-static bool_t handleConsoleLineInternal(char *line, int lineLength) {
+static bool handleConsoleLineInternal(char *line, int lineLength) {
int firstTokenLength = tokenLength(line);
// print("processing [%s] with %d actions\r\n", line, consoleActionCount);
@@ -251,7 +287,7 @@ static bool_t handleConsoleLineInternal(char *line, int lineLength) {
}
}
}
- return FALSE;
+ return false;
}
/**
@@ -274,7 +310,7 @@ void handleConsoleLine(char *line) {
strcat(confirmation, line);
strcat(confirmation, ":");
- bool_t isKnownComman = handleConsoleLineInternal(line, lineLength);
+ bool isKnownComman = handleConsoleLineInternal(line, lineLength);
// confirmation happens after the command to avoid conflict with command own output
sendOutConfirmation(confirmation, lineLength);
diff --git a/firmware/util/cli_registry.h b/firmware/util/cli_registry.h
index 6f8c0fc9ca..3fef118027 100644
--- a/firmware/util/cli_registry.h
+++ b/firmware/util/cli_registry.h
@@ -23,6 +23,7 @@ typedef enum {
STRING_PARAMETER,
STRING3_PARAMETER,
TWO_INTS_PARAMETER,
+ FLOAT_FLOAT_PARAMETER
} ACTION_PARAMETER_TYPE;
typedef struct {
@@ -38,6 +39,7 @@ int tokenLength(char *msgp);
typedef void (*Void)(void);
typedef void (*VoidInt)(int);
typedef void (*VoidFloat)(float);
+typedef void (*VoidFloatFloat)(float, float);
typedef void (*VoidIntInt)(int, int);
typedef void (*VoidCharPtr)(char *);
typedef void (*VoidCharPtrCharPtrCharPtr)(char *, char *, char *);
@@ -52,6 +54,7 @@ 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 addConsoleActionFF(const char *token, VoidFloatFloat callback);
void addConsoleActionS(const char *token, VoidCharPtr callback);
void addConsoleActionSSS(const char *token, VoidCharPtrCharPtrCharPtr callback);
diff --git a/java_console/autotest/src/com/rusefi/AutoTest.java b/java_console/autotest/src/com/rusefi/AutoTest.java
index 5ee8be0136..454f507d53 100644
--- a/java_console/autotest/src/com/rusefi/AutoTest.java
+++ b/java_console/autotest/src/com/rusefi/AutoTest.java
@@ -24,9 +24,8 @@ public class AutoTest {
sendCommand("set_engine_type 2");
testDodgeNeon();
-// todo: uncomment once we resolve the RAM issue & OUTPUT_SIGNAL_MAX_SIZE gets back to 60
-// sendCommand("set_engine_type 7");
-// testFord6();
+ sendCommand("set_engine_type 7");
+ testFord6();
sendCommand("set_engine_type 4");
testFordFiesta();
@@ -53,9 +52,14 @@ public class AutoTest {
}
private static void testFordFiesta() {
-// WaveChart chart;
-// changeRpm(2000);
-// chart = nextChart();
+ WaveChart chart;
+ IoUtil.changeRpm(2000);
+ chart = nextChart();
+
+ String msg = "Fiesta";
+ double x = 312;
+ assertWave(msg, chart, WaveChart.SPARK_1, 0.1333333, x, x + 360);
+ assertWave(msg, chart, WaveChart.SPARK_3, 0.1333333, x + 180, x + 540);
}
private static void testFord6() {
@@ -83,7 +87,7 @@ public class AutoTest {
IoUtil.changeRpm(600);
chart = nextChart();
x = 76;
- assertWave("aspire default runnint ", chart, WaveChart.SPARK_1, 0.04, x, x + 180, x + 360, x + 540);
+ assertWave("aspire default running ", chart, WaveChart.SPARK_1, 0.04, x, x + 180, x + 360, x + 540);
IoUtil.changeRpm(200);
diff --git a/java_console/io/src/com/rusefi/io/LinkManager.java b/java_console/io/src/com/rusefi/io/LinkManager.java
index 2085dbe912..4644376cd9 100644
--- a/java_console/io/src/com/rusefi/io/LinkManager.java
+++ b/java_console/io/src/com/rusefi/io/LinkManager.java
@@ -50,14 +50,18 @@ public class LinkManager {
});
public static boolean onlyUI = false;
private static LinkConnector connector;
- private static String port;
+
+ /**
+ * This flag controls if mock controls are needed
+ */
+ public static boolean isStimulationMode;
public static void start(String port) {
- LinkManager.port = port;
if (port.equals(LOG_VIEWER)) {
connector = LinkManager.VOID;
} else if (TcpConnector.isTcpPort(port)) {
connector = new TcpConnector(port);
+ isStimulationMode = true;
} else {
connector = new SerialConnector(port);
}
diff --git a/java_console/models/src/com/irnems/core/EngineState.java b/java_console/models/src/com/irnems/core/EngineState.java
index d8673daa8a..6a336e6890 100644
--- a/java_console/models/src/com/irnems/core/EngineState.java
+++ b/java_console/models/src/com/irnems/core/EngineState.java
@@ -64,16 +64,17 @@ public class EngineState {
);
- SensorStats.start(Sensor.COOLANT, Sensor.COOLANT_WIDTH);
- SensorStats.start(Sensor.INTAKE_AIR, Sensor.INTAKE_AIR_WIDTH);
+// SensorStats.start(Sensor.CLT, Sensor.COOLANT_WIDTH);
+// SensorStats.start(Sensor.IAT, Sensor.INTAKE_AIR_WIDTH);
SensorStats.start(Sensor.VREF, Sensor.VREF_WIDTH);
addDoubleSensor(RPM_KEY, Sensor.RPM);
- addDoubleSensor("mat", Sensor.INTAKE_AIR);
+ addDoubleSensor("mat", Sensor.IAT);
addDoubleSensor("map", Sensor.MAP);
addDoubleSensor("map_r", Sensor.MAP_RAW);
- addDoubleSensor("clt", Sensor.COOLANT);
- addDoubleSensor("tp", Sensor.THROTTLE);
+ addDoubleSensor("baro", Sensor.BARO);
+ addDoubleSensor("clt", Sensor.CLT);
+ addDoubleSensor("tp", Sensor.TPS);
addDoubleSensor("dwell0", Sensor.DWELL0);
addDoubleSensor("dwell1", Sensor.DWELL1);
addDoubleSensor("tch", Sensor.T_CHARGE);
@@ -200,7 +201,7 @@ public class EngineState {
public static String unpackString(String message) {
String prefix = "line" + PACKING_DELIMITER;
if (!message.startsWith(prefix)) {
- FileLog.MAIN.logLine("EngineState: unexpected header: " + message);
+ FileLog.MAIN.logLine("EngineState: unexpected header: " + message + " while looking for " + prefix);
return null;
}
message = message.substring(prefix.length());
diff --git a/java_console/models/src/com/irnems/core/Sensor.java b/java_console/models/src/com/irnems/core/Sensor.java
index 645f372d3e..b854b2e3b4 100644
--- a/java_console/models/src/com/irnems/core/Sensor.java
+++ b/java_console/models/src/com/irnems/core/Sensor.java
@@ -10,19 +10,25 @@ public enum Sensor {
RPM("RPM"),
MAP("MAP"),
MAP_RAW("MAP_RAW"),
+ BARO("Baro"),
TIMING("Timing"),
- THROTTLE("throttle", "%", 100),
- COOLANT("coolant", "F", 300),
- COOLANT_WIDTH("c w", "", 30),
- INTAKE_AIR("air temp", "F", 150),
- INTAKE_AIR_WIDTH("air w", "", 30),
+ /**
+ * Please note that these enum names are used to make 'set_mock_XXX_voltage' commands
+ */
+ CLT("Coolant", "temperature, C", 300),
+ IAT("Intake Air", "temperature, C", 150),
+ AFR("A/F ratio", "", 0, 20),
+ MAF("MAF", "Volts", 4),
+ TPS("throttle", "%", 100),
+
+// COOLANT_WIDTH("c w", "", 30),
+// INTAKE_AIR_WIDTH("air w", "", 30),
TABLE_SPARK("table spark", "ms", -40, 40),
VREF("VRef", "Volts", 6),
VBATT("VBatt", "Volts", 18),
VREF_WIDTH("VRef w", "", 1),
- MAF("MAF", "Volts", 4),
DWELL0("Dwell0", "ms", 0, 30, BackgroundColor.BEIGE),
DWELL1("Dwell1", "ms", 0, 30, BackgroundColor.BEIGE),
ADVANCE0("Advance0", "dg", -40, 40, BackgroundColor.BROWN),
@@ -40,7 +46,6 @@ public enum Sensor {
DEFAULT_FUEL("map fuel", "ms", 0, 40),
T_CHARGE("T Charge", "f", 0, 200),
- AFR("A/F ratio", "", 0, 20),
CHARTSIZE("CHARTSIZE"),
CHART_STATUS("CHART_STATUS"),
diff --git a/java_console/models/src/com/irnems/core/test/WaveReportTest.java b/java_console/models/src/com/irnems/core/test/WaveReportTest.java
index 8e995d35d6..c2f2987568 100644
--- a/java_console/models/src/com/irnems/core/test/WaveReportTest.java
+++ b/java_console/models/src/com/irnems/core/test/WaveReportTest.java
@@ -11,7 +11,7 @@ import static junit.framework.Assert.assertEquals;
* (c) Andrey Belomutskiy
*/
public class WaveReportTest {
- public static final String report = "up!14679!down!15991!up!16823!down!18134!up!18965!down!20278!up!21108!down!22420!up!23251!down!24563!up!25394!down!26706!up!27536!down!28850!up!29678!down!30991!up!31822!down!33134!up!33965!down!35277!up!36108!down!37420!up!38251!down!39563!up!40394!down!41706!up!42537!down!43849!";
+ public static final String report = "u!14679!d!15991!u!16823!d!18134!u!18965!d!20278!u!21108!d!22420!u!23251!d!24563!u!25394!d!26706!u!27536!d!28850!u!29678!d!30991!u!31822!d!33134!u!33965!d!35277!u!36108!d!37420!u!38251!d!39563!u!40394!d!41706!u!42537!d!43849!";
@Test
public void testParse() {
diff --git a/java_console/models/src/com/rusefi/waves/WaveChart.java b/java_console/models/src/com/rusefi/waves/WaveChart.java
index 6e1aece866..23ab5a0d5e 100644
--- a/java_console/models/src/com/rusefi/waves/WaveChart.java
+++ b/java_console/models/src/com/rusefi/waves/WaveChart.java
@@ -13,16 +13,18 @@ import java.util.Map;
* (c) Andrey Belomutskiy
*/
public class WaveChart {
- public static final String INJECTOR_1 = "Injector 1";
- public static final String INJECTOR_2 = "Injector 2";
- public static final String INJECTOR_3 = "Injector 3";
- public static final String INJECTOR_4 = "Injector 4";
- public static final String INJECTOR_5 = "Injector 5";
- public static final String INJECTOR_6 = "Injector 6";
- public static final String SPARK_1 = "Spark 1";
- public static final String SPARK_2 = "Spark 2";
- public static final String SPARK_3 = "Spark 3";
- public static final String SPARK_4 = "Spark 4";
+ public static final String INJECTOR_1 = "inj1";
+ public static final String INJECTOR_2 = "inj2";
+ public static final String INJECTOR_3 = "inj3";
+ public static final String INJECTOR_4 = "inj4";
+ public static final String INJECTOR_5 = "inj5";
+ public static final String INJECTOR_6 = "inj6";
+ public static final String INJECTOR_7 = "inj7";
+ public static final String INJECTOR_8 = "inj8";
+ public static final String SPARK_1 = "spa1";
+ public static final String SPARK_2 = "spa2";
+ public static final String SPARK_3 = "spa3";
+ public static final String SPARK_4 = "spa4";
public final Map map;
diff --git a/java_console/models/src/com/rusefi/waves/WaveReport.java b/java_console/models/src/com/rusefi/waves/WaveReport.java
index b102f031aa..a1afd97cae 100644
--- a/java_console/models/src/com/rusefi/waves/WaveReport.java
+++ b/java_console/models/src/com/rusefi/waves/WaveReport.java
@@ -10,6 +10,7 @@ import java.util.List;
/**
* Date: 6/23/13
* (c) Andrey Belomutskiy
+ * @see com.rusefi.AnalogChartPanel.AnalogChart
*/
public class WaveReport implements TimeAxisTranslator {
public static final String WAVE_CHART = "wave_chart";
@@ -19,6 +20,8 @@ public class WaveReport implements TimeAxisTranslator {
*/
public static final double SYS_TICKS_PER_MS = 100;
public static final int mult = (int) (100 * SYS_TICKS_PER_MS); // 100ms
+ private static final String WC_DOWN = "d";
+ private static final String WC_UP = "u";
List list;
private int maxTime;
@@ -68,15 +71,15 @@ public class WaveReport implements TimeAxisTranslator {
List times = new ArrayList();
int index = 0;
- if (array[0].equals("down"))
+ if (array[0].equals(WC_DOWN))
index += 2;
while (index + 3 < array.length) {
- if (!array[index].equals("up")) {
+ if (!array[index].equals(WC_UP)) {
index += 2;
continue;
}
- if (!array[index + 2].equals("down")) {
+ if (!array[index + 2].equals(WC_DOWN)) {
index += 2;
continue;
}
diff --git a/java_console/models/src/com/rusefi/waves/test/WaveChartParserTest.java b/java_console/models/src/com/rusefi/waves/test/WaveChartParserTest.java
index e41b5d8bfa..ccff346bab 100644
--- a/java_console/models/src/com/rusefi/waves/test/WaveChartParserTest.java
+++ b/java_console/models/src/com/rusefi/waves/test/WaveChartParserTest.java
@@ -21,7 +21,7 @@ public class WaveChartParserTest {
WaveChart result = WaveChartParser.unpackToMap("");
assertTrue(result.map.isEmpty());
- result = WaveChartParser.unpackToMap("wave_chart,input1 A8!up!185080!r!0!2670996!crank!up!2670996_2!crank2!up!2674512!Injector 4!up!2674512!Spark 1!up!2674512!Injector 4!down!2674665!Spark 1!down!2674912!crank2!down!2680055!crank2!up!2687963!Injector 2!up!2687963!Spark 1!up!2687963!Injector 2!down!2688116!Spark 1!down!2688363!crank2!down!2693093!crank!down!2697428!crank2!up!2700454!Injector 1!up!2700454!Spark 1!up!2700454!Injector 1!down!2700607!Spark 1!down!2700854!crank2!down!2705329!crank2!up!2712449!Injector 3!up!2712449!Spark 1!up!2712449!Injector 3!down!2712681!Spark 1!down!2712849!crank2!down!2717385!r!0!2721629!crank!up!2721629!crank2!up!2724641!Injector 1!up!2724641!Injector 2!up!2724641!Injector 3!up!2724641!Injector 4!up!2724641!Spark 1!up!2724641!Injector 4!down!2726241!Injector 3!down!2726241!Injector 2!down!2726241!Injector 1!down!2726241!crank2!down!2729677!Spark 1!down!2730008!crank2!up!2736851!Injector 1!up!2736851!Injector 2!up!2736851!Injector 3!up!2736851!Injector 4!up!2736851!Spark 1!up!2736851!Injector 4!down!2738451!Injector 3!down!2738451!Injector 2!down!2738451!Injector 1!down!2738451!crank2!down!2741922!Spark 1!down!2742218!crank!down!2746104!crank2!up!2749010!Injector 1!up!2749010!Injector 2!up!2749010!Injector 3!up!2749010!Injector 4!up!2749010!Spark 1!up!2749010!Injector 4!down!2750601!Injector 3!down!2750601!Injector 2!down!2750601!Injector 1!down!2750601!crank2!down!2753919!Spark 1!down!2754377!crank2!up!2760922!Injector 1!up!2760922!Injector 2!up!2760922!Injector 3!up!2760922!Injector 4!up!2760922!Spark 1!up!2760922!Injector 4!down!2762522!Injector 3!down!2762522!Injector 2!down!2762522!Injector 1!down!2762522!crank2!down!2765882!Spark 1!down!2766289!r!236!2769990!crank!up!2769990!crank2!up!2773003!Injector 1!up!2773003!Injector 2!up!2773003!Injector 3!up!2773003!Injector 4!up!2773003!Spark 1!up!2773003!Injector 4!down!2774603!Injector 3!down!2774603!Injector 2!down!2774603!Injector 1!down!2774603!Spark 1!down!2778110!crank2!down!2778143!crank2!up!2785215!Injector 1!up!2785215!Injector 2!up!2785215!Injector 3!up!2785215!Injector 4!up!2785215!Spark 1!up!2785215!Injector 4!down!2786815!,");
+ result = WaveChartParser.unpackToMap("wave_chart,input1 A8!u!185080!r!0!2670996!crank!u!2670996_2!crank2!u!2674512!Injector 4!u!2674512!Spark 1!u!2674512!Injector 4!d!2674665!Spark 1!d!2674912!crank2!d!2680055!crank2!u!2687963!Injector 2!u!2687963!Spark 1!u!2687963!Injector 2!d!2688116!Spark 1!d!2688363!crank2!d!2693093!crank!d!2697428!crank2!u!2700454!Injector 1!u!2700454!Spark 1!u!2700454!Injector 1!d!2700607!Spark 1!d!2700854!crank2!d!2705329!crank2!u!2712449!Injector 3!u!2712449!Spark 1!u!2712449!Injector 3!d!2712681!Spark 1!d!2712849!crank2!d!2717385!r!0!2721629!crank!u!2721629!crank2!u!2724641!Injector 1!u!2724641!Injector 2!u!2724641!Injector 3!u!2724641!Injector 4!u!2724641!Spark 1!u!2724641!Injector 4!d!2726241!Injector 3!d!2726241!Injector 2!d!2726241!Injector 1!d!2726241!crank2!d!2729677!Spark 1!d!2730008!crank2!u!2736851!Injector 1!u!2736851!Injector 2!u!2736851!Injector 3!u!2736851!Injector 4!u!2736851!Spark 1!u!2736851!Injector 4!d!2738451!Injector 3!d!2738451!Injector 2!d!2738451!Injector 1!d!2738451!crank2!d!2741922!Spark 1!d!2742218!crank!d!2746104!crank2!u!2749010!Injector 1!u!2749010!Injector 2!u!2749010!Injector 3!u!2749010!Injector 4!u!2749010!Spark 1!u!2749010!Injector 4!d!2750601!Injector 3!d!2750601!Injector 2!d!2750601!Injector 1!d!2750601!crank2!d!2753919!Spark 1!d!2754377!crank2!u!2760922!Injector 1!u!2760922!Injector 2!u!2760922!Injector 3!u!2760922!Injector 4!u!2760922!Spark 1!u!2760922!Injector 4!d!2762522!Injector 3!d!2762522!Injector 2!d!2762522!Injector 1!d!2762522!crank2!d!2765882!Spark 1!d!2766289!r!236!2769990!crank!u!2769990!crank2!u!2773003!Injector 1!u!2773003!Injector 2!u!2773003!Injector 3!u!2773003!Injector 4!u!2773003!Spark 1!u!2773003!Injector 4!d!2774603!Injector 3!d!2774603!Injector 2!d!2774603!Injector 1!d!2774603!Spark 1!d!2778110!crank2!d!2778143!crank2!u!2785215!Injector 1!u!2785215!Injector 2!u!2785215!Injector 3!u!2785215!Injector 4!u!2785215!Spark 1!u!2785215!Injector 4!d!2786815!,");
assertEquals(9, result.map.size());
String crankReport = result.get("crank").toString();
@@ -39,14 +39,14 @@ public class WaveChartParserTest {
@Test
public void testDutyCycle() {
- WaveChart result = WaveChartParser.unpackToMap("r!1199!64224414!crank2!up!64225149_3!Injector 2!up!64225149!Spark 1!up!64225249!Injector 2!down!64225303!Spark 1!down!64225649!crank2!down!64226105_4!crank!down!64226980_5!crank2!up!64227730_6!Injector 1!up!64227730!Spark 1!up!64227830!Injector 1!down!64227884!Spark 1!down!64228230!crank2!down!64228678_7!crank2!up!64230212_8!Injector 3!up!64230212!Spark 1!up!64230312!Injector 3!down!64230366!Spark 1!down!64230712!crank2!down!64231156_9!crank!up!64231982_0!crank2!up!64232672_1!Injector 4!up!64232672!Spark 1!up!64232772!Injector 4!down!64232826!Spark 1!down!64233172!crank2!down!64233626_2!r!1200!64234412!crank2!up!64235150_3!Injector 2!up!64235150!Spark 1!up!64235250!Injector 2!down!64235304!Spark 1!down!64235650!crank2!down!64236106_4!crank!down!64236981_5!crank2!up!64237730_6!Injector 1!up!64237730!Spark 1!up!64237830!Injector 1!down!64237884!Spark 1!down!64238230!crank2!down!64238677_7!crank2!up!64240213_8!Injector 3!up!64240213!Spark 1!up!64240313!Injector 3!down!64240367!Spark 1!down!64240713!crank2!down!64241158_9!crank!up!64241982_0!crank2!up!64242674_1!Injector 4!up!64242674!Spark 1!up!64242774!Injector 4!down!64242828!Spark 1!down!64243174!crank2!down!64243625_2!r!1200!64244412!crank2!up!64245149_3!Injector 2!up!64245149!Spark 1!up!64245249!Injector 2!down!64245303!Spark 1!down!64245649!crank2!down!64246106_4!crank!down!64246980_5!crank2!up!64247728_6!Injector 1!up!64247728!Spark 1!up!64247828!Injector 1!down!64247882!Spark 1!down!64248228!crank2!down!64248679_7!crank2!up!64250212_8!Injector 3!up!64250212!Spark 1!up!64250312!Injector 3!down!64250366!Spark 1!down!64250712!crank2!down!64251158_9!crank!up!64251982_0!crank2!up!64252674_1!Injector 4!up!64252674!Spark 1!up!64252774!Injector 4!down!64252828!Spark 1!down!64253174!crank2!down!64253625_2!r!1200!64254412!crank2!up!64255150_3!Injector 2!up!64255150!Spark 1!up!64255250!Injector 2!down!64255304!Spark 1!down!64255650!crank2!down!64256106_4!crank!down!64256982_5!crank2!up!64257728_6!Injector 1!up!64257728!Spark 1!up!64257828!Injector 1!down!64257882!Spark 1!down!64258228!crank2!down!64258678_7!crank2!up!64260214_8!Injector 3!up!64260214!Spark 1!up!64260314!Injector 3!down!64260368!Spark 1!down!64260714!,");
+ WaveChart result = WaveChartParser.unpackToMap("r!1199!64224414!crank2!u!64225149_3!Injector 2!u!64225149!Spark 1!u!64225249!Injector 2!d!64225303!Spark 1!d!64225649!crank2!d!64226105_4!crank!d!64226980_5!crank2!u!64227730_6!Injector 1!u!64227730!Spark 1!u!64227830!Injector 1!d!64227884!Spark 1!d!64228230!crank2!d!64228678_7!crank2!u!64230212_8!Injector 3!u!64230212!Spark 1!u!64230312!Injector 3!d!64230366!Spark 1!d!64230712!crank2!d!64231156_9!crank!u!64231982_0!crank2!u!64232672_1!Injector 4!u!64232672!Spark 1!u!64232772!Injector 4!d!64232826!Spark 1!d!64233172!crank2!d!64233626_2!r!1200!64234412!crank2!u!64235150_3!Injector 2!u!64235150!Spark 1!u!64235250!Injector 2!d!64235304!Spark 1!d!64235650!crank2!d!64236106_4!crank!d!64236981_5!crank2!u!64237730_6!Injector 1!u!64237730!Spark 1!u!64237830!Injector 1!d!64237884!Spark 1!d!64238230!crank2!d!64238677_7!crank2!u!64240213_8!Injector 3!u!64240213!Spark 1!u!64240313!Injector 3!d!64240367!Spark 1!d!64240713!crank2!d!64241158_9!crank!u!64241982_0!crank2!u!64242674_1!Injector 4!u!64242674!Spark 1!u!64242774!Injector 4!d!64242828!Spark 1!d!64243174!crank2!d!64243625_2!r!1200!64244412!crank2!u!64245149_3!Injector 2!u!64245149!Spark 1!u!64245249!Injector 2!d!64245303!Spark 1!d!64245649!crank2!d!64246106_4!crank!d!64246980_5!crank2!u!64247728_6!Injector 1!u!64247728!Spark 1!u!64247828!Injector 1!d!64247882!Spark 1!d!64248228!crank2!d!64248679_7!crank2!u!64250212_8!Injector 3!u!64250212!Spark 1!u!64250312!Injector 3!d!64250366!Spark 1!d!64250712!crank2!d!64251158_9!crank!u!64251982_0!crank2!u!64252674_1!Injector 4!u!64252674!Spark 1!u!64252774!Injector 4!d!64252828!Spark 1!d!64253174!crank2!d!64253625_2!r!1200!64254412!crank2!u!64255150_3!Injector 2!u!64255150!Spark 1!u!64255250!Injector 2!d!64255304!Spark 1!d!64255650!crank2!d!64256106_4!crank!d!64256982_5!crank2!u!64257728_6!Injector 1!u!64257728!Spark 1!u!64257828!Injector 1!d!64257882!Spark 1!d!64258228!crank2!d!64258678_7!crank2!u!64260214_8!Injector 3!u!64260214!Spark 1!u!64260314!Injector 3!d!64260368!Spark 1!d!64260714!,");
assertFalse(result.map.isEmpty());
StringBuilder revolutions = result.get(RevolutionLog.TOP_DEAD_CENTER_MESSAGE);
RevolutionLog rl = RevolutionLog.parseRevolutions(revolutions);
- StringBuilder inj1 = result.get(WaveChart.INJECTOR_1);
+ StringBuilder inj1 = result.get("Injector 1");
WaveReport wr = new WaveReport(inj1.toString());
for (WaveReport.UpDown ud : wr.getList()) {
@@ -58,7 +58,7 @@ public class WaveChartParserTest {
@Test
public void testUpOnly() {
- List list = WaveReport.parse("up!15500!up!25500!up!35500!up!45500!up!55500!up!65500!up!75500!up!85500!");
+ List list = WaveReport.parse("up!15500!u!25500!u!35500!u!45500!u!55500!u!65500!u!75500!u!85500!");
assertEquals(0, list.size());
}
}
diff --git a/java_console/ui/src/com/irnems/EcuStimulator.java b/java_console/ui/src/com/irnems/EcuStimulator.java
index bed82cb177..4602886f2e 100644
--- a/java_console/ui/src/com/irnems/EcuStimulator.java
+++ b/java_console/ui/src/com/irnems/EcuStimulator.java
@@ -8,8 +8,8 @@ import com.irnems.file.TableGenerator;
import com.irnems.models.Point3D;
import com.irnems.models.Range;
import com.irnems.models.XYData;
-import com.irnems.ui.ChartHelper;
-import com.irnems.ui.RpmModel;
+import com.rusefi.ui.ChartHelper;
+import com.rusefi.ui.RpmModel;
import com.irnems.ui.widgets.PotCommand;
import com.irnems.ui.widgets.RpmCommand;
import com.rusefi.io.LinkManager;
diff --git a/java_console/ui/src/com/irnems/Launcher.java b/java_console/ui/src/com/irnems/Launcher.java
index b4a3120f70..fadb8202a8 100644
--- a/java_console/ui/src/com/irnems/Launcher.java
+++ b/java_console/ui/src/com/irnems/Launcher.java
@@ -2,10 +2,10 @@ package com.irnems;
import com.irnems.core.EngineState;
import com.irnems.core.MessagesCentral;
-import com.irnems.ui.*;
import com.rusefi.AnalogChartPanel;
import com.rusefi.PortLookupFrame;
import com.rusefi.io.LinkManager;
+import com.rusefi.ui.*;
import jssc.SerialPortList;
import javax.swing.*;
@@ -20,23 +20,27 @@ import javax.swing.*;
* @see WavePanel
*/
public class Launcher extends FrameHelper {
- private static final Object CONSOLE_VERSION = "20140407";
+ private static final Object CONSOLE_VERSION = "20140709";
+ public static final boolean SHOW_STIMULATOR = false;
public Launcher(String port) {
FileLog.MAIN.start();
LinkManager.start(port);
+ FileLog.MAIN.logLine("Console " + CONSOLE_VERSION);
+
JTabbedPane tabbedPane = new JTabbedPane();
RpmPanel rpmPanel = new RpmPanel();
tabbedPane.addTab("Main", rpmPanel.createRpmPanel());
- tabbedPane.addTab("Gauges", new GaugePanel());
+ tabbedPane.addTab("Gauges", new GaugesPanel());
tabbedPane.addTab("Digital Sniffer", WavePanel.getInstance());
tabbedPane.addTab("Analog Sniffer", new AnalogChartPanel());
// tabbedPane.addTab("ADC", new AdcPanel(new BooleanInputsModel()).createAdcPanel());
-// tabbedPane.add("Emulation Map", EcuStimulator.panel);
+ if (SHOW_STIMULATOR)
+ tabbedPane.add("Emulation Map", EcuStimulator.panel);
// tabbedPane.addTab("live map adjustment", new Live3DReport().getControl());
tabbedPane.add("MessagesCentral", new MsgPanel(true));
diff --git a/java_console/ui/src/com/irnems/LogViewer.java b/java_console/ui/src/com/irnems/LogViewer.java
index 0f3bd1304e..d71bb937de 100644
--- a/java_console/ui/src/com/irnems/LogViewer.java
+++ b/java_console/ui/src/com/irnems/LogViewer.java
@@ -2,7 +2,7 @@ package com.irnems;
import com.irnems.core.EngineState;
import com.irnems.file.FileUtils;
-import com.irnems.ui.WavePanel;
+import com.rusefi.ui.WavePanel;
import com.irnems.ui.widgets.UpDownImage;
import com.rusefi.FIleItem;
import com.rusefi.io.LinkManager;
diff --git a/java_console/ui/src/com/irnems/ShowMap.java b/java_console/ui/src/com/irnems/ShowMap.java
index ff91f636b7..7efaf04473 100644
--- a/java_console/ui/src/com/irnems/ShowMap.java
+++ b/java_console/ui/src/com/irnems/ShowMap.java
@@ -2,8 +2,8 @@ package com.irnems;
import com.irnems.file.BaseMap;
import com.irnems.models.XYData;
-import com.irnems.ui.FrameHelper;
-import com.irnems.ui.ChartHelper;
+import com.rusefi.ui.FrameHelper;
+import com.rusefi.ui.ChartHelper;
import javax.swing.*;
diff --git a/java_console/ui/src/com/irnems/ui/GaugePanel.java b/java_console/ui/src/com/irnems/ui/GaugePanel.java
deleted file mode 100644
index 257de9c06c..0000000000
--- a/java_console/ui/src/com/irnems/ui/GaugePanel.java
+++ /dev/null
@@ -1,133 +0,0 @@
-package com.irnems.ui;
-
-import com.irnems.core.Sensor;
-import com.irnems.core.SensorCentral;
-import com.irnems.ui.widgets.MafCommand;
-import com.irnems.ui.widgets.PotCommand;
-import com.irnems.ui.widgets.RpmCommand;
-import eu.hansolo.steelseries.gauges.Radial;
-import eu.hansolo.steelseries.tools.ColorDef;
-
-import javax.swing.*;
-import java.awt.*;
-
-/**
- * Date: 2/5/13
- * (c) Andrey Belomutskiy
- */
-public class GaugePanel extends JComponent {
- private static final int ADC_MAX_VALUE = 255; // mazda ECU
-// private static final int ADC_MAX_VALUE = 4095; // discovery board
-
- public GaugePanel() {
- setLayout(new GridLayout(1, 3));
-
-
-// Radial radial2 = createRadial("title");
-
- JPanel box2 = new JPanel(new GridLayout(3, 5));
-
-
- box2.add(createControls());
- box2.add(createGauge(Sensor.T_CHARGE));
- box2.add(createGauge(Sensor.DWELL1));
- box2.add(createGauge(Sensor.DWELL0));
- box2.add(createGauge(Sensor.DUTY0));
- box2.add(createGauge(Sensor.ADVANCE0));
- box2.add(createGauge(Sensor.MAF));
- box2.add(createGauge(Sensor.FUEL));
- box2.add(createGauge(Sensor.FUEL_BASE));
- box2.add(createGauge(Sensor.FUEL_CLT));
- box2.add(createGauge(Sensor.FUEL_IAT));
- box2.add(createGauge(Sensor.FUEL_LAG));
-
-// box2.add(createGauge(Sensor.TABLE_SPARK));
-
-
-// box2.add(createGauge(Sensor.DUTY1));
-// box2.add(createGauge(Sensor.ADVANCE1));
- box2.add(createGauge(Sensor.INTAKE_AIR));
- //box2.add(createGauge(Sensor.INTAKE_AIR_WIDTH));
- box2.add(createGauge(Sensor.COOLANT));
-// box2.add(createGauge(Sensor.COOLANT_WIDTH));
-
- box2.add(createGauge(Sensor.MAP));
- box2.add(createGauge(Sensor.MAP_RAW));
- box2.add(createGauge(Sensor.THROTTLE));
-// box2.add(createGauge(Sensor.VREF, PotCommand.VOLTAGE_CORRECTION));
-// box2.add(createGauge(Sensor.VREF_WIDTH));
-
-// box2.add(createGauge(Sensor.ADC_FAST));
-// box2.add(createGauge(Sensor.ADC_FAST_AVG));
-
-
- box2.add(createGauge(Sensor.AFR));
- box2.add(createGauge(Sensor.DEFAULT_FUEL));
-
- box2.add(createGauge(Sensor.TIMING));
-
- box2.add(createRpmGauge());
-
- //add(rpmGauge);
- add(box2);
-// add(new JLabel("fd"), BorderLayout.EAST);
- }
-
- private Component createControls() {
- JPanel controls = new JPanel(new GridLayout(2, 1));
- controls.add(new RpmCommand());
- controls.add(new MafCommand());
- return controls;
- }
-
- private Radial createRpmGauge() {
- final Radial rpmGauge = createRadial("RPM", "", 8000, 0);
- RpmModel.getInstance().addListener(new RpmModel.RpmListener() {
- public void onRpmChange(RpmModel rpm) {
- rpmGauge.setValue(rpm.getValue());
- }
- });
- rpmGauge.setMaxMeasuredValueVisible(true);
- return rpmGauge;
- }
-
- public static Component createGauge(final Sensor sensor) {
- return createGauge(sensor, 1);
- }
-
- public static Component createGauge(final Sensor sensor, final double correction) {
- final Radial gauge = createRadial(sensor.getName(), sensor.getUnits(), sensor.getMaxValue(), sensor.getMinValue());
-
- gauge.setBackgroundColor(sensor.getColor());
-
- SensorCentral.getInstance().addListener(sensor, new SensorCentral.AdcListener() {
- public void onAdcUpdate(SensorCentral model, double value) {
- gauge.setValue(value * correction);
- }
- });
- gauge.setLcdDecimals(2);
- return gauge;
- }
-
- private static Radial createRadial(String title, String units, double maxValue, double minValue) {
-// final Section[] SECTIONS =
-// {
-// new Section(0, to, Color.red)
-// };
-
- Radial radial1 = new Radial();
-// radial1.setSections(SECTIONS);
- radial1.setTitle(title);
- radial1.setUnitString(units);
-
- //radial1.setTrackStop(to);
-
- radial1.setMinValue(minValue);
- radial1.setMaxValue(maxValue);
- radial1.setThresholdVisible(false);
- radial1.setPointerColor(ColorDef.RED);
-
- radial1.setValue(0);
- return radial1;
- }
-}
diff --git a/java_console/ui/src/com/irnems/ui/test/RpmModelTest.java b/java_console/ui/src/com/irnems/ui/test/RpmModelTest.java
index 6e9ca48cdf..c49f652f40 100644
--- a/java_console/ui/src/com/irnems/ui/test/RpmModelTest.java
+++ b/java_console/ui/src/com/irnems/ui/test/RpmModelTest.java
@@ -1,6 +1,6 @@
package com.irnems.ui.test;
-import com.irnems.ui.RpmModel;
+import com.rusefi.ui.RpmModel;
import org.junit.Assert;
import org.junit.Test;
diff --git a/java_console/ui/src/com/irnems/ui/test/UpDownSandbox.java b/java_console/ui/src/com/irnems/ui/test/UpDownSandbox.java
index 110fb3c472..1d86c8f688 100644
--- a/java_console/ui/src/com/irnems/ui/test/UpDownSandbox.java
+++ b/java_console/ui/src/com/irnems/ui/test/UpDownSandbox.java
@@ -2,7 +2,7 @@ package com.irnems.ui.test;
import com.rusefi.waves.WaveReport;
import com.irnems.core.test.WaveReportTest;
-import com.irnems.ui.FrameHelper;
+import com.rusefi.ui.FrameHelper;
import com.irnems.ui.widgets.UpDownImage;
import javax.swing.*;
diff --git a/java_console/ui/src/com/irnems/ui/test/WavePanelSandbox.java b/java_console/ui/src/com/irnems/ui/test/WavePanelSandbox.java
index f67ac9cbfb..8611da9ee3 100644
--- a/java_console/ui/src/com/irnems/ui/test/WavePanelSandbox.java
+++ b/java_console/ui/src/com/irnems/ui/test/WavePanelSandbox.java
@@ -1,7 +1,7 @@
package com.irnems.ui.test;
-import com.irnems.ui.FrameHelper;
-import com.irnems.ui.WavePanel;
+import com.rusefi.ui.FrameHelper;
+import com.rusefi.ui.WavePanel;
import javax.swing.*;
import java.lang.reflect.InvocationTargetException;
diff --git a/java_console/ui/src/com/irnems/ui/test/WavePanelTest.java b/java_console/ui/src/com/irnems/ui/test/WavePanelTest.java
new file mode 100644
index 0000000000..dd35af3c2b
--- /dev/null
+++ b/java_console/ui/src/com/irnems/ui/test/WavePanelTest.java
@@ -0,0 +1,41 @@
+package com.irnems.ui.test;
+
+import com.rusefi.ui.FrameHelper;
+import com.rusefi.ui.WavePanel;
+import org.junit.Test;
+
+import javax.swing.*;
+import java.lang.reflect.InvocationTargetException;
+import java.util.Set;
+import java.util.TreeSet;
+
+import static junit.framework.Assert.assertEquals;
+
+/**
+ * 6/25/14
+ * (c) Andrey Belomutskiy
+ */
+
+public class WavePanelTest {
+ @Test
+ public void testInsertIndex() {
+
+ Set names = new TreeSet();
+ names.add(WavePanel.CRANK1);
+
+ String name;
+
+ name = "inj2";
+ assertEquals(-1, WavePanel.getInsertIndex(name, names));
+ names.add(name);
+
+ name = "inj1";
+ assertEquals(1, WavePanel.getInsertIndex(name, names));
+ names.add(name);
+
+
+ assertEquals(1, WavePanel.getInsertIndex("spa1", names));
+
+ }
+}
+
diff --git a/java_console/ui/src/com/irnems/ui/widgets/AnyCommand.java b/java_console/ui/src/com/irnems/ui/widgets/AnyCommand.java
index c5239d6c77..6ec7dabbdc 100644
--- a/java_console/ui/src/com/irnems/ui/widgets/AnyCommand.java
+++ b/java_console/ui/src/com/irnems/ui/widgets/AnyCommand.java
@@ -3,6 +3,8 @@ package com.irnems.ui.widgets;
import com.rusefi.io.CommandQueue;
import javax.swing.*;
+import javax.swing.event.DocumentEvent;
+import javax.swing.event.DocumentListener;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
@@ -13,7 +15,7 @@ import java.awt.event.ActionListener;
*/
public class AnyCommand extends JPanel {
public AnyCommand() {
- setBorder(BorderFactory.createLineBorder(Color.PINK));
+// setBorder(BorderFactory.createLineBorder(Color.PINK));
setLayout(new FlowLayout(FlowLayout.LEFT));
add(new JLabel("Command: "));
final JTextField text = createCommandControl();
@@ -32,16 +34,60 @@ public class AnyCommand extends JPanel {
@Override
public void actionPerformed(ActionEvent e) {
String cmd = text.getText();
+ if (!isValidInput(text))
+ return;
int timeout = isSlowCommand(cmd) ? 5000 : 300;
- CommandQueue.getInstance().write(cmd, timeout);
+ CommandQueue.getInstance().write(cmd.toLowerCase(), timeout);
}
});
+ text.getDocument().addDocumentListener(new DocumentListener() {
+ @Override
+ public void insertUpdate(DocumentEvent e) {
+ changedUpdate(null);
+ }
+
+ @Override
+ public void removeUpdate(DocumentEvent e) {
+
+ }
+
+ @Override
+ public void changedUpdate(DocumentEvent e) {
+ boolean isOk = isValidInput(text);
+ text.setBorder(isOk ? null : BorderFactory.createLineBorder(Color.red));
+ }
+ });
+
+// text.setInputVerifier(new InputVerifier() {
+// @Override
+// public boolean verify(JComponent input) {
+// boolean isOk = isValidInput(text);
+// text.setBorder(isOk ? null : BorderFactory.createLineBorder(Color.red));
+// return isOk;
+// }
+// });
// todo: limit the length of text in the text field
return text;
}
+ private static boolean isValidInput(JTextField text) {
+ boolean isOk = true;
+ for (char c : text.getText().toCharArray()) {
+ if (c > 127) {
+ /**
+ * https://sourceforge.net/p/rusefi/tickets/63/
+ * only English characters are accepted - we need to reject two-byte unicode stuff
+ */
+ isOk = false;
+ break;
+ }
+ }
+ return isOk;
+ }
+
private static boolean isSlowCommand(String cmd) {
String lc = cmd.toLowerCase();
- return lc.startsWith("set_engine_type") || lc.startsWith("writeconfig") || lc.startsWith("showconfig");
+ return lc.startsWith("set_engine_type") || lc.startsWith("writeconfig") || lc.startsWith("showconfig")
+ || lc.startsWith("perftest");
}
}
diff --git a/java_console/ui/src/com/irnems/ui/widgets/URLLabel.java b/java_console/ui/src/com/irnems/ui/widgets/URLLabel.java
new file mode 100644
index 0000000000..f041e39102
--- /dev/null
+++ b/java_console/ui/src/com/irnems/ui/widgets/URLLabel.java
@@ -0,0 +1,90 @@
+package com.irnems.ui.widgets;
+
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+
+public class URLLabel extends JLabel {
+
+ private static final long serialVersionUID = 8273875024682878518L;
+ private String text;
+ private URI uri;
+
+ public URLLabel(String text, URI uri) {
+ setup(text, uri);
+ }
+
+ public URLLabel(String text, String uri) {
+ URI oURI;
+ try {
+ oURI = new URI(uri);
+ } catch (URISyntaxException e) {
+ // converts to runtime exception for ease of use
+ // if you cannot be sure at compile time that your
+ // uri is valid, construct your uri manually and
+ // use the other constructor.
+ throw new RuntimeException(e);
+ }
+ setup(text, oURI);
+ }
+
+ public void setup(String t, URI u) {
+ text = t;
+ uri = u;
+ setText(text);
+ setToolTipText(uri.toString());
+ addMouseListener(new MouseAdapter() {
+ public void mouseClicked(MouseEvent e) {
+ open(uri);
+ }
+
+ public void mouseEntered(MouseEvent e) {
+ setText(text, false);
+ }
+
+ public void mouseExited(MouseEvent e) {
+ setText(text, true);
+ }
+ });
+ }
+
+ @Override
+ public void setText(String text) {
+ setText(text, true);
+ }
+
+ public void setText(String text, boolean ul) {
+ String link = ul ? "" + text + "" : text;
+ super.setText("" +
+ link + "");
+ this.text = text;
+ }
+
+ public String getRawText() {
+ return text;
+ }
+
+ private static void open(URI uri) {
+ if (Desktop.isDesktopSupported()) {
+ Desktop desktop = Desktop.getDesktop();
+ try {
+ desktop.browse(uri);
+ } catch (IOException e) {
+ JOptionPane.showMessageDialog(null,
+ "Failed to launch the link, " +
+ "your computer is likely misconfigured.",
+ "Cannot Launch Link", JOptionPane.WARNING_MESSAGE
+ );
+ }
+ } else {
+ JOptionPane.showMessageDialog(null,
+ "Java is not able to launch links on your computer.",
+ "Cannot Launch Link", JOptionPane.WARNING_MESSAGE);
+ }
+ }
+}
\ No newline at end of file
diff --git a/java_console/ui/src/com/rusefi/AnalogChartPanel.java b/java_console/ui/src/com/rusefi/AnalogChartPanel.java
index 377a902f34..7662792447 100644
--- a/java_console/ui/src/com/rusefi/AnalogChartPanel.java
+++ b/java_console/ui/src/com/rusefi/AnalogChartPanel.java
@@ -1,10 +1,13 @@
package com.rusefi;
import com.irnems.FileLog;
-import com.irnems.core.MessagesCentral;
-import com.irnems.ui.RpmModel;
-import com.irnems.ui.UiUtils;
+import com.irnems.core.EngineState;
+import com.rusefi.ui.RpmModel;
+import com.rusefi.ui.UiUtils;
+import com.rusefi.ui.WavePanel;
+import com.irnems.ui.widgets.URLLabel;
import com.irnems.ui.widgets.UpDownImage;
+import com.rusefi.io.LinkManager;
import javax.swing.*;
import java.awt.*;
@@ -19,6 +22,7 @@ import java.util.List;
*/
public class AnalogChartPanel extends JPanel {
private static final String KEY = "analog_chart";
+ private static final String HELP_URL = "http://rusefi.com/wiki/index.php?title=Manual:DevConsole#Analog_Chart";
private final TreeMap values = new TreeMap();
private final AnalogChart analogChart = new AnalogChart();
@@ -33,45 +37,54 @@ public class AnalogChartPanel extends JPanel {
public AnalogChartPanel() {
super(new BorderLayout());
- MessagesCentral.getInstance().addListener(new MessagesCentral.MessageListener() {
- @Override
- public void onMessage(Class clazz, String message) {
- if (paused || !message.startsWith(KEY))
- return;
- unpackValues(values, message);
+ LinkManager.engineState.registerStringValueAction(KEY, new EngineState.ValueCallback() {
+ @Override
+ public void onUpdate(String message) {
+
+ unpackValues(values, message);
// MessagesCentral.getInstance().postMessage(AnalogChartPanel.class, "chart arrived, len=" + message.length());
- processValues();
- UpDownImage.trueRepaint(analogChart);
+ processValues();
+ UpDownImage.trueRepaint(analogChart);
- }
- });
+ }
+ }
+ );
JPanel upperPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 5, 0));
JButton imageButton = new JButton("save image");
upperPanel.add(imageButton);
- imageButton.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- int rpm = RpmModel.getInstance().getValue();
- String fileName = FileLog.getDate() + "rpm_" + rpm + "_analog" + ".png";
- UiUtils.saveImage(fileName, analogChart);
- }
- });
+ imageButton.addActionListener(new
+
+ ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ int rpm = RpmModel.getInstance().getValue();
+ String fileName = FileLog.getDate() + "rpm_" + rpm + "_analog" + ".png";
+ UiUtils.saveImage(fileName, analogChart);
+ }
+ }
+ );
final JButton pauseButton = new JButton("Pause");
upperPanel.add(pauseButton);
- pauseButton.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- paused = !paused;
- pauseButton.setText(paused ? "Resume" : "Pause");
- }
- });
+
+ upperPanel.add(new URLLabel(WavePanel.HELP_TEXT, HELP_URL));
+ pauseButton.addActionListener(new
+
+ ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ paused = !paused;
+ pauseButton.setText(paused ? "Resume" : "Pause");
+ }
+ }
+ );
add(upperPanel, BorderLayout.NORTH);
+
add(analogChart, BorderLayout.CENTER);
}
@@ -121,7 +134,7 @@ public class AnalogChartPanel extends JPanel {
values.clear();
String[] tokens = chart.split("\\|");
- for (int i = 1; i < tokens.length - 1; ) {
+ for (int i = 0; i < tokens.length - 1; ) {
String key = tokens[i++];
String value = tokens[i++];
diff --git a/java_console/ui/src/com/rusefi/PortLookupFrame.java b/java_console/ui/src/com/rusefi/PortLookupFrame.java
index 5f708a0f0f..22eef0f167 100644
--- a/java_console/ui/src/com/rusefi/PortLookupFrame.java
+++ b/java_console/ui/src/com/rusefi/PortLookupFrame.java
@@ -55,9 +55,9 @@ public class PortLookupFrame {
comboPorts.addItem(port);
panel.add(comboPorts);
- final JButton buttonUsePort = new JButton("Use this port");
- panel.add(buttonUsePort);
- buttonUsePort.addActionListener(new ActionListener() {
+ final JButton connect = new JButton("Connect");
+ panel.add(connect);
+ connect.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
frame.dispose();
diff --git a/java_console/ui/src/com/irnems/ui/AdcPanel.java b/java_console/ui/src/com/rusefi/ui/AdcPanel.java
similarity index 99%
rename from java_console/ui/src/com/irnems/ui/AdcPanel.java
rename to java_console/ui/src/com/rusefi/ui/AdcPanel.java
index dae2dc002d..a39af2fe49 100644
--- a/java_console/ui/src/com/irnems/ui/AdcPanel.java
+++ b/java_console/ui/src/com/rusefi/ui/AdcPanel.java
@@ -1,4 +1,4 @@
-package com.irnems.ui;
+package com.rusefi.ui;
import com.irnems.core.SensorCentral;
import com.irnems.core.Pair;
diff --git a/java_console/ui/src/com/irnems/ui/BooleanInputsModel.java b/java_console/ui/src/com/rusefi/ui/BooleanInputsModel.java
similarity index 98%
rename from java_console/ui/src/com/irnems/ui/BooleanInputsModel.java
rename to java_console/ui/src/com/rusefi/ui/BooleanInputsModel.java
index 409aee1332..fa21637e49 100644
--- a/java_console/ui/src/com/irnems/ui/BooleanInputsModel.java
+++ b/java_console/ui/src/com/rusefi/ui/BooleanInputsModel.java
@@ -1,4 +1,4 @@
-package com.irnems.ui;
+package com.rusefi.ui;
import java.util.HashMap;
import java.util.Map;
diff --git a/java_console/ui/src/com/irnems/ui/ChartHelper.java b/java_console/ui/src/com/rusefi/ui/ChartHelper.java
similarity index 99%
rename from java_console/ui/src/com/irnems/ui/ChartHelper.java
rename to java_console/ui/src/com/rusefi/ui/ChartHelper.java
index d986eea674..ce731ba250 100644
--- a/java_console/ui/src/com/irnems/ui/ChartHelper.java
+++ b/java_console/ui/src/com/rusefi/ui/ChartHelper.java
@@ -1,4 +1,4 @@
-package com.irnems.ui;
+package com.rusefi.ui;
import com.irnems.FileLog;
import com.irnems.models.Range;
diff --git a/java_console/ui/src/com/irnems/ui/ChartStatusPanel.java b/java_console/ui/src/com/rusefi/ui/ChartStatusPanel.java
similarity index 99%
rename from java_console/ui/src/com/irnems/ui/ChartStatusPanel.java
rename to java_console/ui/src/com/rusefi/ui/ChartStatusPanel.java
index b732094f36..967fb1926e 100644
--- a/java_console/ui/src/com/irnems/ui/ChartStatusPanel.java
+++ b/java_console/ui/src/com/rusefi/ui/ChartStatusPanel.java
@@ -1,4 +1,4 @@
-package com.irnems.ui;
+package com.rusefi.ui;
import com.irnems.waves.TimeAxisTranslator;
import com.rusefi.waves.WaveReport;
diff --git a/java_console/ui/src/com/irnems/ui/DefaultExceptionHandler.java b/java_console/ui/src/com/rusefi/ui/DefaultExceptionHandler.java
similarity index 97%
rename from java_console/ui/src/com/irnems/ui/DefaultExceptionHandler.java
rename to java_console/ui/src/com/rusefi/ui/DefaultExceptionHandler.java
index 0f155fe750..76f2afff4c 100644
--- a/java_console/ui/src/com/irnems/ui/DefaultExceptionHandler.java
+++ b/java_console/ui/src/com/rusefi/ui/DefaultExceptionHandler.java
@@ -1,4 +1,4 @@
-package com.irnems.ui;
+package com.rusefi.ui;
import javax.swing.*;
import java.awt.*;
diff --git a/java_console/ui/src/com/irnems/ui/FrameHelper.java b/java_console/ui/src/com/rusefi/ui/FrameHelper.java
similarity index 97%
rename from java_console/ui/src/com/irnems/ui/FrameHelper.java
rename to java_console/ui/src/com/rusefi/ui/FrameHelper.java
index be704c3c46..4518bf310c 100644
--- a/java_console/ui/src/com/irnems/ui/FrameHelper.java
+++ b/java_console/ui/src/com/rusefi/ui/FrameHelper.java
@@ -1,4 +1,4 @@
-package com.irnems.ui;
+package com.rusefi.ui;
import com.irnems.FileLog;
diff --git a/java_console/ui/src/com/rusefi/ui/GaugesPanel.java b/java_console/ui/src/com/rusefi/ui/GaugesPanel.java
new file mode 100644
index 0000000000..99d3b7395a
--- /dev/null
+++ b/java_console/ui/src/com/rusefi/ui/GaugesPanel.java
@@ -0,0 +1,92 @@
+package com.rusefi.ui;
+
+import com.irnems.core.Sensor;
+import com.irnems.ui.widgets.MafCommand;
+import com.irnems.ui.widgets.RpmCommand;
+import com.rusefi.ui.widgets.SensorGauge;
+import eu.hansolo.steelseries.gauges.Radial;
+
+import javax.swing.*;
+import java.awt.*;
+
+/**
+ * Date: 2/5/13
+ * (c) Andrey Belomutskiy
+ */
+public class GaugesPanel extends JComponent {
+ private static final int ADC_MAX_VALUE = 255; // mazda ECU
+// private static final int ADC_MAX_VALUE = 4095; // discovery board
+
+ public GaugesPanel() {
+ setLayout(new GridLayout(1, 3));
+
+
+// Radial radial2 = createRadial("title");
+
+ JPanel box2 = new JPanel(new GridLayout(3, 5));
+
+
+ box2.add(createControls());
+ box2.add(SensorGauge.createGauge(Sensor.T_CHARGE));
+ box2.add(SensorGauge.createGauge(Sensor.DWELL1));
+ box2.add(SensorGauge.createGauge(Sensor.DWELL0));
+ box2.add(SensorGauge.createGauge(Sensor.DUTY0));
+ box2.add(SensorGauge.createGauge(Sensor.ADVANCE0));
+ box2.add(SensorGauge.createGauge(Sensor.MAF));
+ box2.add(SensorGauge.createGauge(Sensor.FUEL));
+ box2.add(SensorGauge.createGauge(Sensor.BARO));
+ //box2.add(createGauge(Sensor.FUEL_BASE));
+ box2.add(SensorGauge.createGauge(Sensor.FUEL_CLT));
+ box2.add(SensorGauge.createGauge(Sensor.FUEL_IAT));
+ box2.add(SensorGauge.createGauge(Sensor.FUEL_LAG));
+
+// box2.add(createGauge(Sensor.TABLE_SPARK));
+
+
+// box2.add(createGauge(Sensor.DUTY1));
+// box2.add(createGauge(Sensor.ADVANCE1));
+ box2.add(SensorGauge.createGauge(Sensor.IAT));
+ //box2.add(createGauge(Sensor.INTAKE_AIR_WIDTH));
+ box2.add(SensorGauge.createGauge(Sensor.CLT));
+// box2.add(createGauge(Sensor.COOLANT_WIDTH));
+
+ box2.add(SensorGauge.createGauge(Sensor.MAP));
+ box2.add(SensorGauge.createGauge(Sensor.MAP_RAW));
+ box2.add(SensorGauge.createGauge(Sensor.TPS));
+// box2.add(createGauge(Sensor.VREF, PotCommand.VOLTAGE_CORRECTION));
+// box2.add(createGauge(Sensor.VREF_WIDTH));
+
+// box2.add(createGauge(Sensor.ADC_FAST));
+// box2.add(createGauge(Sensor.ADC_FAST_AVG));
+
+
+ box2.add(SensorGauge.createGauge(Sensor.AFR));
+ box2.add(SensorGauge.createGauge(Sensor.DEFAULT_FUEL));
+
+ box2.add(SensorGauge.createGauge(Sensor.TIMING));
+
+ box2.add(createRpmGauge());
+
+ //add(rpmGauge);
+ add(box2);
+// add(new JLabel("fd"), BorderLayout.EAST);
+ }
+
+ private Component createControls() {
+ JPanel controls = new JPanel(new GridLayout(2, 1));
+ controls.add(new RpmCommand());
+ controls.add(new MafCommand());
+ return controls;
+ }
+
+ private Radial createRpmGauge() {
+ final Radial rpmGauge = SensorGauge.createRadial("RPM", "", 8000, 0);
+ RpmModel.getInstance().addListener(new RpmModel.RpmListener() {
+ public void onRpmChange(RpmModel rpm) {
+ rpmGauge.setValue(rpm.getValue());
+ }
+ });
+ rpmGauge.setMaxMeasuredValueVisible(true);
+ return rpmGauge;
+ }
+}
diff --git a/java_console/ui/src/com/irnems/ui/Live3DReport.java b/java_console/ui/src/com/rusefi/ui/Live3DReport.java
similarity index 98%
rename from java_console/ui/src/com/irnems/ui/Live3DReport.java
rename to java_console/ui/src/com/rusefi/ui/Live3DReport.java
index 25dd6f2837..270d446006 100644
--- a/java_console/ui/src/com/irnems/ui/Live3DReport.java
+++ b/java_console/ui/src/com/rusefi/ui/Live3DReport.java
@@ -1,4 +1,4 @@
-package com.irnems.ui;
+package com.rusefi.ui;
import com.irnems.EcuStimulator;
import com.irnems.core.MessagesCentral;
diff --git a/java_console/ui/src/com/irnems/ui/MsgPanel.java b/java_console/ui/src/com/rusefi/ui/MsgPanel.java
similarity index 99%
rename from java_console/ui/src/com/irnems/ui/MsgPanel.java
rename to java_console/ui/src/com/rusefi/ui/MsgPanel.java
index 8eff095d00..e943f18743 100644
--- a/java_console/ui/src/com/irnems/ui/MsgPanel.java
+++ b/java_console/ui/src/com/rusefi/ui/MsgPanel.java
@@ -1,4 +1,4 @@
-package com.irnems.ui;
+package com.rusefi.ui;
import com.irnems.core.MessagesCentral;
import com.irnems.ui.widgets.AnyCommand;
diff --git a/java_console/ui/src/com/irnems/ui/RpmControl.java b/java_console/ui/src/com/rusefi/ui/RpmControl.java
similarity index 99%
rename from java_console/ui/src/com/irnems/ui/RpmControl.java
rename to java_console/ui/src/com/rusefi/ui/RpmControl.java
index d1075c9d45..b5385841a3 100644
--- a/java_console/ui/src/com/irnems/ui/RpmControl.java
+++ b/java_console/ui/src/com/rusefi/ui/RpmControl.java
@@ -1,4 +1,4 @@
-package com.irnems.ui;
+package com.rusefi.ui;
import com.rusefi.io.LinkManager;
import com.irnems.core.EngineTimeListener;
diff --git a/java_console/ui/src/com/irnems/ui/RpmModel.java b/java_console/ui/src/com/rusefi/ui/RpmModel.java
similarity index 98%
rename from java_console/ui/src/com/irnems/ui/RpmModel.java
rename to java_console/ui/src/com/rusefi/ui/RpmModel.java
index f125850897..1f0c54f774 100644
--- a/java_console/ui/src/com/irnems/ui/RpmModel.java
+++ b/java_console/ui/src/com/rusefi/ui/RpmModel.java
@@ -1,4 +1,4 @@
-package com.irnems.ui;
+package com.rusefi.ui;
import com.irnems.core.Sensor;
import com.irnems.core.SensorCentral;
diff --git a/java_console/ui/src/com/irnems/ui/RpmPanel.java b/java_console/ui/src/com/rusefi/ui/RpmPanel.java
similarity index 84%
rename from java_console/ui/src/com/irnems/ui/RpmPanel.java
rename to java_console/ui/src/com/rusefi/ui/RpmPanel.java
index 7e750de511..db59b3c7a0 100644
--- a/java_console/ui/src/com/irnems/ui/RpmPanel.java
+++ b/java_console/ui/src/com/rusefi/ui/RpmPanel.java
@@ -1,10 +1,12 @@
-package com.irnems.ui;
+package com.rusefi.ui;
import com.irnems.EcuStimulator;
-import com.rusefi.io.LinkManager;
+import com.irnems.Launcher;
import com.irnems.core.EngineTimeListener;
import com.irnems.core.Sensor;
import com.irnems.ui.widgets.*;
+import com.rusefi.io.LinkManager;
+import com.rusefi.ui.widgets.SensorGauge;
import net.miginfocom.swing.MigLayout;
import javax.swing.*;
@@ -45,17 +47,17 @@ public class RpmPanel {
JPanel gauges = new JPanel(new GridLayout(2, 3));
gauges.setBorder(BorderFactory.createLineBorder(Color.black));
-// gauges.add(GaugePanel.createCoolantGauge());
- gauges.add(GaugePanel.createGauge(Sensor.DWELL0));
- gauges.add(GaugePanel.createGauge(Sensor.DUTY0));
- gauges.add(GaugePanel.createGauge(Sensor.FUEL));
- //gauges.add(GaugePanel.createGauge(Sensor.ADVANCE0));
+// gauges.add(GaugesPanel.createCoolantGauge());
+ gauges.add(SensorGauge.createGauge(Sensor.DWELL0));
+ gauges.add(SensorGauge.createGauge(Sensor.DUTY0));
+ gauges.add(SensorGauge.createGauge(Sensor.FUEL));
+ //gauges.add(GaugesPanel.createGauge(Sensor.ADVANCE0));
- gauges.add(GaugePanel.createGauge(Sensor.VREF, PotCommand.VOLTAGE_CORRECTION));
- gauges.add(GaugePanel.createGauge(Sensor.MAF));
- gauges.add(GaugePanel.createGauge(Sensor.DWELL1));
-// gauges.add(GaugePanel.createGauge(Sensor.ADVANCE1));
-// gauges.add(GaugePanel.createGauge(Sensor.MAF));
+ gauges.add(SensorGauge.createGauge(Sensor.VREF, PotCommand.VOLTAGE_CORRECTION));
+ gauges.add(SensorGauge.createGauge(Sensor.MAF));
+ gauges.add(SensorGauge.createGauge(Sensor.DWELL1));
+// gauges.add(GaugesPanel.createGauge(Sensor.ADVANCE1));
+// gauges.add(GaugesPanel.createGauge(Sensor.MAF));
final Timer reconnectTimer = new Timer(10000, new ActionListener() {
@@ -97,7 +99,8 @@ public class RpmPanel {
JPanel controls = new JPanel(new MigLayout());
controls.setBorder(BorderFactory.createLineBorder(Color.red));
JButton button = createButton();
-// controls.add(button, "grow, wrap");
+ if (Launcher.SHOW_STIMULATOR)
+ controls.add(button, "grow, wrap");
controls.add(new RpmCommand(), "grow, wrap");
// controls.add(new PotCommand(0).panel, "grow, wrap");
@@ -124,7 +127,7 @@ public class RpmPanel {
}
private JButton createButton() {
- final JButton button = new JButton("run ECU stimulation");
+ final JButton button = new JButton("stimulate stock ECU");
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
diff --git a/java_console/ui/src/com/irnems/ui/UiUtils.java b/java_console/ui/src/com/rusefi/ui/UiUtils.java
similarity index 98%
rename from java_console/ui/src/com/irnems/ui/UiUtils.java
rename to java_console/ui/src/com/rusefi/ui/UiUtils.java
index 6c73d5de46..3a35ddf352 100644
--- a/java_console/ui/src/com/irnems/ui/UiUtils.java
+++ b/java_console/ui/src/com/rusefi/ui/UiUtils.java
@@ -1,4 +1,4 @@
-package com.irnems.ui;
+package com.rusefi.ui;
import javax.imageio.ImageIO;
import javax.swing.*;
diff --git a/java_console/ui/src/com/irnems/ui/WavePanel.java b/java_console/ui/src/com/rusefi/ui/WavePanel.java
similarity index 74%
rename from java_console/ui/src/com/irnems/ui/WavePanel.java
rename to java_console/ui/src/com/rusefi/ui/WavePanel.java
index d27ce3fa44..24dcd49e9d 100644
--- a/java_console/ui/src/com/irnems/ui/WavePanel.java
+++ b/java_console/ui/src/com/rusefi/ui/WavePanel.java
@@ -1,4 +1,4 @@
-package com.irnems.ui;
+package com.rusefi.ui;
import com.irnems.ChartRepository;
import com.irnems.FileLog;
@@ -6,6 +6,7 @@ import com.irnems.core.EngineState;
import com.irnems.core.Sensor;
import com.irnems.core.SensorCentral;
import com.irnems.ui.widgets.AnyCommand;
+import com.irnems.ui.widgets.URLLabel;
import com.irnems.ui.widgets.UpDownImage;
import com.rusefi.io.LinkManager;
import com.rusefi.ui.ChartScrollControl;
@@ -18,9 +19,8 @@ import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
-import java.util.LinkedHashMap;
+import java.util.*;
import java.util.List;
-import java.util.Map;
/**
* Digital Sniffer control consists of a set of {@link UpDownImage}
@@ -33,12 +33,16 @@ import java.util.Map;
*/
public class WavePanel extends JPanel {
private static final int EFI_DEFAULT_CHART_SIZE = 180;
+ public static final String CRANK1 = "c1";
+ public static final Comparator INSTANCE = new ImageOrderComparator();
+ private static final String HELP_URL = "http://rusefi.com/wiki/index.php?title=Manual:DevConsole#Digital_Chart";
+ public static final String HELP_TEXT = "Click here for online help";
- private final Map images = new LinkedHashMap();
+ private final Map images = new TreeMap(INSTANCE);
private final JPanel imagePanel = new JPanel();
private final ZoomControl zoomControl = new ZoomControl();
private final ChartStatusPanel statusPanel = new ChartStatusPanel(zoomControl);
- private final UpDownImage crank = register("crank");
+ private final UpDownImage crank = createImage(CRANK1);
private ChartScrollControl scrollControl;
private boolean isPaused;
@@ -96,6 +100,8 @@ public class WavePanel extends JPanel {
});
buttonPanel.add(scrollControl.getContent());
+ buttonPanel.add(new URLLabel(HELP_TEXT, HELP_URL));
+
add(buttonPanel, BorderLayout.NORTH);
add(imagePanel, BorderLayout.CENTER);
add(statusPanel.infoPanel, BorderLayout.SOUTH);
@@ -108,20 +114,20 @@ public class WavePanel extends JPanel {
};
crank.setZoomProvider(zoomControl);
- imagePanel.add(crank);
- createSecondaryImage("crank2");
- createSecondaryImage("input1 A8");
- createSecondaryImage("input2 E5");
-
- createSecondaryImage(WaveChart.SPARK_1);
- createSecondaryImage(WaveChart.SPARK_2);
- createSecondaryImage(WaveChart.SPARK_3);
- createSecondaryImage(WaveChart.SPARK_4);
-
- createSecondaryImage(WaveChart.INJECTOR_1);
- createSecondaryImage(WaveChart.INJECTOR_2);
- createSecondaryImage(WaveChart.INJECTOR_3);
- createSecondaryImage(WaveChart.INJECTOR_4);
+ resetImagePanel();
+// createSecondaryImage("c2");
+// createSecondaryImage("input1 A8");
+// createSecondaryImage("input2 E5");
+//
+// createSecondaryImage(WaveChart.SPARK_1);
+// createSecondaryImage(WaveChart.SPARK_2);
+// createSecondaryImage(WaveChart.SPARK_3);
+// createSecondaryImage(WaveChart.SPARK_4);
+//
+// createSecondaryImage(WaveChart.INJECTOR_1);
+// createSecondaryImage(WaveChart.INJECTOR_2);
+// createSecondaryImage(WaveChart.INJECTOR_3);
+// createSecondaryImage(WaveChart.INJECTOR_4);
LinkManager.engineState.registerStringValueAction(WaveReport.WAVE_CHART, new EngineState.ValueCallback() {
@Override
@@ -135,6 +141,12 @@ public class WavePanel extends JPanel {
// displayChart("wave_chart,crank2!down!192811978!crank2!up!192813389!crank2!down!192813749!crank2!up!192815156!crank2!down!192815512!crank!up!192820764!crank2!up!192825818!crank2!down!192826182!crank2!up!192827610!crank2!down!192827975!crank2!up!192829399!crank2!down!192829757!crank2!up!192831154!crank2!down!192831507!r!187!192834224!crank!down!192834224!crank2!up!192836757!crank2!down!192841994!crank2!up!192843561!crank2!down!192843925!crank2!up!192845334!crank2!down!192845693!crank2!up!192847086!crank2!down!192847439!crank!up!192853135!crank2!up!192857701!crank2!down!192858065!crank2!up!192859491!crank2!down!192859858!crank2!up!192861269!crank2!down!192861626!crank2!up!192863025!crank2!down!192863382!crank2!up!192868647!crank!down!192871268!crank2!down!192872804!crank2!up!192872804!crank!down!192872804!crank!up!192872804!crank2!down!192873898!crank2!up!192875508!crank2!down!192875887!crank2!up!192877357!crank2!down!192877732!crank2!up!192879192!crank2!down!192879565!crank!up!192886293!r!0!194982088!crank!down!194982088!crank2!up!194984699!crank2!down!194990112!crank2!up!194991715!crank2!down!194992085!crank2!up!194993530!crank2!down!194993884!crank2!up!194995292!crank2!down!194995645!crank!up!195001475!crank2!up!195006153!crank2!down!195006515!crank2!up!195007968!crank2!down!195008325!crank2!up!195009773!crank2!down!195010134!crank2!up!195011549!crank2!down!195011901!crank2!up!195017256!crank!down!195019915!crank2!down!195022597!crank2!up!195024189!crank2!down!195024554!crank2!up!195025980!crank2!down!195026329!crank2!up!195027744!crank2!down!195028103!crank!up!195033418!crank2!up!195038542!crank2!down!195038911!crank2!up!195040351!crank2!down!195040722!crank2!up!195042167!crank2!down!195042529!crank2!up!195043934!crank2!down!195044294!r!187!195047060!crank!down!195047060!crank2!up!195049619!crank2!down!195054954!crank2!up!195056549!crank2!down!195056920!crank2!up!195058345!crank2!down!195058703!crank2!up!195060114!crank2!down!195060464!crank!up!195066245!crank2!up!195070882!crank2!down!195071250!crank2!up!195072689!crank2!down!195073054!crank2!up!195074479!,");
}
+ private void resetImagePanel() {
+ imagePanel.removeAll();
+ imagePanel.add(crank);
+ images.put(CRANK1, crank);
+ }
+
public static WavePanel getInstance() {
return instance;
}
@@ -150,6 +162,8 @@ public class WavePanel extends JPanel {
String imageName = e.getKey();
String report = e.getValue().toString();
+ createSecondaryImage(imageName);
+
UpDownImage image = images.get(imageName);
if (image == null)
continue;
@@ -165,12 +179,34 @@ public class WavePanel extends JPanel {
}
private void createSecondaryImage(String name) {
+ if (images.containsKey(name) || RevolutionLog.TOP_DEAD_CENTER_MESSAGE.equalsIgnoreCase(name))
+ return;
+
+ int index = getInsertIndex(name, images.keySet());
+
UpDownImage image = register(name).setTranslator(crank.createTranslator());
image.setZoomProvider(zoomControl);
- imagePanel.add(image);
+// try {
+ imagePanel.add(image, index);
+// } catch (Throwable e) {
+// System.out.println(e);
+// }
imagePanel.setLayout(new GridLayout(images.size(), 1));
}
+ public static int getInsertIndex(String name, Set strings) {
+ String[] mapKeys = new String[strings.size()];
+ int pos = 0;
+ for (String key : strings)
+ mapKeys[pos++] = key;
+
+// int index = -Arrays.binarySearch(mapKeys, name) - 1;
+ int index = -Arrays.binarySearch(mapKeys, 0, mapKeys.length, name, INSTANCE) - 1;
+ if (index >= strings.size())
+ index = -1;
+ return index;
+ }
+
private void saveImage() {
int rpm = RpmModel.getInstance().getValue();
double maf = SensorCentral.getInstance().getValue(Sensor.MAF);
@@ -179,9 +215,14 @@ public class WavePanel extends JPanel {
}
private UpDownImage register(String name) {
+ UpDownImage image = createImage(name);
+ images.put(name, image);
+ return image;
+ }
+
+ private UpDownImage createImage(String name) {
UpDownImage image = new UpDownImage(name);
image.addMouseMotionListener(statusPanel.motionAdapter);
- images.put(name, image);
return image;
}
@@ -189,4 +230,20 @@ public class WavePanel extends JPanel {
displayChart(ChartRepository.getInstance().getChart(0));
scrollControl.reset();
}
+
+ /**
+ * The job of this comparator is to place Spark charts before Injection charts
+ */
+ private static class ImageOrderComparator implements Comparator {
+ @Override
+ public int compare(String o1, String o2) {
+ return fixSpark(o1).compareTo(fixSpark(o2));
+ }
+
+ String fixSpark(String s) {
+ if (s.toLowerCase().startsWith("spa"))
+ return "d" + s;
+ return s;
+ }
+ }
}
diff --git a/java_console/ui/src/com/irnems/ui/ZoomControl.java b/java_console/ui/src/com/rusefi/ui/ZoomControl.java
similarity index 98%
rename from java_console/ui/src/com/irnems/ui/ZoomControl.java
rename to java_console/ui/src/com/rusefi/ui/ZoomControl.java
index 5203a3f79a..15d71bc772 100644
--- a/java_console/ui/src/com/irnems/ui/ZoomControl.java
+++ b/java_console/ui/src/com/rusefi/ui/ZoomControl.java
@@ -1,4 +1,4 @@
-package com.irnems.ui;
+package com.rusefi.ui;
import com.irnems.waves.ZoomProvider;
diff --git a/java_console/ui/src/com/rusefi/ui/widgets/SensorGauge.java b/java_console/ui/src/com/rusefi/ui/widgets/SensorGauge.java
new file mode 100644
index 0000000000..8d92155bb7
--- /dev/null
+++ b/java_console/ui/src/com/rusefi/ui/widgets/SensorGauge.java
@@ -0,0 +1,134 @@
+package com.rusefi.ui.widgets;
+
+import com.irnems.core.Sensor;
+import com.irnems.core.SensorCentral;
+import com.rusefi.io.CommandQueue;
+import eu.hansolo.steelseries.gauges.Radial;
+import eu.hansolo.steelseries.tools.ColorDef;
+
+import javax.swing.*;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+import java.awt.*;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.text.DecimalFormat;
+import java.text.Format;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Hashtable;
+
+/**
+ * Date: 7/9/14
+ * (c) Andrey Belomutskiy 2012-2014
+ */
+
+public class SensorGauge {
+ private static final Collection MOCKABLE = Arrays.asList(Sensor.CLT, Sensor.AFR, Sensor.IAT, Sensor.MAF,
+ Sensor.TPS);
+ /**
+ * We need to trick the JSlider into displaying float values
+ */
+ private static final int _5_VOLTS_WITH_DECIMAL = 50;
+
+ public static Component createGauge(final Sensor sensor) {
+ return createGauge(sensor, 1);
+ }
+
+ public static Component createGauge(final Sensor sensor, final double correction) {
+ final Radial gauge = createRadial(sensor.getName(), sensor.getUnits(), sensor.getMaxValue(), sensor.getMinValue());
+
+ gauge.setBackgroundColor(sensor.getColor());
+
+ SensorCentral.getInstance().addListener(sensor, new SensorCentral.AdcListener() {
+ public void onAdcUpdate(SensorCentral model, double value) {
+ gauge.setValue(value * correction);
+ }
+ });
+ gauge.setLcdDecimals(2);
+
+ gauge.addMouseListener(new MouseAdapter() {
+ @Override
+ public void mouseClicked(MouseEvent e) {
+ if (e.getClickCount() == 2) {
+ int size = gauge.getSize().width;
+ JFrame n = new JFrame(sensor.getName());
+ boolean isMockable = MOCKABLE.contains(sensor);
+ int h = isMockable ? (int) (size * 1.5) : size;
+
+ JPanel content = new JPanel(new BorderLayout());
+
+ content.add(createGauge(sensor, correction), BorderLayout.CENTER);
+
+ if (isMockable)
+ content.add(createMockVoltageSlider(sensor), BorderLayout.SOUTH);
+
+ n.setSize(size, h);
+ n.setAlwaysOnTop(true);
+ n.add(content);
+ n.setVisible(true);
+ n.setLocation(e.getXOnScreen(), e.getYOnScreen());
+ }
+ }
+ });
+
+ return gauge;
+ }
+
+ private final static Hashtable SLIDER_LABELS = new Hashtable();
+
+ static {
+ Format f = new DecimalFormat("0.0");
+ for (int i = 0; i <= 50; i += 5) {
+ JLabel label = new JLabel(f.format(i * 0.1));
+ label.setFont(label.getFont().deriveFont(Font.PLAIN));
+ SLIDER_LABELS.put(i, label);
+ }
+ }
+
+
+ private static Component createMockVoltageSlider(final Sensor sensor) {
+ /**
+ */
+ final JSlider slider = new JSlider(0, _5_VOLTS_WITH_DECIMAL);
+ slider.setLabelTable(SLIDER_LABELS);
+ slider.setPaintLabels(true);
+ slider.setPaintTicks(true);
+ slider.setMajorTickSpacing(10);
+ slider.setMinorTickSpacing(5);
+
+ slider.addChangeListener(new ChangeListener() {
+ @Override
+ public void stateChanged(ChangeEvent e) {
+ double value = slider.getValue() / 10.0;
+ CommandQueue.getInstance().write("set_mock_" + sensor.name().toLowerCase() + "_voltage " + value);
+ }
+ });
+
+ return slider;
+ }
+
+ public static Radial createRadial(String title, String units, double maxValue, double minValue) {
+// final Section[] SECTIONS =
+// {
+// new Section(0, to, Color.red)
+// };
+
+ Radial radial1 = new Radial();
+// radial1.setSections(SECTIONS);
+ radial1.setTitle(title);
+ radial1.setUnitString(units);
+
+ //radial1.setTrackStop(to);
+
+ radial1.setMinValue(minValue);
+ radial1.setMaxValue(maxValue);
+ radial1.setThresholdVisible(false);
+ radial1.setPointerColor(ColorDef.RED);
+
+ radial1.setValue(0);
+ return radial1;
+ }
+}
+
+
diff --git a/unit_tests/.cproject b/unit_tests/.cproject
index 3732922bb8..e43481f0d2 100644
--- a/unit_tests/.cproject
+++ b/unit_tests/.cproject
@@ -38,6 +38,8 @@
+
+
@@ -57,6 +59,8 @@
+
+
@@ -71,7 +75,7 @@
-
+
@@ -119,7 +123,7 @@
-
+
diff --git a/unit_tests/Makefile b/unit_tests/Makefile
index 17041869be..77bd93a56f 100644
--- a/unit_tests/Makefile
+++ b/unit_tests/Makefile
@@ -71,8 +71,11 @@ PROJECT = rusefi_test
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/system/system.mk
include $(PROJECT_DIR)/controllers/sensors/sensors.mk
+include $(PROJECT_DIR)/controllers/trigger/trigger.mk
include test.mk
# Define linker script file here
@@ -83,6 +86,7 @@ include test.mk
# setting.
CSRC = $(UTILSRC) \
$(CONTROLLERS_ALGO_SRC) \
+ $(CONTROLLERS_CORE_SRC) \
$(CONTROLLERS_MATH_SRC) \
$(CONTROLLERS_SENSORS_SRC) \
$(ENGINES_SRC) \
@@ -92,15 +96,16 @@ CSRC = $(UTILSRC) \
# setting.
CPPSRC = $(UTILSRC_CPP) \
$(CONTROLLERS_ALGO_SRC_CPP) \
- $(PROJECT_DIR)/controllers/trigger/trigger_mazda.cpp \
- $(PROJECT_DIR)/controllers/trigger/trigger_chrysler.cpp \
- $(PROJECT_DIR)/controllers/trigger/trigger_gm.cpp \
- $(PROJECT_DIR)/controllers/trigger/trigger_decoder.cpp \
- $(PROJECT_DIR)/controllers/trigger/trigger_structure.cpp \
+ $(TRIGGER_DECODERS_SRC_CPP) \
$(ENGINES_SRC_CPP) \
+ $(CONTROLLERS_CORE_SRC_CPP) \
$(CONTROLLERS_MATH_SRC_CPP) \
$(CONTROLLERS_SENSORS_SRC_CPP) \
$(TEST_SRC_CPP) \
+ $(PROJECT_DIR)/controllers/trigger/trigger_central.cpp \
+ $(PROJECT_DIR)/controllers/trigger/rpm_calculator.cpp \
+ $(PROJECT_DIR)/controllers/trigger/main_trigger_callback.cpp \
+ $(PROJECT_DIR)/controllers/system/event_queue.cpp \
main.cpp
# C sources to be compiled in ARM mode regardless of the global setting.
@@ -131,7 +136,9 @@ INCDIR = . \
$(PROJECT_DIR)/config/engines \
$(PROJECT_DIR)/controllers/sensors \
$(PROJECT_DIR)/controllers/algo \
+ $(PROJECT_DIR)/controllers/core \
$(PROJECT_DIR)/controllers/math \
+ $(PROJECT_DIR)/controllers/system \
$(PROJECT_DIR)/controllers/trigger \
$(PROJECT_DIR)/ext_algo \
test_data_structures \
diff --git a/unit_tests/boards.h b/unit_tests/boards.h
index 8a162b459f..b49de7bdd3 100644
--- a/unit_tests/boards.h
+++ b/unit_tests/boards.h
@@ -8,14 +8,7 @@
#ifndef BOARDS_H_
#define BOARDS_H_
-#define ADC_LOGIC_TPS 0
-#define ADC_LOGIC_AFR 0
-#define ADC_LOGIC_MAF 0
-#define ADC_LOGIC_MAP 0
#define ADC_CHANNEL_VREF 0
-#define ADC_CHANNEL_VBATT 0
-#define ADC_LOGIC_INTAKE_AIR 0
-#define ADC_LOGIC_COOLANT 0
float getVoltageDivided(int);
float getVoltage(int channel);
diff --git a/unit_tests/efifeatures.h b/unit_tests/efifeatures.h
index 7712b23b37..92fe24e680 100644
--- a/unit_tests/efifeatures.h
+++ b/unit_tests/efifeatures.h
@@ -1,5 +1,5 @@
-/*
- * efifeatures.h
+/**
+ * @file efifeatures.h
*
* Created on: Mar 7, 2014
* Author: Andrey
@@ -8,6 +8,8 @@
#ifndef EFIFEATURES_H_
#define EFIFEATURES_H_
+#define EFI_HISTOGRAMS TRUE
+
#define EFI_CLI_SUPPORT FALSE
#define EFI_SUPPORT_FORD_ASPIRE TRUE
@@ -18,5 +20,7 @@
#define EFI_SIGNAL_EXECUTOR_ONE_TIMER TRUE
+#define EFI_SHAFT_POSITION_INPUT TRUE
+#define EFI_ENGINE_CONTROL TRUE
#endif /* EFIFEATURES_H_ */
diff --git a/unit_tests/engine_test_helper.cpp b/unit_tests/engine_test_helper.cpp
new file mode 100644
index 0000000000..185753f0cf
--- /dev/null
+++ b/unit_tests/engine_test_helper.cpp
@@ -0,0 +1,38 @@
+/**
+ * @file engine_test_helper.cpp
+ *
+ * @date Jun 26, 2014
+ * @author Andrey Belomutskiy, (c) 2012-2014
+ */
+
+#include "engine_test_helper.h"
+#include "stddef.h"
+#include "trigger_decoder.h"
+
+extern int timeNow;
+
+EngineTestHelper::EngineTestHelper(engine_type_e engineType) {
+ ec = &persistentConfig.engineConfiguration;
+
+ configuration.engineConfiguration = ec;
+ configuration.engineConfiguration2 = &ec2;
+
+ resetConfigurationExt(NULL, FORD_INLINE_6_1995, ec, &ec2, &persistentConfig.engineConfiguration.bc);
+}
+
+void EngineTestHelper::fireTriggerEvents() {
+ for (int i = 0; i < 24; i++) {
+ timeNow += 5000; // 5ms
+ triggerCentral.handleShaftSignal(&configuration, SHAFT_PRIMARY_UP, timeNow);
+ timeNow += 5000;
+ triggerCentral.handleShaftSignal(&configuration, SHAFT_PRIMARY_DOWN, timeNow);
+ }
+}
+
+void EngineTestHelper::initTriggerShapeAndRpmCalculator() {
+ initializeTriggerShape(NULL, ec, &ec2);
+ incrementGlobalConfigurationVersion();
+
+ triggerCentral.addEventListener((ShaftPositionListener) &rpmShaftPositionCallback, "rpm reporter", &rpmState);
+
+}
diff --git a/unit_tests/engine_test_helper.h b/unit_tests/engine_test_helper.h
new file mode 100644
index 0000000000..818c0bb47d
--- /dev/null
+++ b/unit_tests/engine_test_helper.h
@@ -0,0 +1,32 @@
+/**
+ * @file engine_test_helper.h
+ *
+ * @date Jun 26, 2014
+ * @author Andrey Belomutskiy, (c) 2012-2014
+ */
+#ifndef ENGINE_TEST_HELPER_H_
+#define ENGINE_TEST_HELPER_H_
+
+#include "engine_configuration.h"
+#include "ec2.h"
+#include "trigger_central.h"
+#include "rpm_calculator.h"
+
+class EngineTestHelper {
+public:
+ EngineTestHelper(engine_type_e engineType);
+ void initTriggerShapeAndRpmCalculator();
+ void fireTriggerEvents();
+
+ persistent_config_s persistentConfig;
+ engine_configuration2_s ec2;
+ configuration_s configuration;
+
+ engine_configuration_s *ec;
+
+ TriggerCentral triggerCentral;
+ RpmCalculator rpmState;
+
+};
+
+#endif /* ENGINE_TEST_HELPER_H_ */
diff --git a/unit_tests/global.h b/unit_tests/global.h
index 8cf7b254cf..f7bd257c0f 100644
--- a/unit_tests/global.h
+++ b/unit_tests/global.h
@@ -13,7 +13,13 @@
#include "efitime.h"
+typedef int bool_t;
+
+typedef void * Logging;
+
#define TRUE 1
#define FALSE 0
+#define CCM_OPTIONAL
+
#endif /* GLOBAL_H_ */
diff --git a/unit_tests/main.cpp b/unit_tests/main.cpp
index 2bab2a75af..50574f8d26 100644
--- a/unit_tests/main.cpp
+++ b/unit_tests/main.cpp
@@ -1,10 +1,8 @@
-/*
- ============================================================================
- Name : main.c
- Author : Andrey Belomutskiy
- Copyright : (c) 2012-2013
- Description : First step towards unit-testing rusEfi algorithms on win32
- ============================================================================
+/**
+ * @file main.cpp
+ * @file First step towards unit-testing rusEfi algorithms
+ *
+ * @author Andrey Belomutskiy (c) 2012-2014
*/
#include
@@ -15,36 +13,35 @@
#include "main.h"
#include "error_handling.h"
#include "ec2.h"
+#include "test_accel_enrichment.h"
+#include "test_interpolation_3d.h"
+#include "test_find_index.h"
+#include "test_sensors.h"
+#include "test_speed_density.h"
+#include "test_fuel_map.h"
extern "C"
{
-
#include "map_resize.h"
#include "test_idle_controller.h"
-#include "test_interpolation_3d.h"
-#include "test_find_index.h"
-#include "test_fuel_map.h"
#include "test_event_registry.h"
-#include "test_sensors.h"
#include "test_signal_executor.h"
#include "test_util.h"
#include "engine_configuration.h"
-#include "engine_math.h"
}
+#include "engine_math.h"
#include "test_engine_math.h"
#include "test_trigger_decoder.h"
static engine_configuration_s ec;
engine_configuration_s *engineConfiguration = &ec;
-static float absF(float value) {
- return value > 0 ? value : -value;
-}
+int timeNow = 0;
uint64_t getTimeNowUs(void) {
- return 0;
+ return timeNow;
}
void assertEqualsM(const char *msg, float expected, float actual) {
@@ -103,6 +100,7 @@ int main(void) {
testEventRegistry();
testSensors();
testCyclicBuffer();
+ testCrc();
testSignalExecutor();
@@ -119,18 +117,25 @@ int main(void) {
testPinHelper();
testSetTableValue();
- printf("Success 20130429\r\n");
+ testAccelEnrichment();
-// resizeMap();
+ testSpeedDensity();
+ testFLStack();
+
+ // resizeMap();
+ printf("Success 20130706\r\n");
return EXIT_SUCCESS;
}
-
int warning(obd_code_e code, const char *fmt, ...) {
printf("Warning: %s\r\n", fmt);
}
+bool hasFirmwareError(void) {
+ return FALSE;
+}
+
void firmwareError(const char *fmt, ...) {
printf(fmt);
exit(-1);
@@ -152,3 +157,7 @@ int warning(const char *fmt, ...) {
printf(fmt);
exit(-1);
}
+
+bool_t isCranking(void) {
+ return 0;
+}
diff --git a/unit_tests/main.h b/unit_tests/main.h
index 5122fb4ce4..ecac1ad520 100644
--- a/unit_tests/main.h
+++ b/unit_tests/main.h
@@ -26,7 +26,6 @@ extern "C"
#include "efitime.h"
#include "boards.h"
-#include "engines.h"
typedef int bool_t;
diff --git a/unit_tests/makelinks.bat b/unit_tests/makelinks.bat
index 95cde49cba..514c51a965 100644
--- a/unit_tests/makelinks.bat
+++ b/unit_tests/makelinks.bat
@@ -1,6 +1,8 @@
junction controllers_algo ..\firmware\controllers\algo
+junction controllers_core ..\firmware\controllers\core
junction controllers_math ..\firmware\controllers\math
+junction controllers_system ..\firmware\controllers\system
junction controllers_trigger ..\firmware\controllers\trigger
junction engines ..\firmware\config\engines
junction controllers_sensors ..\firmware\controllers\sensors
diff --git a/unit_tests/map_resize.c b/unit_tests/map_resize.cpp
similarity index 97%
rename from unit_tests/map_resize.c
rename to unit_tests/map_resize.cpp
index cc876a1020..6addb2b876 100644
--- a/unit_tests/map_resize.c
+++ b/unit_tests/map_resize.cpp
@@ -1,176 +1,175 @@
-/**
- * @file map_resize.c
- *
- * @date Jan 12, 2014
- * @author Andrey Belomutskiy, (c) 2012-2013
- */
-
-#include
-#include "fuel_math.h"
-#include "interpolation.h"
-#include "engines.h"
-#include "engine_configuration.h"
-#include "main.h"
-#include "idle_controller.h"
-
-#if 1
-
-#define AD_LOAD_COUNT 16
-#define AD_RPM_COUNT 16
-
-
-static float ad_rpm_table[] = {/*0*/ 800.000000,
- /*1*/ 1213.333374,
- /*2*/ 1626.666748,
- /*3*/ 2040.000000,
- /*4*/ 2453.333496,
- /*5*/ 2866.666748,
- /*6*/ 3280.000000,
- /*7*/ 3693.333496,
- /*8*/ 4106.666992,
- /*9*/ 4520.000000,
- /*10*/ 4933.333496,
- /*11*/ 5346.666992,
- /*12*/ 5760.000000,
- /*13*/ 6173.333496,
- /*14*/ 6586.666992,
- /*15*/ 7000.000000,
- };;
-
-static float ad_maf_table[] =
-{/*0*/ 1.200000,
-/*1*/ 1.413333,
-/*2*/ 1.626667,
-/*3*/ 1.840000,
-/*4*/ 2.053333,
-/*5*/ 2.266667,
-/*6*/ 2.480000,
-/*7*/ 2.693333,
-/*8*/ 2.906667,
-/*9*/ 3.120000,
-/*10*/ 3.333333,
-/*11*/ 3.546667,
-/*12*/ 3.760000,
-/*13*/ 3.973333,
-/*14*/ 4.186667,
-/*15*/ 4.400000,
-};
-
-static float ad_table[AD_LOAD_COUNT][AD_RPM_COUNT] = {
- /* RPM 800.000000 1213.333374 1626.666748 2040.000000 2453.333496 2866.666748 3280.000000 3693.333496 4106.666992 4520.000000 4933.333496 5346.666992 5760.000000 6173.333496 6586.666992 7000.000000*/
- /* Load 1.200000 */{ 0.662000, -7.730000, -16.722000, -23.139999, -29.398001, -31.268000, -32.108002, -30.436001, -30.896000, -26.656000, -24.704000, -25.108000, -25.132000, -25.459999, -25.459999, -25.459999},
- /* Load 1.413333 */{ 0.546000, -7.662000, -16.882000, -23.482000, -29.520000, -31.323999, -32.108002, -30.656000, -30.468000, -26.879999, -24.746000, -24.742001, -29.032000, -25.562000, -25.562000, -25.562000},
- /* Load 1.626667 */{ 0.584000, -7.870000, -16.714001, -23.025999, -29.542000, -31.166000, -32.175999, -30.540001, -30.268000, -26.416000, -24.134001, -25.007999, -24.698000, -26.167999, -26.167999, -26.167999},
- /* Load 1.840000 */{ 0.584000, -7.658000, -16.714001, -23.254000, -29.351999, -30.978001, -32.141998, -30.874001, -30.896000, -26.507999, -24.558001, -24.389999, -25.761999, -35.492001, -35.492001, -35.492001},
- /* Load 2.053333 */{ 0.584000, -7.862000, -16.538000, -23.254000, -29.232000, -31.296000, -32.520000, -30.142000, -30.388000, -25.903999, -24.370001, -24.082001, -24.792000, -24.351999, -24.351999, -24.351999},
- /* Load 2.266667 */{ -1.364000, -7.726000, -16.806000, -23.254000, -29.639999, -31.006001, -32.298000, -30.912001, -29.882000, -26.392000, -24.664000, -27.233999, -25.374001, -25.417999, -25.417999, -25.417999},
- /* Load 2.480000 */{ 1.364000, -10.490000, -16.705999, -22.441999, -28.101999, -30.238001, -32.363998, -30.719999, -30.896000, -26.608000, -24.664000, -24.431999, -24.500000, -25.510000, -25.510000, -25.510000},
- /* Load 2.693333 */{ 9.864000, -10.416000, -11.680000, -19.150000, -25.754000, -27.936001, -32.554001, -30.656000, -30.153999, -27.184000, -25.252001, -22.812000, -24.452000, -25.219999, -25.219999, -25.219999},
- /* Load 2.906667 */{ 9.866000, 5.452000, 2.854000, -17.212000, -17.552000, -20.688000, -25.660000, -27.809999, -27.691999, -27.224001, -25.882000, -25.360001, -26.100000, -27.992001, -27.992001, -27.992001},
- /* Load 3.120000 */{ 9.864000, 5.452000, 2.854000, -0.342000, -12.526000, -16.218000, -21.364000, -27.590000, -25.780001, -24.170000, -24.664000, -25.584000, -26.490000, -31.968000, -31.968000, -31.968000},
- /* Load 3.333333 */{ 9.864000, 5.516000, 2.854000, -0.226000, -2.738000, -3.816000, -11.924000, -18.808001, -21.038000, -21.538000, -21.209999, -22.228001, -25.046000, -25.156000, -25.156000, -25.156000},
- /* Load 3.546667 */{ 9.866000, 5.518000, 2.854000, 0.000000, -3.022000, -3.816000, -6.428000, -7.788000, -19.426001, -20.860001, -19.966000, -21.030001, -21.396000, -21.570000, -21.570000, -21.570000},
- /* Load 3.760000 */{ 9.864000, 5.516000, 2.772000, -0.226000, -2.732000, -3.500000, -6.798000, -8.102000, -8.660000, -9.500000, -11.788000, -20.132000, -20.072001, -20.510000, -20.510000, -20.510000},
- /* Load 3.973333 */{ 9.864000, 5.518000, 2.854000, 0.000000, -2.880000, -3.816000, -6.420000, -8.320000, -8.426000, -8.532000, -11.470000, -11.442000, -13.610000, -12.022000, -12.022000, -12.022000},
- /* Load 4.186667 */{ 9.750000, 5.518000, 2.604000, 0.000000, -2.880000, -3.654000, -6.050000, -6.888000, -8.372000, -9.364000, -11.764000, -11.732000, -11.864000, -12.376000, -12.376000, -12.376000},
- /* Load 4.400000 */{ 0.350000, 5.590000, 0.502000, 0.910000, 0.864000, 0.954000, 1.324000, -7.436000, 1.170000, 1.054000, 2.058000, 2.098000, 2.636000, -12.352000, -12.352000, -12.352000}
- };
-
-//float getBaseAdvance(int rpm, float key) {
-// // todo: use interpolation
-// int rpm_index = findIndex(ad_rpm_table, AD_RPM_COUNT, rpm);
-// rpm_index = max(rpm_index, 0);
-// int maf_index = findIndex(ad_maf_table, AD_LOAD_COUNT, key);
-// maf_index = max(maf_index, 0);
-//
-// return ad_table[rpm_index][maf_index];
-//}
-
-
-
-#define newRpmSize 16
-#define newKeySize 16
-
-static float newRpmBin[newRpmSize];
-static float newKeyBin[newKeySize];
-
-//static float *fuel_ptrs[FUEL_LOAD_COUNT];
-
-//EngineConfiguration *engineConfiguration;
-
-extern int needInterpolationLogging;
-
-void resizeMap(void) {
-// float keyMin = 1.2;
-// float keyMax = 4.4;
-//
-// float rpmMin = 800;
-// float rpmMax = 7000;
-
-// for (int k = 0; k < FUEL_LOAD_COUNT; k++)
-// fuel_ptrs[k] = engineConfiguration->fuelTable[k];
-
-// for (int i = 0; i < FUEL_MAF_COUNT; i++)
-// engineConfiguration->fuelKeyBins[i] = default_fuel_maf_bins[i];
-// for (int i = 0; i < FUEL_RPM_COUNT; i++)
-// engineConfiguration->fuelRpmBins[i] = default_fuel_rpm_bins[i];
-// for (int k = 0; k < FUEL_MAF_COUNT; k++) {
-// for (int r = 0; r < FUEL_RPM_COUNT; r++) {
-// // todo: this is BAD, this needs to be fixed - TS table indexes are different from default indexes
-// engineConfiguration->fuelTable[k][r] = default_fuel_table[r][k];
-// }
-// }
-
-// assertEquals(15, interpolate3d(1.2, engineConfiguration->fuelKeyBins, FUEL_MAF_COUNT, 8000,
-// engineConfiguration->fuelRpmBins,
-// FUEL_RPM_COUNT, fuel_ptrs));
-
- needInterpolationLogging = 0;
-
-// printf("static float ad_maf_table[AD_LOAD_COUNT] = {");
-// for (int i = 0; i < newKeySize; i++) {
-// newKeyBin[i] = interpolate(0, keyMin, newKeySize - 1, keyMax, i);
-// printf("/*%d*/ %f,\r\n", i, newKeyBin[i]);
-// }
-// printf("};\r\n");
-//
-// printf("static float ad_rpm_table[AD_RPM_COUNT] = {");
-// for (int i = 0; i < newRpmSize; i++) {
-// newRpmBin[i] = interpolate(0, rpmMin, newRpmSize - 1, rpmMax, i);
-// printf("/*%d*/ %f,\r\n", i, newRpmBin[i]);
-// }
-// printf("};\r\n");
-
- printf("static float ad_table[AD_RPM_COUNT][AD_LOAD_COUNT] = {\r\n");
-
- printf("/* RPM\t\t");
- for (int r = 0; r < newRpmSize; r++) {
- float rpm = newRpmBin[r];
- printf("\t%f", rpm);
- }
- printf("*/\r\n");
-
- for (int k = 0; k < newKeySize; k++) {
- float load = newKeyBin[k];
- printf("/* Load %f */{", load);
-
- for (int r = 0; r < newRpmSize; r++) {
- float rpm = newRpmBin[r];
-
- float v = ad_table[k][r];
-
- printf("\t%f", v);
- if (r != newRpmSize - 1)
- printf(",");
-
- }
- printf("}");
- if (k != newKeySize - 1)
- printf(",");
- printf("\r\n");
- }
- printf("};\r\n");
-
-}
-
-#endif
+/**
+ * @file map_resize.c
+ *
+ * @date Jan 12, 2014
+ * @author Andrey Belomutskiy, (c) 2012-2013
+ */
+
+#include
+#include "fuel_math.h"
+#include "interpolation.h"
+#include "engine_configuration.h"
+#include "main.h"
+#include "idle_controller.h"
+
+#if 1
+
+#define AD_LOAD_COUNT 16
+#define AD_RPM_COUNT 16
+
+
+static float ad_rpm_table[] = {/*0*/ 800.000000,
+ /*1*/ 1213.333374,
+ /*2*/ 1626.666748,
+ /*3*/ 2040.000000,
+ /*4*/ 2453.333496,
+ /*5*/ 2866.666748,
+ /*6*/ 3280.000000,
+ /*7*/ 3693.333496,
+ /*8*/ 4106.666992,
+ /*9*/ 4520.000000,
+ /*10*/ 4933.333496,
+ /*11*/ 5346.666992,
+ /*12*/ 5760.000000,
+ /*13*/ 6173.333496,
+ /*14*/ 6586.666992,
+ /*15*/ 7000.000000,
+ };;
+
+static float ad_maf_table[] =
+{/*0*/ 1.200000,
+/*1*/ 1.413333,
+/*2*/ 1.626667,
+/*3*/ 1.840000,
+/*4*/ 2.053333,
+/*5*/ 2.266667,
+/*6*/ 2.480000,
+/*7*/ 2.693333,
+/*8*/ 2.906667,
+/*9*/ 3.120000,
+/*10*/ 3.333333,
+/*11*/ 3.546667,
+/*12*/ 3.760000,
+/*13*/ 3.973333,
+/*14*/ 4.186667,
+/*15*/ 4.400000,
+};
+
+static float ad_table[AD_LOAD_COUNT][AD_RPM_COUNT] = {
+ /* RPM 800.000000 1213.333374 1626.666748 2040.000000 2453.333496 2866.666748 3280.000000 3693.333496 4106.666992 4520.000000 4933.333496 5346.666992 5760.000000 6173.333496 6586.666992 7000.000000*/
+ /* Load 1.200000 */{ 0.662000, -7.730000, -16.722000, -23.139999, -29.398001, -31.268000, -32.108002, -30.436001, -30.896000, -26.656000, -24.704000, -25.108000, -25.132000, -25.459999, -25.459999, -25.459999},
+ /* Load 1.413333 */{ 0.546000, -7.662000, -16.882000, -23.482000, -29.520000, -31.323999, -32.108002, -30.656000, -30.468000, -26.879999, -24.746000, -24.742001, -29.032000, -25.562000, -25.562000, -25.562000},
+ /* Load 1.626667 */{ 0.584000, -7.870000, -16.714001, -23.025999, -29.542000, -31.166000, -32.175999, -30.540001, -30.268000, -26.416000, -24.134001, -25.007999, -24.698000, -26.167999, -26.167999, -26.167999},
+ /* Load 1.840000 */{ 0.584000, -7.658000, -16.714001, -23.254000, -29.351999, -30.978001, -32.141998, -30.874001, -30.896000, -26.507999, -24.558001, -24.389999, -25.761999, -35.492001, -35.492001, -35.492001},
+ /* Load 2.053333 */{ 0.584000, -7.862000, -16.538000, -23.254000, -29.232000, -31.296000, -32.520000, -30.142000, -30.388000, -25.903999, -24.370001, -24.082001, -24.792000, -24.351999, -24.351999, -24.351999},
+ /* Load 2.266667 */{ -1.364000, -7.726000, -16.806000, -23.254000, -29.639999, -31.006001, -32.298000, -30.912001, -29.882000, -26.392000, -24.664000, -27.233999, -25.374001, -25.417999, -25.417999, -25.417999},
+ /* Load 2.480000 */{ 1.364000, -10.490000, -16.705999, -22.441999, -28.101999, -30.238001, -32.363998, -30.719999, -30.896000, -26.608000, -24.664000, -24.431999, -24.500000, -25.510000, -25.510000, -25.510000},
+ /* Load 2.693333 */{ 9.864000, -10.416000, -11.680000, -19.150000, -25.754000, -27.936001, -32.554001, -30.656000, -30.153999, -27.184000, -25.252001, -22.812000, -24.452000, -25.219999, -25.219999, -25.219999},
+ /* Load 2.906667 */{ 9.866000, 5.452000, 2.854000, -17.212000, -17.552000, -20.688000, -25.660000, -27.809999, -27.691999, -27.224001, -25.882000, -25.360001, -26.100000, -27.992001, -27.992001, -27.992001},
+ /* Load 3.120000 */{ 9.864000, 5.452000, 2.854000, -0.342000, -12.526000, -16.218000, -21.364000, -27.590000, -25.780001, -24.170000, -24.664000, -25.584000, -26.490000, -31.968000, -31.968000, -31.968000},
+ /* Load 3.333333 */{ 9.864000, 5.516000, 2.854000, -0.226000, -2.738000, -3.816000, -11.924000, -18.808001, -21.038000, -21.538000, -21.209999, -22.228001, -25.046000, -25.156000, -25.156000, -25.156000},
+ /* Load 3.546667 */{ 9.866000, 5.518000, 2.854000, 0.000000, -3.022000, -3.816000, -6.428000, -7.788000, -19.426001, -20.860001, -19.966000, -21.030001, -21.396000, -21.570000, -21.570000, -21.570000},
+ /* Load 3.760000 */{ 9.864000, 5.516000, 2.772000, -0.226000, -2.732000, -3.500000, -6.798000, -8.102000, -8.660000, -9.500000, -11.788000, -20.132000, -20.072001, -20.510000, -20.510000, -20.510000},
+ /* Load 3.973333 */{ 9.864000, 5.518000, 2.854000, 0.000000, -2.880000, -3.816000, -6.420000, -8.320000, -8.426000, -8.532000, -11.470000, -11.442000, -13.610000, -12.022000, -12.022000, -12.022000},
+ /* Load 4.186667 */{ 9.750000, 5.518000, 2.604000, 0.000000, -2.880000, -3.654000, -6.050000, -6.888000, -8.372000, -9.364000, -11.764000, -11.732000, -11.864000, -12.376000, -12.376000, -12.376000},
+ /* Load 4.400000 */{ 0.350000, 5.590000, 0.502000, 0.910000, 0.864000, 0.954000, 1.324000, -7.436000, 1.170000, 1.054000, 2.058000, 2.098000, 2.636000, -12.352000, -12.352000, -12.352000}
+ };
+
+//float getBaseAdvance(int rpm, float key) {
+// // todo: use interpolation
+// int rpm_index = findIndex(ad_rpm_table, AD_RPM_COUNT, rpm);
+// rpm_index = max(rpm_index, 0);
+// int maf_index = findIndex(ad_maf_table, AD_LOAD_COUNT, key);
+// maf_index = max(maf_index, 0);
+//
+// return ad_table[rpm_index][maf_index];
+//}
+
+
+
+#define newRpmSize 16
+#define newKeySize 16
+
+static float newRpmBin[newRpmSize];
+static float newKeyBin[newKeySize];
+
+//static float *fuel_ptrs[FUEL_LOAD_COUNT];
+
+//EngineConfiguration *engineConfiguration;
+
+extern int needInterpolationLogging;
+
+void resizeMap(void) {
+// float keyMin = 1.2;
+// float keyMax = 4.4;
+//
+// float rpmMin = 800;
+// float rpmMax = 7000;
+
+// for (int k = 0; k < FUEL_LOAD_COUNT; k++)
+// fuel_ptrs[k] = engineConfiguration->fuelTable[k];
+
+// for (int i = 0; i < FUEL_MAF_COUNT; i++)
+// engineConfiguration->fuelKeyBins[i] = default_fuel_maf_bins[i];
+// for (int i = 0; i < FUEL_RPM_COUNT; i++)
+// engineConfiguration->fuelRpmBins[i] = default_fuel_rpm_bins[i];
+// for (int k = 0; k < FUEL_MAF_COUNT; k++) {
+// for (int r = 0; r < FUEL_RPM_COUNT; r++) {
+// // todo: this is BAD, this needs to be fixed - TS table indexes are different from default indexes
+// engineConfiguration->fuelTable[k][r] = default_fuel_table[r][k];
+// }
+// }
+
+// assertEquals(15, interpolate3d(1.2, engineConfiguration->fuelKeyBins, FUEL_MAF_COUNT, 8000,
+// engineConfiguration->fuelRpmBins,
+// FUEL_RPM_COUNT, fuel_ptrs));
+
+ needInterpolationLogging = 0;
+
+// printf("static float ad_maf_table[AD_LOAD_COUNT] = {");
+// for (int i = 0; i < newKeySize; i++) {
+// newKeyBin[i] = interpolate(0, keyMin, newKeySize - 1, keyMax, i);
+// printf("/*%d*/ %f,\r\n", i, newKeyBin[i]);
+// }
+// printf("};\r\n");
+//
+// printf("static float ad_rpm_table[AD_RPM_COUNT] = {");
+// for (int i = 0; i < newRpmSize; i++) {
+// newRpmBin[i] = interpolate(0, rpmMin, newRpmSize - 1, rpmMax, i);
+// printf("/*%d*/ %f,\r\n", i, newRpmBin[i]);
+// }
+// printf("};\r\n");
+
+ printf("static float ad_table[AD_RPM_COUNT][AD_LOAD_COUNT] = {\r\n");
+
+ printf("/* RPM\t\t");
+ for (int r = 0; r < newRpmSize; r++) {
+ float rpm = newRpmBin[r];
+ printf("\t%f", rpm);
+ }
+ printf("*/\r\n");
+
+ for (int k = 0; k < newKeySize; k++) {
+ float load = newKeyBin[k];
+ printf("/* Load %f */{", load);
+
+ for (int r = 0; r < newRpmSize; r++) {
+ float rpm = newRpmBin[r];
+
+ float v = ad_table[k][r];
+
+ printf("\t%f", v);
+ if (r != newRpmSize - 1)
+ printf(",");
+
+ }
+ printf("}");
+ if (k != newKeySize - 1)
+ printf(",");
+ printf("\r\n");
+ }
+ printf("};\r\n");
+
+}
+
+#endif
diff --git a/unit_tests/test.mk b/unit_tests/test.mk
index fe5910bf36..556541a9d1 100644
--- a/unit_tests/test.mk
+++ b/unit_tests/test.mk
@@ -1,15 +1,18 @@
TEST_SRC_C = boards.c \
- test_basic_math/test_find_index.c \
- test_basic_math/test_interpolation_3d.c \
- test_idle_controller.c \
- test_sensors.c
+ test_idle_controller.c
TEST_SRC_CPP = test_util.cpp \
test_data_structures/test_event_registry.cpp \
+ test_basic_math/test_find_index.cpp \
+ test_basic_math/test_interpolation_3d.cpp \
test_data_structures/test_engine_math.cpp \
test_trigger_decoder.cpp \
test_fuel_map.cpp \
- test_signal_executor.cpp
+ engine_test_helper.cpp \
+ test_speed_density.cpp \
+ test_signal_executor.cpp \
+ test_sensors.cpp \
+ test_accel_enrichment.cpp
diff --git a/unit_tests/test_accel_enrichment.cpp b/unit_tests/test_accel_enrichment.cpp
new file mode 100644
index 0000000000..2b1f070d22
--- /dev/null
+++ b/unit_tests/test_accel_enrichment.cpp
@@ -0,0 +1,35 @@
+/**
+ * @file test_accel_enrichment.cpp
+ *
+ * Created on: apr 29, 2014
+ * Author: Dmitry Sidin
+ * Author: Andrey Belomutskiy, (c) 2012-2013
+ */
+
+#include "main.h"
+#include "accel_enrichment.h"
+#include "test_accel_enrichment.h"
+#include "engine_configuration.h"
+
+void testAccelEnrichment(void) {
+
+ engine_configuration_s ec;
+ engine_configuration_s *engineConfiguration = &ec;
+
+ printf("*************************************************** testAccelEnrichment\r\n");
+ engineConfiguration->diffLoadEnrichmentCoef = 1;
+
+ // todo: fix the implementation
+ // todo: add constructor which would reset state properly
+ AccelEnrichmemnt instance;
+
+ for (int i = 0; i == 3; i++)
+ instance.updateDiffEnrichment(engineConfiguration, i);
+// assertEqualsM("diff=1", 1, instance.getDiffEnrichment());
+
+ for (int i = 3; i == 0; i++)
+ instance.updateDiffEnrichment(engineConfiguration, i);
+
+// assertEqualsM("diff=1", 1, instance.getDiffEnrichment());
+
+}
diff --git a/unit_tests/test_accel_enrichment.h b/unit_tests/test_accel_enrichment.h
new file mode 100644
index 0000000000..225a846664
--- /dev/null
+++ b/unit_tests/test_accel_enrichment.h
@@ -0,0 +1,17 @@
+/**
+ * @file test_accel_enrichment.h
+ *
+ * Created on: apr 29, 2014
+ * Author: Dmitry Sidin
+ * Author: Andrey Belomutskiy, (c) 2012-2013
+ */
+
+
+#ifndef TEST_ACCEL_ENRICHMENT_H_
+#define TEST_ACCEL_ENRICHMENT_H_
+
+void testAccelEnrichment(void);
+
+
+
+#endif /* TEST_ACCEL_ENRICHMENT_H_ */
diff --git a/unit_tests/test_basic_math/test_find_index.c b/unit_tests/test_basic_math/test_find_index.cpp
similarity index 96%
rename from unit_tests/test_basic_math/test_find_index.c
rename to unit_tests/test_basic_math/test_find_index.cpp
index 1785336c4b..47d34d851a 100644
--- a/unit_tests/test_basic_math/test_find_index.c
+++ b/unit_tests/test_basic_math/test_find_index.cpp
@@ -1,120 +1,120 @@
-/*
- * test_find_index.c
- *
- * Created on: Oct 30, 2013
- * Author: Andrey Belomutskiy, (c) 2012-2013
- */
-
-#include "engine_math.h"
-#include "main.h"
-#include "interpolation.h"
-#include
-#include "engine_configuration.h"
-
-void testFindIndex(void) {
- printf("*************************************************** testFindIndex\r\n");
-
- float array[] = { 1, 2, 3, 4, 5 };
- int size = 4;
- int result;
-
- printf("To the left\r\n");
- result = findIndex(array, size, -1.0);
- assertEquals(-1, result);
-
- printf("To the right4\r\n");
- result = findIndex(array, size, 10.0);
- assertEquals(3, result);
-
- printf("To the right5\r\n");
- result = findIndex(array, 5, 10.0);
- assertEquals(4, result);
-
- printf("On the edge\r\n");
- result = findIndex(array, size, 4.0);
- assertEquals(3, result);
-
- printf("Another1\r\n");
- result = findIndex(array, size, 3.9);
- assertEquals(2, result);
-
- printf("Another2\r\n");
- result = findIndex(array, size, 4.1);
- assertEquals(3, result);
-
- printf("Another3\r\n");
- result = findIndex(array, size, 2);
- assertEquals(1, result);
-
- printf("Left edge1\r\n");
- result = findIndex(array, size, 1);
- assertEquals(0, result);
-
- printf("Left edge2\r\n");
- result = findIndex(array, size, 1.1);
- assertEquals(0, result);
-
- printf("Middle\r\n");
- result = findIndex(array, size, 3);
- assertEquals(2, result);
-
- size = 5; // now test with off array size
-
- printf("Middle2\r\n");
- result = findIndex(array, size, 4);
- assertEquals(3, result);
-
- printf("Middle2\r\n");
- result = findIndex(array, size, 3.1);
- assertEquals(2, result);
-}
-
-//static float getValue2(float key, float maf) {
-//
-//}
-
-void testInterpolate2d(void) {
- printf("*************************************************** testInterpolate2d\r\n");
-
- float bins4[] = { 1, 2, 3, 4 };
- float values4[] = { 1, 20, 30, 400 };
- int size = 4;
-
- int result;
-
- printf("Left size\r\n");
- result = interpolate2d(0, bins4, values4, size);
- assertEquals(1, result);
-
- printf("Right size\r\n");
- result = interpolate2d(10, bins4, values4, size);
- assertEquals(400, result);
-
- printf("Middle1\r\n");
- result = interpolate2d(3, bins4, values4, size);
- assertEquals(30, result);
-
- printf("Middle1\r\n");
- result = interpolate2d(3.5, bins4, values4, size);
- assertEquals(215, result);
-}
-
-static engine_configuration_s engineConfiguration;
-
-void testSetTableValue(void) {
- printf("*************************************************** testSetTableValue\r\n");
-
- for (int i = 0; i < CLT_CURVE_SIZE; i++) {
- engineConfiguration.cltFuelCorrBins[i] = -40 + i * 10;
- engineConfiguration.cltFuelCorr[i] = 1;
- }
-
- assertEquals(1, engineConfiguration.cltFuelCorr[0]);
-
- setTableValue(engineConfiguration.cltFuelCorrBins, engineConfiguration.cltFuelCorr, CLT_CURVE_SIZE, -40, 1.5);
- assertEquals(1.5, engineConfiguration.cltFuelCorr[0]);
-
- setTableValue(engineConfiguration.cltFuelCorrBins, engineConfiguration.cltFuelCorr, CLT_CURVE_SIZE, -50, 1.4);
- assertEquals(1.4, engineConfiguration.cltFuelCorr[0]);
-
-}
+/*
+ * test_find_index.c
+ *
+ * Created on: Oct 30, 2013
+ * Author: Andrey Belomutskiy, (c) 2012-2013
+ */
+
+#include "engine_math.h"
+#include "main.h"
+#include "interpolation.h"
+#include
+#include "engine_configuration.h"
+
+void testFindIndex(void) {
+ printf("*************************************************** testFindIndex\r\n");
+
+ float array[] = { 1, 2, 3, 4, 5 };
+ int size = 4;
+ int result;
+
+ printf("To the left\r\n");
+ result = findIndex(array, size, -1.0);
+ assertEquals(-1, result);
+
+ printf("To the right4\r\n");
+ result = findIndex(array, size, 10.0);
+ assertEquals(3, result);
+
+ printf("To the right5\r\n");
+ result = findIndex(array, 5, 10.0);
+ assertEquals(4, result);
+
+ printf("On the edge\r\n");
+ result = findIndex(array, size, 4.0);
+ assertEquals(3, result);
+
+ printf("Another1\r\n");
+ result = findIndex(array, size, 3.9);
+ assertEquals(2, result);
+
+ printf("Another2\r\n");
+ result = findIndex(array, size, 4.1);
+ assertEquals(3, result);
+
+ printf("Another3\r\n");
+ result = findIndex(array, size, 2);
+ assertEquals(1, result);
+
+ printf("Left edge1\r\n");
+ result = findIndex(array, size, 1);
+ assertEquals(0, result);
+
+ printf("Left edge2\r\n");
+ result = findIndex(array, size, 1.1);
+ assertEquals(0, result);
+
+ printf("Middle\r\n");
+ result = findIndex(array, size, 3);
+ assertEquals(2, result);
+
+ size = 5; // now test with off array size
+
+ printf("Middle2\r\n");
+ result = findIndex(array, size, 4);
+ assertEquals(3, result);
+
+ printf("Middle2\r\n");
+ result = findIndex(array, size, 3.1);
+ assertEquals(2, result);
+}
+
+//static float getValue2(float key, float maf) {
+//
+//}
+
+void testInterpolate2d(void) {
+ printf("*************************************************** testInterpolate2d\r\n");
+
+ float bins4[] = { 1, 2, 3, 4 };
+ float values4[] = { 1, 20, 30, 400 };
+ int size = 4;
+
+ int result;
+
+ printf("Left size\r\n");
+ result = interpolate2d(0, bins4, values4, size);
+ assertEquals(1, result);
+
+ printf("Right size\r\n");
+ result = interpolate2d(10, bins4, values4, size);
+ assertEquals(400, result);
+
+ printf("Middle1\r\n");
+ result = interpolate2d(3, bins4, values4, size);
+ assertEquals(30, result);
+
+ printf("Middle1\r\n");
+ result = interpolate2d(3.5, bins4, values4, size);
+ assertEquals(215, result);
+}
+
+static engine_configuration_s engineConfiguration;
+
+void testSetTableValue(void) {
+ printf("*************************************************** testSetTableValue\r\n");
+
+ for (int i = 0; i < CLT_CURVE_SIZE; i++) {
+ engineConfiguration.cltFuelCorrBins[i] = -40 + i * 10;
+ engineConfiguration.cltFuelCorr[i] = 1;
+ }
+
+ assertEquals(1, engineConfiguration.cltFuelCorr[0]);
+
+ setTableValue(engineConfiguration.cltFuelCorrBins, engineConfiguration.cltFuelCorr, CLT_CURVE_SIZE, -40, 1.5);
+ assertEquals(1.5, engineConfiguration.cltFuelCorr[0]);
+
+ setTableValue(engineConfiguration.cltFuelCorrBins, engineConfiguration.cltFuelCorr, CLT_CURVE_SIZE, -50, 1.4);
+ assertEquals(1.4, engineConfiguration.cltFuelCorr[0]);
+
+}
diff --git a/unit_tests/test_basic_math/test_interpolation_3d.c b/unit_tests/test_basic_math/test_interpolation_3d.cpp
similarity index 96%
rename from unit_tests/test_basic_math/test_interpolation_3d.c
rename to unit_tests/test_basic_math/test_interpolation_3d.cpp
index 117d1c2073..6fa875b94c 100644
--- a/unit_tests/test_basic_math/test_interpolation_3d.c
+++ b/unit_tests/test_basic_math/test_interpolation_3d.cpp
@@ -1,70 +1,70 @@
-/*
- * Created on: Oct 17, 2013
- * Author: Andrey Belomutskiy, (c) 2012-2013
- */
-
-/**
- * @file test_interpolation_3d.c
- */
-
-#include "test_interpolation_3d.h"
-#include
-#include
-
-#include "interpolation.h"
-#include "main.h"
-
-float rpmBins[5] = { 100, 200, 300, 400, 500 };
-float mafBins[4] = { 1, 2, 3, 4 };
-
-float map0[4] = { 1, 2, 3, 4 };
-float map1[4] = { 2, 3, 4, 5 };
-float map2[4] = { 3, 4, 200, 300 };
-float map3[4] = { 4, 200, 500, 600 };
-float map4[4] = { 4, 200, 500, 600 };
-
-float *map[5] = { map0, map1, map2, map3, map4 };
-
-
-static float getValue(float rpm, float maf) {
- return interpolate3d(rpm, rpmBins, 5, maf, mafBins, 4, map);
-}
-
-void testInterpolate3d(void) {
- printf("*************************************************** testInterpolate3d\r\n");
- float dwell;
- printf("*** no interpolation here 1\r\n");
- dwell = getValue(100, 2);
- assertEquals(2, dwell);
-
- printf("*** no interpolation here 2\r\n");
- dwell = getValue(200, 4);
- assertEquals(5, dwell);
-
- printf("*** rpm interpolated value expected1\r\n");
- dwell = getValue(150, 2);
- assertEquals(2.5, dwell);
-
- printf("*** rpm interpolated value expected2\r\n");
- dwell = getValue(250, 3);
- assertEquals(102, dwell);
-
- printf("*** both rpm and maf interpolated value expected\r\n");
- dwell = getValue(335.3, 3.551);
- assertEquals(361, dwell);
-
- printf("*** both rpm and maf interpolated value expected 2\r\n");
- dwell = getValue(410.01, 2.012);
- assertEquals(203.6, dwell);
-
- printf("*** both rpm and maf interpolated value expected 3\r\n");
- dwell = getValue(1000000, 1000);
- assertEquals(600, dwell);
-
- printf("*** both rpm and maf interpolated value expected 4\r\n");
- dwell = getValue(410.01, -1);
- assertEquals(4, dwell);
-
- dwell = getValue(-1, -1);
- assertEquals(1, dwell);
-}
+/*
+ * Created on: Oct 17, 2013
+ * Author: Andrey Belomutskiy, (c) 2012-2013
+ */
+
+/**
+ * @file test_interpolation_3d.c
+ */
+
+#include "test_interpolation_3d.h"
+#include
+#include
+
+#include "interpolation.h"
+#include "main.h"
+
+float rpmBins[5] = { 100, 200, 300, 400, 500 };
+float mafBins[4] = { 1, 2, 3, 4 };
+
+float map0[4] = { 1, 2, 3, 4 };
+float map1[4] = { 2, 3, 4, 5 };
+float map2[4] = { 3, 4, 200, 300 };
+float map3[4] = { 4, 200, 500, 600 };
+float map4[4] = { 4, 200, 500, 600 };
+
+float *map[5] = { map0, map1, map2, map3, map4 };
+
+
+static float getValue(float rpm, float maf) {
+ return interpolate3d(rpm, rpmBins, 5, maf, mafBins, 4, map);
+}
+
+void testInterpolate3d(void) {
+ printf("*************************************************** testInterpolate3d\r\n");
+ float dwell;
+ printf("*** no interpolation here 1\r\n");
+ dwell = getValue(100, 2);
+ assertEquals(2, dwell);
+
+ printf("*** no interpolation here 2\r\n");
+ dwell = getValue(200, 4);
+ assertEquals(5, dwell);
+
+ printf("*** rpm interpolated value expected1\r\n");
+ dwell = getValue(150, 2);
+ assertEquals(2.5, dwell);
+
+ printf("*** rpm interpolated value expected2\r\n");
+ dwell = getValue(250, 3);
+ assertEquals(102, dwell);
+
+ printf("*** both rpm and maf interpolated value expected\r\n");
+ dwell = getValue(335.3, 3.551);
+ assertEquals(361, dwell);
+
+ printf("*** both rpm and maf interpolated value expected 2\r\n");
+ dwell = getValue(410.01, 2.012);
+ assertEquals(203.6, dwell);
+
+ printf("*** both rpm and maf interpolated value expected 3\r\n");
+ dwell = getValue(1000000, 1000);
+ assertEquals(600, dwell);
+
+ printf("*** both rpm and maf interpolated value expected 4\r\n");
+ dwell = getValue(410.01, -1);
+ assertEquals(4, dwell);
+
+ dwell = getValue(-1, -1);
+ assertEquals(1, dwell);
+}
diff --git a/unit_tests/test_data_structures/test_event_registry.cpp b/unit_tests/test_data_structures/test_event_registry.cpp
index a39ecc9b5c..8735929320 100644
--- a/unit_tests/test_data_structures/test_event_registry.cpp
+++ b/unit_tests/test_data_structures/test_event_registry.cpp
@@ -1,5 +1,5 @@
/*
- * test_event_registry.c
+ * test_event_registry.cpp
*
* Created on: Nov 27, 2013
* Author: Andrey Belomutskiy, (c) 2012-2013
@@ -15,44 +15,7 @@ static ActuatorEventList result;
int pinDefaultState[IO_PIN_COUNT];
-void initOutputSignal(OutputSignal *signal, io_pin_e ioPin) {
- signal->io_pin = ioPin;
-}
-
extern int outputSignalCount;
void testEventRegistry(void) {
- printf("*************************************** testEventRegistry\r\n");
-
- printf("resetting\r\n");
- resetEventList(&eventList);
- OutputSignalList list;
-
- printf("registering 0\r\n");
-
- registerActuatorEvent(&eventList, 0, list.add((io_pin_e)10), 0);
- registerActuatorEvent(&eventList, 0, list.add((io_pin_e)20), 10);
- assertEquals(2, eventList.size);
-
- printf("registering 1\r\n");
- registerActuatorEvent(&eventList, 1, list.add((io_pin_e)30), 0);
- registerActuatorEvent(&eventList, 1, list.add((io_pin_e)40), 10);
- assertEquals(4, eventList.size);
-
- printf("Looking for 0\r\n");
- findEvents(0, &eventList, &result);
- assertEquals(2, result.size);
- assertEquals(4, eventList.size);
-
- printf("Validating pins\r\n");
- assertEquals(10, result.events[0].actuator->io_pin);
- assertEquals(20, result.events[1].actuator->io_pin);
-
- printf("Looking for 1\r\n");
- findEvents(1, &eventList, &result);
- assertEquals(2, result.size);
- assertEquals(4, eventList.size);
-
- assertEquals(30, result.events[0].actuator->io_pin);
- assertEquals(40, result.events[1].actuator->io_pin);
}
diff --git a/unit_tests/test_engine_math.cpp b/unit_tests/test_engine_math.cpp
index dbbca267f0..86739b195f 100644
--- a/unit_tests/test_engine_math.cpp
+++ b/unit_tests/test_engine_math.cpp
@@ -11,6 +11,7 @@
#include "engine_configuration.h"
#include "ec2.h"
#include "map.h"
+#include "speed_density.h"
extern engine_configuration_s *engineConfiguration;
extern engine_configuration2_s *engineConfiguration2;
@@ -22,6 +23,17 @@ void testEngineMath(void) {
assertEqualsM("600 RPM", 50, getOneDegreeTimeMs(600) * 180);
assertEqualsM("6000 RPM", 5, getOneDegreeTimeMs(6000) * 180);
+
+
+ assertEquals(312.5, getTCharge(1000, 0, 300, 350));
+ assertEquals(313.5833, getTCharge(1000, 50, 300, 350));
+ assertEquals(314.6667, getTCharge(1000, 100, 300, 350));
+
+
+ assertEquals(312.5, getTCharge(4000, 0, 300, 350));
+ assertEquals(320.0833, getTCharge(4000, 50, 300, 350));
+ assertEquals(327.6667, getTCharge(4000, 100, 300, 350));
+
}
float getMap(void) {
diff --git a/unit_tests/test_fuel_map.cpp b/unit_tests/test_fuel_map.cpp
index 869b804f1e..21aa9c755c 100644
--- a/unit_tests/test_fuel_map.cpp
+++ b/unit_tests/test_fuel_map.cpp
@@ -14,7 +14,7 @@
#include "engine_math.h"
#include "OutputSignalList.h"
#include "ec2.h"
-
+#include "trigger_decoder.h"
extern engine_configuration_s *engineConfiguration;
extern engine_configuration2_s *engineConfiguration2;
@@ -54,7 +54,7 @@ void testFuelMap(void) {
// because all the correction tables are zero
printf("*************************************************** getRunningFuel\r\n");
- assertEquals(1005.5, getRunningFuel(5, 5));
+ assertEqualsM("value", 0.5, getRunningFuel(5, 5));
printf("*************************************************** setting IAT table\r\n");
for (int i = 0; i < IAT_CURVE_SIZE; i++) {
@@ -81,7 +81,7 @@ void testFuelMap(void) {
// 1005 * 2 for IAT correction
printf("*************************************************** getRunningFuel\r\n");
- assertEquals(1005, getRunningFuel(5, 5));
+ assertEqualsM("v1", 30150, getRunningFuel(5, 5));
engineConfiguration->crankingSettings.coolantTempMaxC = 65; // 8ms at 65C
engineConfiguration->crankingSettings.fuelAtMaxTempMs = 8;
@@ -98,19 +98,19 @@ void testFuelMap(void) {
}
static void confgiureFordAspireTriggerShape(trigger_shape_s * s) {
- triggerShapeInit(s);
+ s->reset(FOUR_STROKE_CAM_SENSOR);
- triggerAddEvent(s, 53.747, T_SECONDARY, TV_HIGH);
- triggerAddEvent(s, 121.90, T_SECONDARY, TV_LOW);
- triggerAddEvent(s, 232.76, T_SECONDARY, TV_HIGH);
- triggerAddEvent(s, 300.54, T_SECONDARY, TV_LOW);
- triggerAddEvent(s, 360, T_PRIMARY, TV_HIGH);
+ s->addEvent(53.747, T_SECONDARY, TV_HIGH);
+ s->addEvent(121.90, T_SECONDARY, TV_LOW);
+ s->addEvent(232.76, T_SECONDARY, TV_HIGH);
+ s->addEvent(300.54, T_SECONDARY, TV_LOW);
+ s->addEvent(360, T_PRIMARY, TV_HIGH);
- triggerAddEvent(s, 409.8412, T_SECONDARY, TV_HIGH);
- triggerAddEvent(s, 478.6505, T_SECONDARY, TV_LOW);
- triggerAddEvent(s, 588.045, T_SECONDARY, TV_HIGH);
- triggerAddEvent(s, 657.03, T_SECONDARY, TV_LOW);
- triggerAddEvent(s, 720, T_PRIMARY, TV_LOW);
+ s->addEvent(409.8412, T_SECONDARY, TV_HIGH);
+ s->addEvent(478.6505, T_SECONDARY, TV_LOW);
+ s->addEvent(588.045, T_SECONDARY, TV_HIGH);
+ s->addEvent(657.03, T_SECONDARY, TV_LOW);
+ s->addEvent(720, T_PRIMARY, TV_LOW);
}
@@ -123,23 +123,26 @@ void testAngleResolver(void) {
trigger_shape_s * ts = &engineConfiguration2->triggerShape;
confgiureFordAspireTriggerShape(ts);
- assertEqualsM("shape size", 10, ts->size);
+
+ ts->setTriggerShapeSynchPointIndex(0);
+
+ assertEqualsM("shape size", 10, ts->getSize());
OutputSignalList list;
- resetEventList(&ae);
+ ae.resetEventList();
printf("*************************************************** testAngleResolver 0\r\n");
- registerActuatorEventExt(engineConfiguration, &engineConfiguration2->triggerShape, &ae, list.add(INJECTOR_1_OUTPUT), 53 - 175);
+ registerActuatorEventExt(engineConfiguration, &engineConfiguration2->triggerShape, ae.getNextActuatorEvent(), list.add(INJECTOR_1_OUTPUT), 53 - 175);
assertEqualsM("size", 1, ae.size);
assertEquals(1, list.getSize());
- assertEquals(0, ae.events[0].eventIndex);
- assertEquals(53, ae.events[0].angleOffset);
+ assertEquals(0, ae.events[0].position.eventIndex);
+ assertEquals(53, ae.events[0].position.angleOffset);
printf("*************************************************** testAngleResolver 2\r\n");
- resetEventList(&ae);
- registerActuatorEventExt(engineConfiguration, &engineConfiguration2->triggerShape, &ae, list.add(INJECTOR_1_OUTPUT), 51 + 180 - 175);
- assertEquals(2, ae.events[0].eventIndex);
- assertEquals(51.9870, ae.events[0].angleOffset);
+ ae.resetEventList();
+ registerActuatorEventExt(engineConfiguration, &engineConfiguration2->triggerShape, ae.getNextActuatorEvent(), list.add(INJECTOR_1_OUTPUT), 51 + 180 - 175);
+ assertEquals(2, ae.events[0].position.eventIndex);
+ assertEquals(51.9870, ae.events[0].position.angleOffset);
}
void testPinHelper(void) {
diff --git a/unit_tests/test_idle_controller.c b/unit_tests/test_idle_controller.c
index d8fa0e8b25..5ab5f5280b 100644
--- a/unit_tests/test_idle_controller.c
+++ b/unit_tests/test_idle_controller.c
@@ -7,11 +7,6 @@
#include
-
void idleDebug(char *msg, int value) {
printf("%s\r\n", msg);
}
-
-void isCranking(void) {
- return;
-}
diff --git a/unit_tests/test_idle_controller.h b/unit_tests/test_idle_controller.h
index 75a204acaf..64104678cb 100644
--- a/unit_tests/test_idle_controller.h
+++ b/unit_tests/test_idle_controller.h
@@ -2,6 +2,6 @@
#define TEST_IDLE_CONTROLLER_H
void idleDebug(char *msg, int value);
-void isCranking(void);
+bool_t isCranking(void);
#endif
diff --git a/unit_tests/test_sensors.c b/unit_tests/test_sensors.cpp
similarity index 77%
rename from unit_tests/test_sensors.c
rename to unit_tests/test_sensors.cpp
index 33c8bb43a8..f6f5ee5d5e 100644
--- a/unit_tests/test_sensors.c
+++ b/unit_tests/test_sensors.cpp
@@ -1,52 +1,57 @@
-/**
- * @file test_sensors.c
- *
- * @date Dec 7, 2013
- * @author Andrey Belomutskiy, (c) 2012-2013
- */
-
-#include "main.h"
-#include "thermistors.h"
-#include "allsensors.h"
-
-static ThermistorConf tc;
-
-static void testMapDecoding(void) {
- assertEqualsM("denso 0 volts", -6.64, getMAPValueHonda_Denso183(0));
- assertEquals(31.244, getMAPValueHonda_Denso183(1));
-
- assertEqualsM("MPX_4250 0 volts", 8, getMAPValueMPX_4250(0));
- assertEquals(58.4, getMAPValueMPX_4250(1));
-}
-
-void testTpsRateOfChange(void) {
- print("************************************************** testTpsRateOfChange\r\n");
- saveTpsState(0, 0);
- saveTpsState(CH_FREQUENCY, 50);
- assertEquals(50, getTpsRateOfChange());
-
- saveTpsState(2 * CH_FREQUENCY, 50);
- assertEquals(0, getTpsRateOfChange());
-
- saveTpsState(3 * CH_FREQUENCY, 75);
- assertEquals(25, getTpsRateOfChange());
-
-
-}
-
-void testSensors(void) {
- print("************************************************** testSensors\r\n");
- testMapDecoding();
- testTpsRateOfChange();
-
- setThermistorConfiguration(&tc, 32, 9500, 75, 2100, 120, 1000);
-
- prepareThermistorCurve(&tc);
-
- assertEquals(-0.003, tc.s_h_a);
- assertEquals(0.001, tc.s_h_b);
- assertEquals(0.0, tc.s_h_c);
-
- float t = convertResistanceToKelvinTemperature(2100, &tc);
- assertEquals(75 + KELV, t);
-}
+/**
+ * @file test_sensors.c
+ *
+ * @date Dec 7, 2013
+ * @author Andrey Belomutskiy, (c) 2012-2013
+ */
+
+#include "main.h"
+#include "thermistors.h"
+#include "allsensors.h"
+
+static ThermistorConf tc;
+
+static void testMapDecoding(void) {
+
+ air_pressure_sensor_config_s s;
+ s.sensorType = MT_DENSO183;
+
+ assertEqualsM("denso 0 volts", -6.64, decodePressure(0, &s));
+ assertEquals(31.244, decodePressure(1, &s));
+
+ s.sensorType = MT_MPX4250;
+ assertEqualsM("MPX_4250 0 volts", 8, decodePressure(0, &s));
+ assertEquals(58.4, decodePressure(1, &s));
+}
+
+void testTpsRateOfChange(void) {
+ print("************************************************** testTpsRateOfChange\r\n");
+ saveTpsState(0, 0);
+ saveTpsState(CH_FREQUENCY, 50);
+ assertEquals(50, getTpsRateOfChange());
+
+ saveTpsState(2 * CH_FREQUENCY, 50);
+ assertEquals(0, getTpsRateOfChange());
+
+ saveTpsState(3 * CH_FREQUENCY, 75);
+ assertEquals(25, getTpsRateOfChange());
+
+
+}
+
+void testSensors(void) {
+ print("************************************************** testSensors\r\n");
+ testMapDecoding();
+ testTpsRateOfChange();
+
+ setThermistorConfiguration(&tc, 32, 9500, 75, 2100, 120, 1000);
+
+ prepareThermistorCurve(&tc);
+
+ assertEquals(-0.003, tc.s_h_a);
+ assertEquals(0.001, tc.s_h_b);
+ assertEquals(0.0, tc.s_h_c);
+
+ float t = convertResistanceToKelvinTemperature(2100, &tc);
+ assertEquals(75 + KELV, t);
+}
diff --git a/unit_tests/test_signal_executor.cpp b/unit_tests/test_signal_executor.cpp
index 9d862e5fa6..56bfba681b 100644
--- a/unit_tests/test_signal_executor.cpp
+++ b/unit_tests/test_signal_executor.cpp
@@ -1,5 +1,5 @@
/**
- * @file test_signal_executor.c
+ * @file test_signal_executor.cpp
*
* @date Nov 28, 2013
* @author Andrey Belomutskiy, (c) 2012-2013
@@ -14,22 +14,19 @@
#include "utlist.h"
#include "event_queue.h"
-extern OutputSignal *st_output_list;
-
static io_pin_e testLastToggledPin;
static int testToggleCounter;
-int getRevolutionCounter(void) {
- return 0;
-}
-
void setOutputPinValue(io_pin_e pin, int value) {
// this is a test implementation of the method - we use it to see what's going on
testLastToggledPin = pin;
testToggleCounter++;
}
+EventQueue schedulingQueue;
+
void scheduleTask(scheduling_s *scheduling, int delayUs, schfunc_t callback, void *param) {
+ schedulingQueue.insertTask(scheduling, getTimeNowUs(), delayUs, callback, param);
}
void initSignalExecutorImpl(void) {
@@ -43,13 +40,76 @@ static void callback(void *a) {
callbackCounter++;
}
-void testSignalExecutor() {
+static int complexTestNow;
+
+typedef struct {
+ scheduling_s s;
+ int period;
+} TestPwm;
+
+static void complexCallback(TestPwm *testPwm) {
+ callbackCounter++;
+
+ eq.insertTask(&testPwm->s, complexTestNow, testPwm->period, (schfunc_t)complexCallback, testPwm);
+}
+
+static void testSignalExecutor2(void) {
+ print("*************************************** testSignalExecutor2\r\n");
+ eq.clear();
+ TestPwm p1;
+ TestPwm p2;
+ p1.period = 2;
+ p2.period = 3;
+
+ complexTestNow = 0;
+ callbackCounter = 0;
+ eq.insertTask(&p1.s, 0, 0, (schfunc_t)complexCallback, &p1);
+ eq.insertTask(&p2.s, 0, 0, (schfunc_t)complexCallback, &p2);
+ eq.executeAll(complexTestNow);
+ assertEqualsM("callbackCounter #1", 2, callbackCounter);
+ assertEquals(2, eq.size());
+
+ eq.executeAll(complexTestNow = 2);
+ assertEqualsM("callbackCounter #2", 3, callbackCounter);
+ assertEquals(2, eq.size());
+
+ eq.executeAll(complexTestNow = 3);
+ assertEqualsM("callbackCounter #3", 4, callbackCounter);
+ assertEquals(2, eq.size());
+
+}
+
+void testSignalExecutor(void) {
print("*************************************** testSignalExecutor\r\n");
assertEquals(EMPTY_QUEUE, eq.getNextEventTime(0));
scheduling_s s1;
scheduling_s s2;
+ scheduling_s s3;
+ eq.insertTask(&s1, 0, 10, callback, NULL);
+ eq.insertTask(&s2, 0, 11, callback, NULL);
+ eq.insertTask(&s3, 0, 12, callback, NULL);
+ callbackCounter = 0;
+ eq.executeAll(10);
+ assertEquals(1, callbackCounter);
+ callbackCounter = 0;
+ eq.executeAll(11);
+ assertEquals(1, callbackCounter);
+ eq.clear();
+
+ eq.insertTask(&s1, 0, 12, callback, NULL);
+ eq.insertTask(&s2, 0, 11, callback, NULL);
+ eq.insertTask(&s3, 0, 10, callback, NULL);
+ callbackCounter = 0;
+ eq.executeAll(10);
+ assertEquals(1, callbackCounter);
+ callbackCounter = 0;
+ eq.executeAll(11);
+ assertEquals(1, callbackCounter);
+ eq.clear();
+
+ callbackCounter = 0;
eq.insertTask(&s1, 0, 10, callback, NULL);
assertEquals(10, eq.getNextEventTime(0));
@@ -77,4 +137,5 @@ void testSignalExecutor() {
eq.executeAll(11);
assertEquals(2, callbackCounter);
+ testSignalExecutor2();
}
diff --git a/unit_tests/test_speed_density.cpp b/unit_tests/test_speed_density.cpp
new file mode 100644
index 0000000000..6b05cdcded
--- /dev/null
+++ b/unit_tests/test_speed_density.cpp
@@ -0,0 +1,31 @@
+/**
+ * @file test_speed_density.cpp
+ *
+ * @date Jun 26, 2014
+ * @author Andrey Belomutskiy, (c) 2012-2014
+ */
+
+#include "main.h"
+#include "engine_test_helper.h"
+#include "speed_density.h"
+#include "test_speed_density.h"
+
+void testSpeedDensity(void) {
+ printf("*************************************************** testSpeedDensity\r\n");
+ EngineTestHelper eth(FORD_INLINE_6_1995);
+
+ eth.ec->triggerConfig.totalToothCount = 8;
+ eth.initTriggerShapeAndRpmCalculator();
+
+ eth.fireTriggerEvents();
+ assertEqualsM("RPM", 1500, eth.rpmState.rpm());
+
+ // 427 cubic inches, that's a LOT of engine
+ eth.ec->displacement = 6.99728;
+ eth.ec->cylindersCount = 8;
+
+ eth.ec->injectorFlow = gramm_second_to_cc_minute(5.303);
+
+ // 0.01414 sec or 14.14 ms
+ assertEquals(0.01414, sdMath(eth.ec, 0.92, 98, 12.5, 293.16));
+}
diff --git a/unit_tests/test_speed_density.h b/unit_tests/test_speed_density.h
new file mode 100644
index 0000000000..e4dd8cd546
--- /dev/null
+++ b/unit_tests/test_speed_density.h
@@ -0,0 +1,13 @@
+/**
+ * @file test_speed_density.h
+ *
+ * @date Jun 26, 2014
+ * @author Andrey Belomutskiy, (c) 2012-2014
+ */
+
+#ifndef TEST_SPEED_DENSITY_H_
+#define TEST_SPEED_DENSITY_H_
+
+void testSpeedDensity(void);
+
+#endif /* TEST_SPEED_DENSITY_H_ */
diff --git a/unit_tests/test_trigger_decoder.cpp b/unit_tests/test_trigger_decoder.cpp
index fde3d9c257..b21a1988a2 100644
--- a/unit_tests/test_trigger_decoder.cpp
+++ b/unit_tests/test_trigger_decoder.cpp
@@ -14,6 +14,20 @@
#include "dodge_neon.h"
#include "ford_1995_inline_6.h"
#include "mazda_323.h"
+#include "rpm_calculator.h"
+#include "event_queue.h"
+#include "algo.h"
+
+#include "trigger_central.h"
+#include "main_trigger_callback.h"
+#include "engine.h"
+#include "advance_map.h"
+#include "engine_test_helper.h"
+#include "speed_density.h"
+
+Engine engine;
+
+extern int timeNow;
extern "C" {
void sendOutConfirmation(char *value, int i);
@@ -28,7 +42,8 @@ int getTheAngle(engine_type_e engineType) {
engine_configuration_s *ec = &persistentConfig.engineConfiguration;
engine_configuration2_s ec2;
- resetConfigurationExt(engineType, ec, &ec2, &persistentConfig.boardConfiguration);
+ initDataStructures(ec);
+ resetConfigurationExt(NULL, engineType, ec, &ec2, &persistentConfig.engineConfiguration.bc);
trigger_shape_s * shape = &ec2.triggerShape;
return findTriggerZeroEventIndex(shape, &ec->triggerConfig);
@@ -44,18 +59,18 @@ static void testDodgeNeonDecoder(void) {
engine_configuration_s *ec = &persistentConfig.engineConfiguration;
engine_configuration2_s ec2;
- resetConfigurationExt(DODGE_NEON_1995, ec, &ec2, &persistentConfig.boardConfiguration);
+ resetConfigurationExt(NULL, DODGE_NEON_1995, ec, &ec2, &persistentConfig.engineConfiguration.bc);
+ assertEquals(8, ec2.triggerShape.getTriggerShapeSynchPointIndex());
trigger_shape_s * shape = &ec2.triggerShape;
- trigger_state_s state;
- clearTriggerState(&state);
-//
-// assertFalseM("1 shaft_is_synchronized", state.shaft_is_synchronized);
-//
-// int r = 0;
+ TriggerState state;
+
+ assertFalseM("1 shaft_is_synchronized", state.shaft_is_synchronized);
+
+ int r = 0;
// processTriggerEvent(&state, shape, &ec->triggerConfig, SHAFT_PRIMARY_UP, r + 60);
// assertFalseM("2 shaft_is_synchronized", state.shaft_is_synchronized); // still no synchronization
-//
+
// processTriggerEvent(&state, shape, &ec->triggerConfig, SHAFT_PRIMARY_DOWN, r + 210);
// assertFalseM("3 shaft_is_synchronized", state.shaft_is_synchronized); // still no synchronization
//
@@ -87,6 +102,11 @@ static void testDodgeNeonDecoder(void) {
// processTriggerEvent(&state, shape, &ec->triggerConfig, SHAFT_PRIMARY_DOWN, r + 630);
}
+static void assertTriggerPosition(event_trigger_position_s *position, int eventIndex, float angleOffset) {
+ assertEqualsM("eventIndex", eventIndex, position->eventIndex);
+ assertEqualsM("angleOffset", angleOffset, position->angleOffset);
+}
+
static void test1995FordInline6TriggerDecoder(void) {
printf("*************************************************** test1995FordInline6TriggerDecoder\r\n");
@@ -98,45 +118,57 @@ static void test1995FordInline6TriggerDecoder(void) {
engine_configuration_s *ec = &persistentConfig.engineConfiguration;
engine_configuration2_s ec2;
- resetConfigurationExt(FORD_INLINE_6_1995, ec, &ec2, &persistentConfig.boardConfiguration);
-
- ActuatorEventList *ecl = &ec2.engineEventConfiguration.ignitionEvents;
- assertEqualsM("ignition events size", 6, ecl->size);
- assertEqualsM("event index", 0, ecl->events[0].eventIndex);
- assertEquals(0, ecl->events[0].angleOffset);
-
- assertEqualsM("event index", 10, ecl->events[5].eventIndex);
- assertEquals(0, ecl->events[5].angleOffset);
-
- trigger_state_s state;
- clearTriggerState(&state);
+ resetConfigurationExt(NULL, FORD_INLINE_6_1995, ec, &ec2, &persistentConfig.engineConfiguration.bc);
+ assertEqualsM("triggerShapeSynchPointIndex", 0, ec2.triggerShape.getTriggerShapeSynchPointIndex());
trigger_shape_s * shape = &ec2.triggerShape;
+ event_trigger_position_s position;
+ assertEqualsM("globalTriggerAngleOffset", 0, ec->globalTriggerAngleOffset);
+ findTriggerPosition(ec, shape, &position, 0);
+ assertTriggerPosition(&position, 0, 0);
+
+ findTriggerPosition(ec, shape, &position, 200);
+ assertTriggerPosition(&position, 3, 20);
+
+ findTriggerPosition(ec, shape, &position, 360);
+ assertTriggerPosition(&position, 6, 0);
+
+
+ IgnitionEventList *ecl = &ec2.engineEventConfiguration.ignitionEvents[0];
+ assertEqualsM("ignition events size", 6, ecl->size);
+ assertEqualsM("event index", 0, ecl->events[0].dwellPosition.eventIndex);
+ assertEquals(0, ecl->events[0].dwellPosition.angleOffset);
+
+ assertEqualsM("event index", 10, ecl->events[5].dwellPosition.eventIndex);
+ assertEquals(0, ecl->events[5].dwellPosition.angleOffset);
+
+ TriggerState state;
+
assertFalseM("shaft_is_synchronized", state.shaft_is_synchronized);
int r = 10;
- processTriggerEvent(&state, shape, &ec->triggerConfig, SHAFT_PRIMARY_DOWN, r);
+ state.decodeTriggerEvent(shape, &ec->triggerConfig, SHAFT_PRIMARY_DOWN, r);
assertFalseM("shaft_is_synchronized", state.shaft_is_synchronized); // still no synchronization
- processTriggerEvent(&state, shape, &ec->triggerConfig, SHAFT_PRIMARY_UP, ++r);
+ state.decodeTriggerEvent(shape, &ec->triggerConfig, SHAFT_PRIMARY_UP, ++r);
assertTrue(state.shaft_is_synchronized); // first signal rise synchronize
- assertEquals(0, state.current_index);
- processTriggerEvent(&state, shape, &ec->triggerConfig, SHAFT_PRIMARY_DOWN, r++);
- assertEquals(1, state.current_index);
+ assertEquals(0, state.getCurrentIndex());
+ state.decodeTriggerEvent(shape, &ec->triggerConfig, SHAFT_PRIMARY_DOWN, r++);
+ assertEquals(1, state.getCurrentIndex());
for (int i = 2; i < 10;) {
- processTriggerEvent(&state, shape, &ec->triggerConfig, SHAFT_PRIMARY_UP, r++);
- assertEqualsM("even", i++, state.current_index);
- processTriggerEvent(&state, shape, &ec->triggerConfig, SHAFT_PRIMARY_DOWN, r++);
- assertEqualsM("odd", i++, state.current_index);
+ state.decodeTriggerEvent(shape, &ec->triggerConfig, SHAFT_PRIMARY_UP, r++);
+ assertEqualsM("even", i++, state.getCurrentIndex());
+ state.decodeTriggerEvent(shape, &ec->triggerConfig, SHAFT_PRIMARY_DOWN, r++);
+ assertEqualsM("odd", i++, state.getCurrentIndex());
}
- processTriggerEvent(&state, shape, &ec->triggerConfig, SHAFT_PRIMARY_UP, r++);
- assertEquals(10, state.current_index);
+ state.decodeTriggerEvent(shape, &ec->triggerConfig, SHAFT_PRIMARY_UP, r++);
+ assertEquals(10, state.getCurrentIndex());
- processTriggerEvent(&state, shape, &ec->triggerConfig, SHAFT_PRIMARY_DOWN, r++);
- assertEquals(11, state.current_index);
+ state.decodeTriggerEvent(shape, &ec->triggerConfig, SHAFT_PRIMARY_DOWN, r++);
+ assertEquals(11, state.getCurrentIndex());
- processTriggerEvent(&state, shape, &ec->triggerConfig, SHAFT_PRIMARY_UP, r++);
- assertEquals(0, state.current_index); // new revolution
+ state.decodeTriggerEvent(shape, &ec->triggerConfig, SHAFT_PRIMARY_UP, r++);
+ assertEquals(0, state.getCurrentIndex()); // new revolution
assertEqualsM("running dwell", 0.5, getSparkDwellMsT(ec, 2000));
}
@@ -149,7 +181,8 @@ void testFordAspire(void) {
persistent_config_s persistentConfig;
engine_configuration_s *ec = &persistentConfig.engineConfiguration;
engine_configuration2_s ec2;
- resetConfigurationExt(FORD_ASPIRE_1996, ec, &ec2, &persistentConfig.boardConfiguration);
+ resetConfigurationExt(NULL, FORD_ASPIRE_1996, ec, &ec2, &persistentConfig.engineConfiguration.bc);
+ assertEquals(4, ec2.triggerShape.getTriggerShapeSynchPointIndex());
assertEquals(800, ec->fuelRpmBins[0]);
assertEquals(7000, ec->fuelRpmBins[15]);
@@ -169,8 +202,8 @@ void testMazda323(void) {
persistent_config_s persistentConfig;
engine_configuration_s *ec = &persistentConfig.engineConfiguration;
engine_configuration2_s ec2;
- resetConfigurationExt(MAZDA_323, ec, &ec2, &persistentConfig.boardConfiguration);
-
+ resetConfigurationExt(NULL, MAZDA_323, ec, &ec2, &persistentConfig.engineConfiguration.bc);
+ assertEquals(0, ec2.triggerShape.getTriggerShapeSynchPointIndex());
}
void testMazdaMianaNbDecoder(void) {
@@ -179,56 +212,126 @@ void testMazdaMianaNbDecoder(void) {
persistent_config_s persistentConfig;
engine_configuration_s *ec = &persistentConfig.engineConfiguration;
engine_configuration2_s ec2;
- resetConfigurationExt(MAZDA_MIATA_NB, ec, &ec2, &persistentConfig.boardConfiguration);
+ resetConfigurationExt(NULL, MAZDA_MIATA_NB, ec, &ec2, &persistentConfig.engineConfiguration.bc);
+ assertEquals(11, ec2.triggerShape.getTriggerShapeSynchPointIndex());
- trigger_state_s state;
- clearTriggerState(&state);
+ TriggerState state;
trigger_shape_s * shape = &ec2.triggerShape;
int a = 0;
- processTriggerEvent(&state, shape, &ec->triggerConfig, SHAFT_PRIMARY_DOWN, a + 20);
+ state.decodeTriggerEvent(shape, &ec->triggerConfig, SHAFT_PRIMARY_DOWN, a + 20);
assertFalseM("0a shaft_is_synchronized", state.shaft_is_synchronized);
- processTriggerEvent(&state, shape, &ec->triggerConfig, SHAFT_PRIMARY_UP, a + 340);
+ state.decodeTriggerEvent(shape, &ec->triggerConfig, SHAFT_PRIMARY_UP, a + 340);
assertFalseM("0b shaft_is_synchronized", state.shaft_is_synchronized);
- processTriggerEvent(&state, shape, &ec->triggerConfig, SHAFT_PRIMARY_DOWN, a + 360);
+ state.decodeTriggerEvent(shape, &ec->triggerConfig, SHAFT_PRIMARY_DOWN, a + 360);
assertFalseM("0c shaft_is_synchronized", state.shaft_is_synchronized);
- processTriggerEvent(&state, shape, &ec->triggerConfig, SHAFT_PRIMARY_UP, a + 380);
+ state.decodeTriggerEvent(shape, &ec->triggerConfig, SHAFT_PRIMARY_UP, a + 380);
assertFalseM("0d shaft_is_synchronized", state.shaft_is_synchronized);
- processTriggerEvent(&state, shape, &ec->triggerConfig, SHAFT_PRIMARY_DOWN, a + 400);
+ state.decodeTriggerEvent(shape, &ec->triggerConfig, SHAFT_PRIMARY_DOWN, a + 400);
assertTrueM("0e shaft_is_synchronized", state.shaft_is_synchronized);
- processTriggerEvent(&state, shape, &ec->triggerConfig, SHAFT_PRIMARY_UP, a + 720);
+ state.decodeTriggerEvent(shape, &ec->triggerConfig, SHAFT_PRIMARY_UP, a + 720);
assertTrueM("0f shaft_is_synchronized", state.shaft_is_synchronized);
a = 720;
- processTriggerEvent(&state, shape, &ec->triggerConfig, SHAFT_PRIMARY_DOWN, a + 20);
+ state.decodeTriggerEvent(shape, &ec->triggerConfig, SHAFT_PRIMARY_DOWN, a + 20);
assertTrueM("1a shaft_is_synchronized", state.shaft_is_synchronized);
- processTriggerEvent(&state, shape, &ec->triggerConfig, SHAFT_PRIMARY_UP, a + 340);
+ state.decodeTriggerEvent(shape, &ec->triggerConfig, SHAFT_PRIMARY_UP, a + 340);
assertTrueM("1b shaft_is_synchronized", state.shaft_is_synchronized);
- processTriggerEvent(&state, shape, &ec->triggerConfig, SHAFT_PRIMARY_DOWN, a + 360);
+ state.decodeTriggerEvent(shape, &ec->triggerConfig, SHAFT_PRIMARY_DOWN, a + 360);
assertTrueM("1c shaft_is_synchronized", state.shaft_is_synchronized);
- processTriggerEvent(&state, shape, &ec->triggerConfig, SHAFT_PRIMARY_UP, a + 380);
+ state.decodeTriggerEvent(shape, &ec->triggerConfig, SHAFT_PRIMARY_UP, a + 380);
assertTrueM("1d shaft_is_synchronized", state.shaft_is_synchronized);
- assertEquals(5, state.current_index);
+ assertEquals(5, state.getCurrentIndex());
- processTriggerEvent(&state, shape, &ec->triggerConfig, SHAFT_PRIMARY_DOWN, a + 400);
+ state.decodeTriggerEvent(shape, &ec->triggerConfig, SHAFT_PRIMARY_DOWN, a + 400);
assertTrueM("1e shaft_is_synchronized", state.shaft_is_synchronized);
- assertEquals(0, state.current_index);
+ assertEquals(0, state.getCurrentIndex());
- processTriggerEvent(&state, shape, &ec->triggerConfig, SHAFT_PRIMARY_UP, a + 720);
+ state.decodeTriggerEvent(shape, &ec->triggerConfig, SHAFT_PRIMARY_UP, a + 720);
assertTrueM("1f shaft_is_synchronized", state.shaft_is_synchronized);
+ event_trigger_position_s position;
+ assertEqualsM("globalTriggerAngleOffset", 276, ec->globalTriggerAngleOffset);
+ findTriggerPosition(ec, shape, &position, 0);
+ assertTriggerPosition(&position, 7, 46);
+
+ findTriggerPosition(ec, shape, &position, 180);
+ assertTriggerPosition(&position, 13, 46);
+
+ findTriggerPosition(ec, shape, &position, 360);
+ assertTriggerPosition(&position, 17, 46);
+
+ findTriggerPosition(ec, shape, &position, 444);
+ assertTriggerPosition(&position, 0, 0);
+
+ findTriggerPosition(ec, shape, &position, 444.1);
+ assertTriggerPosition(&position, 0, 0.1);
+
+ findTriggerPosition(ec, shape, &position, 445);
+ assertTriggerPosition(&position, 0, 1);
+
+ findTriggerPosition(ec, shape, &position, 494);
+ assertTriggerPosition(&position, 3, 0);
+
+ findTriggerPosition(ec, shape, &position, 719);
+ assertTriggerPosition(&position, 7, 45);
+
+ ec->globalTriggerAngleOffset = 0;
+ findTriggerPosition(ec, shape, &position, 0);
+ assertTriggerPosition(&position, 0, 0);
+
+ ec->globalTriggerAngleOffset = 10;
+ findTriggerPosition(ec, shape, &position, 0);
+ assertTriggerPosition(&position, 0, 10);
+
+ findTriggerPosition(ec, shape, &position, -10);
+ assertTriggerPosition(&position, 0, 0);
+}
+
+static void testCitroen(void) {
+ printf("*************************************************** testCitroen\r\n");
+
+ persistent_config_s persistentConfig;
+ engine_configuration_s *ec = &persistentConfig.engineConfiguration;
+ engine_configuration2_s ec2;
+ assertEquals(0, ec2.triggerShape.getTriggerShapeSynchPointIndex());
+
+ resetConfigurationExt(NULL, CITROEN_TU3JP, ec, &ec2, &persistentConfig.engineConfiguration.bc);
+
+ assertEquals(0, ec2.triggerShape.getTriggerShapeSynchPointIndex());
+}
+
+static void testRoverV8(void) {
+ printf("*************************************************** testRoverV8\r\n");
+
+ persistent_config_s persistentConfig;
+ engine_configuration_s *ec = &persistentConfig.engineConfiguration;
+ engine_configuration2_s ec2;
+ resetConfigurationExt(NULL, ROVER_V8, ec, &ec2, &persistentConfig.engineConfiguration.bc);
+
+ assertEquals(0, ec2.triggerShape.getTriggerShapeSynchPointIndex());
+}
+
+static void testMiniCooper(void) {
+ printf("*************************************************** testMiniCooper\r\n");
+
+ persistent_config_s persistentConfig;
+ engine_configuration_s *ec = &persistentConfig.engineConfiguration;
+ engine_configuration2_s ec2;
+ resetConfigurationExt(NULL, MINI_COOPER_R50, ec, &ec2, &persistentConfig.engineConfiguration.bc);
+
}
-void testFordEscortGt(void) {
+static void testFordEscortGt(void) {
printf("*************************************************** testFordEscortGt\r\n");
persistent_config_s persistentConfig;
engine_configuration_s *ec = &persistentConfig.engineConfiguration;
engine_configuration2_s ec2;
- resetConfigurationExt(FORD_ESCORT_GT, ec, &ec2, &persistentConfig.boardConfiguration);
+ resetConfigurationExt(NULL, FORD_ESCORT_GT, ec, &ec2, &persistentConfig.engineConfiguration.bc);
}
void testGY6_139QMB(void) {
@@ -237,25 +340,127 @@ void testGY6_139QMB(void) {
persistent_config_s persistentConfig;
engine_configuration_s *ec = &persistentConfig.engineConfiguration;
engine_configuration2_s ec2;
- resetConfigurationExt(GY6_139QMB, ec, &ec2, &persistentConfig.boardConfiguration);
+ resetConfigurationExt(NULL, GY6_139QMB, ec, &ec2, &persistentConfig.engineConfiguration.bc);
- trigger_state_s state;
- clearTriggerState(&state);
+ TriggerState state;
assertFalseM("shaft_is_synchronized", state.shaft_is_synchronized);
trigger_shape_s * shape = &ec2.triggerShape;
assertFalseM("shaft_is_synchronized", state.shaft_is_synchronized);
- assertEquals(0, state.current_index);
+ assertEquals(0, state.getCurrentIndex());
int now = 0;
- processTriggerEvent(&state, shape, &ec->triggerConfig, SHAFT_PRIMARY_UP, now++);
+ state.decodeTriggerEvent(shape, &ec->triggerConfig, SHAFT_PRIMARY_UP, now++);
assertTrueM("shaft_is_synchronized", state.shaft_is_synchronized);
- assertEquals(0, state.current_index);
+ assertEquals(0, state.getCurrentIndex());
- processTriggerEvent(&state, shape, &ec->triggerConfig, SHAFT_PRIMARY_DOWN, now++);
+ state.decodeTriggerEvent(shape, &ec->triggerConfig, SHAFT_PRIMARY_DOWN, now++);
assertTrueM("shaft_is_synchronized", state.shaft_is_synchronized);
- assertEquals(1, state.current_index);
+ assertEquals(1, state.getCurrentIndex());
+}
+
+extern EventQueue schedulingQueue;
+
+static void testRpmCalculator(void) {
+ printf("*************************************************** testRpmCalculator\r\n");
+
+ EngineTestHelper eth(FORD_INLINE_6_1995);
+
+ engine_configuration_s *ec = ð.persistentConfig.engineConfiguration;
+
+ engine_configuration2_s *ec2 = ð.ec2;
+
+ ec->triggerConfig.totalToothCount = 8;
+ eth.initTriggerShapeAndRpmCalculator();
+
+ configuration_s configuration = { ec, ec2 };
+ timeNow = 0;
+ assertEquals(0, eth.rpmState.rpm());
+
+ eth.fireTriggerEvents();
+ assertEqualsM("RPM", 1500, eth.rpmState.rpm());
+
+ assertEqualsM("index #1", 15, eth.triggerCentral.triggerState.getCurrentIndex());
+
+
+ static MainTriggerCallback triggerCallbackInstance;
+ triggerCallbackInstance.init(ec, ec2);
+ eth.triggerCentral.addEventListener((ShaftPositionListener)&onTriggerEvent, "main loop", &triggerCallbackInstance);
+
+ engine.rpmCalculator = ð.rpmState;
+ prepareTimingMap();
+
+ timeNow += 5000; // 5ms
+ eth.triggerCentral.handleShaftSignal(&configuration, SHAFT_PRIMARY_UP, timeNow);
+ assertEqualsM("index #2", 0, eth.triggerCentral.triggerState.getCurrentIndex());
+ assertEqualsM("queue size", 2, schedulingQueue.size());
+ assertEqualsM("ev 1", 695000, schedulingQueue.getForUnitText(0)->momentUs);
+ assertEqualsM("ev 2", 245000, schedulingQueue.getForUnitText(1)->momentUs);
+ schedulingQueue.clear();
+
+ timeNow += 5000;
+ eth.triggerCentral.handleShaftSignal(&configuration, SHAFT_PRIMARY_DOWN, timeNow);
+ timeNow += 5000; // 5ms
+ eth.triggerCentral.handleShaftSignal(&configuration, SHAFT_PRIMARY_UP, timeNow);
+ timeNow += 5000;
+ eth.triggerCentral.handleShaftSignal(&configuration, SHAFT_PRIMARY_DOWN, timeNow);
+ assertEqualsM("index #3", 3, eth.triggerCentral.triggerState.getCurrentIndex());
+ assertEqualsM("queue size 3", 4, schedulingQueue.size());
+ assertEquals(258333, schedulingQueue.getForUnitText(0)->momentUs);
+ assertEquals(257833, schedulingQueue.getForUnitText(1)->momentUs);
+ assertEqualsM("ev 5", 708333, schedulingQueue.getForUnitText(2)->momentUs);
+ assertEqualsM("3/3", 258333, schedulingQueue.getForUnitText(3)->momentUs);
+ schedulingQueue.clear();
+
+ timeNow += 5000;
+ eth.triggerCentral.handleShaftSignal(&configuration, SHAFT_PRIMARY_DOWN, timeNow);
+ timeNow += 5000; // 5ms
+ eth.triggerCentral.handleShaftSignal(&configuration, SHAFT_PRIMARY_UP, timeNow);
+ timeNow += 5000; // 5ms
+ eth.triggerCentral.handleShaftSignal(&configuration, SHAFT_PRIMARY_UP, timeNow);
+ assertEqualsM("index #4", 6, eth.triggerCentral.triggerState.getCurrentIndex());
+ assertEqualsM("queue size 4", 4, schedulingQueue.size());
+ assertEqualsM("4/0", 271666, schedulingQueue.getForUnitText(0)->momentUs);
+ schedulingQueue.clear();
+
+ timeNow += 5000;
+ eth.triggerCentral.handleShaftSignal(&configuration, SHAFT_PRIMARY_DOWN, timeNow);
+ assertEqualsM("queue size 5", 1, schedulingQueue.size());
+ assertEqualsM("5/1", 284500, schedulingQueue.getForUnitText(0)->momentUs);
+ schedulingQueue.clear();
+
+ timeNow += 5000; // 5ms
+ eth.triggerCentral.handleShaftSignal(&configuration, SHAFT_PRIMARY_UP, timeNow);
+ assertEqualsM("queue size 6", 3, schedulingQueue.size());
+ assertEqualsM("6/0", 285000, schedulingQueue.getForUnitText(0)->momentUs);
+ assertEqualsM("6/1", 735000, schedulingQueue.getForUnitText(1)->momentUs);
+ assertEqualsM("6/0", 285000, schedulingQueue.getForUnitText(2)->momentUs);
+ schedulingQueue.clear();
+
+ timeNow += 5000;
+ eth.triggerCentral.handleShaftSignal(&configuration, SHAFT_PRIMARY_DOWN, timeNow);
+ assertEqualsM("queue size 7", 0, schedulingQueue.size());
+ schedulingQueue.clear();
+
+ timeNow += 5000; // 5ms
+ eth.triggerCentral.handleShaftSignal(&configuration, SHAFT_PRIMARY_UP, timeNow);
+ assertEqualsM("queue size 8", 4, schedulingQueue.size());
+ assertEqualsM("8/0", 298333, schedulingQueue.getForUnitText(0)->momentUs);
+ assertEqualsM("8/1", 297833, schedulingQueue.getForUnitText(1)->momentUs);
+ assertEqualsM("8/2", 748333, schedulingQueue.getForUnitText(2)->momentUs);
+ assertEqualsM("8/3", 298333, schedulingQueue.getForUnitText(3)->momentUs);
+ schedulingQueue.clear();
+
+ timeNow += 5000;
+ eth.triggerCentral.handleShaftSignal(&configuration, SHAFT_PRIMARY_DOWN, timeNow);
+ assertEqualsM("queue size 9", 0, schedulingQueue.size());
+ schedulingQueue.clear();
+
+ timeNow += 5000; // 5ms
+ eth.triggerCentral.handleShaftSignal(&configuration, SHAFT_PRIMARY_UP, timeNow);
+ assertEqualsM("queue size 10", 0, schedulingQueue.size());
+ schedulingQueue.clear();
}
void testTriggerDecoder(void) {
@@ -263,8 +468,8 @@ void testTriggerDecoder(void) {
engine_configuration2_s ec2;
- initializeSkippedToothTriggerShapeExt(&ec2, 2, 0);
- assertEqualsM("shape size", ec2.triggerShape.size, 4);
+ initializeSkippedToothTriggerShapeExt(&ec2, 2, 0, FOUR_STROKE_CAM_SENSOR);
+ assertEqualsM("shape size", ec2.triggerShape.getSize(), 4);
assertEquals(ec2.triggerShape.wave.switchTimes[0], 0.25);
assertEquals(ec2.triggerShape.wave.switchTimes[1], 0.5);
assertEquals(ec2.triggerShape.wave.switchTimes[2], 0.75);
@@ -276,7 +481,11 @@ void testTriggerDecoder(void) {
testMazdaMianaNbDecoder();
testGY6_139QMB();
testFordEscortGt();
+ testMiniCooper();
+ testRoverV8();
+ testCitroen();
-// testMazda323();
+ testMazda323();
+
+ testRpmCalculator();
}
-
diff --git a/unit_tests/test_util.cpp b/unit_tests/test_util.cpp
index b62b9ec7dd..e8a4c4424e 100644
--- a/unit_tests/test_util.cpp
+++ b/unit_tests/test_util.cpp
@@ -13,27 +13,40 @@
#include "histogram.h"
#include "malfunction_central.h"
-#include "eficonsole_logic.h"
+#include "cli_registry.h"
#include "nmea.h"
#include "efilib2.h"
+#include "crc.h"
+#include "fl_stack.h"
+
+void testCrc(void) {
+ assertEquals(4, efiRound(4.4, 1));
+ assertEquals(1.2, efiRound(1.2345, 0.1));
+
+ print("*************************************** testCrc\r\n");
+
+ const char * A = "A";
+
+ assertEqualsM("crc8", 168, calc_crc((const crc_t *)A, 1));
+ int c = crc32(A, 1);
+ printf("crc32(A)=%x\r\n", c);
+ assertEqualsM("crc32", 0xd3d99e8b, crc32(A, 1));
+}
static cyclic_buffer sb;
-
void testOverflow64Counter(void) {
print("*************************************** testOverflow64Counter\r\n");
Overflow64Counter o;
- assertEquals(0, o.get());
- o.offer(10);
- assertEquals(10, o.get());
+ assertEquals(0, o.get(0, true));
+ assertEquals(10, o.get(10, true));
- o.offer(20);
- assertEquals(20, o.get());
+ assertEquals(20, o.get(20, true));
- o.offer(0); // overflow
- assertEquals(4294967296, o.get());
+ // overflow
+ assertEquals(4294967296, o.get(0, true));
}
void testCyclicBuffer(void) {
@@ -292,3 +305,11 @@ void testConsoleLogic(void) {
//addConsoleActionSSS("GPS", testGpsParser);
}
+void testFLStack(void) {
+ print("******************************************* testFLStack\r\n");
+
+ FLStack stack;
+ assertEquals(0, stack.size());
+
+
+}
diff --git a/unit_tests/test_util.h b/unit_tests/test_util.h
index 0bd3c24cb6..d47f0e9caf 100644
--- a/unit_tests/test_util.h
+++ b/unit_tests/test_util.h
@@ -13,15 +13,14 @@ extern "C"
{
#endif /* __cplusplus */
-
-
+void testCrc(void);
void testCyclicBuffer(void);
void testOverflow64Counter(void);
void testHistogram(void);
void testMalfunctionCentral(void);
void testConsoleLogic(void);
void testGpsParser(void);
-
+void testFLStack(void);
#ifdef __cplusplus
}