manual sync

This commit is contained in:
rusefi 2014-07-09 21:15:49 -04:00
parent 93b522b2aa
commit 6803af5650
177 changed files with 3326 additions and 1957 deletions

View File

@ -140,6 +140,10 @@
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/ports/common/ARMCMx/CMSIS/include}&quot;"/>
</option>
<option id="org.eclipse.cdt.cross.arm.gnu.cpp.compiler.option.other.otherflags.1439013659" name="Other flags" superClass="org.eclipse.cdt.cross.arm.gnu.cpp.compiler.option.other.otherflags" value="-c -fmessage-length=0 -std=c++11 -Werror=write-strings" valueType="string"/>
<option id="org.eclipse.cdt.cross.arm.gnu.cpp.compiler.option.preprocessor.def.1500938905" name="Defined symbols (-D)" superClass="org.eclipse.cdt.cross.arm.gnu.cpp.compiler.option.preprocessor.def" valueType="definedSymbols">
<listOptionValue builtIn="false" value="CORTEX_USE_FPU=TRUE"/>
</option>
<option id="org.eclipse.cdt.cross.arm.gnu.cpp.compiler.option.optimization.flags.1776181591" name="Other optimization flags" superClass="org.eclipse.cdt.cross.arm.gnu.cpp.compiler.option.optimization.flags" value="-mfloat-abi=softfp -mfpu=fpv4-sp-d16 -fsingle-precision-constant" valueType="string"/>
<inputType id="org.eclipse.cdt.cross.arm.gnu.sourcery.windows.cpp.compiler.base.input.1939416167" superClass="org.eclipse.cdt.cross.arm.gnu.sourcery.windows.cpp.compiler.base.input"/>
</tool>
<tool id="org.eclipse.cdt.cross.arm.gnu.sourcery.windows.elf.c.linker.debug.369587711" name="ARM Sourcery Windows GCC C Linker" superClass="org.eclipse.cdt.cross.arm.gnu.sourcery.windows.elf.c.linker.debug"/>
@ -299,6 +303,10 @@
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/ports/common/ARMCMx}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/chibios/os/ports/common/ARMCMx/CMSIS/include}&quot;"/>
</option>
<option id="org.eclipse.cdt.cross.arm.gnu.cpp.compiler.option.preprocessor.def.104404165" superClass="org.eclipse.cdt.cross.arm.gnu.cpp.compiler.option.preprocessor.def" valueType="definedSymbols">
<listOptionValue builtIn="false" value="CORTEX_USE_FPU=TRUE"/>
</option>
<option id="org.eclipse.cdt.cross.arm.gnu.cpp.compiler.option.optimization.flags.514837677" superClass="org.eclipse.cdt.cross.arm.gnu.cpp.compiler.option.optimization.flags" value="-mfloat-abi=softfp -mfpu=fpv4-sp-d16 -fsingle-precision-constant" valueType="string"/>
<inputType id="org.eclipse.cdt.cross.arm.gnu.sourcery.windows.cpp.compiler.base.input.815685204" superClass="org.eclipse.cdt.cross.arm.gnu.sourcery.windows.cpp.compiler.base.input"/>
</tool>
<tool id="org.eclipse.cdt.cross.arm.gnu.sourcery.windows.elf.c.linker.release.1692652942" name="ARM Sourcery Windows GCC C Linker" superClass="org.eclipse.cdt.cross.arm.gnu.sourcery.windows.elf.c.linker.release"/>

2
firmware/.gitignore vendored
View File

@ -1,2 +0,0 @@
.dep
build

View File

@ -293,7 +293,8 @@ ULIBS = -lm
##############################################################################
ifeq ($(USE_FPU),yes)
USE_OPT += -mfloat-abi=hard -mfpu=fpv4-sp-d16 -fsingle-precision-constant
USE_OPT += -mfloat-abi=hard -mfpu=fpv4-sp-d16 -fsingle-precision-constant
USE_CPPOPT += -mfloat-abi=hard -mfpu=fpv4-sp-d16 -fsingle-precision-constant
DDEFS += -DCORTEX_USE_FPU=TRUE
else
DDEFS += -DCORTEX_USE_FPU=FALSE

View File

@ -60,19 +60,11 @@
#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6)
#define EFI_CAN_DEVICE CAND2
#define EFI_CAN_RX_PORT GPIOB
#define EFI_CAN_RX_PIN 12
#define EFI_CAN_RX_AF 9
#define EFI_CAN_TX_PORT GPIOB
#define EFI_CAN_TX_PIN 6
#define EFI_CAN_TX_AF 9
//#define EFI_CAN_DEVICE CAND1
//#define EFI_CAN_RX_PORT GPIOB
//#define EFI_CAN_RX_PIN 8
//#define EFI_CAN_RX_AF 9
//#define EFI_CAN_TX_PORT GPIOB
//#define EFI_CAN_TX_PIN 9
//#define EFI_CAN_TX_AF 9
/**
@ -230,4 +222,10 @@
#define GPS_SERIAL_TX_PIN 6
#define GPS_SERIAL_RX_PIN 7
#define CONSOLE_MODE_SWITCH_PORT GPIOB
#define CONSOLE_MODE_SWITCH_PIN 1
#define CONFIG_RESET_SWITCH_PORT GPIOD
#define CONFIG_RESET_SWITCH_PIN 6
#endif /*ARRO_BOARD_H_*/

View File

@ -105,17 +105,17 @@
#define EFI_SUPPORT_NISSAN_PRIMERA TRUE
#define EFI_SUPPORT_1995_FORD_INLINE_6 TRUE
#define EFI_WAVE_CHART TRUE
#define EFI_HISTOGRAMS TRUE
#define EFI_ANALOG_CHART TRUE
#if defined __GNUC__
#define EFI_PERF_METRICS TRUE
#define EFI_ANALOG_CHART TRUE
#define EFI_WAVE_CHART TRUE
#define DL_OUTPUT_BUFFER 9000
#else
// todo: CCM usage for IAR?
#define EFI_PERF_METRICS FALSE
#define EFI_ANALOG_CHART FALSE
#define EFI_WAVE_CHART FALSE
#define DL_OUTPUT_BUFFER 6000
#define DL_OUTPUT_BUFFER 9000
#endif
/**

View File

@ -14,7 +14,7 @@ void setGy6139qmbDefaultEngineConfiguration(engine_configuration_s *engineConfig
engineConfiguration->rpmHardLimit = 9000;
engineConfiguration->crankingSettings.crankingRpm = 800;
engineConfiguration->analogInputDividerCoefficient = 1.52;
engineConfiguration->engineLoadMode = LM_MAP;
engineConfiguration->algorithm = LM_MAP;
engineConfiguration->globalTriggerAngleOffset = 15;
engineConfiguration->analogChartMode = AC_MAP;
engineConfiguration->cylindersCount = 1;
@ -27,6 +27,6 @@ void setGy6139qmbDefaultEngineConfiguration(engine_configuration_s *engineConfig
*/
engineConfiguration->triggerConfig.totalToothCount = 1;
engineConfiguration->triggerConfig.skippedToothCount = 0;
engineConfiguration->triggerConfig.isSynchronizationNeeded = FALSE;
engineConfiguration->needSecondTriggerInput = FALSE;
engineConfiguration->triggerConfig.isSynchronizationNeeded = false;
engineConfiguration->needSecondTriggerInput = false;
}

View File

