diff --git a/firmware/.cproject b/firmware/.cproject
index e01fca04ca..7979bd8af7 100644
--- a/firmware/.cproject
+++ b/firmware/.cproject
@@ -78,7 +78,7 @@
-
+
-
+
@@ -303,10 +304,10 @@
-
-
+
diff --git a/firmware/Makefile b/firmware/Makefile
index ccf2bc06e4..7fdc736f98 100644
--- a/firmware/Makefile
+++ b/firmware/Makefile
@@ -196,6 +196,7 @@ INCDIR = $(PORTINC) $(KERNINC) $(TESTINC) \
hw_layer/serial_over_usb \
hw_layer/algo \
hw_layer/lcd \
+ hw_layer/stm32f4 \
emulation \
emulation/hw_layer \
emulation/test \
diff --git a/firmware/config/boards/arro_board.h b/firmware/config/boards/arro_board.h
index 55e7c0327f..ffd5b0fb83 100644
--- a/firmware/config/boards/arro_board.h
+++ b/firmware/config/boards/arro_board.h
@@ -220,14 +220,10 @@
#define EFI_SIGNAL_EXECUTOR_ONE_TIMER TRUE
#define EFI_SIGNAL_EXECUTOR_HW_TIMER FALSE
-
// USART1 -> check defined STM32_SERIAL_USE_USART1
// For GPS we have USART1. We can start with PB7 USART1_RX and PB6 USART1_TX
#define GPS_SERIAL_DEVICE &SD1
#define GPS_SERIAL_SPEED 38400
-#define GPS_PORT GPIOB
-#define GPS_SERIAL_TX_PIN 6
-#define GPS_SERIAL_RX_PIN 7
#define CONSOLE_MODE_SWITCH_PORT GPIOB
#define CONSOLE_MODE_SWITCH_PIN 1
diff --git a/firmware/config/efifeatures.h b/firmware/config/efifeatures.h
index 0ba4b9e9bf..06bee97a45 100644
--- a/firmware/config/efifeatures.h
+++ b/firmware/config/efifeatures.h
@@ -73,7 +73,7 @@
#define EFI_HD44780_LCD TRUE
-#define EFI_IDLE_CONTROL FALSE
+#define EFI_IDLE_CONTROL TRUE
#define EFI_FUEL_PUMP TRUE
@@ -124,9 +124,6 @@
#define EFI_UART_GPS TRUE
//#define EFI_UART_GPS FALSE
-//#define EFI_IDLE_CONTROL TRUE
-#define EFI_IDLE_CONTROL FALSE
-
//#define EFI_ELECTRONIC_THROTTLE_BODY TRUE
#define EFI_ELECTRONIC_THROTTLE_BODY FALSE
diff --git a/firmware/config/engines/engines.mk b/firmware/config/engines/engines.mk
index 737ca5ae24..323b3a343e 100644
--- a/firmware/config/engines/engines.mk
+++ b/firmware/config/engines/engines.mk
@@ -16,4 +16,5 @@ ENGINES_SRC_CPP = $(PROJECT_DIR)/config/engines/ford_aspire.cpp \
$(PROJECT_DIR)/config/engines/GY6_139QMB.cpp \
$(PROJECT_DIR)/config/engines/rover_v8.cpp \
$(PROJECT_DIR)/config/engines/mazda_323.cpp \
- $(PROJECT_DIR)/config/engines/saturn_ion.cpp
\ No newline at end of file
+ $(PROJECT_DIR)/config/engines/saturn_ion.cpp \
+ $(PROJECT_DIR)/config/engines/mitsubishi.cpp
\ No newline at end of file
diff --git a/firmware/config/engines/ford_1995_inline_6.cpp b/firmware/config/engines/ford_1995_inline_6.cpp
index aa70e30818..c74b2db9d8 100644
--- a/firmware/config/engines/ford_1995_inline_6.cpp
+++ b/firmware/config/engines/ford_1995_inline_6.cpp
@@ -48,10 +48,10 @@ void setFordInline6(engine_configuration_s *engineConfiguration, board_configura
engineConfiguration->globalTriggerAngleOffset = 0;
engineConfiguration->ignitionOffset = 13;
- setThermistorConfiguration(&engineConfiguration->cltThermistorConf, -10, 160310, 60, 7700, 120.00, 1180);
+ setThermistorConfiguration(&engineConfiguration->cltThermistorConf, -10.0, 160310.0, 60.0, 7700.0, 120.0, 1180.0);
engineConfiguration->cltThermistorConf.bias_resistor = 2700;
- setThermistorConfiguration(&engineConfiguration->iatThermistorConf, -10, 160310, 60, 7700, 120.00, 1180);
+ setThermistorConfiguration(&engineConfiguration->iatThermistorConf, -10.0, 160310.0, 60.0, 7700.0, 120.0, 1180.0);
engineConfiguration->iatThermistorConf.bias_resistor = 2700;
// 12ch analog board pinout:
@@ -75,15 +75,15 @@ void setFordInline6(engine_configuration_s *engineConfiguration, board_configura
boardConfiguration->adcHwChannelEnabled[15] = ADC_FAST;
- engineConfiguration->tpsAdcChannel = 4;
- engineConfiguration->iatAdcChannel = 2;
- engineConfiguration->cltAdcChannel = 1;
- engineConfiguration->afrSensor.afrAdcChannel = 11;
+ engineConfiguration->tpsAdcChannel = EFI_ADC_4;
+ engineConfiguration->iatAdcChannel = EFI_ADC_2;
+ engineConfiguration->cltAdcChannel = EFI_ADC_1;
+ engineConfiguration->afrSensor.afrAdcChannel = EFI_ADC_11;
engineConfiguration->map.sensor.sensorType = MT_MPX4250;
- engineConfiguration->map.sensor.hwChannel = 15;
+ engineConfiguration->map.sensor.hwChannel = EFI_ADC_15;
engineConfiguration->baroSensor.sensorType = MT_MPX4250;
- engineConfiguration->baroSensor.hwChannel = 7;
+ engineConfiguration->baroSensor.hwChannel = EFI_ADC_7;
// 6 channel output board
// output 1 is PB9
@@ -105,10 +105,10 @@ void setFordInline6(engine_configuration_s *engineConfiguration, board_configura
// engineConfiguration->vBattAdcChannel = 0; //
// engineConfiguration->mafAdcChannel = 1;
- boardConfiguration->primaryTriggerInputPin = GPIOA_8;
- boardConfiguration->secondaryTriggerInputPin = GPIOA_5;
- boardConfiguration->primaryLogicAnalyzerPin = GPIOC_6;
- boardConfiguration->secondaryLogicAnalyzerPin = GPIOE_7;
+ boardConfiguration->triggerInputPins[0] = GPIOA_8;
+ boardConfiguration->triggerInputPins[1] = GPIOA_5;
+ boardConfiguration->logicAnalyzerPins[0] = GPIOC_6;
+ boardConfiguration->logicAnalyzerPins[1] = GPIOE_7;
}
diff --git a/firmware/config/engines/ford_aspire.cpp b/firmware/config/engines/ford_aspire.cpp
index 1bfee66739..5d6e71b1eb 100644
--- a/firmware/config/engines/ford_aspire.cpp
+++ b/firmware/config/engines/ford_aspire.cpp
@@ -90,6 +90,11 @@ void setFordAspireEngineConfiguration(engine_configuration_s *engineConfiguratio
engineConfiguration->rpmHardLimit = 7000;
+ /**
+ * 18K Ohm @ -20C
+ * 2.1K Ohm @ 24C
+ * 1K Ohm @ 49C
+ */
setThermistorConfiguration(&engineConfiguration->cltThermistorConf, -20, 18000, 23.8889, 2100, 48.8889, 1000);
engineConfiguration->cltThermistorConf.bias_resistor = 3300; // that's my custom resistor value!
@@ -112,9 +117,12 @@ void setFordAspireEngineConfiguration(engine_configuration_s *engineConfiguratio
engineConfiguration->injectionOffset = 59;
setDefaultMaps(engineConfiguration);
+ // set_cranking_rpm 550
engineConfiguration->crankingSettings.crankingRpm = 550;
+ // set_cranking_charge_angle 70
engineConfiguration->crankingChargeAngle = 70;
- engineConfiguration->crankingTimingAngle = 26 + 11;
+ // set_cranking_timing_angle 37
+ engineConfiguration->crankingTimingAngle = 37;
setSingleCoilDwell(engineConfiguration);
engineConfiguration->ignitionMode = IM_ONE_COIL;
@@ -140,11 +148,11 @@ void setFordAspireEngineConfiguration(engine_configuration_s *engineConfiguratio
// Frankenstein analog input #12: adc
- engineConfiguration->tpsAdcChannel = 3;
- engineConfiguration->vBattAdcChannel = 0;
- engineConfiguration->map.sensor.hwChannel = 4;
- engineConfiguration->mafAdcChannel = 1;
- engineConfiguration->cltAdcChannel = 11;
+ engineConfiguration->tpsAdcChannel = EFI_ADC_3;
+ engineConfiguration->vBattAdcChannel = EFI_ADC_0;
+ engineConfiguration->map.sensor.hwChannel = EFI_ADC_4;
+ engineConfiguration->mafAdcChannel = EFI_ADC_1;
+ engineConfiguration->cltAdcChannel = EFI_ADC_11;
// engineConfiguration->iatAdcChannel =
engineConfiguration->map.sensor.sensorType = MT_DENSO183;
diff --git a/firmware/config/engines/ford_escort_gt.cpp b/firmware/config/engines/ford_escort_gt.cpp
index 531b033f46..a3ac21f6bf 100644
--- a/firmware/config/engines/ford_escort_gt.cpp
+++ b/firmware/config/engines/ford_escort_gt.cpp
@@ -40,9 +40,9 @@ void setFordEscortGt(engine_configuration_s *engineConfiguration, board_configur
// Frankenstein analog input #10: adc
// Frankenstein analog input #11: adc
// Frankenstein analog input #12: adc
- engineConfiguration->mafAdcChannel = 1;
- engineConfiguration->tpsAdcChannel = 3;
- engineConfiguration->cltAdcChannel = 11;
+ engineConfiguration->mafAdcChannel = EFI_ADC_1;
+ engineConfiguration->tpsAdcChannel = EFI_ADC_3;
+ engineConfiguration->cltAdcChannel = EFI_ADC_11;
// Frankenstein: high side #1 is PE8
diff --git a/firmware/config/engines/honda_accord.cpp b/firmware/config/engines/honda_accord.cpp
index 7e3979a0d8..2869caadab 100644
--- a/firmware/config/engines/honda_accord.cpp
+++ b/firmware/config/engines/honda_accord.cpp
@@ -6,19 +6,26 @@
* http://rusefi.com/forum/viewtopic.php?f=3&t=621
*
* engine_type 6
+ * engine_type 17
*
* @date Jan 12, 2014
* @author Andrey Belomutskiy, (c) 2012-2014
*/
#include "main.h"
-#include "engine_configuration.h"
#include "trigger_decoder.h"
+#include "thermistors.h"
+#include "honda_accord.h"
-void setHondaAccordConfiguration(engine_configuration_s *engineConfiguration, board_configuration_s *boardConfiguration) {
- engineConfiguration->engineType = HONDA_ACCORD;
+static void setHondaAccordConfigurationCommon(engine_configuration_s *engineConfiguration, board_configuration_s *boardConfiguration) {
+ engineConfiguration->map.sensor.sensorType = MT_DENSO183;
- engineConfiguration->map.sensor.sensorType = MT_HONDA3BAR;
+ engineConfiguration->ignitionMode = IM_ONE_COIL;
+ engineConfiguration->injectionMode = IM_BATCH;
+
+ engineConfiguration->idleMode = IM_MANUAL;
+
+ engineConfiguration->HD44780height = 4;
engineConfiguration->cylindersCount = 4;
engineConfiguration->displacement = 2.156;
@@ -26,9 +33,9 @@ void setHondaAccordConfiguration(engine_configuration_s *engineConfiguration, bo
// Keihin 06164-P0A-A00
engineConfiguration->injectorFlow = 248;
-
- engineConfiguration->algorithm = LM_SPEED_DENSITY;
-
+// engineConfiguration->algorithm = LM_SPEED_DENSITY;
+ // I want to start with a simple Alpha-N
+ engineConfiguration->algorithm = LM_TPS;
engineConfiguration->crankingSettings.coolantTempMaxC = 65; // 8ms at 65C
engineConfiguration->crankingSettings.fuelAtMaxTempMs = 8;
@@ -36,24 +43,158 @@ void setHondaAccordConfiguration(engine_configuration_s *engineConfiguration, bo
engineConfiguration->crankingSettings.coolantTempMinC = 0; // 20ms at 0C
engineConfiguration->crankingSettings.fuelAtMinTempMs = 15;
+ /**
+ * 18K Ohm @ -20C
+ * 2.1K Ohm @ 24C
+ * 100 Ohm @ 120C
+ */
+ setThermistorConfiguration(&engineConfiguration->cltThermistorConf, -20.0, 18000.0, 23.8889, 2100.0, 120.0, 100.0);
+ engineConfiguration->cltThermistorConf.bias_resistor = 1500; // same as OEM ECU
+ setThermistorConfiguration(&engineConfiguration->iatThermistorConf, -20.0, 18000.0, 23.8889, 2100.0, 120.0, 100.0);
+ engineConfiguration->iatThermistorConf.bias_resistor = 1500; // same as OEM ECU
+
+ // set_cranking_charge_angle 35
+ engineConfiguration->crankingChargeAngle = 35;
+ // set_cranking_timing_angle 0
+ engineConfiguration->crankingTimingAngle = 0;
+
+ // set_global_trigger_offset_angle 34
+ engineConfiguration->globalTriggerAngleOffset = 34;
+
+ // set_rpm_hard_limit 4000
+ engineConfiguration->rpmHardLimit = 4000; // yes, 4k. let's play it safe for now
+ // set_cranking_rpm 2000
+ engineConfiguration->crankingSettings.crankingRpm = 600;
+
+
+ // set_ignition_offset 350
+// engineConfiguration->ignitionOffset = 350;
+ // set_injection_offset 510
+// engineConfiguration->injectionOffset = 510;
+
+
+ /**
+ * ADC inputs:
+ *
+ * Inp1/ADC12 PC2: CLT
+ * Inp2/ADC11 PC1: AIT/IAT
+ * Inp3/ADC0 PA0: MAP
+ * Inp4/ADC13 PC3: AFR
+ * Inp6/ADC1 PA1: TPS
+ * Inp12/ADC14 PC4: VBatt
+ */
memset(boardConfiguration->adcHwChannelEnabled, 0, sizeof(boardConfiguration->adcHwChannelEnabled));
boardConfiguration->adcHwChannelEnabled[0] = ADC_FAST; // ADC0 - PA0 - MAP
- boardConfiguration->adcHwChannelEnabled[1] = ADC_SLOW;
+ boardConfiguration->adcHwChannelEnabled[1] = ADC_SLOW; // TPS
boardConfiguration->adcHwChannelEnabled[2] = ADC_SLOW;
boardConfiguration->adcHwChannelEnabled[3] = ADC_SLOW;
boardConfiguration->adcHwChannelEnabled[4] = ADC_SLOW;
boardConfiguration->adcHwChannelEnabled[6] = ADC_SLOW;
- boardConfiguration->adcHwChannelEnabled[7] = ADC_SLOW;
- boardConfiguration->adcHwChannelEnabled[11] = ADC_SLOW;
- boardConfiguration->adcHwChannelEnabled[12] = ADC_SLOW;
- boardConfiguration->adcHwChannelEnabled[13] = ADC_SLOW;
+ boardConfiguration->adcHwChannelEnabled[11] = ADC_SLOW; // IAT
+ boardConfiguration->adcHwChannelEnabled[12] = ADC_SLOW; // CLT
+ boardConfiguration->adcHwChannelEnabled[13] = ADC_SLOW; // AFR
+ boardConfiguration->adcHwChannelEnabled[14] = ADC_SLOW; // VBatt
+
+ /**
+ * D14/W10 O2 Sensor
+ */
+ engineConfiguration->afrSensor.afrAdcChannel = EFI_ADC_13;
+
+ /**
+ * VBatt
+ */
+ engineConfiguration->vBattAdcChannel = EFI_ADC_14;
+ engineConfiguration->vbattDividerCoeff = ((float) (8.2 + 33)) / 8.2 * 2;
+
+ // todo engineConfiguration->afrSensor.afrAdcChannel = 14;
- engineConfiguration->map.sensor.sensorType = MT_MPX4250;
- engineConfiguration->map.sensor.hwChannel = 0;
+ /**
+ * MAP D17/W5
+ */
+ engineConfiguration->map.sensor.hwChannel = EFI_ADC_0;
+ /**
+ * TPS D11/W11
+ */
+ engineConfiguration->tpsAdcChannel = EFI_ADC_1;
+
+ /**
+ * IAT D15/W7
+ */
+ engineConfiguration->iatAdcChannel = EFI_ADC_11;
+
+ /**
+ * CLT D13/W9
+ */
+ engineConfiguration->cltAdcChannel = EFI_ADC_12;
+
+
+ /**
+ * Outputs
+ */
+ // Frankenso low out #:
+ // Frankenso low out #:
+ // Frankenso low out #:
+ // Frankenso low out #:
+ // Frankenso low out #5: PE3
+ // Frankenso low out #6: PE4
+ // Frankenso low out #7: PE1 (do not use with discovery!)
+ // Frankenso low out #:
+ // Frankenso low out #9: PB9
+ // Frankenso low out #10: PE0 (do not use with discovery!)
+ // Frankenso low out #11: PB8
+ // Frankenso low out #12: PB7
+
+ boardConfiguration->idleValvePin = GPIOE_5;
+ boardConfiguration->o2heaterPin = GPIOC_13;
+
+ boardConfiguration->injectionPins[0] = GPIOB_8;
+ boardConfiguration->injectionPins[1] = GPIOB_9;
+ boardConfiguration->injectionPins[2] = GPIOE_1;
+ boardConfiguration->injectionPins[3] = GPIOB_7;
+
+ boardConfiguration->ignitionPins[0] = GPIOE_4;
+ boardConfiguration->ignitionPins[1] = GPIO_NONE;
+ boardConfiguration->ignitionPins[2] = GPIO_NONE;
+ boardConfiguration->ignitionPins[3] = GPIO_NONE;
+
+ boardConfiguration->fuelPumpPin = GPIOE_3;
+ boardConfiguration->fuelPumpPinMode = OM_DEFAULT;
+
+ boardConfiguration->gps_rx_pin = GPIO_NONE;
+ boardConfiguration->gps_tx_pin = GPIO_NONE;
+
+ boardConfiguration->HD44780_rs = GPIOE_7;
+ boardConfiguration->HD44780_e = GPIOE_9;
+ boardConfiguration->HD44780_db4 = GPIOE_11;
+ boardConfiguration->HD44780_db5 = GPIOE_13;
+ boardConfiguration->HD44780_db6 = GPIOE_15;
+ boardConfiguration->HD44780_db7 = GPIOB_10;
+
+ boardConfiguration->logicAnalyzerPins[1] = GPIO_NONE;
+
+
+ boardConfiguration->idleSolenoidFrequency = 500;
}
+void setHondaAccordConfigurationTwoWires(engine_configuration_s *engineConfiguration, board_configuration_s *boardConfiguration) {
+ engineConfiguration->engineType = HONDA_ACCORD_CD_TWO_WIRES;
+ engineConfiguration->triggerConfig.triggerType = TT_HONDA_ACCORD_CD_TWO_WIRES;
+ setHondaAccordConfigurationCommon(engineConfiguration, boardConfiguration);
+}
+
+void setHondaAccordConfigurationThreeWires(engine_configuration_s *engineConfiguration, board_configuration_s *boardConfiguration) {
+ engineConfiguration->engineType = HONDA_ACCORD_CD;
+ engineConfiguration->triggerConfig.triggerType = TT_HONDA_ACCORD_CD;
+ setHondaAccordConfigurationCommon(engineConfiguration, boardConfiguration);
+}
+
+void setHondaAccordConfigurationDip(engine_configuration_s *engineConfiguration, board_configuration_s *boardConfiguration) {
+ engineConfiguration->engineType = HONDA_ACCORD_CD_DIP;
+ engineConfiguration->triggerConfig.triggerType = TT_HONDA_ACCORD_CD_DIP;
+ setHondaAccordConfigurationCommon(engineConfiguration, boardConfiguration);
+}
diff --git a/firmware/config/engines/honda_accord.h b/firmware/config/engines/honda_accord.h
index 9fa9da863c..327474a260 100644
--- a/firmware/config/engines/honda_accord.h
+++ b/firmware/config/engines/honda_accord.h
@@ -10,6 +10,8 @@
#include "engine_configuration.h"
-void setHondaAccordConfiguration(engine_configuration_s *engineConfiguration, board_configuration_s *boardConfiguration);
+void setHondaAccordConfigurationTwoWires(engine_configuration_s *engineConfiguration, board_configuration_s *boardConfiguration);
+void setHondaAccordConfigurationThreeWires(engine_configuration_s *engineConfiguration, board_configuration_s *boardConfiguration);
+void setHondaAccordConfigurationDip(engine_configuration_s *engineConfiguration, board_configuration_s *boardConfiguration);
#endif /* HONDA_ACCORD_H_ */
diff --git a/firmware/config/engines/mazda_miata_nb.cpp b/firmware/config/engines/mazda_miata_nb.cpp
index 207b995086..1ee33e2273 100644
--- a/firmware/config/engines/mazda_miata_nb.cpp
+++ b/firmware/config/engines/mazda_miata_nb.cpp
@@ -34,13 +34,13 @@ void setMazdaMiataNbEngineConfiguration(engine_configuration_s *engineConfigurat
setThermistorConfiguration(&engineConfiguration->iatThermistorConf, -10, 160310, 60, 7700, 120.00, 1180);
engineConfiguration->iatThermistorConf.bias_resistor = 2700;
- engineConfiguration->tpsAdcChannel = 3; // 15 is the old value
- engineConfiguration->vBattAdcChannel = 0; // 1 is the old value
+ engineConfiguration->tpsAdcChannel = EFI_ADC_3; // 15 is the old value
+ engineConfiguration->vBattAdcChannel = EFI_ADC_0; // 1 is the old value
// engineConfiguration->map.channel = 1;
- engineConfiguration->mafAdcChannel = 1;
- engineConfiguration->cltAdcChannel = 11;
- engineConfiguration->iatAdcChannel = 13;
- engineConfiguration->afrSensor.afrAdcChannel = 2;
+ engineConfiguration->mafAdcChannel = EFI_ADC_1;
+ engineConfiguration->cltAdcChannel = EFI_ADC_11;
+ engineConfiguration->iatAdcChannel = EFI_ADC_13;
+ engineConfiguration->afrSensor.afrAdcChannel = EFI_ADC_2;
boardConfiguration->idleValvePin = GPIOE_0;
boardConfiguration->idleValvePinMode = OM_DEFAULT;
diff --git a/firmware/config/engines/mitsubishi.cpp b/firmware/config/engines/mitsubishi.cpp
new file mode 100644
index 0000000000..d6f6a2fe40
--- /dev/null
+++ b/firmware/config/engines/mitsubishi.cpp
@@ -0,0 +1,95 @@
+/**
+ * @file mitsubishi.cpp
+ *
+ * MITSU_4G93 16
+ *
+ * @date Aug 5, 2014
+ * @author Andrey Belomutskiy, (c) 2012-2014
+ */
+
+#include "mitsubishi.h"
+#include "thermistors.h"
+
+void setMitsubishiConfiguration(engine_configuration_s *engineConfiguration, board_configuration_s *boardConfiguration) {
+ engineConfiguration->engineType = MITSU_4G93;
+
+ engineConfiguration->triggerConfig.triggerType = TT_MITSU;
+
+ engineConfiguration->cylindersCount = 4;
+ engineConfiguration->displacement = 1.800;
+
+ // set_ignition_mode 2
+ engineConfiguration->ignitionMode = IM_WASTED_SPARK;
+ engineConfiguration->firingOrder = FO_1_THEN_3_THEN_4_THEN2;
+
+ // set_global_trigger_offset_angle 671
+ engineConfiguration->globalTriggerAngleOffset = 671;
+
+ // set_cranking_rpm 550
+ engineConfiguration->crankingSettings.crankingRpm = 550;
+ // set_cranking_charge_angle 70
+ engineConfiguration->crankingChargeAngle = 70;
+ // set_cranking_timing_angle 715
+ engineConfiguration->crankingTimingAngle = 715;
+
+ // set_whole_fuel_map 3
+ setWholeFuelMap(engineConfiguration, 3);
+
+ // since CLT is not wired up yet let's just use same value for min and max
+ // set_cranking_fuel_max 6 40
+ engineConfiguration->crankingSettings.coolantTempMaxC = 37.7; // 6ms at 37.7C
+ engineConfiguration->crankingSettings.fuelAtMaxTempMs = 6;
+
+ // set_cranking_fuel_min 6 -40
+ engineConfiguration->crankingSettings.coolantTempMinC = -40; // 6ms at -40C
+ engineConfiguration->crankingSettings.fuelAtMinTempMs = 6;
+
+// /**
+// * 29150 Ohm @ 40C
+// * 10160 Ohm @ 70C
+// * 1270 Ohm @ 150C
+// */
+// setThermistorConfiguration(&engineConfiguration->cltThermistorConf, 40, 29150, 70, 10160, 150, 1270);
+
+ /**
+ * 18K Ohm @ -20C
+ * 2.1K Ohm @ 24C
+ * 294 Ohm @ 80C
+ * http://www.rexbo.eu/hella/coolant-temperature-sensor-6pt009107121?c=100334&at=3130
+ */
+ setThermistorConfiguration(&engineConfiguration->cltThermistorConf, -20, 18000, 23.8889, 2100, 80, 294);
+
+ engineConfiguration->cltThermistorConf.bias_resistor = 2700;
+
+ // Frankenstein: low side - inj #1: PC14
+ // Frankenstein: low side - inj #2: PC15
+ // Frankenstein: low side - inj #3: PE6
+ // Frankenstein: low side - inj #4: PC13
+ // Frankenstein: low side - inj #5: PE4
+ // Frankenstein: low side - inj #6: PE5
+ // Frankenstein: low side - inj #7: PE2
+ // Frankenstein: low side - inj #8: PE3
+ // Frankenstein: low side - inj #9: PE0
+ // Frankenstein: low side - inj #10: PE1
+ // Frankenstein: low side - inj #11: PB8
+ // Frankenstein: low side - inj #12: PB9
+
+ boardConfiguration->injectionPins[0] = GPIOB_9; // Frankenstein: low side - inj #12
+ boardConfiguration->injectionPins[1] = GPIOB_8; // Frankenstein: low side - inj #11
+ boardConfiguration->injectionPins[2] = GPIOE_3; // Frankenstein: low side - inj #8
+ boardConfiguration->injectionPins[3] = GPIOE_5; // Frankenstein: low side - inj #6
+
+
+ // Frankenstein: high side #1: PE8
+ // Frankenstein: high side #2: PE10
+
+ boardConfiguration->ignitionPins[0] = GPIOE_8; // Frankenstein: high side #1
+ boardConfiguration->ignitionPins[1] = GPIO_NONE;
+ boardConfiguration->ignitionPins[2] = GPIOE_10; // // Frankenstein: high side #2
+ boardConfiguration->ignitionPins[3] = GPIO_NONE;
+
+ engineConfiguration->HD44780width = 20;
+ engineConfiguration->HD44780height = 4;
+}
+
+
diff --git a/firmware/config/engines/mitsubishi.h b/firmware/config/engines/mitsubishi.h
new file mode 100644
index 0000000000..653de9fdf2
--- /dev/null
+++ b/firmware/config/engines/mitsubishi.h
@@ -0,0 +1,16 @@
+/**
+ * @file mitsubishi.h
+ *
+ * @date Aug 5, 2014
+ * @author Andrey Belomutskiy, (c) 2012-2014
+ */
+#ifndef MITSUBISHI_H_
+#define MITSUBISHI_H_
+
+#include "main.h"
+
+#include "engine_configuration.h"
+
+void setMitsubishiConfiguration(engine_configuration_s *engineConfiguration, board_configuration_s *boardConfiguration);
+
+#endif /* MITSUBISHI_H_ */
diff --git a/firmware/console/console_io.c b/firmware/console/console_io.c
index a6b8fd472d..2b93793a8b 100644
--- a/firmware/console/console_io.c
+++ b/firmware/console/console_io.c
@@ -80,11 +80,9 @@ static bool getConsoleLine(BaseSequentialStream *chp, char *line, unsigned size)
continue;
#endif
- if (c < 0)
+ if (c < 0 || c == 4) {
return TRUE;
- if (c == 4) {
- return TRUE;
- }
+ }
if (c == 8) {
if (p != line) {
// backspace
@@ -101,8 +99,9 @@ static bool getConsoleLine(BaseSequentialStream *chp, char *line, unsigned size)
*p = 0;
return false;
}
- if (c < 0x20)
+ if (c < 0x20) {
continue;
+ }
if (p < line + size - 1) {
consolePutChar((uint8_t) c);
*p++ = (char) c;
@@ -152,7 +151,7 @@ SerialDriver * getConsoleChannel(void) {
}
}
-int isConsoleReady(void) {
+bool isConsoleReady(void) {
if (isSerialOverUart()) {
return isSerialConsoleStarted;
} else {
@@ -169,7 +168,7 @@ void consolePutChar(int x) {
// 10 seconds
#define CONSOLE_WRITE_TIMEOUT 10000
-void consoleOutputBuffer(const int8_t *buf, int size) {
+void consoleOutputBuffer(const uint8_t *buf, int size) {
lastWriteSize = size;
#if !EFI_UART_ECHO_TEST_MODE
lastWriteActual = chnWriteTimeout(getConsoleChannel(), buf, size, CONSOLE_WRITE_TIMEOUT);
diff --git a/firmware/console/console_io.h b/firmware/console/console_io.h
index 935751fad2..afa2b39e00 100644
--- a/firmware/console/console_io.h
+++ b/firmware/console/console_io.h
@@ -32,9 +32,9 @@ extern "C"
SerialDriver * getConsoleChannel(void);
void consolePutChar(int x);
-void consoleOutputBuffer(const int8_t *buf, int size);
+void consoleOutputBuffer(const uint8_t *buf, int size);
void startConsole(void (*console_line_callback_p)(char *));
-int isConsoleReady(void);
+bool isConsoleReady(void);
bool isSerialOverUart(void);
#ifdef __cplusplus
diff --git a/firmware/console/eficonsole.c b/firmware/console/eficonsole.c
index 61861c1eee..4c94e6dbfb 100644
--- a/firmware/console/eficonsole.c
+++ b/firmware/console/eficonsole.c
@@ -130,17 +130,14 @@ static void cmd_threads(void) {
#endif
}
-void sendOutConfirmation(char *value, int i) {
- scheduleMsg(&logger, "%s%d", value, i);
-}
-
/**
* This methods prints the message to whatever is configured as our primary console
*/
void print(const char *format, ...) {
#if !EFI_UART_ECHO_TEST_MODE
- if (!isConsoleReady())
+ if (!isConsoleReady()) {
return;
+ }
va_list ap;
va_start(ap, format);
chvprintf((BaseSequentialStream*)getConsoleChannel(), format, ap);
@@ -148,7 +145,7 @@ void print(const char *format, ...) {
#endif /* EFI_UART_ECHO_TEST_MODE */
}
-void initializeConsole() {
+void initializeConsole(void) {
initIntermediateLoggingBuffer();
initConsoleLogic();
diff --git a/firmware/console/eficonsole.h b/firmware/console/eficonsole.h
index ef0b10c723..0685f1ed8d 100644
--- a/firmware/console/eficonsole.h
+++ b/firmware/console/eficonsole.h
@@ -16,7 +16,6 @@ extern "C"
#endif /* __cplusplus */
void initializeConsole(void);
-void sendOutConfirmation(char *value, int i);
void print(const char *fmt, ...);
#ifdef __cplusplus
diff --git a/firmware/console/status_loop.cpp b/firmware/console/status_loop.cpp
index 3d4bd8997e..bcf43b923f 100644
--- a/firmware/console/status_loop.cpp
+++ b/firmware/console/status_loop.cpp
@@ -1,5 +1,5 @@
/**
- * @file status_loop.c
+ * @file status_loop.cpp
* @brief Human-readable protocol status messages
*
* http://rusefi.com/forum/viewtopic.php?t=263 Dev console overview
@@ -46,8 +46,6 @@
#include "tunerstudio.h"
#endif /* EFI_TUNER_STUDIO */
-#include "wave_math.h"
-
#include "fuel_math.h"
#include "main_trigger_callback.h"
#include "engine_math.h"
@@ -56,18 +54,22 @@
#include "rfiutil.h"
#include "svnversion.h"
#include "engine.h"
+#include "lcd_controller.h"
+#include "fuel_math.h"
#if EFI_PROD_CODE
// todo: move this logic to algo folder!
#include "rtc_helper.h"
#include "lcd_HD44780.h"
#include "rusefi.h"
+#include "pin_repository.h"
+#include "flash_main.h"
#endif
extern Engine engine;
// this 'true' value is needed for simulator
-static volatile int fullLog = TRUE;
+static volatile bool fullLog = true;
int warningEnabled = TRUE;
//int warningEnabled = FALSE;
@@ -112,10 +114,6 @@ static const char* boolean2string(int value) {
return value ? "YES" : "NO";
}
-void finishStatusLine(void) {
- printLine(&logger);
-}
-
void printSensors(void) {
#if EFI_FILE_LOGGING
resetLogging(&fileLogger);
@@ -186,7 +184,7 @@ void printState(int currentCkpEventCounter) {
#define INITIAL_FULL_LOG TRUE
//#define INITIAL_FULL_LOG FALSE
-static char LOGGING_BUFFER[500];
+static char LOGGING_BUFFER[700];
volatile int needToReportStatus = FALSE;
static int prevCkpEventCounter = -1;
@@ -203,13 +201,42 @@ static void printStatus(void) {
*/
static systime_t timeOfPreviousPrintVersion = (systime_t) -1;
-static void printVersion(systime_t nowSeconds) {
- if (overflowDiff(nowSeconds, timeOfPreviousPrintVersion) < 4)
+#if EFI_PROD_CODE
+static void printOutPin(const char *pinName, brain_pin_e hwPin) {
+ appendPrintf(&logger, "outpin%s%s@%s%s", DELIMETER, pinName,
+ hwPortname(hwPin), DELIMETER);
+}
+#endif /* EFI_PROD_CODE */
+
+static void printInfo(systime_t nowSeconds) {
+ /**
+ * we report the version every 4 seconds - this way the console does not need to
+ * request it and we will display it pretty soon
+ */
+ if (overflowDiff(nowSeconds, timeOfPreviousPrintVersion) < 4) {
return;
+ }
timeOfPreviousPrintVersion = nowSeconds;
appendPrintf(&logger, "rusEfiVersion%s%d@%s %s%s", DELIMETER, getRusEfiVersion(), VCS_VERSION,
getConfigurationName(engineConfiguration),
DELIMETER);
+#if EFI_PROD_CODE
+ printOutPin(WC_CRANK1, boardConfiguration->triggerInputPins[0]);
+ printOutPin(WC_CRANK2, boardConfiguration->triggerInputPins[1]);
+ printOutPin(WA_CHANNEL_1, boardConfiguration->logicAnalyzerPins[0]);
+ printOutPin(WA_CHANNEL_2, boardConfiguration->logicAnalyzerPins[1]);
+
+ for (int i = 0; i < engineConfiguration->cylindersCount; i++) {
+ // todo: extract method?
+ io_pin_e pin = (io_pin_e) ((int) SPARKOUT_1_OUTPUT + i);
+
+ printOutPin(getPinName(pin), boardConfiguration->ignitionPins[i]);
+
+ pin = (io_pin_e) ((int) INJECTOR_1_OUTPUT + i);
+ printOutPin(getPinName(pin), boardConfiguration->injectionPins[i]);
+ }
+#endif
+
}
static systime_t timeOfPreviousReport = (systime_t) -1;
@@ -220,8 +247,9 @@ extern char errorMessageBuffer[200];
* @brief Sends all pending data to dev console
*/
void updateDevConsoleState(void) {
- if (!isConsoleReady())
+ if (!isConsoleReady()) {
return;
+ }
// looks like this is not needed anymore
// checkIfShouldHalt();
printPending();
@@ -240,15 +268,17 @@ void updateDevConsoleState(void) {
pokeAdcInputs();
#endif
- if (!fullLog)
+ if (!fullLog) {
return;
+ }
systime_t nowSeconds = getTimeNowSeconds();
- printVersion(nowSeconds);
+ printInfo(nowSeconds);
int currentCkpEventCounter = getCrankEventCounter();
- if (prevCkpEventCounter == currentCkpEventCounter && timeOfPreviousReport == nowSeconds)
+ if (prevCkpEventCounter == currentCkpEventCounter && timeOfPreviousReport == nowSeconds) {
return;
+ }
timeOfPreviousReport = nowSeconds;
@@ -257,10 +287,10 @@ void updateDevConsoleState(void) {
printState(currentCkpEventCounter);
#if EFI_WAVE_ANALYZER
-// printWave(&logger);
+ printWave(&logger);
#endif
- finishStatusLine();
+ printLine(&logger);
}
#if EFI_PROD_CODE
@@ -272,7 +302,7 @@ void updateDevConsoleState(void) {
*/
static void showFuelMap2(float rpm, float engineLoad) {
- float baseFuel = getBaseTableFuel(rpm, engineLoad);
+ float baseFuel = getBaseTableFuel((int) rpm, engineLoad);
float iatCorrection = getIatCorrection(getIntakeAirTemperature());
float cltCorrection = getCltCorrection(getCoolantTemperature());
@@ -283,49 +313,19 @@ static void showFuelMap2(float rpm, float engineLoad) {
scheduleMsg(&logger2, "iatCorrection=%f cltCorrection=%f injectorLag=%f", iatCorrection, cltCorrection,
injectorLag);
- float value = getRunningFuel(baseFuel, &engine, rpm);
+ float value = getRunningFuel(baseFuel, &engine, (int) rpm);
scheduleMsg(&logger2, "injection pulse width: %f", value);
}
static void showFuelMap(void) {
- showFuelMap2(getRpm(), getEngineLoad());
+ showFuelMap2((float) getRpm(), getEngineLoad());
}
-
-static char buffer[10];
-static char dateBuffer[30];
-
-void updateHD44780lcd(void) {
-
- lcd_HD44780_set_position(0, 9);
- lcd_HD44780_print_char('R');
- lcd_HD44780_set_position(0, 10);
-
- char * ptr = itoa10(buffer, getRpm());
- ptr[0] = 0;
- int len = ptr - buffer;
- for (int i = 0; i < 6 - len; i++)
- lcd_HD44780_print_char(' ');
-
- lcd_HD44780_print_string(buffer);
-
- lcd_HD44780_set_position(2, 0);
- lcd_HD44780_print_char('C');
-
- ftoa(buffer, getCoolantTemperature(), 100);
- lcd_HD44780_print_string(buffer);
-
-#if EFI_PROD_CODE
- dateToString(dateBuffer);
- lcd_HD44780_set_position(1, 0);
- lcd_HD44780_print_string(dateBuffer);
-#endif /* EFI_PROD_CODE */
-}
#endif /* EFI_PROD_CODE */
static THD_WORKING_AREA(lcdThreadStack, UTILITY_THREAD_STACK_SIZE);
-static void lcdThread(void *arg) {
+static void lcdThread(void) {
chRegSetThreadName("lcd");
while (true) {
#if EFI_HD44780_LCD
@@ -338,7 +338,6 @@ static void lcdThread(void *arg) {
static THD_WORKING_AREA(tsThreadStack, UTILITY_THREAD_STACK_SIZE);
#if EFI_TUNER_STUDIO
-extern TunerStudioOutputChannels tsOutputChannels;
void updateTunerStudioState(TunerStudioOutputChannels *tsOutputChannels) {
#if EFI_SHAFT_POSITION_INPUT
@@ -351,6 +350,9 @@ void updateTunerStudioState(TunerStudioOutputChannels *tsOutputChannels) {
float coolant = getCoolantTemperature();
float intake = getIntakeAirTemperature();
+ float engineLoad = getEngineLoad();
+ float baseFuel = getBaseTableFuel((int) rpm, engineLoad);
+
tsOutputChannels->rpm = rpm;
tsOutputChannels->coolant_temperature = coolant;
tsOutputChannels->intake_air_temperature = intake;
@@ -362,8 +364,24 @@ void updateTunerStudioState(TunerStudioOutputChannels *tsOutputChannels) {
tsOutputChannels->atmospherePressure = getBaroPressure();
tsOutputChannels->manifold_air_pressure = getMap();
tsOutputChannels->checkEngine = hasErrorCodes();
+#if EFI_PROD_CODE
+ tsOutputChannels->needBurn = getNeedToWriteConfiguration();
+ tsOutputChannels->hasSdCard = isSdCardAlive();
+ tsOutputChannels->isFuelPumpOn = getOutputPinValue(FUEL_PUMP_RELAY);
+ tsOutputChannels->isFanOn = getOutputPinValue(FAN_RELAY);
+ tsOutputChannels->isO2HeaterOn = getOutputPinValue(O2_HEATER);
+ tsOutputChannels->ignition_enabled = engineConfiguration->isIgnitionEnabled;
+ tsOutputChannels->injection_enabled = engineConfiguration->isInjectionEnabled;
+ tsOutputChannels->cylinder_cleanup_enabled = engineConfiguration->isCylinderCleanupEnabled;
+ tsOutputChannels->secondTriggerChannelEnabled = engineConfiguration->secondTriggerChannelEnabled;
+#endif
tsOutputChannels->tCharge = getTCharge(rpm, tps, coolant, intake);
+ tsOutputChannels->sparkDwell = getSparkDwellMs(rpm);
+ tsOutputChannels->pulseWidth = getRunningFuel(baseFuel, &engine, rpm);
+ tsOutputChannels->crankingFuel = getCrankingFuel();
}
+
+extern TunerStudioOutputChannels tsOutputChannels;
#endif /* EFI_TUNER_STUDIO */
static void tsStatusThread(void *arg) {
@@ -403,8 +421,8 @@ void initStatusLoop(void) {
void startStatusThreads(void) {
// todo: refactoring needed, this file should probably be split into pieces
- chThdCreateStatic(lcdThreadStack, sizeof(lcdThreadStack), NORMALPRIO, (tfunc_t) lcdThread, NULL);
- chThdCreateStatic(tsThreadStack, sizeof(tsThreadStack), NORMALPRIO, (tfunc_t) tsStatusThread, NULL);
+ chThdCreateStatic(lcdThreadStack, sizeof(lcdThreadStack), NORMALPRIO, (tfunc_t) lcdThread, (void*) NULL);
+ chThdCreateStatic(tsThreadStack, sizeof(tsThreadStack), NORMALPRIO, (tfunc_t) tsStatusThread, (void*) NULL);
}
void setFullLog(int value) {
@@ -413,6 +431,6 @@ void setFullLog(int value) {
fullLog = value;
}
-int getFullLog(void) {
+bool getFullLog(void) {
return fullLog;
}
diff --git a/firmware/console/status_loop.h b/firmware/console/status_loop.h
index a0bb5f1798..8db2ece694 100644
--- a/firmware/console/status_loop.h
+++ b/firmware/console/status_loop.h
@@ -17,7 +17,7 @@ void printState(int currentCkpEventCounter);
void initStatusLoop(void);
void updateDevConsoleState(void);
-int getFullLog(void);
+bool getFullLog(void);
void printSensors(void);
void setFullLog(int value);
void startStatusThreads(void);
diff --git a/firmware/console/tunerstudio/tunerstudio.cpp b/firmware/console/tunerstudio/tunerstudio.cpp
index 0d47803aa0..38c49a0d23 100644
--- a/firmware/console/tunerstudio/tunerstudio.cpp
+++ b/firmware/console/tunerstudio/tunerstudio.cpp
@@ -33,7 +33,6 @@
#include "tunerstudio_algo.h"
#include "tunerstudio_configuration.h"
#include "malfunction_central.h"
-#include "wave_math.h"
#include "console_io.h"
#include "crc.h"
@@ -54,14 +53,14 @@ static SerialConfig tsSerialConfig = { TS_SERIAL_SPEED, 0, USART_CR2_STOP1_BITS
#endif /* EFI_PROD_CODE */
#define MAX_PAGE_ID 0
-#define PAGE_0_SIZE 5824
+#define PAGE_0_SIZE 5928
+#define TS_OUTPUT_SIZE 116
// in MS, that's 10 seconds
#define TS_READ_TIMEOUT 10000
#define PROTOCOL "001"
-
BaseChannel * getTsSerialDevice(void) {
#if EFI_PROD_CODE
if (isSerialOverUart()) {
@@ -77,7 +76,6 @@ BaseChannel * getTsSerialDevice(void) {
static Logging logger;
-extern engine_configuration_s *engineConfiguration;
extern persistent_config_s configWorkingCopy;
extern persistent_config_container_s persistentState;
@@ -108,6 +106,10 @@ extern TunerStudioOutputChannels tsOutputChannels;
extern TunerStudioState tsState;
+extern engine_configuration_s *engineConfiguration;
+extern board_configuration_s *boardConfiguration;
+
+
static void printStats(void) {
#if EFI_PROD_CODE
if (!isSerialOverUart()) {
@@ -127,14 +129,11 @@ static void printStats(void) {
// 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);
+// int offset = (int) (&boardConfiguration->o2heaterPin) - (int) engineConfiguration;
+// scheduleMsg(&logger, "o2heaterPin %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");
+// offset = (int) (&boardConfiguration->idleSolenoidFrequency) - (int) engineConfiguration;
+// scheduleMsg(&logger, "idleSolenoidFrequency %d", offset);
}
void tunerStudioWriteData(const uint8_t * buffer, int size) {
@@ -227,7 +226,7 @@ void handleWriteValueCommand(ts_response_format_e mode, uint16_t page, uint16_t
// scheduleMsg(&logger, "Page number %d\r\n", pageId); // we can get a lot of these
#endif
- int size = sizeof(TunerStudioWriteValueRequest);
+// int size = sizeof(TunerStudioWriteValueRequest);
// scheduleMsg(&logger, "Reading %d\r\n", size);
if (offset > getTunerStudioPageSize(tsState.currentPageId)) {
@@ -258,7 +257,7 @@ void handlePageReadCommand(ts_response_format_e mode, uint16_t pageId, uint16_t
tsState.currentPageId = pageId;
#if EFI_TUNER_STUDIO_VERBOSE
- scheduleMsg(&logger, "Page requested: page %d offset=%d count=%d", tsState.currentPageId, offset, count);
+ scheduleMsg(&logger, "Page requested: page %d offset=%d count=%d", (int)tsState.currentPageId, offset, count);
#endif
if (tsState.currentPageId > MAX_PAGE_ID) {
@@ -305,7 +304,7 @@ void handleBurnCommand(ts_response_format_e mode, uint16_t page) {
memcpy(&persistentState.persistentConfiguration, &configWorkingCopy, sizeof(persistent_config_s));
#if EFI_INTERNAL_FLASH
- writeToFlash();
+ setNeedToWriteConfiguration();
#endif
incrementGlobalConfigurationVersion();
tunerStudioWriteCrcPacket(TS_RESPONSE_BURN_OK, NULL, 0);
@@ -397,7 +396,7 @@ static msg_t tsThreadEntryPoint(void *arg) {
}
// scheduleMsg(&logger, "Got secondByte=%x=[%c]", secondByte, secondByte);
- int incomingPacketSize = firstByte * 256 + secondByte;
+ uint32_t incomingPacketSize = firstByte * 256 + secondByte;
if (incomingPacketSize == 0 || incomingPacketSize > sizeof(crcIoBuffer)) {
scheduleMsg(&logger, "TunerStudio: invalid size: %d", incomingPacketSize);
@@ -435,7 +434,7 @@ static msg_t tsThreadEntryPoint(void *arg) {
expectedCrc = SWAP_UINT32(expectedCrc);
- int actualCrc = crc32(crcIoBuffer, incomingPacketSize);
+ uint32_t actualCrc = crc32(crcIoBuffer, incomingPacketSize);
if (actualCrc != expectedCrc) {
scheduleMsg(&logger, "TunerStudio: CRC %x %x %x %x", crcIoBuffer[incomingPacketSize + 0],
crcIoBuffer[incomingPacketSize + 1], crcIoBuffer[incomingPacketSize + 2],
@@ -466,6 +465,13 @@ void syncTunerStudioCopy(void) {
void startTunerStudioConnectivity(void) {
initLogging(&logger, "tuner studio");
+
+ if (sizeof(engine_configuration_s) != getTunerStudioPageSize(0))
+ firmwareError("TS page size mismatch: %d/%d", sizeof(engine_configuration_s), getTunerStudioPageSize(0));
+
+ if (sizeof(TunerStudioOutputChannels) != TS_OUTPUT_SIZE)
+ firmwareError("TS outputs size mismatch: %d/%d", sizeof(TunerStudioOutputChannels), TS_OUTPUT_SIZE);
+
memset(&tsState, 0, sizeof(tsState));
#if EFI_PROD_CODE
if (isSerialOverUart()) {
diff --git a/firmware/console/tunerstudio/tunerstudio_algo.cpp b/firmware/console/tunerstudio/tunerstudio_algo.cpp
index 27ab46a87c..c4475ad9d4 100644
--- a/firmware/console/tunerstudio/tunerstudio_algo.cpp
+++ b/firmware/console/tunerstudio/tunerstudio_algo.cpp
@@ -48,6 +48,7 @@
#include "tunerstudio_configuration.h"
#include "engine_configuration.h"
#include "tunerstudio.h"
+#include "svnversion.h"
#ifndef FALSE
#define FALSE 0
@@ -150,5 +151,6 @@ void handleTestCommand(void) {
* extension of the protocol to simplify troubleshooting
*/
tunerStudioDebug("got T (Test)");
- tunerStudioWriteData((const uint8_t *) "alive\r\n", 7);
+ tunerStudioWriteData((const uint8_t *)VCS_VERSION, sizeof(VCS_VERSION));
+ tunerStudioWriteData((const uint8_t *) " alive\r\n", 8);
}
diff --git a/firmware/console/tunerstudio/tunerstudio_configuration.h b/firmware/console/tunerstudio/tunerstudio_configuration.h
index a3379fb6ea..84bef28ef2 100644
--- a/firmware/console/tunerstudio/tunerstudio_configuration.h
+++ b/firmware/console/tunerstudio/tunerstudio_configuration.h
@@ -16,6 +16,7 @@
* support 'float' (F32) type. You would need a beta version to handle floats
*/
typedef struct {
+ // primary instrument cluster gauges
int rpm; // size 4, offset 0
float coolant_temperature; // size 4, offset 4
float intake_air_temperature; // size 4, offset 8
@@ -28,8 +29,29 @@ typedef struct {
short int alignment; // size 2, offset 34
float atmospherePressure; // size 4, offset 36
float manifold_air_pressure; // size 4, offset 40
- int checkEngine; // size 4, offset 44
- float tCharge;
+ float crankingFuel;
+ int tpsVolrage;
+ float tCharge; // 52
+ float inj_adv; // 56
+ float sparkDwell; // 60
+ float pulseWidth; // 64
+ float warmUpEnrich; // 68
+ /**
+ * Yes, I do not really enjoy packing bits into integers but we simply have too many boolean flags and I cannot
+ * water 4 bytes per trafic - I want gauges to work as fast as possible
+ */
+ unsigned int hasSdCard : 1; // bit 0
+ unsigned int ignition_enabled : 1; // bit 1
+ unsigned int injection_enabled : 1; // bit 2
+ unsigned int cylinder_cleanup_enabled : 1; // bit 3
+ unsigned int cylinder_cleanup : 1; // bit 4
+ unsigned int isFuelPumpOn : 1; // bit 5
+ unsigned int isFanOn : 1; // bit 6
+ unsigned int isO2HeaterOn : 1; // bit 7
+ unsigned int checkEngine : 1; // bit 8
+ unsigned int needBurn : 1; // bit 9
+ unsigned int secondTriggerChannelEnabled : 1; // bit 10
+ int unused[10];
} TunerStudioOutputChannels;
#endif /* TUNERSTUDIO_CONFIGURATION_H_ */
diff --git a/firmware/console_util/datalogging.c b/firmware/console_util/datalogging.c
index 642ec658cb..173711f299 100644
--- a/firmware/console_util/datalogging.c
+++ b/firmware/console_util/datalogging.c
@@ -49,7 +49,8 @@
/**
* This is the buffer into which all the data providers write
*/
-static char pendingBuffer[DL_OUTPUT_BUFFER] CCM_OPTIONAL;
+static char pendingBuffer[DL_OUTPUT_BUFFER] CCM_OPTIONAL
+;
/**
* We copy all the pending data into this buffer once we are ready to push it out
@@ -57,10 +58,12 @@ static char pendingBuffer[DL_OUTPUT_BUFFER] CCM_OPTIONAL;
static char outputBuffer[DL_OUTPUT_BUFFER];
static MemoryStream intermediateLoggingBuffer;
-static uint8_t intermediateLoggingBufferData[INTERMEDIATE_LOGGING_BUFFER_SIZE] CCM_OPTIONAL; //todo define max-printf-buffer
+static uint8_t intermediateLoggingBufferData[INTERMEDIATE_LOGGING_BUFFER_SIZE] CCM_OPTIONAL
+;
+//todo define max-printf-buffer
static bool intermediateLoggingBufferInited = FALSE;
-static int validateBuffer(Logging *logging, int extraLen, const char *text) {
+static int validateBuffer(Logging *logging, uint32_t extraLen, const char *text) {
if (logging->buffer == NULL) {
firmwareError("Logging not initialized: %s", logging->name);
return TRUE;
@@ -81,10 +84,11 @@ static int validateBuffer(Logging *logging, int extraLen, const char *text) {
void append(Logging *logging, const char *text) {
efiAssertVoid(text != NULL, "append NULL");
- int extraLen = strlen(text);
+ uint32_t extraLen = strlen(text);
int errcode = validateBuffer(logging, extraLen, text);
- if (errcode)
+ if (errcode) {
return;
+ }
strcpy(logging->linePointer, text);
logging->linePointer += extraLen;
}
@@ -171,6 +175,7 @@ char* getCaption(LoggingPoints loggingPoint) {
return NULL;
}
+/*
// todo: this method does not really belong to this file
static char* get2ndCaption(int loggingPoint) {
switch (loggingPoint) {
@@ -192,6 +197,7 @@ static char* get2ndCaption(int loggingPoint) {
firmwareError("No such loggingPoint");
return NULL;
}
+*/
void initLoggingExt(Logging *logging, const char *name, char *buffer, int bufferSize) {
print("Init logging %s\r\n", name);
@@ -284,8 +290,8 @@ static void printWithLength(char *line) {
if (!isConsoleReady())
return;
- consoleOutputBuffer((const int8_t *) header, strlen(header));
- consoleOutputBuffer((const int8_t *) line, p - line);
+ consoleOutputBuffer((const uint8_t *) header, strlen(header));
+ consoleOutputBuffer((const uint8_t *) line, p - line);
}
void printLine(Logging *logging) {
@@ -368,15 +374,17 @@ void scheduleLogging(Logging *logging) {
// strcpy(fatalMessage, "datalogging.c: output buffer overflow: ");
// strcat(fatalMessage, logging->name);
// fatal(fatalMessage);
- if (!alreadyLocked)
+ if (!alreadyLocked) {
unlockOutputBuffer();
+ }
resetLogging(logging);
return;
}
strcat(pendingBuffer, logging->buffer);
- if (!alreadyLocked)
+ if (!alreadyLocked) {
unlockOutputBuffer();
+ }
resetLogging(logging);
}
@@ -387,15 +395,16 @@ uint32_t remainingSize(Logging *logging) {
/**
* This method actually sends all the pending data to the communication layer
*/
-void printPending() {
+void printPending(void) {
lockOutputBuffer();
// we cannot output under syslock, so another buffer
strcpy(outputBuffer, pendingBuffer);
pendingBuffer[0] = 0; // reset pending buffer
unlockOutputBuffer();
- if (strlen(outputBuffer) > 0)
+ if (strlen(outputBuffer) > 0) {
printWithLength(outputBuffer);
+ }
}
void initIntermediateLoggingBuffer(void) {
diff --git a/firmware/console_util/rfiutil.c b/firmware/console_util/rfiutil.c
index dde04d8fb8..c8d54cdb29 100644
--- a/firmware/console_util/rfiutil.c
+++ b/firmware/console_util/rfiutil.c
@@ -20,6 +20,7 @@
*/
#include
+#include "main.h"
#include "rfiutil.h"
/*
@@ -49,7 +50,7 @@ int mylog10(int param) {
char hexChar(int v) {
v = v & 0xF;
if (v < 10)
- return '0' + v;
+ return (char)('0' + v);
return 'A' - 10 + v;
}
@@ -68,8 +69,7 @@ int isLocked(void) {
void chVTSetAny(virtual_timer_t *vtp, systime_t time, vtfunc_t vtfunc, void *par) {
if (isIsrContext()) {
- chSysLockFromIsr()
- ;
+ bool wasLocked = lockAnyContext();
/**
* todo: this could be simplified once we migrate to ChibiOS 3.0
@@ -79,7 +79,8 @@ void chVTSetAny(virtual_timer_t *vtp, systime_t time, vtfunc_t vtfunc, void *par
chVTResetI(vtp);
chVTSetI(vtp, time, vtfunc, par);
- chSysUnlockFromIsr()
+ if (!wasLocked)
+ chSysUnlockFromIsr()
;
} else {
chSysLock()
diff --git a/firmware/controllers/PwmTester.cpp b/firmware/controllers/PwmTester.cpp
index ee48b24199..3e09cb13f9 100644
--- a/firmware/controllers/PwmTester.cpp
+++ b/firmware/controllers/PwmTester.cpp
@@ -23,11 +23,11 @@ static void startPwmTest(int freq) {
scheduleMsg(&logger, "running pwm test @%d", freq);
// PD13, GPIO_NONE because pin is initialized elsewhere already
- startSimplePwm(&pwmTest[0], "tester", LED_WARNING, 10, 0.5);
+ startSimplePwm(&pwmTest[0], "tester", LED_WARNING, 10, 0.5f);
// currently this is PB9 by default - see boardConfiguration->injectionPins
- startSimplePwm(&pwmTest[1], "tester", INJECTOR_1_OUTPUT, freq / 1.3333333333, 0.5);
+ startSimplePwm(&pwmTest[1], "tester", INJECTOR_1_OUTPUT, freq / 1.3333333333, 0.5f);
// currently this is PB8 by default
- startSimplePwm(&pwmTest[2], "tester", INJECTOR_2_OUTPUT, freq / 1000, 0.5);
+ startSimplePwm(&pwmTest[2], "tester", INJECTOR_2_OUTPUT, freq / 1000, 0.5f);
// currently this is PE3 by default
startSimplePwm(&pwmTest[3], "tester", INJECTOR_3_OUTPUT, freq, 0.5);
// currently this is PE5 by default
diff --git a/firmware/controllers/algo/advance_map.cpp b/firmware/controllers/algo/advance_map.cpp
index 91f0813e6d..20920226fa 100644
--- a/firmware/controllers/algo/advance_map.cpp
+++ b/firmware/controllers/algo/advance_map.cpp
@@ -35,7 +35,7 @@ static Map3D1616 advanceMap;
float getBaseAdvance(int rpm, float engineLoad) {
efiAssert(!cisnan(engineLoad), "invalid el", NAN);
efiAssert(!cisnan(engineLoad), "invalid rpm", NAN);
- return advanceMap.getValue(engineLoad, engineConfiguration->ignitionLoadBins, rpm,
+ return advanceMap.getValue(engineLoad, engineConfiguration->ignitionLoadBins, (float)rpm,
engineConfiguration->ignitionRpmBins);
}
diff --git a/firmware/controllers/algo/ec2.h b/firmware/controllers/algo/ec2.h
index cc3f46e06b..e071f0eb06 100644
--- a/firmware/controllers/algo/ec2.h
+++ b/firmware/controllers/algo/ec2.h
@@ -40,25 +40,20 @@ extern "C"
* these fields are not integrated with Tuner Studio. Step by step :)
*/
class engine_configuration2_s {
+ // todo: move these fields into Engine class, eliminate this class
public:
engine_configuration2_s();
Thermistor iat;
Thermistor clt;
-// int crankAngleRange;
-
trigger_shape_s triggerShape;
- cranking_ignition_mode_e crankingIgnitionMode;
-
EventHandlerConfiguration engineEventConfiguration;
- int isInjectionEnabledFlag;
-
/**
* This coefficient translates ADC value directly into voltage adjusted according to
- * voltage divider configuration.
+ * voltage divider configuration. This is a future (?) performance optimization.
*/
float adcToVoltageInputDividerCoefficient;
};
@@ -72,6 +67,7 @@ void prepareOutputSignals(engine_configuration_s *engineConfiguration,
engine_configuration2_s *engineConfiguration2);
void initializeIgnitionActions(float advance, float dwellAngle, engine_configuration_s *engineConfiguration, engine_configuration2_s *engineConfiguration2, IgnitionEventList *list);
+float getFuelMultiplier(engine_configuration_s const *e, injection_mode_e mode);
void addFuelEvents(engine_configuration_s const *e, engine_configuration2_s *engineConfiguration2, ActuatorEventList *list, injection_mode_e mode);
void registerActuatorEventExt(engine_configuration_s const *engineConfiguration, trigger_shape_s * s, ActuatorEvent *e, OutputSignal *actuator, float angleOffset);
@@ -83,7 +79,6 @@ void resetConfigurationExt(Logging * logger, engine_type_e engineType,
void applyNonPersistentConfiguration(Logging * logger, engine_configuration_s *engineConfiguration,
engine_configuration2_s *engineConfiguration2);
-
void setDefaultNonPersistentConfiguration(engine_configuration2_s *engineConfiguration2);
void printConfiguration(engine_configuration_s *engineConfiguration, engine_configuration2_s *engineConfiguration2);
diff --git a/firmware/controllers/algo/engine_configuration.cpp b/firmware/controllers/algo/engine_configuration.cpp
index 00fe7668fb..fdcf10e191 100644
--- a/firmware/controllers/algo/engine_configuration.cpp
+++ b/firmware/controllers/algo/engine_configuration.cpp
@@ -48,6 +48,7 @@
#include "ford_escort_gt.h"
#include "citroenBerlingoTU3JP.h"
#include "rover_v8.h"
+#include "mitsubishi.h"
static volatile int globalConfigurationVersion = 0;
@@ -179,8 +180,8 @@ void setDefaultConfiguration(engine_configuration_s *engineConfiguration, board_
engineConfiguration->analogChartMode = AC_TRIGGER;
- engineConfiguration->map.sensor.hwChannel = 4;
- engineConfiguration->baroSensor.hwChannel = 4;
+ engineConfiguration->map.sensor.hwChannel = EFI_ADC_4;
+ engineConfiguration->baroSensor.hwChannel = EFI_ADC_4;
engineConfiguration->firingOrder = FO_1_THEN_3_THEN_4_THEN2;
engineConfiguration->crankingInjectionMode = IM_SIMULTANEOUS;
@@ -219,18 +220,19 @@ void setDefaultConfiguration(engine_configuration_s *engineConfiguration, board_
engineConfiguration->displayMode = DM_HD44780;
engineConfiguration->logFormat = LF_NATIVE;
+ engineConfiguration->directSelfStimulation = false;
engineConfiguration->triggerConfig.triggerType = TT_TOOTHED_WHEEL_60_2;
- engineConfiguration->HD44780width = 16;
- engineConfiguration->HD44780height = 2;
+ engineConfiguration->HD44780width = 20;
+ engineConfiguration->HD44780height = 4;
- engineConfiguration->tpsAdcChannel = 3;
- engineConfiguration->vBattAdcChannel = 5;
- engineConfiguration->cltAdcChannel = 6;
- engineConfiguration->iatAdcChannel = 7;
- engineConfiguration->mafAdcChannel = 0;
- engineConfiguration->afrSensor.afrAdcChannel = 14;
+ engineConfiguration->tpsAdcChannel = EFI_ADC_3;
+ engineConfiguration->vBattAdcChannel = EFI_ADC_5;
+ engineConfiguration->cltAdcChannel = EFI_ADC_6;
+ engineConfiguration->iatAdcChannel = EFI_ADC_7;
+ engineConfiguration->mafAdcChannel = EFI_ADC_0;
+ engineConfiguration->afrSensor.afrAdcChannel = EFI_ADC_14;
initBpsxD1Sensor(&engineConfiguration->afrSensor);
@@ -247,12 +249,21 @@ void setDefaultConfiguration(engine_configuration_s *engineConfiguration, board_
engineConfiguration->hasMapSensor = TRUE;
engineConfiguration->hasCltSensor = TRUE;
+ boardConfiguration->idleSolenoidFrequency = 200;
+// engineConfiguration->idleMode = IM_AUTO;
+ engineConfiguration->idleMode = IM_MANUAL;
+
+ engineConfiguration->isInjectionEnabled = true;
+ engineConfiguration->isIgnitionEnabled = true;
+ engineConfiguration->isCylinderCleanupEnabled = true;
+ engineConfiguration->secondTriggerChannelEnabled = true;
boardConfiguration->idleValvePin = GPIOE_2;
boardConfiguration->idleValvePinMode = OM_DEFAULT;
boardConfiguration->fuelPumpPin = GPIOC_13;
boardConfiguration->fuelPumpPinMode = OM_DEFAULT;
boardConfiguration->electronicThrottlePin1 = GPIOC_9;
+ boardConfiguration->o2heaterPin = GPIO_NONE;
boardConfiguration->injectionPins[0] = GPIOB_9;
boardConfiguration->injectionPins[1] = GPIOB_8;
@@ -292,9 +303,11 @@ void setDefaultConfiguration(engine_configuration_s *engineConfiguration, board_
boardConfiguration->triggerSimulatorPins[0] = GPIOD_1;
boardConfiguration->triggerSimulatorPins[1] = GPIOD_2;
+ boardConfiguration->triggerSimulatorPins[2] = GPIOD_3;
boardConfiguration->triggerSimulatorPinModes[0] = OM_DEFAULT;
boardConfiguration->triggerSimulatorPinModes[1] = OM_DEFAULT;
+ boardConfiguration->triggerSimulatorPinModes[2] = OM_DEFAULT;
boardConfiguration->HD44780_rs = GPIOE_9;
boardConfiguration->HD44780_e = GPIOE_11;
@@ -303,6 +316,9 @@ void setDefaultConfiguration(engine_configuration_s *engineConfiguration, board_
boardConfiguration->HD44780_db6 = GPIOB_11;
boardConfiguration->HD44780_db7 = GPIOB_13;
+ boardConfiguration->gps_rx_pin = GPIOB_7;
+ boardConfiguration->gps_tx_pin = GPIOB_6;
+
memset(boardConfiguration->adcHwChannelEnabled, 0, sizeof(boardConfiguration->adcHwChannelEnabled));
boardConfiguration->adcHwChannelEnabled[0] = ADC_SLOW;
boardConfiguration->adcHwChannelEnabled[1] = ADC_SLOW;
@@ -316,10 +332,10 @@ void setDefaultConfiguration(engine_configuration_s *engineConfiguration, board_
boardConfiguration->adcHwChannelEnabled[12] = ADC_SLOW;
boardConfiguration->adcHwChannelEnabled[13] = ADC_SLOW;
- boardConfiguration->primaryTriggerInputPin = GPIOC_6;
- boardConfiguration->secondaryTriggerInputPin = GPIOA_5;
- boardConfiguration->primaryLogicAnalyzerPin = GPIOA_8;
- boardConfiguration->secondaryLogicAnalyzerPin = GPIOE_7;
+ boardConfiguration->triggerInputPins[0] = GPIOC_6;
+ boardConfiguration->triggerInputPins[1] = GPIOA_5;
+ boardConfiguration->logicAnalyzerPins[0] = GPIOA_8;
+ boardConfiguration->logicAnalyzerPins[1] = GPIOE_7;
boardConfiguration->idleThreadPeriod = 100;
boardConfiguration->consoleLoopPeriod = 200;
@@ -342,13 +358,8 @@ void setDefaultConfiguration(engine_configuration_s *engineConfiguration, board_
boardConfiguration->digitalPotentiometerChipSelect[3] = GPIO_NONE;
}
-void setDefaultNonPersistentConfiguration(engine_configuration2_s *engineConfiguration2) {
- /**
- * 720 is the range for four stroke
- */
-// engineConfiguration2->crankAngleRange = 720;
-
-}
+//void setDefaultNonPersistentConfiguration(engine_configuration2_s *engineConfiguration2) {
+//}
void resetConfigurationExt(Logging * logger, engine_type_e engineType, engine_configuration_s *engineConfiguration,
engine_configuration2_s *engineConfiguration2, board_configuration_s *boardConfiguration) {
@@ -381,8 +392,17 @@ void resetConfigurationExt(Logging * logger, engine_type_e engineType, engine_co
setNissanPrimeraEngineConfiguration(engineConfiguration);
break;
#endif
- case HONDA_ACCORD:
- setHondaAccordConfiguration(engineConfiguration, boardConfiguration);
+ case HONDA_ACCORD_CD:
+ setHondaAccordConfigurationThreeWires(engineConfiguration, boardConfiguration);
+ break;
+ case HONDA_ACCORD_CD_TWO_WIRES:
+ setHondaAccordConfigurationTwoWires(engineConfiguration, boardConfiguration);
+ break;
+ case HONDA_ACCORD_CD_DIP:
+ setHondaAccordConfigurationDip(engineConfiguration, boardConfiguration);
+ break;
+ case MITSU_4G93:
+ setMitsubishiConfiguration(engineConfiguration, boardConfiguration);
break;
#if EFI_SUPPORT_1995_FORD_INLINE_6 || defined(__DOXYGEN__)
case FORD_INLINE_6_1995:
@@ -435,8 +455,6 @@ void applyNonPersistentConfiguration(Logging * logger, engine_configuration_s *e
#if EFI_PROD_CODE
scheduleMsg(logger, "applyNonPersistentConfiguration()");
#endif
- engineConfiguration2->isInjectionEnabledFlag = TRUE;
-
initializeTriggerShape(logger, engineConfiguration, engineConfiguration2);
if (engineConfiguration2->triggerShape.getSize() == 0) {
firmwareError("triggerShape size is zero");
diff --git a/firmware/controllers/algo/engine_configuration.h b/firmware/controllers/algo/engine_configuration.h
index 86b5b2dcef..b13693ef77 100644
--- a/firmware/controllers/algo/engine_configuration.h
+++ b/firmware/controllers/algo/engine_configuration.h
@@ -77,7 +77,7 @@ typedef enum {
} can_device_mode_e;
typedef struct {
- int afrAdcChannel;
+ adc_channel_e afrAdcChannel;
float v1;
float value1;
float v2;
@@ -143,8 +143,13 @@ typedef struct {
brain_pin_e HD44780_db6;
brain_pin_e HD44780_db7;
- brain_pin_e triggerSimulatorPins[2];
- pin_output_mode_e triggerSimulatorPinModes[2];
+ brain_pin_e gps_rx_pin;
+ brain_pin_e gps_tx_pin;
+
+ int idleSolenoidFrequency;
+
+ int unused;
+
/**
* Digital Potentiometer is used by stock ECU stimulation code
@@ -154,10 +159,8 @@ typedef struct {
adc_channel_mode_e adcHwChannelEnabled[HW_MAX_ADC_INDEX];
- brain_pin_e primaryTriggerInputPin;
- brain_pin_e secondaryTriggerInputPin;
- brain_pin_e primaryLogicAnalyzerPin;
- brain_pin_e secondaryLogicAnalyzerPin;
+ brain_pin_e triggerInputPins[2];
+ brain_pin_e logicAnalyzerPins[2];
int idleThreadPeriod;
int consoleLoopPeriod;
@@ -173,6 +176,15 @@ typedef struct {
brain_pin_e canTxPin;
brain_pin_e canRxPin;
+ brain_pin_e triggerSimulatorPins[3];
+ pin_output_mode_e triggerSimulatorPinModes[3];
+
+ brain_pin_e o2heaterPin;
+ pin_output_mode_e o2heaterPinModeTodO;
+
+ int unused2[8];
+
+
} board_configuration_s;
@@ -207,7 +219,11 @@ typedef struct {
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
+ /**
+ * Should the trigger emulator push data right into trigger input, eliminating the need for physical jumper wires?
+ * PS: Funny name, right? :)
+ */
+ short int directSelfStimulation; // 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
@@ -265,7 +281,6 @@ typedef struct {
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)
@@ -329,21 +344,21 @@ typedef struct {
int HD44780width;
int HD44780height;
- int tpsAdcChannel;
+ adc_channel_e tpsAdcChannel;
int overrideCrankingIgnition;
int analogChartFrequency;
trigger_config_s triggerConfig;
int space;
- int vBattAdcChannel;
+ adc_channel_e vBattAdcChannel;
float globalFuelCorrection;
// todo: merge with channel settings, use full-scale Thermistor!
- int cltAdcChannel;
- int iatAdcChannel;
- int mafAdcChannel;
+ adc_channel_e cltAdcChannel;
+ adc_channel_e iatAdcChannel;
+ adc_channel_e mafAdcChannel;
afr_sensor_s afrSensor;
@@ -367,12 +382,20 @@ typedef struct {
float veTable[VE_LOAD_COUNT][VE_RPM_COUNT]; // size 1024
float afrTable[AFR_LOAD_COUNT][AFR_RPM_COUNT]; // size 1024
-
board_configuration_s bc;
int hasMapSensor;
int hasCltSensor;
+ idle_mode_e idleMode;
+
+ bool isInjectionEnabled : 1; // bit 0
+ bool isIgnitionEnabled : 1; // bit 1
+ bool isCylinderCleanupEnabled : 1; // bit 2
+ bool secondTriggerChannelEnabled : 1; // bit 3
+
+
+ int unused3[8];
} engine_configuration_s;
diff --git a/firmware/controllers/algo/error_handling.h b/firmware/controllers/algo/error_handling.h
index e9176c57ee..29712833a1 100644
--- a/firmware/controllers/algo/error_handling.h
+++ b/firmware/controllers/algo/error_handling.h
@@ -29,6 +29,7 @@ int warning(obd_code_e code, const char *fmt, ...);
*/
void firmwareError(const char *fmt, ...);
bool hasFirmwareError(void);
+char *getFirmwareError(void);
/**
* declared as a macro so that this code does not use stack
@@ -43,6 +44,7 @@ bool hasFirmwareError(void);
void chDbgPanic3(const char *msg, const char * file, int line);
void initErrorHandling(void);
+char *getWarninig(void);
// todo: better place for this shared declaration?
int getRusEfiVersion(void);
diff --git a/firmware/controllers/algo/event_registry.h b/firmware/controllers/algo/event_registry.h
index 1d455eb8a2..8df696ab4d 100644
--- a/firmware/controllers/algo/event_registry.h
+++ b/firmware/controllers/algo/event_registry.h
@@ -62,7 +62,7 @@ void ArrayList< Type, Dimention>::resetEventList(void) {
template
Type * ArrayList< Type, Dimention>::getNextActuatorEvent(void) {
- efiAssert(size < Dimention, "registerActuatorEvent() too many events", NULL);
+ efiAssert(size < Dimention, "registerActuatorEvent() too many events", (Type *)NULL);
return &events[size++];
}
diff --git a/firmware/controllers/algo/fuel_math.h b/firmware/controllers/algo/fuel_math.h
index 80b5a8ecf9..30e852b5d2 100644
--- a/firmware/controllers/algo/fuel_math.h
+++ b/firmware/controllers/algo/fuel_math.h
@@ -23,6 +23,7 @@ float getIatCorrection(float iat);
float getInjectorLag(float vBatt);
float getCltCorrection(float clt);
float getRunningFuel(float baseFuel, Engine *engine, int rpm);
+float getCrankingFuel(void);
float getStartingFuel(float coolantTemperature);
float getFuelMs(int rpm, Engine *engine);
diff --git a/firmware/controllers/algo/idle_controller.c b/firmware/controllers/algo/idle_controller.c
index d172a00ef0..fdbbbe3461 100644
--- a/firmware/controllers/algo/idle_controller.c
+++ b/firmware/controllers/algo/idle_controller.c
@@ -78,10 +78,10 @@ int getIdle(IdleValveState *idle, int currentRpm, int now) {
}
if (currentRpm >= idle->targetRpmRangeRight + 100)
- return changeValue(idle, currentRpm, now, "rpm is too high: ", -IDLE_DECREASE_STEP);
+ return changeValue(idle, currentRpm, now, "idle control: rpm is too high: ", -IDLE_DECREASE_STEP);
if (currentRpm >= idle->targetRpmRangeRight)
- return changeValue(idle, currentRpm, now, "rpm is a bit too high: ", -1);
+ return changeValue(idle, currentRpm, now, "idle control: rpm is a bit too high: ", -1);
// we are here if RPM is low, let's see how low
// if (currentRpm < 0.7 * idle->targetRpmRangeLeft) {
@@ -89,7 +89,7 @@ int getIdle(IdleValveState *idle, int currentRpm, int now) {
// return setNewValue(idle, currentRpm, now, "RPMs are seriously low: ", 15 * IDLE_INCREASE_STEP);
// } else
if (currentRpm < idle->targetRpmRangeLeft - 100) {
- return changeValue(idle, currentRpm, now, "RPMs are low: ", IDLE_INCREASE_STEP);
+ return changeValue(idle, currentRpm, now, "idle control: RPMs are low: ", IDLE_INCREASE_STEP);
}
- return changeValue(idle, currentRpm, now, "RPMs are a bit low: ", 1);
+ return changeValue(idle, currentRpm, now, "idle control: RPMs are a bit low: ", 1);
}
diff --git a/firmware/controllers/algo/io_pins.h b/firmware/controllers/algo/io_pins.h
index 317853aacf..56625eab07 100644
--- a/firmware/controllers/algo/io_pins.h
+++ b/firmware/controllers/algo/io_pins.h
@@ -12,6 +12,9 @@
#define GPIO_NULL NULL
+/**
+ * Logical pins. See brain_pin_e for physical pins.
+ */
typedef enum {
LED_WARNING, // Orange on-board LED
LED_RUNNING, // Green on-board LED
@@ -23,9 +26,13 @@ typedef enum {
LED_DEBUG,
LED_EMULATOR,
+ /**
+ * see board_configuration_s->idleValvePin
+ */
IDLE_VALVE,
TRIGGER_EMULATOR_PRIMARY,
TRIGGER_EMULATOR_SECONDARY,
+ TRIGGER_EMULATOR_3RD,
SPARKOUT_1_OUTPUT,
SPARKOUT_2_OUTPUT,
@@ -57,6 +64,12 @@ typedef enum {
ELECTRONIC_THROTTLE_CONTROL_2,
ELECTRONIC_THROTTLE_CONTROL_3,
+ /**
+ * these seven segment display pins are related to unused external tachometer code
+ * I still have the hardware so maybe one day I will fix it, but for now it's just dead code
+ * See https://www.youtube.com/watch?v=YYiHoN6MBqE
+ * todo: this should be re-implemented in a smarter way with some sort of multiplexing anyway
+ */
/* digit 1 */
LED_HUGE_0, // B2
LED_HUGE_1,
@@ -87,6 +100,7 @@ typedef enum {
FUEL_PUMP_RELAY,
FAN_RELAY,
+ O2_HEATER,
SPI_CS_1,
SPI_CS_2,
diff --git a/firmware/controllers/algo/rusefi_enums.h b/firmware/controllers/algo/rusefi_enums.h
index 07d469be49..c2b89176fe 100644
--- a/firmware/controllers/algo/rusefi_enums.h
+++ b/firmware/controllers/algo/rusefi_enums.h
@@ -46,7 +46,7 @@ typedef enum {
NISSAN_PRIMERA = 5,
#endif /* EFI_SUPPORT_NISSAN_PRIMERA */
- HONDA_ACCORD = 6,
+ HONDA_ACCORD_CD = 6,
FORD_INLINE_6_1995 = 7,
/**
@@ -70,6 +70,15 @@ typedef enum {
CITROEN_TU3JP = 15,
+ MITSU_4G93 = 16,
+
+ /**
+ * a version of HONDA_ACCORD_CD which only uses two of three trigger input sensors
+ */
+ HONDA_ACCORD_CD_TWO_WIRES = 17,
+
+ HONDA_ACCORD_CD_DIP = 18,
+
Internal_ForceMyEnumIntSize_engine_type = ENUM_SIZE_HACK,
} engine_type_e;
@@ -85,6 +94,14 @@ typedef enum {
TT_TOOTHED_WHEEL_60_2 = 8,
TT_TOOTHED_WHEEL_36_1 = 9,
+ TT_HONDA_ACCORD_CD = 10,
+
+ TT_MITSU = 11,
+
+ TT_HONDA_ACCORD_CD_TWO_WIRES = 12,
+
+ TT_HONDA_ACCORD_CD_DIP = 13,
+
Internal_ForceMyEnumIntSize_trigger_type = ENUM_SIZE_HACK,
} trigger_type_e;
@@ -96,11 +113,28 @@ typedef enum {
Internal_ForceMyEnumIntSize_adc_channel_mode = ENUM_SIZE_HACK,
} adc_channel_mode_e;
+// todo: better names?
typedef enum {
- SHAFT_PRIMARY_UP = 0,
- SHAFT_PRIMARY_DOWN = 1,
- SHAFT_SECONDARY_UP = 2,
- SHAFT_SECONDARY_DOWN = 3,
+ TV_LOW = 0,
+ TV_HIGH = 1
+} trigger_value_e;
+
+// todo: better names?
+typedef enum {
+ T_PRIMARY = 0,
+ T_SECONDARY = 1,
+ // todo: I really do not want to call this 'tertiary'. maybe we should rename all of these?
+ T_CHANNEL_3 = 2
+} trigger_wheel_e;
+
+// todo: better names?
+typedef enum {
+ SHAFT_PRIMARY_DOWN = 0,
+ SHAFT_PRIMARY_UP = 1,
+ SHAFT_SECONDARY_DOWN = 2,
+ SHAFT_SECONDARY_UP = 3,
+ SHAFT_3RD_DOWN = 4,
+ SHAFT_3RD_UP = 5,
} trigger_event_e;
/**
@@ -149,6 +183,13 @@ typedef enum {
Internal_ForceMyEnumIntSize_log_format = ENUM_SIZE_HACK,
} log_format_e;
+
+typedef enum {
+ IM_AUTO = 0,
+ IM_MANUAL = 1,
+ Internal_ForceMyEnumIntSize_idle_mode = ENUM_SIZE_HACK,
+} idle_mode_e;
+
typedef enum {
/**
* GND for logical OFF, VCC for logical ON
@@ -244,6 +285,29 @@ typedef enum {
Internal_ForceMyEnumIntSize_cranking_internal_error = ENUM_SIZE_HACK,
} internal_error_e;
+typedef enum {
+ EFI_ADC_0 = 0,
+ EFI_ADC_1 = 1,
+ EFI_ADC_2 = 2,
+ EFI_ADC_3 = 3,
+ EFI_ADC_4 = 4,
+ EFI_ADC_5 = 5,
+ EFI_ADC_6 = 6,
+ EFI_ADC_7 = 7,
+ EFI_ADC_8 = 8,
+ EFI_ADC_9 = 9,
+ EFI_ADC_10 = 10,
+ EFI_ADC_11 = 11,
+ EFI_ADC_12 = 12,
+ EFI_ADC_13 = 13,
+ EFI_ADC_14 = 14,
+ EFI_ADC_15 = 15,
+
+ EFI_ADC_ERROR = 999,
+
+ Internal_ForceMyEnumIntSize_cranking_adc_channel = ENUM_SIZE_HACK,
+} adc_channel_e;
+
/**
* Hardware pin. This enum is platform-specific.
*/
@@ -334,6 +398,7 @@ typedef enum {
GPIOE_15 = 79,
GPIO_NONE = 80,
+ GPIO_INVALID = 81,
Internal_ForceMyEnumIntSize_cranking_brain_pin = ENUM_SIZE_HACK,
} brain_pin_e;
diff --git a/firmware/controllers/algo/wave_chart.c b/firmware/controllers/algo/wave_chart.c
index 18d809cbb8..fc0bbf8643 100644
--- a/firmware/controllers/algo/wave_chart.c
+++ b/firmware/controllers/algo/wave_chart.c
@@ -79,7 +79,7 @@ void resetWaveChart(WaveChart *chart) {
static char WAVE_LOGGING_BUFFER[WAVE_LOGGING_SIZE] CCM_OPTIONAL
;
-int isWaveChartFull(WaveChart *chart) {
+static int isWaveChartFull(WaveChart *chart) {
return chart->counter >= chartSize;
}
@@ -94,8 +94,9 @@ static void setChartActive(int value) {
}
void setChartSize(int newSize) {
- if (newSize < 5)
+ if (newSize < 5) {
return;
+ }
chartSize = newSize;
printStatus();
}
@@ -114,8 +115,10 @@ void publishChart(WaveChart *chart) {
Logging *l = &chart->logging;
scheduleSimpleMsg(&debugLogging, "IT'S TIME", strlen(l->buffer));
#endif
- if (isChartActive && getFullLog())
+ bool isFullLog = getFullLog();
+ if (isChartActive && isFullLog) {
scheduleLogging(&chart->logging);
+ }
}
static char timeBuffer[10];
@@ -128,8 +131,9 @@ void addWaveChartEvent3(WaveChart *chart, const char *name, const char * msg, co
#if DEBUG_WAVE
scheduleSimpleMsg(&debugLogging, "current", chart->counter);
#endif
- if (isWaveChartFull(chart))
+ if (isWaveChartFull(chart)) {
return;
+ }
#if EFI_HISTOGRAMS && EFI_PROD_CODE
int beforeCallback = hal_lld_get_counter_value();
@@ -140,8 +144,9 @@ void addWaveChartEvent3(WaveChart *chart, const char *name, const char * msg, co
bool alreadyLocked = lockOutputBuffer(); // we have multiple threads writing to the same output buffer
- if (chart->counter == 0)
+ if (chart->counter == 0) {
chart->startTime = time100;
+ }
chart->counter++;
if (remainingSize(&chart->logging) > 30) {
/**
@@ -161,13 +166,15 @@ void addWaveChartEvent3(WaveChart *chart, const char *name, const char * msg, co
appendFast(&chart->logging, msg2);
appendFast(&chart->logging, CHART_DELIMETER);
}
- if (!alreadyLocked)
+ if (!alreadyLocked) {
unlockOutputBuffer();
+ }
#if EFI_HISTOGRAMS && EFI_PROD_CODE
- int diff = hal_lld_get_counter_value() - beforeCallback;
- if (diff > 0)
+ int64_t diff = hal_lld_get_counter_value() - beforeCallback;
+ if (diff > 0) {
hsAdd(&waveChartHisto, diff);
+ }
#endif /* EFI_HISTOGRAMS */
}
@@ -181,8 +188,9 @@ void showWaveChartHistogram(void) {
void initWaveChart(WaveChart *chart) {
initLogging(&logger, "wave info");
- if (!isChartActive)
+ if (!isChartActive) {
printMsg(&logger, "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! chart disabled");
+ }
printStatus();
diff --git a/firmware/controllers/alternatorController.cpp b/firmware/controllers/alternatorController.cpp
index 6d69acf09e..a5a260f841 100644
--- a/firmware/controllers/alternatorController.cpp
+++ b/firmware/controllers/alternatorController.cpp
@@ -10,7 +10,6 @@
#include "main.h"
#include "rpm_calculator.h"
#include "pwm_generator.h"
-#include "wave_math.h"
#include "alternatorController.h"
#include "pin_repository.h"
#include "engine_configuration.h"
diff --git a/firmware/controllers/controllers.mk b/firmware/controllers/controllers.mk
index 3c6995a100..9d8b2bea7f 100644
--- a/firmware/controllers/controllers.mk
+++ b/firmware/controllers/controllers.mk
@@ -13,4 +13,5 @@ CONTROLLERS_SRC_CPP = $(PROJECT_DIR)/controllers/settings.cpp \
controllers/idle_thread.cpp \
controllers/PwmTester.cpp \
$(PROJECT_DIR)/controllers/alternatorController.cpp \
+ $(PROJECT_DIR)/controllers/lcd_controller.cpp \
$(PROJECT_DIR)/controllers/engine_controller.cpp
diff --git a/firmware/controllers/core/EfiWave.cpp b/firmware/controllers/core/EfiWave.cpp
index d67e822b9e..bd79907ed4 100644
--- a/firmware/controllers/core/EfiWave.cpp
+++ b/firmware/controllers/core/EfiWave.cpp
@@ -44,7 +44,7 @@ float multi_wave_s::getSwitchTime(int index) const {
void checkSwitchTimes2(int size, float *switchTimes) {
for (int i = 0; i < size - 1; i++) {
if (switchTimes[i] >= switchTimes[i + 1]) {
- firmwareError("invalid switchTimes");
+ firmwareError("invalid switchTimes @%d: %f/%f", i, switchTimes[i], switchTimes[i + 1]);
}
}
}
diff --git a/firmware/controllers/core/EfiWave.h b/firmware/controllers/core/EfiWave.h
index fbe52c6d06..182a52d47b 100644
--- a/firmware/controllers/core/EfiWave.h
+++ b/firmware/controllers/core/EfiWave.h
@@ -10,7 +10,7 @@
#include "engine_configuration.h"
#define PWM_PHASE_MAX_COUNT 250
-#define PWM_PHASE_MAX_WAVE_PER_PWM 2
+#define PWM_PHASE_MAX_WAVE_PER_PWM 3
/**
* @brief PWM configuration for the specific output pin
@@ -35,6 +35,10 @@ public:
void setSwitchTime(int phaseIndex, float value);
void checkSwitchTimes(int size);
int getChannelState(int channelIndex, int phaseIndex) const;
+
+ int findAngleMatch(float angle, int size) const;
+ int waveIndertionAngle(float angle, int size) const;
+
/**
* Number of signal wires
*/
@@ -49,5 +53,7 @@ public:
};
void checkSwitchTimes2(int size, float *switchTimes);
+void configureHondaAccordCD(trigger_shape_s *s, bool with3rdSignal);
+void configureHondaAccordCDDip(trigger_shape_s *s);
#endif /* EFI_WAVE_H_ */
diff --git a/firmware/controllers/core/avg_values.c b/firmware/controllers/core/avg_values.c
index 65bd1b1c9e..2794e5e4a3 100644
--- a/firmware/controllers/core/avg_values.c
+++ b/firmware/controllers/core/avg_values.c
@@ -22,10 +22,9 @@ void avgReset(AvgTable *table) {
}
void avgAddValue(AvgTable *table, int rpm, float key, float value) {
- if (rpm >= MAX_RPM)
- return;
- if (key >= MAX_KEY)
+ if (rpm >= MAX_RPM || key >= MAX_KEY) {
return;
+ }
int i = (int)(AVG_TAB_SIZE * rpm / MAX_RPM);
int j = (int)(AVG_TAB_SIZE * key / MAX_KEY);
@@ -35,26 +34,25 @@ void avgAddValue(AvgTable *table, int rpm, float key, float value) {
float avgGetValueByIndexes(AvgTable *table, int i, int j) {
int count = table->counts[i][j];
- if (count == 0)
+ if (count == 0) {
return NAN;
+ }
return table->values[i][j] / count;
}
float avgGetValue(AvgTable *table, int rpm, float key) {
- if (rpm >= MAX_RPM)
- return NAN;
- if (key >= MAX_KEY)
+ if (rpm >= MAX_RPM || key >= MAX_KEY) {
return NAN;
+ }
int i = (int)(AVG_TAB_SIZE * rpm / MAX_RPM);
int j = (int)(AVG_TAB_SIZE * key / MAX_KEY);
return avgGetValueByIndexes(table, i, j);
}
int avgGetValuesCount(AvgTable *table, int rpm, float key) {
- if (rpm >= MAX_RPM)
- return 0;
- if (key >= MAX_KEY)
+ if (rpm >= MAX_RPM || key >= MAX_KEY) {
return 0;
+ }
int i = (int)(AVG_TAB_SIZE * rpm / MAX_RPM);
int j = (int)(AVG_TAB_SIZE * key / MAX_KEY);
diff --git a/firmware/controllers/core/table_helper.h b/firmware/controllers/core/table_helper.h
index 58998ac7e0..c4367fdec6 100644
--- a/firmware/controllers/core/table_helper.h
+++ b/firmware/controllers/core/table_helper.h
@@ -26,8 +26,9 @@ private:
template
void Map3D::init(float table[RPM_BIN_SIZE][LOAD_BIN_SIZE]) {
- for (int k = 0; k < LOAD_BIN_SIZE; k++)
+ for (int k = 0; k < LOAD_BIN_SIZE; k++) {
pointers[k] = table[k];
+ }
initialized = MAGIC_TRUE_VALUE;
}
diff --git a/firmware/controllers/engine_controller.cpp b/firmware/controllers/engine_controller.cpp
index 7e591904df..1221b21a33 100644
--- a/firmware/controllers/engine_controller.cpp
+++ b/firmware/controllers/engine_controller.cpp
@@ -30,6 +30,7 @@
#include "main_trigger_callback.h"
#include "map_multiplier_thread.h"
#include "io_pins.h"
+#include "flash_main.h"
#include "tunerstudio.h"
#include "injector_central.h"
#include "ignition_central.h"
@@ -54,7 +55,8 @@
extern board_configuration_s *boardConfiguration;
-persistent_config_container_s persistentState CCM_OPTIONAL;
+persistent_config_container_s persistentState CCM_OPTIONAL
+;
engine_configuration_s *engineConfiguration = &persistentState.persistentConfiguration.engineConfiguration;
board_configuration_s *boardConfiguration = &persistentState.persistentConfiguration.engineConfiguration.bc;
@@ -69,10 +71,11 @@ static VirtualTimer fuelPumpTimer;
static Logging logger;
-static engine_configuration2_s ec2 CCM_OPTIONAL;
+static engine_configuration2_s ec2 CCM_OPTIONAL
+;
engine_configuration2_s * engineConfiguration2 = &ec2;
-static configuration_s cfg = {&persistentState.persistentConfiguration.engineConfiguration, &ec2};
+static configuration_s cfg = { &persistentState.persistentConfiguration.engineConfiguration, &ec2 };
configuration_s * configuration = &cfg;
@@ -104,10 +107,8 @@ static void updateErrorCodes(void) {
/**
* technically we can set error codes right inside the getMethods, but I a bit on a fence about it
*/
- setError(isValidIntakeAirTemperature(getIntakeAirTemperature()),
- OBD_Intake_Air_Temperature_Circuit_Malfunction);
- setError(isValidCoolantTemperature(getCoolantTemperature()),
- OBD_Engine_Coolant_Temperature_Circuit_Malfunction);
+ setError(isValidIntakeAirTemperature(getIntakeAirTemperature()), OBD_Intake_Air_Temperature_Circuit_Malfunction);
+ setError(isValidCoolantTemperature(getCoolantTemperature()), OBD_Engine_Coolant_Temperature_Circuit_Malfunction);
}
static void fanRelayControl(void) {
@@ -118,11 +119,9 @@ static void fanRelayControl(void) {
int newValue;
if (isCurrentlyOn) {
// if the fan is already on, we keep it on till the 'fanOff' temperature
- newValue = getCoolantTemperature()
- > engineConfiguration->fanOffTemperature;
+ newValue = getCoolantTemperature() > engineConfiguration->fanOffTemperature;
} else {
- newValue = getCoolantTemperature()
- > engineConfiguration->fanOnTemperature;
+ newValue = getCoolantTemperature() > engineConfiguration->fanOnTemperature;
}
if (isCurrentlyOn != newValue) {
@@ -156,25 +155,31 @@ static void onEvenyGeneralMilliseconds(void *arg) {
*/
halTime.get(hal_lld_get_counter_value(), true);
+ if (!engine.rpmCalculator->isRunning())
+ writeToFlashIfPending();
+
engine.updateSlowSensors();
updateErrorCodes();
fanRelayControl();
+ setOutputPinValue(O2_HEATER, engine.rpmCalculator->isRunning());
+
// schedule next invocation
- chVTSetAny(&everyMsTimer, boardConfiguration->generalPeriodicThreadPeriod * TICKS_IN_MS, &onEvenyGeneralMilliseconds, 0);
+ chVTSetAny(&everyMsTimer, boardConfiguration->generalPeriodicThreadPeriod * TICKS_IN_MS,
+ &onEvenyGeneralMilliseconds, 0);
}
static void initPeriodicEvents(void) {
// schedule first invocation
- chVTSetAny(&everyMsTimer, boardConfiguration->generalPeriodicThreadPeriod * TICKS_IN_MS, &onEvenyGeneralMilliseconds, 0);
+ chVTSetAny(&everyMsTimer, boardConfiguration->generalPeriodicThreadPeriod * TICKS_IN_MS,
+ &onEvenyGeneralMilliseconds, 0);
}
static void fuelPumpOff(void *arg) {
if (getOutputPinValue(FUEL_PUMP_RELAY))
- scheduleMsg(&logger, "fuelPump OFF at %s%d",
- hwPortname(boardConfiguration->fuelPumpPin));
+ scheduleMsg(&logger, "fuelPump OFF at %s%d", hwPortname(boardConfiguration->fuelPumpPin));
turnOutputPinOff(FUEL_PUMP_RELAY);
}
@@ -182,10 +187,8 @@ static void fuelPumpOn(trigger_event_e signal, int index, void *arg) {
if (index != 0)
return; // let's not abuse the timer - one time per revolution would be enough
// todo: the check about GPIO_NONE should be somewhere else!
- if (!getOutputPinValue(FUEL_PUMP_RELAY)
- && boardConfiguration->fuelPumpPin != GPIO_NONE)
- scheduleMsg(&logger, "fuelPump ON at %s",
- hwPortname(boardConfiguration->fuelPumpPin));
+ if (!getOutputPinValue(FUEL_PUMP_RELAY) && boardConfiguration->fuelPumpPin != GPIO_NONE)
+ scheduleMsg(&logger, "fuelPump ON at %s", hwPortname(boardConfiguration->fuelPumpPin));
turnOutputPinOn(FUEL_PUMP_RELAY);
/**
* the idea of this implementation is that we turn the pump when the ECU turns on or
@@ -200,7 +203,7 @@ static void initFuelPump(void) {
fuelPumpOn(SHAFT_PRIMARY_UP, 0, NULL);
}
-char * getPinNameByAdcChannel(int hwChannel, char *buffer) {
+char * getPinNameByAdcChannel(adc_channel_e hwChannel, char *buffer) {
strcpy((char*) buffer, portname(getAdcChannelPort(hwChannel)));
itoa10(&buffer[2], getAdcChannelPin(hwChannel));
return (char*) buffer;
@@ -208,14 +211,14 @@ char * getPinNameByAdcChannel(int hwChannel, char *buffer) {
static char pinNameBuffer[16];
-static void printAnalogChannelInfoExt(const char *name, int hwChannel,
- float adcVoltage) {
+static void printAnalogChannelInfoExt(const char *name, adc_channel_e hwChannel, float adcVoltage) {
float voltage = adcVoltage * engineConfiguration->analogInputDividerCoefficient;
- scheduleMsg(&logger, "%s ADC%d %s rawValue=%f/divided=%fv", name, hwChannel,
+ scheduleMsg(&logger, "%s ADC%d %s %s rawValue=%f/divided=%fv", name, hwChannel,
+ getAdcMode(hwChannel),
getPinNameByAdcChannel(hwChannel, pinNameBuffer), adcVoltage, voltage);
}
-static void printAnalogChannelInfo(const char *name, int hwChannel) {
+static void printAnalogChannelInfo(const char *name, adc_channel_e hwChannel) {
printAnalogChannelInfoExt(name, hwChannel, getVoltage(hwChannel));
}
@@ -227,11 +230,10 @@ static void printAnalogInfo(void) {
printAnalogChannelInfo("AFR", engineConfiguration->afrSensor.afrAdcChannel);
printAnalogChannelInfo("MAP", engineConfiguration->map.sensor.hwChannel);
printAnalogChannelInfo("BARO", engineConfiguration->baroSensor.hwChannel);
- printAnalogChannelInfoExt("Vbatt", engineConfiguration->vBattAdcChannel,
- getVBatt());
+ printAnalogChannelInfoExt("Vbatt", engineConfiguration->vBattAdcChannel, getVBatt());
}
-static THD_WORKING_AREA(csThreadStack, UTILITY_THREAD_STACK_SIZE);// declare thread stack
+static THD_WORKING_AREA(csThreadStack, UTILITY_THREAD_STACK_SIZE); // declare thread stack
void initEngineContoller(void) {
if (hasFirmwareError())
@@ -269,8 +271,7 @@ void initEngineContoller(void) {
// multiple issues with this initMapAdjusterThread();
initPeriodicEvents();
- chThdCreateStatic(csThreadStack, sizeof(csThreadStack), LOWPRIO,
- (tfunc_t) csThread, NULL);
+ chThdCreateStatic(csThreadStack, sizeof(csThreadStack), LOWPRIO, (tfunc_t) csThread, NULL);
initInjectorCentral();
initPwmTester();
@@ -306,6 +307,5 @@ void initEngineContoller(void) {
initFuelPump();
#endif
-
addConsoleAction("analoginfo", printAnalogInfo);
}
diff --git a/firmware/controllers/engine_controller.h b/firmware/controllers/engine_controller.h
index 89dae2505c..2061e69185 100644
--- a/firmware/controllers/engine_controller.h
+++ b/firmware/controllers/engine_controller.h
@@ -13,7 +13,7 @@
#include "signal_executor.h"
#include "engine_configuration.h"
-char * getPinNameByAdcChannel(int hwChannel, char *buffer);
+char * getPinNameByAdcChannel(adc_channel_e hwChannel, char *buffer);
void initEngineContoller(void);
#endif /* ENGINE_STATUS_H_ */
diff --git a/firmware/controllers/error_handling.c b/firmware/controllers/error_handling.c
index ad68fe2fc5..cd977e1df2 100644
--- a/firmware/controllers/error_handling.c
+++ b/firmware/controllers/error_handling.c
@@ -8,6 +8,7 @@
#include "main.h"
#include "error_handling.h"
#include "io_pins.h"
+#include "memstreams.h"
#if EFI_HD44780_LCD
#include "lcd_HD44780.h"
@@ -16,6 +17,8 @@
static time_t timeOfPreviousWarning = -10;
static Logging logger;
+#define WARNING_PREFIX "WARNING: "
+
extern int warningEnabled;
extern int main_loop_started;
@@ -45,6 +48,10 @@ void chDbgPanic3(const char *msg, const char * file, int line) {
}
}
+#define WARNING_BUFFER_SIZE 80
+static char warningBuffer[WARNING_BUFFER_SIZE];
+static MemoryStream warningStream;
+
/**
* @returns TRUE in case there are too many warnings
*/
@@ -56,16 +63,27 @@ int warning(obd_code_e code, const char *fmt, ...) {
resetLogging(&logger); // todo: is 'reset' really needed here?
appendMsgPrefix(&logger);
+
va_list ap;
va_start(ap, fmt);
- vappendPrintf(&logger, fmt, ap);
+ append(&logger, WARNING_PREFIX);
+ warningStream.eos = 0; // reset
+ chvprintf((BaseSequentialStream *) &warningStream, fmt, ap);
+ warningStream.buffer[warningStream.eos] = 0;
va_end(ap);
+
+ append(&logger, warningBuffer);
append(&logger, DELIMETER);
scheduleLogging(&logger);
return FALSE;
}
+char *getWarninig(void) {
+ return warningBuffer;
+}
+
void initErrorHandling(void) {
initLogging(&logger, "error handling");
+ msObjectInit(&warningStream, (uint8_t *)warningBuffer, WARNING_BUFFER_SIZE, 0);
}
diff --git a/firmware/controllers/flash_main.cpp b/firmware/controllers/flash_main.cpp
index b286fa6dd1..42a6d72be3 100644
--- a/firmware/controllers/flash_main.cpp
+++ b/firmware/controllers/flash_main.cpp
@@ -19,20 +19,12 @@
#include "datalogging.h"
-#include "audi_aan.h"
-#include "dodge_neon.h"
-#include "ford_aspire.h"
-#include "ford_fiesta.h"
-#include "ford_1995_inline_6.h"
-#include "snow_blower.h"
-#include "nissan_primera.h"
-#include "honda_accord.h"
-#include "GY6_139QMB.h"
-
#include "ec2.h"
static engine_type_e defaultEngineType = FORD_ASPIRE_1996;
+static bool needToWriteConfiguration = false;
+
static Logging logger;
extern persistent_config_container_s persistentState;
@@ -50,6 +42,24 @@ crc_t flashStateCrc(persistent_config_container_s *state) {
return calc_crc((const crc_t*) &state->persistentConfiguration, sizeof(persistent_config_s));
}
+void setNeedToWriteConfiguration(void) {
+ scheduleMsg(&logger, "Scheduling configuration write");
+ needToWriteConfiguration = true;
+}
+
+bool getNeedToWriteConfiguration(void) {
+ return needToWriteConfiguration;
+}
+
+void writeToFlashIfPending() {
+ if(!getNeedToWriteConfiguration())
+ return;
+ // todo: technically we need a lock here, realistically we should be fine.
+ needToWriteConfiguration = false;
+ scheduleMsg(&logger, "Writing pending configuration");
+ writeToFlash();
+}
+
void writeToFlash(void) {
#if EFI_INTERNAL_FLASH
persistentState.size = PERSISTENT_SIZE;
@@ -89,7 +99,7 @@ void readFromFlash(void) {
flashRead(FLASH_ADDR, (char *) &persistentState, PERSISTENT_SIZE);
- setDefaultNonPersistentConfiguration(engineConfiguration2);
+ //setDefaultNonPersistentConfiguration(engineConfiguration2);
if (!isValidCrc(&persistentState) || persistentState.size != PERSISTENT_SIZE) {
printMsg(&logger, "Need to reset flash to default");
@@ -104,7 +114,6 @@ void readFromFlash(void) {
}
void initFlash(void) {
- print("initFlash()\r\n");
initLogging(&logger, "Flash memory");
addConsoleAction("readconfig", readFromFlash);
diff --git a/firmware/controllers/flash_main.h b/firmware/controllers/flash_main.h
index a28338d5c2..bb708fde8c 100644
--- a/firmware/controllers/flash_main.h
+++ b/firmware/controllers/flash_main.h
@@ -11,7 +11,7 @@
#include "engine_configuration.h"
-#define FLASH_DATA_VERSION 3975
+#define FLASH_DATA_VERSION 4320
#ifdef __cplusplus
extern "C"
@@ -20,7 +20,19 @@ extern "C"
void readFromFlash(void);
void initFlash(void);
+/**
+ * Because of hardware-related issues, stm32f4 chip is totally
+ * frozen while we are writing to internal flash. Writing the configuration takes
+ * about 1-2 seconds, we cannot afford to do that while the engine is
+ * running so we postpone the write until the engine is stopped.
+ */
void writeToFlash(void);
+void setNeedToWriteConfiguration(void);
+/**
+ * @return true if an flash write is pending
+ */
+bool getNeedToWriteConfiguration(void);
+void writeToFlashIfPending(void);
#ifdef __cplusplus
}
diff --git a/firmware/controllers/idle_thread.cpp b/firmware/controllers/idle_thread.cpp
index 566b5de12b..324d761565 100644
--- a/firmware/controllers/idle_thread.cpp
+++ b/firmware/controllers/idle_thread.cpp
@@ -27,18 +27,15 @@
#include "idle_controller.h"
#include "rpm_calculator.h"
#include "pwm_generator.h"
-#include "wave_math.h"
#include "idle_thread.h"
#include "pin_repository.h"
#include "engine_configuration.h"
#include "engine.h"
-#define IDLE_AIR_CONTROL_VALVE_PWM_FREQUENCY 200
-
static THD_WORKING_AREA(ivThreadStack, UTILITY_THREAD_STACK_SIZE);
-static volatile int isIdleControlActive = EFI_IDLE_CONTROL;
extern board_configuration_s *boardConfiguration;
+extern engine_configuration_s *engineConfiguration;
/**
* here we keep the value we got from IDLE SWITCH input
@@ -48,7 +45,7 @@ static volatile int idleSwitchState;
static Logging logger;
extern Engine engine;
-static SimplePwm idleValve;
+static SimplePwm idleValvePwm;
/**
* Idle level calculation algorithm lives in idle_controller.c
@@ -65,20 +62,21 @@ void idleDebug(char *msg, int value) {
}
static void setIdleControlEnabled(int value) {
- isIdleControlActive = value;
- scheduleMsg(&logger, "isIdleControlActive=%d", isIdleControlActive);
+ engineConfiguration->idleMode = value ? IM_MANUAL : IM_AUTO;
+ scheduleMsg(&logger, "isIdleControlActive=%d", engineConfiguration->idleMode);
}
static void setIdleValvePwm(int value) {
// todo: change parameter type, maybe change parameter validation?
if (value < 1 || value > 999)
return;
- scheduleMsg(&logger, "setting idle valve PWM %d", value);
+ scheduleMsg(&logger, "setting idle valve PWM %d @%d on %s", value, boardConfiguration->idleSolenoidFrequency,
+ hwPortname(boardConfiguration->idleValvePin));
/**
* currently idle level is an integer per mil (0-1000 range), and PWM takes a float in the 0..1 range
* todo: unify?
*/
- idleValve.setSimplePwmDutyCycle(0.001 * value);
+ idleValvePwm.setSimplePwmDutyCycle(0.001 * value);
}
static msg_t ivThread(int param) {
@@ -91,7 +89,7 @@ static msg_t ivThread(int param) {
// this value is not used yet
idleSwitchState = palReadPad(getHwPort(boardConfiguration->idleSwitchPin), getHwPin(boardConfiguration->idleSwitchPin));
- if (!isIdleControlActive)
+ if (engineConfiguration->idleMode != IM_AUTO)
continue;
int nowSec = getTimeNowSeconds();
@@ -117,10 +115,13 @@ static void setIdleRpmAction(int value) {
void startIdleThread() {
initLogging(&logger, "Idle Valve Control");
- startSimplePwmExt(&idleValve, "Idle Valve",
+ /**
+ * Start PWM for IDLE_VALVE logical / idleValvePin physical
+ */
+ startSimplePwmExt(&idleValvePwm, "Idle Valve",
boardConfiguration->idleValvePin,
IDLE_VALVE,
- IDLE_AIR_CONTROL_VALVE_PWM_FREQUENCY,
+ boardConfiguration->idleSolenoidFrequency,
0.5);
idleInit(&idle);
diff --git a/firmware/controllers/injector_central.cpp b/firmware/controllers/injector_central.cpp
index c083bb58a3..a71747e2d5 100644
--- a/firmware/controllers/injector_central.cpp
+++ b/firmware/controllers/injector_central.cpp
@@ -32,7 +32,6 @@
static Logging logger;
extern engine_configuration_s *engineConfiguration;
-extern engine_configuration2_s *engineConfiguration2;
extern board_configuration_s *boardConfiguration;
static int is_injector_enabled[MAX_INJECTOR_COUNT];
@@ -76,46 +75,83 @@ static void setInjectorEnabled(int id, int value) {
printStatus();
}
-void runBench(brain_pin_e brainPin, io_pin_e pin, float onTime, float offTime, int count) {
- scheduleMsg(&logger, "Running bench: ON_TIME=%f ms OFF_TIME=%fms Counter=%d", onTime, offTime, count);
+static void runBench(brain_pin_e brainPin, io_pin_e pin, float delayMs, float onTimeMs, float offTimeMs, int count) {
+ scheduleMsg(&logger, "Running bench: ON_TIME=%f ms OFF_TIME=%fms Counter=%d", onTimeMs, offTimeMs, count);
scheduleMsg(&logger, "output on %s", hwPortname(brainPin));
+ int delaySt = (int) (delayMs * CH_FREQUENCY / 1000);
+ if (delaySt != 0) {
+ chThdSleep(delaySt);
+ }
+
for (int i = 0; i < count; i++) {
setOutputPinValue(pin, TRUE);
- chThdSleep((int) (onTime * CH_FREQUENCY / 1000));
+ chThdSleep((int) (onTimeMs * CH_FREQUENCY / 1000));
setOutputPinValue(pin, FALSE);
- chThdSleep((int) (offTime * CH_FREQUENCY / 1000));
+ int offTimeSt = (int) (offTimeMs * CH_FREQUENCY / 1000);
+ if (offTimeSt > 0) {
+ chThdSleep(offTimeSt);
+ }
}
scheduleMsg(&logger, "Done!");
}
static volatile int needToRunBench = FALSE;
-float onTime;
-float offTime;
-int count;
-brain_pin_e brainPin;
-io_pin_e pin;
+static float onTime;
+static float offTime;
+static float delayMs;
+static int count;
+static brain_pin_e brainPin;
+static io_pin_e pin;
-static void fuelbench(char * onStr, char *offStr, char *countStr) {
- onTime = atoff(onStr);
- offTime = atoff(offStr);
+static void pinbench(const char *delayStr, const char *onTimeStr, const char *offTimeStr, const char *countStr,
+ io_pin_e pinParam, brain_pin_e brainPinParam) {
+ delayMs = atoff(delayStr);
+ onTime = atoff(onTimeStr);
+ offTime = atoff(offTimeStr);
count = atoi(countStr);
- brainPin = boardConfiguration->injectionPins[0];
- pin = INJECTOR_1_OUTPUT;
+ brainPin = brainPinParam;
+ pin = pinParam;
needToRunBench = TRUE;
}
-static void sparkbench(char * onStr, char *offStr, char *countStr) {
- onTime = atoff(onStr);
- offTime = atoff(offStr);
- count = atoi(countStr);
+static void fuelbench2(const char *delayStr, const char *indexStr, const char * onTimeStr, const char *offTimeStr,
+ const char *countStr) {
+ int index = atoi(indexStr);
+ brain_pin_e b = boardConfiguration->injectionPins[index - 1];
+ io_pin_e p = (io_pin_e) ((int) INJECTOR_1_OUTPUT - 1 + index);
+ pinbench(delayStr, onTimeStr, offTimeStr, countStr, p, b);
+}
+
+static void fuelpumpbench(int delayParam, int onTimeParam) {
+ brainPin = boardConfiguration->fuelPumpPin;
+ pin = FUEL_PUMP_RELAY;
+
+ delayMs = delayParam;
+ onTime = onTimeParam;
+ offTime = 0;
+ count = 1;
- brainPin = boardConfiguration->ignitionPins[0];
- pin = SPARKOUT_1_OUTPUT;
needToRunBench = TRUE;
}
+static void fuelbench(const char * onTimeStr, const char *offTimeStr, const char *countStr) {
+ fuelbench2("0", "1", onTimeStr, offTimeStr, countStr);
+}
+
+static void sparkbench2(const char *delayStr, const char *indexStr, const char * onTimeStr, const char *offTimeStr,
+ const char *countStr) {
+ int index = atoi(indexStr);
+ brain_pin_e b = boardConfiguration->ignitionPins[index - 1];
+ io_pin_e p = (io_pin_e) ((int) SPARKOUT_1_OUTPUT - 1 + index);
+ pinbench(delayStr, onTimeStr, offTimeStr, countStr, p, b);
+}
+
+static void sparkbench(const char * onTimeStr, const char *offTimeStr, const char *countStr) {
+ sparkbench2("0", "1", onTimeStr, offTimeStr, countStr);
+}
+
static THD_WORKING_AREA(benchThreadStack, UTILITY_THREAD_STACK_SIZE);
static msg_t benchThread(int param) {
@@ -126,7 +162,7 @@ static msg_t benchThread(int param) {
chThdSleepMilliseconds(200);
}
needToRunBench = FALSE;
- runBench(brainPin, pin, onTime, offTime, count);
+ runBench(brainPin, pin, delayMs, onTime, offTime, count);
}
#if defined __GNUC__
return 0;
@@ -142,15 +178,20 @@ void initInjectorCentral(void) {
// todo: should we move this code closer to the injection logic?
for (int i = 0; i < engineConfiguration->cylindersCount; i++) {
- io_pin_e pin = (io_pin_e)((int)INJECTOR_1_OUTPUT + i);
+ io_pin_e pin = (io_pin_e) ((int) INJECTOR_1_OUTPUT + i);
- outputPinRegisterExt2(getPinName(pin), pin,
- boardConfiguration->injectionPins[i], &boardConfiguration->injectionPinMode);
+ outputPinRegisterExt2(getPinName(pin), pin, boardConfiguration->injectionPins[i],
+ &boardConfiguration->injectionPinMode);
}
printStatus();
addConsoleActionII("injector", setInjectorEnabled);
+ addConsoleActionII("fuelpumpbench", &fuelpumpbench);
+
addConsoleActionSSS("fuelbench", &fuelbench);
addConsoleActionSSS("sparkbench", &sparkbench);
+
+ addConsoleActionSSSSS("fuelbench2", &fuelbench2);
+ addConsoleActionSSSSS("sparkbench2", &sparkbench2);
}
diff --git a/firmware/controllers/lcd_controller.cpp b/firmware/controllers/lcd_controller.cpp
new file mode 100644
index 0000000000..eb06fd77f0
--- /dev/null
+++ b/firmware/controllers/lcd_controller.cpp
@@ -0,0 +1,193 @@
+/**
+ * @file lcd_controller.cpp
+ *
+ * @date Aug 14, 2014
+ * @author Andrey Belomutskiy, (c) 2012-2014
+ */
+
+#include "main.h"
+#include "lcd_controller.h"
+#include "lcd_HD44780.h"
+#include "efilib.h"
+#include "rpm_calculator.h"
+#include "allsensors.h"
+#include "engine.h"
+#include "rtc_helper.h"
+#include "io_pins.h"
+
+extern Engine engine;
+extern engine_configuration_s *engineConfiguration;
+
+#define LCD_WIDTH 20
+// this value should be even
+#define NUMBER_OF_DIFFERENT_LINES 4
+
+char * appendStr(char *ptr, const char *suffix) {
+ for (uint32_t i = 0; i < strlen(suffix); i++) {
+ *ptr++ = suffix[i];
+ }
+ return ptr;
+}
+
+static char * prepareVBattMapLine(char *buffer) {
+ char *ptr = buffer;
+ *ptr++ = 'V';
+ ptr = ftoa(ptr, getVBatt(), 10.0f);
+
+ ptr = appendStr(ptr, " M");
+ ptr = ftoa(ptr, getRawMap(), 10.0f);
+ return ptr;
+}
+
+static char * prepareCltIatTpsLine(char *buffer) {
+ char *ptr = buffer;
+ *ptr++ = 'C';
+ ptr = ftoa(ptr, getCoolantTemperature(), 10.0f);
+
+ ptr = appendStr(ptr, " C");
+ ptr = ftoa(ptr, getIntakeAirTemperature(), 10.0f);
+
+ ptr = appendStr(ptr, " TP");
+ ptr = itoa10(ptr, (int) getTPS());
+ return ptr;
+}
+
+static const char* algorithmStr[] = { "MAF", "TPS", "MAP", "SD" };
+static const char* ignitionModeStr[] = { "1C", "IND", "WS" };
+static const char* injectionModeStr[] = { "Sim", "Seq", "Bch" };
+static const char* idleModeStr[] = { "I:A", "I:M" };
+
+static const char *getPinShortName(io_pin_e pin) {
+ switch (pin) {
+ case ALTERNATOR_SWITCH:
+ return "AL";
+ case FUEL_PUMP_RELAY:
+ return "FP";
+ case FAN_RELAY:
+ return "FN";
+ case O2_HEATER:
+ return "O2H";
+ default:
+ firmwareError("No short name for %d", (int) pin);
+ return "";
+ }
+}
+
+char * appendPinStatus(char *buffer, io_pin_e pin) {
+ char *ptr = appendStr(buffer, getPinShortName(pin));
+ int state = getOutputPinValue(pin);
+ // todo: should we handle INITIAL_PIN_STATE?
+ if (state) {
+ return appendStr(ptr, ":Y ");
+ } else {
+ return appendStr(ptr, ":n ");
+ }
+}
+
+static char * prepareInfoLine(char *buffer) {
+ char *ptr = buffer;
+
+ ptr = appendStr(ptr, algorithmStr[engineConfiguration->algorithm]);
+
+ ptr = appendStr(ptr, " ");
+ ptr = appendStr(ptr, ignitionModeStr[engineConfiguration->ignitionMode]);
+
+ ptr = appendStr(ptr, " ");
+ ptr = appendStr(ptr, injectionModeStr[engineConfiguration->injectionMode]);
+
+ ptr = appendStr(ptr, " ");
+ ptr = appendStr(ptr, idleModeStr[engineConfiguration->idleMode]);
+
+ ptr = appendStr(ptr, " ");
+ return ptr;
+}
+
+static char * prepareStatusLine(char *buffer) {
+ char *ptr = buffer;
+
+ ptr = appendPinStatus(ptr, FUEL_PUMP_RELAY);
+ ptr = appendPinStatus(ptr, FAN_RELAY);
+ ptr = appendPinStatus(ptr, O2_HEATER);
+ return ptr;
+}
+
+static char buffer[LCD_WIDTH + 4];
+static char dateBuffer[30];
+
+static void prepareCurrentSecondLine(int index) {
+ memset(buffer, ' ', LCD_WIDTH);
+ char *ptr;
+ switch (index) {
+ case 0:
+ ptr = prepareCltIatTpsLine(buffer);
+ break;
+ case 1:
+ ptr = prepareInfoLine(buffer);
+ break;
+ case 2:
+ ptr = prepareVBattMapLine(buffer);
+ break;
+ case 3:
+ ptr = prepareStatusLine(buffer);
+ break;
+ }
+ *ptr = ' ';
+}
+
+void updateHD44780lcd(void) {
+
+ lcd_HD44780_set_position(0, 9);
+ /**
+ * this would blink so that we know the LCD is alive
+ */
+ if (getTimeNowSeconds() % 2 == 0) {
+ lcd_HD44780_print_char('R');
+ } else {
+ lcd_HD44780_print_char(' ');
+ }
+ lcd_HD44780_set_position(0, 10);
+
+ char * ptr = itoa10(buffer, getRpm());
+ ptr[0] = 0;
+ int len = ptr - buffer;
+ for (int i = 0; i < 6 - len; i++) {
+ lcd_HD44780_print_char(' ');
+ }
+ lcd_HD44780_print_string(buffer);
+
+ if (hasFirmwareError()) {
+ memcpy(buffer, getFirmwareError(), LCD_WIDTH);
+ buffer[LCD_WIDTH] = 0;
+ lcd_HD44780_set_position(1, 0);
+ lcd_HD44780_print_string(buffer);
+ return;
+ }
+
+ lcd_HD44780_set_position(1, 0);
+ memset(buffer, ' ', LCD_WIDTH);
+ memcpy(buffer, getWarninig(), LCD_WIDTH);
+ buffer[LCD_WIDTH] = 0;
+ lcd_HD44780_print_string(buffer);
+
+ if (engineConfiguration->HD44780height < 3) {
+ return;
+ }
+
+ int index = (getTimeNowSeconds() / 2) % (NUMBER_OF_DIFFERENT_LINES / 2);
+
+ prepareCurrentSecondLine(index);
+ buffer[LCD_WIDTH] = 0;
+ lcd_HD44780_set_position(2, 0);
+ lcd_HD44780_print_string(buffer);
+
+ prepareCurrentSecondLine(index + NUMBER_OF_DIFFERENT_LINES / 2);
+ buffer[LCD_WIDTH] = 0;
+ lcd_HD44780_set_position(3, 0);
+ lcd_HD44780_print_string(buffer);
+
+#if EFI_PROD_CODE
+ dateToString(dateBuffer);
+ lcd_HD44780_set_position(1, 0);
+ lcd_HD44780_print_string(dateBuffer);
+#endif /* EFI_PROD_CODE */
+}
diff --git a/firmware/controllers/lcd_controller.h b/firmware/controllers/lcd_controller.h
new file mode 100644
index 0000000000..cee3d9c48a
--- /dev/null
+++ b/firmware/controllers/lcd_controller.h
@@ -0,0 +1,13 @@
+/**
+ * @file lcd_controller.h
+ *
+ * @date Aug 14, 2014
+ * @author Andrey Belomutskiy, (c) 2012-2014
+ */
+
+#ifndef LCD_CONTROLLER_H_
+#define LCD_CONTROLLER_H_
+
+void updateHD44780lcd(void);
+
+#endif /* LCD_CONTROLLER_H_ */
diff --git a/firmware/controllers/map_averaging.cpp b/firmware/controllers/map_averaging.cpp
index f3b2f8aaab..84ace3edfc 100644
--- a/firmware/controllers/map_averaging.cpp
+++ b/firmware/controllers/map_averaging.cpp
@@ -22,7 +22,7 @@
#include "map.h"
-#if EFI_MAP_AVERAGING
+#if EFI_MAP_AVERAGING || defined(__DOXYGEN__)
#include "map_averaging.h"
#include "trigger_central.h"
diff --git a/firmware/controllers/map_multiplier_thread.cpp b/firmware/controllers/map_multiplier_thread.cpp
index 159890a80e..55d94830be 100644
--- a/firmware/controllers/map_multiplier_thread.cpp
+++ b/firmware/controllers/map_multiplier_thread.cpp
@@ -13,7 +13,6 @@
#include "map_adjuster.h"
#include "rpm_calculator.h"
#include "main_trigger_callback.h"
-#include "wave_math.h"
#include "allsensors.h"
#include "engine_math.h"
#include "engine.h"
diff --git a/firmware/controllers/math/engine_math.cpp b/firmware/controllers/math/engine_math.cpp
index a75065c22f..c013f90fb0 100644
--- a/firmware/controllers/math/engine_math.cpp
+++ b/firmware/controllers/math/engine_math.cpp
@@ -188,6 +188,21 @@ static void registerInjectionEvent(engine_configuration_s const *e,
}
+float getFuelMultiplier(engine_configuration_s const *e, injection_mode_e mode) {
+ switch(mode) {
+ case IM_SEQUENTIAL:
+ return 1;
+ case IM_SIMULTANEOUS:
+ // todo: pre-calculate and save into ec2?
+ return 1.0 / e->cylindersCount;
+ case IM_BATCH:
+ return 2.0 / e->cylindersCount;
+ default:
+ firmwareError("Unexpected getFuelMultiplier %d", mode);
+ return NAN;
+ }
+}
+
void addFuelEvents(engine_configuration_s const *e, engine_configuration2_s *engineConfiguration2,
ActuatorEventList *list, injection_mode_e mode) {
list->resetEventList();
@@ -216,9 +231,16 @@ void addFuelEvents(engine_configuration_s const *e, engine_configuration2_s *eng
break;
case IM_BATCH:
for (int i = 0; i < e->cylindersCount; i++) {
- io_pin_e pin = (io_pin_e) ((int) INJECTOR_1_OUTPUT + (i % 2));
+ int index = i % (e->cylindersCount / 2);
+ io_pin_e pin = (io_pin_e) ((int) INJECTOR_1_OUTPUT + index);
float angle = baseAngle + i * 720.0 / e->cylindersCount;
registerInjectionEvent(e, s, list, pin, angle);
+
+ /**
+ * also fire the 2nd half of the injectors so that we can implement a batch mode on individual wires
+ */
+ pin = (io_pin_e) ((int) INJECTOR_1_OUTPUT + index + (e->cylindersCount / 2));
+ registerInjectionEvent(e, s, list, pin, angle);
}
break;
default:
@@ -270,8 +292,9 @@ void findTriggerPosition(engine_configuration_s const *engineConfiguration, trig
while (true) {
middle = (left + right) / 2;
- if (middle == left)
+ if (middle == left) {
break;
+ }
if (angleOffset < s->eventAngles[middle]) {
right = middle;
@@ -299,8 +322,10 @@ void registerActuatorEventExt(engine_configuration_s const *engineConfiguration,
OutputSignal *actuator, float angleOffset) {
efiAssertVoid(s->getSize() > 0, "uninitialized trigger_shape_s");
- if (e == NULL)
- return; // error already reported
+ if (e == NULL) {
+ // error already reported
+ return;
+ }
e->actuator = actuator;
findTriggerPosition(engineConfiguration, s, &e->position, angleOffset);
@@ -337,8 +362,7 @@ 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.setTriggerShapeSynchPointIndex(findTriggerZeroEventIndex(
- &engineConfiguration2->triggerShape, &engineConfiguration->triggerConfig));
+ engineConfiguration2->triggerShape.calculateTriggerSynchPoint(&engineConfiguration->triggerConfig);
injectonSignals.clear();
EventHandlerConfiguration *config = &engineConfiguration2->engineEventConfiguration;
@@ -364,6 +388,7 @@ void setTimingLoadBin(engine_configuration_s *engineConfiguration, float l, floa
setTableBin(engineConfiguration->ignitionLoadBins, IGN_LOAD_COUNT, l, r);
}
-int isInjectionEnabled(engine_configuration2_s const *engineConfiguration2) {
- return engineConfiguration2->isInjectionEnabledFlag;
+int isInjectionEnabled(engine_configuration_s *engineConfiguration) {
+ // todo: is this worth a method? should this be inlined?
+ return engineConfiguration->isInjectionEnabled;
}
diff --git a/firmware/controllers/math/engine_math.h b/firmware/controllers/math/engine_math.h
index 61fcbbfc0c..bc52074bc9 100644
--- a/firmware/controllers/math/engine_math.h
+++ b/firmware/controllers/math/engine_math.h
@@ -19,7 +19,7 @@
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);
+int isInjectionEnabled(engine_configuration_s *engineConfiguration);
float fixAngle(float angle);
diff --git a/firmware/controllers/math/speed_density.cpp b/firmware/controllers/math/speed_density.cpp
index e29549f650..1aecf8a828 100644
--- a/firmware/controllers/math/speed_density.cpp
+++ b/firmware/controllers/math/speed_density.cpp
@@ -26,7 +26,7 @@ static Map3D1616 afrMap;
#define tpMin 0
#define tpMax 100
// http://rusefi.com/math/t_charge.html
-float getTCharge(int rpm, int tps, float coolantTemp, float airTemp) {
+float getTCharge(int rpm, float tps, float coolantTemp, float airTemp) {
float minRpmKcurrentTPS = interpolate(tpMin, K_AT_MIN_RPM_MIN_TPS, tpMax,
K_AT_MIN_RPM_MAX_TPS, tps);
float maxRpmKcurrentTPS = interpolate(tpMin, K_AT_MAX_RPM_MIN_TPS, tpMax,
diff --git a/firmware/controllers/math/speed_density.h b/firmware/controllers/math/speed_density.h
index 980ea65ee4..7f10c30531 100644
--- a/firmware/controllers/math/speed_density.h
+++ b/firmware/controllers/math/speed_density.h
@@ -11,7 +11,7 @@
#include "ec2.h"
#include "engine.h"
-float getTCharge(int rpm, int tps, float coolantTemp, float airTemp);
+float getTCharge(int rpm, float tps, float coolantTemp, float airTemp);
void setDetaultVETable(engine_configuration_s *engineConfiguration);
float sdMath(engine_configuration_s *engineConfiguration, float VE, float MAP, float AFR, float temp);
diff --git a/firmware/controllers/sensors/map.cpp b/firmware/controllers/sensors/map.cpp
index 6ea32eb324..3e1539393e 100644
--- a/firmware/controllers/sensors/map.cpp
+++ b/firmware/controllers/sensors/map.cpp
@@ -18,8 +18,11 @@ extern engine_configuration_s * engineConfiguration;
*/
static FastInterpolation denso183(0, -6.64, 5, 182.78);
-// todo: figure out real values
-static FastInterpolation honda3bar(0.32, -95.8371264, 4.84, 300);
+/**
+ * MAP sensor output voltage of 3.0v = a gauge reading of 0 in. Hg
+ * MAP sensor output voltage of 0.5v = a gauge reading of 27 in. Hg
+ */
+static FastInterpolation honda3bar(0.5, 91.422, 3.0, 0);
static FastInterpolation mpx4250(0, 8, 5, 260);
diff --git a/firmware/controllers/sensors/sensor_types.h b/firmware/controllers/sensors/sensor_types.h
index 95ae5be362..a161488567 100644
--- a/firmware/controllers/sensors/sensor_types.h
+++ b/firmware/controllers/sensors/sensor_types.h
@@ -20,7 +20,7 @@ typedef struct {
float Min;
float Max;
air_pressure_sensor_type_e sensorType;
- int hwChannel;
+ adc_channel_e hwChannel;
} air_pressure_sensor_config_s;
/**
@@ -65,7 +65,7 @@ typedef struct {
typedef struct {
ThermistorConf *config;
- int channel;
+ adc_channel_e channel;
} Thermistor;
#endif /* THERMISTOR_TYPES_H_ */
diff --git a/firmware/controllers/sensors/thermistors.cpp b/firmware/controllers/sensors/thermistors.cpp
index c2be6ca4b3..705d0cea46 100644
--- a/firmware/controllers/sensors/thermistors.cpp
+++ b/firmware/controllers/sensors/thermistors.cpp
@@ -1,5 +1,5 @@
/**
- * @file thermistors.c
+ * @file thermistors.cpp
*
* @date Feb 17, 2013
* @author Andrey Belomutskiy, (c) 2012-2014
@@ -18,8 +18,8 @@
#include "ec2.h"
// Celsius
-#define LIMPING_MODE_IAT_TEMPERATURE 30
-#define LIMPING_MODE_CLT_TEMPERATURE 70
+#define LIMPING_MODE_IAT_TEMPERATURE 30.0f
+#define LIMPING_MODE_CLT_TEMPERATURE 70.0f
extern engine_configuration_s *engineConfiguration;
extern engine_configuration2_s *engineConfiguration2;
@@ -34,8 +34,9 @@ float getR1InVoltageDividor(float Vout, float Vin, float r2) {
}
float getR2InVoltageDividor(float Vout, float Vin, float r1) {
- if (Vout == 0)
+ if (Vout == 0) {
return NAN;
+ }
return r1 / (Vin / Vout - 1);
}
@@ -46,7 +47,7 @@ float getVoutInVoltageDividor(float Vin, float r1, float r2) {
float convertResistanceToKelvinTemperature(float resistance, ThermistorConf *thermistor) {
if (resistance <= 0) {
//warning("Invalid resistance in convertResistanceToKelvinTemperature=", resistance);
- return 0;
+ return 0.0f;
}
float logR = logf(resistance);
return 1 / (thermistor->s_h_a + thermistor->s_h_b * logR + thermistor->s_h_c * logR * logR * logR);
@@ -93,12 +94,12 @@ float getTemperatureC(Thermistor *thermistor) {
return convertKelvinToCelcius(kelvinTemperature);
}
-int isValidCoolantTemperature(float temperature) {
+bool isValidCoolantTemperature(float temperature) {
// I hope magic constants are appropriate here
return !cisnan(temperature) && temperature > -50 && temperature < 250;
}
-int isValidIntakeAirTemperature(float temperature) {
+bool isValidIntakeAirTemperature(float temperature) {
// I hope magic constants are appropriate here
return !cisnan(temperature) && temperature > -50 && temperature < 100;
}
@@ -109,7 +110,7 @@ int isValidIntakeAirTemperature(float temperature) {
float getCoolantTemperature(void) {
float temperature = getTemperatureC(&engineConfiguration2->clt);
if (!isValidCoolantTemperature(temperature)) {
- warning(OBD_PCM_Processor_Fault, "unrealistic coolant temperature %f", temperature);
+ warning(OBD_PCM_Processor_Fault, "unrealistic CLT %f", temperature);
return LIMPING_MODE_CLT_TEMPERATURE;
}
return temperature;
@@ -154,13 +155,13 @@ void prepareThermistorCurve(ThermistorConf * config) {
float getIntakeAirTemperature(void) {
float temperature = getTemperatureC(&engineConfiguration2->iat);
if (!isValidIntakeAirTemperature(temperature)) {
- warning(OBD_PCM_Processor_Fault, "unrealistic intake temperature %f", temperature);
+ warning(OBD_PCM_Processor_Fault, "unrealistic IAT %f", temperature);
return LIMPING_MODE_IAT_TEMPERATURE;
}
return temperature;
}
-static void initThermistorCurve(Thermistor * t, ThermistorConf *config, int channel) {
+static void initThermistorCurve(Thermistor * t, ThermistorConf *config, adc_channel_e channel) {
prepareThermistorCurve(config);
t->config = config;
t->channel = channel;
diff --git a/firmware/controllers/sensors/thermistors.h b/firmware/controllers/sensors/thermistors.h
index 2dd6fad8b8..37a7ac394d 100644
--- a/firmware/controllers/sensors/thermistors.h
+++ b/firmware/controllers/sensors/thermistors.h
@@ -38,9 +38,9 @@ float getKelvinTemperature(float resistance, ThermistorConf *thermistor);
float getResistance(Thermistor *thermistor);
float getTemperatureC(Thermistor *thermistor);
float getCoolantTemperature(void);
-int isValidCoolantTemperature(float temperature);
+bool isValidCoolantTemperature(float temperature);
float getIntakeAirTemperature(void);
-int isValidIntakeAirTemperature(float temperature);
+bool isValidIntakeAirTemperature(float temperature);
float convertResistanceToKelvinTemperature(float resistance,
ThermistorConf *thermistor);
diff --git a/firmware/controllers/sensors/tps.cpp b/firmware/controllers/sensors/tps.cpp
index 4371584c6d..4f2d7bcb15 100644
--- a/firmware/controllers/sensors/tps.cpp
+++ b/firmware/controllers/sensors/tps.cpp
@@ -4,7 +4,6 @@
#include "engine_configuration.h"
#include "interpolation.h"
#include "adc_inputs.h"
-#include "wave_math.h"
extern engine_configuration_s *engineConfiguration;
@@ -49,14 +48,16 @@ float getTpsRateOfChange(void) {
*
* */
float getTpsValue(int adc) {
- if (adc < engineConfiguration->tpsMin)
- return 0;
- if (adc > engineConfiguration->tpsMax)
- return 100;
+ if (adc < engineConfiguration->tpsMin) {
+ return 0.0f;
+ }
+ if (adc > engineConfiguration->tpsMax) {
+ return 100.0f;
+ }
// todo: double comparison using EPS
if (engineConfiguration->tpsMin == engineConfiguration->tpsMax) {
firmwareError("Invalid TPS configuration: same value");
- return 0;
+ return 0.0f;
}
return interpolate(engineConfiguration->tpsMin, 0, engineConfiguration->tpsMax, 100, adc);
}
diff --git a/firmware/controllers/sensors/voltage.c b/firmware/controllers/sensors/voltage.c
index 7077143750..a1b6361699 100644
--- a/firmware/controllers/sensors/voltage.c
+++ b/firmware/controllers/sensors/voltage.c
@@ -11,6 +11,7 @@
#include "boards.h"
#include "engine_configuration.h"
#include "adc_inputs.h"
+#include "voltage.h"
extern engine_configuration_s *engineConfiguration;
diff --git a/firmware/controllers/settings.cpp b/firmware/controllers/settings.cpp
index ee23cc16f8..68eee0185f 100644
--- a/firmware/controllers/settings.cpp
+++ b/firmware/controllers/settings.cpp
@@ -43,17 +43,21 @@ static void doPrintConfiguration(void) {
printConfiguration(engineConfiguration, engineConfiguration2);
}
-static void printIntArray(int array[], int size) {
- for (int j = 0; j < size; j++)
- print("%d ", array[j]);
- print("\r\n");
-}
+/*
+ static void printIntArray(int array[], int size) {
+ for (int j = 0; j < size; j++) {
+ print("%d ", array[j]);
+ }
+ print("\r\n");
+ }
+ */
void printFloatArray(const char *prefix, float array[], int size) {
appendMsgPrefix(&logger);
appendPrintf(&logger, prefix);
- for (int j = 0; j < size; j++)
+ for (int j = 0; j < size; j++) {
appendPrintf(&logger, "%f ", array[j]);
+ }
appendMsgPostfix(&logger);
scheduleLogging(&logger);
}
@@ -76,8 +80,12 @@ const char* getConfigurationName(engine_configuration_s *engineConfiguration) {
case NISSAN_PRIMERA:
return "Nissan Primera";
#endif /* EFI_SUPPORT_NISSAN_PRIMERA */
- case HONDA_ACCORD:
- return "Honda Accord";
+ case HONDA_ACCORD_CD:
+ return "Honda Accord 3w";
+ case HONDA_ACCORD_CD_TWO_WIRES:
+ return "Honda Accord 2w";
+ case HONDA_ACCORD_CD_DIP:
+ return "Honda Dip";
case FORD_INLINE_6_1995:
return "Ford 1995 inline 6";
case GY6_139QMB:
@@ -96,7 +104,10 @@ const char* getConfigurationName(engine_configuration_s *engineConfiguration) {
return "Citroen TU3JP";
case ROVER_V8:
return "Rover v8";
+ case MITSU_4G93:
+ return "Mitsu 4G93";
default:
+ firmwareError("Unexpected: engineType %d", engineConfiguration->engineType);
return NULL;
}
}
@@ -125,7 +136,8 @@ static const char * boolToString(bool value) {
*/
void printConfiguration(engine_configuration_s *engineConfiguration, engine_configuration2_s *engineConfiguration2) {
- scheduleMsg(&logger, "Template %s trigger %d", getConfigurationName(engineConfiguration), engineConfiguration->triggerConfig.triggerType);
+ scheduleMsg(&logger, "Template %s/%d trigger %d", getConfigurationName(engineConfiguration),
+ engineConfiguration->engineType, engineConfiguration->triggerConfig.triggerType);
scheduleMsg(&logger, "configurationVersion=%d", getGlobalConfigurationVersion());
@@ -152,16 +164,18 @@ void printConfiguration(engine_configuration_s *engineConfiguration, engine_conf
// appendMsgPrefix(&logger);
- scheduleMsg(&logger, "rpmHardLimit: %d", engineConfiguration->rpmHardLimit);
- scheduleMsg(&logger, "rpmMultiplier=%f", engineConfiguration->rpmMultiplier);
+ scheduleMsg(&logger, "rpmHardLimit: %d/rpmMultiplier=%f", engineConfiguration->rpmHardLimit,
+ engineConfiguration->rpmMultiplier);
- scheduleMsg(&logger, "tpsMin: %d", engineConfiguration->tpsMin);
- scheduleMsg(&logger, "tpsMax: %d", engineConfiguration->tpsMax);
+ scheduleMsg(&logger, "tpsMin: %d/tpsMax: %d", engineConfiguration->tpsMin, engineConfiguration->tpsMax);
+ scheduleMsg(&logger, "ignitionMode: %d/enabled=%s", engineConfiguration->ignitionMode,
+ boolToString(engineConfiguration->isIgnitionEnabled));
scheduleMsg(&logger, "timingMode: %d", engineConfiguration->timingMode);
scheduleMsg(&logger, "fixedModeTiming: %d", (int) engineConfiguration->fixedModeTiming);
scheduleMsg(&logger, "ignitionOffset=%f", engineConfiguration->ignitionOffset);
- scheduleMsg(&logger, "injectionOffset=%f", engineConfiguration->injectionOffset);
+ scheduleMsg(&logger, "injectionOffset=%f/enabled=%s", (double) engineConfiguration->injectionOffset,
+ boolToString(engineConfiguration->isInjectionEnabled));
scheduleMsg(&logger, "crankingChargeAngle=%f", engineConfiguration->crankingChargeAngle);
scheduleMsg(&logger, "crankingTimingAngle=%f", engineConfiguration->crankingTimingAngle);
@@ -176,7 +190,8 @@ void printConfiguration(engine_configuration_s *engineConfiguration, engine_conf
pinModeToString(boardConfiguration->malfunctionIndicatorPinMode));
scheduleMsg(&logger, "analogInputDividerCoefficient: %f", engineConfiguration->analogInputDividerCoefficient);
- scheduleMsg(&logger, "needSecondTriggerInput: %s", boolToString(engineConfiguration2->triggerShape.needSecondTriggerInput));
+ scheduleMsg(&logger, "needSecondTriggerInput: %s",
+ boolToString(engineConfiguration2->triggerShape.needSecondTriggerInput));
#if EFI_PROD_CODE
scheduleMsg(&logger, "idleValvePin: %s", hwPortname(boardConfiguration->idleValvePin));
@@ -201,19 +216,23 @@ void printConfiguration(engine_configuration_s *engineConfiguration, engine_conf
pinModeToString(boardConfiguration->triggerSimulatorPinModes[0]));
scheduleMsg(&logger, "secondary trigger simulator: %s %s", hwPortname(boardConfiguration->triggerSimulatorPins[1]),
pinModeToString(boardConfiguration->triggerSimulatorPinModes[1]));
+ scheduleMsg(&logger, "3rd trigger simulator: %s %s", hwPortname(boardConfiguration->triggerSimulatorPins[2]),
+ pinModeToString(boardConfiguration->triggerSimulatorPinModes[2]));
- scheduleMsg(&logger, "primary trigger input: %s", hwPortname(boardConfiguration->primaryTriggerInputPin));
+ scheduleMsg(&logger, "primary trigger input: %s", hwPortname(boardConfiguration->triggerInputPins[0]));
+ scheduleMsg(&logger, "secondary trigger input: %s", hwPortname(boardConfiguration->triggerInputPins[1]));
+ scheduleMsg(&logger, "primary logic input: %s", hwPortname(boardConfiguration->logicAnalyzerPins[0]));
+ scheduleMsg(&logger, "secondary logic input: %s", hwPortname(boardConfiguration->logicAnalyzerPins[1]));
scheduleMsg(&logger, "boardTestModeJumperPin: %s", hwPortname(boardConfiguration->boardTestModeJumperPin));
scheduleMsg(&logger, "digitalPotentiometerSpiDevice %d", boardConfiguration->digitalPotentiometerSpiDevice);
for (int i = 0; i < DIGIPOT_COUNT; i++) {
- scheduleMsg(&logger, "digitalPotentiometer CS%d %s", i, hwPortname(boardConfiguration->digitalPotentiometerChipSelect[i]));
+ scheduleMsg(&logger, "digitalPotentiometer CS%d %s", i,
+ hwPortname(boardConfiguration->digitalPotentiometerChipSelect[i]));
}
#endif /* EFI_PROD_CODE */
-
- scheduleMsg(&logger, "isInjectionEnabledFlag %s", boolToString(engineConfiguration2->isInjectionEnabledFlag));
}
static void setFixedModeTiming(int value) {
@@ -228,6 +247,10 @@ static void setTimingMode(int value) {
incrementGlobalConfigurationVersion();
}
+static void setIdleMode(int mode) {
+ engineConfiguration->idleMode = (idle_mode_e) mode;
+}
+
void setEngineType(int value) {
engineConfiguration->engineType = (engine_type_e) value;
resetConfigurationExt(&logger, (engine_type_e) value, engineConfiguration, engineConfiguration2,
@@ -295,7 +318,7 @@ static void setRpmMultiplier(int value) {
static char pinNameBuffer[16];
static void printThermistor(const char *msg, Thermistor *thermistor) {
- int adcChannel = thermistor->channel;
+ adc_channel_e adcChannel = thermistor->channel;
float voltage = getVoltageDivided(adcChannel);
float r = getResistance(thermistor);
@@ -309,8 +332,8 @@ static void printThermistor(const char *msg, Thermistor *thermistor) {
#endif
}
-static void printMAPInfo(void) {
#if EFI_PROD_CODE
+static void printMAPInfo(void) {
scheduleMsg(&logger, "map type=%d raw=%f MAP=%f", engineConfiguration->map.sensor.sensorType, getRawMap(),
getMap());
if (engineConfiguration->map.sensor.sensorType == MT_CUSTOM) {
@@ -321,8 +344,8 @@ static void printMAPInfo(void) {
if (engineConfiguration->baroSensor.sensorType == MT_CUSTOM) {
scheduleMsg(&logger, "min=%f max=%f", engineConfiguration->baroSensor.Min, engineConfiguration->baroSensor.Max);
}
-#endif
}
+#endif
static void printTPSInfo(void) {
#if EFI_PROD_CODE
@@ -337,16 +360,22 @@ static void printTPSInfo(void) {
static void printTemperatureInfo(void) {
printThermistor("CLT", &engineConfiguration2->clt);
+ if (!isValidCoolantTemperature(getCoolantTemperature())) {
+ scheduleMsg(&logger, "CLT sensing error");
+ }
printThermistor("IAT", &engineConfiguration2->iat);
+ if (!isValidIntakeAirTemperature(getIntakeAirTemperature())) {
+ scheduleMsg(&logger, "IAT sensing error");
+ }
float rClt = getResistance(&engineConfiguration2->clt);
float rIat = getResistance(&engineConfiguration2->iat);
#if EFI_ANALOG_INPUTS
- int cltChannel = engineConfiguration2->clt.channel;
+ adc_channel_e cltChannel = engineConfiguration2->clt.channel;
scheduleMsg(&logger, "CLT R=%f on channel %d@%s", rClt, cltChannel,
getPinNameByAdcChannel(cltChannel, pinNameBuffer));
- int iatChannel = engineConfiguration2->iat.channel;
+ adc_channel_e iatChannel = engineConfiguration2->iat.channel;
scheduleMsg(&logger, "IAT R=%f on channel %d@%s", rIat, iatChannel,
getPinNameByAdcChannel(iatChannel, pinNameBuffer));
@@ -425,7 +454,7 @@ static void setIgnitionMode(int value) {
}
static void setTriggerType(int value) {
- engineConfiguration->triggerConfig.triggerType = (trigger_type_e)value;
+ engineConfiguration->triggerConfig.triggerType = (trigger_type_e) value;
incrementGlobalConfigurationVersion();
doPrintConfiguration();
}
@@ -450,6 +479,10 @@ static void setGlobalFuelCorrection(float value) {
engineConfiguration->globalFuelCorrection = value;
}
+static void setVBattDivider(float value) {
+ engineConfiguration->vbattDividerCoeff = value;
+}
+
static void setWholeTimingMap(float value) {
// todo: table helper?
scheduleMsg(&logger, "Setting whole timing map to %f", value);
@@ -465,7 +498,72 @@ static void setWholeFuelMapCmd(float value) {
setWholeFuelMap(engineConfiguration, value);
}
-static void setTimingMap(char * rpmStr, char *loadStr, char *valueStr) {
+static void setTriggerInputPin(const char *indexStr, const char *pinName) {
+#if EFI_PROD_CODE
+ int index = atoi(indexStr);
+ if (index < 0 || index > 2)
+ return;
+ brain_pin_e pin = parseBrainPin(pinName);
+ scheduleMsg(&logger, "setting trigger pin[%d] to %s please save&restart", index, hwPortname(pin));
+ boardConfiguration->triggerInputPins[index] = pin;
+#endif
+}
+
+#if EFI_PROD_CODE
+static void setTriggerSimulatorMode(const char *indexStr, const char *modeCode) {
+ int index = atoi(indexStr);
+ if (index < 0 || index > 2 || absI(index) == ERROR_CODE) {
+ return;
+ }
+ int mode = atoi(modeCode);
+ if (absI(mode) == ERROR_CODE) {
+ return;
+ }
+ boardConfiguration->triggerSimulatorPinModes[index] = (pin_output_mode_e) mode;
+}
+
+static void setTriggerSimulatorPin(const char *indexStr, const char *pinName) {
+ int index = atoi(indexStr);
+ if (index < 0 || index > 2)
+ return;
+ brain_pin_e pin = parseBrainPin(pinName);
+ scheduleMsg(&logger, "setting trigger simulator pin[%d] to %s please save&restart", index, hwPortname(pin));
+ boardConfiguration->triggerSimulatorPins[index] = pin;
+}
+
+static void setAnalogInputPin(const char *sensorStr, const char *pinName) {
+ brain_pin_e pin = parseBrainPin(pinName);
+ adc_channel_e channel = getAdcChannel(pin);
+ if (channel == EFI_ADC_ERROR) {
+ scheduleMsg(&logger, "Error with [%s]", pinName);
+ return;
+ }
+ if (strEqual("map", sensorStr)) {
+ engineConfiguration->map.sensor.hwChannel = channel;
+ scheduleMsg(&logger, "setting MAP to %s/%d", pinName, channel);
+ } else if (strEqual("clt", sensorStr)) {
+ engineConfiguration->cltAdcChannel = channel;
+ scheduleMsg(&logger, "setting CLT to %s/%d", pinName, channel);
+ } else if (strEqual("iat", sensorStr)) {
+ engineConfiguration->iatAdcChannel = channel;
+ scheduleMsg(&logger, "setting IAT to %s/%d", pinName, channel);
+ } else if (strEqual("tps", sensorStr)) {
+ engineConfiguration->tpsAdcChannel = channel;
+ scheduleMsg(&logger, "setting TPS to %s/%d", pinName, channel);
+ }
+}
+
+static void setLogicInputPin(const char *indexStr, const char *pinName) {
+ int index = atoi(indexStr);
+ if (index < 0 || index > 2)
+ return;
+ brain_pin_e pin = parseBrainPin(pinName);
+ scheduleMsg(&logger, "setting logic input pin[%d] to %s please save&restart", index, hwPortname(pin));
+ boardConfiguration->logicAnalyzerPins[index] = pin;
+}
+#endif /* EFI_PROD_CODE */
+
+static void setTimingMap(const char * rpmStr, const char *loadStr, const char *valueStr) {
float rpm = atoff(rpmStr);
float engineLoad = atoff(loadStr);
float value = atoff(valueStr);
@@ -479,7 +577,7 @@ static void setTimingMap(char * rpmStr, char *loadStr, char *valueStr) {
scheduleMsg(&logger, "Setting timing map entry %d:%d to %f", rpmIndex, loadIndex, value);
}
-static void setFuelMap(char * rpmStr, char *loadStr, char *valueStr) {
+static void setFuelMap(const char * rpmStr, const char *loadStr, const char *valueStr) {
float rpm = atoff(rpmStr);
float engineLoad = atoff(loadStr);
float value = atoff(valueStr);
@@ -494,15 +592,35 @@ static void setFuelMap(char * rpmStr, char *loadStr, char *valueStr) {
}
static void enableInjection(void) {
- engineConfiguration2->isInjectionEnabledFlag = TRUE;
+ engineConfiguration->isInjectionEnabled = true;
scheduleMsg(&logger, "injection enabled");
}
static void disableInjection(void) {
- engineConfiguration2->isInjectionEnabledFlag = FALSE;
+ engineConfiguration->isInjectionEnabled = false;
scheduleMsg(&logger, "injection disabled");
}
+static void enableIgnition(void) {
+ engineConfiguration->isIgnitionEnabled = true;
+ scheduleMsg(&logger, "ignition enabled");
+}
+
+static void disableIgnition(void) {
+ engineConfiguration->isIgnitionEnabled = false;
+ scheduleMsg(&logger, "ignition disabled");
+}
+
+static void enableSelfStimulation(void) {
+ engineConfiguration->directSelfStimulation = true;
+ scheduleMsg(&logger, "self stimulation enabled");
+}
+
+static void disableSelfStimulation(void) {
+ engineConfiguration->directSelfStimulation = false;
+ scheduleMsg(&logger, "self stimulation disabled");
+}
+
#if EFI_WAVE_CHART
extern int waveChartUsedSize;
#endif
@@ -510,11 +628,11 @@ extern int waveChartUsedSize;
static void printAllInfo(void) {
printTemperatureInfo();
printTPSInfo();
- printMAPInfo();
#if EFI_WAVE_CHART
scheduleMsg(&logger, "waveChartUsedSize=%d", waveChartUsedSize);
#endif
#if EFI_PROD_CODE
+ printMAPInfo();
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
@@ -526,7 +644,6 @@ void initSettings(void) {
addConsoleAction("showconfig", doPrintConfiguration);
addConsoleAction("tempinfo", printTemperatureInfo);
addConsoleAction("tpsinfo", printTPSInfo);
- addConsoleAction("mapinfo", printMAPInfo);
addConsoleAction("info", printAllInfo);
addConsoleActionI("set_ignition_offset", setIgnitionOffset);
@@ -536,6 +653,7 @@ void initSettings(void) {
addConsoleActionI("set_fixed_mode_timing", setFixedModeTiming);
addConsoleActionI("set_timing_mode", setTimingMode);
addConsoleActionI("set_engine_type", setEngineType);
+ addConsoleActionI("set_idle_mode", setIdleMode);
addConsoleActionI("set_injection_pin_mode", setInjectionPinMode);
addConsoleActionI("set_ignition_pin_mode", setIgnitionPinMode);
@@ -567,9 +685,28 @@ void initSettings(void) {
addConsoleActionI("set_firing_order", setFiringOrder);
addConsoleActionI("set_algorithm", setAlgorithm);
+ // todo: refactor this - looks like all boolean flags should be controlled with less code duplication
addConsoleAction("enable_injection", enableInjection);
addConsoleAction("disable_injection", disableInjection);
+ addConsoleAction("enable_ignition", enableIgnition);
+ addConsoleAction("disable_ignition", disableIgnition);
+ addConsoleAction("enable_self_stimulation", enableSelfStimulation);
+ addConsoleAction("disable_self_stimulation", disableSelfStimulation);
+
addConsoleActionII("set_toothed_wheel", setToothedWheel);
addConsoleActionI("set_trigger_type", setTriggerType);
+
+ addConsoleActionSS("set_trigger_input_pin", setTriggerInputPin);
+
+ addConsoleActionF("set_vbatt_divider", setVBattDivider);
+
+#if EFI_PROD_CODE
+ addConsoleActionSS("set_trigger_simulator_pin", setTriggerSimulatorPin);
+ addConsoleActionSS("set_trigger_simulator_mode", setTriggerSimulatorMode);
+
+ addConsoleAction("mapinfo", printMAPInfo);
+ addConsoleActionSS("set_analog_input_pin", setAnalogInputPin);
+ addConsoleActionSS("set_logic_input_pin", setLogicInputPin);
+#endif /* EFI_PROD_CODE */
}
diff --git a/firmware/controllers/system/pwm_generator_logic.cpp b/firmware/controllers/system/pwm_generator_logic.cpp
index 57703a54a4..df37fb13cf 100644
--- a/firmware/controllers/system/pwm_generator_logic.cpp
+++ b/firmware/controllers/system/pwm_generator_logic.cpp
@@ -56,7 +56,7 @@ static uint64_t getNextSwitchTimeUs(PwmConfig *state) {
* Once 'iteration' gets relatively high, we might lose calculation precision here.
* This is addressed by ITERATION_LIMIT
*/
- uint64_t timeToSwitchUs = (iteration + switchTime) * periodUs;
+ uint64_t timeToSwitchUs = (uint64_t)((iteration + switchTime) * periodUs);
#if DEBUG_PWM
scheduleMsg(&logger, "start=%d timeToSwitch=%d", state->safe.start, timeToSwitch);
@@ -66,8 +66,9 @@ static uint64_t getNextSwitchTimeUs(PwmConfig *state) {
void PwmConfig::handleCycleStart() {
if (safe.phaseIndex == 0) {
- if (cycleCallback != NULL)
+ if (cycleCallback != NULL) {
cycleCallback(this);
+ }
efiAssertVoid(periodUs != 0, "period not initialized");
if (safe.periodUs != periodUs || safe.iteration == ITERATION_LIMIT) {
/**
@@ -119,6 +120,9 @@ static uint64_t togglePwmState(PwmConfig *state) {
* We are here if we are late for a state transition.
* At 12000RPM=200Hz with a 60 toothed wheel we need to change state every
* 1000000 / 200 / 120 = ~41 uS. We are kind of OK.
+ *
+ * We are also here after a flash write. Flash write freezes the whole chip for a couple of seconds,
+ * so PWM generation and trigger simulation generation would have to recover from this time lag.
*/
//todo: introduce error and test this error handling warning(OBD_PCM_Processor_Fault, "PWM: negative switch time");
timeToSwitch = 10;
diff --git a/firmware/controllers/trigger/main_trigger_callback.cpp b/firmware/controllers/trigger/main_trigger_callback.cpp
index 4956477f33..17b0d44236 100644
--- a/firmware/controllers/trigger/main_trigger_callback.cpp
+++ b/firmware/controllers/trigger/main_trigger_callback.cpp
@@ -30,7 +30,7 @@
#endif
-#if EFI_ENGINE_CONTROL
+#if EFI_ENGINE_CONTROL || defined(__DOXYGEN__)
#include "main_trigger_callback.h"
#include "ec2.h"
@@ -97,7 +97,7 @@ static void handleFuelInjectionEvent(MainTriggerCallback *mainTriggerCallback, A
}
static void handleFuel(MainTriggerCallback *mainTriggerCallback, int eventIndex, int rpm) {
- if (!isInjectionEnabled(mainTriggerCallback->engineConfiguration2))
+ if (!isInjectionEnabled(mainTriggerCallback->engineConfiguration))
return;
efiAssertVoid(getRemainingStack(chThdSelf()) > 16, "stack#3");
efiAssertVoid(eventIndex < 2 * mainTriggerCallback->engineConfiguration2->triggerShape.shaftPositionEventCount,
@@ -185,7 +185,7 @@ static void handleSparkEvent(MainTriggerCallback *mainTriggerCallback, int event
}
static void handleSpark(MainTriggerCallback *mainTriggerCallback, int eventIndex, int rpm, IgnitionEventList *list) {
- if (!isValidRpm(rpm))
+ if (!isValidRpm(rpm) || !mainTriggerCallback->engineConfiguration->isIgnitionEnabled)
return; // this might happen for instance in case of a single trigger event after a pause
/**
@@ -326,17 +326,16 @@ void MainTriggerCallback::init(Engine *engine, engine_configuration2_s *engineCo
void initMainEventListener(Engine *engine, engine_configuration2_s *engineConfiguration2) {
efiAssertVoid(engine!=NULL, "null engine");
- engine_configuration_s *engineConfiguration = engine->engineConfiguration;
mainTriggerCallbackInstance.init(engine, engineConfiguration2);
-#if EFI_PROD_CODE
+#if EFI_PROD_CODE || defined(__DOXYGEN__)
addConsoleAction("performanceinfo", showTriggerHistogram);
addConsoleAction("maininfo", showMainInfo);
initLogging(&logger, "main event handler");
printMsg(&logger, "initMainLoop: %d", currentTimeMillis());
- if (!isInjectionEnabled(mainTriggerCallbackInstance.engineConfiguration2))
+ if (!isInjectionEnabled(mainTriggerCallbackInstance.engineConfiguration))
printMsg(&logger, "!!!!!!!!!!!!!!!!!!! injection disabled");
#endif
diff --git a/firmware/controllers/trigger/rpm_calculator.cpp b/firmware/controllers/trigger/rpm_calculator.cpp
index 874ff50b90..cc7eb4b48e 100644
--- a/firmware/controllers/trigger/rpm_calculator.cpp
+++ b/firmware/controllers/trigger/rpm_calculator.cpp
@@ -19,7 +19,7 @@
extern WaveChart waveChart;
#endif /* EFI_WAVE_CHART */
-#if EFI_SHAFT_POSITION_INPUT
+#if EFI_SHAFT_POSITION_INPUT || defined(__DOXYGEN__)
#include "trigger_central.h"
#include "engine_configuration.h"
@@ -77,7 +77,7 @@ uint64_t getLastRpmEventTime(void) {
return rpmState.lastRpmEventTimeUs;
}
-#if EFI_PROD_CODE || EFI_SIMULATOR
+#if (EFI_PROD_CODE || EFI_SIMULATOR) || defined(__DOXYGEN__)
bool isCranking(void) {
int rpm = getRpm();
return isCrankingR(rpm);
@@ -141,10 +141,14 @@ void rpmShaftPositionCallback(trigger_event_e ckpSignalType, int index, RpmCalcu
addWaveChartEvent(WC_CRANK2, WC_UP, (char*) shaft_signal_msg_index);
} else if (ckpSignalType == SHAFT_SECONDARY_DOWN) {
addWaveChartEvent(WC_CRANK2, WC_DOWN, (char*) shaft_signal_msg_index);
+ } else if (ckpSignalType == SHAFT_3RD_UP) {
+ addWaveChartEvent(WC_CRANK3, WC_UP, (char*) shaft_signal_msg_index);
+ } else if (ckpSignalType == SHAFT_3RD_DOWN) {
+ addWaveChartEvent(WC_CRANK3, WC_DOWN, (char*) shaft_signal_msg_index);
}
if (index != 0) {
-#if EFI_ANALOG_CHART
+#if EFI_ANALOG_CHART || defined(__DOXYGEN__)
if (engineConfiguration->analogChartMode == AC_TRIGGER)
acAddData(getCrankshaftAngle(getTimeNowUs()), 1000 * ckpSignalType + index);
#endif
@@ -174,7 +178,7 @@ void rpmShaftPositionCallback(trigger_event_e ckpSignalType, int index, RpmCalcu
}
}
rpmState->lastRpmEventTimeUs = nowUs;
-#if EFI_ANALOG_CHART
+#if EFI_ANALOG_CHART || defined(__DOXYGEN__)
if (engineConfiguration->analogChartMode == AC_TRIGGER)
acAddData(getCrankshaftAngle(nowUs), index);
#endif
@@ -184,22 +188,31 @@ static scheduling_s tdcScheduler[2];
static char rpmBuffer[10];
-#if EFI_PROD_CODE || EFI_SIMULATOR
+#if (EFI_PROD_CODE || EFI_SIMULATOR) || defined(__DOXYGEN__)
+/**
+ * This callback has nothing to do with actual engine control, it just sends a Top Dead Center mark to the dev console
+ * digital sniffer.
+ */
static void onTdcCallback(void) {
itoa10(rpmBuffer, getRpm());
addWaveChartEvent(TOP_DEAD_CENTER_MESSAGE, (char*) rpmBuffer, "");
}
+/**
+ * This trigger callback schedules the actual physical TDC callback in relation to trigger synchronization point.
+ */
static void tdcMarkCallback(trigger_event_e ckpSignalType, int index, void *arg) {
- if (index == 0) {
+ bool isTriggerSynchronizationPoint = index == 0;
+ if (isTriggerSynchronizationPoint) {
int index = getRevolutionCounter() % 2;
+ // todo: use event-based scheduling, not just time-based scheduling
scheduleByAngle(&tdcScheduler[index], engineConfiguration->globalTriggerAngleOffset, (schfunc_t) onTdcCallback, NULL);
}
}
#endif
void initRpmCalculator(void) {
-#if EFI_PROD_CODE || EFI_SIMULATOR
+#if (EFI_PROD_CODE || EFI_SIMULATOR) || defined(__DOXYGEN__)
initLogging(&logger, "rpm calc");
engine.rpmCalculator = &rpmState;
@@ -213,7 +226,7 @@ void initRpmCalculator(void) {
addTriggerEventListener((ShaftPositionListener)&rpmShaftPositionCallback, "rpm reporter", &rpmState);
}
-#if EFI_PROD_CODE || EFI_SIMULATOR
+#if (EFI_PROD_CODE || EFI_SIMULATOR) || defined(__DOXYGEN__)
/**
* Schedules a callback 'angle' degree of crankshaft from now.
* The callback would be executed once after the duration of time which
diff --git a/firmware/controllers/trigger/rpm_calculator.h b/firmware/controllers/trigger/rpm_calculator.h
index 9e6d33ceb2..b57a6c512d 100644
--- a/firmware/controllers/trigger/rpm_calculator.h
+++ b/firmware/controllers/trigger/rpm_calculator.h
@@ -9,12 +9,13 @@
#ifndef RPM_REPORTER_H_
#define RPM_REPORTER_H_
-#include
+#include
#define WC_DOWN "d"
#define WC_UP "u"
#define WC_CRANK1 "c1"
#define WC_CRANK2 "c2"
+#define WC_CRANK3 "c3"
#define NOISY_RPM -1
@@ -58,6 +59,9 @@ uint64_t getLastRpmEventTime(void);
int getRevolutionCounter(void);
float getCrankshaftAngle(uint64_t timeUs);
+/**
+ * @return true if engine is running
+ */
bool isRunning(void);
bool isValidRpm(int rpm);
void addWaveChartEvent(const char *name, const char *msg, const char *msg2);
diff --git a/firmware/controllers/trigger/trigger.mk b/firmware/controllers/trigger/trigger.mk
index 91560eb8f1..1228a9d0f2 100644
--- a/firmware/controllers/trigger/trigger.mk
+++ b/firmware/controllers/trigger/trigger.mk
@@ -7,6 +7,7 @@ TRIGGER_DECODERS_SRC_CPP = \
$(PROJECT_DIR)/controllers/trigger/trigger_chrysler.cpp \
$(PROJECT_DIR)/controllers/trigger/trigger_structure.cpp \
$(PROJECT_DIR)/controllers/trigger/trigger_decoder.cpp \
+ $(PROJECT_DIR)/controllers/trigger/trigger_mitsubishi.cpp \
$(PROJECT_DIR)/controllers/trigger/trigger_gm.cpp
TRIGGER_SRC_CPP = \
diff --git a/firmware/controllers/trigger/trigger_bmw.cpp b/firmware/controllers/trigger/trigger_bmw.cpp
index 7798843874..6e18bf1555 100644
--- a/firmware/controllers/trigger/trigger_bmw.cpp
+++ b/firmware/controllers/trigger/trigger_bmw.cpp
@@ -26,8 +26,9 @@ void configureMiniCooperTriggerShape(trigger_shape_s *s) {
s->addEvent(a, T_SECONDARY, TV_LOW);
a += w;
- for (int i = 0; i <= 22; i++)
+ for (int i = 0; i <= 22; i++) {
a = addPair(s, a, w);
+ }
a += 3 * w;
@@ -38,13 +39,15 @@ void configureMiniCooperTriggerShape(trigger_shape_s *s) {
s->addEvent(a, T_SECONDARY, TV_LOW);
a += w;
- for (int i = 0; i < 36; i++)
+ for (int i = 0; i < 36; i++) {
a = addPair(s, a, w);
+ }
s->addEvent(376, T_PRIMARY, TV_HIGH);
- for (int i = 0; i < 21; i++)
+ for (int i = 0; i < 21; i++) {
a = addPair(s, a, w);
+ }
a += 3 * w;
efiAssertVoid(absF(firstGapAngle + 360 - a) < 0.1, "shape constraint");
@@ -54,13 +57,14 @@ void configureMiniCooperTriggerShape(trigger_shape_s *s) {
s->addEvent(a, T_SECONDARY, TV_LOW);
a += w;
- for (int i = 0; i < 33; i++)
+ for (int i = 0; i < 33; i++) {
a = addPair(s, a, w);
+ }
efiAssertVoid(absF(720 - w / 2 - a) < 0.1, "shape constraint");
s->addEvent(a, T_SECONDARY, TV_HIGH);
- s->addEvent(720, T_PRIMARY, TV_LOW);
+ s->addEvent(720.0, T_PRIMARY, TV_LOW);
s->shaftPositionEventCount = s->getSize();
/**
diff --git a/firmware/controllers/trigger/trigger_central.cpp b/firmware/controllers/trigger/trigger_central.cpp
index 6270f943b7..8c546ea296 100644
--- a/firmware/controllers/trigger/trigger_central.cpp
+++ b/firmware/controllers/trigger/trigger_central.cpp
@@ -11,7 +11,6 @@
#include "main_trigger_callback.h"
#include "engine_configuration.h"
#include "listener_array.h"
-#include "wave_math.h"
#include "data_buffer.h"
#include "histogram.h"
#if EFI_PROD_CODE
@@ -63,6 +62,10 @@ TriggerCentral::TriggerCentral() {
clearCallbacks(&triggerListeneres);
}
+int TriggerCentral::getHwEventCounter(int index) {
+ return hwEventCounters[index];
+}
+
void TriggerCentral::handleShaftSignal(configuration_s *configuration, trigger_event_e signal, uint64_t nowUs) {
efiAssertVoid(configuration!=NULL, "configuration");
@@ -81,7 +84,7 @@ void TriggerCentral::handleShaftSignal(configuration_s *configuration, trigger_e
* We are here if there is a time gap between now and previous shaft event - that means the engine is not runnig.
* That means we have lost synchronization since the engine is not running :)
*/
- triggerState.shaft_is_synchronized = FALSE;
+ triggerState.shaft_is_synchronized = false;
}
previousShaftEventTime = nowUs;
@@ -92,16 +95,19 @@ void TriggerCentral::handleShaftSignal(configuration_s *configuration, trigger_e
*/
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
+ if (!triggerState.shaft_is_synchronized) {
+ // we should not propagate event if we do not know where we are
+ return;
+ }
if (triggerState.getCurrentIndex() >= configuration->engineConfiguration2->triggerShape.shaftPositionEventCount) {
int f = warning(OBD_PCM_Processor_Fault, "unexpected eventIndex=%d", triggerState.getCurrentIndex());
if (!f) {
#if EFI_PROD_CODE
// this temporary code is about trigger noise debugging
- for (int i = 0; i < HW_EVENT_TYPES; i++)
+ for (int i = 0; i < HW_EVENT_TYPES; i++) {
scheduleMsg(&logging, "event type: %d count=%d", i, hwEventCounters[i]);
+ }
#endif
}
} else {
@@ -110,7 +116,7 @@ void TriggerCentral::handleShaftSignal(configuration_s *configuration, trigger_e
* cycle into a four stroke, 720 degrees cycle. TODO
*/
int triggerIndexForListeners;
- if( getOperationMode(configuration->engineConfiguration) == FOUR_STROKE_CAM_SENSOR) {
+ if (getOperationMode(configuration->engineConfiguration) == FOUR_STROKE_CAM_SENSOR) {
// That's easy - trigger cycle matches engine cycle
triggerIndexForListeners = triggerState.getCurrentIndex();
} else {
@@ -119,7 +125,6 @@ void TriggerCentral::handleShaftSignal(configuration_s *configuration, trigger_e
triggerIndexForListeners = triggerState.getCurrentIndex() + (isEven ? 0 : triggerShape->getSize());
}
-
/**
* Here we invoke all the listeners - the main engine control logic is inside these listeners
*/
@@ -130,7 +135,7 @@ void TriggerCentral::handleShaftSignal(configuration_s *configuration, trigger_e
int diff = afterCallback - beforeCallback;
// this counter is only 32 bits so it overflows every minute, let's ignore the value in case of the overflow for simplicity
if (diff > 0)
- hsAdd(&triggerCallback, diff);
+ hsAdd(&triggerCallback, diff);
#endif /* EFI_HISTOGRAMS */
}
@@ -140,9 +145,18 @@ void printAllCallbacksHistogram(void) {
#endif
}
+static void triggerInfo() {
+#if EFI_PROD_CODE
+ scheduleMsg(&logging, "trigger %d/%d/%d/%d", triggerCentral.getHwEventCounter(0),
+ triggerCentral.getHwEventCounter(1), triggerCentral.getHwEventCounter(2),
+ triggerCentral.getHwEventCounter(3));
+#endif
+}
+
void initTriggerCentral(void) {
#if EFI_PROD_CODE
initLogging(&logging, "ShaftPosition");
+ addConsoleAction("triggerinfo", triggerInfo);
#endif
#if EFI_HISTOGRAMS
diff --git a/firmware/controllers/trigger/trigger_central.h b/firmware/controllers/trigger/trigger_central.h
index 44550a7e13..69a7406472 100644
--- a/firmware/controllers/trigger/trigger_central.h
+++ b/firmware/controllers/trigger/trigger_central.h
@@ -10,19 +10,21 @@
#include "rusefi_enums.h"
#include "listener_array.h"
+#include "trigger_decoder.h"
typedef void (*ShaftPositionListener)(trigger_event_e signal, int index, void *arg);
#ifdef __cplusplus
#include "ec2.h"
-#define HW_EVENT_TYPES 4
+#define HW_EVENT_TYPES 6
class TriggerCentral {
public:
TriggerCentral();
void addEventListener(ShaftPositionListener handler, const char *name, void *arg);
void handleShaftSignal(configuration_s *configuration, trigger_event_e signal, uint64_t nowUs);
+ int getHwEventCounter(int index);
TriggerState triggerState;
private:
IntListenerArray triggerListeneres;
diff --git a/firmware/controllers/trigger/trigger_chrysler.cpp b/firmware/controllers/trigger/trigger_chrysler.cpp
index 2ecffcfcab..5ebd5b8736 100644
--- a/firmware/controllers/trigger/trigger_chrysler.cpp
+++ b/firmware/controllers/trigger/trigger_chrysler.cpp
@@ -19,7 +19,7 @@ void configureNeonTriggerShape(trigger_shape_s *s) {
// voodoo magic - we always need 720 at the end
int base = 720 - 560;
- s->initialState[0] = 1;
+ s->initialState[T_PRIMARY] = 1;
s->addEvent(base - 720 + 600, T_SECONDARY, TV_HIGH);
s->addEvent(base - 720 + 604, T_SECONDARY, TV_LOW);
diff --git a/firmware/controllers/trigger/trigger_decoder.cpp b/firmware/controllers/trigger/trigger_decoder.cpp
index f71d8c0ef0..6b3ea12942 100644
--- a/firmware/controllers/trigger/trigger_decoder.cpp
+++ b/firmware/controllers/trigger/trigger_decoder.cpp
@@ -26,13 +26,11 @@
#include "trigger_chrysler.h"
#include "trigger_gm.h"
#include "trigger_bmw.h"
+#include "trigger_mitsubishi.h"
-extern "C" {
#include "trigger_structure.h"
-#include "wave_math.h"
-}
-#if EFI_PROD_CODE || EFI_SIMULATOR
+#if (EFI_PROD_CODE || EFI_SIMULATOR) || defined(__DOXYGEN__)
static Logging logger;
#endif
@@ -45,33 +43,43 @@ int isTriggerDecoderError(void) {
return errorDetection.sum(6) > 4;
}
-static inline int isSynchronizationGap(TriggerState const *shaftPositionState, trigger_shape_s const *triggerShape,
- trigger_config_s const *triggerConfig, const int currentDuration) {
- if (!triggerShape->isSynchronizationNeeded)
+static inline bool isSynchronizationGap(TriggerState const *shaftPositionState, trigger_shape_s const *triggerShape,
+ const int currentDuration) {
+ if (!triggerShape->isSynchronizationNeeded) {
return false;
+ }
return currentDuration > shaftPositionState->toothed_previous_duration * triggerShape->syncRatioFrom
&& currentDuration < shaftPositionState->toothed_previous_duration * triggerShape->syncRatioTo;
}
-static inline int noSynchronizationResetNeeded(TriggerState *shaftPositionState, trigger_shape_s const *triggerShape,
- trigger_config_s const*triggerConfig) {
- if (triggerShape->isSynchronizationNeeded)
+static inline bool noSynchronizationResetNeeded(TriggerState *shaftPositionState, trigger_shape_s const *triggerShape) {
+ if (triggerShape->isSynchronizationNeeded) {
return false;
- if (!shaftPositionState->shaft_is_synchronized)
- return TRUE;
+ }
+ if (!shaftPositionState->shaft_is_synchronized) {
+ return true;
+ }
/**
* in case of noise the counter could be above the expected number of events
*/
return shaftPositionState->getCurrentIndex() >= triggerShape->shaftPositionEventCount - 1;
}
+static trigger_wheel_e eventIndex[6] = { T_PRIMARY, T_PRIMARY, T_SECONDARY, T_SECONDARY, T_CHANNEL_3, T_CHANNEL_3 };
+static trigger_value_e eventType[6] = { TV_LOW, TV_HIGH, TV_LOW, TV_HIGH, TV_LOW, TV_HIGH };
+
/**
- * @brief Trigger decoding happends here
+ * @brief Trigger decoding happens here
* This method changes the state of trigger_state_s data structure according to the trigger event
*/
void TriggerState::decodeTriggerEvent(trigger_shape_s const*triggerShape, trigger_config_s const*triggerConfig,
- trigger_event_e signal, uint64_t nowUs) {
+ trigger_event_e const signal, uint64_t nowUs) {
+ efiAssertVoid(signal <= SHAFT_3RD_UP, "unexpected signal");
+
+ trigger_wheel_e triggerWheel = eventIndex[signal];
+
+ eventCount[triggerWheel]++;
int isLessImportant = (triggerShape->useRiseEdge && signal != SHAFT_PRIMARY_UP)
|| (!triggerShape->useRiseEdge && signal != SHAFT_PRIMARY_DOWN);
@@ -80,7 +88,7 @@ void TriggerState::decodeTriggerEvent(trigger_shape_s const*triggerShape, trigge
/**
* For less important events we simply increment the index.
*/
- nextTriggerEvent();
+ nextTriggerEvent(triggerWheel, nowUs);
return;
}
@@ -100,28 +108,37 @@ void TriggerState::decodeTriggerEvent(trigger_shape_s const*triggerShape, trigge
}
#endif
- if (noSynchronizationResetNeeded(this, triggerShape, triggerConfig)
- || isSynchronizationGap(this, triggerShape, triggerConfig, currentDuration)) {
+ if (noSynchronizationResetNeeded(this, triggerShape) || isSynchronizationGap(this, triggerShape, currentDuration)) {
/**
* We can check if things are fine by comparing the number of events in a cycle with the expected number of event.
*/
- int isDecodingError = getCurrentIndex() != triggerShape->shaftPositionEventCount - 1;
+ bool isDecodingError = eventCount[0] != triggerShape->expectedEventCount[0]
+ || eventCount[1] != triggerShape->expectedEventCount[1]
+ || eventCount[2] != triggerShape->expectedEventCount[2];
+
errorDetection.add(isDecodingError);
- if (isTriggerDecoderError())
- warning(OBD_PCM_Processor_Fault, "trigger decoding issue");
+ if (isTriggerDecoderError()) {
+ warning(OBD_PCM_Processor_Fault, "trigger decoding issue. expected %d/%d/%d got %d/%d/%d",
+ triggerShape->expectedEventCount[0], triggerShape->expectedEventCount[1],
+ triggerShape->expectedEventCount[2], eventCount[0], eventCount[1], eventCount[2]);
+ }
- shaft_is_synchronized = TRUE;
- nextRevolution(triggerShape->shaftPositionEventCount);
+ shaft_is_synchronized = true;
+ // this call would update duty cycle values
+// nextTriggerEvent(triggerWheel, nowUs);
+
+ nextRevolution(triggerShape->shaftPositionEventCount, nowUs);
} else {
- nextTriggerEvent();
+ nextTriggerEvent(triggerWheel, nowUs);
}
toothed_previous_duration = currentDuration;
toothed_previous_time = nowUs;
}
-static void initializeSkippedToothTriggerShape(trigger_shape_s *s, int totalTeethCount, int skippedCount, operation_mode_e operationMode) {
+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(operationMode);
@@ -139,8 +156,8 @@ static void initializeSkippedToothTriggerShape(trigger_shape_s *s, int totalTeet
s->addEvent(720, T_PRIMARY, TV_LOW);
}
-void initializeSkippedToothTriggerShapeExt(trigger_shape_s *s, int totalTeethCount,
- int skippedCount, operation_mode_e operationMode) {
+void initializeSkippedToothTriggerShapeExt(trigger_shape_s *s, int totalTeethCount, int skippedCount,
+ operation_mode_e operationMode) {
efiAssertVoid(totalTeethCount > 0, "totalTeethCount is zero");
s->totalToothCount = totalTeethCount;
@@ -185,17 +202,16 @@ void initializeTriggerShape(Logging *logger, engine_configuration_s *engineConfi
triggerShape->useRiseEdge = TRUE;
triggerShape->needSecondTriggerInput = TRUE;
-
switch (triggerConfig->triggerType) {
case TT_TOOTHED_WHEEL:
engineConfiguration2->triggerShape.needSecondTriggerInput = false;
- engineConfiguration2->triggerShape.isSynchronizationNeeded = engineConfiguration->triggerConfig.customIsSynchronizationNeeded;
+ engineConfiguration2->triggerShape.isSynchronizationNeeded =
+ engineConfiguration->triggerConfig.customIsSynchronizationNeeded;
initializeSkippedToothTriggerShapeExt(triggerShape, triggerConfig->customTotalToothCount,
- triggerConfig->customSkippedToothCount,
- getOperationMode(engineConfiguration));
+ triggerConfig->customSkippedToothCount, getOperationMode(engineConfiguration));
return;
case TT_MAZDA_MIATA_NB:
@@ -231,6 +247,22 @@ void initializeTriggerShape(Logging *logger, engine_configuration_s *engineConfi
setToothedWheelConfiguration(triggerShape, 36, 1, engineConfiguration);
return;
+ case TT_HONDA_ACCORD_CD_TWO_WIRES:
+ configureHondaAccordCD(triggerShape, false);
+ return;
+
+ case TT_HONDA_ACCORD_CD:
+ configureHondaAccordCD(triggerShape, true);
+ return;
+
+ case TT_HONDA_ACCORD_CD_DIP:
+ configureHondaAccordCDDip(triggerShape);
+ return;
+
+ case TT_MITSU:
+ initializeMitsubishi4g18(triggerShape);
+ return;
+
default:
firmwareError("initializeTriggerShape() not implemented: %d", triggerConfig->triggerType);
;
@@ -244,7 +276,8 @@ TriggerStimulatorHelper::TriggerStimulatorHelper() {
secondaryWheelState = false;
}
-void TriggerStimulatorHelper::nextStep(TriggerState *state, trigger_shape_s * shape, int i, trigger_config_s const*triggerConfig) {
+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();
@@ -267,6 +300,22 @@ void TriggerStimulatorHelper::nextStep(TriggerState *state, trigger_shape_s * sh
}
}
+static void onFindIndex(TriggerState *state) {
+
+}
+
+static int doFindTrigger(TriggerStimulatorHelper *helper, trigger_shape_s * shape, trigger_config_s const*triggerConfig,
+ TriggerState *state) {
+ for (int i = 0; i < 4 * PWM_PHASE_MAX_COUNT; i++) {
+ helper->nextStep(state, shape, i, triggerConfig);
+
+ if (state->shaft_is_synchronized)
+ return i % shape->getSize();;
+ }
+ firmwareError("findTriggerZeroEventIndex() failed");
+ return EFI_ERROR_CODE;
+}
+
/**
* 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.
@@ -278,16 +327,23 @@ int findTriggerZeroEventIndex(trigger_shape_s * shape, trigger_config_s const*tr
TriggerState state;
errorDetection.clear();
+
TriggerStimulatorHelper helper;
- for (int i = 0; i < 4 * PWM_PHASE_MAX_COUNT; i++) {
- helper.nextStep(&state, shape, i, triggerConfig);
-
- if (state.shaft_is_synchronized)
- return i % shape->getSize();;
+ int index = doFindTrigger(&helper, shape, triggerConfig, &state);
+ if (index == EFI_ERROR_CODE) {
+ return index;
}
- firmwareError("findTriggerZeroEventIndex() failed");
- return -1;
+ /**
+ * Now that we have just located the synch point, we can simulate the whole cycle
+ * in order to calculate expected duty cycle
+ */
+
+
+ state.cycleCallback = onFindIndex;
+
+
+ return index;
}
void initTriggerDecoder(void) {
diff --git a/firmware/controllers/trigger/trigger_decoder.h b/firmware/controllers/trigger/trigger_decoder.h
index 8922c881f7..cbe6ccf00a 100644
--- a/firmware/controllers/trigger/trigger_decoder.h
+++ b/firmware/controllers/trigger/trigger_decoder.h
@@ -8,12 +8,52 @@
#ifndef TRIGGER_DECODER_H_
#define TRIGGER_DECODER_H_
-#include
-
#include "trigger_structure.h"
#include "engine_configuration.h"
#include "ec2.h"
+class TriggerState;
+
+typedef void (*TriggerStateCallback)(TriggerState *);
+
+class TriggerState {
+public:
+ TriggerState();
+ int getCurrentIndex();
+ int getTotalRevolutionCounter();
+ uint64_t getTotalEventCounter();
+ uint64_t getStartOfRevolutionIndex();
+ void nextRevolution(int triggerEventCount, uint64_t nowUs);
+ void nextTriggerEvent(trigger_wheel_e triggerWheel, uint64_t nowUs);
+ void decodeTriggerEvent(trigger_shape_s const*triggerShape, trigger_config_s const*triggerConfig, trigger_event_e const signal, uint64_t nowUs);
+
+ TriggerStateCallback cycleCallback;
+
+ /**
+ * TRUE if we know where we are
+ */
+ unsigned char shaft_is_synchronized;
+
+ uint64_t toothed_previous_duration;
+ uint64_t toothed_previous_time;
+private:
+ void clear();
+ /**
+ * index within trigger revolution, from 0 to trigger event count
+ */
+ int current_index;
+ /**
+ * Number of actual events within current trigger cycle
+ * see trigger_shape_s
+ */
+ int eventCount[PWM_PHASE_MAX_WAVE_PER_PWM];
+ uint64_t timeOfPreviousEvent[PWM_PHASE_MAX_WAVE_PER_PWM];
+ int totalTime[PWM_PHASE_MAX_WAVE_PER_PWM];
+ uint64_t totalEventCountBase;
+ int totalRevolutionCounter;
+ bool isFirstEvent;
+};
+
class TriggerStimulatorHelper {
public:
TriggerStimulatorHelper();
diff --git a/firmware/controllers/trigger/trigger_emulator_algo.cpp b/firmware/controllers/trigger/trigger_emulator_algo.cpp
index b9bf2cd808..a4250adff1 100644
--- a/firmware/controllers/trigger/trigger_emulator_algo.cpp
+++ b/firmware/controllers/trigger/trigger_emulator_algo.cpp
@@ -7,7 +7,6 @@
#include "main.h"
#include "trigger_emulator_algo.h"
#include "engine_configuration.h"
-#include "wave_math.h"
#include "LocalVersionHolder.h"
#include "ec2.h"
@@ -20,8 +19,9 @@ extern engine_configuration2_s *engineConfiguration2;
*/
static int pinStates1[PWM_PHASE_MAX_COUNT];
static int pinStates2[PWM_PHASE_MAX_COUNT];
-static single_wave_s waves[2] = {single_wave_s(pinStates1), single_wave_s(pinStates2)};
-static single_wave_s sr[2] = {waves[0], waves[1]};
+static int pinStates3[PWM_PHASE_MAX_COUNT];
+static single_wave_s waves[PWM_PHASE_MAX_WAVE_PER_PWM] = {single_wave_s(pinStates1), single_wave_s(pinStates2), single_wave_s(pinStates3)};
+static single_wave_s sr[PWM_PHASE_MAX_WAVE_PER_PWM] = {waves[0], waves[1], waves[2]};
static float swtchTms[PWM_PHASE_MAX_COUNT];
@@ -52,8 +52,8 @@ static void updateTriggerShapeIfNeeded(PwmConfig *state) {
applyNonPersistentConfiguration(&logger, engineConfiguration, engineConfiguration2);
trigger_shape_s *s = &engineConfiguration2->triggerShape;
- int *pinStates[2] = {s->wave.waves[0].pinStates, s->wave.waves[1].pinStates};
- copyPwmParameters(state, s->getSize(), s->wave.switchTimes, 2, pinStates);
+ int *pinStates[PWM_PHASE_MAX_WAVE_PER_PWM] = {s->wave.waves[0].pinStates, s->wave.waves[1].pinStates, s->wave.waves[2].pinStates};
+ copyPwmParameters(state, s->getSize(), s->wave.switchTimes, PWM_PHASE_MAX_WAVE_PER_PWM, pinStates);
state->safe.periodUs = -1; // this would cause loop re-initialization
}
}
@@ -64,10 +64,9 @@ 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};
- weComplexInit("position sensor", &triggerSignal, s->getSize(), s->wave.switchTimes, 2, pinStates,
- updateTriggerShapeIfNeeded,
- stateChangeCallback);
+ int *pinStates[PWM_PHASE_MAX_WAVE_PER_PWM] = { s->wave.waves[0].pinStates, s->wave.waves[1].pinStates, s->wave.waves[2].pinStates};
+ weComplexInit("position sensor", &triggerSignal, s->getSize(), s->wave.switchTimes, PWM_PHASE_MAX_WAVE_PER_PWM, pinStates,
+ updateTriggerShapeIfNeeded, stateChangeCallback);
addConsoleActionI("rpm", &setTriggerEmulatorRPM);
diff --git a/firmware/controllers/trigger/trigger_gm.cpp b/firmware/controllers/trigger/trigger_gm.cpp
index 0283cd6a10..cd9ae5a6e2 100644
--- a/firmware/controllers/trigger/trigger_gm.cpp
+++ b/firmware/controllers/trigger/trigger_gm.cpp
@@ -16,25 +16,25 @@ void configureGmTriggerShape(trigger_config_s *triggerConfig, trigger_shape_s *s
s->shaftPositionEventCount = 14;
s->addEvent(120 - w, T_PRIMARY, TV_HIGH);
- s->addEvent(120, T_PRIMARY, TV_LOW);
+ s->addEvent(120.0, T_PRIMARY, TV_LOW);
s->addEvent(240 - w, T_PRIMARY, TV_HIGH);
- s->addEvent(240, T_PRIMARY, TV_LOW);
+ s->addEvent(240.0, T_PRIMARY, TV_LOW);
s->addEvent(360 - w, T_PRIMARY, TV_HIGH);
- s->addEvent(360, T_PRIMARY, TV_LOW);
+ s->addEvent(360.0, T_PRIMARY, TV_LOW);
s->addEvent(480 - w, T_PRIMARY, TV_HIGH);
- s->addEvent(480, T_PRIMARY, TV_LOW);
+ s->addEvent(480.0, T_PRIMARY, TV_LOW);
s->addEvent(600 - w, T_PRIMARY, TV_HIGH);
- s->addEvent(600, T_PRIMARY, TV_LOW);
+ s->addEvent(600.0, T_PRIMARY, TV_LOW);
s->addEvent(700 - w, T_PRIMARY, TV_HIGH);
- s->addEvent(700, T_PRIMARY, TV_LOW);
+ s->addEvent(700.0, T_PRIMARY, TV_LOW);
s->addEvent(720 - w, T_PRIMARY, TV_HIGH);
- s->addEvent(720, T_PRIMARY, TV_LOW);
+ s->addEvent(720.0, T_PRIMARY, TV_LOW);
}
diff --git a/firmware/controllers/trigger/trigger_mazda.cpp b/firmware/controllers/trigger/trigger_mazda.cpp
index bc0629e7a6..a5c29a536b 100644
--- a/firmware/controllers/trigger/trigger_mazda.cpp
+++ b/firmware/controllers/trigger/trigger_mazda.cpp
@@ -21,7 +21,7 @@
#include "trigger_mazda.h"
void initializeMazdaMiataNbShape(trigger_shape_s *s) {
- setTriggerSynchronizationGap(s, 0.11);
+ setTriggerSynchronizationGap(s, 0.11f);
s->useRiseEdge = false;
s->reset(FOUR_STROKE_CAM_SENSOR);
@@ -29,33 +29,33 @@ void initializeMazdaMiataNbShape(trigger_shape_s *s) {
/**
* cam sensor is primary, crank sensor is secondary
*/
- s->addEvent(20, T_PRIMARY, TV_HIGH);
+ s->addEvent(20.0f, T_PRIMARY, 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);
+ s->addEvent(66.0f, T_SECONDARY, TV_LOW);
+ s->addEvent(70.0f, T_SECONDARY, TV_HIGH);
+ s->addEvent(136.0f, T_SECONDARY, TV_LOW);
+ s->addEvent(140.0f, T_SECONDARY, TV_HIGH);
+ s->addEvent(246.0f, T_SECONDARY, TV_LOW);
+ s->addEvent(250.0f, T_SECONDARY, TV_HIGH);
+ s->addEvent(316.0f, T_SECONDARY, TV_LOW);
+ s->addEvent(320.0f, T_SECONDARY, TV_HIGH);
- s->addEvent(340, T_PRIMARY, TV_LOW);
- s->addEvent(360, T_PRIMARY, TV_HIGH);
+ s->addEvent(340.0f, T_PRIMARY, TV_LOW);
+ s->addEvent(360.0f, T_PRIMARY, TV_HIGH);
- s->addEvent(380, T_PRIMARY, TV_LOW);
- s->addEvent(400, T_PRIMARY, TV_HIGH);
+ s->addEvent(380.0f, T_PRIMARY, TV_LOW);
+ s->addEvent(400.0f, T_PRIMARY, 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);
+ s->addEvent(426.0f, T_SECONDARY, TV_LOW);
+ s->addEvent(430.0f, T_SECONDARY, TV_HIGH);
+ s->addEvent(496.0f, T_SECONDARY, TV_LOW);
+ s->addEvent(500.0f, T_SECONDARY, TV_HIGH);
+ s->addEvent(606.0f, T_SECONDARY, TV_LOW);
+ s->addEvent(610.0f, T_SECONDARY, TV_HIGH);
+ s->addEvent(676.0f, T_SECONDARY, TV_LOW);
+ s->addEvent(680.0f, T_SECONDARY, TV_HIGH);
- s->addEvent(720, T_PRIMARY, TV_LOW);
+ s->addEvent(720.0f, T_PRIMARY, TV_LOW);
s->shaftPositionEventCount = 6 + 16;
}
@@ -68,7 +68,7 @@ void configureMazdaProtegeLx(trigger_shape_s *s) {
s->reset(FOUR_STROKE_CAM_SENSOR);
// s->initialState[0] = 1;
- float w = 720 / 4 * 0.215;
+// float w = 720 / 4 * 0.215;
float a = 5;
// s->addEvent(a, T_SECONDARY, TV_LOW);
// s->addEvent(a + w, T_SECONDARY, TV_HIGH);
diff --git a/firmware/controllers/trigger/trigger_mitsubishi.cpp b/firmware/controllers/trigger/trigger_mitsubishi.cpp
new file mode 100644
index 0000000000..5ffcfa3aef
--- /dev/null
+++ b/firmware/controllers/trigger/trigger_mitsubishi.cpp
@@ -0,0 +1,35 @@
+/**
+ * @file trigger_mitsubishi.cpp
+ *
+ * @date Aug 5, 2014
+ * @author Andrey Belomutskiy, (c) 2012-2014
+ */
+
+#include "trigger_mitsubishi.h"
+
+void initializeMitsubishi4g18(trigger_shape_s *s) {
+ s->reset(FOUR_STROKE_CAM_SENSOR);
+ s->useRiseEdge = false;
+
+ setTriggerSynchronizationGap(s, 1.6666);
+
+ int secondaryWidth = 70;
+
+ s->addEvent(180.0 - 131 + 5, T_PRIMARY, TV_HIGH);
+ s->addEvent(180.0 - secondaryWidth, T_SECONDARY, TV_HIGH);
+ s->addEvent(180.0, T_SECONDARY, TV_LOW);
+ s->addEvent(180.0 + 49 + 5, T_PRIMARY, TV_LOW);
+
+ s->addEvent(360.0 - secondaryWidth, T_SECONDARY, TV_HIGH);
+ s->addEvent(360.0, T_SECONDARY, TV_LOW);
+
+ s->addEvent(540.0 - 131 + 5, T_PRIMARY, TV_HIGH);
+ s->addEvent(540.0 - secondaryWidth, T_SECONDARY, TV_HIGH);
+ s->addEvent(540.0 - 131 + 5 + 90, T_PRIMARY, TV_LOW);
+ s->addEvent(540.0, T_SECONDARY, TV_LOW);
+
+ s->addEvent(720.0 - secondaryWidth, T_SECONDARY, TV_HIGH);
+ s->addEvent(720.0, T_SECONDARY, TV_LOW);
+
+ s->shaftPositionEventCount = s->getSize();
+}
diff --git a/firmware/controllers/trigger/trigger_mitsubishi.h b/firmware/controllers/trigger/trigger_mitsubishi.h
new file mode 100644
index 0000000000..3d72956fbe
--- /dev/null
+++ b/firmware/controllers/trigger/trigger_mitsubishi.h
@@ -0,0 +1,14 @@
+/**
+ * @file trigger_mitsubishi.h
+ *
+ * @date Aug 5, 2014
+ * @author Andrey Belomutskiy, (c) 2012-2014
+ */
+#ifndef TRIGGER_MITSUBISHI_H_
+#define TRIGGER_MITSUBISHI_H_
+
+#include "trigger_structure.h"
+
+void initializeMitsubishi4g18(trigger_shape_s *s);
+
+#endif /* TRIGGER_MITSUBISHI_H_ */
diff --git a/firmware/controllers/trigger/trigger_structure.cpp b/firmware/controllers/trigger/trigger_structure.cpp
index a11cdb8ac2..8b00593baa 100644
--- a/firmware/controllers/trigger/trigger_structure.cpp
+++ b/firmware/controllers/trigger/trigger_structure.cpp
@@ -24,17 +24,18 @@
#include "trigger_decoder.h"
trigger_shape_helper::trigger_shape_helper() {
- waves[0].init(pinStates0);
- waves[1].init(pinStates1);
+ for (int i = 0; i < TRIGGER_CHANNEL_COUNT; i++) {
+ waves[i].init(pinStates[i]);
+ }
}
trigger_shape_s::trigger_shape_s() :
- wave(switchTimes, NULL) {
+ wave(switchTimesBuffer, NULL) {
reset(OM_NONE);
wave.waves = h.waves;
}
-int trigger_shape_s::getSize() {
+int trigger_shape_s::getSize() const {
return size;
}
@@ -46,6 +47,10 @@ int trigger_shape_s::getTriggerShapeSynchPointIndex() {
int getEngineCycleEventCount2(operation_mode_e mode, trigger_shape_s * s);
float fixAngle(float angle);
+void trigger_shape_s::calculateTriggerSynchPoint(trigger_config_s const*triggerConfig) {
+ setTriggerShapeSynchPointIndex(findTriggerZeroEventIndex(this, triggerConfig));
+}
+
void trigger_shape_s::setTriggerShapeSynchPointIndex(int triggerShapeSynchPointIndex) {
this->triggerShapeSynchPointIndex = triggerShapeSynchPointIndex;
@@ -69,7 +74,8 @@ void trigger_shape_s::reset(operation_mode_e operationMode) {
shaftPositionEventCount = 0;
triggerShapeSynchPointIndex = 0;
memset(initialState, 0, sizeof(initialState));
- memset(switchTimes, 0, sizeof(switchTimes));
+ memset(switchTimesBuffer, 0, sizeof(switchTimesBuffer));
+ memset(expectedEventCount, 0, sizeof(expectedEventCount));
wave.reset();
previousAngle = 0;
}
@@ -78,11 +84,32 @@ int multi_wave_s::getChannelState(int channelIndex, int phaseIndex) const {
return waves[channelIndex].pinStates[phaseIndex];
}
+int multi_wave_s::waveIndertionAngle(float angle, int size) const {
+ for (int i = size - 1; i >= 0; i--) {
+ if (angle > switchTimes[i])
+ return i + 1;
+ }
+ return 0;
+}
+
+int multi_wave_s::findAngleMatch(float angle, int size) const {
+ for (int i = 0; i < size; i++) {
+ if (isSameF(switchTimes[i], angle))
+ return i;
+ }
+ return EFI_ERROR_CODE;
+}
+
void multi_wave_s::setSwitchTime(int index, float value) {
switchTimes[index] = value;
}
TriggerState::TriggerState() {
+ cycleCallback = NULL;
+ shaft_is_synchronized = FALSE;
+ toothed_previous_time = 0;
+ toothed_previous_duration = 0;
+ totalRevolutionCounter = 0;
clear();
totalEventCountBase = 0;
isFirstEvent = true;
@@ -100,8 +127,11 @@ uint64_t TriggerState::getTotalEventCounter() {
return totalEventCountBase + current_index;
}
-void TriggerState::nextRevolution(int triggerEventCount) {
- current_index = 0;
+void TriggerState::nextRevolution(int triggerEventCount, uint64_t nowUs) {
+ if (cycleCallback != NULL) {
+ cycleCallback(this);
+ }
+ clear();
totalRevolutionCounter++;
totalEventCountBase += triggerEventCount;
}
@@ -110,21 +140,29 @@ int TriggerState::getTotalRevolutionCounter() {
return totalRevolutionCounter;
}
-void TriggerState::nextTriggerEvent() {
+void TriggerState::nextTriggerEvent(trigger_wheel_e triggerWheel, uint64_t nowUs) {
+ uint64_t prevTime = timeOfPreviousEvent[triggerWheel];
+ if (prevTime != 0) {
+ totalTime[triggerWheel] += (nowUs - prevTime);
+ timeOfPreviousEvent[triggerWheel] = 0;
+ } else {
+ timeOfPreviousEvent[triggerWheel] = nowUs;
+ }
+
current_index++;
}
void TriggerState::clear() {
- shaft_is_synchronized = FALSE;
- toothed_previous_time = 0;
- toothed_previous_duration = 0;
+ memset(eventCount, 0, sizeof(eventCount));
+ memset(timeOfPreviousEvent, 0, sizeof(timeOfPreviousEvent));
+ memset(totalTime, 0, sizeof(totalTime));
current_index = 0;
- totalRevolutionCounter = 0;
}
float trigger_shape_s::getAngle(int index) const {
- if (operationMode == FOUR_STROKE_CAM_SENSOR)
- return switchAngles[index];
+ if (operationMode == FOUR_STROKE_CAM_SENSOR) {
+ return getSwitchAngle(index);
+ }
/**
* FOUR_STROKE_CRANK_SENSOR magic:
* We have two crank shaft revolutions for each engine cycle
@@ -134,20 +172,29 @@ float trigger_shape_s::getAngle(int index) const {
int triggerEventCounter = size;
if (index < triggerEventCounter) {
- return switchAngles[index];
+ return getSwitchAngle(index);
} else {
- return 360 + switchAngles[index - triggerEventCounter];
+ return 360 + getSwitchAngle(index - triggerEventCounter);
}
}
-void trigger_shape_s::addEvent(float angle, trigger_wheel_e waveIndex, trigger_value_e state) {
+void trigger_shape_s::addEvent(float angle, trigger_wheel_e const waveIndex, trigger_value_e const 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");
+
+ expectedEventCount[waveIndex]++;
+
+ efiAssertVoid(angle > 0, "angle should be positive");
+ if (size > 0) {
+ if (angle <= previousAngle) {
+ firmwareError("invalid angle order: %f and %f", angle, previousAngle);
+ return;
+ }
+ }
previousAngle = angle;
if (size == 0) {
size = 1;
@@ -165,46 +212,203 @@ void trigger_shape_s::addEvent(float angle, trigger_wheel_e waveIndex, trigger_v
wave->pinStates[0] = initialState[i];
}
- setSwitchTime(0, angle);
+ wave.setSwitchTime(0, angle);
wave.waves[waveIndex].pinStates[0] = state;
return;
}
-// if(angle!=trigger->wave.switchTimes[trigger->currentIndex])
+ int exactMatch = wave.findAngleMatch(angle, size);
+ if (exactMatch != EFI_ERROR_CODE) {
+ firmwareError("same angle: not supported");
+ return;
+ }
- int index = size++;
+ int index = wave.waveIndertionAngle(angle, size);
- for (int i = 0; i < PWM_PHASE_MAX_WAVE_PER_PWM; i++)
+ // shifting existing data
+ for (int i = size - 1; i >= index; i--) {
+ for (int j = 0; j < PWM_PHASE_MAX_WAVE_PER_PWM; j++) {
+ wave.waves[j].pinStates[i + 1] = wave.getChannelState(j, index);
+ }
+ wave.setSwitchTime(i + 1, wave.getSwitchTime(i));
+ }
+
+// int index = size;
+ size++;
+
+ for (int i = 0; i < PWM_PHASE_MAX_WAVE_PER_PWM; i++) {
wave.waves[i].pinStates[index] = wave.getChannelState(i, index - 1);
- setSwitchTime(index, angle);
+ }
+ wave.setSwitchTime(index, angle);
wave.waves[waveIndex].pinStates[index] = 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);
+int trigger_shape_s::getCycleDuration() const {
+ return (operationMode == FOUR_STROKE_CAM_SENSOR) ? 720 : 360;
+}
+
+float trigger_shape_s::getSwitchAngle(int index) const {
+ return getCycleDuration() * wave.getSwitchTime(index);
}
void multi_wave_s::checkSwitchTimes(int size) {
checkSwitchTimes2(size, switchTimes);
}
-void setToothedWheelConfiguration(trigger_shape_s *s, int total, int skipped, engine_configuration_s const *engineConfiguration) {
+void setToothedWheelConfiguration(trigger_shape_s *s, int total, int skipped,
+ engine_configuration_s const *engineConfiguration) {
s->isSynchronizationNeeded = (skipped != 0);
s->totalToothCount = total;
s->skippedToothCount = skipped;
s->needSecondTriggerInput = false;
- s->useRiseEdge = TRUE;
+ s->useRiseEdge = true;
- initializeSkippedToothTriggerShapeExt(s, s->totalToothCount,
- s->skippedToothCount,
+ initializeSkippedToothTriggerShapeExt(s, s->totalToothCount, s->skippedToothCount,
getOperationMode(engineConfiguration));
}
void setTriggerSynchronizationGap(trigger_shape_s *s, float synchGap) {
- s->isSynchronizationNeeded = TRUE;
+ s->isSynchronizationNeeded = true;
s->syncRatioFrom = synchGap * 0.75;
s->syncRatioTo = synchGap * 1.25;
}
+
+#define S24 (720.0f / 24 / 2)
+
+static float addAccordPair(trigger_shape_s *s, float sb) {
+ s->addEvent(sb, T_SECONDARY, TV_HIGH);
+ sb += S24;
+ s->addEvent(sb, T_SECONDARY, TV_LOW);
+ sb += S24;
+
+ return sb;
+}
+
+#define DIP 7.5f
+static float addAccordPair3(trigger_shape_s *s, float sb) {
+ sb += DIP;
+ s->addEvent(sb, T_CHANNEL_3, TV_HIGH);
+ sb += DIP;
+ s->addEvent(sb, T_CHANNEL_3, TV_LOW);
+ sb += 2 * DIP;
+ return sb;
+}
+
+/**
+ * Thank you Dip!
+ * http://forum.pgmfi.org/viewtopic.php?f=2&t=15570start=210#p139007
+ */
+void configureHondaAccordCDDip(trigger_shape_s *s) {
+ s->reset(FOUR_STROKE_CAM_SENSOR);
+
+ s->initialState[T_SECONDARY] = TV_HIGH;
+ float sb = 0;
+ sb = addAccordPair3(s, sb);
+ sb = addAccordPair3(s, sb);
+ sb = addAccordPair3(s, sb);
+
+ s->addEvent(90, T_SECONDARY, TV_LOW);
+ sb = 90;
+ sb = addAccordPair3(s, sb);
+ sb = addAccordPair3(s, sb);
+ sb = addAccordPair3(s, sb);
+
+ s->addEvent(180, T_SECONDARY, TV_HIGH);
+ sb = 180;
+ sb = addAccordPair3(s, sb);
+ sb = addAccordPair3(s, sb);
+ sb = addAccordPair3(s, sb);
+
+ s->addEvent(270, T_SECONDARY, TV_LOW);
+ sb = 270;
+ sb = addAccordPair3(s, sb);
+ sb = addAccordPair3(s, sb);
+ sb = addAccordPair3(s, sb);
+
+
+ s->addEvent(360.0f - DIP, T_PRIMARY, TV_HIGH);
+ s->addEvent(360, T_SECONDARY, TV_HIGH);
+ sb = 360;
+ sb = addAccordPair3(s, sb);
+ sb = addAccordPair3(s, sb);
+ sb = addAccordPair3(s, sb);
+
+ s->addEvent(450, T_SECONDARY, TV_LOW);
+ sb = 450;
+ sb = addAccordPair3(s, sb);
+ sb = addAccordPair3(s, sb);
+ sb = addAccordPair3(s, sb);
+
+ s->addEvent(540, T_SECONDARY, TV_HIGH);
+ sb = 540;
+ sb = addAccordPair3(s, sb);
+ sb = addAccordPair3(s, sb);
+ sb = addAccordPair3(s, sb);
+
+ s->addEvent(630, T_SECONDARY, TV_LOW);
+ sb = 630;
+ sb = addAccordPair3(s, sb);
+ sb = addAccordPair3(s, sb);
+ sb = addAccordPair3(s, sb);
+
+ s->addEvent(720.0f - DIP, T_PRIMARY, TV_LOW);
+
+// s->addEvent(720.0f - 12 * sb, T_SECONDARY, TV_LOW);
+// s->addEvent(720.0f, T_SECONDARY, TV_LOW);
+
+ s->addEvent(720.0f, T_SECONDARY, TV_HIGH);
+
+ s->isSynchronizationNeeded = false;
+
+ s->shaftPositionEventCount = s->getSize();
+}
+
+void configureHondaAccordCD(trigger_shape_s *s, bool with3rdSignal) {
+ s->reset(FOUR_STROKE_CAM_SENSOR);
+
+ float sb = 5.0f;
+
+ float tdcWidth = 0.1854 * 720 / 4;
+
+ s->isSynchronizationNeeded = false;
+
+ sb = addAccordPair(s, sb);
+
+ if (with3rdSignal)
+ s->addEvent(sb - S24 / 2, T_CHANNEL_3, TV_HIGH);
+
+ sb = addAccordPair(s, sb);
+ sb = addAccordPair(s, sb);
+ if (with3rdSignal)
+ s->addEvent(sb - S24 / 2, T_CHANNEL_3, TV_LOW);
+ sb = addAccordPair(s, sb);
+ sb = addAccordPair(s, sb);
+ s->addEvent(1 * 180.0f - tdcWidth, T_PRIMARY, TV_HIGH);
+ sb = addAccordPair(s, sb);
+ s->addEvent(1 * 180.0f, T_PRIMARY, TV_LOW);
+
+ sb = addAccordPair(s, sb);
+ sb = addAccordPair(s, sb);
+ sb = addAccordPair(s, sb);
+ sb = addAccordPair(s, sb);
+ sb = addAccordPair(s, sb);
+
+ s->addEvent(2 * 180.0f - tdcWidth, T_PRIMARY, TV_HIGH);
+ sb = addAccordPair(s, sb);
+ s->addEvent(2 * 180.0f, T_PRIMARY, TV_LOW);
+
+ for (int i = 3; i <= 4; i++) {
+ sb = addAccordPair(s, sb);
+ sb = addAccordPair(s, sb);
+ sb = addAccordPair(s, sb);
+ sb = addAccordPair(s, sb);
+ sb = addAccordPair(s, sb);
+
+ s->addEvent(i * 180.0f - tdcWidth, T_PRIMARY, TV_HIGH);
+ sb = addAccordPair(s, sb);
+ s->addEvent(i * 180.0f, T_PRIMARY, TV_LOW);
+ }
+
+ s->shaftPositionEventCount = s->getSize();
+}
diff --git a/firmware/controllers/trigger/trigger_structure.h b/firmware/controllers/trigger/trigger_structure.h
index ee79de4b38..ee8b02e0d0 100644
--- a/firmware/controllers/trigger/trigger_structure.h
+++ b/firmware/controllers/trigger/trigger_structure.h
@@ -16,61 +16,19 @@
class trigger_shape_s;
-class TriggerState {
-public:
- TriggerState();
- int getCurrentIndex();
- int getTotalRevolutionCounter();
- uint64_t getTotalEventCounter();
- uint64_t getStartOfRevolutionIndex();
- void nextRevolution(int triggerEventCount);
- void nextTriggerEvent();
- void decodeTriggerEvent(trigger_shape_s const*triggerShape, trigger_config_s const*triggerConfig, trigger_event_e signal, uint64_t nowUs);
-
-
- /**
- * TRUE if we know where we are
- */
- unsigned char shaft_is_synchronized;
-
- uint64_t toothed_previous_duration;
- uint64_t toothed_previous_time;
-private:
- void clear();
- /**
- * index within trigger revolution, from 0 to trigger event count
- */
- int current_index;
- uint64_t totalEventCountBase;
- int totalRevolutionCounter;
- bool isFirstEvent;
-};
-
-typedef enum {
- TV_LOW = 0,
- TV_HIGH = 1
-} trigger_value_e;
-
-typedef enum {
- T_PRIMARY = 0,
- T_SECONDARY = 1
-} trigger_wheel_e;
+#define TRIGGER_CHANNEL_COUNT 3
class trigger_shape_helper {
- int pinStates0[PWM_PHASE_MAX_COUNT];
- int pinStates1[PWM_PHASE_MAX_COUNT];
+ int pinStates[TRIGGER_CHANNEL_COUNT][PWM_PHASE_MAX_COUNT];
public:
trigger_shape_helper();
- single_wave_s waves[2];
+ single_wave_s waves[TRIGGER_CHANNEL_COUNT];
};
class trigger_shape_s {
-private:
- void setSwitchTime(int index, float angle);
- trigger_shape_helper h;
- int size;
public:
+ trigger_shape_s();
int isSynchronizationNeeded;
int totalToothCount;
@@ -81,14 +39,15 @@ public:
int useRiseEdge;
+ /**
+ * This is used for signal validation
+ */
+ int expectedEventCount[PWM_PHASE_MAX_WAVE_PER_PWM];
+
bool needSecondTriggerInput;
-
-
- trigger_shape_s();
- void addEvent(float angle, trigger_wheel_e waveIndex, trigger_value_e state);
- float getAngle(int phaseIndex) const;
+ void addEvent(float angle, trigger_wheel_e const waveIndex, trigger_value_e const state);
void reset(operation_mode_e operationMode);
- int getSize();
+ int getSize() const;
multi_wave_s wave;
/**
@@ -102,16 +61,20 @@ public:
// tood: maybe even automate this flag calculation?
int initialState[PWM_PHASE_MAX_WAVE_PER_PWM];
-
int getTriggerShapeSynchPointIndex();
+ void calculateTriggerSynchPoint(trigger_config_s const*triggerConfig);
+
void setTriggerShapeSynchPointIndex(int triggerShapeSynchPointIndex);
/**
* These angles are in event coordinates - with synchronization point located at angle zero.
+ * These values are pre-calculated for performance reasons.
*/
float eventAngles[PWM_PHASE_MAX_COUNT];
private:
+ trigger_shape_helper h;
+ int size;
/**
* index of synchronization event within trigger_shape_s
* See findTriggerZeroEventIndex()
@@ -120,20 +83,25 @@ private:
/**
* Values are in the 0..1 range
*/
- float switchTimes[PWM_PHASE_MAX_COUNT];
+ float switchTimesBuffer[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 getSwitchAngle(int index) const;
float previousAngle;
/**
* this is part of performance optimization
*/
operation_mode_e operationMode;
+
+ /**
+ * This private method should only be used to prepare the array of pre-calculated values
+ * See eventAngles array
+ */
+ float getAngle(int phaseIndex) const;
+
+ int getCycleDuration() const;
};
void setTriggerSynchronizationGap(trigger_shape_s *s, float synchGap);
diff --git a/firmware/emulation/analog_chart.c b/firmware/emulation/analog_chart.c
index ed832a1aaa..1ed2ee9f7e 100644
--- a/firmware/emulation/analog_chart.c
+++ b/firmware/emulation/analog_chart.c
@@ -11,7 +11,7 @@
#include "status_loop.h"
#include "engine_configuration.h"
-#if EFI_ANALOG_CHART
+#if EFI_ANALOG_CHART || defined(__DOXYGEN__)
static char LOGGING_BUFFER[5000];
static Logging logging;
@@ -22,8 +22,9 @@ static int initialized = FALSE;
extern engine_configuration_s *engineConfiguration;
void acAddData(float angle, float value) {
- if (!initialized)
+ if (!initialized) {
return; // this is possible because of initialization sequence
+ }
if( engineConfiguration->analogChartFrequency < 1) {
//todofirmwareError()
@@ -35,8 +36,9 @@ void acAddData(float angle, float value) {
// message terminator
appendPrintf(&logging, DELIMETER);
// output pending data
- if (getFullLog())
+ if (getFullLog()) {
scheduleLogging(&logging);
+ }
pendingData = FALSE;
}
return;
@@ -48,8 +50,9 @@ void acAddData(float angle, float value) {
appendPrintf(&logging, "analog_chart%s", DELIMETER);
}
- if (remainingSize(&logging) > 100)
+ if (remainingSize(&logging) > 100) {
appendPrintf(&logging, "%f|%f|", angle, value);
+ }
}
void initAnalogChart(void) {
diff --git a/firmware/emulation/emulation.mk b/firmware/emulation/emulation.mk
index cde4721375..e4b45bf177 100644
--- a/firmware/emulation/emulation.mk
+++ b/firmware/emulation/emulation.mk
@@ -2,10 +2,10 @@
EMULATIONSRC = emulation/hw_layer/poten.c \
emulation/analog_chart.c \
emulation/test/test.c \
- emulation/test/testbmk.c \
- emulation/wave_analyzer.c
+ emulation/test/testbmk.c
EMULATIONSRC_CPP = emulation/trigger_emulator.cpp \
emulation/rfi_perftest.cpp \
- emulation/engine_emulator.cpp
+ emulation/engine_emulator.cpp \
+ emulation/wave_analyzer.cpp
diff --git a/firmware/emulation/hw_layer/poten.c b/firmware/emulation/hw_layer/poten.c
index a443e3ee71..924af0091f 100644
--- a/firmware/emulation/hw_layer/poten.c
+++ b/firmware/emulation/hw_layer/poten.c
@@ -38,16 +38,19 @@
SPIDriver * getDigiralPotDevice(spi_device_e spiDevice) {
#if STM32_SPI_USE_SPI1 || defined(__DOXYGEN__)
- if (spiDevice == SPI_DEVICE_1)
+ if (spiDevice == SPI_DEVICE_1) {
return &SPID1;
+ }
#endif
#if STM32_SPI_USE_SPI2 || defined(__DOXYGEN__)
- if (spiDevic e== SPI_DEVICE_2)
+ if (spiDevic e== SPI_DEVICE_2) {
return &SPID2;
+ }
#endif
#if STM32_SPI_USE_SPI3 || defined(__DOXYGEN__)
- if (spiDevice == SPI_DEVICE_3)
+ if (spiDevice == SPI_DEVICE_3) {
return &SPID3;
+ }
#endif
firmwareError("Unexpected SPI device: %d", spiDevice);
return NULL;
@@ -58,7 +61,7 @@ SPIDriver * getDigiralPotDevice(spi_device_e spiDevice) {
static Logging logger;
-#if EFI_POTENTIOMETER
+#if EFI_POTENTIOMETER || defined(__DOXYGEN__)
Mcp42010Driver config[DIGIPOT_COUNT];
void initPotentiometer(Mcp42010Driver *driver, SPIDriver *spi, ioportid_t port, ioportmask_t pin) {
@@ -102,12 +105,8 @@ void setPotResistance(Mcp42010Driver *driver, int channel, int resistance) {
sendToPot(driver, channel, value);
}
-static void setPotResistance0(int value) {
- setPotResistance(&config[0], 0, value);
-}
-
-static void setPotResistance1(int value) {
- setPotResistance(&config[0], 1, value);
+static void setPotResistanceCommand(int index, int value) {
+ setPotResistance(&config[index / 2], index % 2, value);
}
static void setPotValue1(int value) {
@@ -127,20 +126,20 @@ void initPotentiometers(board_configuration_s *boardConfiguration) {
for (int i = 0; i < DIGIPOT_COUNT; i++) {
brain_pin_e csPin = boardConfiguration->digitalPotentiometerChipSelect[i];
- if (csPin == GPIO_NONE)
+ if (csPin == GPIO_NONE) {
continue;
+ }
initPotentiometer(&config[i], getDigiralPotDevice(boardConfiguration->digitalPotentiometerSpiDevice),
getHwPort(csPin), getHwPin(csPin));
}
- addConsoleActionI("pot0", setPotResistance0);
- addConsoleActionI("pot1", setPotResistance1);
+ addConsoleActionII("pot", setPotResistanceCommand);
addConsoleActionI("potd1", setPotValue1);
- setPotResistance0(3000);
- setPotResistance1(7000);
+ setPotResistance(&config[0], 0, 3000);
+ setPotResistance(&config[0], 1, 7000);
#else
print("digiPot logic disabled\r\n");
#endif
diff --git a/firmware/emulation/rfi_perftest.cpp b/firmware/emulation/rfi_perftest.cpp
index 0bd8eebb9b..66ec25636d 100644
--- a/firmware/emulation/rfi_perftest.cpp
+++ b/firmware/emulation/rfi_perftest.cpp
@@ -18,7 +18,7 @@
#include "console_io.h"
#include "engine.h"
-#if EFI_PERF_METRICS
+#if EFI_PERF_METRICS || defined(__DOXYGEN__)
static Logging logger;
diff --git a/firmware/emulation/trigger_emulator.cpp b/firmware/emulation/trigger_emulator.cpp
index a9defd2a42..1a4b1bf25f 100644
--- a/firmware/emulation/trigger_emulator.cpp
+++ b/firmware/emulation/trigger_emulator.cpp
@@ -1,5 +1,5 @@
/**
- * @file trigger_emulator.c
+ * @file trigger_emulator.cpp
* @brief Position sensor(s) emulation code
*
* This file is mostly about initialization, the configuration is
@@ -14,30 +14,81 @@
#include "main_trigger_callback.h"
#include "datalogging.h"
#include "engine_configuration.h"
+#if EFI_PROD_CODE
#include "pwm_generator.h"
-#include "io_pins.h"
#include "pin_repository.h"
+#endif
+#include "io_pins.h"
#include "trigger_emulator_algo.h"
+#include "trigger_central.h"
extern engine_configuration_s *engineConfiguration;
extern board_configuration_s *boardConfiguration;
extern PwmConfig triggerSignal;
+TriggerEmulatorHelper::TriggerEmulatorHelper() {
+ primaryWheelState = false;
+ secondaryWheelState = false;
+ thirdWheelState = false;
+}
+
+void TriggerEmulatorHelper::handleEmulatorCallback(PwmConfig *state, int stateIndex) {
+ int newPrimaryWheelState = state->multiWave.waves[0].pinStates[stateIndex];
+ int newSecondaryWheelState = state->multiWave.waves[1].pinStates[stateIndex];
+ int new3rdWheelState = state->multiWave.waves[2].pinStates[stateIndex];
+
+ if (primaryWheelState != newPrimaryWheelState) {
+ primaryWheelState = newPrimaryWheelState;
+ hwHandleShaftSignal(primaryWheelState ? SHAFT_PRIMARY_UP : SHAFT_PRIMARY_DOWN);
+ }
+
+ if (secondaryWheelState != newSecondaryWheelState) {
+ secondaryWheelState = newSecondaryWheelState;
+ hwHandleShaftSignal(secondaryWheelState ? SHAFT_SECONDARY_UP : SHAFT_SECONDARY_DOWN);
+ }
+
+ if (thirdWheelState != new3rdWheelState) {
+ thirdWheelState = new3rdWheelState;
+ hwHandleShaftSignal(thirdWheelState ? SHAFT_3RD_UP : SHAFT_3RD_DOWN);
+ }
+
+ // print("hello %d\r\n", chTimeNow());
+}
+
+static TriggerEmulatorHelper helper;
+
+#if EFI_EMULATE_POSITION_SENSORS || defined(__DOXYGEN__)
+
+static void emulatorApplyPinState(PwmConfig *state, int stateIndex) {
+ if (engineConfiguration->directSelfStimulation) {
+ helper.handleEmulatorCallback(state, stateIndex);
+ }
+
+ applyPinState(state, stateIndex);
+}
+#endif /* EFI_EMULATE_POSITION_SENSORS */
+
void initTriggerEmulator(void) {
-#if EFI_EMULATE_POSITION_SENSORS
+#if EFI_EMULATE_POSITION_SENSORS || defined(__DOXYGEN__)
print("Emulating %s\r\n", getConfigurationName(engineConfiguration));
triggerSignal.outputPins[0] = TRIGGER_EMULATOR_PRIMARY;
triggerSignal.outputPins[1] = TRIGGER_EMULATOR_SECONDARY;
+ triggerSignal.outputPins[2] = TRIGGER_EMULATOR_3RD;
+ // todo: refactor, make this a loop
outputPinRegisterExt2("distributor ch1", triggerSignal.outputPins[0], boardConfiguration->triggerSimulatorPins[0],
&boardConfiguration->triggerSimulatorPinModes[0]);
outputPinRegisterExt2("distributor ch2", triggerSignal.outputPins[1], boardConfiguration->triggerSimulatorPins[1],
&boardConfiguration->triggerSimulatorPinModes[1]);
- initTriggerEmulatorLogic(applyPinState);
+ outputPinRegisterExt2("distributor ch3", triggerSignal.outputPins[2], boardConfiguration->triggerSimulatorPins[2],
+ &boardConfiguration->triggerSimulatorPinModes[2]);
+
+
+ initTriggerEmulatorLogic(emulatorApplyPinState);
#else
print("No position sensor(s) emulation\r\n");
#endif /* EFI_EMULATE_POSITION_SENSORS */
diff --git a/firmware/emulation/trigger_emulator.h b/firmware/emulation/trigger_emulator.h
index c687cdb7cc..1930691c0c 100644
--- a/firmware/emulation/trigger_emulator.h
+++ b/firmware/emulation/trigger_emulator.h
@@ -10,23 +10,25 @@
#define DIST_EMULATOR_H_
#include "main.h"
-#include "wave_math.h"
#include "trigger_structure.h"
#include "engine_configuration.h"
+#include "pwm_generator_logic.h"
-#ifdef __cplusplus
-extern "C"
-{
-#endif /* __cplusplus */
+class TriggerEmulatorHelper {
+public:
+ bool primaryWheelState;
+ bool secondaryWheelState;
+ bool thirdWheelState;
+
+ TriggerEmulatorHelper();
+
+ void handleEmulatorCallback(PwmConfig *state, int stateIndex);
+
+};
void initTriggerEmulator(void);
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
void setTriggerEmulatorRPM(int value);
-
#endif /* DIST_EMULATOR_H_ */
diff --git a/firmware/emulation/wave_analyzer.c b/firmware/emulation/wave_analyzer.cpp
similarity index 76%
rename from firmware/emulation/wave_analyzer.c
rename to firmware/emulation/wave_analyzer.cpp
index b2d0e18a31..a1c35998f5 100644
--- a/firmware/emulation/wave_analyzer.c
+++ b/firmware/emulation/wave_analyzer.cpp
@@ -1,256 +1,262 @@
-/**
- * @file wave_analyzer.c
- * @brief Initialization of Input Capture pins used for dev console sniffer
- *
- * This file is responsible for sniffing of external digital signals and registering
- * these digital events in WaveChart used by the Sniffer tab of Dev Console.
- *
- *
- * @date Jan 7, 2013
- * @author Andrey Belomutskiy, (c) 2012-2014
- */
-
-#include "main.h"
-#include "wave_analyzer.h"
-#include "eficonsole.h"
-#include "data_buffer.h"
-#include "pin_repository.h"
-#include "engine_state.h"
-#include "signal_executor.h"
-#include "engine_configuration.h"
-#include "trigger_central.h"
-#include "rfiutil.h"
-
-
-#define CHART_RESET_DELAY 1
-
-extern board_configuration_s *boardConfiguration;
-
-extern engine_configuration_s *engineConfiguration;
-
-static volatile uint32_t ckpPeriodUs; // difference between current crank signal and previous crank signal
-static volatile uint64_t previousCrankSignalStart = 0;
-
-#define MAX_ICU_COUNT 5
-
-static int waveReaderCount = 0;
-static WaveReader readers[MAX_ICU_COUNT];
-extern WaveChart waveChart;
-
-static Logging logger;
-
-static void ensureInitialized(WaveReader *reader) {
- efiAssertVoid(reader->hw.started, "wave analyzer NOT INITIALIZED");
-}
-
-#ifdef EFI_WAVE_ANALYZER
-
-static void waAnaWidthCallback(WaveReader *reader) {
- uint64_t nowUs = getTimeNowUs();
- reader->eventCounter++;
- reader->lastActivityTimeUs = nowUs;
- addWaveChartEvent(reader->name, WC_UP, "");
-
- uint64_t width = nowUs - reader->periodEventTimeUs;
- reader->last_wave_low_widthUs = width;
-
- reader->signalPeriodUs = nowUs - reader->widthEventTimeUs;
- reader->widthEventTimeUs = nowUs;
-}
-
-static void waIcuPeriodCallback(WaveReader *reader) {
- uint64_t nowUs = getTimeNowUs();
- reader->eventCounter++;
- reader->lastActivityTimeUs = nowUs;
- addWaveChartEvent(reader->name, WC_DOWN, "");
-
- uint64_t width = nowUs - reader->widthEventTimeUs;
- reader->last_wave_high_widthUs = width;
-
- reader->periodEventTimeUs = nowUs;
-
- //scheduleSimpleMsg(&irqLogging, "co", reader->chart.counter);
-
-// dbAdd(&wavePeriodTime, now);
-
- int period = ckpPeriodUs; // local copy of volatile variable
-
- uint64_t offset = nowUs - previousCrankSignalStart;
-
- if (offset > period / 2) {
- /**
- * here we calculate the offset in relation to future cranking signal
- */
- offset -= period;
- }
- reader->waveOffsetUs = offset;
-
- // we want only the low phase length, so we subsctract high width from period
-// processSignal(1, &dataPinReader, last_period - last_adc_response_width);
-}
-
-static void setWaveModeSilent(int index, int mode) {
- WaveReader *reader = &readers[index];
-
- setWaveReaderMode(&reader->hw, mode);
-}
-
-void setWaveMode(int index, int mode) {
- setWaveModeSilent(index, mode);
- print("wavemode%d:%d\r\n", index, mode);
-}
-
-int getWaveMode(int index) {
- WaveReader *reader = &readers[index];
- ensureInitialized(reader);
- return reader->hw.activeMode;
-}
-
-int getEventCounter(int index) {
- WaveReader *reader = &readers[index];
- ensureInitialized(reader);
- return reader->eventCounter;
-}
-
-static void initWave(char *name, int index, ICUDriver *driver, ioportid_t port, int pin, int mode) {
- waveReaderCount++;
- efiAssertVoid(index < MAX_ICU_COUNT, "too many ICUs");
- WaveReader *reader = &readers[index];
- WaveReaderHw *hw = &reader->hw;
-
- reader->name = name;
-
- registerCallback(&hw->widthListeners, (IntListener) waAnaWidthCallback, reader);
-
- registerCallback(&hw->periodListeners, (IntListener) waIcuPeriodCallback, reader);
-
- initWaveAnalyzerDriver(hw, driver, port, pin);
-
- print("wave%d input on %s%d\r\n", index, portname(reader->hw.port), reader->hw.pin);
- setWaveReaderMode(hw, mode);
-}
-#endif
-
-//int getCrankStart() {
-// return previousCrankSignalStart;
-//}
-
-//static int getCrankPeriod(void) {
-// return ckpPeriod;
-//}
-
-static void onWaveShaftSignal(trigger_event_e ckpSignalType, int index, void *arg) {
- if (index != 0)
- return;
- uint64_t nowUs = getTimeNowUs();
- ckpPeriodUs = nowUs - previousCrankSignalStart;
- previousCrankSignalStart = nowUs;
-}
-
-static THD_WORKING_AREA(waThreadStack, UTILITY_THREAD_STACK_SIZE);
-
-//static Logging logger;
-
-static msg_t waThread(void *arg) {
- chRegSetThreadName("Wave Analyzer");
-#if EFI_WAVE_CHART
- while (TRUE) {
- chThdSleepSeconds(CHART_RESET_DELAY);
-
- publishChartIfFull(&waveChart);
- }
-#endif /* EFI_WAVE_CHART */
-#if defined __GNUC__
- return -1;
-#endif
-}
-
-int getWaveLowWidth(int index) {
- WaveReader *reader = &readers[index];
- ensureInitialized(reader);
- return reader->last_wave_low_widthUs;
-}
-
-float getWaveHighWidthMs(int index) {
- WaveReader *reader = &readers[index];
- ensureInitialized(reader);
- if (getTimeNowUs() - reader->lastActivityTimeUs > 4 * US_PER_SECOND)
- return 0; // dwell time has expired
- return reader->last_wave_high_widthUs / 1000.0;
-}
-
-uint64_t getWaveOffset(int index) {
- WaveReader *reader = &readers[index];
- ensureInitialized(reader);
- return reader->waveOffsetUs;
-}
-
-float getSignalPeriodMs(int index) {
- WaveReader *reader = &readers[index];
- ensureInitialized(reader);
- return reader->signalPeriodUs / 1000.0;
-}
-
-int getWidthEventTime(int index) {
- WaveReader *reader = &readers[index];
- ensureInitialized(reader);
- return reader->widthEventTimeUs;
-}
-
-uint64_t getPeriodEventTime(int index) {
- WaveReader *reader = &readers[index];
- ensureInitialized(reader);
- return reader->periodEventTimeUs;
-}
-
-int waveBufferReported = 0;
-
-static void reportWave(Logging *logging, int index) {
-// int counter = getEventCounter(index);
-// debugInt2(logging, "ev", index, counter);
-
- float dwellMs = getWaveHighWidthMs(index);
- float periodMs = getSignalPeriodMs(index);
-
- appendPrintf(logging, "duty%d%s", index, DELIMETER);
- appendFloat(logging, 100.0 * dwellMs / periodMs, 2);
- appendPrintf(logging, "%s", DELIMETER);
-
- appendPrintf(logging, "dwell%d%s", index, DELIMETER);
- appendFloat(logging, dwellMs, 2);
- appendPrintf(logging, "%s", DELIMETER);
-
- appendPrintf(logging, "period%d%s", index, DELIMETER);
- appendFloat(logging, periodMs, 2);
- appendPrintf(logging, "%s", DELIMETER);
-
-// int crank = getCrankPeriod();
-
-// int offset = getWaveOffset(index);
-// debugFloat2(logging, "advance", index, 90.0 * offset / crank, 3);
-// debugInt2(logging, "offset", index, offset);
-}
-
-void printWave(Logging *logging) {
- reportWave(logging, 0);
- reportWave(logging, 1);
-}
-
-void initWaveAnalyzer(void) {
-#ifdef EFI_WAVE_ANALYZER
- initLogging(&logger, "wave");
-
- initWave("input1 A8", 0, getInputCaptureDriver(boardConfiguration->primaryLogicAnalyzerPin), getHwPort(boardConfiguration->primaryLogicAnalyzerPin), getHwPin(boardConfiguration->primaryLogicAnalyzerPin), 1);
- initWave("input2 E5", 1, getInputCaptureDriver(boardConfiguration->secondaryLogicAnalyzerPin), getHwPort(boardConfiguration->secondaryLogicAnalyzerPin), getHwPin(boardConfiguration->secondaryLogicAnalyzerPin), 1);
- // initWave("input0 C6", 2, &WAVE_TIMER, WAVE_INPUT_PORT, WAVE_INPUT_PIN, 0);
-
- addTriggerEventListener(&onWaveShaftSignal, "wave analyzer", NULL);
-
- addConsoleActionII("wm", setWaveModeSilent);
-
- chThdCreateStatic(waThreadStack, sizeof(waThreadStack), NORMALPRIO, waThread, NULL);
-
-#else
- print("wave disabled\r\n");
-#endif
-}
+/**
+ * @file wave_analyzer.cpp
+ * @brief Initialization of Input Capture pins used for dev console sniffer
+ *
+ * This file is responsible for sniffing of external digital signals and registering
+ * these digital events in WaveChart used by the Sniffer tab of Dev Console.
+ *
+ *
+ * @date Jan 7, 2013
+ * @author Andrey Belomutskiy, (c) 2012-2014
+ */
+
+#include "main.h"
+#include "wave_analyzer.h"
+#include "eficonsole.h"
+#include "data_buffer.h"
+#include "pin_repository.h"
+#include "engine_state.h"
+#include "signal_executor.h"
+#include "engine_configuration.h"
+#include "trigger_central.h"
+#include "rfiutil.h"
+#include "engine_math.h"
+#include "engine.h"
+
+extern Engine engine;
+
+#define CHART_RESET_DELAY 1
+
+extern board_configuration_s *boardConfiguration;
+
+extern engine_configuration_s *engineConfiguration;
+
+static volatile uint32_t ckpPeriodUs; // difference between current crank signal and previous crank signal
+static volatile uint64_t previousCrankSignalStart = 0;
+
+#define MAX_ICU_COUNT 5
+
+static int waveReaderCount = 0;
+static WaveReader readers[MAX_ICU_COUNT];
+extern WaveChart waveChart;
+
+static Logging logger;
+
+static void ensureInitialized(WaveReader *reader) {
+ efiAssertVoid(reader->hw.started, "wave analyzer NOT INITIALIZED");
+}
+
+#if EFI_WAVE_ANALYZER || defined(__DOXYGEN__)
+
+static void waAnaWidthCallback(WaveReader *reader) {
+ uint64_t nowUs = getTimeNowUs();
+ reader->eventCounter++;
+ reader->lastActivityTimeUs = nowUs;
+ addWaveChartEvent(reader->name, WC_UP, "");
+
+ uint32_t width = nowUs - reader->periodEventTimeUs;
+ reader->last_wave_low_widthUs = width;
+
+ reader->signalPeriodUs = nowUs - reader->widthEventTimeUs;
+ reader->widthEventTimeUs = nowUs;
+}
+
+static void waIcuPeriodCallback(WaveReader *reader) {
+ uint64_t nowUs = getTimeNowUs();
+ reader->eventCounter++;
+ reader->lastActivityTimeUs = nowUs;
+ addWaveChartEvent(reader->name, WC_DOWN, "");
+
+ uint64_t width = nowUs - reader->widthEventTimeUs;
+ reader->last_wave_high_widthUs = width;
+
+ reader->periodEventTimeUs = nowUs;
+
+ //scheduleSimpleMsg(&irqLogging, "co", reader->chart.counter);
+
+// dbAdd(&wavePeriodTime, now);
+
+ uint32_t period = ckpPeriodUs; // local copy of volatile variable
+
+ uint32_t offset = nowUs - previousCrankSignalStart;
+
+ if (offset > period / 2) {
+ /**
+ * here we calculate the offset in relation to future cranking signal
+ */
+ offset -= period;
+ }
+ reader->waveOffsetUs = offset;
+
+ // we want only the low phase length, so we subsctract high width from period
+// processSignal(1, &dataPinReader, last_period - last_adc_response_width);
+}
+
+static void setWaveModeSilent(int index, int mode) {
+ WaveReader *reader = &readers[index];
+
+ setWaveReaderMode(&reader->hw, mode);
+}
+
+//void setWaveMode(int index, int mode) {
+// setWaveModeSilent(index, mode);
+// print("wavemode%d:%d\r\n", index, mode);
+//}
+
+int getWaveMode(int index) {
+ WaveReader *reader = &readers[index];
+ ensureInitialized(reader);
+ return reader->hw.activeMode;
+}
+
+int getEventCounter(int index) {
+ WaveReader *reader = &readers[index];
+ ensureInitialized(reader);
+ return reader->eventCounter;
+}
+
+static void initWave(const char *name, int index, ICUDriver *driver, ioportid_t port, ioportmask_t pin, int mode) {
+ waveReaderCount++;
+ efiAssertVoid(index < MAX_ICU_COUNT, "too many ICUs");
+ WaveReader *reader = &readers[index];
+ WaveReaderHw *hw = &reader->hw;
+
+ reader->name = name;
+
+ registerCallback(&hw->widthListeners, (IntListener) waAnaWidthCallback, (void*)reader);
+
+ registerCallback(&hw->periodListeners, (IntListener) waIcuPeriodCallback, (void*)reader);
+
+ initWaveAnalyzerDriver(hw, driver, port, pin);
+
+ print("wave%d input on %s%d\r\n", index, portname(reader->hw.port), reader->hw.pin);
+ setWaveReaderMode(hw, mode);
+}
+#endif
+
+//int getCrankStart() {
+// return previousCrankSignalStart;
+//}
+
+//static int getCrankPeriod(void) {
+// return ckpPeriod;
+//}
+
+static void onWaveShaftSignal(trigger_event_e ckpSignalType, int index, void *arg) {
+ if (index != 0) {
+ return;
+ }
+ uint64_t nowUs = getTimeNowUs();
+ ckpPeriodUs = nowUs - previousCrankSignalStart;
+ previousCrankSignalStart = nowUs;
+}
+
+static THD_WORKING_AREA(waThreadStack, UTILITY_THREAD_STACK_SIZE);
+
+//static Logging logger;
+
+static msg_t waThread(void *arg) {
+ chRegSetThreadName("Wave Analyzer");
+#if EFI_WAVE_CHART
+ while (TRUE) {
+ chThdSleepSeconds(CHART_RESET_DELAY);
+
+ publishChartIfFull(&waveChart);
+ }
+#endif /* EFI_WAVE_CHART */
+#if defined __GNUC__
+ return -1;
+#endif
+}
+
+uint32_t getWaveLowWidth(int index) {
+ WaveReader *reader = &readers[index];
+ ensureInitialized(reader);
+ return reader->last_wave_low_widthUs;
+}
+
+float getWaveHighWidthMs(int index) {
+ WaveReader *reader = &readers[index];
+ ensureInitialized(reader);
+ if (getTimeNowUs() - reader->lastActivityTimeUs > 4 * US_PER_SECOND) {
+ return 0.0f; // dwell time has expired
+ }
+ return reader->last_wave_high_widthUs / 1000.0f;
+}
+
+uint64_t getWaveOffset(int index) {
+ WaveReader *reader = &readers[index];
+ ensureInitialized(reader);
+ return reader->waveOffsetUs;
+}
+
+float getSignalPeriodMs(int index) {
+ WaveReader *reader = &readers[index];
+ ensureInitialized(reader);
+ return reader->signalPeriodUs / 1000.0f;
+}
+
+uint64_t getWidthEventTime(int index) {
+ WaveReader *reader = &readers[index];
+ ensureInitialized(reader);
+ return reader->widthEventTimeUs;
+}
+
+uint64_t getPeriodEventTime(int index) {
+ WaveReader *reader = &readers[index];
+ ensureInitialized(reader);
+ return reader->periodEventTimeUs;
+}
+
+int waveBufferReported = 0;
+
+static void reportWave(Logging *logging, int index) {
+// int counter = getEventCounter(index);
+// debugInt2(logging, "ev", index, counter);
+
+ float dwellMs = getWaveHighWidthMs(index);
+ float periodMs = getSignalPeriodMs(index);
+
+ appendPrintf(logging, "duty%d%s", index, DELIMETER);
+ appendFloat(logging, 100.0f * dwellMs / periodMs, 2);
+ appendPrintf(logging, "%s", DELIMETER);
+
+ appendPrintf(logging, "dwell%d%s", index, DELIMETER);
+ appendFloat(logging, dwellMs, 2);
+ appendPrintf(logging, "%s", DELIMETER);
+
+ appendPrintf(logging, "period%d%s", index, DELIMETER);
+ appendFloat(logging, periodMs, 2);
+ appendPrintf(logging, "%s", DELIMETER);
+
+ int offset = getWaveOffset(index);
+ int crank = getOneDegreeTimeMs(getRpm()) * 360;
+
+ appendPrintf(logging, "advance%d%s", index, DELIMETER);
+ appendFloat(logging, 90.0 * offset / crank, 3);
+ appendPrintf(logging, "%s", DELIMETER);
+}
+
+void printWave(Logging *logging) {
+ reportWave(logging, 0);
+ reportWave(logging, 1);
+}
+
+void initWaveAnalyzer(void) {
+#if EFI_WAVE_ANALYZER || defined(__DOXYGEN__)
+ initLogging(&logger, "wave");
+
+ initWave(WA_CHANNEL_1, 0, getInputCaptureDriver(boardConfiguration->logicAnalyzerPins[0]), getHwPort(boardConfiguration->logicAnalyzerPins[0]), getHwPin(boardConfiguration->logicAnalyzerPins[0]), 1);
+ initWave(WA_CHANNEL_2, 1, getInputCaptureDriver(boardConfiguration->logicAnalyzerPins[1]), getHwPort(boardConfiguration->logicAnalyzerPins[1]), getHwPin(boardConfiguration->logicAnalyzerPins[1]), 1);
+ // initWave("input0 C6", 2, &WAVE_TIMER, WAVE_INPUT_PORT, WAVE_INPUT_PIN, 0);
+
+ addTriggerEventListener(&onWaveShaftSignal, "wave analyzer", (void*)NULL);
+
+ addConsoleActionII("wm", setWaveModeSilent);
+
+ chThdCreateStatic(waThreadStack, sizeof(waThreadStack), NORMALPRIO, waThread, (void*)NULL);
+
+#else
+ print("wave disabled\r\n");
+#endif
+}
diff --git a/firmware/emulation/wave_analyzer.h b/firmware/emulation/wave_analyzer.h
index 8fc32bd085..e7f7783bb4 100644
--- a/firmware/emulation/wave_analyzer.h
+++ b/firmware/emulation/wave_analyzer.h
@@ -15,19 +15,22 @@
#include "wave_analyzer_hw.h"
#include "wave_chart.h"
+#define WA_CHANNEL_1 "input1"
+#define WA_CHANNEL_2 "input2"
+
typedef struct {
WaveReaderHw hw;
- char *name;
+ const char *name;
volatile int eventCounter;
volatile uint64_t lastActivityTimeUs; // timestamp in microseconds ticks
volatile uint64_t periodEventTimeUs; // time of signal fall in microseconds
volatile uint64_t widthEventTimeUs; // time of signal rise in microseconds
- volatile uint64_t signalPeriodUs; // period between two signal rises in microseconds
+ volatile uint32_t signalPeriodUs; // period between two signal rises in microseconds
volatile uint64_t waveOffsetUs; // offset from CKP signal in systimer ticks
- volatile uint64_t last_wave_low_widthUs; // time period in systimer ticks
+ volatile uint32_t last_wave_low_widthUs; // time period in systimer ticks
volatile uint64_t last_wave_high_widthUs; // time period in systimer ticks
} WaveReader;
@@ -39,7 +42,7 @@ extern "C"
void initWaveAnalyzer(void);
void pokeWaveInfo(void);
void reportWaveInfo(void);
-int getWaveLowWidth(int index);
+uint32_t getWaveLowWidth(int index);
float getWaveHighWidthMs(int index);
uint64_t getWaveOffset(int index);
@@ -48,7 +51,7 @@ int getWaveMode(int index);
int getEventCounter(int index);
float getSignalPeriodMs(int index);
-int getWidthEventTime(int index);
+uint64_t getWidthEventTime(int index);
uint64_t getPeriodEventTime(int index);
//int getCrankStart();
diff --git a/firmware/global.h b/firmware/global.h
index c32c258924..e99c4a116b 100644
--- a/firmware/global.h
+++ b/firmware/global.h
@@ -10,9 +10,15 @@
#include
#include
-#include
#include
+// this is about MISRA not liking 'time.h'. todo: figure out something
+#if defined __GNUC__
+#include
+#else
+typedef unsigned int time_t;
+#endif
+
#include "efifeatures.h"
#include "rusefi_enums.h"
#include "obd_error_codes.h"
@@ -27,6 +33,8 @@
// see also PORT_INT_REQUIRED_STACK
#define UTILITY_THREAD_STACK_SIZE 128
+#define EFI_ERROR_CODE 0xffffffff
+
#if EFI_USE_CCM && defined __GNUC__
#define CCM_OPTIONAL __attribute__((section(".ccm")));
#else
diff --git a/firmware/hw_layer/AdcConfiguration.h b/firmware/hw_layer/AdcConfiguration.h
index 39fdebcfa5..b0a1848b35 100644
--- a/firmware/hw_layer/AdcConfiguration.h
+++ b/firmware/hw_layer/AdcConfiguration.h
@@ -10,13 +10,17 @@
class AdcConfiguration {
public:
AdcConfiguration(ADCConversionGroup* hwConfig);
- void addChannel(int hwChannelIndex);
- int getAdcHardwareIndexByInternalIndex(int index);
+ void addChannel(adc_channel_e hwChannelIndex);
+ adc_channel_e getAdcHardwareIndexByInternalIndex(int index);
int internalAdcIndexByHardwareIndex[20];
+ bool isHwUsed(adc_channel_e hwChannel);
int size();
void init(void);
int conversionCount;
int errorsCount;
+ int getAdcValueByIndex(int internalIndex);
+
+ adc_state values;
private:
ADCConversionGroup* hwConfig;
/**
@@ -24,7 +28,7 @@ private:
*/
int channelCount;
- int hardwareIndexByIndernalAdcIndex[20];
+ adc_channel_e hardwareIndexByIndernalAdcIndex[20];
};
diff --git a/firmware/hw_layer/adc_inputs.cpp b/firmware/hw_layer/adc_inputs.cpp
index b8a95ac414..d853fa45a8 100644
--- a/firmware/hw_layer/adc_inputs.cpp
+++ b/firmware/hw_layer/adc_inputs.cpp
@@ -26,6 +26,7 @@ AdcConfiguration::AdcConfiguration(ADCConversionGroup* hwConfig) {
hwConfig->sqr1 = 0;
hwConfig->sqr2 = 0;
hwConfig->sqr3 = 0;
+ memset(internalAdcIndexByHardwareIndex, 0xFFFFFFFF, sizeof(internalAdcIndexByHardwareIndex));
}
#define ADC_GRP1_BUF_DEPTH_FAST 1
@@ -80,8 +81,6 @@ static adcsample_t getAvgAdcValue(int index, adcsample_t *samples, int bufDepth,
return result / bufDepth;
}
-static adc_state newState;
-
static void adc_callback_slow(ADCDriver *adcp, adcsample_t *buffer, size_t n);
static void adc_callback_fast(ADCDriver *adcp, adcsample_t *buffer, size_t n);
@@ -147,7 +146,7 @@ ADC_TwoSamplingDelay_5Cycles, // cr1
// Conversion group sequence 1...6
};
-static AdcConfiguration fastAdc(&adcgrpcfg_fast);
+AdcConfiguration fastAdc(&adcgrpcfg_fast);
static void pwmpcb_slow(PWMDriver *pwmp) {
#if EFI_INTERNAL_ADC
@@ -202,36 +201,71 @@ static void pwmpcb_fast(PWMDriver *pwmp) {
#endif
}
-int getAdcValueByIndex(int internalIndex) {
- return newState.adc_data[internalIndex];
-}
-
-int getInternalAdcValue(int hwChannel) {
+int getInternalAdcValue(adc_channel_e hwChannel) {
if (boardConfiguration->adcHwChannelEnabled[hwChannel] == ADC_FAST)
return fastAdcValue;
int internalIndex = slowAdc.internalAdcIndexByHardwareIndex[hwChannel];
- return getAdcValueByIndex(internalIndex);
+ return slowAdc.getAdcValueByIndex(internalIndex);
}
static PWMConfig pwmcfg_slow = { PWM_FREQ_SLOW, PWM_PERIOD_SLOW, pwmpcb_slow, { {
PWM_OUTPUT_DISABLED, NULL }, { PWM_OUTPUT_DISABLED, NULL }, {
PWM_OUTPUT_DISABLED, NULL }, { PWM_OUTPUT_DISABLED, NULL } },
/* HW dependent part.*/
-0 };
+0, 0 };
static PWMConfig pwmcfg_fast = { PWM_FREQ_FAST, PWM_PERIOD_FAST, pwmpcb_fast, { {
PWM_OUTPUT_DISABLED, NULL }, { PWM_OUTPUT_DISABLED, NULL }, {
PWM_OUTPUT_DISABLED, NULL }, { PWM_OUTPUT_DISABLED, NULL } },
/* HW dependent part.*/
-0 };
+0, 0 };
static void initAdcPin(ioportid_t port, int pin, const char *msg) {
print("adc %s\r\n", msg);
mySetPadMode("adc input", port, pin, PAL_MODE_INPUT_ANALOG);
}
-GPIO_TypeDef* getAdcChannelPort(int hwChannel) {
+adc_channel_e getAdcChannel(brain_pin_e pin) {
+ switch(pin) {
+ case GPIOA_0:
+ return EFI_ADC_0;
+ case GPIOA_1:
+ return EFI_ADC_1;
+ case GPIOA_2:
+ return EFI_ADC_2;
+ case GPIOA_3:
+ return EFI_ADC_3;
+ case GPIOA_4:
+ return EFI_ADC_4;
+ case GPIOA_5:
+ return EFI_ADC_5;
+ case GPIOA_6:
+ return EFI_ADC_6;
+ case GPIOA_7:
+ return EFI_ADC_7;
+ case GPIOB_0:
+ return EFI_ADC_8;
+ case GPIOB_1:
+ return EFI_ADC_9;
+ case GPIOC_0:
+ return EFI_ADC_10;
+ case GPIOC_1:
+ return EFI_ADC_11;
+ case GPIOC_2:
+ return EFI_ADC_12;
+ case GPIOC_3:
+ return EFI_ADC_13;
+ case GPIOC_4:
+ return EFI_ADC_14;
+ case GPIOC_5:
+ return EFI_ADC_15;
+ default:
+ return EFI_ADC_ERROR;
+ }
+}
+
+GPIO_TypeDef* getAdcChannelPort(adc_channel_e hwChannel) {
// todo: replace this with an array :)
switch (hwChannel) {
case ADC_CHANNEL_IN0:
@@ -272,7 +306,17 @@ GPIO_TypeDef* getAdcChannelPort(int hwChannel) {
}
}
-int getAdcChannelPin(int hwChannel) {
+const char * getAdcMode(adc_channel_e hwChannel) {
+ if (slowAdc.isHwUsed(hwChannel)) {
+ return "slow";
+ }
+ if (fastAdc.isHwUsed(hwChannel)) {
+ return "fast";
+ }
+ return "INACTIVE";
+}
+
+int getAdcChannelPin(adc_channel_e hwChannel) {
// todo: replace this with an array :)
switch (hwChannel) {
case ADC_CHANNEL_IN0:
@@ -313,7 +357,7 @@ int getAdcChannelPin(int hwChannel) {
}
}
-static void initAdcHwChannel(int hwChannel) {
+static void initAdcHwChannel(adc_channel_e hwChannel) {
GPIO_TypeDef* port = getAdcChannelPort(hwChannel);
int pin = getAdcChannelPin(hwChannel);
@@ -324,12 +368,25 @@ int AdcConfiguration::size() {
return channelCount;
}
+int AdcConfiguration::getAdcValueByIndex(int internalIndex) {
+ return values.adc_data[internalIndex];
+}
+
void AdcConfiguration::init(void) {
hwConfig->num_channels = size();
hwConfig->sqr1 += ADC_SQR1_NUM_CH(size());
}
-void AdcConfiguration::addChannel(int hwChannel) {
+bool AdcConfiguration::isHwUsed(adc_channel_e hwChannelIndex) {
+ for (int i = 0; i < channelCount; i++) {
+ if (hardwareIndexByIndernalAdcIndex[i] == hwChannelIndex) {
+ return true;
+ }
+ }
+ return false;
+}
+
+void AdcConfiguration::addChannel(adc_channel_e hwChannel) {
int logicChannel = channelCount++;
internalAdcIndexByHardwareIndex[hwChannel] = logicChannel;
@@ -344,13 +401,13 @@ void AdcConfiguration::addChannel(int hwChannel) {
initAdcHwChannel(hwChannel);
}
-static void printAdcValue(int channel) {
+static void printAdcValue(adc_channel_e channel) {
int value = getAdcValue(channel);
float volts = adcToVoltsDivided(value);
scheduleMsg(&logger, "adc voltage : %f", volts);
}
-int AdcConfiguration::getAdcHardwareIndexByInternalIndex(int index) {
+adc_channel_e AdcConfiguration::getAdcHardwareIndexByInternalIndex(int index) {
return hardwareIndexByIndernalAdcIndex[index];
}
@@ -360,11 +417,11 @@ static void printFullAdcReport(void) {
for (int index = 0; index < slowAdc.size(); index++) {
appendMsgPrefix(&logger);
- int hwIndex = slowAdc.getAdcHardwareIndexByInternalIndex(index);
+ adc_channel_e hwIndex = slowAdc.getAdcHardwareIndexByInternalIndex(index);
GPIO_TypeDef* port = getAdcChannelPort(hwIndex);
int pin = getAdcChannelPin(hwIndex);
- int adcValue = getAdcValueByIndex(index);
+ int adcValue = slowAdc.getAdcValueByIndex(index);
appendPrintf(&logger, " ch%d %s%d", index, portname(port), pin);
appendPrintf(&logger, " ADC%d 12bit=%d", hwIndex, adcValue);
float volts = adcToVolts(adcValue);
@@ -397,7 +454,7 @@ static void adc_callback_slow(ADCDriver *adcp, adcsample_t *buffer, size_t n) {
// newState.time = chimeNow();
for (int i = 0; i < slowAdc.size(); i++) {
int value = getAvgAdcValue(i, slowAdcState.samples, ADC_GRP1_BUF_DEPTH_SLOW, slowAdc.size());
- newState.adc_data[i] = value;
+ slowAdc.values.adc_data[i] = value;
}
}
}
@@ -409,13 +466,16 @@ static void adc_callback_fast(ADCDriver *adcp, adcsample_t *buffer, size_t n) {
// intermediate callback when the buffer is half full.*/
if (adcp->state == ADC_COMPLETE) {
fastAdcValue = getAvgAdcValue(0, samples_fast, ADC_GRP1_BUF_DEPTH_FAST, fastAdc.size());
+
+ fastAdc.values.adc_data[0] = fastAdcValue;
+
#if EFI_MAP_AVERAGING
mapAveragingCallback(fastAdcValue);
#endif /* EFI_MAP_AVERAGING */
}
}
-void initAdcInputs(bool isBoardTestMode) {
+void initAdcInputs(void) {
initLoggingExt(&logger, "ADC", LOGGING_BUFFER, sizeof(LOGGING_BUFFER));
printMsg(&logger, "initAdcInputs()");
@@ -434,22 +494,20 @@ void initAdcInputs(bool isBoardTestMode) {
for (int adc = 0; adc < HW_MAX_ADC_INDEX; adc++) {
adc_channel_mode_e mode = boardConfiguration->adcHwChannelEnabled[adc];
- if (mode == ADC_SLOW || (isBoardTestMode && mode == ADC_FAST)) {
- slowAdc.addChannel(ADC_CHANNEL_IN0 + adc);
+ if (mode == ADC_SLOW) {
+ slowAdc.addChannel((adc_channel_e) (ADC_CHANNEL_IN0 + adc));
} else if (mode == ADC_FAST) {
- fastAdc.addChannel(ADC_CHANNEL_IN0 + adc);
+ fastAdc.addChannel((adc_channel_e) (ADC_CHANNEL_IN0 + adc));
}
}
slowAdc.init();
pwmStart(EFI_INTERNAL_SLOW_ADC_PWM, &pwmcfg_slow);
- if (!isBoardTestMode) {
- fastAdc.init();
+ fastAdc.init();
/*
* Initializes the PWM driver.
*/
pwmStart(EFI_INTERNAL_FAST_ADC_PWM, &pwmcfg_fast);
- }
// ADC_CHANNEL_IN0 // PA0
// ADC_CHANNEL_IN1 // PA1
@@ -470,7 +528,7 @@ void initAdcInputs(bool isBoardTestMode) {
//if(slowAdcChannelCount > ADC_MAX_SLOW_CHANNELS_COUNT) // todo: do we need this logic? do we need this check
- addConsoleActionI("adc", printAdcValue);
+ addConsoleActionI("adc", (VoidInt) printAdcValue);
addConsoleAction("fadc", printFullAdcReport);
#else
printMsg(&logger, "ADC disabled");
diff --git a/firmware/hw_layer/adc_inputs.h b/firmware/hw_layer/adc_inputs.h
index ca76417640..c949f2e8e2 100644
--- a/firmware/hw_layer/adc_inputs.h
+++ b/firmware/hw_layer/adc_inputs.h
@@ -12,24 +12,25 @@
#include "main.h"
#include "adc_math.h"
+const char * getAdcMode(adc_channel_e hwChannel);
+int getAdcChannelPin(adc_channel_e hwChannel);
+void initAdcInputs(void);
+GPIO_TypeDef* getAdcChannelPort(adc_channel_e hwChannel);
+adc_channel_e getAdcChannel(brain_pin_e pin);
+
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
-GPIO_TypeDef* getAdcChannelPort(int hwChannel);
-int getAdcChannelPin(int hwChannel);
-void initAdcInputs(bool isBoardTestMode);
int getAdcHardwareIndexByInternalIndex(int index);
-int getAdcValueByIndex(int internalIndex);
void pokeAdcInputs(void);
-int getInternalAdcValue(int index);
+int getInternalAdcValue(adc_channel_e index);
#ifdef __cplusplus
}
#endif /* __cplusplus */
-
/* Depth of the conversion buffer, channels are sampled X times each.*/
#define ADC_GRP1_BUF_DEPTH_SLOW 1
#define ADC_MAX_CHANNELS_COUNT 16
diff --git a/firmware/hw_layer/board_test.cpp b/firmware/hw_layer/board_test.cpp
index 102a892c3e..113098a2b8 100644
--- a/firmware/hw_layer/board_test.cpp
+++ b/firmware/hw_layer/board_test.cpp
@@ -2,6 +2,8 @@
* @file board_test.cpp
* @brief This is a simple board testing utility
*
+ * By default this is enabled by grounding PB0
+ *
* @date Mar 12, 2014
* @author Andrey Belomutskiy, (c) 2012-2014
*
@@ -29,19 +31,44 @@
static volatile int stepCoutner = 0;
static volatile brain_pin_e currentPin = GPIO_NONE;
-static volatile int currentIndex = 0;
extern AdcConfiguration slowAdc;
+extern AdcConfiguration fastAdc;
-static int isTimeForNextStep(int copy) {
+static bool isTimeForNextStep(int copy) {
return copy != stepCoutner;
}
+static void processAdcPin(AdcConfiguration *adc, int index, const char *prefix) {
+ adc_channel_e hwIndex = adc->getAdcHardwareIndexByInternalIndex(index);
+ GPIO_TypeDef* port = getAdcChannelPort(hwIndex);
+ int pin = getAdcChannelPin(hwIndex);
+
+ int copy = stepCoutner;
+
+ int c = 0;
+
+ while (!isTimeForNextStep(copy)) {
+ print("%s ch%d hwIndex=%d %s%d\r\n", prefix, index, hwIndex, portname(port), pin);
+ int adcValue = adc->getAdcValueByIndex(index);
+
+// print("ADC%d val= %d%s", hwIndex, value, DELIMETER);
+ float volts = adcToVolts(adcValue) * 2;
+ print("v=%f adc=%d c=%d (hit 'n' for next step\r\n", volts, adcValue, c++);
+
+ chThdSleepMilliseconds(300);
+
+ }
+}
+
+static volatile int currentIndex = 0;
+
static void waitForKey(void) {
print("Please hit N to continue\r\n");
int copy = stepCoutner;
- while (!isTimeForNextStep(copy))
+ while (!isTimeForNextStep(copy)) {
chThdSleepMilliseconds(200);
+ }
}
static void nextStep(void) {
@@ -102,12 +129,11 @@ bool isBoardTestMode(void) {
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());
+ print("ADC count: slow %d/fast %d\r\n", slowAdc.size(), fastAdc.size());
if (currentPin != GPIO_NONE) {
print("Blinking %s\r\n", hwPortname(currentPin));
}
-
}
void initBoardTest(void) {
@@ -119,37 +145,15 @@ void initBoardTest(void) {
// this code is ugly as hell, I had no time to think. Todo: refactor
- int pinsCount = sizeof(BLINK_PINS) / sizeof(brain_pin_e);
-
+ processAdcPin(&fastAdc, 0, "fast");
while (currentIndex < slowAdc.size()) {
- int hwIndex = slowAdc.getAdcHardwareIndexByInternalIndex(currentIndex);
- GPIO_TypeDef* port = getAdcChannelPort(hwIndex);
- int pin = getAdcChannelPin(hwIndex);
-
- int value = getAdcValueByIndex(currentIndex);
-
- int copy = stepCoutner;
-
- int c = 0;
-
- while (!isTimeForNextStep(copy)) {
-
- print("ch%d hwIndex=%d %s%d\r\n", currentIndex, hwIndex, portname(port), pin);
-
- int adcValue = getAdcValueByIndex(currentIndex);
-
-// print("ADC%d val= %d%s", hwIndex, value, DELIMETER);
- float volts = adcToVolts(adcValue) * 2;
- print("v=%f adc=%d c=%d (hit 'n' for next step\r\n", volts, adcValue, c++);
-
- chThdSleepMilliseconds(300);
-
- }
+ processAdcPin(&slowAdc, currentIndex, "slow");
currentIndex++;
}
currentIndex = 0;
+ int pinsCount = sizeof(BLINK_PINS) / sizeof(brain_pin_e);
while (currentIndex < pinsCount) {
currentPin = BLINK_PINS[currentIndex];
diff --git a/firmware/hw_layer/can_hw.cpp b/firmware/hw_layer/can_hw.cpp
index 46c52f226c..23fd72a067 100644
--- a/firmware/hw_layer/can_hw.cpp
+++ b/firmware/hw_layer/can_hw.cpp
@@ -17,7 +17,7 @@
#include "can_header.h"
#include "engine_configuration.h"
-#if EFI_CAN_SUPPORT
+#if EFI_CAN_SUPPORT || defined(__DOXYGEN__)
static int canReadCounter = 0;
static Logging logger;
diff --git a/firmware/hw_layer/flash.c b/firmware/hw_layer/flash.c
index 88e4eb480a..ff0e284a21 100644
--- a/firmware/hw_layer/flash.c
+++ b/firmware/hw_layer/flash.c
@@ -5,7 +5,7 @@
#include "main.h"
-#if EFI_INTERNAL_FLASH
+#if EFI_INTERNAL_FLASH || defined(__DOXYGEN__)
#include "flash.h"
#include
diff --git a/firmware/hw_layer/gpio_helper.c b/firmware/hw_layer/gpio_helper.c
index 39109e0106..5dcbe15b4c 100644
--- a/firmware/hw_layer/gpio_helper.c
+++ b/firmware/hw_layer/gpio_helper.c
@@ -36,7 +36,7 @@ void initOutputPinExt(const char *msg, OutputPin *outputPin, GPIO_TypeDef *port,
// firmwareError("outputPin already assigned to %x%d", outputPin->port, outputPin->pin);
// return;
// }
- outputPin->currentLogicValue = -1;
+ outputPin->currentLogicValue = INITIAL_PIN_STATE;
outputPin->port = port;
outputPin->pin = pinNumber;
diff --git a/firmware/hw_layer/gpio_helper.h b/firmware/hw_layer/gpio_helper.h
index 71d1d935fe..a99756eb9f 100644
--- a/firmware/hw_layer/gpio_helper.h
+++ b/firmware/hw_layer/gpio_helper.h
@@ -9,6 +9,9 @@
#ifndef GPIO_HELPER_H_
#define GPIO_HELPER_H_
+#define INITIAL_PIN_STATE -1
+
+
/**
* @brief Single output pin reference and state
*/
diff --git a/firmware/hw_layer/hardware.cpp b/firmware/hw_layer/hardware.cpp
index 4833a720ae..83d76b3977 100644
--- a/firmware/hw_layer/hardware.cpp
+++ b/firmware/hw_layer/hardware.cpp
@@ -185,7 +185,7 @@ void initHardware(Logging *logger) {
getHwPin(boardConfiguration->boardTestModeJumperPin), PAL_MODE_INPUT_PULLUP);
bool isBoardTestMode = GET_BOARD_TEST_MODE_VALUE();
- initAdcInputs(isBoardTestMode);
+ initAdcInputs();
if (isBoardTestMode) {
initBoardTest();
diff --git a/firmware/hw_layer/hw_layer.mk b/firmware/hw_layer/hw_layer.mk
index 0828ccd0f9..b8dd8543ed 100644
--- a/firmware/hw_layer/hw_layer.mk
+++ b/firmware/hw_layer/hw_layer.mk
@@ -19,4 +19,6 @@ HW_LAYER_SRC_CPP = $(PROJECT_DIR)/hw_layer/hardware.cpp \
$(PROJECT_DIR)/hw_layer/adc_inputs.cpp \
$(PROJECT_DIR)/hw_layer/board_test.cpp \
$(PROJECT_DIR)/hw_layer/pwm_generator.cpp \
- $(PROJECT_DIR)/hw_layer/trigger_input.cpp
+ $(PROJECT_DIR)/hw_layer/trigger_input.cpp \
+ $(PROJECT_DIR)/hw_layer/stm32f4/mpu_util.cpp
+
\ No newline at end of file
diff --git a/firmware/hw_layer/io_pins.c b/firmware/hw_layer/io_pins.c
index da52cdca67..4c536f0e4c 100644
--- a/firmware/hw_layer/io_pins.c
+++ b/firmware/hw_layer/io_pins.c
@@ -15,6 +15,7 @@
#include "status_loop.h"
#include "engine_configuration.h"
#include "console_io.h"
+#include "flash_main.h"
#if EFI_ENGINE_CONTROL
#include "main_trigger_callback.h"
@@ -58,7 +59,7 @@ inline static void assertOMode(pin_output_mode_e mode) {
* @brief Sets the value according to current electrical settings
*/
void setOutputPinValue(io_pin_e pin, int logicValue) {
- if (outputs[pin].port == GPIO_NULL)
+ if (outputs[pin].port == GPIO_NULL )
return;
efiAssertVoid(pinDefaultState[pin]!=NULL, "pin mode not initialized");
pin_output_mode_e mode = *pinDefaultState[pin];
@@ -77,9 +78,14 @@ void setDefaultPinState(io_pin_e pin, pin_output_mode_e *outputMode) {
}
static void comBlinkingThread(void *arg) {
- chRegSetThreadName("comm blinking");
+ chRegSetThreadName("communication blinking");
while (TRUE) {
- int delay = isConsoleReady() ? 100 : 33;
+ int delay;
+ if (getNeedToWriteConfiguration()) {
+ delay = isConsoleReady() ? 200 : 66;
+ } else {
+ delay = isConsoleReady() ? 100 : 33;
+ }
setOutputPinValue(LED_COMMUNICATION_1, 0);
setOutputPinValue(LED_EXT_1, 1);
@@ -115,16 +121,16 @@ static void errBlinkingThread(void *arg) {
static void outputPinRegisterExt(const char *msg, io_pin_e ioPin, GPIO_TypeDef *port, uint32_t pin,
pin_output_mode_e *outputMode) {
efiAssertVoid((int)ioPin < IO_PIN_COUNT, "io pin out of range");
- if (port == GPIO_NULL) {
+ if (port == GPIO_NULL ) {
// that's for GRIO_NONE
outputs[ioPin].port = port;
return;
}
assertOMode(*outputMode);
- iomode_t mode = (*outputMode == OM_DEFAULT || *outputMode == OM_INVERTED) ?
- PAL_MODE_OUTPUT_PUSHPULL :
- PAL_MODE_OUTPUT_OPENDRAIN;
+ iomode_t mode =
+ (*outputMode == OM_DEFAULT || *outputMode == OM_INVERTED) ?
+ PAL_MODE_OUTPUT_PUSHPULL : PAL_MODE_OUTPUT_OPENDRAIN;
initOutputPinExt(msg, &outputs[ioPin], port, pin, mode);
@@ -133,20 +139,20 @@ static void outputPinRegisterExt(const char *msg, io_pin_e ioPin, GPIO_TypeDef *
GPIO_TypeDef * getHwPort(brain_pin_e brainPin) {
if (brainPin == GPIO_NONE)
- return GPIO_NULL;
+ return GPIO_NULL ;
if (brainPin > GPIO_NONE) {
firmwareError("Invalid brain_pin_e: %d", brainPin);
- return GPIO_NULL;
+ return GPIO_NULL ;
}
return PORTS[brainPin / 16];
}
-int getHwPin(brain_pin_e brainPin) {
+ioportmask_t getHwPin(brain_pin_e brainPin) {
if (brainPin == GPIO_NONE)
- return -1;
+ return EFI_ERROR_CODE;
if (brainPin > GPIO_NONE) {
firmwareError("Invalid brain_pin_e: %d", brainPin);
- return -1;
+ return EFI_ERROR_CODE;
}
return brainPin % 16;
}
@@ -191,12 +197,10 @@ void initOutputPins(void) {
// todo: it's too late to clear now? this breaks default status LEDs
// todo: fix this?
// memset(&outputs, 0, sizeof(outputs));
-
// outputPinRegister("ext led 1", LED_EXT_1, EXTRA_LED_1_PORT, EXTRA_LED_1_PIN);
// outputPinRegister("ext led 2", LED_EXT_2, EXTRA_LED_2_PORT, EXTRA_LED_2_PIN);
// outputPinRegister("ext led 3", LED_EXT_3, EXTRA_LED_2_PORT, EXTRA_LED_3_PIN);
// outputPinRegister("alive1", LED_DEBUG, GPIOD, 6);
-
outputPinRegister("MalfunctionIndicator", LED_CHECK_ENGINE, getHwPort(boardConfiguration->malfunctionIndicatorPin),
getHwPin(boardConfiguration->malfunctionIndicatorPin));
@@ -214,6 +218,9 @@ void initOutputPins(void) {
outputPinRegister("fan relay", FAN_RELAY, getHwPort(boardConfiguration->fanPin),
getHwPin(boardConfiguration->fanPin));
+ outputPinRegister("o2 heater", O2_HEATER, getHwPort(boardConfiguration->o2heaterPin),
+ getHwPin(boardConfiguration->o2heaterPin));
+
initialLedsBlink();
// digit 1
@@ -245,6 +252,6 @@ void initOutputPins(void) {
ledRegister(LED_HUGE_20, GPIOE, 1);
*/
- chThdCreateStatic(comBlinkingStack, sizeof(comBlinkingStack), NORMALPRIO, (tfunc_t) comBlinkingThread, NULL);
- chThdCreateStatic(errBlinkingStack, sizeof(errBlinkingStack), NORMALPRIO, (tfunc_t) errBlinkingThread, NULL);
+ chThdCreateStatic(comBlinkingStack, sizeof(comBlinkingStack), NORMALPRIO, (tfunc_t) comBlinkingThread, NULL );
+ chThdCreateStatic(errBlinkingStack, sizeof(errBlinkingStack), NORMALPRIO, (tfunc_t) errBlinkingThread, NULL );
}
diff --git a/firmware/hw_layer/microsecond_timer.c b/firmware/hw_layer/microsecond_timer.c
index e1fed3814d..c9041d9e97 100644
--- a/firmware/hw_layer/microsecond_timer.c
+++ b/firmware/hw_layer/microsecond_timer.c
@@ -19,7 +19,7 @@
#define GPTDEVICE GPTD5
-static volatile int64_t lastSetTimerTime;
+static volatile uint64_t lastSetTimerTime;
static int lastSetTimerValue;
static volatile bool isTimerPending = FALSE;
diff --git a/firmware/hw_layer/mmc_card.c b/firmware/hw_layer/mmc_card.c
index c65f68a633..c96d6b8f49 100644
--- a/firmware/hw_layer/mmc_card.c
+++ b/firmware/hw_layer/mmc_card.c
@@ -12,7 +12,7 @@
#include "main.h"
-#if EFI_FILE_LOGGING
+#if EFI_FILE_LOGGING || defined(__DOXYGEN__)
#include
#include
@@ -49,7 +49,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 fs_ready = FALSE;
+static bool fs_ready = false;
#define PUSHPULLDELAY 500
@@ -105,7 +105,7 @@ static void createLogFile(void) {
return;
}
f_sync(&FDLogFile);
- fs_ready = TRUE; // everything Ok
+ fs_ready = true; // everything Ok
unlockSpi();
}
@@ -166,7 +166,7 @@ void appendToLog(char *line) {
errorReported = TRUE;
return;
}
- int lineLength = strlen(line);
+ UINT lineLength = strlen(line);
totalLoggedBytes += lineLength;
lockSpi(SPI_NONE);
FRESULT err = f_write(&FDLogFile, line, lineLength, &bytesWrited);
@@ -234,11 +234,11 @@ static msg_t MMCmonThread(void)
{
chRegSetThreadName("MMC_Monitor");
- while (TRUE) {
+ while (true) {
// this returns TRUE if SD module is there, even without an SD card?
if (blkIsInserted(&MMCD1)) {
- if (fs_ready == FALSE) {
+ if (!fs_ready) {
MMCmount();
}
}
@@ -248,6 +248,10 @@ static msg_t MMCmonThread(void)
}
}
+bool isSdCardAlive(void) {
+ return fs_ready;
+}
+
void initMmcCard(void) {
initLogging(&logger, "mmcCard");
diff --git a/firmware/hw_layer/mmc_card.h b/firmware/hw_layer/mmc_card.h
index f9c310a2ef..6af96ab92e 100644
--- a/firmware/hw_layer/mmc_card.h
+++ b/firmware/hw_layer/mmc_card.h
@@ -16,6 +16,7 @@ extern "C"
#endif /* __cplusplus */
void initMmcCard(void);
+bool isSdCardAlive(void);
void appendToLog(char *line);
#ifdef __cplusplus
diff --git a/firmware/hw_layer/neo6m.c b/firmware/hw_layer/neo6m.c
index 5300a4726b..546f9e05c7 100644
--- a/firmware/hw_layer/neo6m.c
+++ b/firmware/hw_layer/neo6m.c
@@ -12,9 +12,11 @@
*/
#include
+// todo: MISRA does not like time.h
+#include
#include "main.h"
-#if EFI_UART_GPS
+#if EFI_UART_GPS || defined(__DOXYGEN__)
#include "console_io.h"
#include "eficonsole.h"
@@ -22,6 +24,9 @@
#include "nmea.h"
#include "neo6m.h"
#include "rtc_helper.h"
+#include "engine_configuration.h"
+
+extern board_configuration_s *boardConfiguration;
static Logging logging;
@@ -43,8 +48,8 @@ float getCurrentSpeed(void) {
static void printGpsInfo(void) {
// todo: scheduleMsg()
- scheduleMsg(&logging, "GPS RX %s%d", portname(GPS_PORT), GPS_SERIAL_RX_PIN);
- scheduleMsg(&logging, "GPS TX %s%d", portname(GPS_PORT), GPS_SERIAL_TX_PIN);
+ scheduleMsg(&logging, "GPS RX %s", hwPortname(boardConfiguration->gps_rx_pin));
+ scheduleMsg(&logging, "GPS TX %s", hwPortname(boardConfiguration->gps_tx_pin));
scheduleMsg(&logging, "m=%d,e=%d: vehicle speed = %f\r\n", gpsMesagesCount, uartErrors, getCurrentSpeed());
@@ -58,13 +63,13 @@ static void printGpsInfo(void) {
static struct tm curTm;
static void onGpsMessage(char *buffer) {
-
+
gps_location(&GPSdata, buffer);
date_get_tm(&curTm);
- if(GPSdata.quality == 4 && GPSdata.GPStm.tm_year > 0 && GPSdata.GPStm.tm_sec != curTm.tm_sec) {
+ if (GPSdata.quality == 4 && GPSdata.GPStm.tm_year > 0 && GPSdata.GPStm.tm_sec != curTm.tm_sec) {
// quality =4 (valis GxRMC), year > 0, and difference more then second
- date_set_tm(&GPSdata.GPStm); // set GPS time
+ date_set_tm(&GPSdata.GPStm); // set GPS time
//}
}
gpsMesagesCount++;
@@ -101,12 +106,16 @@ static msg_t GpsThreadEntryPoint(void *arg) {
}
void initGps(void) {
+ if (boardConfiguration->gps_rx_pin == GPIO_NONE || boardConfiguration->gps_tx_pin == GPIO_NONE) {
+ return;
+ }
+
initLogging(&logging, "uart gps");
sdStart(GPS_SERIAL_DEVICE, &GPSserialConfig);
// GPS we have USART1: PB7 -> USART1_RX and PB6 -> USART1_TX
- mySetPadMode("GPS tx", GPS_PORT, GPS_SERIAL_TX_PIN, PAL_MODE_ALTERNATE(7));
- mySetPadMode("GPS rx", GPS_PORT, GPS_SERIAL_RX_PIN, PAL_MODE_ALTERNATE(7));
+ mySetPadMode("GPS tx", getHwPort(boardConfiguration->gps_tx_pin), getHwPin(boardConfiguration->gps_tx_pin), PAL_MODE_ALTERNATE(7));
+ mySetPadMode("GPS rx", getHwPort(boardConfiguration->gps_rx_pin), getHwPin(boardConfiguration->gps_rx_pin), PAL_MODE_ALTERNATE(7));
// todo: add a thread which would save location. If the GPS 5Hz - we should save the location each 200 ms
chThdCreateStatic(GPS_WORKING_AREA, sizeof(GPS_WORKING_AREA), LOWPRIO, GpsThreadEntryPoint, NULL);
diff --git a/firmware/hw_layer/pin_repository.c b/firmware/hw_layer/pin_repository.c
index 80e42b68d2..fc0f16beab 100644
--- a/firmware/hw_layer/pin_repository.c
+++ b/firmware/hw_layer/pin_repository.c
@@ -76,10 +76,35 @@ static void reportPins(void) {
static MemoryStream portNameStream;
static char portNameBuffer[20];
+brain_pin_e parseBrainPin(const char *str) {
+ if (strEqual(str, "none"))
+ return GPIO_NONE;
+ // todo: create method toLowerCase?
+ if (str[0] != 'p' && str[0] != 'p') {
+ return GPIO_INVALID;
+ }
+ char port = str[1];
+ brain_pin_e basePin;
+ if (port >= 'a' && port <= 'z') {
+ basePin = (brain_pin_e) ((int) GPIOA_0 + 16 * (port - 'a'));
+ } else if (port >= 'A' && port <= 'Z') {
+ basePin = (brain_pin_e) ((int) GPIOA_0 + 16 * (port - 'A'));
+ } else {
+ return GPIO_INVALID;
+ }
+ const char *pinStr = str + 2;
+ int pin = atoi(pinStr);
+ return basePin + pin;
+}
+
char *hwPortname(brain_pin_e brainPin) {
+ if (brainPin == GPIO_INVALID) {
+ return "INVALID";
+ }
GPIO_TypeDef *hwPort = getHwPort(brainPin);
- if (hwPort == GPIO_NULL)
+ if (hwPort == GPIO_NULL) {
return "NONE";
+ }
int hwPin = getHwPin(brainPin);
portNameStream.eos = 0; // reset
chprintf((BaseSequentialStream *) &portNameStream, "%s%d", portname(hwPort), hwPin);
@@ -93,7 +118,7 @@ void initPinRepository(void) {
*/
initLogging(&logger, "pin repos");
- msObjectInit(&portNameStream, portNameBuffer, sizeof(portNameBuffer), 0);
+ msObjectInit(&portNameStream, (uint8_t*)portNameBuffer, sizeof(portNameBuffer), 0);
for (int i = 0; i < PIN_REPO_SIZE; i++)
PIN_USED[i] = 0;
@@ -124,7 +149,7 @@ void mySetPadMode(const char *msg, ioportid_t port, ioportmask_t pin, iomode_t m
int index = portIndex * 16 + pin;
if (PIN_USED[index] != NULL) {
- firmwareError("Pin %s%d requested by %s but already used by %s", portname(port), pin, msg, PIN_USED[index]);
+ firmwareError("%s%d req by %s used by %s", portname(port), pin, msg, PIN_USED[index]);
return;
}
markUsed(index, msg);
diff --git a/firmware/hw_layer/pin_repository.h b/firmware/hw_layer/pin_repository.h
index 839d6d3ff4..680a15ee76 100644
--- a/firmware/hw_layer/pin_repository.h
+++ b/firmware/hw_layer/pin_repository.h
@@ -24,12 +24,13 @@ extern "C"
void initPinRepository(void);
char *hwPortname(brain_pin_e brainPin);
+brain_pin_e parseBrainPin(const char *str);
void mySetPadMode(const char *msg, ioportid_t port, ioportmask_t pin, iomode_t mode);
char *portname(GPIO_TypeDef* GPIOx);
// does not exactly belong here, but that works better for tests
void outputPinRegister(const char *msg, io_pin_e ioPin, GPIO_TypeDef *port, uint32_t pin);
-int getHwPin(brain_pin_e brainPin);
+ioportmask_t getHwPin(brain_pin_e brainPin);
GPIO_TypeDef * getHwPort(brain_pin_e brainPin);
#ifdef __cplusplus
diff --git a/firmware/hw_layer/pwm_generator.cpp b/firmware/hw_layer/pwm_generator.cpp
index 3572f2a213..100e9e40e4 100644
--- a/firmware/hw_layer/pwm_generator.cpp
+++ b/firmware/hw_layer/pwm_generator.cpp
@@ -15,7 +15,6 @@
#include "pwm_generator.h"
#include "pin_repository.h"
-#include "wave_math.h"
#include "datalogging.h"
static Logging logger;
diff --git a/firmware/hw_layer/rtc_helper.c b/firmware/hw_layer/rtc_helper.c
index e067a213c9..d4c797a598 100644
--- a/firmware/hw_layer/rtc_helper.c
+++ b/firmware/hw_layer/rtc_helper.c
@@ -15,6 +15,7 @@
static Logging logger;
+#if EFI_RTC
static void date_help(void) {
scheduleMsg(&logger, "Usage: date_help");
scheduleMsg(&logger, " date_get");
@@ -22,6 +23,8 @@ static void date_help(void) {
scheduleMsg(&logger, "where N is time in seconds sins Unix epoch - see http://www.epochconverter.com");
}
+#endif /* EFI_RTC */
+
void date_set_tm(struct tm *timp) {
#if EFI_RTC
rtcSetTimeTm(&RTCD1, timp);
@@ -91,8 +94,8 @@ void dateToString(char *lcd_str) {
#endif /* EFI_RTC */
}
-static void date_get(void) {
#if EFI_RTC
+static void date_get(void) {
static time_t unix_time;
struct tm timp;
@@ -109,11 +112,9 @@ static void date_get(void) {
appendMsgPostfix(&logger);
scheduleLogging(&logger);
}
-#endif
}
static void date_set(char *strDate) {
-#if EFI_RTC
if (strlen(strDate) > 0) {
time_t unix_time = (double) atoff(strDate);
if (unix_time > 0) {
@@ -123,8 +124,8 @@ static void date_set(char *strDate) {
}
}
scheduleMsg(&logger, "date_set Date parameter %s is wrong\r\n", strDate);
-#endif
}
+#endif /* EFI_RTC */
void initRtc(void) {
initLogging(&logger, "rtc");
diff --git a/firmware/hw_layer/serial_over_usb/usbconsole.c b/firmware/hw_layer/serial_over_usb/usbconsole.c
index a2581823e8..2780bfffcc 100644
--- a/firmware/hw_layer/serial_over_usb/usbconsole.c
+++ b/firmware/hw_layer/serial_over_usb/usbconsole.c
@@ -44,7 +44,7 @@ void usb_serial_start(void) {
palSetPadMode(GPIOA, 3, PAL_MODE_ALTERNATE(7));
}
-int is_usb_serial_ready(void) {
+bool is_usb_serial_ready(void) {
return SDU1.config->usbp->state == USB_ACTIVE;
}
diff --git a/firmware/hw_layer/serial_over_usb/usbconsole.h b/firmware/hw_layer/serial_over_usb/usbconsole.h
index cc9b6f9d7a..2d6a8203aa 100644
--- a/firmware/hw_layer/serial_over_usb/usbconsole.h
+++ b/firmware/hw_layer/serial_over_usb/usbconsole.h
@@ -14,7 +14,7 @@ extern "C"
#endif /* __cplusplus */
void usb_serial_start(void);
-int is_usb_serial_ready(void);
+bool is_usb_serial_ready(void);
#ifdef __cplusplus
}
diff --git a/firmware/hw_layer/stm32f4/mpu_util.cpp b/firmware/hw_layer/stm32f4/mpu_util.cpp
new file mode 100644
index 0000000000..28a1b7d2a2
--- /dev/null
+++ b/firmware/hw_layer/stm32f4/mpu_util.cpp
@@ -0,0 +1,50 @@
+/**
+ * @file mpu_util.cpp
+ *
+ * @date Jul 27, 2014
+ * @author Andrey Belomutskiy, (c) 2012-2014
+ */
+
+#include "main.h"
+#include "mpu_util.h"
+#include "error_handling.h"
+
+void baseHardwareInit(void) {
+ // looks like this holds a random value on start? Let's set a nice clean zero
+ DWT_CYCCNT = 0;
+}
+
+void DebugMonitorVector(void) {
+
+ chDbgPanic3("DebugMonitorVector", __FILE__, __LINE__);
+
+ while (TRUE)
+ ;
+}
+
+void UsageFaultVector(void) {
+
+ chDbgPanic3("UsageFaultVector", __FILE__, __LINE__);
+
+ while (TRUE)
+ ;
+}
+
+void BusFaultVector(void) {
+
+ chDbgPanic3("BusFaultVector", __FILE__, __LINE__);
+
+ while (TRUE) {
+ }
+}
+
+void HardFaultVector(void) {
+
+ chDbgPanic3("HardFaultVector", __FILE__, __LINE__);
+
+ while (TRUE) {
+ }
+}
+
+
+
diff --git a/firmware/hw_layer/stm32f4/mpu_util.h b/firmware/hw_layer/stm32f4/mpu_util.h
new file mode 100644
index 0000000000..4228b6fd2f
--- /dev/null
+++ b/firmware/hw_layer/stm32f4/mpu_util.h
@@ -0,0 +1,29 @@
+/**
+ * @file mpu_util.h
+ *
+ * @date Jul 27, 2014
+ * @author Andrey Belomutskiy, (c) 2012-2014
+ */
+#ifndef MPU_UTIL_H_
+#define MPU_UTIL_H_
+
+void baseHardwareInit(void);
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+// these need to be declared C style for the linker magic to work
+
+void DebugMonitorVector(void);
+void UsageFaultVector(void);
+void BusFaultVector(void);
+void HardFaultVector(void);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* MPU_UTIL_H_ */
diff --git a/firmware/hw_layer/trigger_input.cpp b/firmware/hw_layer/trigger_input.cpp
index cb65eda94f..8779f90ed8 100644
--- a/firmware/hw_layer/trigger_input.cpp
+++ b/firmware/hw_layer/trigger_input.cpp
@@ -25,13 +25,12 @@ extern engine_configuration_s *engineConfiguration;
extern engine_configuration2_s *engineConfiguration2;
extern board_configuration_s *boardConfiguration;
-
static inline ICUDriver *getPrimaryInputCaptureDriver(void) {
- return getInputCaptureDriver(boardConfiguration->primaryTriggerInputPin);
+ return getInputCaptureDriver(boardConfiguration->triggerInputPins[0]);
}
static inline ICUDriver *getSecondaryInputCaptureDriver(void) {
- return getInputCaptureDriver(boardConfiguration->secondaryTriggerInputPin);
+ return getInputCaptureDriver(boardConfiguration->triggerInputPins[1]);
}
/**
@@ -40,9 +39,11 @@ static inline ICUDriver *getSecondaryInputCaptureDriver(void) {
*/
static void shaft_icu_width_callback(ICUDriver *icup) {
int isPrimary = icup == getPrimaryInputCaptureDriver();
- if (!isPrimary && !engineConfiguration2->triggerShape.needSecondTriggerInput)
+ if (!isPrimary && !engineConfiguration2->triggerShape.needSecondTriggerInput) {
return;
+ }
// icucnt_t last_width = icuGetWidth(icup); so far we are fine with system time
+ // todo: add support for 3rd channel
trigger_event_e signal = isPrimary ? SHAFT_PRIMARY_UP : SHAFT_SECONDARY_UP;
hwHandleShaftSignal(signal);
@@ -50,11 +51,13 @@ static void shaft_icu_width_callback(ICUDriver *icup) {
static void shaft_icu_period_callback(ICUDriver *icup) {
int isPrimary = icup == getPrimaryInputCaptureDriver();
- if (!isPrimary && !engineConfiguration2->triggerShape.needSecondTriggerInput)
+ if (!isPrimary && !engineConfiguration2->triggerShape.needSecondTriggerInput) {
return;
+ }
+ // todo: add support for 3rd channel
// icucnt_t last_period = icuGetPeriod(icup); so far we are fine with system time
- trigger_event_e signal = isPrimary ? SHAFT_PRIMARY_DOWN : SHAFT_SECONDARY_DOWN;
+ trigger_event_e signal = isPrimary ? SHAFT_PRIMARY_DOWN : SHAFT_SECONDARY_DOWN;
hwHandleShaftSignal(signal);
}
@@ -66,28 +69,35 @@ shaft_icu_width_callback, shaft_icu_period_callback };
void initShaftPositionInputCapture(void) {
+ ICUDriver *driver;
+ driver = getInputCaptureDriver(boardConfiguration->triggerInputPins[0]);
+
+ // todo: extract method!
// initialize primary Input Capture Unit pin
- initWaveAnalyzerDriver(&primaryCrankInput, getPrimaryInputCaptureDriver(),
- getHwPort(boardConfiguration->primaryTriggerInputPin),
- getHwPin(boardConfiguration->primaryTriggerInputPin));
+ initWaveAnalyzerDriver(&primaryCrankInput, driver, getHwPort(boardConfiguration->triggerInputPins[0]),
+ getHwPin(boardConfiguration->triggerInputPins[0]));
/**
* Start primary Input Capture Unit using given configuration
* @see shaft_icucfg for callback entry points
*/
shaft_icucfg.channel = ICU_CHANNEL_1;
- print("initShaftPositionInputCapture 1 %s\r\n", hwPortname(boardConfiguration->primaryTriggerInputPin));
- icuStart(getPrimaryInputCaptureDriver(), &shaft_icucfg);
- icuEnable(getPrimaryInputCaptureDriver());
+ print("initShaftPositionInputCapture 1 %s\r\n", hwPortname(boardConfiguration->triggerInputPins[0]));
+ if (driver != NULL) {
+ icuStart(driver, &shaft_icucfg);
+ icuEnable(driver);
+ }
+ driver = getInputCaptureDriver(boardConfiguration->triggerInputPins[1]);
// initialize secondary Input Capture Unit pin
initWaveAnalyzerDriver(&secondaryCrankInput, getSecondaryInputCaptureDriver(),
- getHwPort(boardConfiguration->secondaryTriggerInputPin),
- getHwPin(boardConfiguration->secondaryTriggerInputPin));
+ getHwPort(boardConfiguration->triggerInputPins[1]), getHwPin(boardConfiguration->triggerInputPins[1]));
shaft_icucfg.channel = ICU_CHANNEL_1;
- print("initShaftPositionInputCapture 2 %s\r\n", hwPortname(boardConfiguration->secondaryTriggerInputPin));
- icuStart(getSecondaryInputCaptureDriver(), &shaft_icucfg);
- icuEnable(getSecondaryInputCaptureDriver());
+ print("initShaftPositionInputCapture 2 %s\r\n", hwPortname(boardConfiguration->triggerInputPins[1]));
+ if (driver != NULL) {
+ icuStart(driver, &shaft_icucfg);
+ icuEnable(driver);
+ }
print("crank input disabled\r\n");
}
diff --git a/firmware/hw_layer/wave_analyzer_hw.c b/firmware/hw_layer/wave_analyzer_hw.c
index 38e4323dd6..edefb916e1 100644
--- a/firmware/hw_layer/wave_analyzer_hw.c
+++ b/firmware/hw_layer/wave_analyzer_hw.c
@@ -18,17 +18,20 @@ static void icuPeriordCallBack(ICUDriver *driver);
* CORE_CLOCK / 33.33333 = TICKS * 65536
* 168000000 / 33.333333 / 65536 = 76.90
*/
-static ICUConfig wave_icucfg = { ICU_INPUT_ACTIVE_LOW, CORE_CLOCK / 100, icuWidthCallback, icuPeriordCallBack };
+static ICUConfig wave_icucfg = { ICU_INPUT_ACTIVE_LOW, CORE_CLOCK / 100, icuWidthCallback, icuPeriordCallBack, 0,
+ ICU_CHANNEL_1, 0 };
static int registeredIcuCount = 0;
static WaveReaderHw* registeredIcus[8];
static WaveReaderHw * findWaveReaderHw(ICUDriver *driver) {
- for (int i = 0; i < registeredIcuCount; i++)
- if (registeredIcus[i]->driver == driver)
+ for (int i = 0; i < registeredIcuCount; i++) {
+ if (registeredIcus[i]->driver == driver) {
return registeredIcus[i];
+ }
+ }
firmwareError("reader not found");
- return NULL;
+ return (WaveReaderHw *) NULL;
}
static void icuWidthCallback(ICUDriver *driver) {
@@ -51,65 +54,76 @@ static void icuPeriordCallBack(ICUDriver *driver) {
invokeJustArgCallbacks(&hw->periodListeners);
}
-static int getAlternateFunctions(ICUDriver *driver) {
+static uint32_t getAlternateFunctions(ICUDriver *driver) {
if (driver == NULL) {
firmwareError("getAlternateFunctions(NULL)");
- return -1;
+ return 0xffffffff;
}
#if STM32_ICU_USE_TIM1
- if (driver == &ICUD1)
+ if (driver == &ICUD1) {
return GPIO_AF_TIM1;
+ }
#endif
#if STM32_ICU_USE_TIM2
- if (driver == &ICUD2)
+ if (driver == &ICUD2) {
return GPIO_AF_TIM2;
+ }
#endif
#if STM32_ICU_USE_TIM3
- if (driver == &ICUD3)
+ if (driver == &ICUD3) {
return GPIO_AF_TIM3;
+ }
#endif
#if STM32_ICU_USE_TIM4
- if (driver == &ICUD4)
- return GPIO_AF_TIM4;
+ if (driver == &ICUD4) {
+ return GPIO_AF_TIM4;
+ }
#endif
#if STM32_ICU_USE_TIM9
- if (driver == &ICUD9)
+ if (driver == &ICUD9) {
return GPIO_AF_TIM9;
+ }
#endif
firmwareError("No such driver");
- return -1;
+ return 0xffffffff;
}
ICUDriver * getInputCaptureDriver(brain_pin_e hwPin) {
#if STM32_ICU_USE_TIM1
- if (hwPin == GPIOA_8)
+ if (hwPin == GPIOA_8) {
return &ICUD1;
+ }
#endif
#if STM32_ICU_USE_TIM2
- if (hwPin == GPIOA_5)
+ if (hwPin == GPIOA_5) {
return &ICUD2;
+ }
#endif
#if STM32_ICU_USE_TIM3
- if (hwPin == GPIOC_6)
+ if (hwPin == GPIOC_6) {
return &ICUD3;
+ }
#endif
#if STM32_ICU_USE_TIM9
- if (hwPin == GPIOE_7)
+ if (hwPin == GPIOE_7) {
return &ICUD9;
+ }
#endif
-
- return NULL;
+ return (ICUDriver *) NULL;
}
-void initWaveAnalyzerDriver(WaveReaderHw *hw, ICUDriver *driver, ioportid_t port, int pin) {
+void initWaveAnalyzerDriver(WaveReaderHw *hw, ICUDriver *driver, ioportid_t port, ioportmask_t pin) {
hw->driver = driver;
hw->port = port;
hw->pin = pin;
- mySetPadMode("wave input", port, pin, PAL_MODE_ALTERNATE(getAlternateFunctions(driver)));
+ if (driver != NULL) {
+ iomode_t mode = (iomode_t) PAL_MODE_ALTERNATE(getAlternateFunctions(driver));
+ mySetPadMode("wave input", port, pin, mode);
// hw->widthListeners.currentListenersCount = 0;
- registeredIcus[registeredIcuCount++] = hw;
+ registeredIcus[registeredIcuCount++] = hw;
+ }
}
void setWaveReaderMode(WaveReaderHw *hw, int mode) {
@@ -121,11 +135,13 @@ void setWaveReaderMode(WaveReaderHw *hw, int mode) {
}
ICUDriver *driver = hw->driver;
- if (hw->started) {
- icuDisable(driver);
- icuStop(driver);
+ if (driver != NULL) {
+ if (hw->started) {
+ icuDisable(driver);
+ icuStop(driver);
+ }
+ icuStart(driver, &wave_icucfg);
+ icuEnable(driver);
}
- icuStart(driver, &wave_icucfg);
- icuEnable(driver);
hw->started = TRUE;
}
diff --git a/firmware/hw_layer/wave_analyzer_hw.h b/firmware/hw_layer/wave_analyzer_hw.h
index f559d01b72..0d3c454cb7 100644
--- a/firmware/hw_layer/wave_analyzer_hw.h
+++ b/firmware/hw_layer/wave_analyzer_hw.h
@@ -28,7 +28,7 @@ extern "C"
#endif /* __cplusplus */
void initWaveAnalyzerDriver(WaveReaderHw *hw, ICUDriver *driver,
- ioportid_t port, int pin);
+ ioportid_t port, ioportmask_t pin);
void setWaveReaderMode(WaveReaderHw *hw, int mode);
ICUDriver * getInputCaptureDriver(brain_pin_e hwPin);
diff --git a/firmware/main.cpp b/firmware/main.cpp
index 5bbf57b9b7..67f60f566d 100644
--- a/firmware/main.cpp
+++ b/firmware/main.cpp
@@ -7,16 +7,10 @@
* http://rusefi.com/
*/
-extern "C"
-{
-#include "global.h"
-}
#include "main.h"
-
-extern "C"
-{
#include "rusefi.h"
-}
+#include "mpu_util.h"
+
int main(void) {
/*
* ChibiOS/RT initialization
@@ -24,8 +18,7 @@ int main(void) {
halInit();
chSysInit();
- // looks like this holds a random value on start? Let's set a nice clean zero
- DWT_CYCCNT = 0;
+ baseHardwareInit();
runRusEfi();
return 0;
diff --git a/firmware/main.h b/firmware/main.h
index 6eab11f046..b3537933a4 100644
--- a/firmware/main.h
+++ b/firmware/main.h
@@ -49,7 +49,6 @@ extern "C"
extern "C"
{
#endif
-void updateHD44780lcd(void);
int systicks2ms(int systicks);
bool lockAnyContext(void);
diff --git a/firmware/rusefi.cpp b/firmware/rusefi.cpp
index 49ab99623e..4137959502 100644
--- a/firmware/rusefi.cpp
+++ b/firmware/rusefi.cpp
@@ -9,6 +9,12 @@
/**
* @mainpage
*
+ * @section sec_into
+ *
+ * rusEfi is implemented based on the idea that with modern 100+ MHz microprocessors the relatively
+ * undemanding task of internal combustion engine control could be implemented in a high-level, processor-independent
+ * (to some extent) manner. Thus the key concepts of rusEfi: dependency on high-level hardware abstraction layer, software-based PWM etc.
+ *
* @section sec_main Brief overview
*
* rusEfi runs on crankshaft or camshaft ('trigger') position sensor events.
@@ -76,7 +82,7 @@
*
*
See main_trigger_callback.cpp for main trigger event handler
*
See fuel_math.cpp for details on fuel amount logic
- *
See rpm_calculator.c for details on how getRpm() is calculated
+ *
See rpm_calculator.cpp for details on how getRpm() is calculated
*
*/
@@ -110,13 +116,17 @@ static Logging logging;
int main_loop_started = FALSE;
-static MemoryStream errorMessageStream;
+static MemoryStream firmwareErrorMessageStream;
uint8_t errorMessageBuffer[200];
static bool hasFirmwareErrorFlag = FALSE;
extern board_configuration_s *boardConfiguration;
+char *getFirmwareError(void) {
+ return (char*)errorMessageBuffer;
+}
+
void runRusEfi(void) {
- msObjectInit(&errorMessageStream, errorMessageBuffer, sizeof(errorMessageBuffer), 0);
+ msObjectInit(&firmwareErrorMessageStream, errorMessageBuffer, sizeof(errorMessageBuffer), 0);
initErrorHandling();
@@ -188,42 +198,8 @@ void scheduleReset(void) {
unlockAnyContext();
}
-void DebugMonitorVector(void) {
-
- chDbgPanic3("DebugMonitorVector", __FILE__, __LINE__);
-
- while (TRUE)
- ;
-}
-
-void UsageFaultVector(void) {
-
- chDbgPanic3("UsageFaultVector", __FILE__, __LINE__);
-
- while (TRUE)
- ;
-}
-
-void BusFaultVector(void) {
-
- chDbgPanic3("BusFaultVector", __FILE__, __LINE__);
-
- while (TRUE)
- ;
-}
-
-void HardFaultVector(void) {
-
- chDbgPanic3("HardFaultVector", __FILE__, __LINE__);
-
- while (TRUE)
- ;
-}
-
extern int main_loop_started;
-void onFatalError(const char *msg, char * file, int line);
-
static char panicMessage[200];
void chDbgStackOverflowPanic(Thread *otp) {
@@ -243,15 +219,15 @@ void firmwareError(const char *fmt, ...) {
return;
setOutputPinValue(LED_ERROR, 1);
hasFirmwareErrorFlag = TRUE;
- errorMessageStream.eos = 0; // reset
+ firmwareErrorMessageStream.eos = 0; // reset
va_list ap;
va_start(ap, fmt);
- chvprintf((BaseSequentialStream *) &errorMessageStream, fmt, ap);
+ chvprintf((BaseSequentialStream *) &firmwareErrorMessageStream, fmt, ap);
va_end(ap);
- errorMessageStream.buffer[errorMessageStream.eos] = 0; // need to terminate explicitly
+ firmwareErrorMessageStream.buffer[firmwareErrorMessageStream.eos] = 0; // need to terminate explicitly
}
int getRusEfiVersion(void) {
- return 20140724;
+ return 20140822;
}
diff --git a/firmware/rusefi.h b/firmware/rusefi.h
index 06ec810af5..f9c26b13d9 100644
--- a/firmware/rusefi.h
+++ b/firmware/rusefi.h
@@ -11,20 +11,4 @@
void runRusEfi(void);
void scheduleReset(void);
-#ifdef __cplusplus
-extern "C"
-{
-#endif /* __cplusplus */
-
-// these need to be declared C style for the linker magic to work
-
-void DebugMonitorVector(void);
-void UsageFaultVector(void);
-void BusFaultVector(void);
-void HardFaultVector(void);
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
#endif /* RUSEFI_H_ */
diff --git a/firmware/svnversion.h b/firmware/svnversion.h
index 6fe1449f9e..2b9f53db14 100644
--- a/firmware/svnversion.h
+++ b/firmware/svnversion.h
@@ -1,5 +1,5 @@
// This file was generated by Version2Header
-// Wed Jul 23 08:21:40 EDT 2014
+// Thu Aug 21 13:54:37 EDT 2014
#ifndef VCS_VERSION
-#define VCS_VERSION "4047"
+#define VCS_VERSION "4372"
#endif
diff --git a/firmware/util/cli_registry.c b/firmware/util/cli_registry.c
index b7831b1871..6952d96ae8 100644
--- a/firmware/util/cli_registry.c
+++ b/firmware/util/cli_registry.c
@@ -70,10 +70,18 @@ void addConsoleActionS(const char *token, VoidCharPtr callback) {
doAddAction(token, STRING_PARAMETER, (Void) callback);
}
+void addConsoleActionSS(const char *token, VoidCharPtrCharPtr callback) {
+ doAddAction(token, STRING2_PARAMETER, (Void) callback);
+}
+
void addConsoleActionSSS(const char *token, VoidCharPtrCharPtrCharPtr callback) {
doAddAction(token, STRING3_PARAMETER, (Void) callback);
}
+void addConsoleActionSSSSS(const char *token, VoidCharPtrCharPtrCharPtrCharPtrCharPtr callback) {
+ doAddAction(token, STRING5_PARAMETER, (Void) callback);
+}
+
void addConsoleActionF(const char *token, VoidFloat callback) {
doAddAction(token, FLOAT_PARAMETER, (Void) callback);
}
@@ -93,7 +101,7 @@ void helpCommand(void) {
}
#endif /* EFI_PROD_CODE */
-#if EFI_PROD_CODE || EFI_SIMULATOR
+#if (EFI_PROD_CODE || EFI_SIMULATOR) || defined(__DOXYGEN__)
scheduleMsg(&logging, "%d actions available", consoleActionCount);
for (int i = 0; i < consoleActionCount; i++) {
TokenCallback *current = &consoleActions[i];
@@ -116,24 +124,82 @@ void handleActionWithParameter(TokenCallback *current, char *parameter) {
return;
}
+ // todo: refactor this hell!
+ if (current->parameterType == STRING2_PARAMETER) {
+ int spaceIndex = indexOf(parameter, ' ');
+ if (spaceIndex == -1) {
+ return;
+ }
+ parameter[spaceIndex] = 0;
+ char * param0 = parameter;
+
+ parameter += spaceIndex + 1;
+ char * param1 = parameter;
+
+ VoidCharPtrCharPtr callbackS = (VoidCharPtrCharPtr) current->callback;
+ (*callbackS)(param0, param1);
+ return;
+
+ }
+
if (current->parameterType == STRING3_PARAMETER) {
int spaceIndex = indexOf(parameter, ' ');
- if (spaceIndex == -1)
+ if (spaceIndex == -1) {
return;
+ }
parameter[spaceIndex] = 0;
- char * firstParam = parameter;
+ char * param0 = parameter;
parameter += spaceIndex + 1;
spaceIndex = indexOf(parameter, ' ');
if (spaceIndex == -1)
return;
parameter[spaceIndex] = 0;
- char * secondParam = parameter;
+ char * param1 = parameter;
parameter += spaceIndex + 1;
- char * thirdParam = parameter;
+ char * param2 = parameter;
VoidCharPtrCharPtrCharPtr callbackS = (VoidCharPtrCharPtrCharPtr) current->callback;
- (*callbackS)(firstParam, secondParam, thirdParam);
+ (*callbackS)(param0, param1, param2);
+ return;
+
+ }
+
+ // todo: refactor this hell!
+ if (current->parameterType == STRING5_PARAMETER) {
+ int spaceIndex = indexOf(parameter, ' ');
+ if (spaceIndex == -1) {
+ return;
+ }
+ parameter[spaceIndex] = 0;
+ char * param0 = parameter;
+
+ parameter += spaceIndex + 1;
+ spaceIndex = indexOf(parameter, ' ');
+ if (spaceIndex == -1)
+ return;
+ parameter[spaceIndex] = 0;
+ char * param1 = parameter;
+
+ parameter += spaceIndex + 1;
+ spaceIndex = indexOf(parameter, ' ');
+ if (spaceIndex == -1)
+ return;
+ parameter[spaceIndex] = 0;
+ char * param2 = parameter;
+
+ parameter += spaceIndex + 1;
+ spaceIndex = indexOf(parameter, ' ');
+ if (spaceIndex == -1)
+ return;
+ parameter[spaceIndex] = 0;
+ char * param3 = parameter;
+
+ parameter += spaceIndex + 1;
+ char * param4 = parameter;
+
+ VoidCharPtrCharPtrCharPtrCharPtrCharPtr callbackS = (VoidCharPtrCharPtrCharPtrCharPtrCharPtr) current->callback;
+ (*callbackS)(param0, param1, param2, param3, param4);
return;
}
@@ -144,8 +210,20 @@ void handleActionWithParameter(TokenCallback *current, char *parameter) {
return;
parameter[spaceIndex] = 0;
int value1 = atoi(parameter);
+ if (absI(value1) == absI(ERROR_CODE)) {
+#if (EFI_PROD_CODE || EFI_SIMULATOR) || defined(__DOXYGEN__)
+ scheduleMsg(&logging, "not an integer [%s]", parameter);
+#endif
+ return;
+ }
parameter += spaceIndex + 1;
int value2 = atoi(parameter);
+ if (absI(value2) == absI(ERROR_CODE)) {
+#if (EFI_PROD_CODE || EFI_SIMULATOR) || defined(__DOXYGEN__)
+ scheduleMsg(&logging, "not an integer [%s]", parameter);
+#endif
+ return;
+ }
VoidIntInt callbackS = (VoidIntInt) current->callback;
(*callbackS)(value1, value2);
return;
@@ -189,12 +267,13 @@ void handleActionWithParameter(TokenCallback *current, char *parameter) {
/**
* @return Number of space-separated tokens in the string
*/
-int tokenLength(char *msgp) {
+int tokenLength(const char *msgp) {
int result = 0;
while (*msgp) {
char ch = *msgp++;
- if (ch == ' ')
+ if (ch == ' ') {
break;
+ }
result++;
}
return result;
@@ -204,8 +283,9 @@ int strEqual(const char *str1, const char *str2) {
// todo: there must be a standard function?!
int len1 = strlen(str1);
int len2 = strlen(str2);
- if (len1 != len2)
+ if (len1 != len2) {
return false;
+ }
for (int i = 0; i < len1; i++)
if (str1[i] != str2[i])
return false;
@@ -257,8 +337,6 @@ char *validateSecureLine(char *line) {
static char confirmation[200];
-void sendOutConfirmation(char *value, int i);
-
static bool handleConsoleLineInternal(char *line, int lineLength) {
int firstTokenLength = tokenLength(line);
@@ -271,7 +349,7 @@ static bool handleConsoleLineInternal(char *line, int lineLength) {
if (strEqual(line, current->token)) {
// invoke callback function by reference
(*current->callback)();
- return TRUE;
+ return true;
}
}
} else {
@@ -290,6 +368,12 @@ static bool handleConsoleLineInternal(char *line, int lineLength) {
return false;
}
+#if (EFI_PROD_CODE || EFI_SIMULATOR) || defined(__DOXYGEN__)
+static void sendOutConfirmation(const char *command, int length) {
+ scheduleMsg(&logging, "%s%d", command, length);
+}
+#endif
+
/**
* @brief This function takes care of one command line once we have it
*/
@@ -310,10 +394,11 @@ void handleConsoleLine(char *line) {
strcat(confirmation, line);
strcat(confirmation, ":");
- bool isKnownComman = handleConsoleLineInternal(line, lineLength);
-
- // confirmation happens after the command to avoid conflict with command own output
+#if EFI_PROD_CODE || EFI_SIMULATOR
sendOutConfirmation(confirmation, lineLength);
+#endif
+
+ bool isKnownComman = handleConsoleLineInternal(line, lineLength);
if (!isKnownComman)
helpCommand();
diff --git a/firmware/util/cli_registry.h b/firmware/util/cli_registry.h
index 3fef118027..2f06662389 100644
--- a/firmware/util/cli_registry.h
+++ b/firmware/util/cli_registry.h
@@ -14,14 +14,16 @@ extern "C"
{
#endif /* __cplusplus */
-#define CONSOLE_MAX_ACTIONS 96
+#define CONSOLE_MAX_ACTIONS 128
typedef enum {
NO_PARAMETER,
ONE_PARAMETER,
FLOAT_PARAMETER,
STRING_PARAMETER,
+ STRING2_PARAMETER,
STRING3_PARAMETER,
+ STRING5_PARAMETER,
TWO_INTS_PARAMETER,
FLOAT_FLOAT_PARAMETER
} ACTION_PARAMETER_TYPE;
@@ -34,7 +36,7 @@ typedef struct {
//void addDefaultConsoleActions(void);
//void handleActionWithParameter(TokenCallback *current, char *parameter);
-int tokenLength(char *msgp);
+int tokenLength(const char *msgp);
typedef void (*Void)(void);
typedef void (*VoidInt)(int);
@@ -42,7 +44,9 @@ typedef void (*VoidFloat)(float);
typedef void (*VoidFloatFloat)(float, float);
typedef void (*VoidIntInt)(int, int);
typedef void (*VoidCharPtr)(char *);
-typedef void (*VoidCharPtrCharPtrCharPtr)(char *, char *, char *);
+typedef void (*VoidCharPtrCharPtr)(const char *, const char *);
+typedef void (*VoidCharPtrCharPtrCharPtr)(const char *, const char *, const char *);
+typedef void (*VoidCharPtrCharPtrCharPtrCharPtrCharPtr)(const char *, const char *, const char *, const char *, const char *);
char *validateSecureLine(char *line);
int strEqual(const char *str1, const char *str2);
@@ -56,7 +60,9 @@ 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 addConsoleActionSS(const char *token, VoidCharPtrCharPtr callback);
void addConsoleActionSSS(const char *token, VoidCharPtrCharPtrCharPtr callback);
+void addConsoleActionSSSSS(const char *token, VoidCharPtrCharPtrCharPtrCharPtrCharPtr callback);
#ifdef __cplusplus
}
diff --git a/firmware/util/crc.c b/firmware/util/crc.c
index be044b7ea8..6f2cbe78ae 100644
--- a/firmware/util/crc.c
+++ b/firmware/util/crc.c
@@ -84,8 +84,9 @@ uint32_t crc32(const void *buf, uint32_t size) {
p = buf;
crc = crc ^ 0xFFFFFFFF;
- while (size--)
+ while (size--) {
crc = crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8);
+ }
return crc ^ 0xFFFFFFFF;
}
diff --git a/firmware/util/efilib.cpp b/firmware/util/efilib.cpp
index dd3f804626..8797d5f1d7 100644
--- a/firmware/util/efilib.cpp
+++ b/firmware/util/efilib.cpp
@@ -16,7 +16,7 @@
/**
* there is some BS related to isnan in MinGW, so let's have all the issues in one place
*/
-int cisnan(float f) {
+bool cisnan(float f) {
return *(((int*) (&f))) == 0x7FC00000;
}
@@ -49,8 +49,9 @@ int indexOf(const char *string, char ch) {
// todo: there should be a standard function for this
int len = strlen(string);
for (int i = 0; i < len; i++) {
- if (string[i] == ch)
+ if (string[i] == ch) {
return i;
+ }
}
return -1;
}
@@ -59,10 +60,12 @@ int indexOf(const char *string, char ch) {
int atoi(const char *string) {
// todo: use stdlib '#include '
int len = strlen(string);
- if (len == 0)
+ if (len == 0) {
return -ERROR_CODE;
- if (string[0] == '-')
+ }
+ if (string[0] == '-') {
return -atoi(string + 1);
+ }
int result = 0;
for (int i = 0; i < len; i++) {
@@ -93,9 +96,9 @@ static char *ltoa_internal(char *p, long num, unsigned radix) {
} while ((num /= radix) != 0);
i = (int) (p + _MAX_FILLER - q);
- do
+ do {
*p++ = *q++;
- while (--i);
+ } while (--i);
return p;
}
@@ -120,9 +123,15 @@ char* itoa10(char *p, int num) {
return itoa_signed(p, num, 10);
}
+#define EPS 0.0001
+
+bool isSameF(float v1, float v2) {
+ return absF(v1 - v2) < EPS;
+}
+
// string to float
float atoff(const char *param) {
- int totallen = strlen(param);
+ uint32_t totallen = strlen(param);
if (totallen > sizeof(todofixthismesswithcopy) - 1)
return (float) NAN;
strcpy(todofixthismesswithcopy, param);
@@ -144,7 +153,8 @@ float atoff(const char *param) {
int decimal = atoi(string);
float divider = 1.0;
// todo: reuse 'pow10' function which we have anyway
- for (int i = 0; i < decimalLen; i++)
+ for (int i = 0; i < decimalLen; i++) {
divider = divider * 10.0;
+ }
return integerPart + decimal / divider;
}
diff --git a/firmware/util/efilib.h b/firmware/util/efilib.h
index c3462f9f7a..6ffbebf8f9 100644
--- a/firmware/util/efilib.h
+++ b/firmware/util/efilib.h
@@ -8,7 +8,8 @@
#ifndef EFILIB_H_
#define EFILIB_H_
-#include "stdint.h"
+#include
+#include "global.h"
// number of milliseconds in one period of given frequency (per second)
#define frequency2periodMs(freq) ((1000.0f) / (freq))
@@ -16,7 +17,6 @@
// number of microseconds in one period of given frequency (per second)
#define frequency2periodUs(freq) ((1000000.0f) / (freq))
-
#ifndef FALSE
#define FALSE 0
#endif
@@ -34,7 +34,7 @@ extern "C"
int indexOf(const char *string, char ch);
float atoff(const char *string);
int atoi(const char *string);
-int cisnan(float f);
+bool cisnan(float f);
int absI(int32_t value);
float absF(float value);
@@ -43,6 +43,7 @@ int maxI(int i1, int i2);
int minI(int i1, int i2);
float maxF(float i1, float i2);
char* itoa10(char *p, int num);
+bool isSameF(float v1, float v2);
#ifdef __cplusplus
}
diff --git a/firmware/util/efilib2.cpp b/firmware/util/efilib2.cpp
index 4406aa9410..ce08bdd896 100644
--- a/firmware/util/efilib2.cpp
+++ b/firmware/util/efilib2.cpp
@@ -26,7 +26,7 @@ uint64_t Overflow64Counter::get(uint32_t value, int isPrimaryThread) {
// this method is lock-free, only one thread is allowed to commit state
// these are local copies for thread-safery
// todo: this is still not atomic, so technically not thread safe.
- int localValue = currentValue;
+ uint32_t localValue = currentValue;
uint64_t localBase = currentBase;
if (value < localValue) {
// new value less than previous value means there was an overflow in that 32 bit counter
diff --git a/firmware/util/histogram.c b/firmware/util/histogram.c
index 0a06a1341e..55a556bc23 100644
--- a/firmware/util/histogram.c
+++ b/firmware/util/histogram.c
@@ -82,8 +82,9 @@ int histogramGetIndex(int64_t value) {
* @brief Reset histogram_s to orignal state
*/
void initHistogram(histogram_s *h, const char *name) {
- if(strlen(name) > sizeof(h->name) - 1)
+ if(strlen(name) > sizeof(h->name) - 1) {
firmwareError("Histogram name [%s] too long", name);
+ }
strcpy(h->name, name);
h->total_value = 0;
h->total_count = 0;
@@ -111,16 +112,18 @@ int hsReport(histogram_s *h, int* report) {
int index = 0;
if (h->total_count <= 5) {
- for (int j = 0; j < BOUND_LENGTH; j++)
+ for (int j = 0; j < BOUND_LENGTH; j++) {
for (int k = 0; k < h->values[j]; k++) {
report[index++] = (bounds[j] + bounds[j + 1]) / 2;
}
+ }
return index;
}
int minIndex = 0;
- while (h->values[minIndex] == 0)
+ while (h->values[minIndex] == 0) {
minIndex++;
+ }
report[index++] = h->values[minIndex];
int64_t acc = 0;
@@ -128,10 +131,12 @@ int hsReport(histogram_s *h, int* report) {
for (int j = 0; j < 3; j++) {
int64_t k = confidence_bounds[j] * h->total_count;
// Always drop at least 1 'non-confident' sample...
- if (k == 0)
+ if (k == 0) {
k = 1;
- if (k == h->total_count)
+ }
+ if (k == h->total_count) {
k = h->total_count - 1;
+ }
// 'k' is desired number of samples.
while (acc + h->values[minIndex] < k)
acc += h->values[minIndex++];
diff --git a/firmware/util/util.mk b/firmware/util/util.mk
index e6125e9830..e9129d5415 100644
--- a/firmware/util/util.mk
+++ b/firmware/util/util.mk
@@ -3,8 +3,7 @@ UTILSRC = $(PROJECT_DIR)/util/data_buffer.c \
$(PROJECT_DIR)/util/listener_array.c \
$(PROJECT_DIR)/util/crc.c \
$(PROJECT_DIR)/util/histogram.c \
- $(PROJECT_DIR)/util/cli_registry.c \
- $(PROJECT_DIR)/util/wave_math.c
+ $(PROJECT_DIR)/util/cli_registry.c
UTILSRC_CPP = $(PROJECT_DIR)/util/cyclic_buffer.cpp \
$(PROJECT_DIR)/util/efilib.cpp \
diff --git a/firmware/util/wave_math.c b/firmware/util/wave_math.c
deleted file mode 100644
index d69ba560fb..0000000000
--- a/firmware/util/wave_math.c
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * wave_math.c
- *
- * @date Dec 25, 2012
- * @author Andrey Belomutskiy, (c) 2012-2014
- */
-
-#include "wave_math.h"
-
-//#define LOOPS_TIME(value, divider) (((int)((value) / (divider))) * (divider))
-
-//float floatmod(float value, float divider) {
-// // number of full cycles
-// int loopsNumber = (int)(value / divider);
-// // total time of full cycles
-// float loopsTime = loopsNumber * divider;
-//
-// return value - loopsTime;
-//}
-
-///**
-// * @param waveLen length of each wave, in ticks
-// */
-//int waveState(time_t start, time_t now, float waveLen, float leftSide,
-// float rightSide) {
-// /**
-// * number of ticks since start of thread
-// */
-// float time = now - start;
-// float mod = floatmod(time, waveLen);
-// return mod >= waveLen * leftSide && mod < waveLen * rightSide;
-//}
diff --git a/firmware/util/wave_math.h b/firmware/util/wave_math.h
deleted file mode 100644
index 24beddd01a..0000000000
--- a/firmware/util/wave_math.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * @file wave_math.h
- * TODO: this file needs a better name, maybe the methods shoould be moved somewhere?
- *
- *
- * @date Dec 25, 2012
- * @author Andrey Belomutskiy, (c) 2012-2014
- */
-
-#ifndef WAVE_MATH_H_
-#define WAVE_MATH_H_
-
-#include "global.h"
-
-// todo: looks like it's time to remove this file?
-
-//float floatmod(float value, float divider);
-//int waveState(time_t start, time_t now, float waveLen, float leftSide,
-// float rightSide);
-
-#endif /* WAVE_MATH_H_ */
diff --git a/java_console/.idea/misc.xml b/java_console/.idea/misc.xml
index 28737110d7..14c5327fa4 100644
--- a/java_console/.idea/misc.xml
+++ b/java_console/.idea/misc.xml
@@ -6,7 +6,7 @@
http://www.w3.org/1999/xhtml
-
+
diff --git a/java_console/.idea/workspace.xml b/java_console/.idea/workspace.xml
index abbbae189a..24eb8aa4e6 100644
--- a/java_console/.idea/workspace.xml
+++ b/java_console/.idea/workspace.xml
@@ -1,18 +1,24 @@
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+
@@ -27,14 +33,16 @@
-
+
+
+
@@ -49,7 +57,9 @@
+
+
@@ -59,27 +69,20 @@
+
+
-
+
-
-
-
-
-
-
-
-
-
-
+
@@ -87,19 +90,10 @@
-
-
+
+
-
-
-
-
-
-
-
-
-
-
+
@@ -107,10 +101,29 @@
-
-
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -118,48 +131,32 @@
-
-
+
+
-
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
+
+
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
+
@@ -190,14 +187,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
@@ -220,23 +243,285 @@
-
-
+
+
-
-
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -266,6 +551,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -277,7 +592,23 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -287,26 +618,164 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
-
-
-
+
+
+
@@ -315,7 +784,7 @@
-
+
@@ -330,17 +799,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
-
+
@@ -357,28 +838,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -401,16 +860,103 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -418,29 +964,7 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
@@ -467,12 +991,20 @@
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -486,12 +1018,7 @@
-
-
-
-
-
-
+
@@ -511,25 +1038,76 @@
-
-
-
-
-
-
+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
localhost
5050
-
+
@@ -539,7 +1117,6 @@
-
@@ -553,28 +1130,36 @@
-
-
+
+
@@ -638,85 +1223,177 @@
1358212757093
1358212757093
-
+
+ 1395244613176
+ 1395244613176
+
+
+ 1395249535113
+ 1395249535113
+
+
+ 1395250201104
+ 1395250201104
+
+
+ 1395250224103
+ 1395250224103
+
+
+ 1395251870107
+ 1395251870108
+
+
+ 1395255022112
+ 1395255022112
+
+
+ 1395255576161
+ 1395255576161
+
+
+ 1395255938112
+ 1395255938112
+
+
+ 1395256696106
+ 1395256696106
+
+
+ 1395257239103
+ 1395257239103
+
+
+ 1395258701114
+ 1395258701114
+
+
+ 1395268614105
+ 1395268614105
+
+
+ 1395406238343
+ 1395406238343
+
+
+ 1395406395107
+ 1395406395107
+
+
+ 1395406782105
+ 1395406782105
+
+
+ 1395408511110
+ 1395408511110
+
+
+ 1395408695103
+ 1395408695103
+
+
+ 1395675577187
+ 1395675577187
+
+
+ 1395675759106
+ 1395675759106
+
+
+ 1395677644104
+ 1395677644104
+
+
+ 1395692826123
+ 1395692826123
+
+
+ 1395693273111
+ 1395693273111
+
+
+ 1395693503113
+ 1395693503113
+
+
+ 1395772919110
+ 1395772919110
+
+
+ 1395773841112
+ 1395773841112
+
+
+ 1395779239117
+ 1395779239117
+
+
+ 1395779802104
+ 1395779802104
+
+
+ 1395779923103
+ 1395779923103
+
+
+ 1395780055115
+ 1395780055115
+
+
+ 1395846716220
+ 1395846716220
+
+
+ 1398525852184
+ 1398525852184
+
+
-
-
+
+
+
-
+
-
-
-
+
+
+
+
-
-
+
+
-
+
-
-
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -729,6 +1406,15 @@
+
+
+
+
+
+
+
+
+
@@ -736,118 +1422,329 @@
+
+
+
+
+
+
+
+
+
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
+
-
-
-
-
-
-
-
-
+
-
+
-
-
-
-
-
-
-
-
+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -924,7 +1821,7 @@
- surfaceplotter
+ SteelSeries
diff --git a/java_console/autotest/src/com/rusefi/AutoTest.java b/java_console/autotest/src/com/rusefi/AutoTest.java
index 454f507d53..829417e11d 100644
--- a/java_console/autotest/src/com/rusefi/AutoTest.java
+++ b/java_console/autotest/src/com/rusefi/AutoTest.java
@@ -7,6 +7,7 @@ import com.rusefi.waves.WaveChart;
import static com.rusefi.IoUtil.nextChart;
import static com.rusefi.IoUtil.sendCommand;
import static com.rusefi.TestingUtils.assertNull;
+import static com.rusefi.TestingUtils.assertTrue;
import static com.rusefi.TestingUtils.assertWave;
/**
@@ -21,7 +22,6 @@ public class AutoTest {
private static void mainTestBody() {
testFordAspire();
- sendCommand("set_engine_type 2");
testDodgeNeon();
sendCommand("set_engine_type 7");
@@ -32,6 +32,7 @@ public class AutoTest {
}
private static void testDodgeNeon() {
+ sendCommand("set_engine_type 2");
WaveChart chart;
IoUtil.changeRpm(2000);
sendCommand("set_ignition_mode 1");
@@ -49,6 +50,13 @@ public class AutoTest {
assertWave(msg, chart, WaveChart.SPARK_2, 0.13333, x);
assertWave(msg, chart, WaveChart.SPARK_1, 0.13333, x + 180);
assertWave(msg, chart, WaveChart.SPARK_3, 0.13333, x + 360);
+
+ // switching to Speed Density
+ sendCommand("set_mock_map_voltage 1");
+ sendCommand("set_algorithm 3");
+ chart = nextChart();
+ x = 110;
+ assertWave(msg, chart, WaveChart.INJECTOR_4, 0.42966, x + 540);
}
private static void testFordFiesta() {
@@ -67,18 +75,26 @@ public class AutoTest {
IoUtil.changeRpm(2000);
chart = nextChart();
+ String msg = "ford 6";
+
int x = 7;
- assertWave("ford 6", chart, WaveChart.SPARK_1, 0.01666, x, x + 120, x + 240, x + 360, x + 480, x + 600);
+ assertWave(msg, chart, WaveChart.SPARK_1, 0.01666, x, x + 120, x + 240, x + 360, x + 480, x + 600);
+
+ assertNull(msg, chart.get(WaveChart.TRIGGER_2));
+ sendCommand("set_trigger_type 1"); // TT_FORD_ASPIRE
+ chart = nextChart();
+ assertTrue(msg, chart.get(WaveChart.TRIGGER_2) != null);
}
private static void testFordAspire() {
+ String msg = "Aspire";
WaveChart chart;
// todo: interesting changeRpm(100);
sendCommand("set_cranking_rpm 500");
IoUtil.changeRpm(200);
- float x;
+ double x;
chart = nextChart();
x = 55;
assertWave("aspire default cranking ", chart, WaveChart.SPARK_1, 0.1944, x, x + 180, x + 360, x + 540);
@@ -133,8 +149,8 @@ public class AutoTest {
sendCommand("set_fuel_map 2000 4 15.66");
sendCommand("set_fuel_map 2200 4.2 15.66");
sendCommand("set_fuel_map 2000 4.2 15.66");
- // fake 2 means 4 on the gauge because of the divider. should we simplify this?
- sendCommand("set_fake_maf_voltage 2");
+ // mock 2 means 4 on the gauge because of the divider. should we simplify this?
+ sendCommand("set_mock_maf_voltage 2");
sendCommand("set_global_trigger_offset_angle 175");
chart = nextChart();
@@ -162,6 +178,21 @@ public class AutoTest {
chart = nextChart();
x = 59;
assertWave(chart, WaveChart.SPARK_2, 0.133, x);
+
+
+ // switching to Speed Density
+ sendCommand("set_mock_map_voltage 1");
+ sendCommand("set_algorithm 3");
+ chart = nextChart();
+ x = 8.88;
+ assertWave(msg, chart, WaveChart.INJECTOR_1, 0.296666, x + 180);
+ assertWave(msg, chart, WaveChart.INJECTOR_2, 0.296666, x);
+ assertWave(msg, chart, WaveChart.INJECTOR_4, 0.296666, x + 540);
+
+ // above hard limit
+ IoUtil.changeRpm(10000);
+ chart = nextChart();
+ assertNull("hard limit check", chart.get(WaveChart.INJECTOR_1));
}
public static void main(String[] args) throws InterruptedException {
diff --git a/java_console/autotest/src/com/rusefi/ExecHelper.java b/java_console/autotest/src/com/rusefi/ExecHelper.java
index 845195fd0e..073672975c 100644
--- a/java_console/autotest/src/com/rusefi/ExecHelper.java
+++ b/java_console/autotest/src/com/rusefi/ExecHelper.java
@@ -15,6 +15,9 @@ public class ExecHelper {
private static final String SIMULATOR_COMMAND = "../win32_functional_tests/build/rusefi_simulator.exe";
static Process simulatorProcess;
+ /**
+ * This is currently used by auto-tests only. Todo: reuse same code for UI-launched simulator?
+ */
private static void runSimulator() {
Thread.currentThread().setName("Main simulation");
diff --git a/java_console/build.xml b/java_console/build.xml
index 89bd64d030..8528913833 100644
--- a/java_console/build.xml
+++ b/java_console/build.xml
@@ -6,7 +6,7 @@
-
+
diff --git a/java_console/io/src/com/rusefi/io/CommandQueue.java b/java_console/io/src/com/rusefi/io/CommandQueue.java
index 860eac1acf..fdf2d93a3a 100644
--- a/java_console/io/src/com/rusefi/io/CommandQueue.java
+++ b/java_console/io/src/com/rusefi/io/CommandQueue.java
@@ -1,11 +1,16 @@
package com.rusefi.io;
import com.irnems.core.MessagesCentral;
+import com.rusefi.io.tcp.TcpConnector;
import org.jetbrains.annotations.NotNull;
+import java.util.ArrayList;
+import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
+import static com.rusefi.io.tcp.TcpConnector.parseIntWithReason;
+
/**
* This class keeps re-sending a command till a proper confirmation is received
*
@@ -21,6 +26,7 @@ public class CommandQueue {
private static final CommandQueue instance = new CommandQueue();
private final BlockingQueue pendingCommands = new LinkedBlockingQueue();
+ private final List commandListeners = new ArrayList<>();
private final Runnable runnable = new Runnable() {
@SuppressWarnings("InfiniteLoopStatement")
@@ -38,6 +44,10 @@ public class CommandQueue {
}
};
+ public void addListener(CommandQueueListener listener) {
+ commandListeners.add(listener);
+ }
+
/**
* this method is always invoked on 'Commands Queue' thread {@link #runnable}
*
@@ -94,7 +104,7 @@ public class CommandQueue {
mc.postMessage(CommandQueue.class, "Broken confirmation: " + confirmation);
return;
}
- int length = Integer.parseInt(confirmation.substring(index + 1));
+ int length = parseIntWithReason(confirmation.substring(index + 1), "CQ confirmation");
if (length != index) {
mc.postMessage(CommandQueue.class, "Broken confirmation length: " + confirmation);
return;
@@ -122,6 +132,10 @@ public class CommandQueue {
* Non-blocking command request
*/
public void write(String command, int timeout, InvocationConfirmationListener listener) {
+
+ for (CommandQueueListener cql : commandListeners)
+ cql.onCommand(command);
+
pendingCommands.add(new MethodInvocation(command, timeout, listener));
}
@@ -144,4 +158,8 @@ public class CommandQueue {
return timeout;
}
}
+
+ public interface CommandQueueListener {
+ void onCommand(String command);
+ }
}
diff --git a/java_console/io/src/com/rusefi/io/tcp/TcpConnector.java b/java_console/io/src/com/rusefi/io/tcp/TcpConnector.java
index 358759bb8f..e76d7b0e87 100644
--- a/java_console/io/src/com/rusefi/io/tcp/TcpConnector.java
+++ b/java_console/io/src/com/rusefi/io/tcp/TcpConnector.java
@@ -21,20 +21,41 @@ public class TcpConnector implements LinkConnector {
private boolean withError;
public TcpConnector(String port) {
- this.port = getTcpPort(port);
+ try {
+ this.port = getTcpPort(port);
+ } catch (InvalidTcpPort e) {
+ throw new IllegalStateException("Unexpected", e);
+ }
}
public static boolean isTcpPort(String port) {
try {
getTcpPort(port);
return true;
- } catch (NumberFormatException e) {
+ } catch (InvalidTcpPort e) {
return false;
}
}
- public static int getTcpPort(String port) {
- return Integer.parseInt(port);
+ static class InvalidTcpPort extends Exception {
+
+ }
+
+
+ public static int getTcpPort(String port) throws InvalidTcpPort {
+ try {
+ return Integer.parseInt(port);
+ } catch (NumberFormatException e) {
+ throw new InvalidTcpPort();
+ }
+ }
+
+ public static int parseIntWithReason(String number, String reason) {
+ try {
+ return Integer.parseInt(number);
+ } catch (NumberFormatException e) {
+ throw new IllegalArgumentException("Unexpected [" + number + "] for " + reason, e);
+ }
}
/**
@@ -96,14 +117,18 @@ public class TcpConnector implements LinkConnector {
}
}
- public static Collection extends String> getAvailablePorts() {
+ public static Collection getAvailablePorts() {
+ return isTcpPortOpened() ? Collections.singletonList("" + DEFAULT_PORT) : Collections.emptyList();
+ }
+
+ public static boolean isTcpPortOpened() {
try {
Socket s = new Socket(LOCALHOST, DEFAULT_PORT);
s.close();
- return Collections.singletonList("" + DEFAULT_PORT);
+ return true;
} catch (IOException e) {
System.out.println("Connection refused in getAvailablePorts(): simulator not running");
- return Collections.emptyList();
+ return false;
}
}
}
diff --git a/java_console/models/src/com/irnems/core/MessagesCentral.java b/java_console/models/src/com/irnems/core/MessagesCentral.java
index 8ef06e6c99..c23e564b02 100644
--- a/java_console/models/src/com/irnems/core/MessagesCentral.java
+++ b/java_console/models/src/com/irnems/core/MessagesCentral.java
@@ -7,6 +7,8 @@ import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
/**
+ * Messages from the firmware and UI panels which want to display them
+ *
* Date: 4/27/13
* (c) Andrey Belomutskiy
*/
diff --git a/java_console/models/src/com/irnems/models/MafValue.java b/java_console/models/src/com/irnems/models/MafValue.java
index 3d52b63a9d..01cf1834c3 100644
--- a/java_console/models/src/com/irnems/models/MafValue.java
+++ b/java_console/models/src/com/irnems/models/MafValue.java
@@ -1,5 +1,7 @@
package com.irnems.models;
+import com.rusefi.io.tcp.TcpConnector;
+
/**
* @author Andrey Belomutskiy
* 1/29/13
@@ -17,7 +19,7 @@ public class MafValue {
}
public static MafValue valueOf(String value) {
- return new MafValue(Integer.parseInt(value));
+ return new MafValue(TcpConnector.parseIntWithReason(value, "MAF value"));
}
@Override
diff --git a/java_console/models/src/com/irnems/models/Range.java b/java_console/models/src/com/irnems/models/Range.java
index 855feb952a..0edca6c285 100644
--- a/java_console/models/src/com/irnems/models/Range.java
+++ b/java_console/models/src/com/irnems/models/Range.java
@@ -8,6 +8,10 @@ public class Range {
private final float min;
private final float max;
+ public Range(double min, double max) {
+ this((float) min, (float) max);
+ }
+
public Range(float min, float max) {
this.min = min;
this.max = max;
diff --git a/java_console/models/src/com/irnems/waves/ZoomProvider.java b/java_console/models/src/com/irnems/waves/ZoomProvider.java
index 17ecf5b31b..0d0bac0ceb 100644
--- a/java_console/models/src/com/irnems/waves/ZoomProvider.java
+++ b/java_console/models/src/com/irnems/waves/ZoomProvider.java
@@ -10,6 +10,10 @@ public interface ZoomProvider {
public double getZoomValue() {
return 1;
}
+
+ public String toString() {
+ return "default";
+ }
};
double getZoomValue();
diff --git a/java_console/models/src/com/rusefi/waves/RevolutionLog.java b/java_console/models/src/com/rusefi/waves/RevolutionLog.java
index 142fc61022..a982aa5de3 100644
--- a/java_console/models/src/com/rusefi/waves/RevolutionLog.java
+++ b/java_console/models/src/com/rusefi/waves/RevolutionLog.java
@@ -1,7 +1,11 @@
package com.rusefi.waves;
+import com.rusefi.io.tcp.TcpConnector;
+
import java.util.*;
+import static com.rusefi.io.tcp.TcpConnector.*;
+
/**
* 1/11/14.
* (c) Andrey Belomutskiy
@@ -21,8 +25,8 @@ public class RevolutionLog {
String[] r = revolutions.toString().split("!");
for (int i = 0; i < r.length - 1; i += 2) {
- int rpm = Integer.parseInt(r[i]);
- int time = Integer.parseInt(r[i + 1]);
+ int rpm = parseIntWithReason(r[i], "RL rpm");
+ int time = parseIntWithReason(r[i + 1], "RL time");
time2rpm.put(time, rpm);
}
return new RevolutionLog(time2rpm);
diff --git a/java_console/models/src/com/rusefi/waves/WaveChart.java b/java_console/models/src/com/rusefi/waves/WaveChart.java
index 23ab5a0d5e..b970c07f5b 100644
--- a/java_console/models/src/com/rusefi/waves/WaveChart.java
+++ b/java_console/models/src/com/rusefi/waves/WaveChart.java
@@ -26,6 +26,9 @@ public class WaveChart {
public static final String SPARK_3 = "spa3";
public static final String SPARK_4 = "spa4";
+ public static final String TRIGGER_1 = "c1";
+ public static final String TRIGGER_2 = "c2";
+
public final Map map;
public WaveChart(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 a1afd97cae..9742402168 100644
--- a/java_console/models/src/com/rusefi/waves/WaveReport.java
+++ b/java_console/models/src/com/rusefi/waves/WaveReport.java
@@ -2,14 +2,18 @@ package com.rusefi.waves;
import com.irnems.waves.TimeAxisTranslator;
import com.irnems.waves.ZoomProvider;
+import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
+ * A model of a digital signal represented as a sequence of {@link UpDown}
+ *
* Date: 6/23/13
* (c) Andrey Belomutskiy
+ *
* @see com.rusefi.AnalogChartPanel.AnalogChart
*/
public class WaveReport implements TimeAxisTranslator {
@@ -23,7 +27,7 @@ public class WaveReport implements TimeAxisTranslator {
private static final String WC_DOWN = "d";
private static final String WC_UP = "u";
- List list;
+ private final List list;
private int maxTime;
/**
* min timestamp on this chart, in systicks
@@ -35,11 +39,11 @@ public class WaveReport implements TimeAxisTranslator {
}
public WaveReport(List list) {
- if (list.isEmpty())
- throw new IllegalStateException("empty");
this.list = list;
- minTime = list.get(0).upTime;
- maxTime = list.get(list.size() - 1).downTime;
+ if (!list.isEmpty()) {
+ minTime = list.get(0).upTime;
+ maxTime = list.get(list.size() - 1).downTime;
+ }
}
public static boolean isCloseEnough(double v1, double v2) {
@@ -63,6 +67,7 @@ public class WaveReport implements TimeAxisTranslator {
return minTime;
}
+ @NotNull
public static List parse(String report) {
String[] array = report.split("!");
// if (array.length % 4 != 0)
diff --git a/java_console/ui/src/com/irnems/Launcher.java b/java_console/ui/src/com/irnems/Launcher.java
index fadb8202a8..a6d49212fd 100644
--- a/java_console/ui/src/com/irnems/Launcher.java
+++ b/java_console/ui/src/com/irnems/Launcher.java
@@ -2,8 +2,7 @@ package com.irnems;
import com.irnems.core.EngineState;
import com.irnems.core.MessagesCentral;
-import com.rusefi.AnalogChartPanel;
-import com.rusefi.PortLookupFrame;
+import com.rusefi.*;
import com.rusefi.io.LinkManager;
import com.rusefi.ui.*;
import jssc.SerialPortList;
@@ -20,8 +19,8 @@ import javax.swing.*;
* @see WavePanel
*/
public class Launcher extends FrameHelper {
- private static final Object CONSOLE_VERSION = "20140709";
- public static final boolean SHOW_STIMULATOR = false;
+ public static final int CONSOLE_VERSION = 20140820;
+ public static final boolean SHOW_STIMULATOR = true;
public Launcher(String port) {
FileLog.MAIN.start();
@@ -34,15 +33,17 @@ public class Launcher extends FrameHelper {
RpmPanel rpmPanel = new RpmPanel();
tabbedPane.addTab("Main", rpmPanel.createRpmPanel());
- tabbedPane.addTab("Gauges", new GaugesPanel());
- tabbedPane.addTab("Digital Sniffer", WavePanel.getInstance());
+ tabbedPane.addTab("Gauges", new GaugesPanel().getContent());
+ tabbedPane.addTab("Digital Sniffer", WavePanel.getInstance().getPanel());
tabbedPane.addTab("Analog Sniffer", new AnalogChartPanel());
// tabbedPane.addTab("ADC", new AdcPanel(new BooleanInputsModel()).createAdcPanel());
- if (SHOW_STIMULATOR)
- tabbedPane.add("Emulation Map", EcuStimulator.panel);
+ if (SHOW_STIMULATOR) {
+ EcuStimulator stimulator = EcuStimulator.getInstance();
+ tabbedPane.add("Emulation Map", stimulator.getPanel());
+ }
// tabbedPane.addTab("live map adjustment", new Live3DReport().getControl());
- tabbedPane.add("MessagesCentral", new MsgPanel(true));
+ tabbedPane.add("MessagesCentral", new MsgPanel(true).getContent());
tabbedPane.add("Log Viewer", new LogViewer());
@@ -64,8 +65,9 @@ public class Launcher extends FrameHelper {
LinkManager.engineState.registerStringValueAction("rusEfiVersion", new EngineState.ValueCallback() {
@Override
- public void onUpdate(String value) {
- setTitle(value);
+ public void onUpdate(String firmwareVersion) {
+ setTitle(firmwareVersion);
+ VersionChecker.getInstance().onFirmwareVersion(firmwareVersion);
}
});
}
@@ -80,11 +82,13 @@ public class Launcher extends FrameHelper {
/**
* looks like reconnectTimer in {@link RpmPanel} keeps AWT alive. Simplest solution would be to 'exit'
*/
+ SimulatorHelper.onWindowClosed();
System.exit(0);
}
public static void main(final String[] args) throws Exception {
Thread.setDefaultUncaughtExceptionHandler(new DefaultExceptionHandler());
+ VersionChecker.start();
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
awtCode(args);
diff --git a/java_console/ui/src/com/irnems/LogViewer.java b/java_console/ui/src/com/irnems/LogViewer.java
index d71bb937de..c9d48cb365 100644
--- a/java_console/ui/src/com/irnems/LogViewer.java
+++ b/java_console/ui/src/com/irnems/LogViewer.java
@@ -3,7 +3,7 @@ package com.irnems;
import com.irnems.core.EngineState;
import com.irnems.file.FileUtils;
import com.rusefi.ui.WavePanel;
-import com.irnems.ui.widgets.UpDownImage;
+import com.rusefi.ui.widgets.UpDownImage;
import com.rusefi.FIleItem;
import com.rusefi.io.LinkManager;
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 1d86c8f688..3e7815521d 100644
--- a/java_console/ui/src/com/irnems/ui/test/UpDownSandbox.java
+++ b/java_console/ui/src/com/irnems/ui/test/UpDownSandbox.java
@@ -3,7 +3,7 @@ package com.irnems.ui.test;
import com.rusefi.waves.WaveReport;
import com.irnems.core.test.WaveReportTest;
import com.rusefi.ui.FrameHelper;
-import com.irnems.ui.widgets.UpDownImage;
+import com.rusefi.ui.widgets.UpDownImage;
import javax.swing.*;
import java.lang.reflect.InvocationTargetException;
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 8611da9ee3..941c82f4c7 100644
--- a/java_console/ui/src/com/irnems/ui/test/WavePanelSandbox.java
+++ b/java_console/ui/src/com/irnems/ui/test/WavePanelSandbox.java
@@ -19,7 +19,7 @@ public class WavePanelSandbox extends FrameHelper {
wp.displayChart("Injector 1!down!55013038!crank!up!55013444!crank!down!55013781!Injector 3!up!55013789!Injector 3!down!55013969!crank2!up!55014065!crank!up!55014358!crank!down!55014706!input1 A8!up!55014730!Injector 4!up!55014734!Injector 4!down!55014933!input1 A8!down!55014941!crank!up!55015298!crank!down!55015638!Injector 2!up!55015644!Injector 2!down!55015823!crank2!down!55015932!crank!up!55016223!crank!down!55016566!Injector 1!up!55016574!Injector 1!down!55016753!crank!up!55017148!crank!down!55017494!Injector 3!up!55017499!Injector 3!down!55017679!crank2!up!55017777!crank!up!55018070!crank!down!55018406!Injector 4!input1 A8!up!55018414!up!55018416!input1 A8!down!55018439!input1 A8!up!55018439!Injector 4!down!55018593!input1 A8!down!55018600!crank!up!55018989!crank!down!55019330!Injector 2!up!55019338!Injector 2!down!55019517!crank2!down!55019618!crank!up!55019909!crank!down!55020246!Injector 1!up!55020251!Injector 1!down!55020430!crank!up!55020827!crank!down!55021171!Injector 3!up!55021179!Injector 3!down!55021358!crank2!up!55021453!crank!up!55021747!crank!down!55022084!Injector 4input1 A8!up!55022089!!up!55022093!Injector 4!down!55022270!input1 A8!down!55022276!input1 A8!up!55022276!input1 A8!down!55022276!crank!up!55022666!crank!down!55023006!Injector 2!up!55023011!Injector 2!down!55023191!crank2!down!55023294!crank!up!55023584!crank!down!55023928!Injector 1!up!55023932!Injector 1!down!55024109!crank!up!55024507!crank!down!55024846!Injector 3!up!55024871!Injector 3!down!55025072!crank2!up!55025138!crank!up!55025440!crank!down!55025780!Injector 4input1 A8!up!55025785!!up!55025791!input1 A8!down!55025923!input1 A8!up!55025923!Injector 4!down!55025970!input1 A8!down!55025976!input1 A8!up!55025976!crank!up!55026355!crank!down!55026690!Injector 2!up!55026696!Injector 2!down!55026874!crank2!down!55026979!crank!up!55027268!crank!down!55027611!Injector 1!up!55027619!Injector 1!down!55027800!crank!up!55028186!crank!down!55028520!,");
- showFrame(wp);
+ showFrame(wp.getPanel());
}
public static void main(String[] args) throws InvocationTargetException, InterruptedException {
diff --git a/java_console/ui/src/com/rusefi/AnalogChartPanel.java b/java_console/ui/src/com/rusefi/AnalogChartPanel.java
index 7662792447..f32f7c7784 100644
--- a/java_console/ui/src/com/rusefi/AnalogChartPanel.java
+++ b/java_console/ui/src/com/rusefi/AnalogChartPanel.java
@@ -5,8 +5,8 @@ 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.ui.widgets.URLLabel;
+import com.rusefi.ui.widgets.UpDownImage;
import com.rusefi.io.LinkManager;
import javax.swing.*;
diff --git a/java_console/ui/src/com/irnems/EcuStimulator.java b/java_console/ui/src/com/rusefi/EcuStimulator.java
similarity index 52%
rename from java_console/ui/src/com/irnems/EcuStimulator.java
rename to java_console/ui/src/com/rusefi/EcuStimulator.java
index 4602886f2e..cec8bea91b 100644
--- a/java_console/ui/src/com/irnems/EcuStimulator.java
+++ b/java_console/ui/src/com/rusefi/EcuStimulator.java
@@ -1,5 +1,6 @@
-package com.irnems;
+package com.rusefi;
+import com.irnems.FileLog;
import com.irnems.core.MessagesCentral;
import com.irnems.core.Sensor;
import com.irnems.core.EngineTimeListener;
@@ -8,14 +9,18 @@ import com.irnems.file.TableGenerator;
import com.irnems.models.Point3D;
import com.irnems.models.Range;
import com.irnems.models.XYData;
+import com.rusefi.test.EcuStimulatorSandbox;
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.ui.widgets.PotCommand;
+import com.rusefi.ui.widgets.RpmCommand;
import com.rusefi.io.LinkManager;
import net.ericaro.surfaceplotter.DefaultSurfaceModel;
import javax.swing.*;
+import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
import java.io.*;
import java.util.ArrayList;
import java.util.Collections;
@@ -25,24 +30,24 @@ import java.util.concurrent.CountDownLatch;
/**
* Date: 3/24/13
* (c) Andrey Belomutskiy
+ *
+ * @see EcuStimulatorSandbox
*/
public class EcuStimulator {
// private static final String TITLE = "Spark Advance";
private static final String TITLE = "Fuel Table";
- private static final String D = ",";
+ private static final String DELIMITER = ",";
private static final long SLEEP_TIME = 300;
- private static final float MAF_MIN = 1.2f;
- private static final float MAF_MAX = 4.5f;
- private static final double MAF_INCREMENT = 0.1;
+ private static final double EL_INCREMENT = 0.1;
private static final int RPM_MIN = 400;
private static final int RPM_MAX = 6000;
private static final int RPM_INCREMENT = 250;
private static final Sensor DWELL_SENSOR = Sensor.DWELL0;
- private static final String TABLE_FILE_NAME = "table" + RPM_INCREMENT + "_" + MAF_INCREMENT + ".csv";
+ private static final String CSV_FILE_NAME = "table" + RPM_INCREMENT + "_" + EL_INCREMENT + ".csv";
private static final int MEASURES = 7;
// private static final String C_FILE_NAME = "advance_map.c";
@@ -51,21 +56,40 @@ public class EcuStimulator {
private static final String C_PREFIX = "fuel_";
public static Range RPM_RANGE = new Range(0, RPM_MAX); // x-coord
- static Range mafRange = new Range(MAF_MIN, MAF_MAX); // y-coord
- private static XYData data = new XYData();
- private static DefaultSurfaceModel model = ChartHelper.createDefaultSurfaceModel(data, RPM_RANGE, mafRange);
- public static JPanel panel = ChartHelper.create3DControl(data, model, TITLE);
+ private StimulationInputs inputs = new StimulationInputs(this);
+ //
+ private XYData data = new XYData();
+ private DefaultSurfaceModel model = ChartHelper.createDefaultSurfaceModel(data, RPM_RANGE, new Range(1, 5));
- public static void buildTable() {
+ private final JPanel content = new JPanel(new BorderLayout());
+
+ private JPanel panel = ChartHelper.create3DControl(data, model, TITLE);
+
+ private static EcuStimulator instance = new EcuStimulator();
+
+ private EcuStimulator() {
+ content.add(panel, BorderLayout.CENTER);
+ content.add(inputs.getContent(), BorderLayout.WEST);
+ }
+
+ public static EcuStimulator getInstance() {
+ return instance;
+ }
+
+ public JPanel getPanel() {
+ return content;
+ }
+
+ public void buildTable() {
data.clear();
// setPotVoltage(2.2, Sensor.MAF);
// if (1 == 1)
// return;
- final BufferedWriter bw;
+ final BufferedWriter csv;
try {
- bw = new BufferedWriter(new FileWriter(TABLE_FILE_NAME));
+ csv = new BufferedWriter(new FileWriter(CSV_FILE_NAME));
} catch (IOException e) {
throw new IllegalStateException(e);
}
@@ -77,26 +101,26 @@ public class EcuStimulator {
model.plot().execute();
String msg = putValue("rpm", rpm) +
- putValue("maf", maf) +
+ putValue("engine_load", maf) +
putValue("advance", advance) +
putValue("dwell", dwell);
MessagesCentral.getInstance().postMessage(EcuStimulator.class, msg);
try {
- bw.write(msg + "\r\n");
- bw.flush();
+ csv.write(msg + "\r\n");
+ csv.flush();
} catch (IOException e) {
throw new IllegalStateException(e);
}
}
};
- buildTable(bw, listener, DWELL_SENSOR);
+ ChartHelper.setYRange(new Range(inputs.getEngineLoadMin(), inputs.getEngineLoadMax()), model);
+
+ buildTable(listener, DWELL_SENSOR);
try {
- bw.close();
- } catch (FileNotFoundException e) {
- throw new IllegalStateException(e);
+ csv.close();
} catch (IOException e) {
throw new IllegalStateException(e);
}
@@ -104,45 +128,27 @@ public class EcuStimulator {
TableGenerator.writeAsC(data, C_PREFIX, C_FILE_NAME);
}
- private static void buildTable(BufferedWriter bw, ResultListener listener, Sensor dwellSensor) {
+ private void buildTable(ResultListener listener, Sensor dwellSensor) {
for (int rpm = RPM_MIN; rpm <= RPM_MAX; rpm += RPM_INCREMENT)
runSimulation(rpm, listener, dwellSensor);
}
- private static void runSimulation(int rpm, ResultListener resultListener, final Sensor dwellSensor) {
- for (double maf = MAF_MIN; maf <= MAF_MAX; maf += MAF_INCREMENT) {
+ private void runSimulation(int rpm, ResultListener resultListener, final Sensor dwellSensor) {
+ for (double engineLoad = inputs.getEngineLoadMin(); engineLoad <= inputs.getEngineLoadMax(); engineLoad += EL_INCREMENT) {
//setPotVoltage(maf, Sensor.MAF);
- setPotVoltage(maf, null);
+ setPotVoltage(engineLoad, null);
setRpm(rpm);
+ /**
+ * Let's give the firmware some time to react
+ */
sleepRuntime(SLEEP_TIME);
/**
* We are making a number of measurements and then we take the middle one
*/
- final List dwells = new ArrayList(MEASURES);
- final List advances = new ArrayList(MEASURES);
-
- final CountDownLatch latch = new CountDownLatch(MEASURES);
-
- EngineTimeListener listener = new EngineTimeListener() {
- @Override
- public void onTime(double time) {
- if (latch.getCount() == 0)
- return;
- double dwell = getValue(dwellSensor);
- double advance = 0;//getValue(Sensor.ADVANCE0);
- dwells.add(dwell);
- advances.add(advance);
- latch.countDown();
- }
- };
- LinkManager.engineState.timeListeners.add(listener);
- try {
- latch.await();
- } catch (InterruptedException e) {
- throw new IllegalStateException(e);
- }
- LinkManager.engineState.timeListeners.remove(listener);
+ MultipleMeasurements r = waitForMultipleResults(dwellSensor);
+ List dwells = r.getDwells();
+ List advances = r.getAdvances();
// sorting measurements, taking middle value
Collections.sort(dwells);
@@ -155,16 +161,15 @@ public class EcuStimulator {
double dwell = dwells.get(MEASURES / 2);
double advance = advances.get(MEASURES / 2);
- if (dwell > 40) {
- throw new UnsupportedOperationException();
- }
+ if (dwell > 40)
+ throw new IllegalStateException("Unexpected value, how comes? " + dwell);
- log("Stimulator result: " + rpm + "@" + maf + ": " + dwell);
+ log("Stimulator result: " + rpm + "@" + engineLoad + ": " + dwell);
// double dwell = Launcher.getAdcModel().getValue(Sensor.DWELL0);
// double advance = Launcher.getAdcModel().getValue(Sensor.ADVANCE);
- resultListener.onResult(rpm, maf, (float) advance, dwell);
+ resultListener.onResult(rpm, engineLoad, (float) advance, dwell);
}
}
@@ -195,8 +200,8 @@ public class EcuStimulator {
if (sensor != null)
log("Current targetVoltage: " + getValue(sensor) + ", setting " + targetVoltage);
int attempt = 0;
- //double vRef = SensorCentral.getInstance().getValue(Sensor.VREF) * PotCommand.VOLTAGE_CORRECTION;
- double vRef = 4.7;
+ double vRef = getVRef();
+
int resistance = PotCommand.getPotResistance(targetVoltage, vRef);
if (resistance <= 0) {
log("Invalid resistance " + resistance + ". Invalid targetVoltage " + targetVoltage + "?");
@@ -219,20 +224,97 @@ public class EcuStimulator {
}
}
+ private static double getVRef() {
+ // todo: make this adjustable via the UI
+ //double vRef = SensorCentral.getInstance().getValue(Sensor.VREF) * PotCommand.VOLTAGE_CORRECTION;
+ return 4.7;
+ }
+
private static void log(String message) {
MessagesCentral.getInstance().postMessage(EcuStimulator.class, message);
FileLog.MAIN.logLine(message);
}
private static String putValue(String msg, double value) {
- return msg + D + value + D;
+ return msg + DELIMITER + value + DELIMITER;
}
private static String putValue(String msg, int value) {
- return msg + D + value + D;
+ return msg + DELIMITER + value + DELIMITER;
+ }
+
+ public JButton createButton() {
+ final JButton button = new JButton("stimulate stock ECU");
+ button.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ buildTable();
+ } catch (Throwable e) {
+ e.printStackTrace();
+ System.exit(-20);
+ }
+ SwingUtilities.invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ button.setText("Done");
+ }
+ });
+ }
+ }, "Ecu Stimulator").start();
+ }
+ });
+ return button;
+ }
+
+ public StimulationInputs getInputs() {
+ return inputs;
}
interface ResultListener {
- void onResult(int rpm, double maf, float advance, double dwell);
+ void onResult(int rpm, double engineLoad, float advance, double dwell);
+ }
+
+ public MultipleMeasurements waitForMultipleResults(final Sensor dwellSensor) {
+ final MultipleMeasurements result = new MultipleMeasurements();
+
+ final CountDownLatch latch = new CountDownLatch(MEASURES);
+
+ EngineTimeListener listener = new EngineTimeListener() {
+ @Override
+ public void onTime(double time) {
+ if (latch.getCount() == 0)
+ return;
+ double dwell = getValue(dwellSensor);
+ double advance = 0;//getValue(Sensor.ADVANCE0);
+ result.dwells.add(dwell);
+ result.advances.add(advance);
+ latch.countDown();
+ }
+ };
+ LinkManager.engineState.timeListeners.add(listener);
+ try {
+ latch.await();
+ } catch (InterruptedException e) {
+ throw new IllegalStateException(e);
+ }
+ LinkManager.engineState.timeListeners.remove(listener);
+ return result;
+ }
+
+ private class MultipleMeasurements {
+ private List dwells = new ArrayList<>(MEASURES);
+ private List advances = new ArrayList<>(MEASURES);
+
+ public List getDwells() {
+ return dwells;
+ }
+
+ public List getAdvances() {
+ return advances;
+ }
}
}
diff --git a/java_console/ui/src/com/rusefi/PortLookupFrame.java b/java_console/ui/src/com/rusefi/PortLookupFrame.java
index 22eef0f167..8f3a87e832 100644
--- a/java_console/ui/src/com/rusefi/PortLookupFrame.java
+++ b/java_console/ui/src/com/rusefi/PortLookupFrame.java
@@ -3,6 +3,8 @@ package com.rusefi;
import com.irnems.Launcher;
import com.rusefi.io.LinkManager;
import com.rusefi.io.tcp.TcpConnector;
+import com.rusefi.ui.UiUtils;
+import com.rusefi.ui.widgets.URLLabel;
import jssc.SerialPortList;
import javax.swing.*;
@@ -20,17 +22,18 @@ import java.util.List;
*/
public class PortLookupFrame {
public static void chooseSerialPort() {
- List ports = new ArrayList();
+ List ports = new ArrayList<>();
ports.addAll(Arrays.asList(SerialPortList.getPortNames()));
ports.addAll(TcpConnector.getAvailablePorts());
- final JFrame frame = new JFrame("Serial port selection");
+ final JFrame frame = new JFrame(Launcher.CONSOLE_VERSION + ": Serial port selection");
- final JPanel panel = new JPanel(new FlowLayout());
+ JPanel content = new JPanel(new BorderLayout());
+
+ final JPanel upperPanel = new JPanel(new FlowLayout());
if (!ports.isEmpty())
- addPortSelection(ports, frame, panel);
-
+ addPortSelection(ports, frame, upperPanel);
final JButton buttonLogViewer = new JButton();
buttonLogViewer.setText("Use " + LinkManager.LOG_VIEWER);
@@ -42,15 +45,27 @@ public class PortLookupFrame {
}
});
- panel.add(buttonLogViewer);
+ upperPanel.add(buttonLogViewer);
- frame.add(panel);
+ JPanel centerPanel = new JPanel(new FlowLayout());
+ centerPanel.add(SimulatorHelper.createSimulatorComponent(frame));
+
+
+ JPanel lowerPanel = new JPanel(new FlowLayout());
+ lowerPanel.add(new URLLabel("rusEfi (c) 2012-2014", "http://rusefi.com/?java_console"));
+ content.add(upperPanel, BorderLayout.NORTH);
+ content.add(centerPanel, BorderLayout.CENTER);
+ content.add(lowerPanel, BorderLayout.SOUTH);
+
+
+ frame.add(content);
frame.pack();
frame.setVisible(true);
+ UiUtils.centerWindow(frame);
}
private static void addPortSelection(List ports, final JFrame frame, JPanel panel) {
- final JComboBox comboPorts = new JComboBox();
+ final JComboBox comboPorts = new JComboBox<>();
for (final String port : ports)
comboPorts.addItem(port);
panel.add(comboPorts);
diff --git a/java_console/ui/src/com/rusefi/SimulatorHelper.java b/java_console/ui/src/com/rusefi/SimulatorHelper.java
new file mode 100644
index 0000000000..e6cc25fa32
--- /dev/null
+++ b/java_console/ui/src/com/rusefi/SimulatorHelper.java
@@ -0,0 +1,69 @@
+package com.rusefi;
+
+import com.irnems.Launcher;
+import com.rusefi.io.tcp.TcpConnector;
+
+import javax.swing.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.File;
+import java.io.IOException;
+
+public class SimulatorHelper {
+ public static final String BINARY = "rusefi_simulator.exe";
+ private static Process process;
+
+ public static boolean isBinaryHere() {
+ return new File(BINARY).exists();
+ }
+
+ private static void startSimulator() {
+ try {
+ process = Runtime.getRuntime().exec(BINARY);
+ } catch (IOException e) {
+ throw new IllegalStateException(e);
+ }
+ // unfortunately at this point Windows might popup a dialog asking for a permission to listen to port
+
+ boolean isPortOpened = false;
+ for (int i = 0; i < 60 && !isPortOpened; i++) {
+ isPortOpened = TcpConnector.isTcpPortOpened();
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ throw new IllegalStateException("Unexpected", e);
+ }
+ }
+ if (!isPortOpened)
+ throw new IllegalStateException("Port not opened?");
+
+ new Launcher("" + TcpConnector.DEFAULT_PORT);
+
+ }
+
+ public static JComponent createSimulatorComponent(final JFrame frame) {
+ if (!SimulatorHelper.isBinaryHere())
+ return new JLabel(SimulatorHelper.BINARY + " not found");
+
+ if (TcpConnector.isTcpPortOpened())
+ return new JLabel("Port " + TcpConnector.DEFAULT_PORT + " already busy. Simulator running?");
+
+
+ JButton simulatorButton = new JButton("Start Simulator");
+ simulatorButton.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent event) {
+ frame.dispose();
+ startSimulator();
+ }
+ });
+
+
+ return simulatorButton;
+ }
+
+ public static void onWindowClosed() {
+ if (process != null)
+ process.destroy();
+ }
+}
\ No newline at end of file
diff --git a/java_console/ui/src/com/rusefi/StimulationInputs.java b/java_console/ui/src/com/rusefi/StimulationInputs.java
new file mode 100644
index 0000000000..cae9c5280a
--- /dev/null
+++ b/java_console/ui/src/com/rusefi/StimulationInputs.java
@@ -0,0 +1,58 @@
+package com.rusefi;
+
+import com.irnems.Launcher;
+
+import javax.swing.*;
+import java.awt.*;
+
+/**
+ * 8/13/14
+ * (c) Andrey Belomutskiy
+ */
+public class StimulationInputs {
+
+ private final JPanel content = new JPanel(new GridLayout(12, 1));
+
+ private final JSpinner loadEngineMin = new JSpinner(new SpinnerNumberModel(1.0, 0.0, 5.0, 0.1));
+ private final JSpinner loadEngineMax = new JSpinner(new SpinnerNumberModel(4.0, 0.0, 5.0, 0.1));
+
+ private final JSpinner elResistance2 = new JSpinner(new SpinnerNumberModel(10000, 0, 100000, 1));
+
+ public StimulationInputs(EcuStimulator ecuStimulator) {
+ content.add(new JLabel("Engine load from"));
+ content.add(wrap(loadEngineMin));
+
+ content.add(new JLabel("Engine load to"));
+ content.add(wrap(loadEngineMax));
+
+ content.add(new JLabel("EL resistance"));
+ content.add(wrap(elResistance2));
+
+ JButton button = ecuStimulator.createButton();
+ if (Launcher.SHOW_STIMULATOR)
+ content.add(wrap(button));
+ }
+
+ public double getEngineLoadMin() {
+ return (Double) loadEngineMin.getValue();
+ }
+
+ public double getEngineLoadMax() {
+ return (Double) loadEngineMax.getValue();
+ }
+
+ public static JComponent wrap(JComponent component) {
+ JPanel result = new JPanel();
+ result.add(component);
+ return result;
+ }
+
+ public JPanel getContent() {
+ return content;
+ }
+
+ public double getEngineLoadR2Resistance() {
+ return (double) elResistance2.getValue();
+ }
+}
+
diff --git a/java_console/ui/src/com/rusefi/VersionChecker.java b/java_console/ui/src/com/rusefi/VersionChecker.java
new file mode 100644
index 0000000000..c05b06b122
--- /dev/null
+++ b/java_console/ui/src/com/rusefi/VersionChecker.java
@@ -0,0 +1,114 @@
+package com.rusefi;
+
+import com.irnems.FileLog;
+import com.rusefi.io.tcp.TcpConnector;
+
+import javax.swing.*;
+import java.awt.*;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Map;
+
+import static com.irnems.Launcher.*;
+
+/**
+ * This class checks the recommended versions numbers and compares them with current versions
+ *
+ * (c) Andrey Belomutskiy
+ * 8/10/14
+ */
+public class VersionChecker {
+ private static final String JAVA_CONSOLE_TAG = "java_console";
+ private static final String FIRMWARE_TAG = "firmware";
+ private static final String VERSIONS_URL = "http://rusefi.com/console/versions.txt";
+
+ private static final VersionChecker instance = new VersionChecker();
+
+
+ private final Map map = new HashMap<>();
+ private int previousReportedVersion;
+
+ private VersionChecker() {
+ }
+
+ public static void start() {
+ Thread t = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ instance.readAndProcess();
+ } catch (IOException e) {
+ e.printStackTrace();
+ FileLog.MAIN.logLine("Failed to read from " + VERSIONS_URL);
+ }
+ }
+ }, "version checker");
+ t.setDaemon(true);
+ t.start();
+ }
+
+ private void readAndProcess() throws IOException {
+ URL url = new URL(VERSIONS_URL);
+ BufferedReader s = new BufferedReader(new InputStreamReader(url.openStream()));
+
+ FileLog.MAIN.logLine("Reading from " + VERSIONS_URL);
+
+ String line;
+ while ((line = s.readLine()) != null) {
+ String[] pair = line.split("=");
+ if (pair.length == 2)
+ map.put(pair[0], TcpConnector.parseIntWithReason(pair[1], "VC value"));
+ }
+
+
+ final Integer javaVersion = map.get(JAVA_CONSOLE_TAG);
+ System.out.println("Got java_console: " + javaVersion);
+ showUpdateWarningIfNeeded("dev console", javaVersion, CONSOLE_VERSION);
+ System.out.println("Got firmware: " + map.get(FIRMWARE_TAG));
+
+ }
+
+ private static void showUpdateWarningIfNeeded(final String componentName, final Integer latestVersion, final int currentVersion) {
+ if (latestVersion == null || currentVersion >= latestVersion)
+ return;
+ SwingUtilities.invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ Component parent = JFrame.getFrames()[0];
+ String message = "It's time to update " + componentName + "!\r\n" +
+ "Your version: " + currentVersion + "\r\n" +
+ "Latest version: " + latestVersion;
+ JOptionPane.showMessageDialog(parent, message, "Update", JOptionPane.WARNING_MESSAGE);
+ }
+ });
+ }
+
+ public static VersionChecker getInstance() {
+ return instance;
+ }
+
+ public void onFirmwareVersion(String firmwareString) {
+ Integer latestVersion = map.get(FIRMWARE_TAG);
+ if (latestVersion == null) {
+ // no version file yet? nothing to bother about
+ return;
+ }
+ String[] tokens = firmwareString.split("[@\\s]");
+ int version;
+ try {
+ version = Integer.parseInt(tokens[1]);
+ } catch (NumberFormatException e) {
+ FileLog.MAIN.logLine("Error processing version [" + firmwareString + "]");
+ return;
+ }
+ if (version == previousReportedVersion) {
+ // no reason to bother our user too often
+ return;
+ }
+ previousReportedVersion = version;
+ showUpdateWarningIfNeeded("firmware", latestVersion, version);
+ }
+}
diff --git a/java_console/ui/src/com/rusefi/test/EcuStimulatorSandbox.java b/java_console/ui/src/com/rusefi/test/EcuStimulatorSandbox.java
new file mode 100644
index 0000000000..91cb96f892
--- /dev/null
+++ b/java_console/ui/src/com/rusefi/test/EcuStimulatorSandbox.java
@@ -0,0 +1,14 @@
+package com.rusefi.test;
+
+import com.rusefi.EcuStimulator;
+import com.rusefi.ui.FrameHelper;
+
+/**
+ * 8/13/14
+ * (c) Andrey Belomutskiy
+ */
+public class EcuStimulatorSandbox extends FrameHelper {
+ public static void main(String[] args) {
+ new EcuStimulatorSandbox().showFrame(EcuStimulator.getInstance().getPanel());
+ }
+}
diff --git a/java_console/ui/src/com/rusefi/test/MsgPanelSandbox.java b/java_console/ui/src/com/rusefi/test/MsgPanelSandbox.java
new file mode 100644
index 0000000000..7bdeac64d6
--- /dev/null
+++ b/java_console/ui/src/com/rusefi/test/MsgPanelSandbox.java
@@ -0,0 +1,17 @@
+package com.rusefi.test;
+
+import com.rusefi.ui.FrameHelper;
+import com.rusefi.ui.MsgPanel;
+
+public class MsgPanelSandbox extends FrameHelper {
+ private MsgPanelSandbox() {
+ showFrame(new MsgPanel(true).getContent());
+
+ }
+
+ public static void main(String[] args) {
+
+ new MsgPanelSandbox();
+
+ }
+}
\ No newline at end of file
diff --git a/java_console/ui/src/com/rusefi/ui/ChartHelper.java b/java_console/ui/src/com/rusefi/ui/ChartHelper.java
index ce731ba250..d3bac816c1 100644
--- a/java_console/ui/src/com/rusefi/ui/ChartHelper.java
+++ b/java_console/ui/src/com/rusefi/ui/ChartHelper.java
@@ -3,7 +3,7 @@ package com.rusefi.ui;
import com.irnems.FileLog;
import com.irnems.models.Range;
import com.irnems.models.XYData;
-import com.irnems.ui.widgets.JTextFieldWithWidth;
+import com.rusefi.ui.widgets.JTextFieldWithWidth;
import net.ericaro.surfaceplotter.DefaultSurfaceModel;
import net.ericaro.surfaceplotter.JSurfacePanel;
import net.ericaro.surfaceplotter.Mapper;
@@ -14,6 +14,8 @@ import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
+import static com.rusefi.io.tcp.TcpConnector.*;
+
/**
* Date: 1/22/13
* (c) Andrey Belomutskiy
@@ -60,7 +62,7 @@ public class ChartHelper {
ActionListener updateValue = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
- int rpm = Integer.parseInt(xField.getText());
+ int rpm = parseIntWithReason(xField.getText(), "CH xField");
double y = Double.parseDouble(yField.getText());
@@ -101,8 +103,7 @@ public class ChartHelper {
sm.setXMin(xRange.getMin());
sm.setXMax(xRange.getMax());
- sm.setYMin(yRange.getMin());
- sm.setYMax(yRange.getMax());
+ setYRange(yRange, sm);
sm.setBoxed(true);
sm.setDisplayXY(true);
@@ -131,4 +132,9 @@ public class ChartHelper {
sm.plot().execute();
return sm;
}
+
+ public static void setYRange(Range yRange, DefaultSurfaceModel sm) {
+ sm.setYMin(yRange.getMin());
+ sm.setYMax(yRange.getMax());
+ }
}
diff --git a/java_console/ui/src/com/rusefi/ui/ChartScrollControl.java b/java_console/ui/src/com/rusefi/ui/ChartScrollControl.java
index 65f0d6facc..9994ced579 100644
--- a/java_console/ui/src/com/rusefi/ui/ChartScrollControl.java
+++ b/java_console/ui/src/com/rusefi/ui/ChartScrollControl.java
@@ -25,6 +25,7 @@ public class ChartScrollControl {
setInfoText(index);
JButton prev = new JButton("<");
+ prev.setToolTipText("Previous page");
prev.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
@@ -38,6 +39,7 @@ public class ChartScrollControl {
JButton next = new JButton(">");
+ next.setToolTipText("Next page");
next.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
diff --git a/java_console/ui/src/com/rusefi/ui/DefaultExceptionHandler.java b/java_console/ui/src/com/rusefi/ui/DefaultExceptionHandler.java
index 76f2afff4c..dda9624cc2 100644
--- a/java_console/ui/src/com/rusefi/ui/DefaultExceptionHandler.java
+++ b/java_console/ui/src/com/rusefi/ui/DefaultExceptionHandler.java
@@ -1,8 +1,13 @@
package com.rusefi.ui;
+import com.irnems.FileLog;
+
import javax.swing.*;
import java.awt.*;
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+import static com.irnems.Launcher.*;
import static javax.swing.JOptionPane.OK_OPTION;
/**
@@ -15,9 +20,29 @@ public class DefaultExceptionHandler implements Thread.UncaughtExceptionHandler
}
public static void handleException(Throwable e) {
- // Here you should have a more robust, permanent record of problems
- JOptionPane.showMessageDialog(findActiveFrame(), e.toString(), "Exception Occurred", OK_OPTION);
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ PrintStream ps = new PrintStream(baos);
+ e.printStackTrace(ps);
+
+ JPanel content = new JPanel(new BorderLayout());
+ content.add(new JLabel(e.toString()), BorderLayout.NORTH);
+
+ JTextArea textArea = new JTextArea(baos.toString());
+
+ textArea.setLineWrap(true);
+ textArea.setWrapStyleWord(true);
+ JScrollPane scrollPane = new JScrollPane(textArea) {
+ @Override
+ public Dimension getPreferredSize() {
+ return new Dimension(500, 400);
+ }
+ };
+
+ content.add(scrollPane, BorderLayout.CENTER);
+
+ JOptionPane.showConfirmDialog(findActiveFrame(), content, CONSOLE_VERSION + ": Exception Occurred", JOptionPane.DEFAULT_OPTION);
e.printStackTrace();
+ FileLog.MAIN.logLine("handleException: " + baos.toString());
}
private static Frame findActiveFrame() {
diff --git a/java_console/ui/src/com/rusefi/ui/GaugesPanel.java b/java_console/ui/src/com/rusefi/ui/GaugesPanel.java
index 99d3b7395a..818bf0666f 100644
--- a/java_console/ui/src/com/rusefi/ui/GaugesPanel.java
+++ b/java_console/ui/src/com/rusefi/ui/GaugesPanel.java
@@ -1,8 +1,8 @@
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.MafCommand;
+import com.rusefi.ui.widgets.RpmCommand;
import com.rusefi.ui.widgets.SensorGauge;
import eu.hansolo.steelseries.gauges.Radial;
@@ -13,26 +13,33 @@ import java.awt.*;
* Date: 2/5/13
* (c) Andrey Belomutskiy
*/
-public class GaugesPanel extends JComponent {
+public class GaugesPanel {
private static final int ADC_MAX_VALUE = 255; // mazda ECU
// private static final int ADC_MAX_VALUE = 4095; // discovery board
+ private final JPanel content = new JPanel(new BorderLayout());
+
public GaugesPanel() {
- setLayout(new GridLayout(1, 3));
-
-
// Radial radial2 = createRadial("title");
JPanel box2 = new JPanel(new GridLayout(3, 5));
-
box2.add(createControls());
+ box2.add(createRpmGauge());
+ box2.add(SensorGauge.createGauge(Sensor.MAF));
+ box2.add(SensorGauge.createGauge(Sensor.CLT));
+ box2.add(SensorGauge.createGauge(Sensor.IAT));
+ box2.add(SensorGauge.createGauge(Sensor.TPS));
+ box2.add(SensorGauge.createGauge(Sensor.MAP));
+ box2.add(SensorGauge.createGauge(Sensor.MAP_RAW));
+
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));
@@ -45,14 +52,9 @@ public class GaugesPanel extends JComponent {
// 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));
@@ -65,13 +67,17 @@ public class GaugesPanel extends JComponent {
box2.add(SensorGauge.createGauge(Sensor.TIMING));
- box2.add(createRpmGauge());
//add(rpmGauge);
- add(box2);
+ content.add(box2, BorderLayout.CENTER);
+ content.add(new WarningPanel().getPanel(), BorderLayout.SOUTH);
// add(new JLabel("fd"), BorderLayout.EAST);
}
+ public JComponent getContent() {
+ return content;
+ }
+
private Component createControls() {
JPanel controls = new JPanel(new GridLayout(2, 1));
controls.add(new RpmCommand());
diff --git a/java_console/ui/src/com/rusefi/ui/Live3DReport.java b/java_console/ui/src/com/rusefi/ui/Live3DReport.java
index 270d446006..9506248536 100644
--- a/java_console/ui/src/com/rusefi/ui/Live3DReport.java
+++ b/java_console/ui/src/com/rusefi/ui/Live3DReport.java
@@ -1,6 +1,6 @@
package com.rusefi.ui;
-import com.irnems.EcuStimulator;
+import com.rusefi.EcuStimulator;
import com.irnems.core.MessagesCentral;
import com.irnems.models.Point3D;
import com.irnems.models.Range;
diff --git a/java_console/ui/src/com/rusefi/ui/MsgPanel.java b/java_console/ui/src/com/rusefi/ui/MsgPanel.java
index e943f18743..2621853f97 100644
--- a/java_console/ui/src/com/rusefi/ui/MsgPanel.java
+++ b/java_console/ui/src/com/rusefi/ui/MsgPanel.java
@@ -1,8 +1,8 @@
package com.rusefi.ui;
import com.irnems.core.MessagesCentral;
-import com.irnems.ui.widgets.AnyCommand;
-import com.irnems.ui.widgets.IdleLabel;
+import com.rusefi.ui.widgets.AnyCommand;
+import com.rusefi.ui.widgets.IdleLabel;
import javax.swing.*;
import javax.swing.text.BadLocationException;
@@ -22,17 +22,31 @@ import java.util.Date;
*
* @see AnyCommand
*/
-public class MsgPanel extends JPanel {
+public class MsgPanel {
private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH_mm");
+ private static final int MAX_SIZE = 50000;
private final JTextPane msg = new JTextPane();
private boolean isPaused;
+ private final JPanel content = new JPanel(new BorderLayout()) {
+ @Override
+ public Dimension getPreferredSize() {
+ Dimension size = super.getPreferredSize();
+ return new Dimension(250, size.height);
+ }
+ };
public MsgPanel(boolean needsRpmControl) {
- super(new BorderLayout());
- setBorder(BorderFactory.createLineBorder(Color.green));
+ content.setBorder(BorderFactory.createLineBorder(Color.green));
JScrollPane pane = new JScrollPane(msg, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
- add(pane, BorderLayout.CENTER);
+
+ JPanel middlePanel = new JPanel(new BorderLayout());
+ middlePanel.add(pane, BorderLayout.CENTER);
+ if (needsRpmControl)
+ middlePanel.add(new RecentCommands().getContent(), BorderLayout.EAST);
+
+
+ content.add(middlePanel, BorderLayout.CENTER);
MessagesCentral.getInstance().addListener(new MessagesCentral.MessageListener() {
@Override
public void onMessage(Class clazz, String message) {
@@ -66,14 +80,19 @@ public class MsgPanel extends JPanel {
buttonPanel.add(new AnyCommand());
if (needsRpmControl)
buttonPanel.add(new RpmControl().getContent());
- add(buttonPanel, BorderLayout.NORTH);
+ content.add(buttonPanel, BorderLayout.NORTH);
JPanel statsPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
statsPanel.add(new RpmControl().getContent());
statsPanel.add(new IdleLabel());
+ statsPanel.add(new WarningPanel().getPanel());
- add(statsPanel, BorderLayout.SOUTH);
+ content.add(statsPanel, BorderLayout.SOUTH);
+ }
+
+ public JPanel getContent() {
+ return content;
}
private void clearMessages(Document d) {
@@ -86,7 +105,7 @@ public class MsgPanel extends JPanel {
private void append(String line) {
Document d = msg.getDocument();
- if (d.getLength() > 10000)
+ if (d.getLength() > MAX_SIZE)
clearMessages(d);
try {
d.insertString(d.getLength(), line + "\r\n", null);
@@ -95,10 +114,4 @@ public class MsgPanel extends JPanel {
throw new IllegalStateException(e);
}
}
-
- @Override
- public Dimension getPreferredSize() {
- Dimension size = super.getPreferredSize();
- return new Dimension(250, size.height);
- }
}
diff --git a/java_console/ui/src/com/rusefi/ui/RecentCommands.java b/java_console/ui/src/com/rusefi/ui/RecentCommands.java
new file mode 100644
index 0000000000..37b5a6972e
--- /dev/null
+++ b/java_console/ui/src/com/rusefi/ui/RecentCommands.java
@@ -0,0 +1,109 @@
+package com.rusefi.ui;
+
+import com.rusefi.StimulationInputs;
+import com.rusefi.io.CommandQueue;
+import com.rusefi.ui.widgets.UpDownImage;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.Map;
+
+public class RecentCommands {
+ private final static int NUMBER_OF_COMMANDS = 12;
+
+ private final JPanel content = new JPanel(new GridLayout(NUMBER_OF_COMMANDS, 1));
+
+ private final LinkedHashMap entries = new LinkedHashMap() {
+ @Override
+ protected boolean removeEldestEntry(Map.Entry eldest) {
+ return size() > NUMBER_OF_COMMANDS;
+ }
+ };
+
+ private boolean reentrant;
+
+ public RecentCommands() {
+
+ CommandQueue.getInstance().addListener(new CommandQueue.CommandQueueListener() {
+ @Override
+ public void onCommand(String command) {
+ if (!reentrant)
+ add(command);
+ }
+ });
+
+ add("showconfig");
+ add("writeconfig");
+ add("enable_injection");
+ add("disable_injection");
+ add("enable_ignition");
+ add("disable_ignition");
+ }
+
+ public void add(String command) {
+ entries.put(new Entry(command), null);
+
+ content.removeAll();
+ for (Entry entry : entries.keySet()) {
+ content.add(createButton(entry));
+ }
+ UpDownImage.trueRepaint(content.getParent());
+// UpDownImage.trueLayout(content);
+ }
+
+ private JComponent createButton(final Entry entry) {
+ JButton button = new JButton(entry.command);
+ button.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
+
+ button.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ reentrant = true;
+ CommandQueue.getInstance().write(entry.command);
+ reentrant = false;
+ }
+ });
+
+ return StimulationInputs.wrap(button);
+ }
+
+ public Component getContent() {
+ return content;
+ }
+
+ static class Entry {
+ private final String command;
+
+ Entry(String command) {
+ this.command = command;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ Entry entry = (Entry) o;
+
+ return !(command != null ? !command.equals(entry.command) : entry.command != null);
+
+ }
+
+ @Override
+ public int hashCode() {
+ return command != null ? command.hashCode() : 0;
+ }
+
+ @Override
+ public String toString() {
+ return "{" +
+ "command='" + command + '\'' +
+ '}';
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/java_console/ui/src/com/rusefi/ui/RpmPanel.java b/java_console/ui/src/com/rusefi/ui/RpmPanel.java
index db59b3c7a0..791f3a0bca 100644
--- a/java_console/ui/src/com/rusefi/ui/RpmPanel.java
+++ b/java_console/ui/src/com/rusefi/ui/RpmPanel.java
@@ -1,10 +1,10 @@
package com.rusefi.ui;
-import com.irnems.EcuStimulator;
+import com.rusefi.EcuStimulator;
import com.irnems.Launcher;
import com.irnems.core.EngineTimeListener;
import com.irnems.core.Sensor;
-import com.irnems.ui.widgets.*;
+import com.rusefi.ui.widgets.*;
import com.rusefi.io.LinkManager;
import com.rusefi.ui.widgets.SensorGauge;
import net.miginfocom.swing.MigLayout;
@@ -86,7 +86,7 @@ public class RpmPanel {
rpmPanel.add(controls, BorderLayout.WEST);
rpmPanel.add(gauges, BorderLayout.CENTER);
MsgPanel msgPanel = new MsgPanel(false);
- rpmPanel.add(msgPanel, BorderLayout.EAST);
+ rpmPanel.add(msgPanel.getContent(), BorderLayout.EAST);
return rpmPanel;
}
@@ -98,10 +98,6 @@ public class RpmPanel {
private JPanel createControls() {
JPanel controls = new JPanel(new MigLayout());
controls.setBorder(BorderFactory.createLineBorder(Color.red));
- JButton button = createButton();
- if (Launcher.SHOW_STIMULATOR)
- controls.add(button, "grow, wrap");
-
controls.add(new RpmCommand(), "grow, wrap");
// controls.add(new PotCommand(0).panel, "grow, wrap");
// controls.add(new PotCommand(1).panel, "grow, wrap");
@@ -125,32 +121,5 @@ public class RpmPanel {
return controls;
}
-
- private JButton createButton() {
- final JButton button = new JButton("stimulate stock ECU");
- button.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- new Thread(new Runnable() {
- @Override
- public void run() {
- try {
- EcuStimulator.buildTable();
- } catch (Throwable e) {
- e.printStackTrace();
- System.exit(-20);
- }
- SwingUtilities.invokeLater(new Runnable() {
- @Override
- public void run() {
- button.setText("Done");
- }
- });
- }
- }, "Ecu Stimulator").start();
- }
- });
- return button;
- }
}
diff --git a/java_console/ui/src/com/rusefi/ui/UiUtils.java b/java_console/ui/src/com/rusefi/ui/UiUtils.java
index 3a35ddf352..844a0e5c1a 100644
--- a/java_console/ui/src/com/rusefi/ui/UiUtils.java
+++ b/java_console/ui/src/com/rusefi/ui/UiUtils.java
@@ -33,4 +33,11 @@ public class UiUtils {
public static void setPauseButtonText(JButton pauseButton, boolean isPaused) {
pauseButton.setText(isPaused ? "resume" : "pause");
}
+
+ public static void centerWindow(Window w) {
+ w.pack();
+ Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
+ Dimension frameSize = w.getSize();
+ w.setLocation((screenSize.width - frameSize.width) / 2, (screenSize.height - frameSize.height) / 2);
+ }
}
diff --git a/java_console/ui/src/com/rusefi/ui/WarningPanel.java b/java_console/ui/src/com/rusefi/ui/WarningPanel.java
new file mode 100644
index 0000000000..8c052b829b
--- /dev/null
+++ b/java_console/ui/src/com/rusefi/ui/WarningPanel.java
@@ -0,0 +1,55 @@
+package com.rusefi.ui;
+
+import com.irnems.core.MessagesCentral;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+public class WarningPanel {
+
+ private static final String WARNING = "WARNING";
+ private static final String ERROR = "firmware error";
+ private final JPanel panel = new JPanel(new BorderLayout());
+
+ private final JLabel label = new JLabel();
+ private final JButton reset = new JButton("reset");
+
+ public WarningPanel() {
+ label.setForeground(Color.red);
+ panel.add(label, BorderLayout.WEST);
+
+ Font currentFont = label.getFont();
+ label.setFont(currentFont.deriveFont((float) (currentFont.getSize() * 1.5)));
+
+ clear();
+
+ reset.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ clear();
+ }
+ });
+
+ MessagesCentral.getInstance().addListener(new MessagesCentral.MessageListener() {
+ @Override
+ public void onMessage(Class clazz, String message) {
+ if (message.startsWith(WARNING) || message.startsWith(ERROR)) {
+ label.setText(message);
+ reset.setEnabled(true);
+ }
+ }
+ });
+ panel.add(reset, BorderLayout.EAST);
+ }
+
+ private void clear() {
+ label.setText("");
+ reset.setEnabled(false);
+ }
+
+ public JPanel getPanel() {
+ return panel;
+ }
+}
diff --git a/java_console/ui/src/com/rusefi/ui/WavePanel.java b/java_console/ui/src/com/rusefi/ui/WavePanel.java
index 24dcd49e9d..61cbc5e513 100644
--- a/java_console/ui/src/com/rusefi/ui/WavePanel.java
+++ b/java_console/ui/src/com/rusefi/ui/WavePanel.java
@@ -5,11 +5,10 @@ import com.irnems.FileLog;
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;
+import com.rusefi.ui.widgets.AnyCommand;
+import com.rusefi.ui.widgets.URLLabel;
+import com.rusefi.ui.widgets.UpDownImage;
import com.rusefi.waves.RevolutionLog;
import com.rusefi.waves.WaveChart;
import com.rusefi.waves.WaveChartParser;
@@ -31,17 +30,36 @@ import java.util.List;
*
* @see ChartStatusPanel status bar
*/
-public class WavePanel extends JPanel {
+public class WavePanel {
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 TreeMap(INSTANCE);
- private final JPanel imagePanel = new JPanel();
+ private final JPanel chartPanel = new JPanel(new BorderLayout());
+ private final JPanel panel = new JPanel(new BorderLayout());
+
+ /**
+ * imageName -> UpDownImage
+ */
+ private final Map images = new TreeMap<>(INSTANCE);
+ /**
+ * this is the panel which displays all {@link UpDownImage} using {@link GridLayout}
+ */
+ private final JPanel imagePanel = new JPanel(new GridLayout(1, 1)) {
+ @Override
+ public Dimension getPreferredSize() {
+ Dimension d = chartPanel.getSize();
+ Dimension s = super.getPreferredSize();
+ return new Dimension((int) (d.width * zoomControl.getZoomProvider().getZoomValue()), s.height);
+ }
+ };
+
+ JScrollPane pane = new JScrollPane(imagePanel, JScrollPane.VERTICAL_SCROLLBAR_NEVER, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
+
private final ZoomControl zoomControl = new ZoomControl();
- private final ChartStatusPanel statusPanel = new ChartStatusPanel(zoomControl);
+ private final ChartStatusPanel statusPanel = new ChartStatusPanel(zoomControl.getZoomProvider());
private final UpDownImage crank = createImage(CRANK1);
private ChartScrollControl scrollControl;
@@ -50,7 +68,22 @@ public class WavePanel extends JPanel {
private static WavePanel instance = new WavePanel();
private WavePanel() {
- setLayout(new BorderLayout());
+
+
+ LinkManager.engineState.registerStringValueAction("outpin", new EngineState.ValueCallback() {
+ @Override
+ public void onUpdate(String value) {
+ String pinInfo[] = value.split("@");
+ if (pinInfo.length != 2)
+ return;
+ String channel = pinInfo[0];
+ String pin = pinInfo[1];
+ UpDownImage image = images.get(channel);
+ if (image != null)
+ image.setPhysicalPin(pin);
+ }
+ });
+
statusPanel.setWaveReport(crank.createTranslator());
@@ -102,9 +135,9 @@ public class WavePanel extends JPanel {
buttonPanel.add(new URLLabel(HELP_TEXT, HELP_URL));
- add(buttonPanel, BorderLayout.NORTH);
- add(imagePanel, BorderLayout.CENTER);
- add(statusPanel.infoPanel, BorderLayout.SOUTH);
+ chartPanel.add(buttonPanel, BorderLayout.NORTH);
+ chartPanel.add(pane, BorderLayout.CENTER);
+ chartPanel.add(statusPanel.infoPanel, BorderLayout.SOUTH);
zoomControl.listener = new ZoomControl.ZoomControlListener() {
@Override
@@ -113,21 +146,12 @@ public class WavePanel extends JPanel {
}
};
- crank.setZoomProvider(zoomControl);
+ crank.setZoomProvider(zoomControl.getZoomProvider());
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
@@ -138,6 +162,9 @@ public class WavePanel extends JPanel {
}
});
+ panel.add(chartPanel, BorderLayout.CENTER);
+ panel.add(new WarningPanel().getPanel(), BorderLayout.SOUTH);
+
// 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!,");
}
@@ -158,24 +185,34 @@ public class WavePanel extends JPanel {
statusPanel.setRevolutions(revolutions);
- for (Map.Entry e : map.map.entrySet()) {
- String imageName = e.getKey();
- String report = e.getValue().toString();
-
+ /**
+ * First let's create images for new keys
+ */
+ for (String imageName : map.map.keySet())
createSecondaryImage(imageName);
+
+ for (String imageName : images.keySet()) {
UpDownImage image = images.get(imageName);
if (image == null)
- continue;
+ throw new IllegalStateException("image not found for " + imageName);
+
+ StringBuilder sb = map.map.get(imageName);
+ String report = sb == null ? "" : sb.toString();
+
image.setRevolutions(revolutions);
List list = WaveReport.parse(report);
- if (list.isEmpty()) {
- image.onUpdate(); // this would reset empty image
- continue;
- }
WaveReport wr = new WaveReport(list);
image.setWaveReport(wr, revolutions);
}
+ /**
+ * this is to fix the UI glitch when images tab shows a tiny square
+ */
+ UpDownImage.trueRepaint(chartPanel.getParent());
+ }
+
+ public JPanel getPanel() {
+ return panel;
}
private void createSecondaryImage(String name) {
@@ -184,13 +221,13 @@ public class WavePanel extends JPanel {
int index = getInsertIndex(name, images.keySet());
- UpDownImage image = register(name).setTranslator(crank.createTranslator());
- image.setZoomProvider(zoomControl);
-// try {
+ FileLog.MAIN.logLine("Registering " + name + "@" + index);
+
+ UpDownImage image = createImage(name);
+ images.put(name, image);
+ image.setTranslator(crank.createTranslator());
+ image.setZoomProvider(zoomControl.getZoomProvider());
imagePanel.add(image, index);
-// } catch (Throwable e) {
-// System.out.println(e);
-// }
imagePanel.setLayout(new GridLayout(images.size(), 1));
}
@@ -214,12 +251,6 @@ public class WavePanel extends JPanel {
UiUtils.saveImage(fileName, imagePanel);
}
- 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);
diff --git a/java_console/ui/src/com/rusefi/ui/ZoomControl.java b/java_console/ui/src/com/rusefi/ui/ZoomControl.java
index 15d71bc772..506450c4f5 100644
--- a/java_console/ui/src/com/rusefi/ui/ZoomControl.java
+++ b/java_console/ui/src/com/rusefi/ui/ZoomControl.java
@@ -11,11 +11,22 @@ import java.awt.event.ActionListener;
* 7/7/13
* (c) Andrey Belomutskiy
*/
-public class ZoomControl extends JPanel implements ZoomProvider {
+public class ZoomControl extends JPanel {
private final JLabel currentValue = new JLabel();
private double value;
public ZoomControlListener listener = null;
+ ZoomProvider zoomProvider = new ZoomProvider() {
+ @Override
+ public double getZoomValue() {
+ return value;
+ }
+
+ public String toString() {
+ return "zoom " + value;
+ }
+ };
+
public ZoomControl() {
super(new FlowLayout());
setValue(1);
@@ -37,8 +48,19 @@ public class ZoomControl extends JPanel implements ZoomProvider {
setValue(value * 1.1);
}
});
+ plus.setToolTipText("Zoom in");
add(plus);
+ JButton resetZoom = new JButton("*");
+ resetZoom.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ setValue(1);
+ }
+ });
+ resetZoom.setToolTipText("Reset zoom");
+ add(resetZoom);
+
JButton minus = new JButton("-");
minus.addActionListener(new ActionListener() {
@Override
@@ -46,6 +68,7 @@ public class ZoomControl extends JPanel implements ZoomProvider {
setValue(value / 1.1);
}
});
+ minus.setToolTipText("Zoom out");
add(minus);
}
@@ -56,9 +79,8 @@ public class ZoomControl extends JPanel implements ZoomProvider {
listener.onZoomChange();
}
- @Override
- public double getZoomValue() {
- return value;
+ public ZoomProvider getZoomProvider() {
+ return zoomProvider;
}
interface ZoomControlListener {
diff --git a/java_console/ui/src/com/irnems/ui/widgets/AdcDebugControl.java b/java_console/ui/src/com/rusefi/ui/widgets/AdcDebugControl.java
similarity index 90%
rename from java_console/ui/src/com/irnems/ui/widgets/AdcDebugControl.java
rename to java_console/ui/src/com/rusefi/ui/widgets/AdcDebugControl.java
index 2b03a06980..420bf14e2c 100644
--- a/java_console/ui/src/com/irnems/ui/widgets/AdcDebugControl.java
+++ b/java_console/ui/src/com/rusefi/ui/widgets/AdcDebugControl.java
@@ -1,4 +1,4 @@
-package com.irnems.ui.widgets;
+package com.rusefi.ui.widgets;
import com.irnems.core.Sensor;
diff --git a/java_console/ui/src/com/irnems/ui/widgets/AnyCommand.java b/java_console/ui/src/com/rusefi/ui/widgets/AnyCommand.java
similarity index 88%
rename from java_console/ui/src/com/irnems/ui/widgets/AnyCommand.java
rename to java_console/ui/src/com/rusefi/ui/widgets/AnyCommand.java
index 6ec7dabbdc..7a37982ffa 100644
--- a/java_console/ui/src/com/irnems/ui/widgets/AnyCommand.java
+++ b/java_console/ui/src/com/rusefi/ui/widgets/AnyCommand.java
@@ -1,4 +1,4 @@
-package com.irnems.ui.widgets;
+package com.rusefi.ui.widgets;
import com.rusefi.io.CommandQueue;
@@ -14,6 +14,8 @@ import java.awt.event.ActionListener;
* (c) Andrey Belomutskiy
*/
public class AnyCommand extends JPanel {
+ private static final int COMMAND_CONFIRMATION_TIMEOUT = 1000;
+
public AnyCommand() {
// setBorder(BorderFactory.createLineBorder(Color.PINK));
setLayout(new FlowLayout(FlowLayout.LEFT));
@@ -36,8 +38,7 @@ public class AnyCommand extends JPanel {
String cmd = text.getText();
if (!isValidInput(text))
return;
- int timeout = isSlowCommand(cmd) ? 5000 : 300;
- CommandQueue.getInstance().write(cmd.toLowerCase(), timeout);
+ CommandQueue.getInstance().write(cmd.toLowerCase(), COMMAND_CONFIRMATION_TIMEOUT);
}
});
text.getDocument().addDocumentListener(new DocumentListener() {
@@ -84,10 +85,4 @@ public class AnyCommand extends JPanel {
}
return isOk;
}
-
- private static boolean isSlowCommand(String cmd) {
- String lc = cmd.toLowerCase();
- 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/BooleanFlagControlPanel.java b/java_console/ui/src/com/rusefi/ui/widgets/BooleanFlagControlPanel.java
similarity index 97%
rename from java_console/ui/src/com/irnems/ui/widgets/BooleanFlagControlPanel.java
rename to java_console/ui/src/com/rusefi/ui/widgets/BooleanFlagControlPanel.java
index a46f867eab..6d04169c8e 100644
--- a/java_console/ui/src/com/irnems/ui/widgets/BooleanFlagControlPanel.java
+++ b/java_console/ui/src/com/rusefi/ui/widgets/BooleanFlagControlPanel.java
@@ -1,4 +1,4 @@
-package com.irnems.ui.widgets;
+package com.rusefi.ui.widgets;
import com.irnems.core.Sensor;
import com.irnems.core.SensorCentral;
diff --git a/java_console/ui/src/com/irnems/ui/widgets/IdleLabel.java b/java_console/ui/src/com/rusefi/ui/widgets/IdleLabel.java
similarity index 94%
rename from java_console/ui/src/com/irnems/ui/widgets/IdleLabel.java
rename to java_console/ui/src/com/rusefi/ui/widgets/IdleLabel.java
index 4e424b4cb2..a80183945a 100644
--- a/java_console/ui/src/com/irnems/ui/widgets/IdleLabel.java
+++ b/java_console/ui/src/com/rusefi/ui/widgets/IdleLabel.java
@@ -1,4 +1,4 @@
-package com.irnems.ui.widgets;
+package com.rusefi.ui.widgets;
import com.irnems.core.Sensor;
import com.irnems.core.SensorCentral;
diff --git a/java_console/ui/src/com/irnems/ui/widgets/InjectorControl.java b/java_console/ui/src/com/rusefi/ui/widgets/InjectorControl.java
similarity index 91%
rename from java_console/ui/src/com/irnems/ui/widgets/InjectorControl.java
rename to java_console/ui/src/com/rusefi/ui/widgets/InjectorControl.java
index 31ac982d9c..9d7241f98e 100644
--- a/java_console/ui/src/com/irnems/ui/widgets/InjectorControl.java
+++ b/java_console/ui/src/com/rusefi/ui/widgets/InjectorControl.java
@@ -1,4 +1,4 @@
-package com.irnems.ui.widgets;
+package com.rusefi.ui.widgets;
import com.irnems.core.Sensor;
diff --git a/java_console/ui/src/com/irnems/ui/widgets/JTextFieldWithWidth.java b/java_console/ui/src/com/rusefi/ui/widgets/JTextFieldWithWidth.java
similarity index 94%
rename from java_console/ui/src/com/irnems/ui/widgets/JTextFieldWithWidth.java
rename to java_console/ui/src/com/rusefi/ui/widgets/JTextFieldWithWidth.java
index 4bf6b80b27..76c0fa3a55 100644
--- a/java_console/ui/src/com/irnems/ui/widgets/JTextFieldWithWidth.java
+++ b/java_console/ui/src/com/rusefi/ui/widgets/JTextFieldWithWidth.java
@@ -1,4 +1,4 @@
-package com.irnems.ui.widgets;
+package com.rusefi.ui.widgets;
import javax.swing.*;
import java.awt.*;
diff --git a/java_console/ui/src/com/irnems/ui/widgets/LogModeWidget.java b/java_console/ui/src/com/rusefi/ui/widgets/LogModeWidget.java
similarity index 96%
rename from java_console/ui/src/com/irnems/ui/widgets/LogModeWidget.java
rename to java_console/ui/src/com/rusefi/ui/widgets/LogModeWidget.java
index 43a582865c..4ff6833b7d 100644
--- a/java_console/ui/src/com/irnems/ui/widgets/LogModeWidget.java
+++ b/java_console/ui/src/com/rusefi/ui/widgets/LogModeWidget.java
@@ -1,4 +1,4 @@
-package com.irnems.ui.widgets;
+package com.rusefi.ui.widgets;
import com.rusefi.io.CommandQueue;
diff --git a/java_console/ui/src/com/irnems/ui/widgets/MafCommand.java b/java_console/ui/src/com/rusefi/ui/widgets/MafCommand.java
similarity index 94%
rename from java_console/ui/src/com/irnems/ui/widgets/MafCommand.java
rename to java_console/ui/src/com/rusefi/ui/widgets/MafCommand.java
index ffeda2ff35..e2a0d33281 100644
--- a/java_console/ui/src/com/irnems/ui/widgets/MafCommand.java
+++ b/java_console/ui/src/com/rusefi/ui/widgets/MafCommand.java
@@ -1,6 +1,6 @@
-package com.irnems.ui.widgets;
+package com.rusefi.ui.widgets;
-import com.irnems.EcuStimulator;
+import com.rusefi.EcuStimulator;
import com.irnems.core.Sensor;
import javax.swing.*;
diff --git a/java_console/ui/src/com/irnems/ui/widgets/PotCommand.java b/java_console/ui/src/com/rusefi/ui/widgets/PotCommand.java
similarity index 94%
rename from java_console/ui/src/com/irnems/ui/widgets/PotCommand.java
rename to java_console/ui/src/com/rusefi/ui/widgets/PotCommand.java
index b39203d5e7..0d9a29cb26 100644
--- a/java_console/ui/src/com/irnems/ui/widgets/PotCommand.java
+++ b/java_console/ui/src/com/rusefi/ui/widgets/PotCommand.java
@@ -1,8 +1,9 @@
-package com.irnems.ui.widgets;
+package com.rusefi.ui.widgets;
import com.irnems.core.MessagesCentral;
import com.irnems.core.Sensor;
import com.irnems.core.SensorCentral;
+import com.rusefi.EcuStimulator;
import com.rusefi.io.CommandQueue;
import javax.swing.*;
@@ -16,7 +17,6 @@ import java.awt.*;
*/
public class PotCommand {
public static final double VOLTAGE_CORRECTION = 2.9 / 3;
- private static final int MAF_CHANNEL_ECU_INTERNAL_RESISTANCE = 1000; // 1KOhm internal resistor?
public final JPanel panel;
final JSpinner potSpinner;
@@ -87,7 +87,7 @@ public class PotCommand {
}
public static int getPotResistance(Double vout, double vRef) {
- double r = getR1InVoltageDividor3(vout, vRef, MAF_CHANNEL_ECU_INTERNAL_RESISTANCE);
+ double r = getR1InVoltageDividor3(vout, vRef, EcuStimulator.getInstance().getInputs().getEngineLoadR2Resistance());
MessagesCentral.getInstance().postMessage(PotCommand.class, "VRef=" + vRef + ", needed resistance: " + r);
// pot command accept resistance and does the conversion itself
return (int) r;
diff --git a/java_console/ui/src/com/irnems/ui/widgets/RpmCommand.java b/java_console/ui/src/com/rusefi/ui/widgets/RpmCommand.java
similarity index 94%
rename from java_console/ui/src/com/irnems/ui/widgets/RpmCommand.java
rename to java_console/ui/src/com/rusefi/ui/widgets/RpmCommand.java
index 453cbb8778..c24bc1d8f2 100644
--- a/java_console/ui/src/com/irnems/ui/widgets/RpmCommand.java
+++ b/java_console/ui/src/com/rusefi/ui/widgets/RpmCommand.java
@@ -1,4 +1,4 @@
-package com.irnems.ui.widgets;
+package com.rusefi.ui.widgets;
import com.rusefi.io.CommandQueue;
@@ -38,6 +38,9 @@ public class RpmCommand extends JPanel {
}
public static void requestRpmChange(int rpm) {
+ /**
+ * @see
+ */
CommandQueue.getInstance().write("rpm " + rpm);
}
}
diff --git a/java_console/ui/src/com/irnems/ui/widgets/URLLabel.java b/java_console/ui/src/com/rusefi/ui/widgets/URLLabel.java
similarity index 98%
rename from java_console/ui/src/com/irnems/ui/widgets/URLLabel.java
rename to java_console/ui/src/com/rusefi/ui/widgets/URLLabel.java
index f041e39102..aa2f98a63f 100644
--- a/java_console/ui/src/com/irnems/ui/widgets/URLLabel.java
+++ b/java_console/ui/src/com/rusefi/ui/widgets/URLLabel.java
@@ -1,4 +1,4 @@
-package com.irnems.ui.widgets;
+package com.rusefi.ui.widgets;
import javax.swing.*;
diff --git a/java_console/ui/src/com/irnems/ui/widgets/UpDownImage.java b/java_console/ui/src/com/rusefi/ui/widgets/UpDownImage.java
similarity index 87%
rename from java_console/ui/src/com/irnems/ui/widgets/UpDownImage.java
rename to java_console/ui/src/com/rusefi/ui/widgets/UpDownImage.java
index 7a0d111bcb..b7e157c409 100644
--- a/java_console/ui/src/com/irnems/ui/widgets/UpDownImage.java
+++ b/java_console/ui/src/com/rusefi/ui/widgets/UpDownImage.java
@@ -1,6 +1,7 @@
-package com.irnems.ui.widgets;
+package com.rusefi.ui.widgets;
import com.irnems.waves.TimeAxisTranslator;
+import com.rusefi.ui.WavePanel;
import com.rusefi.waves.WaveReport;
import com.irnems.waves.ZoomProvider;
import com.rusefi.waves.RevolutionLog;
@@ -11,11 +12,12 @@ import java.text.SimpleDateFormat;
import java.util.Date;
/**
- * This is a renderer of {@link WaveReport} - this makes a simple Logical Analyzer
+ * This is a renderer of an individual {@link WaveReport} - this makes a simple Logical Analyzer
*
*
* Date: 6/23/13
* (c) Andrey Belomutskiy
+ * @see WavePanel
*/
public class UpDownImage extends JPanel {
private static final SimpleDateFormat FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss");
@@ -28,9 +30,15 @@ public class UpDownImage extends JPanel {
private final String name;
private TimeAxisTranslator translator;
private RevolutionLog time2rpm = RevolutionLog.parseRevolutions(null);
+ private String pin = "";
public UpDownImage(final String name) {
this(WaveReport.MOCK, name);
+ setToolTip();
+ }
+
+ public void setToolTip() {
+ setToolTipText("Channel " + name + "
Physical pin: " + pin + "");
}
public void setZoomProvider(ZoomProvider zoomProvider) {
@@ -41,11 +49,27 @@ public class UpDownImage extends JPanel {
trueRepaint(this);
}
+ /**
+ * This does not make any sense :( That's an attempt
+ * to hack http://rusefi.com/forum/viewtopic.php?f=2&t=631&p=10083#p10081
+ */
public static void trueRepaint(JComponent control) {
control.invalidate();
control.repaint();
}
+ public static void trueRepaint(Container control) {
+ if (control == null)
+ return;
+ control.invalidate();
+ control.repaint();
+ }
+
+ public static void trueLayout(Component component) {
+ component.invalidate();
+ component.validate();
+ }
+
public UpDownImage(WaveReport wr, String name) {
this.name = name;
setWaveReport(wr, null);
@@ -191,4 +215,9 @@ public class UpDownImage extends JPanel {
public void setRevolutions(StringBuilder revolutions) {
time2rpm = RevolutionLog.parseRevolutions(revolutions);
}
+
+ public void setPhysicalPin(String pin) {
+ this.pin = pin;
+ setToolTip();
+ }
}
diff --git a/java_console/ui/src/com/irnems/ui/widgets/WaveInfoPanel.java b/java_console/ui/src/com/rusefi/ui/widgets/WaveInfoPanel.java
similarity index 89%
rename from java_console/ui/src/com/irnems/ui/widgets/WaveInfoPanel.java
rename to java_console/ui/src/com/rusefi/ui/widgets/WaveInfoPanel.java
index 9e724df135..23bd5cea7b 100644
--- a/java_console/ui/src/com/irnems/ui/widgets/WaveInfoPanel.java
+++ b/java_console/ui/src/com/rusefi/ui/widgets/WaveInfoPanel.java
@@ -1,4 +1,4 @@
-package com.irnems.ui.widgets;
+package com.rusefi.ui.widgets;
/**
* Date: 1/14/13
diff --git a/unit_tests/boards.c b/unit_tests/boards.c
index 1b1a9651eb..8f6eb4ae87 100644
--- a/unit_tests/boards.c
+++ b/unit_tests/boards.c
@@ -7,7 +7,13 @@
#include "boards.h"
+float testMafValue = 0;
+
float getVoltageDivided(int channel) {
+ switch(channel) {
+ case TEST_MAF_CHANNEL:
+ return testMafValue;
+ }
return 0;
}
diff --git a/unit_tests/boards.h b/unit_tests/boards.h
index b49de7bdd3..6960a92abc 100644
--- a/unit_tests/boards.h
+++ b/unit_tests/boards.h
@@ -10,6 +10,8 @@
#define ADC_CHANNEL_VREF 0
+#define TEST_MAF_CHANNEL 10000013
+
float getVoltageDivided(int);
float getVoltage(int channel);
int getAdcValue(int channel);
diff --git a/unit_tests/engine_test_helper.cpp b/unit_tests/engine_test_helper.cpp
index 185753f0cf..1cbae0c28d 100644
--- a/unit_tests/engine_test_helper.cpp
+++ b/unit_tests/engine_test_helper.cpp
@@ -8,16 +8,23 @@
#include "engine_test_helper.h"
#include "stddef.h"
#include "trigger_decoder.h"
+#include "speed_density.h"
extern int timeNow;
EngineTestHelper::EngineTestHelper(engine_type_e engineType) {
ec = &persistentConfig.engineConfiguration;
+ engine.engineConfiguration = ec;
+
configuration.engineConfiguration = ec;
configuration.engineConfiguration2 = &ec2;
+
+ initSpeedDensity(ec);
+
resetConfigurationExt(NULL, FORD_INLINE_6_1995, ec, &ec2, &persistentConfig.engineConfiguration.bc);
+ ec->mafAdcChannel = (adc_channel_e)TEST_MAF_CHANNEL;
}
void EngineTestHelper::fireTriggerEvents() {
diff --git a/unit_tests/engine_test_helper.h b/unit_tests/engine_test_helper.h
index 818c0bb47d..a3c7aff8d8 100644
--- a/unit_tests/engine_test_helper.h
+++ b/unit_tests/engine_test_helper.h
@@ -21,6 +21,7 @@ public:
persistent_config_s persistentConfig;
engine_configuration2_s ec2;
configuration_s configuration;
+ Engine engine;
engine_configuration_s *ec;
diff --git a/unit_tests/global.h b/unit_tests/global.h
index f7bd257c0f..4f6c643aad 100644
--- a/unit_tests/global.h
+++ b/unit_tests/global.h
@@ -10,6 +10,7 @@
#include
#include
+#include
#include "efitime.h"
@@ -17,6 +18,7 @@ typedef int bool_t;
typedef void * Logging;
+#define EFI_ERROR_CODE 0xffffffff
#define TRUE 1
#define FALSE 0
diff --git a/unit_tests/main.cpp b/unit_tests/main.cpp
index 50574f8d26..38e00d984b 100644
--- a/unit_tests/main.cpp
+++ b/unit_tests/main.cpp
@@ -124,7 +124,7 @@ int main(void) {
testFLStack();
// resizeMap();
- printf("Success 20130706\r\n");
+ printf("Success 20130820\r\n");
return EXIT_SUCCESS;
}
diff --git a/unit_tests/test_fuel_map.cpp b/unit_tests/test_fuel_map.cpp
index 21aa9c755c..5244cfe0ed 100644
--- a/unit_tests/test_fuel_map.cpp
+++ b/unit_tests/test_fuel_map.cpp
@@ -1,5 +1,5 @@
/**
- * @file test_fuel_map.c
+ * @file test_fuel_map.cpp
*
* Created on: Nov 6, 2013
* Author: Andrey Belomutskiy, (c) 2012-2013
@@ -15,6 +15,10 @@
#include "OutputSignalList.h"
#include "ec2.h"
#include "trigger_decoder.h"
+#include "engine_test_helper.h"
+
+extern float testMafValue;
+
extern engine_configuration_s *engineConfiguration;
extern engine_configuration2_s *engineConfiguration2;
@@ -43,7 +47,7 @@ void testFuelMap(void) {
printf("*************************************************** prepareFuelMap\r\n");
prepareFuelMap();
- assertEquals(1005, getBaseFuel(5, 5));
+ assertEquals(1005, getBaseTableFuel(5, 5));
engineConfiguration->injectorLag = 0.5;
@@ -52,9 +56,12 @@ void testFuelMap(void) {
engineConfiguration->battInjectorLagCorr[i] = 2 * i;
}
+ EngineTestHelper eth(FORD_ASPIRE_1996);
+
// because all the correction tables are zero
printf("*************************************************** getRunningFuel\r\n");
- assertEqualsM("value", 0.5, getRunningFuel(5, 5));
+ float baseFuel = getBaseTableFuel(5, getEngineLoadT(ð.engine));
+ assertEqualsM("value", 0.5, getRunningFuel(baseFuel, ð.engine, 5));
printf("*************************************************** setting IAT table\r\n");
for (int i = 0; i < IAT_CURVE_SIZE; i++) {
@@ -78,10 +85,14 @@ void testFuelMap(void) {
float injectorLag = getInjectorLag(getVBatt());
assertEquals(0, injectorLag);
+ testMafValue = 5;
// 1005 * 2 for IAT correction
printf("*************************************************** getRunningFuel\r\n");
- assertEqualsM("v1", 30150, getRunningFuel(5, 5));
+ baseFuel = getBaseTableFuel(5, getEngineLoadT(ð.engine));
+ assertEqualsM("v1", 30150, getRunningFuel(baseFuel, ð.engine, 5));
+
+ testMafValue = 0;
engineConfiguration->crankingSettings.coolantTempMaxC = 65; // 8ms at 65C
engineConfiguration->crankingSettings.fuelAtMaxTempMs = 8;
@@ -111,8 +122,33 @@ static void confgiureFordAspireTriggerShape(trigger_shape_s * s) {
s->addEvent(588.045, T_SECONDARY, TV_HIGH);
s->addEvent(657.03, T_SECONDARY, TV_LOW);
s->addEvent(720, T_PRIMARY, TV_LOW);
-}
+ assertEquals(53.747 / 720, s->wave.getSwitchTime(0));
+ assertEqualsM("@0", 1, s->wave.getChannelState(1, 0));
+ assertEqualsM("@0", 1, s->wave.getChannelState(1, 0));
+
+ assertEqualsM("@1", 0, s->wave.getChannelState(0, 1));
+ assertEqualsM("@1", 0, s->wave.getChannelState(1, 1));
+
+ assertEqualsM("@2", 0, s->wave.getChannelState(0, 2));
+ assertEqualsM("@2", 1, s->wave.getChannelState(1, 2));
+
+ assertEqualsM("@3", 0, s->wave.getChannelState(0, 3));
+ assertEqualsM("@3", 0, s->wave.getChannelState(1, 3));
+
+ assertEqualsM("@4", 1, s->wave.getChannelState(0, 4));
+ assertEqualsM("@5", 1, s->wave.getChannelState(1, 5));
+ assertEqualsM("@8", 0, s->wave.getChannelState(1, 8));
+ assertEquals(121.90 / 720, s->wave.getSwitchTime(1));
+ assertEquals(657.03 / 720, s->wave.getSwitchTime(8));
+
+ assertEqualsM("expecting 0", 0, s->wave.findAngleMatch(53.747 / 720.0, s->getSize()));
+ assertEqualsM("expecting not found", -1, s->wave.findAngleMatch(53 / 720.0, s->getSize()));
+ assertEquals(7, s->wave.findAngleMatch(588.045 / 720.0, s->getSize()));
+
+ assertEqualsM("expecting 0", 0, s->wave.waveIndertionAngle(23.747 / 720.0, s->getSize()));
+ assertEqualsM("expecting 1", 1, s->wave.waveIndertionAngle(63.747 / 720.0, s->getSize()));
+}
static ActuatorEventList ae;
@@ -124,7 +160,14 @@ void testAngleResolver(void) {
confgiureFordAspireTriggerShape(ts);
- ts->setTriggerShapeSynchPointIndex(0);
+ ts->calculateTriggerSynchPoint(&engineConfiguration->triggerConfig);
+
+ assertEqualsM("index 2", 232.76, ts->eventAngles[3]); // this angle is relation to synch point
+ assertEqualsM("time 2", 0.3233, ts->wave.getSwitchTime(2));
+ assertEqualsM("index 5", 409.8412, ts->eventAngles[6]);
+ assertEqualsM("time 5", 0.5692, ts->wave.getSwitchTime(5));
+
+ assertEquals(9, ts->getTriggerShapeSynchPointIndex());
assertEqualsM("shape size", 10, ts->getSize());
@@ -142,7 +185,7 @@ void testAngleResolver(void) {
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);
+ assertEquals(109.1, ae.events[0].position.angleOffset);
}
void testPinHelper(void) {
diff --git a/unit_tests/test_signal_executor.cpp b/unit_tests/test_signal_executor.cpp
index 56bfba681b..a7e86cc518 100644
--- a/unit_tests/test_signal_executor.cpp
+++ b/unit_tests/test_signal_executor.cpp
@@ -25,7 +25,7 @@ void setOutputPinValue(io_pin_e pin, int value) {
EventQueue schedulingQueue;
-void scheduleTask(scheduling_s *scheduling, int delayUs, schfunc_t callback, void *param) {
+void scheduleTask(const char *msg, scheduling_s *scheduling, int delayUs, schfunc_t callback, void *param) {
schedulingQueue.insertTask(scheduling, getTimeNowUs(), delayUs, callback, param);
}
diff --git a/unit_tests/test_speed_density.cpp b/unit_tests/test_speed_density.cpp
index 6b05cdcded..2aa2571c5e 100644
--- a/unit_tests/test_speed_density.cpp
+++ b/unit_tests/test_speed_density.cpp
@@ -14,7 +14,7 @@ void testSpeedDensity(void) {
printf("*************************************************** testSpeedDensity\r\n");
EngineTestHelper eth(FORD_INLINE_6_1995);
- eth.ec->triggerConfig.totalToothCount = 8;
+ eth.ec->triggerConfig.customTotalToothCount = 8;
eth.initTriggerShapeAndRpmCalculator();
eth.fireTriggerEvents();
diff --git a/unit_tests/test_trigger_decoder.cpp b/unit_tests/test_trigger_decoder.cpp
index b21a1988a2..c584472b86 100644
--- a/unit_tests/test_trigger_decoder.cpp
+++ b/unit_tests/test_trigger_decoder.cpp
@@ -291,47 +291,28 @@ void testMazdaMianaNbDecoder(void) {
assertTriggerPosition(&position, 0, 0);
}
-static void testCitroen(void) {
- printf("*************************************************** testCitroen\r\n");
+static void testTriggerDecoder(const char *msg, engine_type_e type, int synchPointIndex) {
+ printf("*************************************************** %s\r\n", msg);
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);
+ resetConfigurationExt(NULL, type, ec, &ec2, &persistentConfig.engineConfiguration.bc);
- assertEquals(0, ec2.triggerShape.getTriggerShapeSynchPointIndex());
+ assertEquals(synchPointIndex, 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());
+ testTriggerDecoder("testRoverV8", ROVER_V8, 0);
}
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);
-
+ testTriggerDecoder("testMiniCooper", MINI_COOPER_R50, 121);
}
static void testFordEscortGt(void) {
- printf("*************************************************** testFordEscortGt\r\n");
-
- persistent_config_s persistentConfig;
- engine_configuration_s *ec = &persistentConfig.engineConfiguration;
- engine_configuration2_s ec2;
- resetConfigurationExt(NULL, FORD_ESCORT_GT, ec, &ec2, &persistentConfig.engineConfiguration.bc);
}
void testGY6_139QMB(void) {
@@ -371,7 +352,7 @@ static void testRpmCalculator(void) {
engine_configuration2_s *ec2 = ð.ec2;
- ec->triggerConfig.totalToothCount = 8;
+ ec->triggerConfig.customTotalToothCount = 8;
eth.initTriggerShapeAndRpmCalculator();
configuration_s configuration = { ec, ec2 };
@@ -385,7 +366,7 @@ static void testRpmCalculator(void) {
static MainTriggerCallback triggerCallbackInstance;
- triggerCallbackInstance.init(ec, ec2);
+ triggerCallbackInstance.init(ð.engine, ec2);
eth.triggerCentral.addEventListener((ShaftPositionListener)&onTriggerEvent, "main loop", &triggerCallbackInstance);
engine.rpmCalculator = ð.rpmState;
@@ -394,7 +375,7 @@ static void testRpmCalculator(void) {
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("queue size", 4, schedulingQueue.size());
assertEqualsM("ev 1", 695000, schedulingQueue.getForUnitText(0)->momentUs);
assertEqualsM("ev 2", 245000, schedulingQueue.getForUnitText(1)->momentUs);
schedulingQueue.clear();
@@ -406,7 +387,7 @@ static void testRpmCalculator(void) {
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());
+ assertEqualsM("queue size 3", 6, schedulingQueue.size());
assertEquals(258333, schedulingQueue.getForUnitText(0)->momentUs);
assertEquals(257833, schedulingQueue.getForUnitText(1)->momentUs);
assertEqualsM("ev 5", 708333, schedulingQueue.getForUnitText(2)->momentUs);
@@ -420,7 +401,7 @@ static void testRpmCalculator(void) {
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("queue size 4", 6, schedulingQueue.size());
assertEqualsM("4/0", 271666, schedulingQueue.getForUnitText(0)->momentUs);
schedulingQueue.clear();
@@ -432,7 +413,7 @@ static void testRpmCalculator(void) {
timeNow += 5000; // 5ms
eth.triggerCentral.handleShaftSignal(&configuration, SHAFT_PRIMARY_UP, timeNow);
- assertEqualsM("queue size 6", 3, schedulingQueue.size());
+ assertEqualsM("queue size 6", 5, 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);
@@ -445,7 +426,7 @@ static void testRpmCalculator(void) {
timeNow += 5000; // 5ms
eth.triggerCentral.handleShaftSignal(&configuration, SHAFT_PRIMARY_UP, timeNow);
- assertEqualsM("queue size 8", 4, schedulingQueue.size());
+ assertEqualsM("queue size 8", 6, 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);
@@ -468,7 +449,7 @@ void testTriggerDecoder(void) {
engine_configuration2_s ec2;
- initializeSkippedToothTriggerShapeExt(&ec2, 2, 0, FOUR_STROKE_CAM_SENSOR);
+ initializeSkippedToothTriggerShapeExt(&ec2.triggerShape, 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);
@@ -480,10 +461,16 @@ void testTriggerDecoder(void) {
test1995FordInline6TriggerDecoder();
testMazdaMianaNbDecoder();
testGY6_139QMB();
- testFordEscortGt();
+ testTriggerDecoder("testFordEscortGt", FORD_ESCORT_GT, 0);
testMiniCooper();
testRoverV8();
- testCitroen();
+ testTriggerDecoder("testCitroen", CITROEN_TU3JP, 0);
+ testTriggerDecoder("testFordEscortGt", FORD_ESCORT_GT, 0);
+ testTriggerDecoder("testAccordCd 3w", HONDA_ACCORD_CD, 12);
+ testTriggerDecoder("testAccordCd 2w", HONDA_ACCORD_CD_TWO_WIRES, 10);
+ testTriggerDecoder("testAccordCdDip", HONDA_ACCORD_CD_DIP, 27);
+
+ testTriggerDecoder("testMitsu", MITSU_4G93, 3);
testMazda323();
diff --git a/unit_tests/test_util.cpp b/unit_tests/test_util.cpp
index e8a4c4424e..e0a9ba5d6a 100644
--- a/unit_tests/test_util.cpp
+++ b/unit_tests/test_util.cpp
@@ -200,10 +200,10 @@ static void testEchoII(int param, int param2) {
lastInteger2 = param2;
}
-static char *lastFirst = NULL;
-static char *lastThird = NULL;
+static const char *lastFirst = NULL;
+static const char *lastThird = NULL;
-static void testEchoSSS(char *first, char *second, char *third) {
+static void testEchoSSS(const char *first, const char *second, const char *third) {
lastFirst = first;
lastThird = third;
}