@ -28,7 +28,7 @@
extern engine_configuration2_s engineConfiguration2;
void configureShaftPositionEmulatorShape(PwmConfig *state) {
static void configureShaftPositionEmulatorShapeWhat(PwmConfig *state) {
/**
* One signal per cam shaft revolution
*/
@ -40,11 +40,6 @@ void configureShaftPositionEmulatorShape(PwmConfig *state) {
weComplexInit("distributor", state, 0, 2, switchTimes, 1, pinStates);
}
void configureEngineEventHandler(EventHandlerConfiguration *config) {
registerActuatorEvent(&config->ignitionEvents, 0, 1, 0);
registerActuatorEvent(&config->ignitionEvents, 0, 2, 90);
}
void setDefaultEngineConfiguration(EngineConfiguration *engineConfiguration) {
engineConfiguration2.shaftPositionEventCount = 2;
}

View File

@ -1,7 +1,10 @@
/**
* @file citroenBerlingoTU3JP.cpp
*
* CITROEN_TU3JP 15
* CITROEN_TU3JP: engine_type 15
*
* This config overrides some values of the default configuration which is set by setDefaultConfiguration() method
*
*
* @date Apr 15, 2014
* @author Andrey Belomutskiy, (c) 2012-2014
@ -12,9 +15,11 @@
void setCitroenBerlingoTU3JPConfiguration(engine_configuration_s *engineConfiguration, board_configuration_s *boardConfiguration) {
engineConfiguration->engineType = CITROEN_TU3JP;
engineConfiguration->triggerConfig.triggerType = TT_TOOTHED_WHEEL;
engineConfiguration->triggerConfig.totalToothCount = 60;
engineConfiguration->triggerConfig.skippedToothCount = 2;
//engineConfiguration->triggerConfig.triggerType = todo 60_2
setToothedWheelConfiguration(engineConfiguration, 60, 2);
setTriggerSynchronizationGap(&engineConfiguration->triggerConfig, 2.5);
// set_cranking_injection_mode 0

View File

@ -3,6 +3,8 @@
*
* DODGE_NEON_1995 = 2
*
* This config overrides some values of the default configuration which is set by setDefaultConfiguration() method
*
* @date Dec 16, 2013
* @author Andrey Belomutskiy, (c) 2012-2014
*/
@ -21,7 +23,7 @@ void setDodgeNeonEngineConfiguration(engine_configuration_s *engineConfiguration
engineConfiguration->triggerConfig.triggerType = TT_DODGE_NEON;
engineConfiguration->engineLoadMode = LM_TPS;
engineConfiguration->algorithm = LM_TPS;
// set_rpm_hard_limit 4000
engineConfiguration->rpmHardLimit = 4000; // yes, 4k. let's play it safe for now
@ -40,10 +42,10 @@ void setDodgeNeonEngineConfiguration(engine_configuration_s *engineConfiguration
// set_whole_fuel_map 3
setWholeFuelMap(engineConfiguration, 3);
setTriggerSynchronizationGap(engineConfiguration, 0.72);
setTriggerSynchronizationGap(&engineConfiguration->triggerConfig, 0.72);
engineConfiguration->triggerConfig.useRiseEdge = FALSE;
engineConfiguration->needSecondTriggerInput = TRUE;
engineConfiguration->triggerConfig.useRiseEdge = false;
engineConfiguration->needSecondTriggerInput = true;
// set_cranking_injection_mode 0
engineConfiguration->crankingInjectionMode = IM_SIMULTANEOUS;

View File

@ -4,6 +4,8 @@
*
* http://rusefi.com/forum/viewtopic.php?f=3&t=469
*
* This config overrides some values of the default configuration which is set by setDefaultConfiguration() method
*
* FORD_INLINE_6_1995 = 7
*
* @date Feb 12, 2014
@ -38,12 +40,9 @@ void setFordInline6(engine_configuration_s *engineConfiguration, board_configura
/**
* We treat the trigger as 6/0 toothed wheel
*/
engineConfiguration->triggerConfig.triggerType = TT_TOOTHED_WHEEL;
engineConfiguration->triggerConfig.totalToothCount = 6;
engineConfiguration->triggerConfig.skippedToothCount = 0;
engineConfiguration->triggerConfig.isSynchronizationNeeded = FALSE;
setToothedWheelConfiguration(engineConfiguration, 6, 0);
engineConfiguration->triggerConfig.useRiseEdge = TRUE;
engineConfiguration->needSecondTriggerInput = FALSE;
engineConfiguration->needSecondTriggerInput = false;
engineConfiguration->globalTriggerAngleOffset = 0;
engineConfiguration->ignitionOffset = 13;

View File

@ -119,8 +119,7 @@ void setFordAspireEngineConfiguration(engine_configuration_s *engineConfiguratio
setSingleCoilDwell(engineConfiguration);
engineConfiguration->ignitionMode = IM_ONE_COIL;
engineConfiguration->triggerConfig.triggerType = TT_FORD_ASPIRE;
engineConfiguration->triggerConfig.isSynchronizationNeeded = FALSE;
engineConfiguration->triggerConfig.isSynchronizationNeeded = false;
boardConfiguration->injectionPins[4] = GPIO_NONE;
boardConfiguration->injectionPins[5] = GPIO_NONE;

View File

@ -23,8 +23,6 @@ void setFordEscortGt(engine_configuration_s *engineConfiguration, board_configur
// set_injection_offset 510
engineConfiguration->injectionOffset = 59;
setSingleCoilDwell(engineConfiguration);
engineConfiguration->ignitionMode = IM_ONE_COIL;

View File

@ -20,8 +20,7 @@ void setFordFiestaDefaultEngineConfiguration(engine_configuration_s *engineConfi
engineConfiguration->rpmHardLimit = 7000;
setOperationMode(engineConfiguration, FOUR_STROKE_CRANK_SENSOR);
engineConfiguration->triggerConfig.totalToothCount = 36;
engineConfiguration->triggerConfig.skippedToothCount = 1;
setToothedWheelConfiguration(engineConfiguration, 36, 1);
engineConfiguration->ignitionMode = IM_WASTED_SPARK;
engineConfiguration->firingOrder = FO_1_THEN_3_THEN_4_THEN2;

View File

@ -16,8 +16,5 @@ void setMazda323EngineConfiguration(engine_configuration_s *engineConfiguration)
/**
* We treat the trigger as 4/0 toothed wheel
*/
engineConfiguration->triggerConfig.totalToothCount = 4;
engineConfiguration->triggerConfig.skippedToothCount = 0;
engineConfiguration->triggerConfig.isSynchronizationNeeded = FALSE;
setToothedWheelConfiguration(engineConfiguration, 4, 0);
}

View File

@ -17,8 +17,8 @@ void setMazdaMiataNbEngineConfiguration(engine_configuration_s *engineConfigurat
engineConfiguration->triggerConfig.triggerType = TT_MAZDA_MIATA_NB;
setTriggerSynchronizationGap(engineConfiguration, 0.11);
engineConfiguration->triggerConfig.useRiseEdge = FALSE;
setTriggerSynchronizationGap(&engineConfiguration->triggerConfig, 0.11);
engineConfiguration->triggerConfig.useRiseEdge = false;
engineConfiguration->globalTriggerAngleOffset = 276;
// set_cranking_injection_mode 0

View File

@ -13,8 +13,7 @@
#include "nissan_primera.h"
void setNissanPrimeraEngineConfiguration(engine_configuration_s *engineConfiguration) {
engineConfiguration->triggerConfig.totalToothCount = 60;
engineConfiguration->triggerConfig.skippedToothCount = 2;
setToothedWheelConfiguration(engineConfiguration, 60, 2);
}
#endif /* EFI_SUPPORT_NISSAN_PRIMERA */

View File

@ -3,6 +3,8 @@
*
* V8, firing order 18436572
*
* This config overrides some values of the default configuration which is set by setDefaultConfiguration() method
*
* ROVER_V8 = 10
*
* @date Jun 27, 2014
@ -16,11 +18,9 @@ void setRoverv8(engine_configuration_s *engineConfiguration,
board_configuration_s *boardConfiguration) {
setOperationMode(engineConfiguration, FOUR_STROKE_CRANK_SENSOR);
engineConfiguration->triggerConfig.totalToothCount = 36;
engineConfiguration->triggerConfig.skippedToothCount = 1;
setToothedWheelConfiguration(engineConfiguration, 36, 1);
// todo: displacement? 4 liters?
engineConfiguration->displacement = 4;
engineConfiguration->displacement = 3.528;
engineConfiguration->cylindersCount = 8;
engineConfiguration->firingOrder = FO_1_8_4_3_6_5_7_2;
@ -33,8 +33,8 @@ void setRoverv8(engine_configuration_s *engineConfiguration,
setWholeFuelMap(engineConfiguration, 3);
// set_cranking_injection_mode 0
engineConfiguration->crankingInjectionMode = IM_SEQUENTIAL;
// set_cranking_injection_mode 0
engineConfiguration->crankingInjectionMode = IM_SIMULTANEOUS;
// set_injection_mode 1
engineConfiguration->injectionMode = IM_SEQUENTIAL;

View File

@ -31,7 +31,7 @@ extern SerialUSBDriver SDU1;
int lastWriteSize;
int lastWriteActual;
static bool_t isSerialConsoleStarted = FALSE;
static bool isSerialConsoleStarted = false;
static EventListener consoleEventListener;
@ -99,7 +99,7 @@ static bool getConsoleLine(BaseSequentialStream *chp, char *line, unsigned size)
consolePutChar('\r');
consolePutChar('\n');
*p = 0;
return FALSE;
return false;
}
if (c < 0x20)
continue;
@ -136,7 +136,7 @@ static msg_t consoleThreadThreadEntryPoint(void *arg) {
(console_line_callback)(consoleInput);
}
#if defined __GNUC__
return FALSE;
return false;
#endif
}
@ -182,7 +182,10 @@ void startConsole(void (*console_line_callback_p)(char *)) {
console_line_callback = console_line_callback_p;
#if EFI_PROD_CODE
is_serial_over_uart = palReadPad(GPIOA, GPIOA_BUTTON) != EFI_USE_UART_FOR_CONSOLE;
palSetPadMode(CONSOLE_MODE_SWITCH_PORT, CONSOLE_MODE_SWITCH_PIN, PAL_MODE_INPUT_PULLUP);
is_serial_over_uart = GET_CONSOLE_MODE_VALUE() == EFI_USE_UART_FOR_CONSOLE;
if (isSerialOverUart()) {
/*
@ -221,10 +224,10 @@ bool lockAnyContext(void) {
chSysLock()
;
}
return FALSE;
return false;
}
bool_t lockOutputBuffer(void) {
bool lockOutputBuffer(void) {
return lockAnyContext();
}

View File

@ -21,6 +21,9 @@
#include "efifeatures.h"
#include "boards.h"
#define GET_CONSOLE_MODE_VALUE() palReadPad(CONSOLE_MODE_SWITCH_PORT, CONSOLE_MODE_SWITCH_PIN)
#define SHOULD_INGORE_FLASH() (palReadPad(CONFIG_RESET_SWITCH_PORT, CONFIG_RESET_SWITCH_PIN) == 0)
#ifdef __cplusplus
extern "C"
{

View File

@ -161,7 +161,6 @@ void printState(int currentCkpEventCounter) {
int rpm = getRpm();
debugInt(&logger, "ckp_c", currentCkpEventCounter);
debugInt(&logger, "fuel_lag", getRevolutionCounter());
// debugInt(&logger, "idl", getIdleSwitch());
@ -171,7 +170,7 @@ void printState(int currentCkpEventCounter) {
debugFloat(&logger, "fuel_base", getBaseFuel(rpm, engineLoad), 2);
// debugFloat(&logger, "fuel_iat", getIatCorrection(getIntakeAirTemperature()), 2);
// debugFloat(&logger, "fuel_clt", getCltCorrection(getCoolantTemperature()), 2);
// debugFloat(&logger, "fuel_lag", getInjectorLag(getVBatt()), 2);
debugFloat(&logger, "fuel_lag", getInjectorLag(getVBatt()), 2);
debugFloat(&logger, "fuel", getRunningFuel(rpm, engineLoad), 2);
debugFloat(&logger, "timing", getAdvance(rpm, engineLoad), 2);
@ -298,26 +297,27 @@ void updateDevConsoleState(void) {
* that would be 'show fuel for rpm 3500 maf 4.0'
*/
static void showFuelMap(int rpm, int key100) {
float engineLoad = key100 / 100.0;
static void showFuelMap2(float rpm, float engineLoad) {
float baseFuel = getBaseFuel(rpm, engineLoad);
float iatCorrection = getIatCorrection(getIntakeAirTemperature());
float cltCorrection = getCltCorrection(getCoolantTemperature());
float injectorLag = getInjectorLag(getVBatt());
print("baseFuel=%f\r\n", baseFuel);
scheduleMsg(&logger2, "rpm=%f engineLoad=%f", rpm, engineLoad);
scheduleMsg(&logger2, "baseFuel=%f", baseFuel);
print("iatCorrection=%f cltCorrection=%f injectorLag=%d\r\n", iatCorrection, cltCorrection,
(int) (100 * injectorLag));
scheduleMsg(&logger2, "iatCorrection=%f cltCorrection=%f injectorLag=%f", iatCorrection, cltCorrection,
injectorLag);
float value = getRunningFuel(rpm, engineLoad);
print("fuel map rpm=%d, key=%f: %d\r\n", rpm, engineLoad, (int) (100 * value));
scheduleMsg(&logger2, "fuel map value = %f", value);
scheduleMsg(&logger2, "injection pulse width: %f", value);
}
static void showFuelMap(void) {
showFuelMap2(getRpm(), getEngineLoad());
}
static char buffer[10];
static char dateBuffer[30];
@ -415,7 +415,8 @@ void initStatusLoop(void) {
#if EFI_PROD_CODE
initLogging(&logger2, "main event handler");
addConsoleActionII("sfm", showFuelMap);
addConsoleActionFF("fuelinfo2", showFuelMap2);
addConsoleAction("fuelinfo", showFuelMap);
addConsoleAction("status", printStatus);
#endif /* EFI_PROD_CODE */

View File

@ -26,12 +26,9 @@
#include "engine_state.h"
#include "tunerstudio.h"
#include "pin_repository.h"
#include "main_trigger_callback.h"
#include "flash_main.h"
#include "usbconsole.h"
#include "map_averaging.h"
#include "tunerstudio_algo.h"
#include "tunerstudio_configuration.h"
@ -42,27 +39,40 @@
#if EFI_TUNER_STUDIO
#define MAX_PAGE_ID 5
#define PAGE_0_SIZE 1356
// in MS, that's 10 seconds
#define TS_READ_TIMEOUT 10000
#if EFI_PROD_CODE
#include "pin_repository.h"
#include "usbconsole.h"
#include "map_averaging.h"
extern SerialUSBDriver SDU1;
#define CONSOLE_DEVICE &SDU1
#define TS_SERIAL_UART_DEVICE &SD3
//#define TS_SERIAL_SPEED 115200
#define TS_SERIAL_SPEED 38400
static SerialConfig tsSerialConfig = { TS_SERIAL_SPEED, 0, USART_CR2_STOP1_BITS | USART_CR2_LINEN, 0 };
#endif /* EFI_PROD_CODE */
#define MAX_PAGE_ID 0
#define PAGE_0_SIZE 5804
// in MS, that's 10 seconds
#define TS_READ_TIMEOUT 10000
#define PROTOCOL "001"
extern SerialUSBDriver SDU1;
BaseChannel * getTsSerialDevice(void) {
#if EFI_PROD_CODE
if (isSerialOverUart()) {
// if console uses UART then TS uses USB
return (BaseChannel *) &SDU1;
} else {
return (BaseChannel *) TS_SERIAL_UART_DEVICE;
}
#else
return (BaseChannel *) TS_SIMULATOR_PORT;
#endif
}
static Logging logger;
@ -71,12 +81,10 @@ extern engine_configuration_s *engineConfiguration;
extern persistent_config_s configWorkingCopy;
extern persistent_config_container_s persistentState;
extern SerialUSBDriver SDU1;
#define CONSOLE_DEVICE &SDU1
static efitimems_t previousWriteReportMs = 0;
static int ts_serail_ready(void) {
#if EFI_PROD_CODE
if (isSerialOverUart()) {
// TS uses USB when console uses serial
return is_usb_serial_ready();
@ -84,10 +92,11 @@ static int ts_serail_ready(void) {
// TS uses serial when console uses USB
return TRUE;
}
#else
return TRUE;
#endif
}
static SerialConfig tsSerialConfig = { TS_SERIAL_SPEED, 0, USART_CR2_STOP1_BITS | USART_CR2_LINEN, 0 };
static THD_WORKING_AREA(TS_WORKING_AREA, UTILITY_THREAD_STACK_SIZE);
static int tsCounter = 0;
@ -100,10 +109,12 @@ extern TunerStudioOutputChannels tsOutputChannels;
extern TunerStudioState tsState;
static void printStats(void) {
#if EFI_PROD_CODE
if (!isSerialOverUart()) {
scheduleMsg(&logger, "TS RX on %s%d", portname(TS_SERIAL_RX_PORT), TS_SERIAL_RX_PIN);
scheduleMsg(&logger, "TS TX on %s%d", portname(TS_SERIAL_TX_PORT), TS_SERIAL_TX_PIN);
}
#endif /* EFI_PROD_CODE */
scheduleMsg(&logger, "TunerStudio total/error counter=%d/%d", tsCounter, tsState.errorCounter);
scheduleMsg(&logger, "TunerStudio H counter=%d", tsState.queryCommandCounter);
scheduleMsg(&logger, "TunerStudio O counter=%d size=%d", tsState.outputChannelsCommandCounter,
@ -113,15 +124,34 @@ static void printStats(void) {
scheduleMsg(&logger, "TunerStudio W counter=%d", tsState.writeValueCommandCounter);
scheduleMsg(&logger, "TunerStudio C counter=%d", tsState.writeChunkCommandCounter);
scheduleMsg(&logger, "TunerStudio P counter=%d current page %d", tsState.pageCommandCounter, tsState.currentPageId);
scheduleMsg(&logger, "pages total size=%d", sizeof(engine_configuration_s));
scheduleMsg(&logger, "page 0 size=%d", getTunerStudioPageSize(0));
scheduleMsg(&logger, "page 1 size=%d", getTunerStudioPageSize(1));
// scheduleMsg(&logger, "timingMode %d", (int)(&engineConfiguration->timingMode) - (int)engineConfiguration);
// scheduleMsg(&logger, "cylindersCount %d", (int)(&engineConfiguration->cylindersCount) - (int)engineConfiguration);
scheduleMsg(&logger, "analogChartFrequency %d",
(int) (&engineConfiguration->analogChartFrequency) - (int) engineConfiguration);
int fuelMapOffset = (int) (&engineConfiguration->fuelTable) - (int) engineConfiguration;
scheduleMsg(&logger, "fuelTable %d", fuelMapOffset);
int offset = (int) (&engineConfiguration->bc.injectionPinMode) - (int) engineConfiguration;
scheduleMsg(&logger, "injectionPinMode %d", offset);
offset = (int) (&engineConfiguration->bc.idleThreadPeriod) - (int) engineConfiguration;
scheduleMsg(&logger, "idleThreadPeriod %d", offset);
if (sizeof(engine_configuration_s) != getTunerStudioPageSize(0))
firmwareError("TS page size mismatch");
}
void tunerStudioWriteData(const uint8_t * buffer, int size) {
chSequentialStreamWrite(getTsSerialDevice(), buffer, size);
}
void tunerStudioDebug(char *msg) {
void tunerStudioDebug(const char *msg) {
#if EFI_TUNER_STUDIO_VERBOSE
scheduleMsg(&logger, "%s", msg);
printStats();
@ -132,13 +162,13 @@ char *getWorkingPageAddr(int pageIndex) {
switch (pageIndex) {
case 0:
return (char*) &configWorkingCopy.engineConfiguration;
case 1:
return (char*) &configWorkingCopy.boardConfiguration;
case 2: // fuelTable
case 3: // ignitionTable
case 4: // veTable
case 5: // afrTable
return (char*) &configWorkingCopy.engineConfiguration + PAGE_0_SIZE + (pageIndex - 2) * 1024;
// case 1:
// return (char*) &configWorkingCopy.boardConfiguration;
// case 2: // fuelTable
// case 3: // ignitionTable
// case 4: // veTable
// case 5: // afrTable
// return (char*) &configWorkingCopy.engineConfiguration + PAGE_0_SIZE + (pageIndex - 2) * 1024;
}
return NULL;
}
@ -147,58 +177,56 @@ int getTunerStudioPageSize(int pageIndex) {
switch (pageIndex) {
case 0:
return PAGE_0_SIZE;
case 1:
return sizeof(configWorkingCopy.boardConfiguration);
case 2:
case 3:
case 4:
return 1024;
// case 1:
// return sizeof(configWorkingCopy.boardConfiguration);
// case 2:
// case 3:
// case 4:
// return 1024;
}
return 0;
}
void handlePageSelectCommand(uint16_t pageId) {
void handlePageSelectCommand(ts_response_format_e mode, uint16_t pageId) {
tsState.pageCommandCounter++;
tsState.currentPageId = pageId;
scheduleMsg(&logger, "page %d selected", tsState.currentPageId);
tunerStudioWriteCrcPacket(TS_RESPONSE_OK, NULL, 0);
tsSendResponse(mode, NULL, 0);
}
/**
* This command is needed to make the whole transfer a bit faster
* @note See also handleWriteValueCommand
*/
void handleWriteChunkCommand(short offset, short count, void *content) {
void handleWriteChunkCommand(ts_response_format_e mode, short offset, short count, void *content) {
tsState.writeChunkCommandCounter++;
scheduleMsg(&logger, "receiving page %d chunk offset %d size %d", tsState.currentPageId, offset, count);
if (offset > getTunerStudioPageSize(tsState.currentPageId)) {
scheduleMsg(&logger, "ERROR offset %d", offset);
// out of range
tsState.errorCounter++;
tunerStudioError("ERROR: out of range");
offset = 0;
}
if (count > getTunerStudioPageSize(tsState.currentPageId)) {
tunerStudioError("ERROR: unexpected count");
scheduleMsg(&logger, "ERROR count %d", count);
// out of range
tsState.errorCounter++;
count = 0;
}
uint8_t * addr = (uint8_t *) (getWorkingPageAddr(tsState.currentPageId) + offset);
// memcpy(addr, content, count);
memcpy(addr, content, count);
tunerStudioWriteCrcPacket(TS_RESPONSE_OK, NULL, 0);
tsSendResponse(mode, NULL, 0);
}
/**
* 'Write' command receives a single value at a given offset
* @note Writing values one by one is pretty slow
*/
void handleWriteValueCommand(uint16_t page, uint16_t offset, uint8_t value) {
void handleWriteValueCommand(ts_response_format_e mode, uint16_t page, uint16_t offset, uint8_t value) {
tsState.writeValueCommandCounter++;
tsState.currentPageId = page;
@ -213,9 +241,8 @@ void handleWriteValueCommand(uint16_t page, uint16_t offset, uint8_t value) {
// scheduleMsg(&logger, "Reading %d\r\n", size);
if (offset > getTunerStudioPageSize(tsState.currentPageId)) {
tunerStudioError("ERROR: out of range2");
scheduleMsg(&logger, "ERROR offset %d", offset);
// out of range
tsState.errorCounter++;
offset = 0;
return;
}
@ -235,7 +262,7 @@ static void sendErrorCode(void) {
tunerStudioWriteCrcPacket(TS_RESPONSE_CRC_FAILURE, NULL, 0);
}
void handlePageReadCommand(uint16_t pageId, uint16_t offset, uint16_t count) {
void handlePageReadCommand(ts_response_format_e mode, uint16_t pageId, uint16_t offset, uint16_t count) {
tsState.readPageCommandsCounter++;
tunerStudioDebug("got R (Read page)");
tsState.currentPageId = pageId;
@ -249,7 +276,7 @@ void handlePageReadCommand(uint16_t pageId, uint16_t offset, uint16_t count) {
// something is not right here
tsState.currentPageId = 0;
tsState.errorCounter++;
tunerStudioError("ERROR: invalid page");
return;
}
@ -262,16 +289,16 @@ void handlePageReadCommand(uint16_t pageId, uint16_t offset, uint16_t count) {
}
const uint8_t *addr = (const uint8_t *) (getWorkingPageAddr(tsState.currentPageId) + offset);
tunerStudioWriteCrcPacket(TS_RESPONSE_OK, addr, count);
tsSendResponse(mode, addr, count);
#if EFI_TUNER_STUDIO_VERBOSE
scheduleMsg(&logger, "Sending %d done", size);
scheduleMsg(&logger, "Sending %d done", count);
#endif
}
/**
* 'Burn' command is a command to commit the changes
*/
void handleBurnCommand(uint16_t page) {
void handleBurnCommand(ts_response_format_e mode, uint16_t page) {
tsState.burnCommandCounter++;
tunerStudioDebug("got B (Burn)");
@ -285,14 +312,59 @@ void handleBurnCommand(uint16_t page) {
// todo: how about some multi-threading?
memcpy(&persistentState.persistentConfiguration, &configWorkingCopy, sizeof(persistent_config_s));
scheduleMsg(&logger, "va1=%d", configWorkingCopy.boardConfiguration.idleValvePin);
scheduleMsg(&logger, "va2=%d", persistentState.persistentConfiguration.boardConfiguration.idleValvePin);
scheduleMsg(&logger, "va1=%d", configWorkingCopy.engineConfiguration.bc.idleValvePin);
scheduleMsg(&logger, "va2=%d", persistentState.persistentConfiguration.engineConfiguration.bc.idleValvePin);
#if EFI_INTERNAL_FLASH
writeToFlash();
#endif
incrementGlobalConfigurationVersion();
tunerStudioWriteCrcPacket(TS_RESPONSE_BURN_OK, NULL, 0);
}
static TunerStudioReadRequest readRequest;
static short int pageIn;
static bool handlePlainCommand(uint8_t command) {
if (command == TS_HELLO_COMMAND) {
scheduleMsg(&logger, "Got naked Query command");
handleQueryCommand(TS_PLAIN);
return true;
} else if (command == 't' || command == 'T') {
handleTestCommand();
return true;
} else if (command == TS_PAGE_COMMAND) {
int recieved = chSequentialStreamRead(getTsSerialDevice(), (uint8_t *)&pageIn, sizeof(pageIn));
handlePageSelectCommand(TS_PLAIN, pageIn);
return true;
} else if (command == TS_READ_COMMAND) {
//scheduleMsg(&logger, "Got naked READ PAGE???");
int recieved = chSequentialStreamRead(getTsSerialDevice(), (uint8_t *)&readRequest, sizeof(readRequest));
if (recieved != sizeof(readRequest)) {
// todo: handler error
return true;
}
handlePageReadCommand(TS_PLAIN, readRequest.page, readRequest.offset, readRequest.count);
return true;
} else if (command == TS_OUTPUT_COMMAND) {
//scheduleMsg(&logger, "Got naked Channels???");
handleOutputChannelsCommand(TS_PLAIN);
return true;
} else if (command == 'F') {
tunerStudioDebug("not ignoring F");
tunerStudioWriteData((const uint8_t *) PROTOCOL, strlen(PROTOCOL));
return true;
} else {
return false;
}
}
static bool isKnownCommand(char command) {
return command == TS_HELLO_COMMAND || command == TS_READ_COMMAND || command == TS_OUTPUT_COMMAND
|| command == TS_PAGE_COMMAND || command == TS_BURN_COMMAND || command == TS_SINGLE_WRITE_COMMAND
|| command == TS_CHUNK_WRITE_COMMAND;
}
static uint8_t firstByte;
static uint8_t secondByte;
@ -303,12 +375,12 @@ static msg_t tsThreadEntryPoint(void *arg) {
(void) arg;
chRegSetThreadName("tunerstudio thread");
int wasReady = FALSE;
int wasReady = false;
while (true) {
int isReady = ts_serail_ready();
if (!isReady) {
chThdSleepMilliseconds(10);
wasReady = FALSE;
wasReady = false;
continue;
}
@ -321,32 +393,16 @@ static msg_t tsThreadEntryPoint(void *arg) {
int recieved = chSequentialStreamRead(getTsSerialDevice(), &firstByte, 1);
if (recieved != 1) {
tsState.errorCounter++;
tunerStudioError("ERROR: no command");
continue;
}
// scheduleMsg(&logger, "Got first=%x=[%c]", firstByte, firstByte);
if (firstByte == TS_HELLO_COMMAND) {
scheduleMsg(&logger, "Got naked Query command");
handleQueryCommand(FALSE);
if (handlePlainCommand(firstByte))
continue;
} else if (firstByte == 't' || firstByte == 'T') {
handleTestCommand();
continue;
} else if (firstByte == TS_READ_COMMAND) {
scheduleMsg(&logger, "Got naked READ PAGE???");
continue;
} else if (firstByte == TS_OUTPUT_COMMAND) {
scheduleMsg(&logger, "Got naked Channels???");
continue;
} else if (firstByte == 'F') {
tunerStudioDebug("not ignoring F");
tunerStudioWriteData((const uint8_t *) PROTOCOL, strlen(PROTOCOL));
continue;
}
recieved = chSequentialStreamRead(getTsSerialDevice(), &secondByte, 1);
if (recieved != 1) {
tsState.errorCounter++;
tunerStudioError("ERROR: no second");
continue;
}
// scheduleMsg(&logger, "Got secondByte=%x=[%c]", secondByte, secondByte);
@ -355,22 +411,19 @@ static msg_t tsThreadEntryPoint(void *arg) {
if (incomingPacketSize == 0 || incomingPacketSize > sizeof(crcIoBuffer)) {
scheduleMsg(&logger, "TunerStudio: invalid size: %d", incomingPacketSize);
tsState.errorCounter++;
tunerStudioError("ERROR: size");
sendErrorCode();
continue;
}
recieved = chnReadTimeout(getTsSerialDevice(), crcIoBuffer, 1, MS2ST(TS_READ_TIMEOUT));
if (recieved != 1) {
scheduleMsg(&logger, "did not receive command");
tsState.errorCounter++;
tunerStudioError("ERROR: did not receive command");
continue;
}
char command = crcIoBuffer[0];
if (command != TS_HELLO_COMMAND && command != TS_READ_COMMAND && command != TS_OUTPUT_COMMAND
&& command != TS_PAGE_COMMAND && command != TS_BURN_COMMAND && command != TS_SINGLE_WRITE_COMMAND
&& command != TS_CHUNK_WRITE_COMMAND) {
if (!isKnownCommand(command)) {
scheduleMsg(&logger, "unexpected command %x", command);
sendErrorCode();
continue;
@ -380,9 +433,11 @@ static msg_t tsThreadEntryPoint(void *arg) {
recieved = chnReadTimeout(getTsSerialDevice(), (void * ) (crcIoBuffer + 1), incomingPacketSize + 4 - 1,
MS2ST(TS_READ_TIMEOUT));
if (recieved != incomingPacketSize + 4 - 1) {
scheduleMsg(&logger, "got ONLY %d", recieved);
tsState.errorCounter++;
int expectedSize = incomingPacketSize + 4 - 1;
if (recieved != expectedSize) {
scheduleMsg(&logger, "got ONLY %d for packet size %d/%d for command %c", recieved, incomingPacketSize,
expectedSize, command);
tunerStudioError("ERROR: not enough");
continue;
}
@ -398,14 +453,14 @@ static msg_t tsThreadEntryPoint(void *arg) {
scheduleMsg(&logger, "TunerStudio: command %c actual CRC %x/expected %x", crcIoBuffer[0], actualCrc,
expectedCrc);
tsState.errorCounter++;
tunerStudioError("ERROR: CRC issue");
continue;
}
// scheduleMsg(&logger, "TunerStudio: P00-07 %x %x %x %x %x %x %x %x", crcIoBuffer[0], crcIoBuffer[1],
// crcIoBuffer[2], crcIoBuffer[3], crcIoBuffer[4], crcIoBuffer[5], crcIoBuffer[6], crcIoBuffer[7]);
int success = tunerStudioHandleCommand(crcIoBuffer, incomingPacketSize);
int success = tunerStudioHandleCrcCommand(crcIoBuffer, incomingPacketSize);
if (!success)
print("got unexpected TunerStudio command %x:%c\r\n", command, command);
@ -422,6 +477,7 @@ void syncTunerStudioCopy(void) {
void startTunerStudioConnectivity(void) {
initLogging(&logger, "tuner studio");
memset(&tsState, 0, sizeof(tsState));
#if EFI_PROD_CODE
if (isSerialOverUart()) {
print("TunerStudio over USB serial");
usb_serial_start();
@ -433,7 +489,7 @@ void startTunerStudioConnectivity(void) {
sdStart(TS_SERIAL_UART_DEVICE, &tsSerialConfig);
}
#endif /* EFI_PROD_CODE */
syncTunerStudioCopy();
addConsoleAction("tsinfo", printStats);

View File

@ -10,39 +10,46 @@
#include "tunerstudio_configuration.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
void startTunerStudioConnectivity(void);
void syncTunerStudioCopy(void);
void updateTunerStudioState(TunerStudioOutputChannels *tsOutputChannels);
void tunerStudioWriteCrcPacket(const uint8_t command, const void *buf, const uint16_t size);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#if defined __GNUC__
typedef struct
__attribute__((packed)) {
// GCC
#define pre_packed
#define post_packed __attribute__((packed))
#else
typedef __packed struct {
// IAR
#define pre_packed __packed
#define post_packed
#endif
typedef pre_packed struct
post_packed {
short int offset;
short int count;
} TunerStudioWriteChunkRequest;
typedef pre_packed struct
post_packed {
short int page;
short int offset;
short int count;
} TunerStudioReadRequest;
} TunerStudioWriteChunkRequest;
#if defined __GNUC__
typedef struct
__attribute__((packed)) {
#else
typedef __packed struct {
#endif
short int offset;
unsigned char value;
} TunerStudioWriteValueRequest;
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
void startTunerStudioConnectivity(void);
void syncTunerStudioCopy(void);
void updateTunerStudioState(TunerStudioOutputChannels *tsOutputChannels);
void tunerStudioWriteCrcPacket(const uint8_t command, const void *buf, const uint16_t size);
#ifdef __cplusplus
}
#endif /* __cplusplus */
typedef pre_packed struct
post_packed {
short int offset;
unsigned char value;
} TunerStudioWriteValueRequest;
#endif /* TUNERSTUDIO_H_ */

View File

@ -1,3 +1,3 @@
TUNERSTUDIOSRC = console/tunerstudio/tunerstudio_algo.c \
console/tunerstudio/tunerstudio.c
TUNERSTUDIOSRC = $(PROJECT_DIR)/console/tunerstudio/tunerstudio_algo.c \
$(PROJECT_DIR)/console/tunerstudio/tunerstudio.c

View File

@ -65,34 +65,39 @@ TunerStudioOutputChannels tsOutputChannels;
*/
persistent_config_s configWorkingCopy;
int tunerStudioHandleCommand(char *data, int incomingPacketSize) {
void tunerStudioError(const char *msg) {
tunerStudioDebug(msg);
tsState.errorCounter++;
}
int tunerStudioHandleCrcCommand(char *data, int incomingPacketSize) {
char command = data[0];
data++;
if (command == TS_HELLO_COMMAND) {
tunerStudioDebug("got CRC Query");
handleQueryCommand(TRUE);
handleQueryCommand(TS_CRC);
} else if (command == TS_OUTPUT_COMMAND) {
handleOutputChannelsCommand();
handleOutputChannelsCommand(TS_CRC);
} else if (command == TS_PAGE_COMMAND) {
uint16_t page = *(uint16_t *) data;
handlePageSelectCommand(page);
handlePageSelectCommand(TS_CRC, page);
} else if (command == TS_CHUNK_WRITE_COMMAND) {
uint16_t offset = *(uint16_t *) data;
uint16_t count = *(uint16_t *) (data + 2);
handleWriteChunkCommand(offset, count, data + 4);
handleWriteChunkCommand(TS_CRC, offset, count, data + 4);
} else if (command == TS_SINGLE_WRITE_COMMAND) {
uint16_t page = *(uint16_t *) data;
uint16_t offset = *(uint16_t *) (data + 2);
uint8_t value = data[4];
handleWriteValueCommand(page, offset, value);
handleWriteValueCommand(TS_CRC, page, offset, value);
} else if (command == TS_BURN_COMMAND) {
uint16_t page = *(uint16_t *) data;
handleBurnCommand(page);
handleBurnCommand(TS_CRC, page);
} else if (command == TS_READ_COMMAND) {
uint16_t page = *(uint16_t *) data;
uint16_t offset = *(uint16_t *) (data + 2);
uint16_t count = *(uint16_t *) (data + 4);
handlePageReadCommand(page, offset, count);
handlePageReadCommand(TS_CRC, page, offset, count);
} else if (command == 't' || command == 'T') {
handleTestCommand();
} else if (command == 'F') {
@ -105,32 +110,38 @@ int tunerStudioHandleCommand(char *data, int incomingPacketSize) {
* Currently on some firmware versions the F command is not used and is just ignored by the firmware as a unknown command."
*/
} else {
tunerStudioDebug("ignoring unexpected");
tsState.errorCounter++;
tunerStudioError("ERROR: ignoring unexpected command");
return FALSE;
}
return TRUE;
}
void handleQueryCommand(int needCrc) {
void tsSendResponse(ts_response_format_e mode, const uint8_t * buffer, int size) {
if (mode == TS_CRC) {
tunerStudioWriteCrcPacket(TS_RESPONSE_OK, buffer, size);
} else {
if (size > 0)
tunerStudioWriteData(buffer, size);
}
}
/**
* Query with CRC takes place while re-establishing connection
* Query without CRC takes place on TunerStudio startup
*/
void handleQueryCommand(ts_response_format_e mode) {
tsState.queryCommandCounter++;
tunerStudioDebug("got H (queryCommand)");
if (needCrc) {
// Query with CRC takes place while re-establishing connection
tunerStudioWriteCrcPacket(TS_RESPONSE_OK, (const uint8_t *) TS_SIGNATURE, strlen(TS_SIGNATURE) + 1);
} else {
// Query without CRC takes place on TunerStudio startup
tunerStudioWriteData((const uint8_t *) TS_SIGNATURE, strlen(TS_SIGNATURE) + 1);
}
tsSendResponse(mode, (const uint8_t *) TS_SIGNATURE, strlen(TS_SIGNATURE) + 1);
}
/**
* @brief 'Output' command sends out a snapshot of current values
*/
void handleOutputChannelsCommand(void) {
void handleOutputChannelsCommand(ts_response_format_e mode) {
tsState.outputChannelsCommandCounter++;
// this method is invoked too often to print any debug information
tunerStudioWriteCrcPacket(TS_RESPONSE_OK, (const uint8_t *) &tsOutputChannels, sizeof(TunerStudioOutputChannels));
tsSendResponse(mode, (const uint8_t *) &tsOutputChannels, sizeof(TunerStudioOutputChannels));
}
void handleTestCommand(void) {

View File

@ -24,6 +24,11 @@
#define TS_RESPONSE_BURN_OK 0x04
#define TS_RESPONSE_CRC_FAILURE 0x82
typedef enum {
TS_PLAIN = 0,
TS_CRC = 1
} ts_response_format_e;
typedef struct {
int queryCommandCounter;
int outputChannelsCommandCounter;
@ -37,22 +42,25 @@ typedef struct {
short currentPageId;
} TunerStudioState;
int tunerStudioHandleCommand(char *data, int incomingPacketSize);
int tunerStudioHandleCrcCommand(char *data, int incomingPacketSize);
void handleTestCommand(void);
void handleQueryCommand(int needCrc);
void handleOutputChannelsCommand(void);
void handleQueryCommand(ts_response_format_e mode);
void tsSendResponse(ts_response_format_e mode, const uint8_t * buffer, int size);
void handleOutputChannelsCommand(ts_response_format_e mode);
char *getWorkingPageAddr(int pageIndex);
int getTunerStudioPageSize(int pageIndex);
void handleWriteValueCommand(uint16_t page, uint16_t offset, uint8_t value);
void handleWriteChunkCommand(short offset, short count, void *content);
void handlePageSelectCommand(uint16_t pageId);
void handlePageReadCommand(uint16_t pageId, uint16_t offset, uint16_t count);
void handleBurnCommand(uint16_t page);
void handleWriteValueCommand(ts_response_format_e mode, uint16_t page, uint16_t offset, uint8_t value);
void handleWriteChunkCommand(ts_response_format_e mode, short offset, short count, void *content);
void handlePageSelectCommand(ts_response_format_e mode, uint16_t pageId);
void handlePageReadCommand(ts_response_format_e mode, uint16_t pageId, uint16_t offset, uint16_t count);
void handleBurnCommand(ts_response_format_e mode, uint16_t page);
void tunerStudioWriteData(const uint8_t * buffer, int size);
void tunerStudioDebug(char *msg);
void tunerStudioDebug(const char *msg);
void tunerStudioError(const char *msg);
#define TS_HELLO_COMMAND 'H'
#define TS_OUTPUT_COMMAND 'O'

View File

@ -66,8 +66,7 @@ static int validateBuffer(Logging *logging, int extraLen, const char *text) {
return TRUE;
}
int currentLen = loggingSize(logging);
if (currentLen + extraLen > logging->bufferSize - 1) {
if (remainingSize(logging) < extraLen + 1) {
strcpy(logging->SMALL_BUFFER, "Logging buffer overflow: ");
strcat(logging->SMALL_BUFFER, logging->name);
strcat(logging->SMALL_BUFFER, "/");
@ -90,6 +89,22 @@ void append(Logging *logging, const char *text) {
logging->linePointer += extraLen;
}
/**
* @note This method if fast because it does not validate much, be sure what you are doing
*/
void appendFast(Logging *logging, const char *text) {
// todo: fix this implementation? this would be a one-pass implementation instead of a two-pass
// char c;
// char *s = (char *) text;
// do {
// c = *s++;
// *logging->linePointer++ = c;
// } while (c != '\0');
int extraLen = strlen(text);
strcpy(logging->linePointer, text);
logging->linePointer += extraLen;
}
static void vappendPrintfI(Logging *logging, const char *fmt, va_list arg) {
intermediateLoggingBuffer.eos = 0; // reset
chvprintf((BaseSequentialStream *) &intermediateLoggingBuffer, fmt, arg);
@ -365,8 +380,8 @@ void scheduleLogging(Logging *logging) {
resetLogging(logging);
}
uint32_t loggingSize(Logging *logging) {
return (int) logging->linePointer - (int) (logging->buffer);
uint32_t remainingSize(Logging *logging) {
return logging->bufferSize - loggingSize(logging);
}
/**

View File

@ -43,11 +43,13 @@ extern "C"
{
#endif /* __cplusplus */
bool_t lockOutputBuffer(void);
bool lockOutputBuffer(void);
void unlockOutputBuffer(void);
void initIntermediateLoggingBuffer(void);
uint32_t loggingSize(Logging *logging);
uint32_t remainingSize(Logging *logging);
#define loggingSize(logging) ((int) (logging)->linePointer - (int) ((logging)->buffer))
int isInitialized(Logging *logging);
@ -74,6 +76,7 @@ char* getCaption(LoggingPoints loggingPoint);
void appendPrintf(Logging *logging, const char *fmt, ...);
void vappendPrintf(Logging *logging, const char *fmt, va_list arg);
void append(Logging *logging, const char *text);
void appendFast(Logging *logging, const char *text);
/**
* this method copies the line into the intermediate buffer for later output by
* the main thread

View File

@ -25,7 +25,7 @@
#include "io_pins.h"
// todo: this value is too low for 6 cyl engine, get it back to 60
#define OUTPUT_SIGNAL_MAX_SIZE 60
#define OUTPUT_SIGNAL_MAX_SIZE 90
class OutputSignalList {
public:

View File

@ -21,16 +21,22 @@
#include "global.h"
#include "algo.h"
//#include "rpm_calculator.h"
#include "advance_map.h"
#include "fuel_math.h"
#include "wave_chart.h"
#include "settings.h"
#include "signal_executor.h"
#include "speed_density.h"
WaveChart waveChart;
void initAlgo(void) {
void initDataStructures(engine_configuration_s *engineConfiguration) {
prepareFuelMap();
prepareTimingMap();
initSpeedDensity(engineConfiguration);
}
void initAlgo(engine_configuration_s *engineConfiguration) {
#if EFI_PROD_CODE || EFI_SIMULATOR
initSettings();
initSignalExecutor();
@ -39,10 +45,4 @@ void initAlgo(void) {
#if EFI_WAVE_CHART
initWaveChart(&waveChart);
#endif
prepareFuelMap();
prepareTimingMap();
}

View File

@ -8,12 +8,15 @@
#ifndef ALGO_H_
#define ALGO_H_
#include "engine_configuration.h"
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
void initAlgo(void);
void initDataStructures(engine_configuration_s *engineConfiguration);
void initAlgo(engine_configuration_s *engineConfiguration);
#ifdef __cplusplus
}

View File

@ -22,6 +22,10 @@
typedef struct {
ActuatorEventList crankingInjectionEvents;
ActuatorEventList injectionEvents;
/**
* We are alternating two event lists in order to avoid a potential issue around revolution boundary
* when an event is scheduled within the next revolution.
*/
IgnitionEventList ignitionEvents[2];
} EventHandlerConfiguration;

View File

@ -9,5 +9,15 @@
* @author Andrey Belomutskiy, (c) 2012-2014
*/
#include "main.h"
#include "engine.h"
#include "engine_state.h"
/**
* We are executing these heavy (logarithm) methods from outside the trigger callbacks for performance reasons.
*/
void Engine::updateSlowSensors() {
engineState.iat = getIntakeAirTemperature();
engineState.clt = getCoolantTemperature();
}

View File

@ -10,12 +10,26 @@
#include "main.h"
#include "engine_configuration.h"
class EngineState {
public:
/**
* Access to these two fields is not synchronized in any way - that should work since float read/write are atomic.
*/
float iat;
float clt;
};
class RpmCalculator;
class Engine {
public:
RpmCalculator *rpmCalculator;
engine_configuration_s *engineConfiguration;
EngineState engineState;
void updateSlowSensors();
};
#endif /* ENGINE_H_ */

View File

@ -26,8 +26,9 @@
#include "interpolation.h"
#include "trigger_decoder.h"
#include "engine_math.h"
#include "speed_density.h"
#if EFI_PROD_CODE
#if EFI_TUNER_STUDIO
#include "tunerstudio.h"
#endif
@ -94,11 +95,18 @@ void setWholeFuelMap(engine_configuration_s *engineConfiguration, float value) {
}
}
void setTriggerSynchronizationGap(engine_configuration_s *engineConfiguration, float synchGap) {
engineConfiguration->triggerConfig.isSynchronizationNeeded = TRUE;
void setToothedWheelConfiguration(engine_configuration_s *engineConfiguration, int total, int skipped) {
engineConfiguration->triggerConfig.triggerType = TT_TOOTHED_WHEEL;
engineConfiguration->triggerConfig.isSynchronizationNeeded = (skipped != 0);
engineConfiguration->triggerConfig.syncRatioFrom = synchGap * 0.75;
engineConfiguration->triggerConfig.syncRatioTo = synchGap * 1.25;
engineConfiguration->triggerConfig.totalToothCount = total;
engineConfiguration->triggerConfig.skippedToothCount = skipped;
}
void setTriggerSynchronizationGap(trigger_config_s *triggerConfig, float synchGap) {
triggerConfig->isSynchronizationNeeded = TRUE;
triggerConfig->syncRatioFrom = synchGap * 0.75;
triggerConfig->syncRatioTo = synchGap * 1.25;
}
/**
@ -110,6 +118,8 @@ void setDefaultConfiguration(engine_configuration_s *engineConfiguration, board_
memset(engineConfiguration, 0, sizeof(engine_configuration_s));
memset(boardConfiguration, 0, sizeof(board_configuration_s));
setDetaultVETable(engineConfiguration);
engineConfiguration->injectorLag = 0.0;
for (int i = 0; i < IAT_CURVE_SIZE; i++) {
@ -147,8 +157,8 @@ void setDefaultConfiguration(engine_configuration_s *engineConfiguration, board_
setTimingLoadBin(engineConfiguration, 1.2, 4.4);
setTimingRpmBin(engineConfiguration, 800, 7000);
setTableBin(engineConfiguration->map.samplingAngleBins, MAP_ANGLE_SIZE, 800, 7000);
setTableBin(engineConfiguration->map.samplingWindowBins, MAP_ANGLE_SIZE, 800, 7000);
setTableBin2(engineConfiguration->map.samplingAngleBins, MAP_ANGLE_SIZE, 800, 7000, 1);
setTableBin2(engineConfiguration->map.samplingWindowBins, MAP_ANGLE_SIZE, 800, 7000, 1);
// set_whole_timing_map 3
setWholeFuelMap(engineConfiguration, 3);
@ -193,7 +203,7 @@ void setDefaultConfiguration(engine_configuration_s *engineConfiguration, board_
engineConfiguration->overrideCrankingIgnition = TRUE;
engineConfiguration->analogChartFrequency = 20;
engineConfiguration->engineLoadMode = LM_MAF;
engineConfiguration->algorithm = LM_MAF;
engineConfiguration->vbattDividerCoeff = ((float) (15 + 65)) / 15;
@ -206,7 +216,7 @@ void setDefaultConfiguration(engine_configuration_s *engineConfiguration, board_
engineConfiguration->can_nbc_type = CAN_BUS_NBC_BMW;
engineConfiguration->can_sleep_period = 50;
engineConfiguration->canReadEnabled = TRUE;
engineConfiguration->canWriteEnabled = FALSE;
engineConfiguration->canWriteEnabled = false;
setOperationMode(engineConfiguration, FOUR_STROKE_CAM_SENSOR);
engineConfiguration->cylindersCount = 4;
@ -221,7 +231,7 @@ void setDefaultConfiguration(engine_configuration_s *engineConfiguration, board_
engineConfiguration->logFormat = LF_NATIVE;
engineConfiguration->triggerConfig.triggerType = TT_TOOTHED_WHEEL;
setTriggerSynchronizationGap(engineConfiguration, 2);
setTriggerSynchronizationGap(&engineConfiguration->triggerConfig, 2);
engineConfiguration->triggerConfig.useRiseEdge = TRUE;
engineConfiguration->HD44780width = 16;
@ -260,12 +270,26 @@ void setDefaultConfiguration(engine_configuration_s *engineConfiguration, board_
boardConfiguration->injectionPins[3] = GPIOE_5;
boardConfiguration->injectionPins[4] = GPIOE_6;
boardConfiguration->injectionPins[5] = GPIOC_12;
boardConfiguration->injectionPins[6] = GPIO_NONE;
boardConfiguration->injectionPins[7] = GPIO_NONE;
boardConfiguration->injectionPins[8] = GPIO_NONE;
boardConfiguration->injectionPins[9] = GPIO_NONE;
boardConfiguration->injectionPins[10] = GPIO_NONE;
boardConfiguration->injectionPins[11] = GPIO_NONE;
boardConfiguration->injectionPinMode = OM_DEFAULT;
boardConfiguration->ignitionPins[0] = GPIOC_7;
boardConfiguration->ignitionPins[1] = GPIOE_4; // todo: update this value
boardConfiguration->ignitionPins[2] = GPIOE_0; // todo: update this value
boardConfiguration->ignitionPins[3] = GPIOE_1; // todo: update this value
boardConfiguration->ignitionPins[4] = GPIO_NONE;
boardConfiguration->ignitionPins[5] = GPIO_NONE;
boardConfiguration->ignitionPins[6] = GPIO_NONE;
boardConfiguration->ignitionPins[7] = GPIO_NONE;
boardConfiguration->ignitionPins[8] = GPIO_NONE;
boardConfiguration->ignitionPins[9] = GPIO_NONE;
boardConfiguration->ignitionPins[10] = GPIO_NONE;
boardConfiguration->ignitionPins[11] = GPIO_NONE;
boardConfiguration->ignitionPinMode = OM_DEFAULT;
boardConfiguration->malfunctionIndicatorPin = GPIOC_9;
@ -314,6 +338,12 @@ void setDefaultConfiguration(engine_configuration_s *engineConfiguration, board_
boardConfiguration->generalPeriodicThreadPeriod = 200;
boardConfiguration->tunerStudioSerialSpeed = 38400;
boardConfiguration->boardTestModeJumperPin = GPIOB_0;
boardConfiguration->canDeviceMode = CD_USE_CAN2;
boardConfiguration->canTxPin = GPIOB_0;
boardConfiguration->canRxPin = GPIOB_12;
}
void setDefaultNonPersistentConfiguration(engine_configuration2_s *engineConfiguration2) {
@ -438,8 +468,8 @@ void setOperationMode(engine_configuration_s *engineConfiguration, operation_mod
}
}
operation_mode_e getOperationMode( engine_configuration_s const *engineConfiguration) {
if(engineConfiguration->rpmMultiplier == 1)
operation_mode_e getOperationMode(engine_configuration_s const *engineConfiguration) {
if (engineConfiguration->rpmMultiplier == 1)
return FOUR_STROKE_CRANK_SENSOR;
return FOUR_STROKE_CAM_SENSOR;

View File

@ -68,6 +68,14 @@ typedef enum {
Internal_ForceMyEnumIntSize_timing_mode = ENUM_SIZE_HACK,
} timing_mode_e;
typedef enum {
CD_OFF = 0,
CD_USE_CAN1 = 1,
CD_USE_CAN2 = 2,
Internal_ForceMyEnumIntSize_can_device_mode = ENUM_SIZE_HACK,
} can_device_mode_e;
typedef struct {
int afrAdcChannel;
float v1;
@ -97,202 +105,6 @@ typedef struct {
} trigger_config_s;
/**
* @brief Engine configuration.
* Values in this data structure are adjustable and persisted in on-board flash RAM.
*
* The offsets are tracked using
* https://docs.google.com/spreadsheet/ccc?key=0AiAmAn6tn3L_dGJXZDZOcVVhaG9SaHZKU1dyMjhEV0E
*
* todo: currently the fields here are simply in the order in which they were implemented
* todo: re-arrange this structure one we have a stable code version
*/
typedef struct {
float injectorLag; // size 4, offset 0
/**
* cc/min, cubic centimeter per minute
*
* By the way, g/s = 0.125997881 * (lb/hr)
* g/s = 0.125997881 * (cc/min)/10.5
* g/s = 0.0119997981 * cc/min
*
*/
float injectorFlow; // size 4, offset 4
float battInjectorLagCorrBins[VBAT_INJECTOR_CURVE_SIZE]; // size 32, offset 8
float battInjectorLagCorr[VBAT_INJECTOR_CURVE_SIZE]; // size 32, offset 40
float cltFuelCorrBins[CLT_CURVE_SIZE]; // size 64, offset 72
float cltFuelCorr[CLT_CURVE_SIZE]; // size 64, offset 136
float iatFuelCorrBins[IAT_CURVE_SIZE]; // size 64, offset 200
float iatFuelCorr[IAT_CURVE_SIZE]; // size 64, offset 264
short int rpmHardLimit; // size 2, offset 328
// todo: extract these two fields into a structure
// todo: we need two sets of TPS parameters - modern ETBs have to sensors
short int tpsMin; // size 2, offset 330
// tpsMax value as 10 bit ADC value. Not Voltage!
short int tpsMax; // size 2, offset 332
short int analogChartMode;
cranking_parameters_s crankingSettings;
MAP_sensor_config_s map;
// todo: merge with channel settings, use full-scale Thermistor here!
ThermistorConf cltThermistorConf; // size 40 (10*4), offset 336
ThermistorConf iatThermistorConf; // size 40, offset 376
float sparkDwellBins[DWELL_COUNT]; // offset 580
float sparkDwell[DWELL_COUNT];
float ignitionLoadBins[IGN_LOAD_COUNT];
float ignitionRpmBins[IGN_RPM_COUNT];
/**
* this value could be used to offset the whole ignition timing table by a constant
*/
float ignitionOffset;
/**
* While cranking (which causes battery voltage to drop) we can calculate dwell time in shaft
* degrees, not in absolute time as in running mode.
*/
float crankingChargeAngle;
timing_mode_e timingMode;
/**
* This value is used in 'fixed timing' mode, i.e. constant timing
* This mode is useful for instance while adjusting distributor location
*/
float fixedModeTiming;
// WARNING: by default, our small enums are ONE BYTE. but if the are surrounded by non-enums - alignments do the trick
engine_type_e engineType;
float fuelLoadBins[FUEL_LOAD_COUNT]; //
// RPM is float and not integer in order to use unified methods for interpolation
float fuelRpmBins[FUEL_RPM_COUNT]; //
/**
* Engine displacement, in liters
* see also cylindersCount
*/
float displacement;
int unused[2];
injection_mode_e crankingInjectionMode;
injection_mode_e injectionMode;
/**
* Inside rusEfi all the angles are handled in relation to the trigger synchronization event
* which depends on the trigger shape and has nothing to do wit Top Dead Center (TDC)
*
* For engine configuration humans need angles from TDC.
*
* This field is the angle between Top Dead Center (TDC) and the first trigger event.
* Knowing this angle allows us to control timing and other angles in reference to TDC.
*/
float globalTriggerAngleOffset;
/**
* We have 3.3V ADC and most of the analog input signals are 5V, this forces us to use
* voltage dividers on the input circuits. This parameter holds the coefficient of these dividers.
* see also vbattDividerCoeff
*/
float analogInputDividerCoefficient;
/**
* This setting controls which algorithm is used for ENGINE LOAD
*/
engine_load_mode_e engineLoadMode;
/**
* see
*/
float vbattDividerCoeff;
/**
* Cooling fan turn-on temperature threshold, in Celsuis
*/
float fanOnTemperature;
/**
* Cooling fan turn-off temperature threshold, in Celsuis
*/
float fanOffTemperature;
int canReadEnabled;
int canWriteEnabled;
can_nbc_e can_nbc_type;
int can_sleep_period;
int cylindersCount;
ignition_mode_e ignitionMode;
firing_order_e firingOrder;
/**
* This magic constant is about four-stroke engines with camshaft position sensors.
* On any four stroke engine, each revolution of the camshaft is two revolutions
* of the crankshaft. If camshaft position is our primary sensor, we use this multiplier
* to convert from camshaft angles to crankshaft angles. All angels across the system
* should be crankshaft angles.
*/
float rpmMultiplier;
display_mode_e displayMode;
log_format_e logFormat;
int firmwareVersion;
int HD44780width;
int HD44780height;
int tpsAdcChannel;
int overrideCrankingIgnition;
int analogChartFrequency;
int unused5[10];
trigger_config_s triggerConfig;
int needSecondTriggerInput;
int vBattAdcChannel;
float globalFuelCorrection;
// todo: merge with channel settings, use full-scale Thermistor!
int cltAdcChannel;
int iatAdcChannel;
int mafAdcChannel;
afr_sensor_s afrSensor;
float injectionOffset;
float crankingTimingAngle;
float diffLoadEnrichmentCoef;
air_pressure_sensor_config_s baroSensor;
float veLoadBins[VE_LOAD_COUNT];
float veRpmBins[VE_RPM_COUNT];
float afrLoadBins[AFR_LOAD_COUNT];
float afrRpmBins[AFR_RPM_COUNT];
// the large tables are always in the end - that's related to TunerStudio paging implementation
float fuelTable[FUEL_LOAD_COUNT][FUEL_RPM_COUNT]; // size 1024
float ignitionTable[IGN_LOAD_COUNT][IGN_RPM_COUNT]; // size 1024
float veTable[VE_LOAD_COUNT][VE_RPM_COUNT]; // size 1024
float afrTable[AFR_LOAD_COUNT][AFR_RPM_COUNT]; // size 1024
} engine_configuration_s;
void setOperationMode(engine_configuration_s *engineConfiguration, operation_mode_e mode);
operation_mode_e getOperationMode(engine_configuration_s const *engineConfiguration);
#define HW_MAX_ADC_INDEX 16
typedef struct {
@ -355,11 +167,216 @@ typedef struct {
int tunerStudioSerialSpeed;
brain_pin_e boardTestModeJumperPin;
can_device_mode_e canDeviceMode;
brain_pin_e canTxPin;
brain_pin_e canRxPin;
} board_configuration_s;
/**
* @brief Engine configuration.
* Values in this data structure are adjustable and persisted in on-board flash RAM.
*
* The offsets are tracked using
* https://docs.google.com/spreadsheet/ccc?key=0AiAmAn6tn3L_dGJXZDZOcVVhaG9SaHZKU1dyMjhEV0E
*
* todo: currently the fields here are simply in the order in which they were implemented
* todo: re-arrange this structure one we have a stable code version
*/
typedef struct {
float injectorLag; // size 4, offset 0
/**
* cc/min, cubic centimeter per minute
*
* By the way, g/s = 0.125997881 * (lb/hr)
* g/s = 0.125997881 * (cc/min)/10.5
* g/s = 0.0119997981 * cc/min
*
*/
float injectorFlow; // size 4, offset 4
float battInjectorLagCorrBins[VBAT_INJECTOR_CURVE_SIZE]; // size 32, offset 8
float battInjectorLagCorr[VBAT_INJECTOR_CURVE_SIZE]; // size 32, offset 40
float cltFuelCorrBins[CLT_CURVE_SIZE]; // size 64, offset 72
float cltFuelCorr[CLT_CURVE_SIZE]; // size 64, offset 136
float iatFuelCorrBins[IAT_CURVE_SIZE]; // size 64, offset 200
float iatFuelCorr[IAT_CURVE_SIZE]; // size 64, offset 264
short int unused2; // size 2, offset 328
// todo: extract these two fields into a structure
// todo: we need two sets of TPS parameters - modern ETBs have to sensors
short int tpsMin; // size 2, offset 330
// tpsMax value as 10 bit ADC value. Not Voltage!
short int tpsMax; // size 2, offset 332
short int analogChartMode;
cranking_parameters_s crankingSettings;
MAP_sensor_config_s map;
// todo: merge with channel settings, use full-scale Thermistor here!
ThermistorConf cltThermistorConf; // size 40 (10*4), offset 336
ThermistorConf iatThermistorConf; // size 40, offset 376
float sparkDwellBins[DWELL_COUNT]; // offset 580
float sparkDwell[DWELL_COUNT];
float ignitionLoadBins[IGN_LOAD_COUNT];
float ignitionRpmBins[IGN_RPM_COUNT];
/**
* this value could be used to offset the whole ignition timing table by a constant
*/
float ignitionOffset;
/**
* While cranking (which causes battery voltage to drop) we can calculate dwell time in shaft
* degrees, not in absolute time as in running mode.
*/
float crankingChargeAngle;
timing_mode_e timingMode;
/**
* This value is used in 'fixed timing' mode, i.e. constant timing
* This mode is useful for instance while adjusting distributor location
*/
float fixedModeTiming;
// WARNING: by default, our small enums are ONE BYTE. but if the are surrounded by non-enums - alignments do the trick
engine_type_e engineType;
float fuelLoadBins[FUEL_LOAD_COUNT]; //
// RPM is float and not integer in order to use unified methods for interpolation
float fuelRpmBins[FUEL_RPM_COUNT]; //
/**
* Engine displacement, in liters
* see also cylindersCount
*/
float displacement;
int rpmHardLimit;
injection_mode_e crankingInjectionMode;
injection_mode_e injectionMode;
/**
* Inside rusEfi all the angles are handled in relation to the trigger synchronization event
* which depends on the trigger shape and has nothing to do wit Top Dead Center (TDC)
*
* For engine configuration humans need angles from TDC.
*
* This field is the angle between Top Dead Center (TDC) and the first trigger event.
* Knowing this angle allows us to control timing and other angles in reference to TDC.
*/
float globalTriggerAngleOffset;
/**
* We have 3.3V ADC and most of the analog input signals are 5V, this forces us to use
* voltage dividers on the input circuits. This parameter holds the coefficient of these dividers.
* see also vbattDividerCoeff
*/
float analogInputDividerCoefficient;
/**
* This setting controls which algorithm is used for ENGINE LOAD
*/
engine_load_mode_e algorithm;
/**
* see
*/
float vbattDividerCoeff;
/**
* Cooling fan turn-on temperature threshold, in Celsuis
*/
float fanOnTemperature;
/**
* Cooling fan turn-off temperature threshold, in Celsuis
*/
float fanOffTemperature;
int canReadEnabled;
int canWriteEnabled;
can_nbc_e can_nbc_type;
int can_sleep_period;
int cylindersCount;
ignition_mode_e ignitionMode;
firing_order_e firingOrder;
/**
* This magic constant is about four-stroke engines with camshaft position sensors.
* On any four stroke engine, each revolution of the camshaft is two revolutions
* of the crankshaft. If camshaft position is our primary sensor, we use this multiplier
* to convert from camshaft angles to crankshaft angles. All angels across the system
* should be crankshaft angles.
*/
float rpmMultiplier;
display_mode_e displayMode;
log_format_e logFormat;
int firmwareVersion;
int HD44780width;
int HD44780height;
int tpsAdcChannel;
int overrideCrankingIgnition;
int analogChartFrequency;
trigger_config_s triggerConfig;
int needSecondTriggerInput;
int vBattAdcChannel;
float globalFuelCorrection;
// todo: merge with channel settings, use full-scale Thermistor!
int cltAdcChannel;
int iatAdcChannel;
int mafAdcChannel;
afr_sensor_s afrSensor;
float injectionOffset;
float crankingTimingAngle;
float diffLoadEnrichmentCoef;
air_pressure_sensor_config_s baroSensor;
float veLoadBins[VE_LOAD_COUNT];
float veRpmBins[VE_RPM_COUNT];
float afrLoadBins[AFR_LOAD_COUNT];
float afrRpmBins[AFR_RPM_COUNT];
// the large tables are always in the end - that's related to TunerStudio paging implementation
float fuelTable[FUEL_LOAD_COUNT][FUEL_RPM_COUNT]; // size 1024
float ignitionTable[IGN_LOAD_COUNT][IGN_RPM_COUNT]; // size 1024
float veTable[VE_LOAD_COUNT][VE_RPM_COUNT]; // size 1024
float afrTable[AFR_LOAD_COUNT][AFR_RPM_COUNT]; // size 1024
board_configuration_s bc;
} engine_configuration_s;
void setOperationMode(engine_configuration_s *engineConfiguration, operation_mode_e mode);
operation_mode_e getOperationMode(engine_configuration_s const *engineConfiguration);
typedef struct {
engine_configuration_s engineConfiguration;
board_configuration_s boardConfiguration;
} persistent_config_s;
typedef struct {
@ -379,7 +396,8 @@ void setWholeFuelMap(engine_configuration_s *engineConfiguration, float value);
void setConstantDwell(engine_configuration_s *engineConfiguration, float dwellMs);
void printFloatArray(const char *prefix, float array[], int size);
void setTriggerSynchronizationGap(engine_configuration_s *engineConfiguration, float synchGap);
void setTriggerSynchronizationGap(trigger_config_s *triggerConfig, float synchGap);
void setToothedWheelConfiguration(engine_configuration_s *engineConfiguration, int total, int skipped);
void incrementGlobalConfigurationVersion(void);
int getGlobalConfigurationVersion(void);

View File

@ -55,10 +55,8 @@ int getRusEfiVersion(void);
#define efiAssertVoid(condition, message) { if (!(condition)) { firmwareError(message); return; } }
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* ERROR_HANDLING_H_ */

View File

@ -24,11 +24,11 @@
#include "main.h"
#include "engine_math.h"
void registerActuatorEvent(ActuatorEventList *list, int eventIndex, OutputSignal *actuator, float angleOffset) {
ActuatorEvent *e = list->getNextActuatorEvent();
if (e == NULL)
return; // error already reported
e->position.eventIndex = eventIndex;
e->actuator = actuator;
e->position.angleOffset = angleOffset;
}
//void registerActuatorEventWhat(ActuatorEventList *list, int eventIndex, OutputSignal *actuator, float angleOffset) {
// ActuatorEvent *e = list->getNextActuatorEvent();
// if (e == NULL)
// return; // error already reported
// e->position.eventIndex = eventIndex;
// e->actuator = actuator;
// e->position.angleOffset = angleOffset;
//}

View File

@ -11,7 +11,7 @@
#include "global.h"
#include "signal_executor.h"
#define MAX_EVENT_COUNT 40
#define MAX_EVENT_COUNT 80
/**
* This structure defines an angle position within the trigger
@ -31,13 +31,15 @@ typedef struct {
typedef struct {
event_trigger_position_s position;
OutputSignal *actuator;
scheduling_s signalTimer;
} ActuatorEvent;
typedef struct IgnitionEvent_struct IgnitionEvent;
struct IgnitionEvent_struct {
ActuatorEvent actuator;
io_pin_e io_pin;
scheduling_s signalTimerUp;
scheduling_s signalTimerDown;
event_trigger_position_s dwellPosition;
float advance;
event_trigger_position_s sparkPosition;
IgnitionEvent *next;
@ -68,14 +70,14 @@ typedef ArrayList<ActuatorEvent, MAX_EVENT_COUNT> ActuatorEventList;
typedef ArrayList<IgnitionEvent, MAX_EVENT_COUNT> IgnitionEventList;
/**
* this is an intermediate implementation of flexible event handling.
*
* In the future implementation we will drop the 'eventIndex' parameter and everything will be
* angle-driven. But that's just a plan for next iteration.
*
* @param actuator injector or coil OutputSignal
*/
void registerActuatorEvent(ActuatorEventList *list, int eventIndex, OutputSignal *actuator, float angleOffset);
///**
// * this is an intermediate implementation of flexible event handling.
// *
// * In the future implementation we will drop the 'eventIndex' parameter and everything will be
// * angle-driven. But that's just a plan for next iteration.
// *
// * @param actuator injector or coil OutputSignal
// */
//void registerActuatorEvent(ActuatorEventList *list, int eventIndex, OutputSignal *actuator, float angleOffset);
#endif /* EVENT_REGISTRY_H_ */

View File

@ -1,5 +1,5 @@
/**
* @file fuel_math.c
* @file fuel_math.cpp
* @brief Fuel amount calculation logic
*
* While engine running, fuel amount is an interpolated value from the fuel map by getRpm() and getEngineLoad()

View File

@ -111,7 +111,7 @@ extern "C"
void initPrimaryPins(void);
void initOutputPins(void);
char *getPinName(io_pin_e io_pin);
const char *getPinName(io_pin_e io_pin);
void turnOutputPinOn(io_pin_e pin);
void turnOutputPinOff(io_pin_e pin);
void setOutputPinValue(io_pin_e pin, int logicValue);

View File

@ -80,6 +80,7 @@ typedef enum {
TT_GM_7X = 5,
TT_MINI_COOPER_R50 = 6,
TT_FORD_ESCORT_GT = 7,
TT_TT_TOOTHED_WHEEL_60_2 = 8,
Internal_ForceMyEnumIntSize_trigger_type = ENUM_SIZE_HACK,
} trigger_type_e;
@ -170,19 +171,20 @@ typedef enum {
} pin_input_mode_e;
typedef enum {
FO_ONE_CYLINDER = 1,
FO_1_THEN_3_THEN_4_THEN2 = 2,
FO_1_THEN_2_THEN_4_THEN3 = 3,
FO_1_THEN_3_THEN_2_THEN4 = 4,
FO_1_THEN_5_THEN_3_THEN_6_THEN_2_THEN_4 = 5,
FO_1_8_4_3_6_5_7_2 = 6,
FO_ONE_CYLINDER = 0,
FO_1_THEN_3_THEN_4_THEN2 = 1,
FO_1_THEN_2_THEN_4_THEN3 = 2,
FO_1_THEN_3_THEN_2_THEN4 = 3,
FO_1_THEN_5_THEN_3_THEN_6_THEN_2_THEN_4 = 4,
FO_1_8_4_3_6_5_7_2 = 5,
Internal_ForceMyEnumIntSize_firing_order = ENUM_SIZE_HACK,
} firing_order_e;
// todo: better enum name
typedef enum {
FOUR_STROKE_CRANK_SENSOR = 0,
FOUR_STROKE_CAM_SENSOR = 1,
OM_NONE = 0,
FOUR_STROKE_CRANK_SENSOR = 1,
FOUR_STROKE_CAM_SENSOR = 2,
Internal_ForceMyEnumIntSize_operation_mode_e = ENUM_SIZE_HACK,
} operation_mode_e;
@ -191,7 +193,13 @@ typedef enum {
* @brief Ignition Mode
*/
typedef enum {
/**
* in this mode only SPARKOUT_1_OUTPUT is used
*/
IM_ONE_COIL = 0,
/**
* in this mode we use as many coils as we have cylinders
*/
IM_INDIVIDUAL_COILS = 1,
IM_WASTED_SPARK = 2,

View File

@ -51,19 +51,12 @@ void initSignalExecutor(void) {
void initOutputSignal(OutputSignal *signal, io_pin_e ioPin) {
signal->io_pin = ioPin;
signal->name = getPinName(ioPin);
initOutputSignalBase(signal);
}
void initOutputSignalBase(OutputSignal *signal) {
signal->initialized = TRUE;
}
void turnPinHigh(OutputSignal *signal) {
void turnPinHigh(io_pin_e pin) {
#if EFI_DEFAILED_LOGGING
// signal->hi_time = hTimeNow();
#endif /* EFI_DEFAILED_LOGGING */
io_pin_e pin = signal->io_pin;
// turn the output level ACTIVE
// todo: this XOR should go inside the setOutputPinValue method
setOutputPinValue(pin, TRUE);
@ -79,14 +72,14 @@ void turnPinHigh(OutputSignal *signal) {
#endif
#if EFI_WAVE_CHART
addWaveChartEvent(signal->name, "up", "");
addWaveChartEvent(getPinName(pin), WC_UP, "");
#endif /* EFI_WAVE_ANALYZER */
}
void turnPinLow(OutputSignal *signal) {
void turnPinLow(io_pin_e pin) {
// turn off the output
// todo: this XOR should go inside the setOutputPinValue method
setOutputPinValue(signal->io_pin, FALSE);
setOutputPinValue(pin, false);
#if EFI_DEFAILED_LOGGING
systime_t after = hTimeNow();
@ -95,7 +88,7 @@ void turnPinLow(OutputSignal *signal) {
#endif /* EFI_DEFAILED_LOGGING */
#if EFI_WAVE_CHART
addWaveChartEvent(signal->name, "down", "");
addWaveChartEvent(getPinName(pin), WC_DOWN, "");
#endif /* EFI_WAVE_ANALYZER */
}
@ -118,50 +111,67 @@ void scheduleOutput(OutputSignal *signal, float delayMs, float durationMs) {
return;
}
scheduleOutputBase(signal, delayMs, durationMs);
int index = getRevolutionCounter() % 2;
scheduling_s * sUp = &signal->signalTimerUp[index];
scheduling_s * sDown = &signal->signalTimerDown[index];
scheduleTask(sUp, (int)MS2US(delayMs), (schfunc_t) &turnPinHigh, (void *) signal);
scheduleTask(sDown, (int)MS2US(delayMs + durationMs), (schfunc_t) &turnPinLow, (void*) signal);
// signal->last_scheduling_time = now;
scheduleTask(sUp, (int)MS2US(delayMs), (schfunc_t) &turnPinHigh, (void *) signal->io_pin);
scheduleTask(sDown, (int)MS2US(delayMs + durationMs), (schfunc_t) &turnPinLow, (void*) signal->io_pin);
}
void scheduleOutputBase(OutputSignal *signal, float delayMs, float durationMs) {
/**
* it's better to check for the exact 'TRUE' value since otherwise
* we would accept any memory garbage
*/
efiAssertVoid(signal->initialized == TRUE, "Signal not initialized");
// signal->offset = offset;
// signal->duration = duration;
}
char *getPinName(io_pin_e io_pin) {
const char *getPinName(io_pin_e io_pin) {
switch (io_pin) {
// todo: refactor this hell - introduce arrays & checks?
case SPARKOUT_1_OUTPUT:
return "Spark 1";
return "spa1";
case SPARKOUT_2_OUTPUT:
return "Spark 2";
return "spa2";
case SPARKOUT_3_OUTPUT:
return "Spark 3";
return "spa3";
case SPARKOUT_4_OUTPUT:
return "Spark 4";
return "spa4";
case SPARKOUT_5_OUTPUT:
return "spa5";
case SPARKOUT_6_OUTPUT:
return "spa6";
case SPARKOUT_7_OUTPUT:
return "spa7";
case SPARKOUT_8_OUTPUT:
return "spa8";
case SPARKOUT_9_OUTPUT:
return "spa9";
case SPARKOUT_10_OUTPUT:
return "spa10";
case SPARKOUT_11_OUTPUT:
return "spa11";
case SPARKOUT_12_OUTPUT:
return "spa12";
case INJECTOR_1_OUTPUT:
return "Injector 1";
return "inj1";
case INJECTOR_2_OUTPUT:
return "Injector 2";
return "inj2";
case INJECTOR_3_OUTPUT:
return "Injector 3";
return "inj3";
case INJECTOR_4_OUTPUT:
return "Injector 4";
return "inj4";
case INJECTOR_5_OUTPUT:
return "Injector 5";
return "inj5";
case INJECTOR_6_OUTPUT:
return "inj6";
case INJECTOR_7_OUTPUT:
return "inj7";
case INJECTOR_8_OUTPUT:
return "inj8";
case INJECTOR_9_OUTPUT:
return "inj9";
case INJECTOR_10_OUTPUT:
return "inj10";
case INJECTOR_11_OUTPUT:
return "inj11";
case INJECTOR_12_OUTPUT:
return "inj12";
default:
return "No name";
return "Pin needs name";
}
}

View File

@ -28,12 +28,7 @@
*/
typedef struct OutputSignal_struct OutputSignal;
struct OutputSignal_struct {
/**
* name of this signal
*/
char *name;
io_pin_e io_pin;
int initialized;
/**
* We are alternating instances so that events which extend into next revolution are not reused while
@ -41,9 +36,6 @@ struct OutputSignal_struct {
*/
scheduling_s signalTimerUp[2];
scheduling_s signalTimerDown[2];
scheduling_s triggerEvent;
float angleOffsetParam;
};
#ifdef __cplusplus
@ -56,8 +48,8 @@ void scheduleOutput(OutputSignal *signal, float delayMs, float durationMs);
void initOutputSignalBase(OutputSignal *signal);
void scheduleOutputBase(OutputSignal *signal, float delayMs, float durationMs);
void turnPinHigh(OutputSignal *signal);
void turnPinLow(OutputSignal *signal);
void turnPinHigh(io_pin_e pin);
void turnPinLow(io_pin_e pin);
void initSignalExecutor(void);
void initSignalExecutorImpl(void);

View File

@ -34,12 +34,19 @@
#define CHART_DELIMETER "!"
#if EFI_HISTOGRAMS
#include "rfiutil.h"
#include "histogram.h"
static histogram_s waveChartHisto;
#endif
/**
* This is the number of events in the digital chart which would be displayed
* on the 'digital sniffer' pane
*/
#if EFI_PROD_CODE
static volatile int chartSize = 100;
// todo: does it really need to be a variable? maybe a constant should be enough?
static volatile int chartSize = 300;
#define WAVE_LOGGING_SIZE 5000
#else
// need more events for automated test
@ -47,6 +54,8 @@ static volatile int chartSize = 400;
#define WAVE_LOGGING_SIZE 35000
#endif
int waveChartUsedSize;
static int isChartActive = TRUE;
//static int isChartActive = FALSE;
@ -67,7 +76,12 @@ void resetWaveChart(WaveChart *chart) {
appendPrintf(&chart->logging, "wave_chart%s", DELIMETER);
}
static char WAVE_LOGGING_BUFFER[WAVE_LOGGING_SIZE] CCM_OPTIONAL;
static char WAVE_LOGGING_BUFFER[WAVE_LOGGING_SIZE] CCM_OPTIONAL
;
int isWaveChartFull(WaveChart *chart) {
return chart->counter >= chartSize;
}
static void printStatus(void) {
scheduleIntValue(&logger, "chart", isChartActive);
@ -93,12 +107,9 @@ void publishChartIfFull(WaveChart *chart) {
}
}
int isWaveChartFull(WaveChart *chart) {
return chart->counter >= chartSize;
}
void publishChart(WaveChart *chart) {
appendPrintf(&chart->logging, DELIMETER);
waveChartUsedSize = loggingSize(&chart->logging);
#if DEBUG_WAVE
Logging *l = &chart->logging;
scheduleSimpleMsg(&debugLogging, "IT'S TIME", strlen(l->buffer));
@ -107,8 +118,10 @@ void publishChart(WaveChart *chart) {
scheduleLogging(&chart->logging);
}
static char timeBuffer[10];
/**
* @brief Register a change in sniffed signal
* @brief Register an event for digital sniffer
*/
void addWaveChartEvent3(WaveChart *chart, const char *name, const char * msg, const char * msg2) {
efiAssertVoid(chart->isInitialized, "chart not initialized");
@ -117,13 +130,52 @@ void addWaveChartEvent3(WaveChart *chart, const char *name, const char * msg, co
#endif
if (isWaveChartFull(chart))
return;
bool alreadyLocked = lockOutputBuffer(); // we have multiple threads writing to the same output buffer
appendPrintf(&chart->logging, "%s%s%s%s", name, CHART_DELIMETER, msg, CHART_DELIMETER);
#if EFI_HISTOGRAMS && EFI_PROD_CODE
int beforeCallback = hal_lld_get_counter_value();
#endif
int time100 = getTimeNowUs() / 10;
appendPrintf(&chart->logging, "%d%s%s", time100, msg2, CHART_DELIMETER);
bool alreadyLocked = lockOutputBuffer(); // we have multiple threads writing to the same output buffer
if (chart->counter == 0)
chart->startTime = time100;
chart->counter++;
if (remainingSize(&chart->logging) > 30) {
/**
* printf is a heavy method, append is used here as a performance optimization
*/
appendFast(&chart->logging, name);
appendFast(&chart->logging, CHART_DELIMETER);
appendFast(&chart->logging, msg);
appendFast(&chart->logging, CHART_DELIMETER);
/**
* We want smaller times within a chart in order to reduce packet size.
*/
time100 -= chart->startTime;
itoa10(timeBuffer, time100);
appendFast(&chart->logging, timeBuffer);
appendFast(&chart->logging, msg2);
appendFast(&chart->logging, CHART_DELIMETER);
}
if (!alreadyLocked)
unlockOutputBuffer();
#if EFI_HISTOGRAMS && EFI_PROD_CODE
int diff = hal_lld_get_counter_value() - beforeCallback;
if (diff > 0)
hsAdd(&waveChartHisto, diff);
#endif /* EFI_HISTOGRAMS */
}
void showWaveChartHistogram(void) {
#if EFI_PROD_CODE
printHistogram(&logger, &waveChartHisto);
#endif
}
void initWaveChart(WaveChart *chart) {
@ -140,6 +192,10 @@ void initWaveChart(WaveChart *chart) {
initLoggingExt(&debugLogging, "wave chart debug", &debugLogging.DEFAULT_BUFFER, sizeof(debugLogging.DEFAULT_BUFFER));
#endif
#if EFI_HISTOGRAMS
initHistogram(&waveChartHisto, "wave chart");
#endif /* EFI_HISTOGRAMS */
resetWaveChart(chart);
addConsoleActionI("chartsize", setChartSize);
addConsoleActionI("chart", setChartActive);

View File

@ -23,6 +23,7 @@ typedef struct {
Logging logging;
#endif /* EFI_WAVE_CHART */
int counter;
int startTime;
volatile int isInitialized;
} WaveChart;
@ -34,9 +35,10 @@ extern "C"
void addWaveChartEvent3(WaveChart *chart, const char *name, const char *msg, const char *msg2);
void publishChart(WaveChart *chart);
void initWaveChart(WaveChart *chart);
void showWaveChartHistogram(void);
void resetWaveChart(WaveChart *chart);
void setChartSize(int newSize);
int isWaveChartFull(WaveChart *chart);
//int isWaveChartFull(WaveChart *chart);
void publishChartIfFull(WaveChart *chart);
#ifdef __cplusplus

View File

@ -37,24 +37,6 @@ void multi_wave_s::reset(void) {
waveCount = 0;
}
float multi_wave_s::getAngle(int index, engine_configuration_s const *engineConfiguration, trigger_shape_s * s) const {
if (getOperationMode(engineConfiguration) == FOUR_STROKE_CAM_SENSOR)
return getSwitchTime(index) * 720.0;
/**
* FOUR_STROKE_CRANK_SENSOR magic:
* We have two crank shaft revolutions for each engine cycle
* See also trigger_central.cpp
* See also getEngineCycleEventCount()
*/
int triggerEventCounter = s->getSize();
if (index < triggerEventCounter) {
return getSwitchTime(index) * 360.0;
} else {
return 360 + getSwitchTime(index - triggerEventCounter) * 360.0;
}
}
float multi_wave_s::getSwitchTime(int index) const {
return switchTimes[index];
}

View File

@ -32,7 +32,6 @@ public:
void init(float *st, single_wave_s *waves);
void reset(void);
float getSwitchTime(int phaseIndex) const;
float getAngle(int phaseIndex, engine_configuration_s const *engineConfiguration, trigger_shape_s * s) const;
void setSwitchTime(int phaseIndex, float value);
void checkSwitchTimes(int size);
int getChannelState(int channelIndex, int phaseIndex) const;

View File

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

View File

@ -0,0 +1,45 @@
/**
* @file fl_stack.h
* @brief Fixed-length stack
*
* @date Jul 9, 2014
* @author Andrey Belomutskiy, (c) 2012-2014
*/
#ifndef FL_STACK_H_
#define FL_STACK_H_
template<typename T, int MAXSIZE>
class FLStack {
public:
FLStack();
void push(T value);
T pop();
int size();
bool isEmpty();
private:
int index;
T values[MAXSIZE];
};
template<typename T, int MAXSIZE>
FLStack<T, MAXSIZE>::FLStack() {
index = 0;
}
template<typename T, int MAXSIZE>
bool FLStack<T, MAXSIZE>::isEmpty() {
return index == 0;
}
template<typename T, int MAXSIZE>
void FLStack<T, MAXSIZE>::push(T value) {
values[index++] = value;
}
template<typename T, int MAXSIZE>
int FLStack<T, MAXSIZE>::size() {
return index;
}
#endif /* FL_STACK_H_ */

View File

@ -82,9 +82,13 @@ int findIndex(float array[], int size, float value) {
int left = 0;
int right = size;
while (1) {
if (size-- == 0)
efiAssert(FALSE, "Unexpected state in binary search", 0);
// todo: extract binary search as template method?
while (true) {
#if 0
// that's an assertion to make sure we do not loop here
size--;
efiAssert(size > 0, "Unexpected state in binary search", 0);
#endif
middle = (left + right) / 2;

View File

@ -0,0 +1,29 @@
/**
* @file table_helper.cpp
* @brief Helper methods related to 3D & 2D tables manipulation (maps and curves)
*
* @date Jul 6, 2014
* @author Andrey Belomutskiy, (c) 2012-2014
*/
#include "table_helper.h"
#include "efilib.h"
#include "interpolation.h"
void setTableBin2(float array[], int size, float l, float r, float precision) {
for (int i = 0; i < size; i++) {
float value = interpolate(0, l, size - 1, r, i);
/**
* rounded values look nicer, also we want to avoid precision mismatch with Tuner Studio
*/
array[i] = efiRound(value, precision);
}
}
void setTableBin(float array[], int size, float l, float r) {
setTableBin2(array, size, l, r, 0.01);
}
void setRpmTableBin(float array[], int size) {
setTableBin2(array, size, 800, 7000, 1);
}

View File

@ -0,0 +1,56 @@
/**
* @file table_helper.h
*
* @date Jul 6, 2014
* @author Andrey Belomutskiy, (c) 2012-2014
*/
#ifndef TABLE_HELPER_H_
#define TABLE_HELPER_H_
#include <math.h>
#include "error_handling.h"
// 'random' value to be sure we are not treating any non-zero trash as TRUE
#define MAGIC_TRUE_VALUE 153351512
template<int RPM_BIN_SIZE, int LOAD_BIN_SIZE>
class Map3D {
public:
void init(float table[RPM_BIN_SIZE][LOAD_BIN_SIZE]);
float getValue(float x, float xBin[], float y, float yBin[]);
void setAll(float value);
private:
float *pointers[LOAD_BIN_SIZE];
int initialized;
};
template<int RPM_BIN_SIZE, int LOAD_BIN_SIZE>
void Map3D<RPM_BIN_SIZE, LOAD_BIN_SIZE>::init(float table[RPM_BIN_SIZE][LOAD_BIN_SIZE]) {
for (int k = 0; k < LOAD_BIN_SIZE; k++)
pointers[k] = table[k];
initialized = MAGIC_TRUE_VALUE;
}
template<int RPM_BIN_SIZE, int LOAD_BIN_SIZE>
float Map3D<RPM_BIN_SIZE, LOAD_BIN_SIZE>::getValue(float x, float xBin[], float y, float yBin[]) {
efiAssert(initialized == MAGIC_TRUE_VALUE, "map initialized", NAN);
return interpolate3d(x, xBin, LOAD_BIN_SIZE, y, yBin, RPM_BIN_SIZE, pointers);
}
template<int RPM_BIN_SIZE, int LOAD_BIN_SIZE>
void Map3D<RPM_BIN_SIZE, LOAD_BIN_SIZE>::setAll(float value) {
efiAssertVoid(initialized == MAGIC_TRUE_VALUE, "map initialized");
for (int l = 0; l < LOAD_BIN_SIZE; l++) {
for (int r = 0; r < RPM_BIN_SIZE; r++) {
pointers[l][r] = value;
}
}
}
typedef Map3D<16, 16> Map3D1616;
void setTableBin(float array[], int size, float l, float r);
void setTableBin2(float array[], int size, float l, float r, float precision);
void setRpmTableBin(float array[], int size);
#endif /* TABLE_HELPER_H_ */

View File

@ -57,7 +57,7 @@ extern board_configuration_s *boardConfiguration;
persistent_config_container_s persistentState CCM_OPTIONAL;
engine_configuration_s *engineConfiguration = &persistentState.persistentConfiguration.engineConfiguration;
board_configuration_s *boardConfiguration = &persistentState.persistentConfiguration.boardConfiguration;
board_configuration_s *boardConfiguration = &persistentState.persistentConfiguration.engineConfiguration.bc;
/**
* CH_FREQUENCY is the number of system ticks in a second
@ -244,7 +244,7 @@ void initEngineContoller(void) {
initAnalogChart();
#endif /* EFI_ANALOG_CHART */
initAlgo();
initAlgo(engineConfiguration);
#if EFI_WAVE_ANALYZER
initWaveAnalyzer();

View File

@ -13,16 +13,7 @@
#include "signal_executor.h"
#include "engine_configuration.h"
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
char * getPinNameByAdcChannel(int hwChannel, char *buffer);
void initEngineContoller(void);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* ENGINE_STATUS_H_ */

View File

@ -15,7 +15,6 @@
#include "flash.h"
#include "rusefi.h"
//#include "tunerstudio.h"
#include "engine_controller.h"
#include "datalogging.h"
@ -55,7 +54,7 @@ void writeToFlash(void) {
#if EFI_INTERNAL_FLASH
persistentState.size = PERSISTENT_SIZE;
persistentState.version = FLASH_DATA_VERSION;
scheduleMsg(&logger, "FLASH_DATA_VERSION=%d", persistentState.version);
scheduleMsg(&logger, "flash compatible with %d", persistentState.version);
crc_t result = flashStateCrc(&persistentState);
persistentState.value = result;
scheduleMsg(&logger, "Reseting flash, size=%d", PERSISTENT_SIZE);
@ -85,7 +84,7 @@ static void doResetConfiguration(void) {
boardConfiguration);
}
static void readFromFlash(void) {
void readFromFlash(void) {
printMsg(&logger, "readFromFlash()");
flashRead(FLASH_ADDR, (char *) &persistentState, PERSISTENT_SIZE);
@ -112,6 +111,4 @@ void initFlash(void) {
addConsoleAction("readconfig", readFromFlash);
addConsoleAction("writeconfig", writeToFlash);
addConsoleAction("resetconfig", doResetConfiguration);
readFromFlash();
}

View File

@ -11,13 +11,14 @@
#include "engine_configuration.h"
#define FLASH_DATA_VERSION 3601
#define FLASH_DATA_VERSION 3880
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
void readFromFlash(void);
void initFlash(void);
void writeToFlash(void);

View File

@ -34,8 +34,8 @@ extern board_configuration_s *boardConfiguration;
void initIgnitionCentral(void) {
initLogging(&logger, "IgnitionCentral");
outputPinRegisterExt2("sparkout1", SPARKOUT_1_OUTPUT, boardConfiguration->ignitionPins[0], &boardConfiguration->ignitionPinMode);
outputPinRegisterExt2("sparkout2", SPARKOUT_2_OUTPUT, boardConfiguration->ignitionPins[1], &boardConfiguration->ignitionPinMode);
outputPinRegisterExt2("sparkout3", SPARKOUT_3_OUTPUT, boardConfiguration->ignitionPins[2], &boardConfiguration->ignitionPinMode);
outputPinRegisterExt2("sparkout4", SPARKOUT_4_OUTPUT, boardConfiguration->ignitionPins[3], &boardConfiguration->ignitionPinMode);
for (int i = 0; i < engineConfiguration->cylindersCount; i++) {
io_pin_e pin = (io_pin_e)((int)INJECTOR_1_OUTPUT + i);
outputPinRegisterExt2(getPinName(pin), pin, boardConfiguration->ignitionPins[i], &boardConfiguration->ignitionPinMode);
}
}

View File

@ -139,24 +139,16 @@ void initInjectorCentral(void) {
for (int i = 0; i < engineConfiguration->cylindersCount; i++)
is_injector_enabled[i] = true;
printStatus();
// todo: should we move this code closer to the injection logic?
// todo: dynamic initialization
// todo: consider actual cylinders count
outputPinRegisterExt2("injector1", INJECTOR_1_OUTPUT, boardConfiguration->injectionPins[0],
&boardConfiguration->injectionPinMode);
outputPinRegisterExt2("injector2", INJECTOR_2_OUTPUT, boardConfiguration->injectionPins[1],
&boardConfiguration->injectionPinMode);
outputPinRegisterExt2("injector3", INJECTOR_3_OUTPUT, boardConfiguration->injectionPins[2],
&boardConfiguration->injectionPinMode);
outputPinRegisterExt2("injector4", INJECTOR_4_OUTPUT, boardConfiguration->injectionPins[3],
&boardConfiguration->injectionPinMode);
outputPinRegisterExt2("injector5", INJECTOR_5_OUTPUT, boardConfiguration->injectionPins[4],
&boardConfiguration->injectionPinMode);
outputPinRegisterExt2("injector5", INJECTOR_6_OUTPUT, boardConfiguration->injectionPins[5],
&boardConfiguration->injectionPinMode);
for (int i = 0; i < engineConfiguration->cylindersCount; i++) {
io_pin_e pin = (io_pin_e)((int)INJECTOR_1_OUTPUT + i);
outputPinRegisterExt2(getPinName(pin), pin,
boardConfiguration->injectionPins[i], &boardConfiguration->injectionPinMode);
}
printStatus();
addConsoleActionII("injector", setInjectorEnabled);
addConsoleActionSSS("fuelbench", &fuelbench);

View File

@ -42,14 +42,14 @@
* @deprecated
*/
float getOneDegreeTimeMs(int rpm) {
return 1000.0 * 60 / 360 / rpm;
return 1000.0f * 60 / 360 / rpm;
}
/**
* @return time needed to rotate crankshaft by one degree, in microseconds.
*/
float getOneDegreeTimeUs(int rpm) {
return 1000000.0 * 60 / 360 / rpm;
return 1000000.0f * 60 / 360 / rpm;
}
/**
@ -67,7 +67,7 @@ float fixAngle(float angle) {
// I guess this implementation would be faster than 'angle % 720'
while (angle < 0)
angle += 720;
while (angle > 720)
while (angle >= 720)
angle -= 720;
return angle;
}
@ -77,7 +77,7 @@ float fixAngle(float angle) {
*
*/
float getEngineLoadT(engine_configuration_s *engineConfiguration) {
switch (engineConfiguration->engineLoadMode) {
switch (engineConfiguration->algorithm) {
case LM_MAF:
return getMaf();
case LM_MAP:
@ -88,7 +88,7 @@ float getEngineLoadT(engine_configuration_s *engineConfiguration) {
// TODO: real implementation
return getMap();
default:
firmwareError("Unexpected engine load parameter: %d", engineConfiguration->engineLoadMode);
firmwareError("Unexpected engine load parameter: %d", engineConfiguration->algorithm);
return -1;
}
}
@ -113,26 +113,26 @@ int isCrankingRT(engine_configuration_s *engineConfiguration, int rpm) {
return rpm > 0 && rpm < engineConfiguration->crankingSettings.crankingRpm;
}
OutputSignalList ignitionSignals;
OutputSignalList injectonSignals;
OutputSignalList injectonSignals CCM_OPTIONAL;
static void registerSparkEvent(engine_configuration_s const *engineConfiguration, trigger_shape_s * s,
IgnitionEventList *list, OutputSignal *actuator, float localAdvance, float dwell) {
IgnitionEventList *list, io_pin_e pin, float localAdvance, float dwell) {
IgnitionEvent *event = list->getNextActuatorEvent();
if (event == NULL)
return; // error already reported
event->io_pin = pin;
event->advance = localAdvance;
registerActuatorEventExt(engineConfiguration, s, &event->actuator, actuator, localAdvance - dwell);
findTriggerPosition(engineConfiguration, s, &event->dwellPosition, localAdvance - dwell);
}
void initializeIgnitionActions(float advance, float dwellAngle, engine_configuration_s *engineConfiguration,
engine_configuration2_s *engineConfiguration2, IgnitionEventList *list) {
efiAssertVoid(engineConfiguration->cylindersCount > 0, "cylindersCount");
ignitionSignals.clear();
list->resetEventList();
@ -140,15 +140,15 @@ void initializeIgnitionActions(float advance, float dwellAngle, engine_configura
case IM_ONE_COIL:
for (int i = 0; i < engineConfiguration->cylindersCount; i++) {
// todo: extract method
float localAdvance = advance + 720.0 * i / engineConfiguration->cylindersCount;
float localAdvance = advance + 720.0f * i / engineConfiguration->cylindersCount;
registerSparkEvent(engineConfiguration, &engineConfiguration2->triggerShape, list,
ignitionSignals.add(SPARKOUT_1_OUTPUT), localAdvance, dwellAngle);
SPARKOUT_1_OUTPUT, localAdvance, dwellAngle);
}
break;
case IM_WASTED_SPARK:
for (int i = 0; i < engineConfiguration->cylindersCount; i++) {
float localAdvance = advance + 720.0 * i / engineConfiguration->cylindersCount;
float localAdvance = advance + 720.0f * i / engineConfiguration->cylindersCount;
int wastedIndex = i % (engineConfiguration->cylindersCount / 2);
@ -156,17 +156,17 @@ void initializeIgnitionActions(float advance, float dwellAngle, engine_configura
io_pin_e ioPin = (io_pin_e) (SPARKOUT_1_OUTPUT + id);
registerSparkEvent(engineConfiguration, &engineConfiguration2->triggerShape, list,
ignitionSignals.add(ioPin), localAdvance, dwellAngle);
ioPin, localAdvance, dwellAngle);
}
break;
case IM_INDIVIDUAL_COILS:
for (int i = 0; i < engineConfiguration->cylindersCount; i++) {
float localAdvance = advance + 720.0 * i / engineConfiguration->cylindersCount;
float localAdvance = advance + 720.0f * i / engineConfiguration->cylindersCount;
io_pin_e pin = (io_pin_e) ((int) SPARKOUT_1_OUTPUT + getCylinderId(engineConfiguration->firingOrder, i) - 1);
registerSparkEvent(engineConfiguration, &engineConfiguration2->triggerShape, list, ignitionSignals.add(pin),
registerSparkEvent(engineConfiguration, &engineConfiguration2->triggerShape, list, pin,
localAdvance, dwellAngle);
}
break;
@ -176,6 +176,16 @@ void initializeIgnitionActions(float advance, float dwellAngle, engine_configura
}
}
static void registerInjectionEvent(engine_configuration_s const *e,
trigger_shape_s *s,
ActuatorEventList *list,
io_pin_e pin,
float angle
) {
registerActuatorEventExt(e, s, list->getNextActuatorEvent(), injectonSignals.add(pin), angle);
}
void addFuelEvents(engine_configuration_s const *e, engine_configuration2_s *engineConfiguration2,
ActuatorEventList *list, injection_mode_e mode) {
list->resetEventList();
@ -189,7 +199,7 @@ void addFuelEvents(engine_configuration_s const *e, engine_configuration2_s *eng
for (int i = 0; i < e->cylindersCount; i++) {
io_pin_e pin = (io_pin_e) ((int) INJECTOR_1_OUTPUT + getCylinderId(e->firingOrder, i) - 1);
float angle = baseAngle + i * 720.0 / e->cylindersCount;
registerActuatorEventExt(e, s, list->getNextActuatorEvent(), injectonSignals.add(pin), angle);
registerInjectionEvent(e, s, list, pin, angle);
}
break;
case IM_SIMULTANEOUS:
@ -198,7 +208,7 @@ void addFuelEvents(engine_configuration_s const *e, engine_configuration2_s *eng
for (int j = 0; j < e->cylindersCount; j++) {
io_pin_e pin = (io_pin_e) ((int) INJECTOR_1_OUTPUT + j);
registerActuatorEventExt(e, s, list->getNextActuatorEvent(), injectonSignals.add(pin), angle);
registerInjectionEvent(e, s, list, pin, angle);
}
}
break;
@ -206,7 +216,7 @@ void addFuelEvents(engine_configuration_s const *e, engine_configuration2_s *eng
for (int i = 0; i < e->cylindersCount; i++) {
io_pin_e pin = (io_pin_e) ((int) INJECTOR_1_OUTPUT + (i % 2));
float angle = baseAngle + i * 720.0 / e->cylindersCount;
registerActuatorEventExt(e, s, list->getNextActuatorEvent(), injectonSignals.add(pin), angle);
registerInjectionEvent(e, s, list, pin, angle);
}
break;
default:
@ -228,12 +238,16 @@ float getSparkDwellMsT(engine_configuration_s *engineConfiguration, int rpm) {
return interpolate2d(rpm, engineConfiguration->sparkDwellBins, engineConfiguration->sparkDwell, DWELL_CURVE_SIZE);
}
int getEngineCycleEventCount2(operation_mode_e mode, trigger_shape_s * s) {
return mode == FOUR_STROKE_CAM_SENSOR ? s->getSize() : 2 * s->getSize();
}
/**
* Trigger event count equals engine cycle event count if we have a cam sensor.
* Two trigger cycles make one engine cycle in case of a four stroke engine If we only have a cranksensor.
*/
int getEngineCycleEventCount(engine_configuration_s const *engineConfiguration, trigger_shape_s * s) {
return getOperationMode(engineConfiguration) == FOUR_STROKE_CAM_SENSOR ? s->getSize() : 2 * s->getSize();
return getEngineCycleEventCount2(getOperationMode(engineConfiguration), s);
}
void findTriggerPosition(engine_configuration_s const *engineConfiguration, trigger_shape_s * s,
@ -241,37 +255,40 @@ void findTriggerPosition(engine_configuration_s const *engineConfiguration, trig
angleOffset = fixAngle(angleOffset + engineConfiguration->globalTriggerAngleOffset);
// todo: migrate to crankAngleRange?
float firstAngle = s->wave.getAngle(s->triggerShapeSynchPointIndex, engineConfiguration, s);
int engineCycleEventCount = getEngineCycleEventCount(engineConfiguration, s);
// let's find the last trigger angle which is less or equal to the desired angle
int i;
for (i = 0; i < engineCycleEventCount - 1; i++) {
// todo: we need binary search here
float angle = fixAngle(
s->wave.getAngle((s->triggerShapeSynchPointIndex + i + 1) % engineCycleEventCount, engineConfiguration, s)
- firstAngle);
if (angle > angleOffset)
int middle;
int left = 0;
int right = engineCycleEventCount - 1;
/**
* Let's find the last trigger angle which is less or equal to the desired angle
* todo: extract binary search as template method?
*/
while (true) {
middle = (left + right) / 2;
if (middle == left)
break;
if (angleOffset < s->eventAngles[middle]) {
right = middle;
} else if (angleOffset > s->eventAngles[middle]) {
left = middle;
} else {
break;
}
}
// explicit check for zero to avoid issues where logical zero is not exactly zero due to float nature
float eventAngle;
if (i == 0) {
eventAngle = 0;
} else {
eventAngle = fixAngle(
s->wave.getAngle((s->triggerShapeSynchPointIndex + i) % engineCycleEventCount, engineConfiguration, s)
- firstAngle);
}
float eventAngle = s->eventAngles[middle];
if (angleOffset < eventAngle) {
firmwareError("angle constraint violation in registerActuatorEventExt(): %f/%f", angleOffset, eventAngle);
return;
}
position->eventIndex = i;
position->eventIndex = middle;
position->eventAngle = eventAngle;
position->angleOffset = angleOffset - eventAngle;
}
@ -318,8 +335,8 @@ int getCylinderId(firing_order_e firingOrder, int index) {
void prepareOutputSignals(engine_configuration_s *engineConfiguration, engine_configuration2_s *engineConfiguration2) {
// todo: move this reset into decoder
engineConfiguration2->triggerShape.triggerShapeSynchPointIndex = findTriggerZeroEventIndex(
&engineConfiguration2->triggerShape, &engineConfiguration->triggerConfig);
engineConfiguration2->triggerShape.setTriggerShapeSynchPointIndex(findTriggerZeroEventIndex(
&engineConfiguration2->triggerShape, &engineConfiguration->triggerConfig));
injectonSignals.clear();
EventHandlerConfiguration *config = &engineConfiguration2->engineEventConfiguration;
@ -329,16 +346,6 @@ void prepareOutputSignals(engine_configuration_s *engineConfiguration, engine_co
engineConfiguration->injectionMode);
}
void setTableBin(float array[], int size, float l, float r) {
for (int i = 0; i < size; i++) {
float value = interpolate(0, l, size - 1, r, i);
/**
* rounded values look nicer, also we want to avoid precision mismatch with Tuner Studio
*/
array[i] = efiRound(value, 0.01);
}
}
void setFuelRpmBin(engine_configuration_s *engineConfiguration, float l, float r) {
setTableBin(engineConfiguration->fuelRpmBins, FUEL_RPM_COUNT, l, r);
}

View File

@ -13,48 +13,14 @@
#ifdef __cplusplus
#include "ec2.h"
#include "trigger_structure.h"
#include "table_helper.h"
void findTriggerPosition(engine_configuration_s const *engineConfiguration, trigger_shape_s * s,
event_trigger_position_s *position, float angleOffset);
int isInjectionEnabled(engine_configuration2_s const *engineConfiguration2);
// 'random' value to be sure we are not treating any non-zero trash as TRUE
#define MAGIC_TRUE_VALUE 153351512
template<int RPM_BIN_SIZE, int LOAD_BIN_SIZE>
class Map3D {
public:
void init(float table[RPM_BIN_SIZE][LOAD_BIN_SIZE]);
float getValue(float x, float xBin[], float y, float yBin[]);
void setAll(float value);
private:
float *pointers[LOAD_BIN_SIZE];
int initialized;
};
template<int RPM_BIN_SIZE, int LOAD_BIN_SIZE>
void Map3D<RPM_BIN_SIZE, LOAD_BIN_SIZE>::init(float table[RPM_BIN_SIZE][LOAD_BIN_SIZE]) {
for (int k = 0; k < LOAD_BIN_SIZE; k++)
pointers[k] = table[k];
initialized = MAGIC_TRUE_VALUE;
}
template<int RPM_BIN_SIZE, int LOAD_BIN_SIZE>
float Map3D<RPM_BIN_SIZE, LOAD_BIN_SIZE>::getValue(float x, float xBin[], float y, float yBin[]) {
efiAssert(initialized == MAGIC_TRUE_VALUE, "fuel map initialized", NAN);
return interpolate3d(x, xBin, LOAD_BIN_SIZE, y, yBin, RPM_BIN_SIZE, pointers);
}
template<int RPM_BIN_SIZE, int LOAD_BIN_SIZE>
void Map3D<RPM_BIN_SIZE, LOAD_BIN_SIZE>::setAll(float value) {
for (int l = 0; l < LOAD_BIN_SIZE; l++) {
for (int r = 0; r < RPM_BIN_SIZE; r++) {
pointers[l][r] = value;
}
}
}
typedef Map3D<16, 16> Map3D1616;
float fixAngle(float angle);
#endif
@ -63,8 +29,6 @@ extern "C"
{
#endif /* __cplusplus */
//float getDefaultVE(int rpm);
float getDefaultFuel(int rpm, float map);
float getOneDegreeTimeMs(int rpm);
@ -74,19 +38,14 @@ float getCrankshaftRevolutionTimeMs(int rpm);
int isCrankingRT(engine_configuration_s *engineConfiguration, int rpm);
#define isCrankingR(rpm) isCrankingRT(engineConfiguration, rpm)
float fixAngle(float angle);
float getTriggerEventAngle(int triggerEventIndex);
float getEngineLoadT(engine_configuration_s *engineConfiguration);
#define getEngineLoad() getEngineLoadT(engineConfiguration)
float getSparkDwellMsT(engine_configuration_s *engineConfiguration, int rpm);
#define getSparkDwellMs(rpm) getSparkDwellMsT(engineConfiguration, rpm)
int getCylinderId(firing_order_e firingOrder, int index);
void setTableBin(float array[], int size, float l, float r);
void setFuelRpmBin(engine_configuration_s *engineConfiguration, float l, float r);
void setFuelLoadBin(engine_configuration_s *engineConfiguration, float l, float r);
void setTimingRpmBin(engine_configuration_s *engineConfiguration, float l, float r);

View File

@ -45,34 +45,48 @@ float getTCharge(int rpm, int tps, float coolantTemp, float airTemp) {
*/
#define GAS_R 0.28705
/**
* @return value in seconds
*/
float sdMath(engine_configuration_s *engineConfiguration, float VE, float MAP, float AFR, float temp) {
float injectorFlowRate = cc_minute_to_gramm_second(engineConfiguration->injectorFlow);
float Vol = engineConfiguration->displacement / engineConfiguration->cylindersCount;
return (Vol * VE * MAP) / (AFR * injectorFlowRate * GAS_R * temp);
}
/**
* @return value in Milliseconds
*/
float getSpeedDensityFuel(Engine *engine) {
int rpm = engine->rpmCalculator->rpm();
engine_configuration_s *engineConfiguration = engine->engineConfiguration;
float tps = getTPS();
float coolantC = getCoolantTemperature();
float intakeC = getIntakeAirTemperature();
float tChargeK = convertCelciusToKelvin(getTCharge(rpm, tps, coolantC, intakeC));
float MAP = getMap();
float VE = 0.8;//veMap.getValue(rpm)
float AFR = 14.7;
return sdMath(engine->engineConfiguration, VE, MAP, AFR, tChargeK);
float tChargeK = convertCelsiusToKelvin(getTCharge(rpm, tps, coolantC, intakeC));
float map = getMap();
float VE = veMap.getValue(map, engineConfiguration->veLoadBins, rpm,
engineConfiguration->veRpmBins);
float AFR = afrMap.getValue(map, engineConfiguration->afrLoadBins, rpm,
engineConfiguration->afrRpmBins);
return sdMath(engine->engineConfiguration, VE, map, AFR, tChargeK) * 1000;
}
void setDetaultVETable(engine_configuration_s *engineConfiguration) {
setTableBin(engineConfiguration->veRpmBins, FUEL_RPM_COUNT, 800, 7000);
setRpmTableBin(engineConfiguration->veRpmBins, VE_RPM_COUNT);
setTableBin2(engineConfiguration->veLoadBins, VE_LOAD_COUNT, 10, 300, 1);
setRpmTableBin(engineConfiguration->afrRpmBins, AFR_RPM_COUNT);
setTableBin2(engineConfiguration->afrLoadBins, VE_LOAD_COUNT, 10, 300, 1);
veMap.setAll(0.8);
afrMap.setAll(14.7);
}
void initSpeedDensity(configuration_s *config) {
veMap.init(config->engineConfiguration->veTable);
afrMap.init(config->engineConfiguration->afrTable);
void initSpeedDensity(engine_configuration_s *engineConfiguration) {
veMap.init(engineConfiguration->veTable);
afrMap.init(engineConfiguration->afrTable);
}

View File

@ -18,6 +18,7 @@ float sdMath(engine_configuration_s *engineConfiguration, float VE, float MAP, f
#define cc_minute_to_gramm_second(ccm) ((ccm) * 0.0119997981)
void initSpeedDensity(configuration_s *config);
void setDetaultVETable(engine_configuration_s *engineConfiguration);
void initSpeedDensity(engine_configuration_s *engineConfiguration);
#endif /* SPEED_DENSITY_H_ */

View File

@ -17,10 +17,14 @@
#include "engine_math.h"
#include "ec2.h"
// Celsius
#define LIMPING_MODE_IAT_TEMPERATURE 30
#define LIMPING_MODE_CLT_TEMPERATURE 70
extern engine_configuration_s *engineConfiguration;
extern engine_configuration2_s *engineConfiguration2;
static bool_t initialized = FALSE;
static bool initialized = false;
/**
* http://en.wikipedia.org/wiki/Voltage_divider
@ -44,29 +48,21 @@ float convertResistanceToKelvinTemperature(float resistance, ThermistorConf *the
//warning("Invalid resistance in convertResistanceToKelvinTemperature=", resistance);
return 0;
}
float logR = log(resistance);
float logR = logf(resistance);
return 1 / (thermistor->s_h_a + thermistor->s_h_b * logR + thermistor->s_h_c * logR * logR * logR);
}
float convertKelvinToC(float tempK) {
return tempK - KELV;
}
float convertCelciusToKelvin(float tempC) {
return tempC + KELV;
}
float convertCelciustoF(float tempC) {
float convertCelsiustoF(float tempC) {
return tempC * 9 / 5 + 32;
}
float convertFtoCelcius(float tempF) {
float convertFtoCelsius(float tempF) {
return (tempF - 32) / 9 * 5;
}
float convertKelvinToFahrenheit(float kelvin) {
float tempC = convertKelvinToC(kelvin);
return convertCelciustoF(tempC);
float tempC = convertKelvinToCelcius(kelvin);
return convertCelsiustoF(tempC);
}
float getKelvinTemperature(float resistance, ThermistorConf *thermistor) {
@ -94,7 +90,7 @@ float getTemperatureC(Thermistor *thermistor) {
float resistance = getResistance(thermistor);
float kelvinTemperature = getKelvinTemperature(resistance, thermistor->config);
return convertKelvinToC(kelvinTemperature);
return convertKelvinToCelcius(kelvinTemperature);
}
int isValidCoolantTemperature(float temperature) {
@ -108,12 +104,14 @@ int isValidIntakeAirTemperature(float temperature) {
}
/**
* @return coolant temperature, in Celcius
* @return coolant temperature, in Celsius
*/
float getCoolantTemperature(void) {
float temperature = getTemperatureC(&engineConfiguration2->clt);
if (!isValidCoolantTemperature(temperature))
return NAN;
if (!isValidCoolantTemperature(temperature)) {
warning(OBD_PCM_Processor_Fault, "unrealistic coolant temperature %f", temperature);
return LIMPING_MODE_CLT_TEMPERATURE;
}
return temperature;
}
@ -134,9 +132,9 @@ void prepareThermistorCurve(ThermistorConf * config) {
float T2 = config->tempC_2 + KELV;
float T3 = config->tempC_3 + KELV;
float L1 = log(config->resistance_1);
float L2 = log(config->resistance_2);
float L3 = log(config->resistance_3);
float L1 = logf(config->resistance_1);
float L2 = logf(config->resistance_2);
float L3 = logf(config->resistance_3);
float Y1 = 1 / T1;
float Y2 = 1 / T2;
@ -150,11 +148,14 @@ void prepareThermistorCurve(ThermistorConf * config) {
config->s_h_a = Y1 - (config->s_h_b + L1 * L1 * config->s_h_c) * L1;
}
/**
* @return Celsius value
*/
float getIntakeAirTemperature(void) {
float temperature = getTemperatureC(&engineConfiguration2->iat);
if (!isValidIntakeAirTemperature(temperature)) {
warning(OBD_PCM_Processor_Fault, "unrealistic intake temperature %f", temperature);
return NAN;
return LIMPING_MODE_IAT_TEMPERATURE;
}
return temperature;
}

View File

@ -26,10 +26,10 @@ float getR1InVoltageDividor(float Vout, float Vin, float r2);
float getR2InVoltageDividor(float Vout, float Vin, float r1);
float getTempK(float resistance);
/**
* converts Kelvin temperature into Celcius temperature
* converts Kelvin temperature into Celsius temperature
*/
float convertKelvinToCelcius(float tempK);
float convertCelciusToKelvin(float tempC);
#define convertKelvinToCelcius(tempK) ((tempK) - KELV)
#define convertCelsiusToKelvin(tempC) ((tempC) + KELV)
float convertCelciustoF(float tempC);
float convertFtoCelcius(float tempF);

View File

@ -19,10 +19,12 @@
#include "ec2.h"
#include "map.h"
#include "trigger_decoder.h"
#include "console_io.h"
#if EFI_PROD_CODE
#include "rusefi.h"
#include "pin_repository.h"
#include "hardware.h"
#endif /* EFI_PROD_CODE */
#if EFI_INTERNAL_FLASH
@ -114,7 +116,7 @@ static const char * pinModeToString(pin_output_mode_e mode) {
}
}
static const char * boolToString(bool_t value) {
static const char * boolToString(bool value) {
return value ? "Yes" : "No";
}
@ -201,6 +203,7 @@ void printConfiguration(engine_configuration_s *engineConfiguration, engine_conf
scheduleMsg(&logger, "primary trigger input: %s", hwPortname(boardConfiguration->primaryTriggerInputPin));
scheduleMsg(&logger, "boardTestModeJumperPin: %s", hwPortname(boardConfiguration->boardTestModeJumperPin));
#endif /* EFI_PROD_CODE */
scheduleMsg(&logger, "isInjectionEnabledFlag %s", boolToString(engineConfiguration2->isInjectionEnabledFlag));
@ -412,8 +415,8 @@ static void setIgnitionMode(int value) {
doPrintConfiguration();
}
static void setTotalToothCount(int value) {
engineConfiguration->triggerConfig.totalToothCount = value;
static void setToothedWheel(int total, int skipped) {
setToothedWheelConfiguration(engineConfiguration, total, skipped);
initializeTriggerShape(&logger, engineConfiguration, engineConfiguration2);
incrementGlobalConfigurationVersion();
doPrintConfiguration();
@ -484,6 +487,23 @@ static void disableInjection(void) {
scheduleMsg(&logger, "injection disabled");
}
#if EFI_WAVE_CHART
extern int waveChartUsedSize;
#endif
static void printAllInfo(void) {
printTemperatureInfo();
printTPSInfo();
printMAPInfo();
#if EFI_WAVE_CHART
scheduleMsg(&logger, "waveChartUsedSize=%d", waveChartUsedSize);
#endif
#if EFI_PROD_CODE
scheduleMsg(&logger, "console mode jumper: %s", boolToString(!GET_CONSOLE_MODE_VALUE()));
scheduleMsg(&logger, "board test mode jumper: %s", boolToString(GET_BOARD_TEST_MODE_VALUE()));
#endif
}
void initSettings(void) {
initLoggingExt(&logger, "settings control", LOGGING_BUFFER, sizeof(LOGGING_BUFFER));
@ -491,6 +511,7 @@ void initSettings(void) {
addConsoleAction("tempinfo", printTemperatureInfo);
addConsoleAction("tpsinfo", printTPSInfo);
addConsoleAction("mapinfo", printMAPInfo);
addConsoleAction("info", printAllInfo);
addConsoleActionI("set_ignition_offset", setIgnitionOffset);
addConsoleActionI("set_injection_offset", setInjectionOffset);
@ -531,6 +552,6 @@ void initSettings(void) {
addConsoleAction("enable_injection", enableInjection);
addConsoleAction("disable_injection", disableInjection);
addConsoleActionI("set_total_tooth_count", setTotalToothCount);
addConsoleActionII("set_toothed_wheel", setToothedWheel);
}

View File

@ -32,7 +32,7 @@ static void executorCallback(void *arg) {
}
Executor::Executor() {
reentrantLock = FALSE;
reentrantLock = false;
}
void Executor::lock(void) {
@ -76,7 +76,7 @@ void Executor::doExecute(uint64_t nowUs) {
firmwareError("Someone has stolen my lock");
return;
}
reentrantLock = FALSE;
reentrantLock = false;
/**
* Let's set up the timer for the next execution
*/

View File

@ -18,7 +18,7 @@ public:
void execute(uint64_t nowUs);
private:
EventQueue queue;
bool_t reentrantLock;
bool reentrantLock;
void doExecute(uint64_t nowUs);
void lock(void);
void unlock(void);

View File

@ -18,7 +18,7 @@ EventQueue::EventQueue() {
head = NULL;
}
bool_t EventQueue::checkIfPending(scheduling_s *scheduling) {
bool EventQueue::checkIfPending(scheduling_s *scheduling) {
return assertNotInList<scheduling_s>(head, scheduling);
}

View File

@ -16,7 +16,7 @@
#define QUEUE_LENGTH_LIMIT 1000
template<typename T>
bool_t assertNotInList(T *head, T*element) {
bool assertNotInList(T *head, T*element) {
// this code is just to validate state, no functional load
T * current;
int counter = 0;
@ -48,7 +48,7 @@ public:
int size(void);
scheduling_s *getForUnitText(int index);
private:
bool_t checkIfPending(scheduling_s *scheduling);
bool checkIfPending(scheduling_s *scheduling);
scheduling_s *head;
};

View File

@ -46,7 +46,7 @@ void SimplePwm::setSimplePwmDutyCycle(float dutyCycle) {
static uint64_t getNextSwitchTimeUs(PwmConfig *state) {
efiAssert(state->safe.phaseIndex < PWM_PHASE_MAX_COUNT, "phaseIndex range", 0);
int iteration = state->safe.iteration;
float switchTime = state->multiWave.switchTimes[state->safe.phaseIndex];
float switchTime = state->multiWave.getSwitchTime(state->safe.phaseIndex);
float periodMs = state->safe.periodMs;
#if DEBUG_PWM
scheduleMsg(&logger, "iteration=%d switchTime=%f period=%f", iteration, switchTime, period);
@ -131,7 +131,7 @@ void copyPwmParameters(PwmConfig *state, int phaseCount, float *switchTimes, int
state->phaseCount = phaseCount;
for (int phaseIndex = 0; phaseIndex < phaseCount; phaseIndex++) {
state->multiWave.switchTimes[phaseIndex] = switchTimes[phaseIndex];
state->multiWave.setSwitchTime(phaseIndex, switchTimes[phaseIndex]);
for (int waveIndex = 0; waveIndex < waveCount; waveIndex++) {
// print("output switch time index (%d/%d) at %f to %d\r\n", phaseIndex,waveIndex,

View File

@ -79,10 +79,12 @@ static Logging logger;
static void handleFuelInjectionEvent(MainTriggerCallback *mainTriggerCallback, ActuatorEvent *event, int rpm) {
float fuelMs = getFuelMs(rpm) * mainTriggerCallback->engineConfiguration->globalFuelCorrection;
if (cisnan(fuelMs)) {
warning(OBD_PCM_Processor_Fault, "NaN injection pulse");
return;
}
if (fuelMs < 0) {
#if EFI_PROD_CODE
scheduleMsg(&logger, "ERROR: negative injectionPeriod %f", fuelMs);
#endif
warning(OBD_PCM_Processor_Fault, "Negative injection pulse %f", fuelMs);
return;
}
@ -128,8 +130,7 @@ static void handleSparkEvent(MainTriggerCallback *mainTriggerCallback, int event
return;
}
ActuatorEvent *event = &iEvent->actuator;
float sparkDelay = getOneDegreeTimeMs(rpm) * event->position.angleOffset;
float sparkDelay = getOneDegreeTimeMs(rpm) * iEvent->dwellPosition.angleOffset;
int isIgnitionError = sparkDelay < 0;
ignitionErrorDetection.add(isIgnitionError);
if (isIgnitionError) {
@ -140,9 +141,6 @@ static void handleSparkEvent(MainTriggerCallback *mainTriggerCallback, int event
return;
}
OutputSignal *signal = event->actuator;
//scheduleOutput(event->actuator, sparkDelay, dwellMs);
if (cisnan(dwellMs)) {
firmwareError("NaN in scheduleOutput", dwellMs);
return;
@ -152,13 +150,13 @@ static void handleSparkEvent(MainTriggerCallback *mainTriggerCallback, int event
* We are alternating two event lists in order to avoid a potential issue around revolution boundary
* when an event is scheduled within the next revolution.
*/
scheduling_s * sUp = &signal->signalTimerUp[0];
scheduling_s * sDown = &signal->signalTimerDown[0];
scheduling_s * sUp = &iEvent->signalTimerUp;
scheduling_s * sDown = &iEvent->signalTimerDown;
/**
* The start of charge is always within the current trigger event range, so just plain time-based scheduling
*/
scheduleTask(sUp, (int) MS2US(sparkDelay), (schfunc_t) &turnPinHigh, (void *) signal);
scheduleTask(sUp, (int) MS2US(sparkDelay), (schfunc_t) &turnPinHigh, (void *) iEvent->io_pin);
/**
* Spark event is often happening during a later trigger event timeframe
* TODO: improve precision
@ -173,7 +171,7 @@ static void handleSparkEvent(MainTriggerCallback *mainTriggerCallback, int event
*/
float timeTillIgnitionUs = getOneDegreeTimeUs(rpm) * iEvent->sparkPosition.angleOffset;
scheduleTask(sDown, (int) timeTillIgnitionUs, (schfunc_t) &turnPinLow, (void*) signal);
scheduleTask(sDown, (int) timeTillIgnitionUs, (schfunc_t) &turnPinLow, (void*) iEvent->io_pin);
} else {
/**
* Spark should be scheduled in relation to some future trigger event, this way we get better firing precision
@ -183,8 +181,6 @@ static void handleSparkEvent(MainTriggerCallback *mainTriggerCallback, int event
return;
LL_APPEND(iHead, iEvent);
//scheduleTask(sDown, (int) MS2US(sparkDelay + dwellMs), (schfunc_t) &turnPinLow, (void*) signal);
}
}
@ -205,19 +201,17 @@ static void handleSpark(MainTriggerCallback *mainTriggerCallback, int eventIndex
// time to fire a spark which was scheduled previously
LL_DELETE(iHead, current);
ActuatorEvent *event = &current->actuator;
OutputSignal *signal = event->actuator;
scheduling_s * sDown = &signal->signalTimerDown[0];
scheduling_s * sDown = &current->signalTimerDown;
float timeTillIgnitionUs = getOneDegreeTimeUs(rpm) * current->sparkPosition.angleOffset;
scheduleTask(sDown, (int) timeTillIgnitionUs, (schfunc_t) &turnPinLow, (void*) signal);
scheduleTask(sDown, (int) timeTillIgnitionUs, (schfunc_t) &turnPinLow, (void*) current->io_pin);
}
}
// scheduleSimpleMsg(&logger, "eventId spark ", eventIndex);
for (int i = 0; i < list->size; i++) {
IgnitionEvent *event = &list->events[i];
if (event->actuator.position.eventIndex != eventIndex)
if (event->dwellPosition.eventIndex != eventIndex)
continue;
handleSparkEvent(mainTriggerCallback, eventIndex, event, rpm);
}
@ -303,9 +297,14 @@ void onTriggerEvent(trigger_event_e ckpSignalType, int eventIndex, MainTriggerCa
#endif /* EFI_HISTOGRAMS */
}
#include "wave_chart.h"
static void showTriggerHistogram(void) {
printAllCallbacksHistogram();
showMainHistogram();
#if EFI_PROD_CODE
showWaveChartHistogram();
#endif
}
static void showMainInfo(void) {

View File

@ -131,16 +131,16 @@ static char shaft_signal_msg_index[15];
* updated here.
* This callback is invoked on interrupt thread.
*/
void shaftPositionCallback(trigger_event_e ckpSignalType, int index, RpmCalculator *rpmState) {
void rpmShaftPositionCallback(trigger_event_e ckpSignalType, int index, RpmCalculator *rpmState) {
itoa10(&shaft_signal_msg_index[1], index);
if (ckpSignalType == SHAFT_PRIMARY_UP) {
addWaveChartEvent("crank", "up", (char*) shaft_signal_msg_index);
addWaveChartEvent(WC_CRANK1, WC_UP, (char*) shaft_signal_msg_index);
} else if (ckpSignalType == SHAFT_PRIMARY_DOWN) {
addWaveChartEvent("crank", "down", (char*) shaft_signal_msg_index);
addWaveChartEvent(WC_CRANK1, WC_DOWN, (char*) shaft_signal_msg_index);
} else if (ckpSignalType == SHAFT_SECONDARY_UP) {
addWaveChartEvent("crank2", "up", (char*) shaft_signal_msg_index);
addWaveChartEvent(WC_CRANK2, WC_UP, (char*) shaft_signal_msg_index);
} else if (ckpSignalType == SHAFT_SECONDARY_DOWN) {
addWaveChartEvent("crank2", "down", (char*) shaft_signal_msg_index);
addWaveChartEvent(WC_CRANK2, WC_DOWN, (char*) shaft_signal_msg_index);
}
if (index != 0) {
@ -154,7 +154,7 @@ void shaftPositionCallback(trigger_event_e ckpSignalType, int index, RpmCalculat
uint64_t nowUs = getTimeNowUs();
bool_t hadRpmRecently = rpmState->isRunning();
bool hadRpmRecently = rpmState->isRunning();
if (hadRpmRecently) {
if (isNoisySignal(rpmState, nowUs)) {
@ -210,7 +210,7 @@ void initRpmCalculator(void) {
strcpy((char*) shaft_signal_msg_index, "_");
addTriggerEventListener((ShaftPositionListener)&shaftPositionCallback, "rpm reporter", &rpmState);
addTriggerEventListener((ShaftPositionListener)&rpmShaftPositionCallback, "rpm reporter", &rpmState);
}
#if EFI_PROD_CODE || EFI_SIMULATOR

View File

@ -11,6 +11,11 @@
#include <time.h>
#define WC_DOWN "d"
#define WC_UP "u"
#define WC_CRANK1 "c1"
#define WC_CRANK2 "c2"
#define NOISY_RPM -1
#ifdef __cplusplus
@ -36,7 +41,7 @@ public:
* @brief Current RPM
*/
int getRpmE(Engine *engine);
void shaftPositionCallback(trigger_event_e ckpSignalType, int index, RpmCalculator *rpmState);
void rpmShaftPositionCallback(trigger_event_e ckpSignalType, int index, RpmCalculator *rpmState);
#endif
#ifdef __cplusplus

View File

@ -15,11 +15,10 @@ static inline float addPair(trigger_shape_s *s, float a, float w) {
return a;
}
void configureMiniCooperTriggerShape(engine_configuration_s *engineConfiguration,
engine_configuration2_s *engineConfiguration2) {
trigger_shape_s *s = &engineConfiguration2->triggerShape;
void configureMiniCooperTriggerShape(trigger_config_s *triggerConfig,
trigger_shape_s *s) {
s->reset();
s->reset(FOUR_STROKE_CAM_SENSOR);
// s->initialState[0] = 1;
@ -68,5 +67,5 @@ void configureMiniCooperTriggerShape(engine_configuration_s *engineConfiguration
/**
* With just one tooth on camshaft synchronization is not needed
*/
engineConfiguration->triggerConfig.isSynchronizationNeeded = FALSE;
triggerConfig->isSynchronizationNeeded = FALSE;
}

View File

@ -10,7 +10,7 @@
#include "engine_configuration.h"
#include "ec2.h"
void configureMiniCooperTriggerShape(engine_configuration_s *engineConfiguration,
engine_configuration2_s *engineConfiguration2);
void configureMiniCooperTriggerShape(trigger_config_s *triggerConfig,
trigger_shape_s *s);
#endif /* TRIGGER_BMW_H_ */

View File

@ -88,9 +88,9 @@ void TriggerCentral::handleShaftSignal(configuration_s *configuration, trigger_e
trigger_shape_s * triggerShape = &configuration->engineConfiguration2->triggerShape;
/**
* This invocation changes the state of
* This invocation changes the state of triggerState
*/
triggerState.processTriggerEvent(triggerShape, &configuration->engineConfiguration->triggerConfig, signal, nowUs);
triggerState.decodeTriggerEvent(triggerShape, &configuration->engineConfiguration->triggerConfig, signal, nowUs);
if (!triggerState.shaft_is_synchronized)
return; // we should not propagate event if we do not know where we are

View File

@ -30,17 +30,19 @@ private:
};
#endif
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
void addTriggerEventListener(ShaftPositionListener handler, const char *name, void *arg);
uint64_t getCrankEventCounter(void);
uint64_t getStartOfRevolutionIndex(void);
int isSignalDecoderError(void);
void hwHandleShaftSignal(trigger_event_e signal);
void initTriggerCentral(void);
void printAllCallbacksHistogram(void);
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
void addTriggerEventListener(ShaftPositionListener handler, const char *name, void *arg);
int isSignalDecoderError(void);
#ifdef __cplusplus
}
#endif /* __cplusplus */

View File

@ -7,59 +7,59 @@
#include "trigger_chrysler.h"
void configureNeonTriggerShape(trigger_shape_s *s) {
s->reset();
void configureNeonTriggerShape(trigger_config_s *triggerConfig, trigger_shape_s *s) {
s->reset(FOUR_STROKE_CAM_SENSOR);
// voodoo magic - we always need 720 at the end
int base = 720 - 560;
s->initialState[0] = 1;
triggerAddEvent(s, base - 720 + 600, T_SECONDARY, TV_HIGH);
triggerAddEvent(s, base - 720 + 604, T_SECONDARY, TV_LOW);
triggerAddEvent(s, base - 720 + 616, T_SECONDARY, TV_HIGH);
triggerAddEvent(s, base - 720 + 620, T_SECONDARY, TV_LOW);
triggerAddEvent(s, base - 720 + 643, T_SECONDARY, TV_HIGH);
triggerAddEvent(s, base - 720 + 648, T_SECONDARY, TV_LOW);
triggerAddEvent(s, base - 720 + 671, T_SECONDARY, TV_HIGH);
triggerAddEvent(s, base - 720 + 676, T_SECONDARY, TV_LOW);
s->addEvent(base - 720 + 600, T_SECONDARY, TV_HIGH);
s->addEvent(base - 720 + 604, T_SECONDARY, TV_LOW);
s->addEvent(base - 720 + 616, T_SECONDARY, TV_HIGH);
s->addEvent(base - 720 + 620, T_SECONDARY, TV_LOW);
s->addEvent(base - 720 + 643, T_SECONDARY, TV_HIGH);
s->addEvent(base - 720 + 648, T_SECONDARY, TV_LOW);
s->addEvent(base - 720 + 671, T_SECONDARY, TV_HIGH);
s->addEvent(base - 720 + 676, T_SECONDARY, TV_LOW);
triggerAddEvent(s, base + 0, T_PRIMARY, TV_LOW);
s->addEvent(base + 0, T_PRIMARY, TV_LOW);
triggerAddEvent(s, base + 20, T_SECONDARY, TV_HIGH);
triggerAddEvent(s, base + 60, T_SECONDARY, TV_LOW);
triggerAddEvent(s, base + 75, T_SECONDARY, TV_HIGH);
triggerAddEvent(s, base + 79, T_SECONDARY, TV_LOW);
triggerAddEvent(s, base + 101, T_SECONDARY, TV_HIGH);
triggerAddEvent(s, base + 106, T_SECONDARY, TV_LOW);
triggerAddEvent(s, base + 130, T_SECONDARY, TV_HIGH);
triggerAddEvent(s, base + 135, T_SECONDARY, TV_LOW);
s->addEvent(base + 20, T_SECONDARY, TV_HIGH);
s->addEvent(base + 60, T_SECONDARY, TV_LOW);
s->addEvent(base + 75, T_SECONDARY, TV_HIGH);
s->addEvent(base + 79, T_SECONDARY, TV_LOW);
s->addEvent(base + 101, T_SECONDARY, TV_HIGH);
s->addEvent(base + 106, T_SECONDARY, TV_LOW);
s->addEvent(base + 130, T_SECONDARY, TV_HIGH);
s->addEvent(base + 135, T_SECONDARY, TV_LOW);
triggerAddEvent(s, base + 200, T_PRIMARY, TV_HIGH); // width = 150
s->addEvent(base + 200, T_PRIMARY, TV_HIGH); // width = 150
triggerAddEvent(s, base + 236, T_SECONDARY, TV_HIGH);
triggerAddEvent(s, base + 239, T_SECONDARY, TV_LOW);
triggerAddEvent(s, base + 250, T_SECONDARY, TV_HIGH);
triggerAddEvent(s, base + 255, T_SECONDARY, TV_LOW);
triggerAddEvent(s, base + 277, T_SECONDARY, TV_HIGH);
triggerAddEvent(s, base + 282, T_SECONDARY, TV_LOW);
triggerAddEvent(s, base + 305, T_SECONDARY, TV_HIGH);
triggerAddEvent(s, base + 310, T_SECONDARY, TV_LOW);
s->addEvent(base + 236, T_SECONDARY, TV_HIGH);
s->addEvent(base + 239, T_SECONDARY, TV_LOW);
s->addEvent(base + 250, T_SECONDARY, TV_HIGH);
s->addEvent(base + 255, T_SECONDARY, TV_LOW);
s->addEvent(base + 277, T_SECONDARY, TV_HIGH);
s->addEvent(base + 282, T_SECONDARY, TV_LOW);
s->addEvent(base + 305, T_SECONDARY, TV_HIGH);
s->addEvent(base + 310, T_SECONDARY, TV_LOW);
triggerAddEvent(s, base + 374, T_SECONDARY, TV_HIGH);
s->addEvent(base + 374, T_SECONDARY, TV_HIGH);
triggerAddEvent(s, base + 395, T_PRIMARY, TV_LOW); // width =
s->addEvent(base + 395, T_PRIMARY, TV_LOW); // width =
triggerAddEvent(s, base + 418, T_SECONDARY, TV_LOW);
triggerAddEvent(s, base + 436, T_SECONDARY, TV_HIGH);
triggerAddEvent(s, base + 441, T_SECONDARY, TV_LOW);
triggerAddEvent(s, base + 463, T_SECONDARY, TV_HIGH);
triggerAddEvent(s, base + 468, T_SECONDARY, TV_LOW);
triggerAddEvent(s, base + 492, T_SECONDARY, TV_HIGH);
triggerAddEvent(s, base + 497, T_SECONDARY, TV_LOW);
s->addEvent(base + 418, T_SECONDARY, TV_LOW);
s->addEvent(base + 436, T_SECONDARY, TV_HIGH);
s->addEvent(base + 441, T_SECONDARY, TV_LOW);
s->addEvent(base + 463, T_SECONDARY, TV_HIGH);
s->addEvent(base + 468, T_SECONDARY, TV_LOW);
s->addEvent(base + 492, T_SECONDARY, TV_HIGH);
s->addEvent(base + 497, T_SECONDARY, TV_LOW);
triggerAddEvent(s, base + 560, T_PRIMARY, TV_HIGH); // width =
s->addEvent(base + 560, T_PRIMARY, TV_HIGH); // width =
s->shaftPositionEventCount = 4 + 8 + 8 + 8 + 8;
}

View File

@ -10,6 +10,6 @@
#include "trigger_structure.h"
void configureNeonTriggerShape(trigger_shape_s *s);
void configureNeonTriggerShape(trigger_config_s *triggerConfig, trigger_shape_s *s);
#endif /* TRIGGER_CHRYSLER_H_ */

View File

@ -1,5 +1,5 @@
/**
* @file trigger_decoder.c
* @file trigger_decoder.cpp
*
* @date Dec 24, 2013
* @author Andrey Belomutskiy, (c) 2012-2014
@ -48,7 +48,7 @@ int isTriggerDecoderError(void) {
static inline int isSynchronizationGap(TriggerState const *shaftPositionState, trigger_shape_s const *triggerShape,
trigger_config_s const *triggerConfig, const int currentDuration) {
if (!triggerConfig->isSynchronizationNeeded)
return FALSE;
return false;
return currentDuration > shaftPositionState->toothed_previous_duration * triggerConfig->syncRatioFrom
&& currentDuration < shaftPositionState->toothed_previous_duration * triggerConfig->syncRatioTo;
@ -57,7 +57,7 @@ static inline int isSynchronizationGap(TriggerState const *shaftPositionState, t
static inline int noSynchronizationResetNeeded(TriggerState *shaftPositionState, trigger_shape_s const *triggerShape,
trigger_config_s const*triggerConfig) {
if (triggerConfig->isSynchronizationNeeded)
return FALSE;
return false;
if (!shaftPositionState->shaft_is_synchronized)
return TRUE;
/**
@ -67,9 +67,10 @@ static inline int noSynchronizationResetNeeded(TriggerState *shaftPositionState,
}
/**
* @brief This method changes the state of trigger_state_s data structure according to the trigger event
* @brief Trigger decoding happends here
* This method changes the state of trigger_state_s data structure according to the trigger event
*/
void TriggerState::processTriggerEvent(trigger_shape_s const*triggerShape, trigger_config_s const*triggerConfig,
void TriggerState::decodeTriggerEvent(trigger_shape_s const*triggerShape, trigger_config_s const*triggerConfig,
trigger_event_e signal, uint64_t nowUs) {
int isLessImportant = (triggerConfig->useRiseEdge && signal != SHAFT_PRIMARY_UP)
@ -83,7 +84,8 @@ void TriggerState::processTriggerEvent(trigger_shape_s const*triggerShape, trigg
return;
}
int64_t currentDuration = nowUs - toothed_previous_time;
int64_t currentDuration = isFirstEvent ? 0 : nowUs - toothed_previous_time;
isFirstEvent = false;
efiAssertVoid(currentDuration >= 0, "negative duration?");
// todo: skip a number of signal from the beginning
@ -119,51 +121,51 @@ void TriggerState::processTriggerEvent(trigger_shape_s const*triggerShape, trigg
toothed_previous_time = nowUs;
}
static void initializeSkippedToothTriggerShape(trigger_shape_s *s, int totalTeethCount, int skippedCount) {
static void initializeSkippedToothTriggerShape(trigger_shape_s *s, int totalTeethCount, int skippedCount, operation_mode_e operationMode) {
efiAssertVoid(s != NULL, "trigger_shape_s is NULL");
s->reset();
s->reset(operationMode);
float toothWidth = 0.5;
for (int i = 0; i < totalTeethCount - skippedCount - 1; i++) {
float angleDown = 720.0 / totalTeethCount * (i + toothWidth);
float angleUp = 720.0 / totalTeethCount * (i + 1);
triggerAddEvent(s, angleDown, T_PRIMARY, TV_HIGH);
triggerAddEvent(s, angleUp, T_PRIMARY, TV_LOW);
s->addEvent(angleDown, T_PRIMARY, TV_HIGH);
s->addEvent(angleUp, T_PRIMARY, TV_LOW);
}
float angleDown = 720.0 / totalTeethCount * (totalTeethCount - skippedCount - 1 + toothWidth);
triggerAddEvent(s, angleDown, T_PRIMARY, TV_HIGH);
triggerAddEvent(s, 720, T_PRIMARY, TV_LOW);
s->addEvent(angleDown, T_PRIMARY, TV_HIGH);
s->addEvent(720, T_PRIMARY, TV_LOW);
}
void initializeSkippedToothTriggerShapeExt(engine_configuration2_s *engineConfiguration2, int totalTeethCount,
int skippedCount) {
int skippedCount, operation_mode_e operationMode) {
efiAssertVoid(totalTeethCount > 0, "totalTeethCount is zero");
trigger_shape_s *s = &engineConfiguration2->triggerShape;
initializeSkippedToothTriggerShape(s, totalTeethCount, skippedCount);
initializeSkippedToothTriggerShape(s, totalTeethCount, skippedCount, operationMode);
s->shaftPositionEventCount = ((totalTeethCount - skippedCount) * 2);
s->wave.checkSwitchTimes(s->getSize());
}
static void configureFordAspireTriggerShape(trigger_shape_s * s) {
s->reset();
static void configureFordAspireTriggerShape(trigger_config_s *triggerConfig, trigger_shape_s * s) {
s->reset(FOUR_STROKE_CAM_SENSOR);
s->shaftPositionEventCount = 10;
triggerAddEvent(s, 53.747, T_SECONDARY, TV_HIGH);
triggerAddEvent(s, 121.90, T_SECONDARY, TV_LOW); // delta = 68.153
triggerAddEvent(s, 232.76, T_SECONDARY, TV_HIGH); // delta = 110.86
triggerAddEvent(s, 300.54, T_SECONDARY, TV_LOW); // delta = 67.78
triggerAddEvent(s, 360, T_PRIMARY, TV_HIGH);
s->addEvent(53.747, T_SECONDARY, TV_HIGH);
s->addEvent(121.90, T_SECONDARY, TV_LOW); // delta = 68.153
s->addEvent(232.76, T_SECONDARY, TV_HIGH); // delta = 110.86
s->addEvent(300.54, T_SECONDARY, TV_LOW); // delta = 67.78
s->addEvent(360, T_PRIMARY, TV_HIGH);
triggerAddEvent(s, 409.8412, T_SECONDARY, TV_HIGH); // delta = 49.8412
triggerAddEvent(s, 478.6505, T_SECONDARY, TV_LOW); // delta = 68.8093
triggerAddEvent(s, 588.045, T_SECONDARY, TV_HIGH); // delta = 109.3945
triggerAddEvent(s, 657.03, T_SECONDARY, TV_LOW);
triggerAddEvent(s, 720, T_PRIMARY, TV_LOW);
s->addEvent(409.8412, T_SECONDARY, TV_HIGH); // delta = 49.8412
s->addEvent(478.6505, T_SECONDARY, TV_LOW); // delta = 68.8093
s->addEvent(588.045, T_SECONDARY, TV_HIGH); // delta = 109.3945
s->addEvent(657.03, T_SECONDARY, TV_LOW);
s->addEvent(720, T_PRIMARY, TV_LOW);
}
/**
@ -174,45 +176,75 @@ void initializeTriggerShape(Logging *logger, engine_configuration_s *engineConfi
#if EFI_PROD_CODE
printMsg(logger, "initializeTriggerShape()");
#endif
trigger_config_s *tt = &engineConfiguration->triggerConfig;
switch (tt->triggerType) {
trigger_config_s *triggerConfig = &engineConfiguration->triggerConfig;
trigger_shape_s *triggerShape = &engineConfiguration2->triggerShape;
switch (triggerConfig->triggerType) {
case TT_TOOTHED_WHEEL:
initializeSkippedToothTriggerShapeExt(engineConfiguration2, tt->totalToothCount, tt->skippedToothCount);
initializeSkippedToothTriggerShapeExt(engineConfiguration2, triggerConfig->totalToothCount, triggerConfig->skippedToothCount,
getOperationMode(engineConfiguration));
return;
case TT_MAZDA_MIATA_NB:
initializeMazdaMiataNbShape(&engineConfiguration2->triggerShape);
initializeMazdaMiataNbShape(triggerConfig, triggerShape);
return;
case TT_DODGE_NEON:
configureNeonTriggerShape(&engineConfiguration2->triggerShape);
configureNeonTriggerShape(triggerConfig, triggerShape);
return;
case TT_FORD_ASPIRE:
configureFordAspireTriggerShape(&engineConfiguration2->triggerShape);
configureFordAspireTriggerShape(triggerConfig, triggerShape);
return;
case TT_GM_7X:
configureGmTriggerShape(&engineConfiguration2->triggerShape);
configureGmTriggerShape(triggerConfig, triggerShape);
return;
case TT_FORD_ESCORT_GT:
configureMazdaProtegeLx(engineConfiguration, engineConfiguration2);
configureMazdaProtegeLx(triggerConfig, triggerShape);
return;
case TT_MINI_COOPER_R50:
configureMiniCooperTriggerShape(engineConfiguration, engineConfiguration2);
configureMiniCooperTriggerShape(triggerConfig, triggerShape);
return;
default:
firmwareError("initializeTriggerShape() not implemented: %d", tt->triggerType);
firmwareError("initializeTriggerShape() not implemented: %d", triggerConfig->triggerType);
;
}
if (engineConfiguration2->triggerShape.shaftPositionEventCount != engineConfiguration2->triggerShape.getSize())
firmwareError("trigger size or shaftPositionEventCount?");
}
TriggerStimulatorHelper::TriggerStimulatorHelper() {
primaryWheelState = false;
secondaryWheelState = false;
}
void TriggerStimulatorHelper::nextStep(TriggerState *state, trigger_shape_s * shape, int i, trigger_config_s const*triggerConfig) {
int stateIndex = i % shape->getSize();
int loopIndex = i / shape->getSize();
int time = (int) (10000 * (loopIndex + shape->wave.getSwitchTime(stateIndex)));
bool newPrimaryWheelState = shape->wave.getChannelState(0, stateIndex);
bool newSecondaryWheelState = shape->wave.getChannelState(1, stateIndex);
if (primaryWheelState != newPrimaryWheelState) {
primaryWheelState = newPrimaryWheelState;
trigger_event_e s = primaryWheelState ? SHAFT_PRIMARY_UP : SHAFT_PRIMARY_DOWN;
state->decodeTriggerEvent(shape, triggerConfig, s, time);
}
if (secondaryWheelState != newSecondaryWheelState) {
secondaryWheelState = newSecondaryWheelState;
trigger_event_e s = secondaryWheelState ? SHAFT_SECONDARY_UP : SHAFT_SECONDARY_DOWN;
state->decodeTriggerEvent(shape, triggerConfig, s, time);
}
}
/**
* Trigger shape is defined in a way which is convenient for trigger shape definition
* On the other hand, trigger decoder indexing begins from synchronization event.
@ -224,34 +256,13 @@ int findTriggerZeroEventIndex(trigger_shape_s * shape, trigger_config_s const*tr
TriggerState state;
errorDetection.clear();
int primaryWheelState = FALSE;
int secondaryWheelState = FALSE;
TriggerStimulatorHelper helper;
for (int i = 0; i < 4 * PWM_PHASE_MAX_COUNT; i++) {
int stateIndex = i % shape->getSize();
int loopIndex = i / shape->getSize();
int time = (int) (10000 * (loopIndex + shape->wave.getSwitchTime(stateIndex)));
int newPrimaryWheelState = shape->wave.getChannelState(0, stateIndex);
int newSecondaryWheelState = shape->wave.getChannelState(1, stateIndex);
if (primaryWheelState != newPrimaryWheelState) {
primaryWheelState = newPrimaryWheelState;
trigger_event_e s = primaryWheelState ? SHAFT_PRIMARY_UP : SHAFT_PRIMARY_DOWN;
state.processTriggerEvent(shape, triggerConfig, s, time);
}
if (secondaryWheelState != newSecondaryWheelState) {
secondaryWheelState = newSecondaryWheelState;
trigger_event_e s = secondaryWheelState ? SHAFT_SECONDARY_UP : SHAFT_SECONDARY_DOWN;
state.processTriggerEvent(shape, triggerConfig, s, time);
}
helper.nextStep(&state, shape, i, triggerConfig);
if (state.shaft_is_synchronized)
return stateIndex;
return i % shape->getSize();;
}
firmwareError("findTriggerZeroEventIndex() failed");
return -1;

View File

@ -14,19 +14,29 @@
#include "engine_configuration.h"
#include "ec2.h"
class TriggerStimulatorHelper {
public:
TriggerStimulatorHelper();
void nextStep(TriggerState *state, trigger_shape_s * shape, int i, trigger_config_s const*triggerConfig);
private:
bool primaryWheelState;
bool secondaryWheelState;
};
void initializeSkippedToothTriggerShapeExt(engine_configuration2_s *engineConfiguration2, int totalTeethCount, int skippedCount, operation_mode_e operationMode);
int findTriggerZeroEventIndex(trigger_shape_s * shape, trigger_config_s const*triggerConfig);
void initializeTriggerShape(Logging *logger, engine_configuration_s *engineConfiguration, engine_configuration2_s *engineConfiguration2);
void initTriggerDecoder(void);
#ifdef __cplusplus
extern "C"
{
#endif
int isTriggerDecoderError(void);
void initializeSkippedToothTriggerShapeExt(engine_configuration2_s *engineConfiguration2, int totalTeethCount, int skippedCount);
void initializeTriggerShape(Logging *logger, engine_configuration_s *engineConfiguration, engine_configuration2_s *engineConfiguration2);
int findTriggerZeroEventIndex(trigger_shape_s * shape, trigger_config_s const*triggerConfig);
void initTriggerDecoder(void);
#ifdef __cplusplus
}
#endif
#endif /* TRIGGER_DECODER_H_ */

View File

@ -1,5 +1,5 @@
/**
* @file trigger_emulator_algo.c
* @file trigger_emulator_algo.cpp
*
* @date Mar 3, 2014
* @author Andrey Belomutskiy, (c) 2012-2014
@ -61,7 +61,7 @@ void initTriggerEmulatorLogic(pwm_gen_callback *stateChangeCallback) {
trigger_shape_s *s = &engineConfiguration2->triggerShape;
setTriggerEmulatorRPM(DEFAULT_EMULATION_RPM);
int *pinStates[2] = {s->wave.waves[0].pinStates, s->wave.waves[1].pinStates};
int *pinStates[2] = { s->wave.waves[0].pinStates, s->wave.waves[1].pinStates};
weComplexInit("position sensor", &triggerSignal, s->getSize(), s->wave.switchTimes, 2, pinStates,
updateTriggerShapeIfNeeded,
stateChangeCallback);

View File

@ -7,34 +7,34 @@
#include "trigger_gm.h"
void configureGmTriggerShape(trigger_shape_s *s) {
s->reset();
void configureGmTriggerShape(trigger_config_s *triggerConfig, trigger_shape_s *s) {
s->reset(FOUR_STROKE_CAM_SENSOR);
// all angles are x2 here - so, 5 degree width is 10
float w = 10;
s->shaftPositionEventCount = 14;
triggerAddEvent(s, 120 - w, T_PRIMARY, TV_HIGH);
triggerAddEvent(s, 120, T_PRIMARY, TV_LOW);
s->addEvent(120 - w, T_PRIMARY, TV_HIGH);
s->addEvent(120, T_PRIMARY, TV_LOW);
triggerAddEvent(s, 240 - w, T_PRIMARY, TV_HIGH);
triggerAddEvent(s, 240, T_PRIMARY, TV_LOW);
s->addEvent(240 - w, T_PRIMARY, TV_HIGH);
s->addEvent(240, T_PRIMARY, TV_LOW);
triggerAddEvent(s, 360 - w, T_PRIMARY, TV_HIGH);
triggerAddEvent(s, 360, T_PRIMARY, TV_LOW);
s->addEvent(360 - w, T_PRIMARY, TV_HIGH);
s->addEvent(360, T_PRIMARY, TV_LOW);
triggerAddEvent(s, 480 - w, T_PRIMARY, TV_HIGH);
triggerAddEvent(s, 480, T_PRIMARY, TV_LOW);
s->addEvent(480 - w, T_PRIMARY, TV_HIGH);
s->addEvent(480, T_PRIMARY, TV_LOW);
triggerAddEvent(s, 600 - w, T_PRIMARY, TV_HIGH);
triggerAddEvent(s, 600, T_PRIMARY, TV_LOW);
s->addEvent(600 - w, T_PRIMARY, TV_HIGH);
s->addEvent(600, T_PRIMARY, TV_LOW);
triggerAddEvent(s, 700 - w, T_PRIMARY, TV_HIGH);
triggerAddEvent(s, 700, T_PRIMARY, TV_LOW);
s->addEvent(700 - w, T_PRIMARY, TV_HIGH);
s->addEvent(700, T_PRIMARY, TV_LOW);
triggerAddEvent(s, 720 - w, T_PRIMARY, TV_HIGH);
triggerAddEvent(s, 720, T_PRIMARY, TV_LOW);
s->addEvent(720 - w, T_PRIMARY, TV_HIGH);
s->addEvent(720, T_PRIMARY, TV_LOW);
}

View File

@ -10,6 +10,6 @@
#include "trigger_structure.h"
void configureGmTriggerShape(trigger_shape_s *s);
void configureGmTriggerShape(trigger_config_s *triggerConfig, trigger_shape_s *s);
#endif /* TRIGGER_GM_H_ */

View File

@ -1,5 +1,5 @@
/**
* @file trigger_mazda.c
* @file trigger_mazda.cpp
*
* @date Feb 18, 2014
* @author Andrey Belomutskiy, (c) 2012-2014
@ -20,78 +20,75 @@
#include "trigger_mazda.h"
void initializeMazdaMiataNbShape(trigger_shape_s *s) {
s->reset();
void initializeMazdaMiataNbShape(trigger_config_s *triggerConfig, trigger_shape_s *s) {
s->reset(FOUR_STROKE_CAM_SENSOR);
/**
* cam sensor is primary, crank sensor is secondary
*/
triggerAddEvent(s, 20, T_PRIMARY, TV_HIGH);
s->addEvent(20, T_PRIMARY, TV_HIGH);
triggerAddEvent(s, 66, T_SECONDARY, TV_LOW);
triggerAddEvent(s, 70, T_SECONDARY, TV_HIGH);
triggerAddEvent(s, 136, T_SECONDARY, TV_LOW);
triggerAddEvent(s, 140, T_SECONDARY, TV_HIGH);
triggerAddEvent(s, 246, T_SECONDARY, TV_LOW);
triggerAddEvent(s, 250, T_SECONDARY, TV_HIGH);
triggerAddEvent(s, 316, T_SECONDARY, TV_LOW);
triggerAddEvent(s, 320, T_SECONDARY, TV_HIGH);
s->addEvent(66, T_SECONDARY, TV_LOW);
s->addEvent(70, T_SECONDARY, TV_HIGH);
s->addEvent(136, T_SECONDARY, TV_LOW);
s->addEvent(140, T_SECONDARY, TV_HIGH);
s->addEvent(246, T_SECONDARY, TV_LOW);
s->addEvent(250, T_SECONDARY, TV_HIGH);
s->addEvent(316, T_SECONDARY, TV_LOW);
s->addEvent(320, T_SECONDARY, TV_HIGH);
triggerAddEvent(s, 340, T_PRIMARY, TV_LOW);
triggerAddEvent(s, 360, T_PRIMARY, TV_HIGH);
s->addEvent(340, T_PRIMARY, TV_LOW);
s->addEvent(360, T_PRIMARY, TV_HIGH);
triggerAddEvent(s, 380, T_PRIMARY, TV_LOW);
triggerAddEvent(s, 400, T_PRIMARY, TV_HIGH);
s->addEvent(380, T_PRIMARY, TV_LOW);
s->addEvent(400, T_PRIMARY, TV_HIGH);
triggerAddEvent(s, 426, T_SECONDARY, TV_LOW);
triggerAddEvent(s, 430, T_SECONDARY, TV_HIGH);
triggerAddEvent(s, 496, T_SECONDARY, TV_LOW);
triggerAddEvent(s, 500, T_SECONDARY, TV_HIGH);
triggerAddEvent(s, 606, T_SECONDARY, TV_LOW);
triggerAddEvent(s, 610, T_SECONDARY, TV_HIGH);
triggerAddEvent(s, 676, T_SECONDARY, TV_LOW);
triggerAddEvent(s, 680, T_SECONDARY, TV_HIGH);
s->addEvent(426, T_SECONDARY, TV_LOW);
s->addEvent(430, T_SECONDARY, TV_HIGH);
s->addEvent(496, T_SECONDARY, TV_LOW);
s->addEvent(500, T_SECONDARY, TV_HIGH);
s->addEvent(606, T_SECONDARY, TV_LOW);
s->addEvent(610, T_SECONDARY, TV_HIGH);
s->addEvent(676, T_SECONDARY, TV_LOW);
s->addEvent(680, T_SECONDARY, TV_HIGH);
triggerAddEvent(s, 720, T_PRIMARY, TV_LOW);
s->addEvent(720, T_PRIMARY, TV_LOW);
s->shaftPositionEventCount = 6 + 16;
}
void configureMazdaProtegeLx(engine_configuration_s *engineConfiguration,
engine_configuration2_s *engineConfiguration2) {
void configureMazdaProtegeLx(trigger_config_s *triggerConfig, trigger_shape_s *s) {
trigger_shape_s *s = &engineConfiguration2->triggerShape;
s->reset();
s->reset(FOUR_STROKE_CAM_SENSOR);
// s->initialState[0] = 1;
float w = 720 / 4 * 0.215;
float a = 5;
// triggerAddEvent(s, a, T_SECONDARY, TV_LOW);
// triggerAddEvent(s, a + w, T_SECONDARY, TV_HIGH);
// s->addEvent(a, T_SECONDARY, TV_LOW);
// s->addEvent(a + w, T_SECONDARY, TV_HIGH);
// a += 180;
// triggerAddEvent(s, a, T_SECONDARY, TV_LOW);
// triggerAddEvent(s, a + w, T_SECONDARY, TV_HIGH);
// s->addEvent(a, T_SECONDARY, TV_LOW);
// s->addEvent(a + w, T_SECONDARY, TV_HIGH);
// a += 180;
// triggerAddEvent(s, a, T_SECONDARY, TV_LOW);
// triggerAddEvent(s, a + w, T_SECONDARY, TV_HIGH);
// s->addEvent(a, T_SECONDARY, TV_LOW);
// s->addEvent(a + w, T_SECONDARY, TV_HIGH);
// a += 180;
// triggerAddEvent(s, a, T_SECONDARY, TV_LOW);
// triggerAddEvent(s, a + w, T_SECONDARY, TV_HIGH);
// s->addEvent(a, T_SECONDARY, TV_LOW);
// s->addEvent(a + w, T_SECONDARY, TV_HIGH);
float z = 0.093;
a = 180;
triggerAddEvent(s, a - z * 720, T_PRIMARY, TV_HIGH);
triggerAddEvent(s, a, T_PRIMARY, TV_LOW);
s->addEvent(a - z * 720, T_PRIMARY, TV_HIGH);
s->addEvent(a, T_PRIMARY, TV_LOW);
a += 180;
triggerAddEvent(s, a - z * 720, T_PRIMARY, TV_HIGH);
triggerAddEvent(s, a, T_PRIMARY, TV_LOW);
s->addEvent(a - z * 720, T_PRIMARY, TV_HIGH);
s->addEvent(a, T_PRIMARY, TV_LOW);
a += 180;
triggerAddEvent(s, a - z * 720, T_PRIMARY, TV_HIGH);
triggerAddEvent(s, a, T_PRIMARY, TV_LOW);
s->addEvent(a - z * 720, T_PRIMARY, TV_HIGH);
s->addEvent(a, T_PRIMARY, TV_LOW);
a += 180;
s->addEvent(a - z * 720, T_PRIMARY, TV_HIGH);
@ -100,5 +97,5 @@ void configureMazdaProtegeLx(engine_configuration_s *engineConfiguration,
// s->shaftPositionEventCount = 2 + 8;
s->shaftPositionEventCount = 8;
engineConfiguration->triggerConfig.isSynchronizationNeeded = FALSE;
triggerConfig->isSynchronizationNeeded = false;
}

View File

@ -12,8 +12,7 @@
#include "engine_configuration.h"
#include "ec2.h"
void initializeMazdaMiataNbShape(trigger_shape_s *s);
void configureMazdaProtegeLx(engine_configuration_s *engineConfiguration,
engine_configuration2_s *engineConfiguration2);
void initializeMazdaMiataNbShape(trigger_config_s *triggerConfig, trigger_shape_s *s);
void configureMazdaProtegeLx(trigger_config_s *triggerConfig, trigger_shape_s *s);
#endif /* TRIGGER_MAZDA_H_ */

View File

@ -29,7 +29,7 @@ trigger_shape_helper::trigger_shape_helper() {
trigger_shape_s::trigger_shape_s() :
wave(switchTimes, NULL) {
reset();
reset(OM_NONE);
wave.waves = h.waves;
}
@ -37,7 +37,33 @@ int trigger_shape_s::getSize() {
return size;
}
void trigger_shape_s::reset() {
int trigger_shape_s::getTriggerShapeSynchPointIndex() {
return triggerShapeSynchPointIndex;
}
// todo: clean-up!
int getEngineCycleEventCount2(operation_mode_e mode, trigger_shape_s * s);
float fixAngle(float angle);
void trigger_shape_s::setTriggerShapeSynchPointIndex(int triggerShapeSynchPointIndex) {
this->triggerShapeSynchPointIndex = triggerShapeSynchPointIndex;
int engineCycleEventCount = getEngineCycleEventCount2(operationMode, this);
float firstAngle = getAngle(triggerShapeSynchPointIndex);
for (int i = 0; i < engineCycleEventCount; i++) {
if (i == 0) {
// explicit check for zero to avoid issues where logical zero is not exactly zero due to float nature
eventAngles[i] = 0;
} else {
eventAngles[i] = fixAngle(getAngle((triggerShapeSynchPointIndex + i) % engineCycleEventCount) - firstAngle);
}
}
}
void trigger_shape_s::reset(operation_mode_e operationMode) {
this->operationMode = operationMode;
size = 0;
shaftPositionEventCount = 0;
triggerShapeSynchPointIndex = 0;
@ -58,6 +84,7 @@ void multi_wave_s::setSwitchTime(int index, float value) {
TriggerState::TriggerState() {
clear();
totalEventCountBase = 0;
isFirstEvent = true;
}
int TriggerState::getCurrentIndex() {
@ -74,7 +101,7 @@ uint64_t TriggerState::getTotalEventCounter() {
void TriggerState::nextRevolution(int triggerEventCount) {
current_index = 0;
totalRevolutionCounter ++;
totalRevolutionCounter++;
totalEventCountBase += triggerEventCount;
}
@ -94,7 +121,30 @@ void TriggerState::clear() {
totalRevolutionCounter = 0;
}
float trigger_shape_s::getAngle(int index) const {
if (operationMode == FOUR_STROKE_CAM_SENSOR)
return switchAngles[index];
/**
* FOUR_STROKE_CRANK_SENSOR magic:
* We have two crank shaft revolutions for each engine cycle
* See also trigger_central.cpp
* See also getEngineCycleEventCount()
*/
int triggerEventCounter = size;
if (index < triggerEventCounter) {
return switchAngles[index];
} else {
return 360 + switchAngles[index - triggerEventCounter];
}
}
void trigger_shape_s::addEvent(float angle, trigger_wheel_e waveIndex, trigger_value_e state) {
efiAssertVoid(operationMode != OM_NONE, "operationMode not set");
/**
* While '720' value works perfectly it has not much sense for crank sensor-only scenario.
* todo: accept angle as a value in the 0..1 range?
*/
angle /= 720;
efiAssertVoid(angle > previousAngle, "invalid angle order");
previousAngle = angle;
@ -114,7 +164,7 @@ void trigger_shape_s::addEvent(float angle, trigger_wheel_e waveIndex, trigger_v
wave->pinStates[0] = initialState[i];
}
wave.setSwitchTime(0, angle);
setSwitchTime(0, angle);
wave.waves[waveIndex].pinStates[0] = state;
return;
}
@ -125,13 +175,14 @@ void trigger_shape_s::addEvent(float angle, trigger_wheel_e waveIndex, trigger_v
for (int i = 0; i < PWM_PHASE_MAX_WAVE_PER_PWM; i++)
wave.waves[i].pinStates[index] = wave.getChannelState(i, index - 1);
wave.setSwitchTime(index, angle);
setSwitchTime(index, angle);
wave.waves[waveIndex].pinStates[index] = state;
}
void triggerAddEvent(trigger_shape_s *trigger, float angle, trigger_wheel_e waveIndex, trigger_value_e state) {
// todo: inline this method
trigger->addEvent(angle, waveIndex, state);
void trigger_shape_s::setSwitchTime(int index, float angle) {
int cycleDuration = (operationMode == FOUR_STROKE_CAM_SENSOR) ? 720 : 360;
switchAngles[index] = cycleDuration * angle;
wave.setSwitchTime(index, angle);
}
void multi_wave_s::checkSwitchTimes(int size) {

View File

@ -25,7 +25,7 @@ public:
uint64_t getStartOfRevolutionIndex();
void nextRevolution(int triggerEventCount);
void nextTriggerEvent();
void processTriggerEvent(trigger_shape_s const*triggerShape, trigger_config_s const*triggerConfig, trigger_event_e signal, uint64_t nowUs);
void decodeTriggerEvent(trigger_shape_s const*triggerShape, trigger_config_s const*triggerConfig, trigger_event_e signal, uint64_t nowUs);
/**
@ -43,6 +43,7 @@ private:
int current_index;
uint64_t totalEventCountBase;
int totalRevolutionCounter;
bool isFirstEvent;
};
typedef enum {
@ -66,12 +67,14 @@ public:
class trigger_shape_s {
private:
void setSwitchTime(int index, float angle);
trigger_shape_helper h;
int size;
public:
trigger_shape_s();
void addEvent(float angle, trigger_wheel_e waveIndex, trigger_value_e state);
void reset();
float getAngle(int phaseIndex) const;
void reset(operation_mode_e operationMode);
int getSize();
multi_wave_s wave;
@ -86,25 +89,38 @@ public:
// tood: maybe even automate this flag calculation?
int initialState[PWM_PHASE_MAX_WAVE_PER_PWM];
int getTriggerShapeSynchPointIndex();
void setTriggerShapeSynchPointIndex(int triggerShapeSynchPointIndex);
/**
* These angles are in event coordinates - with synchronization point located at angle zero.
*/
float eventAngles[PWM_PHASE_MAX_COUNT];
private:
/**
* index of synchronization event within trigger_shape_s
* See findTriggerZeroEventIndex()
*/
int triggerShapeSynchPointIndex;
private:
/**
* Values are in the 0..1 range
*/
float switchTimes[PWM_PHASE_MAX_COUNT];
/**
* These are the same values as in switchTimes, but these are angles in the 0..360 or 0..720 range.
* That's a performance optimization - this should save as one multiplication in a critical spot.
*
* These angles are in trigger DESCRIPTION coordinates - i.e. the way you add events while declaring trigger shape
*/
float switchAngles[PWM_PHASE_MAX_COUNT];
float previousAngle;
/**
* this is part of performance optimization
*/
operation_mode_e operationMode;
};
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
void triggerAddEvent(trigger_shape_s *trigger, float angle, trigger_wheel_e waveIndex, trigger_value_e state);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* TRIGGER_STRUCTURE_H_ */

1
firmware/dump.bat Normal file
View File

@ -0,0 +1 @@
arm-none-eabi-objdump -S build/rusefi.elf > build.dump

View File

@ -48,7 +48,7 @@ void acAddData(float angle, float value) {
appendPrintf(&logging, "analog_chart%s", DELIMETER);
}
if (loggingSize(&logging) < sizeof(LOGGING_BUFFER) - 100)
if (remainingSize(&logging) > 100)
appendPrintf(&logging, "%f|%f|", angle, value);
}

View File

@ -16,6 +16,7 @@
#include "gpio_helper.h"
#include "efilib2.h"
#include "console_io.h"
#include "engine.h"
#if EFI_PERF_METRICS
@ -66,6 +67,8 @@ static void testSystemCalls(const int count) {
scheduleMsg(&logger, "Finished %d iterations of 'currentTimeMillis' in %dms", count, time);
}
static Engine testEngine;
static void testRusefiMethods(const int count) {
time_t start, time;
int tempi = 1;
@ -79,12 +82,20 @@ static void testRusefiMethods(const int count) {
scheduleMsg(&logger, "Finished %d iterations of getBaseFuel in %dms", count, time);
start = currentTimeMillis();
for (int i = 0; i < count; i++)
tempi += getFuelMs(1200);
time = currentTimeMillis() - start;
if (tempi != 0)
scheduleMsg(&logger, "Finished %d iterations of getFuelMs in %dms", count, time);
// for (int i = 0; i < count; i++)
// tempi += getDefaultFuel(4020, 2.21111);
// time = currentTimeMillis() - start;
// if (tempi == 0)
// rint("Finished %d iterations of getDefaultFuel in %dms\r\n", count, time);
start = currentTimeMillis();
for (int i = 0; i < count; i++) {
testEngine.updateSlowSensors();
tempi += testEngine.engineState.clt;
}
time = currentTimeMillis() - start;
if (tempi != 0)
scheduleMsg(&logger, "Finished %d iterations of updateSlowSensors in %dms", count, time);
}
static void testMath(const int count) {
@ -165,6 +176,14 @@ static void testMath(const int count) {
scheduleMsg(&logger, "Finished %d iterations of float division in %dms", count, time);
}
start = currentTimeMillis();
tempf = 1;
for (int i = 0; i < count; i++)
tempf += logf(tempf);
time = currentTimeMillis() - start;
if (tempf != 0)
scheduleMsg(&logger, "Finished %d iterations of float log in %dms", count, time);
start = currentTimeMillis();
double tempd = 1;
for (int i = 0; i < count; i++)
@ -181,9 +200,17 @@ static void testMath(const int count) {
if (tempd != 0)
scheduleMsg(&logger, "Finished %d iterations of double division in %dms", count, time);
start = currentTimeMillis();
tempd = 1;
for (int i = 0; i < count; i++)
tempd += log(tempd);
time = currentTimeMillis() - start;
if (tempd != 0)
scheduleMsg(&logger, "Finished %d iterations of double log in %dms", count, time);
}
static void runTests(const int count) {
scheduleMsg(&logger, "Running tests: %d", count);
testRusefiMethods(count / 10);
testSystemCalls(count);
testMath(count);

View File

@ -49,7 +49,7 @@ static void waAnaWidthCallback(WaveReader *reader) {
uint64_t nowUs = getTimeNowUs();
reader->eventCounter++;
reader->lastActivityTimeUs = nowUs;
addWaveChartEvent(reader->name, "up", "");
addWaveChartEvent(reader->name, WC_UP, "");
uint64_t width = nowUs - reader->periodEventTimeUs;
reader->last_wave_low_widthUs = width;
@ -62,7 +62,7 @@ static void waIcuPeriodCallback(WaveReader *reader) {
uint64_t nowUs = getTimeNowUs();
reader->eventCounter++;
reader->lastActivityTimeUs = nowUs;
addWaveChartEvent(reader->name, "down", "");
addWaveChartEvent(reader->name, WC_DOWN, "");
uint64_t width = nowUs - reader->widthEventTimeUs;
reader->last_wave_high_widthUs = width;

View File

@ -30,7 +30,7 @@
#if EFI_USE_CCM && defined __GNUC__
#define CCM_OPTIONAL __attribute__((section(".ccm")));
#else
#define CCM_OPTIONAL
#define CCM_OPTIONAL @ ".ccm"
#endif
// this stuff is about ChibiOS 2.6 > Migration

View File

@ -261,8 +261,7 @@ GPIO_TypeDef* getAdcChannelPort(int hwChannel) {
case ADC_CHANNEL_IN15:
return GPIOC;
default:
firmwareError("Unknown hw channel")
;
firmwareError("Unknown hw channel");
return NULL;
}
}
@ -303,8 +302,7 @@ int getAdcChannelPin(int hwChannel) {
case ADC_CHANNEL_IN15:
return 5;
default:
firmwareError("Unknown hw channel")
;
firmwareError("Unknown hw channel");
return -1;
}
}
@ -411,7 +409,7 @@ static void adc_callback_fast(ADCDriver *adcp, adcsample_t *buffer, size_t n) {
}
}
void initAdcInputs() {
void initAdcInputs(bool isBoardTestMode) {
initLoggingExt(&logger, "ADC", LOGGING_BUFFER, sizeof(LOGGING_BUFFER));
printMsg(&logger, "initAdcInputs()");
@ -430,7 +428,7 @@ void initAdcInputs() {
for (int adc = 0; adc < HW_MAX_ADC_INDEX; adc++) {
adc_channel_mode_e mode = boardConfiguration->adcHwChannelEnabled[adc];
if (mode == ADC_SLOW) {
if (mode == ADC_SLOW || (isBoardTestMode && mode == ADC_FAST)) {
slowAdc.addChannel(ADC_CHANNEL_IN0 + adc);
} else if (mode == ADC_FAST) {
fastAdc.addChannel(ADC_CHANNEL_IN0 + adc);
@ -438,7 +436,14 @@ void initAdcInputs() {
}
slowAdc.init();
fastAdc.init();
pwmStart(EFI_INTERNAL_SLOW_ADC_PWM, &pwmcfg_slow);
if (!isBoardTestMode) {
fastAdc.init();
/*
* Initializes the PWM driver.
*/
pwmStart(EFI_INTERNAL_FAST_ADC_PWM, &pwmcfg_fast);
}
// ADC_CHANNEL_IN0 // PA0
// ADC_CHANNEL_IN1 // PA1
@ -459,11 +464,6 @@ void initAdcInputs() {
//if(slowAdcChannelCount > ADC_MAX_SLOW_CHANNELS_COUNT) // todo: do we need this logic? do we need this check
/*
* Initializes the PWM driver.
*/
pwmStart(EFI_INTERNAL_SLOW_ADC_PWM, &pwmcfg_slow);
pwmStart(EFI_INTERNAL_FAST_ADC_PWM, &pwmcfg_fast);
addConsoleActionI("adc", printAdcValue);
addConsoleAction("fadc", printFullAdcReport);
#else

View File

@ -19,7 +19,7 @@ extern "C"
GPIO_TypeDef* getAdcChannelPort(int hwChannel);
int getAdcChannelPin(int hwChannel);
void initAdcInputs(void);
void initAdcInputs(bool isBoardTestMode);
int getAdcHardwareIndexByInternalIndex(int index);
int getAdcValueByIndex(int internalIndex);
void pokeAdcInputs(void);

View File

@ -28,7 +28,7 @@
#include "AdcConfiguration.h"
static volatile int stepCoutner = 0;
static volatile brain_pin_e currentPin;
static volatile brain_pin_e currentPin = GPIO_NONE;
static volatile int currentIndex = 0;
extern AdcConfiguration slowAdc;
@ -93,11 +93,25 @@ static msg_t ivThread(int param) {
#endif
}
void initBoardTest(void) {
// todo: add a command to go into board test mode after reboot
if (1 == 1)
return;
static bool is_board_test_mode = false;
bool isBoardTestMode(void) {
return is_board_test_mode;
}
void printBoardTestState(void) {
print("Current index=%d\r\n", currentIndex);
print("'n' for next step and 'set X' to return to step X\r\n");
print("ADC count: %d\r\n", slowAdc.size());
if (currentPin != GPIO_NONE) {
print("Blinking %s\r\n", hwPortname(currentPin));
}
}
void initBoardTest(void) {
is_board_test_mode = true;
addConsoleAction("n", nextStep);
addConsoleActionI("set", setIndex);
@ -142,8 +156,7 @@ void initBoardTest(void) {
GPIO_TypeDef *hwPort = getHwPort(currentPin);
uint32_t hwPin = getHwPin(currentPin);
print("currentIndex=%d\r\n", currentIndex);
print("Let's blink %s%d\r\n", portname(hwPort), hwPin);
printBoardTestState();
mySetPadMode("test", hwPort, hwPin, PAL_STM32_MODE_OUTPUT);
currentIndex++;

View File

@ -28,6 +28,8 @@ extern "C"
#endif /* __cplusplus */
void initBoardTest(void);
bool isBoardTestMode(void);
void printBoardTestState(void);
#ifdef __cplusplus
}

View File

@ -25,6 +25,7 @@ static THD_WORKING_AREA(canTreadStack, UTILITY_THREAD_STACK_SIZE);
extern engine_configuration_s *engineConfiguration;
extern engine_configuration2_s *engineConfiguration2;
extern board_configuration_s *board_configuration;
/*
* 500KBaud
@ -175,6 +176,10 @@ static void canInfo(void) {
scheduleMsg(&logger, "CAN rx count %d", canReadCounter);
}
static CANDriver *getCanDevice() {
if(board)
}
void initCan(void) {
initLogging(&logger, "CAN driver");

View File

@ -50,7 +50,7 @@ flashsector_t flashSectorAt(flashaddr_t address) {
* @return CH_SUCCESS Unlock was successful.
* @return CH_FAILED Unlock failed.
*/
static bool_t flashUnlock(void) {
static bool flashUnlock(void) {
/* Check if unlock is really needed */
if (!(FLASH->CR & FLASH_CR_LOCK))
return CH_SUCCESS;
@ -141,13 +141,13 @@ bool flashIsErased(flashaddr_t address, size_t size) {
* then, fallback to byte per byte comparison. */
while (size >= sizeof(flashdata_t)) {
if (*(volatile flashdata_t*) address != (flashdata_t) (-1)) // flashdata_t being unsigned, -1 is 0xFF..FF
return FALSE;
return false;
address += sizeof(flashdata_t);
size -= sizeof(flashdata_t);
}
while (size > 0) {
if (*(char*) address != 0xff)
return FALSE;
return false;
++address;
--size;
}

View File

@ -1,5 +1,5 @@
/**
* @file hardware.c
* @file hardware.cpp
* @brief Hardware package entry point
*
* @date May 27, 2013
@ -12,6 +12,7 @@
#include "io_pins.h"
#include "rtc_helper.h"
#include "rfiutil.h"
#include "console_io.h"
#include "adc_inputs.h"
@ -27,6 +28,7 @@
#include "neo6m.h"
#include "lcd_HD44780.h"
#include "settings.h"
#include "algo.h"
#if EFI_INTERNAL_FLASH
#include "flash_main.h"
@ -55,10 +57,10 @@ void initSpiModules(void) {
#if STM32_SPI_USE_SPI2
// scheduleMsg(&logging, "Turning on SPI2 pins");
initSpiModule(&SPID2,
EFI_SPI2_SCK_PORT, EFI_SPI2_SCK_PIN,
EFI_SPI2_MISO_PORT, EFI_SPI2_MISO_PIN,
EFI_SPI2_MOSI_PORT, EFI_SPI2_MOSI_PIN,
EFI_SPI2_AF);
EFI_SPI2_SCK_PORT, EFI_SPI2_SCK_PIN,
EFI_SPI2_MISO_PORT, EFI_SPI2_MISO_PIN,
EFI_SPI2_MOSI_PORT, EFI_SPI2_MOSI_PIN,
EFI_SPI2_AF);
#endif
#if STM32_SPI_USE_SPI3
// scheduleMsg(&logging, "Turning on SPI3 pins");
@ -78,9 +80,9 @@ void initI2Cmodule(void) {
i2cStart(&I2CD1, &i2cfg);
mySetPadMode("I2C clock", EFI_I2C_SCL_PORT, EFI_I2C_SCL_PIN,
PAL_MODE_ALTERNATE(EFI_I2C_AF) | PAL_STM32_OTYPE_OPENDRAIN);
PAL_MODE_ALTERNATE(EFI_I2C_AF) | PAL_STM32_OTYPE_OPENDRAIN);
mySetPadMode("I2C data", EFI_I2C_SDA_PORT, EFI_I2C_SDA_PIN,
PAL_MODE_ALTERNATE(EFI_I2C_AF) | PAL_STM32_OTYPE_OPENDRAIN);
PAL_MODE_ALTERNATE(EFI_I2C_AF) | PAL_STM32_OTYPE_OPENDRAIN);
}
//static char txbuf[1];
@ -105,7 +107,6 @@ void initHardware(Logging *logger) {
initHistogramsModule();
#endif /* EFI_HISTOGRAMS */
/**
* We need the LED_ERROR pin even before we read configuration
*/
@ -114,12 +115,25 @@ void initHardware(Logging *logger) {
if (hasFirmwareError())
return;
initDataStructures(engineConfiguration);
#if EFI_INTERNAL_FLASH
palSetPadMode(CONFIG_RESET_SWITCH_PORT, CONFIG_RESET_SWITCH_PIN, PAL_MODE_INPUT_PULLUP);
initFlash();
/**
* this call reads configuration from flash memory or sets default configuration
* if flash state does not look right.
*/
initFlash();
if (SHOULD_INGORE_FLASH()) {
engineConfiguration->engineType = FORD_ASPIRE_1996;
resetConfigurationExt(logger, engineConfiguration->engineType, engineConfiguration, engineConfiguration2,
boardConfiguration);
writeToFlash();
} else {
readFromFlash();
}
#else
engineConfiguration->engineType = FORD_ASPIRE_1996;
resetConfigurationExt(logger, engineConfiguration->engineType, engineConfiguration, engineConfiguration2, boardConfiguration);
@ -128,10 +142,20 @@ void initHardware(Logging *logger) {
if (hasFirmwareError())
return;
mySetPadMode("board test", getHwPort(boardConfiguration->boardTestModeJumperPin),
getHwPin(boardConfiguration->boardTestModeJumperPin), PAL_MODE_INPUT_PULLUP);
bool isBoardTestMode = GET_BOARD_TEST_MODE_VALUE();
initAdcInputs(isBoardTestMode);
if (isBoardTestMode) {
initBoardTest();
efiAssertVoid(FALSE, "board test done");
}
initRtc();
initOutputPins();
initAdcInputs();
#if EFI_HIP_9011
initHip9011();
@ -144,7 +168,6 @@ void initHardware(Logging *logger) {
// init_adc_mcp3208(&adcState, &SPID2);
// requestAdcValue(&adcState, 0);
// todo: figure out better startup logic
initTriggerCentral();
@ -195,6 +218,5 @@ void initHardware(Logging *logger) {
// }
// }
initBoardTest();
printMsg(logger, "initHardware() OK!");
}

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