manual sync

This commit is contained in:
Andrey B 2014-07-24 17:30:16 -04:00
parent 88a5e44abf
commit fa6f88dc03
89 changed files with 1362 additions and 1055 deletions

View File

@ -119,7 +119,6 @@ CSRC = $(PORTSRC) \
$(UTILSRC) \
$(ENGINES_SRC) \
$(CONSOLESRC) \
$(TUNERSTUDIOSRC) \
$(CONSOLEUTILSRC) \
$(HALSRC) \
$(EMULATIONSRC) \
@ -145,6 +144,7 @@ CPPSRC = $(CHCPPSRC) \
$(SYSTEMSRC_CPP) \
$(ENGINES_SRC_CPP) \
$(HW_LAYER_SRC_CPP) \
$(TUNERSTUDIO_SRC_CPP) \
$(CONSOLE_SRC_CPP) \
$(CONTROLLERS_SENSORS_SRC_CPP) \
$(CONTROLLERS_SRC_CPP) \

View File

@ -49,7 +49,7 @@
#define STM32_PWM_USE_TIM8 TRUE // slow adc
#define STM32_PWM_USE_TIM9 FALSE
#define STM32_SPI_USE_SPI1 FALSE
#define STM32_SPI_USE_SPI1 TRUE
#define STM32_SPI_USE_SPI2 FALSE // external ADC
#define STM32_SPI_USE_SPI3 TRUE // potentiometer
@ -80,6 +80,16 @@
//#define SPI_CS4_PIN 10
//#define SPI_SD_MODULE_PORT GPIOD
//#define SPI_SD_MODULE_PIN 11
#define EFI_SPI1_SCK_PORT GPIOB
#define EFI_SPI1_SCK_PIN 3
#define EFI_SPI1_MISO_PORT GPIOB
#define EFI_SPI1_MISO_PIN 4
#define EFI_SPI1_MOSI_PORT GPIOB
#define EFI_SPI1_MOSI_PIN 5
#define EFI_SPI1_AF 5
#define EFI_SPI2_SCK_PORT GPIOB
#define EFI_SPI2_SCK_PIN 13
#define EFI_SPI2_MISO_PORT GPIOB
@ -88,17 +98,14 @@
#define EFI_SPI2_MOSI_PIN 15
#define EFI_SPI2_AF 5
/**
* This section is for right-side center SPI
*/
#define SPI_CS1_PORT GPIOD
#define SPI_CS1_PIN 7
// this is pointing into the sky for now - conflict with I2C
#define SPI_CS2_PORT GPIOH
// this is pointing into the sky for now - conflict with I2C
#define SPI_CS2_PIN 0
#define SPI_CS3_PORT GPIOD
#define SPI_CS3_PIN 5
#define SPI_CS4_PORT GPIOD
#define SPI_CS4_PIN 3
#define SPI_SD_MODULE_PORT GPIOD

View File

@ -62,8 +62,8 @@
* MCP42010 digital potentiometer support. This could be useful if you are stimulating some
* stock ECU
*/
#define EFI_POTENTIOMETER FALSE
//#define EFI_POTENTIOMETER TRUE
//#define EFI_POTENTIOMETER FALSE
#define EFI_POTENTIOMETER TRUE
#define EFI_INTERNAL_ADC TRUE

View File

@ -25,8 +25,9 @@ void setGy6139qmbDefaultEngineConfiguration(engine_configuration_s *engineConfig
/**
* We treat the trigger as 1/0 toothed wheel
*/
engineConfiguration->triggerConfig.totalToothCount = 1;
engineConfiguration->triggerConfig.skippedToothCount = 0;
engineConfiguration->triggerConfig.isSynchronizationNeeded = false;
engineConfiguration->needSecondTriggerInput = false;
engineConfiguration->triggerConfig.triggerType = TT_TOOTHED_WHEEL;
engineConfiguration->triggerConfig.customTotalToothCount = 1;
engineConfiguration->triggerConfig.customSkippedToothCount = 0;
engineConfiguration->triggerConfig.customIsSynchronizationNeeded = false;
//todo engineConfiguration2->triggerShape.needSecondTriggerInput = false;
}

View File

@ -15,12 +15,7 @@
void setCitroenBerlingoTU3JPConfiguration(engine_configuration_s *engineConfiguration, board_configuration_s *boardConfiguration) {
engineConfiguration->engineType = CITROEN_TU3JP;
//engineConfiguration->triggerConfig.triggerType = todo 60_2
setToothedWheelConfiguration(engineConfiguration, 60, 2);
setTriggerSynchronizationGap(&engineConfiguration->triggerConfig, 2.5);
engineConfiguration->triggerConfig.triggerType = TT_TOOTHED_WHEEL_60_2;
// set_cranking_injection_mode 0
engineConfiguration->crankingInjectionMode = IM_SIMULTANEOUS;

View File

@ -42,11 +42,6 @@ void setDodgeNeonEngineConfiguration(engine_configuration_s *engineConfiguration
// set_whole_fuel_map 3
setWholeFuelMap(engineConfiguration, 3);
setTriggerSynchronizationGap(&engineConfiguration->triggerConfig, 0.72);
engineConfiguration->triggerConfig.useRiseEdge = false;
engineConfiguration->needSecondTriggerInput = true;
// set_cranking_injection_mode 0
engineConfiguration->crankingInjectionMode = IM_SIMULTANEOUS;
// set_injection_mode 1

View File

@ -40,14 +40,14 @@ void setFordInline6(engine_configuration_s *engineConfiguration, board_configura
/**
* We treat the trigger as 6/0 toothed wheel
*/
setToothedWheelConfiguration(engineConfiguration, 6, 0);
engineConfiguration->triggerConfig.useRiseEdge = TRUE;
engineConfiguration->needSecondTriggerInput = false;
engineConfiguration->triggerConfig.triggerType = TT_TOOTHED_WHEEL;
engineConfiguration->triggerConfig.customTotalToothCount = 6;
engineConfiguration->triggerConfig.customSkippedToothCount = 0;
engineConfiguration->triggerConfig.customIsSynchronizationNeeded = false;
engineConfiguration->globalTriggerAngleOffset = 0;
engineConfiguration->ignitionOffset = 13;
setThermistorConfiguration(&engineConfiguration->cltThermistorConf, -10, 160310, 60, 7700, 120.00, 1180);
engineConfiguration->cltThermistorConf.bias_resistor = 2700;

View File

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

View File

@ -12,7 +12,6 @@
void setFordEscortGt(engine_configuration_s *engineConfiguration, board_configuration_s *boardConfiguration) {
engineConfiguration->triggerConfig.triggerType = TT_FORD_ESCORT_GT;
engineConfiguration->needSecondTriggerInput = FALSE;
engineConfiguration->cylindersCount = 4;
engineConfiguration->firingOrder = FO_1_THEN_3_THEN_4_THEN2;

View File

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

View File

@ -1,6 +1,12 @@
/**
* @file honda_accord.cpp
*
* 1995 Honda Accord EX
* http://rusefi.com/wiki/index.php?title=Vehicle:Honda_Accord_1995
* http://rusefi.com/forum/viewtopic.php?f=3&t=621
*
* engine_type 6
*
* @date Jan 12, 2014
* @author Andrey Belomutskiy, (c) 2012-2014
*/
@ -9,8 +15,45 @@
#include "engine_configuration.h"
#include "trigger_decoder.h"
void setHondaAccordConfiguration(engine_configuration_s *engineConfiguration) {
engineConfiguration->triggerConfig.totalToothCount = 24;
engineConfiguration->triggerConfig.skippedToothCount = 2;
void setHondaAccordConfiguration(engine_configuration_s *engineConfiguration, board_configuration_s *boardConfiguration) {
engineConfiguration->engineType = HONDA_ACCORD;
engineConfiguration->map.sensor.sensorType = MT_HONDA3BAR;
engineConfiguration->cylindersCount = 4;
engineConfiguration->displacement = 2.156;
// Keihin 06164-P0A-A00
engineConfiguration->injectorFlow = 248;
engineConfiguration->algorithm = LM_SPEED_DENSITY;
engineConfiguration->crankingSettings.coolantTempMaxC = 65; // 8ms at 65C
engineConfiguration->crankingSettings.fuelAtMaxTempMs = 8;
engineConfiguration->crankingSettings.coolantTempMinC = 0; // 20ms at 0C
engineConfiguration->crankingSettings.fuelAtMinTempMs = 15;
memset(boardConfiguration->adcHwChannelEnabled, 0, sizeof(boardConfiguration->adcHwChannelEnabled));
boardConfiguration->adcHwChannelEnabled[0] = ADC_FAST; // ADC0 - PA0 - MAP
boardConfiguration->adcHwChannelEnabled[1] = ADC_SLOW;
boardConfiguration->adcHwChannelEnabled[2] = ADC_SLOW;
boardConfiguration->adcHwChannelEnabled[3] = ADC_SLOW;
boardConfiguration->adcHwChannelEnabled[4] = ADC_SLOW;
boardConfiguration->adcHwChannelEnabled[6] = ADC_SLOW;
boardConfiguration->adcHwChannelEnabled[7] = ADC_SLOW;
boardConfiguration->adcHwChannelEnabled[11] = ADC_SLOW;
boardConfiguration->adcHwChannelEnabled[12] = ADC_SLOW;
boardConfiguration->adcHwChannelEnabled[13] = ADC_SLOW;
engineConfiguration->map.sensor.sensorType = MT_MPX4250;
engineConfiguration->map.sensor.hwChannel = 0;
}

View File

@ -10,6 +10,6 @@
#include "engine_configuration.h"
void setHondaAccordConfiguration(engine_configuration_s *engineConfiguration);
void setHondaAccordConfiguration(engine_configuration_s *engineConfiguration, board_configuration_s *boardConfiguration);
#endif /* HONDA_ACCORD_H_ */

View File

@ -16,5 +16,5 @@ void setMazda323EngineConfiguration(engine_configuration_s *engineConfiguration)
/**
* We treat the trigger as 4/0 toothed wheel
*/
setToothedWheelConfiguration(engineConfiguration, 4, 0);
// setToothedWheelConfiguration(engineConfiguration, 4, 0);
}

View File

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

View File

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

View File

@ -18,7 +18,7 @@ void setRoverv8(engine_configuration_s *engineConfiguration,
board_configuration_s *boardConfiguration) {
setOperationMode(engineConfiguration, FOUR_STROKE_CRANK_SENSOR);
setToothedWheelConfiguration(engineConfiguration, 36, 1);
engineConfiguration->triggerConfig.triggerType = TT_TOOTHED_WHEEL_36_1;
engineConfiguration->displacement = 3.528;
engineConfiguration->cylindersCount = 8;

View File

@ -52,7 +52,7 @@ static void myerror(void) {
static void sayHello(void) {
printMsg(&logger, "*** rusEFI (c) Andrey Belomutskiy, 2012-2014. All rights reserved.");
printMsg(&logger, "rusEFI v%d@%d", getRusEfiVersion(), SVN_VERSION);
printMsg(&logger, "rusEFI v%d@%s", getRusEfiVersion(), VCS_VERSION);
printMsg(&logger, "*** Chibios Kernel: %s", CH_KERNEL_VERSION);
printMsg(&logger, "*** Compiled: " __DATE__ " - " __TIME__ "");
printMsg(&logger, "COMPILER=%s", __VERSION__);

View File

@ -129,7 +129,7 @@ void printSensors(void) {
reportSensorI("rpm", getRpm());
reportSensorF("maf", getMaf(), 2);
if (engineConfiguration2->hasMapSensor) {
if (engineConfiguration->hasMapSensor) {
reportSensorF(getCaption(LP_MAP), getMap(), 2);
reportSensorF("map_r", getRawMap(), 2);
}
@ -141,7 +141,7 @@ void printSensors(void) {
reportSensorF(getCaption(LP_THROTTLE), getTPS(), 2);
if (engineConfiguration2->hasCltSensor) {
if (engineConfiguration->hasCltSensor) {
reportSensorF(getCaption(LP_ECT), getCoolantTemperature(), 2);
}
@ -167,11 +167,12 @@ void printState(int currentCkpEventCounter) {
// debugFloat(&logger, "table_spark", getAdvance(rpm, getMaf()), 2);
float engineLoad = getEngineLoad();
debugFloat(&logger, "fuel_base", getBaseFuel(rpm, engineLoad), 2);
float baseFuel = getBaseFuel(&engine, rpm);
debugFloat(&logger, "fuel_base", baseFuel, 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", getRunningFuel(rpm, engineLoad), 2);
debugFloat(&logger, "fuel", getRunningFuel(baseFuel, &engine, rpm), 2);
debugFloat(&logger, "timing", getAdvance(rpm, engineLoad), 2);
@ -187,8 +188,6 @@ void printState(int currentCkpEventCounter) {
static char LOGGING_BUFFER[500];
#if EFI_PROD_CODE
volatile int needToReportStatus = FALSE;
static int prevCkpEventCounter = -1;
@ -198,38 +197,6 @@ static void printStatus(void) {
needToReportStatus = TRUE;
}
//float getTCharge1(float tps) {
// float cltK = tempCtoKelvin(getCoolantTemperature());
// float iatK = tempCtoKelvin(getIntakeAirTemperature());
// return getTCharge(getCurrentRpm(), tps, cltK, iatK);
//}
//#if EFI_CUSTOM_PANIC_METHOD
//extern char *dbg_panic_file;
//extern int dbg_panic_line;
//#endif
//static void checkIfShouldHalt(void) {
//#if CH_DBG_ENABLED
// if (hasFatalError()) {
// /**
// * low-level function is used here to reduce stack usage
// */
// palWritePad(LED_ERROR_PORT, LED_ERROR_PIN, 1);
//#if EFI_CUSTOM_PANIC_METHOD
// print("my FATAL [%s] at %s:%d\r\n", dbg_panic_msg, dbg_panic_file, dbg_panic_line);
//#else
// print("my FATAL [%s] at %s:%d\r\n", dbg_panic_msg);
//#endif
// chThdSleepSeconds(1);
// // todo: figure out how we halt exactly
// while (TRUE) {
// }
// chSysHalt();
// }
//#endif
//}
/**
* Time when the firmware version was reported last time, in seconds
* TODO: implement a request/response instead of just constantly sending this out
@ -240,7 +207,7 @@ static void printVersion(systime_t nowSeconds) {
if (overflowDiff(nowSeconds, timeOfPreviousPrintVersion) < 4)
return;
timeOfPreviousPrintVersion = nowSeconds;
appendPrintf(&logger, "rusEfiVersion%s%d@%d %s%s", DELIMETER, getRusEfiVersion(), SVN_VERSION,
appendPrintf(&logger, "rusEfiVersion%s%d@%s %s%s", DELIMETER, getRusEfiVersion(), VCS_VERSION,
getConfigurationName(engineConfiguration),
DELIMETER);
}
@ -259,14 +226,19 @@ void updateDevConsoleState(void) {
// checkIfShouldHalt();
printPending();
#if EFI_PROD_CODE
// todo: unify with simulator!
if (hasFirmwareError()) {
printMsg(&logger, "firmware error: %s", errorMessageBuffer);
warningEnabled = FALSE;
chThdSleepMilliseconds(200);
return;
}
#endif
#if EFI_PROD_CODE
pokeAdcInputs();
#endif
if (!fullLog)
return;
@ -291,6 +263,8 @@ void updateDevConsoleState(void) {
finishStatusLine();
}
#if EFI_PROD_CODE
/*
* command example:
* sfm 3500 400
@ -298,7 +272,7 @@ void updateDevConsoleState(void) {
*/
static void showFuelMap2(float rpm, float engineLoad) {
float baseFuel = getBaseFuel(rpm, engineLoad);
float baseFuel = getBaseTableFuel(rpm, engineLoad);
float iatCorrection = getIatCorrection(getIntakeAirTemperature());
float cltCorrection = getCltCorrection(getCoolantTemperature());
@ -309,7 +283,7 @@ static void showFuelMap2(float rpm, float engineLoad) {
scheduleMsg(&logger2, "iatCorrection=%f cltCorrection=%f injectorLag=%f", iatCorrection, cltCorrection,
injectorLag);
float value = getRunningFuel(rpm, engineLoad);
float value = getRunningFuel(baseFuel, &engine, rpm);
scheduleMsg(&logger2, "injection pulse width: %f", value);
}

View File

@ -19,7 +19,6 @@ void initStatusLoop(void);
void updateDevConsoleState(void);
int getFullLog(void);
void printSensors(void);
void finishStatusLine(void);
void setFullLog(int value);
void startStatusThreads(void);
void sayOsHello(void);

View File

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

View File

@ -1,154 +1,154 @@
/**
* @file tunerstudio_algo.c
* @brief Tuner Studio plain protocol implementation
*
* This implementation would not happen without the documentation
* provided by Jon Zeeff (jon@zeeff.com)
*
* Tuner Studio has a really simple protocol, a minimal implementation
* capable of displaying current engine state on the gauges would
* require only two commands: queryCommand and ochGetCommand
*
* queryCommand:
* Communication initialization command. TunerStudio sends a single byte H
* ECU response:
* One of the known ECU id strings. We are using "MShift v0.01" id string.
*
* ochGetCommand:
* Request for output channels state.TunerStudio sends a single byte O
* ECU response:
* A snapshot of output channels as described in [OutputChannels] section of the .ini file
* The length of this block is 'ochBlockSize' property of the .ini file
*
* These two commands are enough to get working gauges. In order to start configuring the ECU using
* tuner studio, three more commands should be implemented:
*
* todo: merge this file with tunerstudio.c?
*
*
* @date Oct 22, 2013
* @author Andrey Belomutskiy, (c) 2012-2014
*
* This file is part of rusEfi - see http://rusefi.com
*
* rusEfi is free software; you can redistribute it and/or modify it under the terms of
* the GNU General Public License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* rusEfi is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include <string.h>
#include "tunerstudio_algo.h"
#include "tunerstudio_configuration.h"
#include "engine_configuration.h"
#include "tunerstudio.h"
#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE (!FALSE)
#endif
TunerStudioState tsState;
TunerStudioOutputChannels tsOutputChannels;
/**
* this is a local copy of the configuration. Any changes to this copy
* have no effect until this copy is explicitly propagated to the main working copy
*/
persistent_config_s configWorkingCopy;
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(TS_CRC);
} else if (command == TS_OUTPUT_COMMAND) {
handleOutputChannelsCommand(TS_CRC);
} else if (command == TS_PAGE_COMMAND) {
uint16_t page = *(uint16_t *) data;
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(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(TS_CRC, page, offset, value);
} else if (command == TS_BURN_COMMAND) {
uint16_t page = *(uint16_t *) data;
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(TS_CRC, page, offset, count);
} else if (command == 't' || command == 'T') {
handleTestCommand();
} else if (command == 'F') {
tunerStudioDebug("ignoring F");
/**
* http://www.msextra.com/forums/viewtopic.php?f=122&t=48327
* Response from TS support: This is an optional command *
* "The F command is used to find what ini. file needs to be loaded in TunerStudio to match the controller.
* If you are able to just make your firmware ignore the command that would work.
* Currently on some firmware versions the F command is not used and is just ignored by the firmware as a unknown command."
*/
} else {
tunerStudioError("ERROR: ignoring unexpected command");
return FALSE;
}
return TRUE;
}
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)");
tsSendResponse(mode, (const uint8_t *) TS_SIGNATURE, strlen(TS_SIGNATURE) + 1);
}
/**
* @brief 'Output' command sends out a snapshot of current values
*/
void handleOutputChannelsCommand(ts_response_format_e mode) {
tsState.outputChannelsCommandCounter++;
// this method is invoked too often to print any debug information
tsSendResponse(mode, (const uint8_t *) &tsOutputChannels, sizeof(TunerStudioOutputChannels));
}
void handleTestCommand(void) {
/**
* this is NOT a standard TunerStudio command, this is my own
* extension of the protocol to simplify troubleshooting
*/
tunerStudioDebug("got T (Test)");
tunerStudioWriteData((const uint8_t *) "alive\r\n", 7);
}
/**
* @file tunerstudio_algo.cpp
* @brief Tuner Studio plain protocol implementation
*
* This implementation would not happen without the documentation
* provided by Jon Zeeff (jon@zeeff.com)
*
* Tuner Studio has a really simple protocol, a minimal implementation
* capable of displaying current engine state on the gauges would
* require only two commands: queryCommand and ochGetCommand
*
* queryCommand:
* Communication initialization command. TunerStudio sends a single byte H
* ECU response:
* One of the known ECU id strings. We are using "MShift v0.01" id string.
*
* ochGetCommand:
* Request for output channels state.TunerStudio sends a single byte O
* ECU response:
* A snapshot of output channels as described in [OutputChannels] section of the .ini file
* The length of this block is 'ochBlockSize' property of the .ini file
*
* These two commands are enough to get working gauges. In order to start configuring the ECU using
* tuner studio, three more commands should be implemented:
*
* todo: merge this file with tunerstudio.c?
*
*
* @date Oct 22, 2013
* @author Andrey Belomutskiy, (c) 2012-2014
*
* This file is part of rusEfi - see http://rusefi.com
*
* rusEfi is free software; you can redistribute it and/or modify it under the terms of
* the GNU General Public License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* rusEfi is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include <string.h>
#include "tunerstudio_algo.h"
#include "tunerstudio_configuration.h"
#include "engine_configuration.h"
#include "tunerstudio.h"
#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE (!FALSE)
#endif
TunerStudioState tsState;
TunerStudioOutputChannels tsOutputChannels;
/**
* this is a local copy of the configuration. Any changes to this copy
* have no effect until this copy is explicitly propagated to the main working copy
*/
persistent_config_s configWorkingCopy;
void tunerStudioError(const char *msg) {
tunerStudioDebug(msg);
tsState.errorCounter++;
}
int tunerStudioHandleCrcCommand(uint8_t *data, int incomingPacketSize) {
char command = data[0];
data++;
if (command == TS_HELLO_COMMAND) {
tunerStudioDebug("got CRC Query");
handleQueryCommand(TS_CRC);
} else if (command == TS_OUTPUT_COMMAND) {
handleOutputChannelsCommand(TS_CRC);
} else if (command == TS_PAGE_COMMAND) {
uint16_t page = *(uint16_t *) data;
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(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(TS_CRC, page, offset, value);
} else if (command == TS_BURN_COMMAND) {
uint16_t page = *(uint16_t *) data;
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(TS_CRC, page, offset, count);
} else if (command == 't' || command == 'T') {
handleTestCommand();
} else if (command == 'F') {
tunerStudioDebug("ignoring F");
/**
* http://www.msextra.com/forums/viewtopic.php?f=122&t=48327
* Response from TS support: This is an optional command *
* "The F command is used to find what ini. file needs to be loaded in TunerStudio to match the controller.
* If you are able to just make your firmware ignore the command that would work.
* Currently on some firmware versions the F command is not used and is just ignored by the firmware as a unknown command."
*/
} else {
tunerStudioError("ERROR: ignoring unexpected command");
return FALSE;
}
return TRUE;
}
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)");
tsSendResponse(mode, (const uint8_t *) TS_SIGNATURE, strlen(TS_SIGNATURE) + 1);
}
/**
* @brief 'Output' command sends out a snapshot of current values
*/
void handleOutputChannelsCommand(ts_response_format_e mode) {
tsState.outputChannelsCommandCounter++;
// this method is invoked too often to print any debug information
tsSendResponse(mode, (const uint8_t *) &tsOutputChannels, sizeof(TunerStudioOutputChannels));
}
void handleTestCommand(void) {
/**
* this is NOT a standard TunerStudio command, this is my own
* extension of the protocol to simplify troubleshooting
*/
tunerStudioDebug("got T (Test)");
tunerStudioWriteData((const uint8_t *) "alive\r\n", 7);
}

View File

@ -42,7 +42,7 @@ typedef struct {
short currentPageId;
} TunerStudioState;
int tunerStudioHandleCrcCommand(char *data, int incomingPacketSize);
int tunerStudioHandleCrcCommand(uint8_t *data, int incomingPacketSize);
void handleTestCommand(void);
void handleQueryCommand(ts_response_format_e mode);

View File

@ -14,6 +14,7 @@
#include "engine_math.h"
#include "signal_executor.h"
extern Engine engine;
extern engine_configuration_s *engineConfiguration;
static AccelEnrichmemnt instance;

View File

@ -42,13 +42,11 @@ extern "C"
class engine_configuration2_s {
public:
engine_configuration2_s();
int hasMapSensor;
int hasCltSensor;
Thermistor iat;
Thermistor clt;
int crankAngleRange;
// int crankAngleRange;
trigger_shape_s triggerShape;
@ -83,7 +81,7 @@ void resetConfigurationExt(Logging * logger, engine_type_e engineType,
engine_configuration2_s *engineConfiguration2,
board_configuration_s *boardConfiguration);
void applyNonPersistentConfiguration(Logging * logger, engine_configuration_s *engineConfiguration,
engine_configuration2_s *engineConfiguration2, engine_type_e engineType);
engine_configuration2_s *engineConfiguration2);
void setDefaultNonPersistentConfiguration(engine_configuration2_s *engineConfiguration2);

View File

@ -80,6 +80,7 @@ void initBpsxD1Sensor(afr_sensor_s *sensor) {
}
void setWholeVEMap(engine_configuration_s *engineConfiguration, float value) {
// todo: table helper?
// for (int l = 0; l < VE_LOAD_COUNT; l++) {
// for (int r = 0; r < VE_RPM_COUNT; r++) {
// engineConfiguration->veTable[l][r] = value;
@ -88,6 +89,7 @@ void setWholeVEMap(engine_configuration_s *engineConfiguration, float value) {
}
void setWholeFuelMap(engine_configuration_s *engineConfiguration, float value) {
// todo: table helper?
for (int l = 0; l < FUEL_LOAD_COUNT; l++) {
for (int r = 0; r < FUEL_RPM_COUNT; r++) {
engineConfiguration->fuelTable[l][r] = value;
@ -95,20 +97,6 @@ void setWholeFuelMap(engine_configuration_s *engineConfiguration, float value) {
}
}
void setToothedWheelConfiguration(engine_configuration_s *engineConfiguration, int total, int skipped) {
engineConfiguration->triggerConfig.triggerType = TT_TOOTHED_WHEEL;
engineConfiguration->triggerConfig.isSynchronizationNeeded = (skipped != 0);
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;
}
/**
* @brief Global default engine configuration
* This method sets the default global engine configuration. These values are later overridden by engine-specific defaults
@ -158,7 +146,9 @@ void setDefaultConfiguration(engine_configuration_s *engineConfiguration, board_
setTimingRpmBin(engineConfiguration, 800, 7000);
setTableBin2(engineConfiguration->map.samplingAngleBins, MAP_ANGLE_SIZE, 800, 7000, 1);
setTableBin2(engineConfiguration->map.samplingAngle, MAP_ANGLE_SIZE, 100, 130, 1);
setTableBin2(engineConfiguration->map.samplingWindowBins, MAP_ANGLE_SIZE, 800, 7000, 1);
setTableBin2(engineConfiguration->map.samplingWindow, MAP_ANGLE_SIZE, 50, 50, 1);
// set_whole_timing_map 3
setWholeFuelMap(engineConfiguration, 3);
@ -230,9 +220,7 @@ void setDefaultConfiguration(engine_configuration_s *engineConfiguration, board_
engineConfiguration->logFormat = LF_NATIVE;
engineConfiguration->triggerConfig.triggerType = TT_TOOTHED_WHEEL;
setTriggerSynchronizationGap(&engineConfiguration->triggerConfig, 2);
engineConfiguration->triggerConfig.useRiseEdge = TRUE;
engineConfiguration->triggerConfig.triggerType = TT_TOOTHED_WHEEL_60_2;
engineConfiguration->HD44780width = 16;
engineConfiguration->HD44780height = 2;
@ -248,8 +236,6 @@ void setDefaultConfiguration(engine_configuration_s *engineConfiguration, board_
engineConfiguration->globalFuelCorrection = 1;
engineConfiguration->needSecondTriggerInput = TRUE;
engineConfiguration->map.sensor.sensorType = MT_MPX4250;
engineConfiguration->baroSensor.sensorType = MT_CUSTOM;
@ -258,6 +244,10 @@ void setDefaultConfiguration(engine_configuration_s *engineConfiguration, board_
engineConfiguration->diffLoadEnrichmentCoef = 1;
engineConfiguration->hasMapSensor = TRUE;
engineConfiguration->hasCltSensor = TRUE;
boardConfiguration->idleValvePin = GPIOE_2;
boardConfiguration->idleValvePinMode = OM_DEFAULT;
boardConfiguration->fuelPumpPin = GPIOC_13;
@ -335,7 +325,7 @@ void setDefaultConfiguration(engine_configuration_s *engineConfiguration, board_
boardConfiguration->consoleLoopPeriod = 200;
boardConfiguration->lcdThreadPeriod = 300;
boardConfiguration->tunerStudioThreadPeriod = 300;
boardConfiguration->generalPeriodicThreadPeriod = 200;
boardConfiguration->generalPeriodicThreadPeriod = 50;
boardConfiguration->tunerStudioSerialSpeed = 38400;
@ -344,16 +334,20 @@ void setDefaultConfiguration(engine_configuration_s *engineConfiguration, board_
boardConfiguration->canDeviceMode = CD_USE_CAN2;
boardConfiguration->canTxPin = GPIOB_0;
boardConfiguration->canRxPin = GPIOB_12;
boardConfiguration->digitalPotentiometerSpiDevice = SPI_NONE;
boardConfiguration->digitalPotentiometerChipSelect[0] = GPIOD_7;
boardConfiguration->digitalPotentiometerChipSelect[1] = GPIO_NONE;
boardConfiguration->digitalPotentiometerChipSelect[2] = GPIOD_5;
boardConfiguration->digitalPotentiometerChipSelect[3] = GPIO_NONE;
}
void setDefaultNonPersistentConfiguration(engine_configuration2_s *engineConfiguration2) {
/**
* 720 is the range for four stroke
*/
engineConfiguration2->crankAngleRange = 720;
// engineConfiguration2->crankAngleRange = 720;
engineConfiguration2->hasMapSensor = TRUE;
engineConfiguration2->hasCltSensor = TRUE;
}
void resetConfigurationExt(Logging * logger, engine_type_e engineType, engine_configuration_s *engineConfiguration,
@ -388,7 +382,7 @@ void resetConfigurationExt(Logging * logger, engine_type_e engineType, engine_co
break;
#endif
case HONDA_ACCORD:
setHondaAccordConfiguration(engineConfiguration);
setHondaAccordConfiguration(engineConfiguration, boardConfiguration);
break;
#if EFI_SUPPORT_1995_FORD_INLINE_6 || defined(__DOXYGEN__)
case FORD_INLINE_6_1995:
@ -424,7 +418,7 @@ void resetConfigurationExt(Logging * logger, engine_type_e engineType, engine_co
firmwareError("Unexpected engine type: %d", engineType);
}
applyNonPersistentConfiguration(logger, engineConfiguration, engineConfiguration2, engineType);
applyNonPersistentConfiguration(logger, engineConfiguration, engineConfiguration2);
#if EFI_TUNER_STUDIO
syncTunerStudioCopy();
@ -435,17 +429,17 @@ engine_configuration2_s::engine_configuration2_s() {
}
void applyNonPersistentConfiguration(Logging * logger, engine_configuration_s *engineConfiguration,
engine_configuration2_s *engineConfiguration2, engine_type_e engineType) {
engine_configuration2_s *engineConfiguration2) {
// todo: this would require 'initThermistors() to re-establish a reference, todo: fix
// memset(engineConfiguration2, 0, sizeof(engine_configuration2_s));
#if EFI_PROD_CODE
printMsg(logger, "applyNonPersistentConfiguration()");
scheduleMsg(logger, "applyNonPersistentConfiguration()");
#endif
engineConfiguration2->isInjectionEnabledFlag = TRUE;
initializeTriggerShape(logger, engineConfiguration, engineConfiguration2);
if (engineConfiguration2->triggerShape.getSize() == 0) {
firmwareError("size is zero");
firmwareError("triggerShape size is zero");
return;
}
if (engineConfiguration2->triggerShape.shaftPositionEventCount == 0) {

View File

@ -92,15 +92,15 @@ typedef struct {
typedef struct {
trigger_type_e triggerType;
int isSynchronizationNeeded;
int customIsSynchronizationNeeded;
int totalToothCount;
int skippedToothCount;
int customTotalToothCount;
int customSkippedToothCount;
float syncRatioFrom;
float syncRatioTo;
float customSyncRatioFrom;
float customSyncRatioTo;
int useRiseEdge;
int customUseRiseEdge;
} trigger_config_s;
@ -150,7 +150,7 @@ typedef struct {
* Digital Potentiometer is used by stock ECU stimulation code
*/
spi_device_e digitalPotentiometerSpiDevice;
brain_pin_e digitalPotentiometerChipSelect[4];
brain_pin_e digitalPotentiometerChipSelect[DIGIPOT_COUNT];
adc_channel_mode_e adcHwChannelEnabled[HW_MAX_ADC_INDEX];
@ -335,7 +335,7 @@ typedef struct {
trigger_config_s triggerConfig;
int needSecondTriggerInput;
int space;
int vBattAdcChannel;
float globalFuelCorrection;
@ -370,6 +370,10 @@ typedef struct {
board_configuration_s bc;
int hasMapSensor;
int hasCltSensor;
} engine_configuration_s;
void setOperationMode(engine_configuration_s *engineConfiguration, operation_mode_e mode);
@ -396,9 +400,6 @@ 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(trigger_config_s *triggerConfig, float synchGap);
void setToothedWheelConfiguration(engine_configuration_s *engineConfiguration, int total, int skipped);
void incrementGlobalConfigurationVersion(void);
int getGlobalConfigurationVersion(void);

View File

@ -36,10 +36,12 @@
#include "allsensors.h"
#include "engine_math.h"
#include "rpm_calculator.h"
#include "speed_density.h"
#if EFI_ACCEL_ENRICHMENT
#include "accel_enrichment.h"
#endif /* EFI_ACCEL_ENRICHMENT */
extern Engine engine;
extern engine_configuration_s *engineConfiguration;
static Map3D1616 fuelMap;
@ -83,7 +85,16 @@ float getInjectorLag(float vBatt) {
return engineConfiguration->injectorLag + vBattCorrection;
}
float getBaseFuel(int rpm, float engineLoad) {
float getBaseFuel(Engine *engine, int rpm) {
if (engine->engineConfiguration->algorithm == LM_SPEED_DENSITY) {
return getSpeedDensityFuel(engine, rpm);
} else {
float engineLoad = getEngineLoadT(engine);
return getBaseTableFuel(rpm, engineLoad);
}
}
float getBaseTableFuel(int rpm, float engineLoad) {
efiAssert(!cisnan(engineLoad), "invalid el", NAN);
return fuelMap.getValue(engineLoad, engineConfiguration->fuelLoadBins, rpm,
engineConfiguration->fuelRpmBins);
@ -96,22 +107,17 @@ float getCrankingFuel(void) {
/**
* @returns Length of fuel injection, in milliseconds
*/
float getFuelMs(int rpm) {
float getFuelMs(int rpm, Engine *engine) {
if (isCranking()) {
return getCrankingFuel();
} else {
float fuel = getRunningFuel(rpm, getEngineLoad());
float baseFuel = getBaseFuel(engine, rpm);
float fuel = getRunningFuel(baseFuel, engine, rpm);
return fuel;
}
}
float getRunningFuel(int rpm, float engineLoad) {
if (cisnan(engineLoad)) {
// the warning message should be already produced by the sensor decoder
return NAN;
}
float baseFuel = getBaseFuel(rpm, engineLoad);
float getRunningFuel(float baseFuel, Engine *engine, int rpm) {
float iatCorrection = getIatCorrection(getIntakeAirTemperature());
float cltCorrection = getCltCorrection(getCoolantTemperature());
float injectorLag = getInjectorLag(getVBatt());

View File

@ -13,15 +13,18 @@ extern "C"
{
#endif /* __cplusplus */
#include "engine.h"
void prepareFuelMap(void);
float getBaseFuel(int rpm, float engineLoad);
float getBaseFuel(Engine *engine, int rpm);
float getBaseTableFuel(int rpm, float engineLoad);
float getIatCorrection(float iat);
float getInjectorLag(float vBatt);
float getCltCorrection(float clt);
float getRunningFuel(int rpm, float engineLoad);
float getRunningFuel(float baseFuel, Engine *engine, int rpm);
float getStartingFuel(float coolantTemperature);
float getFuelMs(int rpm);
float getFuelMs(int rpm, Engine *engine);
#ifdef __cplusplus
}

View File

@ -19,16 +19,19 @@
#include "engine_configuration.h"
#include "ec2.h"
#include "event_registry.h"
#include "engine.h"
class MainTriggerCallback {
public:
// MainTriggerCallback();
void init(engine_configuration_s *engineConfiguration, engine_configuration2_s *engineConfiguration2);
void init(Engine *engine, engine_configuration2_s *engineConfiguration2);
Engine *engine;
engine_configuration_s *engineConfiguration;
engine_configuration2_s *engineConfiguration2;
};
void initMainEventListener(engine_configuration_s *engineConfiguration, engine_configuration2_s *engineConfiguration2);
void initMainEventListener(Engine *engine, engine_configuration2_s *engineConfiguration2);
void onTriggerEvent(trigger_event_e ckpSignalType, int eventIndex, MainTriggerCallback *mainTriggerCallback);
#endif

View File

@ -17,6 +17,8 @@
// this is about offsets and sizes in TunerStudio
#define ENUM_SIZE_HACK 2000000000
#define DIGIPOT_COUNT 4
typedef enum {
AUDI_AAN = 1,
#if EFI_SUPPORT_DODGE_NEON
@ -80,7 +82,8 @@ typedef enum {
TT_GM_7X = 5,
TT_MINI_COOPER_R50 = 6,
TT_FORD_ESCORT_GT = 7,
TT_TT_TOOTHED_WHEEL_60_2 = 8,
TT_TOOTHED_WHEEL_60_2 = 8,
TT_TOOTHED_WHEEL_36_1 = 9,
Internal_ForceMyEnumIntSize_trigger_type = ENUM_SIZE_HACK,
} trigger_type_e;
@ -228,6 +231,8 @@ typedef enum {
SPI_NONE = 0,
SPI_DEVICE_1 = 1,
SPI_DEVICE_2 = 2,
SPI_DEVICE_3 = 3,
SPI_DEVICE_4 = 4,
Internal_ForceMyEnumIntSize_spi_device = ENUM_SIZE_HACK,
} spi_device_e;
@ -337,6 +342,7 @@ typedef enum {
MT_CUSTOM = 0,
MT_DENSO183 = 1,
MT_MPX4250 = 2,
MT_HONDA3BAR = 3,
Internal_ForceMyEnumIntSize_cranking_map_type = ENUM_SIZE_HACK,
} air_pressure_sensor_type_e;

View File

@ -115,8 +115,8 @@ void scheduleOutput(OutputSignal *signal, float delayMs, float durationMs) {
scheduling_s * sUp = &signal->signalTimerUp[index];
scheduling_s * sDown = &signal->signalTimerDown[index];
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);
scheduleTask("out up", sUp, (int)MS2US(delayMs), (schfunc_t) &turnPinHigh, (void *) signal->io_pin);
scheduleTask("out down", sDown, (int)MS2US(delayMs + durationMs), (schfunc_t) &turnPinLow, (void*) signal->io_pin);
}
const char *getPinName(io_pin_e io_pin) {

View File

@ -33,13 +33,13 @@ void Map3D<RPM_BIN_SIZE, LOAD_BIN_SIZE>::init(float table[RPM_BIN_SIZE][LOAD_BIN
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);
efiAssert(initialized == MAGIC_TRUE_VALUE, "map not 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");
efiAssertVoid(initialized == MAGIC_TRUE_VALUE, "map not initialized");
for (int l = 0; l < LOAD_BIN_SIZE; l++) {
for (int r = 0; r < RPM_BIN_SIZE; r++) {
pointers[l][r] = value;

View File

@ -156,6 +156,8 @@ static void onEvenyGeneralMilliseconds(void *arg) {
*/
halTime.get(hal_lld_get_counter_value(), true);
engine.updateSlowSensors();
updateErrorCodes();
fanRelayControl();
@ -236,6 +238,8 @@ void initEngineContoller(void) {
return;
initLogging(&logger, "Engine Controller");
engine.engineConfiguration = engineConfiguration;
initSensors();
initPwmGenerator();
@ -289,7 +293,7 @@ void initEngineContoller(void) {
/**
* This method initialized the main listener which actually runs injectors & ignition
*/
initMainEventListener(engineConfiguration, engineConfiguration2);
initMainEventListener(&engine, engineConfiguration2);
#endif /* EFI_ENGINE_CONTROL */
#if EFI_IDLE_CONTROL

View File

@ -57,13 +57,13 @@ void writeToFlash(void) {
scheduleMsg(&logger, "flash compatible with %d", persistentState.version);
crc_t result = flashStateCrc(&persistentState);
persistentState.value = result;
scheduleMsg(&logger, "Reseting flash, size=%d", PERSISTENT_SIZE);
scheduleMsg(&logger, "Reseting flash: size=%d", PERSISTENT_SIZE);
flashErase(FLASH_ADDR, PERSISTENT_SIZE);
scheduleMsg(&logger, "Flashing with CRC=%d", result);
efitimems_t nowMs = currentTimeMillis();
result = flashWrite(FLASH_ADDR, (const char *) &persistentState, PERSISTENT_SIZE);
scheduleMsg(&logger, "Flash programmed in (ms): %d", currentTimeMillis() - nowMs);
scheduleMsg(&logger, "Flashed: %d", result);
scheduleMsg(&logger, "Flashing result: %d", result);
#endif /* EFI_INTERNAL_FLASH */
}
@ -97,8 +97,7 @@ void readFromFlash(void) {
boardConfiguration);
} else {
printMsg(&logger, "Got valid configuration from flash!");
applyNonPersistentConfiguration(&logger, engineConfiguration, engineConfiguration2,
engineConfiguration->engineType);
applyNonPersistentConfiguration(&logger, engineConfiguration, engineConfiguration2);
}
// we can only change the state after the CRC check
engineConfiguration->firmwareVersion = getRusEfiVersion();

View File

@ -11,7 +11,7 @@
#include "engine_configuration.h"
#define FLASH_DATA_VERSION 3880
#define FLASH_DATA_VERSION 3975
#ifdef __cplusplus
extern "C"

View File

@ -35,7 +35,7 @@ void initIgnitionCentral(void) {
initLogging(&logger, "IgnitionCentral");
for (int i = 0; i < engineConfiguration->cylindersCount; i++) {
io_pin_e pin = (io_pin_e)((int)INJECTOR_1_OUTPUT + i);
io_pin_e pin = (io_pin_e)((int)SPARKOUT_1_OUTPUT + i);
outputPinRegisterExt2(getPinName(pin), pin, boardConfiguration->ignitionPins[i], &boardConfiguration->ignitionPinMode);
}
}

View File

@ -37,7 +37,6 @@
#include "analog_chart.h"
#endif /* EFI_ANALOG_CHART */
#define FAST_MAP_CHART_SKIP_FACTOR 16
static Logging logger;
@ -73,12 +72,13 @@ static scheduling_s startTimer[2];
static scheduling_s endTimer[2];
static void startAveraging(void*arg) {
chSysLockFromIsr()
bool wasLocked = lockAnyContext();
;
// with locking we would have a consistent state
v_mapAccumulator = 0;
mapMeasurementsCounter = 0;
chSysUnlockFromIsr()
if (!wasLocked)
chSysUnlockFromIsr()
;
}
@ -111,11 +111,11 @@ void mapAveragingCallback(adcsample_t value) {
}
static void endAveraging(void *arg) {
chSysLockFromIsr()
;
bool wasLocked = lockAnyContext();
// with locking we would have a consistent state
v_averagedMapValue = v_mapAccumulator / mapMeasurementsCounter;
chSysUnlockFromIsr()
if (!wasLocked)
chSysUnlockFromIsr()
;
}
@ -129,7 +129,7 @@ static void shaftPositionCallback(trigger_event_e ckpEventType, int index, void
return;
int rpm = getRpm();
if(!isValidRpm(rpm))
if (!isValidRpm(rpm))
return;
perRevolution = perRevolutionCounter;
@ -139,6 +139,10 @@ static void shaftPositionCallback(trigger_event_e ckpEventType, int index, void
float startAngle = interpolate2d(rpm, config->samplingAngleBins, config->samplingAngle, MAP_ANGLE_SIZE);
float windowAngle = interpolate2d(rpm, config->samplingWindowBins, config->samplingWindow, MAP_WINDOW_SIZE);
if (windowAngle <= 0) {
firmwareError("map sampling angle should be positive");
return;
}
int structIndex = getRevolutionCounter() % 2;
// todo: schedule this based on closest trigger event, same as ignition works
@ -172,7 +176,6 @@ void initMapAveraging(void) {
endTimer[0].name = "map end0";
endTimer[1].name = "map end1";
addTriggerEventListener(&shaftPositionCallback, "rpm reporter", NULL);
addConsoleAction("faststat", showMapStats);
}

View File

@ -76,17 +76,19 @@ float fixAngle(float angle) {
* @brief Returns engine load according to selected engine_load_mode
*
*/
float getEngineLoadT(engine_configuration_s *engineConfiguration) {
float getEngineLoadT(Engine *engine) {
efiAssert(engine!=NULL, "engine 2NULL", NAN);
engine_configuration_s *engineConfiguration = engine->engineConfiguration;
efiAssert(engineConfiguration!=NULL, "engineConfiguration 2NULL", NAN);
switch (engineConfiguration->algorithm) {
case LM_MAF:
return getMaf();
return getMafT(engineConfiguration);
case LM_SPEED_DENSITY:
// SD engine load is used for timing lookup but not for fuel calculation
case LM_MAP:
return getMap();
case LM_TPS:
return getTPS();
case LM_SPEED_DENSITY:
// TODO: real implementation
return getMap();
default:
firmwareError("Unexpected engine load parameter: %d", engineConfiguration->algorithm);
return -1;

View File

@ -14,6 +14,7 @@
#include "ec2.h"
#include "trigger_structure.h"
#include "table_helper.h"
#include "engine.h"
void findTriggerPosition(engine_configuration_s const *engineConfiguration, trigger_shape_s * s,
event_trigger_position_s *position, float angleOffset);
@ -38,8 +39,8 @@ float getCrankshaftRevolutionTimeMs(int rpm);
int isCrankingRT(engine_configuration_s *engineConfiguration, int rpm);
#define isCrankingR(rpm) isCrankingRT(engineConfiguration, rpm)
float getEngineLoadT(engine_configuration_s *engineConfiguration);
#define getEngineLoad() getEngineLoadT(engineConfiguration)
float getEngineLoadT(Engine *engine);
#define getEngineLoad() getEngineLoadT(&engine)
float getSparkDwellMsT(engine_configuration_s *engineConfiguration, int rpm);
#define getSparkDwellMs(rpm) getSparkDwellMsT(engineConfiguration, rpm)

View File

@ -8,7 +8,6 @@
#include "main.h"
#include "speed_density.h"
#include "interpolation.h"
#include "engine.h"
#include "rpm_calculator.h"
#include "engine_math.h"
#include "engine_state.h"
@ -49,6 +48,11 @@ float getTCharge(int rpm, int tps, float coolantTemp, float airTemp) {
* @return value in seconds
*/
float sdMath(engine_configuration_s *engineConfiguration, float VE, float MAP, float AFR, float temp) {
if (MAP < 0.001 || cisnan(MAP)) {
warning(OBD_PCM_Processor_Fault, "invalid MAP value");
return 0;
}
float injectorFlowRate = cc_minute_to_gramm_second(engineConfiguration->injectorFlow);
float Vol = engineConfiguration->displacement / engineConfiguration->cylindersCount;
return (Vol * VE * MAP) / (AFR * injectorFlowRate * GAS_R * temp);
@ -57,8 +61,8 @@ float sdMath(engine_configuration_s *engineConfiguration, float VE, float MAP, f
/**
* @return value in Milliseconds
*/
float getSpeedDensityFuel(Engine *engine) {
int rpm = engine->rpmCalculator->rpm();
float getSpeedDensityFuel(Engine *engine, int rpm) {
//int rpm = engine->rpmCalculator->rpm();
engine_configuration_s *engineConfiguration = engine->engineConfiguration;

View File

@ -9,6 +9,7 @@
#include "engine_configuration.h"
#include "ec2.h"
#include "engine.h"
float getTCharge(int rpm, int tps, float coolantTemp, float airTemp);
void setDetaultVETable(engine_configuration_s *engineConfiguration);
@ -20,5 +21,6 @@ float sdMath(engine_configuration_s *engineConfiguration, float VE, float MAP, f
void setDetaultVETable(engine_configuration_s *engineConfiguration);
void initSpeedDensity(engine_configuration_s *engineConfiguration);
float getSpeedDensityFuel(Engine *engine, int rpm);
#endif /* SPEED_DENSITY_H_ */

View File

@ -19,6 +19,11 @@
#include "ego.h"
#include "voltage.h"
#include "thermistors.h"
#include "adc_inputs.h"
#if EFI_PROD_CODE || EFI_SIMULATOR
#include "adc_math.h"
#endif
#ifdef __cplusplus

View File

@ -2,9 +2,10 @@
#include "boards.h"
#include "engine_configuration.h"
#include "adc_inputs.h"
#include "maf.h"
extern engine_configuration_s *engineConfiguration;
float getMaf(void) {
return getVoltageDivided(engineConfiguration->mafAdcChannel);
return getMafT(engineConfiguration);
}

View File

@ -17,6 +17,8 @@ extern "C"
{
#endif /* __cplusplus */
#define getMafT(ec) (getVoltageDivided(ec->mafAdcChannel))
float getMaf(void);
#ifdef __cplusplus

View File

@ -18,6 +18,9 @@ extern engine_configuration_s * engineConfiguration;
*/
static FastInterpolation denso183(0, -6.64, 5, 182.78);
// todo: figure out real values
static FastInterpolation honda3bar(0.32, -95.8371264, 4.84, 300);
static FastInterpolation mpx4250(0, 8, 5, 260);
float decodePressure(float voltage, air_pressure_sensor_config_s * config) {
@ -29,6 +32,8 @@ float decodePressure(float voltage, air_pressure_sensor_config_s * config) {
return denso183.getValue(voltage);
case MT_MPX4250:
return mpx4250.getValue(voltage);
case MT_HONDA3BAR:
return honda3bar.getValue(voltage);
default:
firmwareError("Unknown MAP type: %d", config->sensorType);
return NAN;

View File

@ -125,7 +125,7 @@ static const char * boolToString(bool value) {
*/
void printConfiguration(engine_configuration_s *engineConfiguration, engine_configuration2_s *engineConfiguration2) {
scheduleMsg(&logger, getConfigurationName(engineConfiguration));
scheduleMsg(&logger, "Template %s trigger %d", getConfigurationName(engineConfiguration), engineConfiguration->triggerConfig.triggerType);
scheduleMsg(&logger, "configurationVersion=%d", getGlobalConfigurationVersion());
@ -172,10 +172,11 @@ void printConfiguration(engine_configuration_s *engineConfiguration, engine_conf
// scheduleMsg(&logger, "crankingRpm: %d", engineConfiguration->crankingSettings.crankingRpm);
scheduleMsg(&logger, "idlePinMode: %s", pinModeToString(boardConfiguration->idleValvePinMode));
scheduleMsg(&logger, "malfunctionIndicatorPinMode: %s", pinModeToString(boardConfiguration->malfunctionIndicatorPinMode));
scheduleMsg(&logger, "malfunctionIndicatorPinMode: %s",
pinModeToString(boardConfiguration->malfunctionIndicatorPinMode));
scheduleMsg(&logger, "analogInputDividerCoefficient: %f", engineConfiguration->analogInputDividerCoefficient);
scheduleMsg(&logger, "needSecondTriggerInput: %s", boolToString(engineConfiguration->needSecondTriggerInput));
scheduleMsg(&logger, "needSecondTriggerInput: %s", boolToString(engineConfiguration2->triggerShape.needSecondTriggerInput));
#if EFI_PROD_CODE
scheduleMsg(&logger, "idleValvePin: %s", hwPortname(boardConfiguration->idleValvePin));
@ -204,12 +205,15 @@ void printConfiguration(engine_configuration_s *engineConfiguration, engine_conf
scheduleMsg(&logger, "primary trigger input: %s", hwPortname(boardConfiguration->primaryTriggerInputPin));
scheduleMsg(&logger, "boardTestModeJumperPin: %s", hwPortname(boardConfiguration->boardTestModeJumperPin));
scheduleMsg(&logger, "digitalPotentiometerSpiDevice %d", boardConfiguration->digitalPotentiometerSpiDevice);
for (int i = 0; i < DIGIPOT_COUNT; i++) {
scheduleMsg(&logger, "digitalPotentiometer CS%d %s", i, hwPortname(boardConfiguration->digitalPotentiometerChipSelect[i]));
}
#endif /* EFI_PROD_CODE */
scheduleMsg(&logger, "isInjectionEnabledFlag %s", boolToString(engineConfiguration2->isInjectionEnabledFlag));
// appendPrintf(&logger, DELIMETER);
// scheduleLogging(&logger);
}
static void setFixedModeTiming(int value) {
@ -369,6 +373,11 @@ static void setCrankingRpm(int value) {
doPrintConfiguration();
}
static void setAlgorithm(int value) {
engineConfiguration->algorithm = (engine_load_mode_e) value;
doPrintConfiguration();
}
static void setFiringOrder(int value) {
engineConfiguration->firingOrder = (firing_order_e) value;
doPrintConfiguration();
@ -415,9 +424,15 @@ static void setIgnitionMode(int value) {
doPrintConfiguration();
}
static void setTriggerType(int value) {
engineConfiguration->triggerConfig.triggerType = (trigger_type_e)value;
incrementGlobalConfigurationVersion();
doPrintConfiguration();
}
static void setToothedWheel(int total, int skipped) {
setToothedWheelConfiguration(engineConfiguration, total, skipped);
initializeTriggerShape(&logger, engineConfiguration, engineConfiguration2);
setToothedWheelConfiguration(&engineConfiguration2->triggerShape, total, skipped, engineConfiguration);
// initializeTriggerShape(&logger, engineConfiguration, engineConfiguration2);
incrementGlobalConfigurationVersion();
doPrintConfiguration();
}
@ -436,6 +451,7 @@ static void setGlobalFuelCorrection(float value) {
}
static void setWholeTimingMap(float value) {
// todo: table helper?
scheduleMsg(&logger, "Setting whole timing map to %f", value);
for (int l = 0; l < IGN_LOAD_COUNT; l++) {
for (int r = 0; r < IGN_RPM_COUNT; r++) {
@ -549,9 +565,11 @@ void initSettings(void) {
addConsoleActionI("set_rpm_hard_limit", setRpmHardLimit);
addConsoleActionI("set_firing_order", setFiringOrder);
addConsoleActionI("set_algorithm", setAlgorithm);
addConsoleAction("enable_injection", enableInjection);
addConsoleAction("disable_injection", disableInjection);
addConsoleActionII("set_toothed_wheel", setToothedWheel);
addConsoleActionI("set_trigger_type", setTriggerType);
}

View File

@ -96,8 +96,11 @@ void Executor::doExecute(uint64_t nowUs) {
* @param [in] delayUs the number of microseconds before the output signal immediate output if delay is zero.
* @param [in] dwell the number of ticks of output duration.
*/
void scheduleTask(scheduling_s *scheduling, int delayUs, schfunc_t callback, void *param) {
efiAssertVoid(delayUs >= 0, "Negative delayUs");
void scheduleTask(const char *prefix, scheduling_s *scheduling, int delayUs, schfunc_t callback, void *param) {
if (delayUs < 0) {
firmwareError("Negative delayUs %s: %d", prefix, delayUs);
return;
}
if (delayUs == 0) {
callback(param);
return;

View File

@ -47,16 +47,16 @@ 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.getSwitchTime(state->safe.phaseIndex);
float periodMs = state->safe.periodMs;
float periodUs = state->safe.periodUs;
#if DEBUG_PWM
scheduleMsg(&logger, "iteration=%d switchTime=%f period=%f", iteration, switchTime, period);
#endif
/**
* todo: once 'iteration' gets relatively high, we might lose calculation precision here
* todo: double-check this spot
* Once 'iteration' gets relatively high, we might lose calculation precision here.
* This is addressed by ITERATION_LIMIT
*/
uint64_t timeToSwitchUs = (iteration + switchTime) * periodMs * 1000;
uint64_t timeToSwitchUs = (iteration + switchTime) * periodUs;
#if DEBUG_PWM
scheduleMsg(&logger, "start=%d timeToSwitch=%d", state->safe.start, timeToSwitch);
@ -64,6 +64,25 @@ static uint64_t getNextSwitchTimeUs(PwmConfig *state) {
return state->safe.startUs + timeToSwitchUs;
}
void PwmConfig::handleCycleStart() {
if (safe.phaseIndex == 0) {
if (cycleCallback != NULL)
cycleCallback(this);
efiAssertVoid(periodUs != 0, "period not initialized");
if (safe.periodUs != periodUs || safe.iteration == ITERATION_LIMIT) {
/**
* period length has changed - we need to reset internal state
*/
safe.startUs = getTimeNowUs();
safe.iteration = 0;
safe.periodUs = periodUs;
#if DEBUG_PWM
scheduleMsg(&logger, "state reset start=%d iteration=%d", state->safe.start, state->safe.iteration);
#endif
}
}
}
/**
* @return Next time for signal toggle
*/
@ -73,31 +92,21 @@ static uint64_t togglePwmState(PwmConfig *state) {
scheduleMsg(&logger, "state->period=%f state->safe.period=%f", state->period, state->safe.period);
#endif
if (state->safe.phaseIndex == 0) {
if (cisnan(state->periodMs)) {
/**
* zero period means PWM is paused
*/
return 1;
}
if (state->cycleCallback != NULL)
state->cycleCallback(state);
efiAssert(state->periodMs != 0, "period not initialized", 0);
if (state->safe.periodMs != state->periodMs || state->safe.iteration == ITERATION_LIMIT) {
/**
* period length has changed - we need to reset internal state
*/
state->safe.startUs = getTimeNowUs();
state->safe.iteration = 0;
state->safe.periodMs = state->periodMs;
#if DEBUG_PWM
scheduleMsg(&logger, "state reset start=%d iteration=%d", state->safe.start, state->safe.iteration);
#endif
}
if (cisnan(state->periodUs)) {
/**
* zero period means PWM is paused
*/
return 1;
}
state->stateChangeCallback(state,
state->safe.phaseIndex == 0 ? state->phaseCount - 1 : state->safe.phaseIndex - 1);
state->handleCycleStart();
/**
* Here is where the 'business logic' - the actual pin state change is happening
*/
// callback state index is offset by one. todo: why? can we simplify this?
int cbStateIndex = state->safe.phaseIndex == 0 ? state->phaseCount - 1 : state->safe.phaseIndex - 1;
state->stateChangeCallback(state, cbStateIndex);
uint64_t nextSwitchTimeUs = getNextSwitchTimeUs(state);
#if DEBUG_PWM
@ -106,8 +115,13 @@ static uint64_t togglePwmState(PwmConfig *state) {
// signed value is needed here
int64_t timeToSwitch = nextSwitchTimeUs - getTimeNowUs();
if (timeToSwitch < 1) {
//todo: introduce error and test this error handling warning(OBD_PCM_Processor_Fault, "PWM: negative switch time");
timeToSwitch = 1000;
/**
* We are here if we are late for a state transition.
* At 12000RPM=200Hz with a 60 toothed wheel we need to change state every
* 1000000 / 200 / 120 = ~41 uS. We are kind of OK.
*/
//todo: introduce error and test this error handling warning(OBD_PCM_Processor_Fault, "PWM: negative switch time");
timeToSwitch = 10;
}
state->safe.phaseIndex++;
@ -118,9 +132,12 @@ static uint64_t togglePwmState(PwmConfig *state) {
return timeToSwitch;
}
/**
* Main PWM loop: toggle pin & schedule next invocation
*/
static void timerCallback(PwmConfig *state) {
time_t timeToSleepUs = togglePwmState(state);
scheduleTask(&state->scheduling, timeToSleepUs, (schfunc_t) timerCallback, state);
scheduleTask("pwm", &state->scheduling, timeToSleepUs, (schfunc_t) timerCallback, state);
}
/**
@ -144,7 +161,7 @@ void copyPwmParameters(PwmConfig *state, int phaseCount, float *switchTimes, int
void weComplexInit(const char *msg, PwmConfig *state, int phaseCount, float *switchTimes, int waveCount,
int **pinStates, pwm_cycle_callback *cycleCallback, pwm_gen_callback *stateChangeCallback) {
efiAssertVoid(state->periodMs != 0, "period is not initialized");
efiAssertVoid(state->periodUs != 0, "period is not initialized");
if (phaseCount == 0) {
firmwareError("signal length cannot be zero");
return;
@ -168,9 +185,10 @@ void weComplexInit(const char *msg, PwmConfig *state, int phaseCount, float *swi
state->stateChangeCallback = stateChangeCallback;
state->safe.phaseIndex = 0;
state->safe.periodMs = -1;
state->safe.periodUs = -1;
state->safe.iteration = -1;
state->name = msg;
// let's start the indefinite callback loop of PWM generation
timerCallback(state);
}

View File

@ -18,7 +18,7 @@ typedef struct {
* a copy so that all phases are executed on the same period, even if another thread
* would be adjusting PWM parameters
*/
float periodMs;
float periodUs;
/**
* Iteration counter
*/
@ -43,6 +43,10 @@ public:
PwmConfig();
PwmConfig(float *switchTimes, single_wave_s *waves);
void init(float *switchTimes, single_wave_s *waves);
void handleCycleStart();
io_pin_e outputPins[PWM_PHASE_MAX_WAVE_PER_PWM];
multi_wave_s multiWave;
const char *name;
@ -50,7 +54,7 @@ public:
* float value of PWM period
* PWM generation is not happening while this value is zero
*/
float periodMs;
float periodUs;
scheduling_s scheduling;

View File

@ -29,7 +29,7 @@ extern "C"
{
#endif /* __cplusplus */
void scheduleTask(scheduling_s *scheduling, int delayUs, schfunc_t callback, void *param);
void scheduleTask(const char *prefix, scheduling_s *scheduling, int delayUs, schfunc_t callback, void *param);
#ifdef __cplusplus
}

View File

@ -28,7 +28,7 @@
#if EFI_SIGNAL_EXECUTOR_SLEEP || defined(__DOXYGEN__)
void scheduleTask(scheduling_s *scheduling, int delayUs, schfunc_t callback, void *param) {
void scheduleTask(const char *prefix, scheduling_s *scheduling, int delayUs, schfunc_t callback, void *param) {
int delaySt = delayUs * CH_FREQUENCY / 1000000;
if (delaySt == 0) {
/**

View File

@ -78,7 +78,7 @@ static cyclic_buffer ignitionErrorDetection;
static Logging logger;
static void handleFuelInjectionEvent(MainTriggerCallback *mainTriggerCallback, ActuatorEvent *event, int rpm) {
float fuelMs = getFuelMs(rpm) * mainTriggerCallback->engineConfiguration->globalFuelCorrection;
float fuelMs = getFuelMs(rpm, mainTriggerCallback->engine) * mainTriggerCallback->engineConfiguration->globalFuelCorrection;
if (cisnan(fuelMs)) {
warning(OBD_PCM_Processor_Fault, "NaN injection pulse");
return;
@ -156,7 +156,7 @@ static void handleSparkEvent(MainTriggerCallback *mainTriggerCallback, int event
/**
* 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 *) iEvent->io_pin);
scheduleTask("spark up", 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
@ -171,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*) iEvent->io_pin);
scheduleTask("spark 1down", 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
@ -204,7 +204,7 @@ static void handleSpark(MainTriggerCallback *mainTriggerCallback, int eventIndex
scheduling_s * sDown = &current->signalTimerDown;
float timeTillIgnitionUs = getOneDegreeTimeUs(rpm) * current->sparkPosition.angleOffset;
scheduleTask(sDown, (int) timeTillIgnitionUs, (schfunc_t) &turnPinLow, (void*) current->io_pin);
scheduleTask("spark 2down", sDown, (int) timeTillIgnitionUs, (schfunc_t) &turnPinLow, (void*) current->io_pin);
}
}
@ -276,7 +276,7 @@ void onTriggerEvent(trigger_event_e ckpSignalType, int eventIndex, MainTriggerCa
firmwareError("invalid dwell: %f at %d", dwellMs, rpm);
return;
}
float advance = getAdvance(rpm, getEngineLoadT(mainTriggerCallback->engineConfiguration));
float advance = getAdvance(rpm, getEngineLoadT(mainTriggerCallback->engine));
float dwellAngle = dwellMs / getOneDegreeTimeMs(rpm);
@ -293,7 +293,7 @@ void onTriggerEvent(trigger_event_e ckpSignalType, int eventIndex, MainTriggerCa
#if EFI_HISTOGRAMS && EFI_PROD_CODE
int diff = hal_lld_get_counter_value() - beforeCallback;
if (diff > 0)
hsAdd(&mainLoopHisto, diff);
hsAdd(&mainLoopHisto, diff);
#endif /* EFI_HISTOGRAMS */
}
@ -309,21 +309,26 @@ static void showTriggerHistogram(void) {
static void showMainInfo(void) {
int rpm = getRpm();
float el = getEngineLoadT(mainTriggerCallbackInstance.engineConfiguration);
float el = getEngineLoadT(mainTriggerCallbackInstance.engine);
#if EFI_PROD_CODE
scheduleMsg(&logger, "rpm %d engine_load %f", rpm, el);
scheduleMsg(&logger, "fuel %fms timing %f", getFuelMs(rpm), getAdvance(rpm, el));
scheduleMsg(&logger, "fuel %fms timing %f", getFuelMs(rpm, mainTriggerCallbackInstance.engine), getAdvance(rpm, el));
#endif
}
void MainTriggerCallback::init(engine_configuration_s *engineConfiguration,
engine_configuration2_s *engineConfiguration2) {
this->engineConfiguration = engineConfiguration;
void MainTriggerCallback::init(Engine *engine, engine_configuration2_s *engineConfiguration2) {
efiAssertVoid(engine!=NULL, "engine NULL");
this->engine = engine;
this->engineConfiguration = engine->engineConfiguration;
efiAssertVoid(engineConfiguration!=NULL, "engineConfiguration NULL");
this->engineConfiguration2 = engineConfiguration2;
}
void initMainEventListener(engine_configuration_s *engineConfiguration, engine_configuration2_s *engineConfiguration2) {
mainTriggerCallbackInstance.init(engineConfiguration, engineConfiguration2);
void initMainEventListener(Engine *engine, engine_configuration2_s *engineConfiguration2) {
efiAssertVoid(engine!=NULL, "null engine");
engine_configuration_s *engineConfiguration = engine->engineConfiguration;
mainTriggerCallbackInstance.init(engine, engineConfiguration2);
#if EFI_PROD_CODE
addConsoleAction("performanceinfo", showTriggerHistogram);
@ -332,7 +337,7 @@ void initMainEventListener(engine_configuration_s *engineConfiguration, engine_c
initLogging(&logger, "main event handler");
printMsg(&logger, "initMainLoop: %d", currentTimeMillis());
if (!isInjectionEnabled(mainTriggerCallbackInstance.engineConfiguration2))
printMsg(&logger, "!!!!!!!!!!!!!!!!!!! injection disabled");
printMsg(&logger, "!!!!!!!!!!!!!!!!!!! injection disabled");
#endif
#if EFI_HISTOGRAMS

View File

@ -231,7 +231,7 @@ void scheduleByAngle(scheduling_s *timer, float angle, schfunc_t callback, void
firmwareError("NaN delay?");
return;
}
scheduleTask(timer, (int)MS2US(delayMs), callback, param);
scheduleTask("by angle", timer, (int)MS2US(delayMs), callback, param);
}
#endif

View File

@ -15,8 +15,7 @@ static inline float addPair(trigger_shape_s *s, float a, float w) {
return a;
}
void configureMiniCooperTriggerShape(trigger_config_s *triggerConfig,
trigger_shape_s *s) {
void configureMiniCooperTriggerShape(trigger_shape_s *s) {
s->reset(FOUR_STROKE_CAM_SENSOR);
@ -67,5 +66,5 @@ void configureMiniCooperTriggerShape(trigger_config_s *triggerConfig,
/**
* With just one tooth on camshaft synchronization is not needed
*/
triggerConfig->isSynchronizationNeeded = FALSE;
s->isSynchronizationNeeded = FALSE;
}

View File

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

View File

@ -7,9 +7,15 @@
#include "trigger_chrysler.h"
void configureNeonTriggerShape(trigger_config_s *triggerConfig, trigger_shape_s *s) {
void configureNeonTriggerShape(trigger_shape_s *s) {
s->reset(FOUR_STROKE_CAM_SENSOR);
setTriggerSynchronizationGap(s, 0.72);
s->useRiseEdge = false;
s->needSecondTriggerInput = true;
// voodoo magic - we always need 720 at the end
int base = 720 - 560;

View File

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

View File

@ -47,16 +47,16 @@ 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)
if (!triggerShape->isSynchronizationNeeded)
return false;
return currentDuration > shaftPositionState->toothed_previous_duration * triggerConfig->syncRatioFrom
&& currentDuration < shaftPositionState->toothed_previous_duration * triggerConfig->syncRatioTo;
return currentDuration > shaftPositionState->toothed_previous_duration * triggerShape->syncRatioFrom
&& currentDuration < shaftPositionState->toothed_previous_duration * triggerShape->syncRatioTo;
}
static inline int noSynchronizationResetNeeded(TriggerState *shaftPositionState, trigger_shape_s const *triggerShape,
trigger_config_s const*triggerConfig) {
if (triggerConfig->isSynchronizationNeeded)
if (triggerShape->isSynchronizationNeeded)
return false;
if (!shaftPositionState->shaft_is_synchronized)
return TRUE;
@ -73,8 +73,8 @@ static inline int noSynchronizationResetNeeded(TriggerState *shaftPositionState,
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)
|| (!triggerConfig->useRiseEdge && signal != SHAFT_PRIMARY_DOWN);
int isLessImportant = (triggerShape->useRiseEdge && signal != SHAFT_PRIMARY_UP)
|| (!triggerShape->useRiseEdge && signal != SHAFT_PRIMARY_DOWN);
if (isLessImportant) {
/**
@ -139,11 +139,12 @@ static void initializeSkippedToothTriggerShape(trigger_shape_s *s, int totalTeet
s->addEvent(720, T_PRIMARY, TV_LOW);
}
void initializeSkippedToothTriggerShapeExt(engine_configuration2_s *engineConfiguration2, int totalTeethCount,
void initializeSkippedToothTriggerShapeExt(trigger_shape_s *s, int totalTeethCount,
int skippedCount, operation_mode_e operationMode) {
efiAssertVoid(totalTeethCount > 0, "totalTeethCount is zero");
trigger_shape_s *s = &engineConfiguration2->triggerShape;
s->totalToothCount = totalTeethCount;
s->skippedToothCount = skippedCount;
initializeSkippedToothTriggerShape(s, totalTeethCount, skippedCount, operationMode);
s->shaftPositionEventCount = ((totalTeethCount - skippedCount) * 2);
@ -151,6 +152,7 @@ void initializeSkippedToothTriggerShapeExt(engine_configuration2_s *engineConfig
}
static void configureFordAspireTriggerShape(trigger_config_s *triggerConfig, trigger_shape_s * s) {
s->isSynchronizationNeeded = false;
s->reset(FOUR_STROKE_CAM_SENSOR);
s->shaftPositionEventCount = 10;
@ -174,23 +176,34 @@ static void configureFordAspireTriggerShape(trigger_config_s *triggerConfig, tri
void initializeTriggerShape(Logging *logger, engine_configuration_s *engineConfiguration,
engine_configuration2_s *engineConfiguration2) {
#if EFI_PROD_CODE
printMsg(logger, "initializeTriggerShape()");
scheduleMsg(logger, "initializeTriggerShape()");
#endif
trigger_config_s *triggerConfig = &engineConfiguration->triggerConfig;
trigger_shape_s *triggerShape = &engineConfiguration2->triggerShape;
setTriggerSynchronizationGap(triggerShape, 2);
triggerShape->useRiseEdge = TRUE;
triggerShape->needSecondTriggerInput = TRUE;
switch (triggerConfig->triggerType) {
case TT_TOOTHED_WHEEL:
initializeSkippedToothTriggerShapeExt(engineConfiguration2, triggerConfig->totalToothCount, triggerConfig->skippedToothCount,
engineConfiguration2->triggerShape.needSecondTriggerInput = false;
engineConfiguration2->triggerShape.isSynchronizationNeeded = engineConfiguration->triggerConfig.customIsSynchronizationNeeded;
initializeSkippedToothTriggerShapeExt(triggerShape, triggerConfig->customTotalToothCount,
triggerConfig->customSkippedToothCount,
getOperationMode(engineConfiguration));
return;
case TT_MAZDA_MIATA_NB:
initializeMazdaMiataNbShape(triggerConfig, triggerShape);
initializeMazdaMiataNbShape(triggerShape);
return;
case TT_DODGE_NEON:
configureNeonTriggerShape(triggerConfig, triggerShape);
configureNeonTriggerShape(triggerShape);
return;
case TT_FORD_ASPIRE:
@ -202,11 +215,20 @@ void initializeTriggerShape(Logging *logger, engine_configuration_s *engineConfi
return;
case TT_FORD_ESCORT_GT:
configureMazdaProtegeLx(triggerConfig, triggerShape);
configureMazdaProtegeLx(triggerShape);
return;
case TT_MINI_COOPER_R50:
configureMiniCooperTriggerShape(triggerConfig, triggerShape);
configureMiniCooperTriggerShape(triggerShape);
return;
case TT_TOOTHED_WHEEL_60_2:
setToothedWheelConfiguration(triggerShape, 60, 2, engineConfiguration);
setTriggerSynchronizationGap(triggerShape, 2.5);
return;
case TT_TOOTHED_WHEEL_36_1:
setToothedWheelConfiguration(triggerShape, 36, 1, engineConfiguration);
return;
default:

View File

@ -23,7 +23,7 @@ private:
bool secondaryWheelState;
};
void initializeSkippedToothTriggerShapeExt(engine_configuration2_s *engineConfiguration2, int totalTeethCount, int skippedCount, operation_mode_e operationMode);
void initializeSkippedToothTriggerShapeExt(trigger_shape_s *s, 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);

View File

@ -36,22 +36,25 @@ void setTriggerEmulatorRPM(int rpm) {
* togglePwmState() would see that the periodMs has changed and act accordingly
*/
if (rpm == 0) {
triggerSignal.periodMs = NAN;
triggerSignal.periodUs = NAN;
} else {
float gRpm = rpm * engineConfiguration->rpmMultiplier / 60.0; // per minute converted to per second
triggerSignal.periodMs = frequency2period(gRpm);
triggerSignal.periodUs = frequency2periodUs(gRpm);
}
scheduleMsg(&logger, "Emulating position sensor(s). RPM=%d", rpm);
}
static void updateTriggerShapeIfNeeded(PwmConfig *state) {
if(localVersion.isOld()) {
if (localVersion.isOld()) {
scheduleMsg(&logger, "Stimulator: updating trigger shape: %d/%d %d", localVersion.getVersion(), getGlobalConfigurationVersion(), currentTimeMillis());
applyNonPersistentConfiguration(&logger, engineConfiguration, engineConfiguration2);
trigger_shape_s *s = &engineConfiguration2->triggerShape;
int *pinStates[2] = {s->wave.waves[0].pinStates, s->wave.waves[1].pinStates};
copyPwmParameters(state, s->getSize(), s->wave.switchTimes, 2, pinStates);
state->safe.periodMs = -1; // this would cause loop re-initialization
state->safe.periodUs = -1; // this would cause loop re-initialization
}
}

View File

@ -20,7 +20,10 @@
#include "trigger_mazda.h"
void initializeMazdaMiataNbShape(trigger_config_s *triggerConfig, trigger_shape_s *s) {
void initializeMazdaMiataNbShape(trigger_shape_s *s) {
setTriggerSynchronizationGap(s, 0.11);
s->useRiseEdge = false;
s->reset(FOUR_STROKE_CAM_SENSOR);
/**
@ -57,7 +60,10 @@ void initializeMazdaMiataNbShape(trigger_config_s *triggerConfig, trigger_shape_
s->shaftPositionEventCount = 6 + 16;
}
void configureMazdaProtegeLx(trigger_config_s *triggerConfig, trigger_shape_s *s) {
void configureMazdaProtegeLx(trigger_shape_s *s) {
s->needSecondTriggerInput = FALSE;
s->reset(FOUR_STROKE_CAM_SENSOR);
// s->initialState[0] = 1;
@ -97,5 +103,5 @@ void configureMazdaProtegeLx(trigger_config_s *triggerConfig, trigger_shape_s *s
// s->shaftPositionEventCount = 2 + 8;
s->shaftPositionEventCount = 8;
triggerConfig->isSynchronizationNeeded = false;
s->isSynchronizationNeeded = false;
}

View File

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

View File

@ -21,6 +21,7 @@
#include "main.h"
#include "trigger_structure.h"
#include "error_handling.h"
#include "trigger_decoder.h"
trigger_shape_helper::trigger_shape_helper() {
waves[0].init(pinStates0);
@ -188,3 +189,22 @@ void trigger_shape_s::setSwitchTime(int index, float angle) {
void multi_wave_s::checkSwitchTimes(int size) {
checkSwitchTimes2(size, switchTimes);
}
void setToothedWheelConfiguration(trigger_shape_s *s, int total, int skipped, engine_configuration_s const *engineConfiguration) {
s->isSynchronizationNeeded = (skipped != 0);
s->totalToothCount = total;
s->skippedToothCount = skipped;
s->needSecondTriggerInput = false;
s->useRiseEdge = TRUE;
initializeSkippedToothTriggerShapeExt(s, s->totalToothCount,
s->skippedToothCount,
getOperationMode(engineConfiguration));
}
void setTriggerSynchronizationGap(trigger_shape_s *s, float synchGap) {
s->isSynchronizationNeeded = TRUE;
s->syncRatioFrom = synchGap * 0.75;
s->syncRatioTo = synchGap * 1.25;
}

View File

@ -71,6 +71,19 @@ private:
trigger_shape_helper h;
int size;
public:
int isSynchronizationNeeded;
int totalToothCount;
int skippedToothCount;
float syncRatioFrom;
float syncRatioTo;
int useRiseEdge;
bool needSecondTriggerInput;
trigger_shape_s();
void addEvent(float angle, trigger_wheel_e waveIndex, trigger_value_e state);
float getAngle(int phaseIndex) const;
@ -123,4 +136,7 @@ private:
operation_mode_e operationMode;
};
void setTriggerSynchronizationGap(trigger_shape_s *s, float synchGap);
void setToothedWheelConfiguration(trigger_shape_s *s, int total, int skipped, engine_configuration_s const *engineConfiguration);
#endif /* TRIGGER_STRUCTURE_H_ */

View File

@ -1,16 +1,16 @@
/**
* @file engine_emulator.c
* @file engine_emulator.cpp
* @brief Entry point for all the emulation and analysis code
*
* @date Mar 15, 2013
* @author Andrey Belomutskiy, (c) 2012-2014
*/
extern "C" {
#include "main.h"
#include "engine_emulator.h"
extern "C" {
#include "status_loop.h"
#include "advance_map.h"
#include "wave_analyzer.h"
@ -92,12 +92,12 @@ static void initECUstimulator(void) {
chThdCreateStatic(eeThreadStack, sizeof(eeThreadStack), NORMALPRIO, (tfunc_t) eeThread, NULL);
}
void initEngineEmulator(void) {
void initEngineEmulator(board_configuration_s *boardConfiguration) {
if (hasFirmwareError())
return;
#if EFI_POTENTIOMETER
initPotentiometers();
initPotentiometers(boardConfiguration);
#endif /* EFI_POTENTIOMETER */
//initECUstimulator();

View File

@ -8,18 +8,7 @@
#ifndef ENGINE_EMULATOR_H_
#define ENGINE_EMULATOR_H_
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
void initEngineEmulator(void);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#include "engine_configuration.h"
void initEngineEmulator(board_configuration_s *boardConfiguration);
#endif /* ENGINE_EMULATOR_H_ */

View File

@ -11,6 +11,7 @@
#include "eficonsole.h"
#include "pin_repository.h"
#include "engine_configuration.h"
#include "hardware.h"
/**
* MCP42010 digital potentiometer driver
@ -35,40 +36,30 @@
*
*/
SPIDriver * getDigiralPotDevice(void) {
#if STM32_SPI_USE_SPI2 || defined(__DOXYGEN__)
// return &SPID2;
SPIDriver * getDigiralPotDevice(spi_device_e spiDevice) {
#if STM32_SPI_USE_SPI1 || defined(__DOXYGEN__)
if (spiDevice == SPI_DEVICE_1)
return &SPID1;
#endif
return &SPID3;
#if STM32_SPI_USE_SPI2 || defined(__DOXYGEN__)
if (spiDevic e== SPI_DEVICE_2)
return &SPID2;
#endif
#if STM32_SPI_USE_SPI3 || defined(__DOXYGEN__)
if (spiDevice == SPI_DEVICE_3)
return &SPID3;
#endif
firmwareError("Unexpected SPI device: %d", spiDevice);
return NULL;
}
//#define POTEN_CS_PORT GPIOB
//#define POTEN_CS_PIN 12
//#define POT_SPI &SPID1
// PA13 & PA14 are system pins
//// chip select
//#define POTEN_CS_PORT GPIOE
//#define POTEN_CS_PIN 15
// chip select
#define POTEN_CS_PORT GPIOA
#define POTEN_CS_PIN 10
//#define POT_SPI &SPID3
/* Low speed SPI configuration (281.250kHz, CPHA=0, CPOL=0, MSb first).*/
#define SPI_POT_CONFIG SPI_CR1_BR_2 | SPI_CR1_BR_1 | SPI_CR1_DFF
static Logging logger;
#if EFI_POTENTIOMETER
Mcp42010Driver config0;
Mcp42010Driver config[DIGIPOT_COUNT];
void initPotentiometer(Mcp42010Driver *driver, SPIDriver *spi, ioportid_t port, ioportmask_t pin) {
driver->spiConfig.end_cb = NULL;
@ -83,14 +74,15 @@ static int getPotStep(int resistanceWA) {
return 256 - (int) ((resistanceWA - 52) * 256 / 10000);
}
static void sendToPot(Mcp42010Driver *driver, int channel, int value) {
lockSpi(SPI_NONE);
spiStart(driver->spi, &driver->spiConfig);
spiSelect(driver->spi);
int word = (17 + channel) * 256 + value;
spiSend(driver->spi, 1, &word);
spiUnselect(driver->spi);
spiStop(driver->spi);
unlockSpi();
}
void setPotResistance(Mcp42010Driver *driver, int channel, int resistance) {
@ -105,32 +97,42 @@ void setPotResistance(Mcp42010Driver *driver, int channel, int resistance) {
appendPrintf(&logger, "%d for R=%d", value, resistance);
appendMsgPostfix(logging);
scheduleLogging(logging);
sendToPot(driver, channel, value);
}
static void setPotResistance0(int value) {
setPotResistance(&config0, 0, value);
setPotResistance(&config[0], 0, value);
}
static void setPotResistance1(int value) {
setPotResistance(&config0, 1, value);
setPotResistance(&config[0], 1, value);
}
static void setPotValue1(int value) {
sendToPot(&config0, 1, value);
sendToPot(&config[0], 1, value);
}
#endif /* EFI_POTENTIOMETER */
void initPotentiometers() {
void initPotentiometers(board_configuration_s *boardConfiguration) {
#if EFI_POTENTIOMETER
initLogging(&logger, "potentiometer");
if (boardConfiguration->digitalPotentiometerSpiDevice == SPI_NONE) {
scheduleMsg(&logger, "digiPot spi disabled");
return;
}
turnOnSpi(boardConfiguration->digitalPotentiometerSpiDevice);
initPotentiometer(&config0, getDigiralPotDevice(), POTEN_CS_PORT, POTEN_CS_PIN);
for (int i = 0; i < DIGIPOT_COUNT; i++) {
brain_pin_e csPin = boardConfiguration->digitalPotentiometerChipSelect[i];
if (csPin == GPIO_NONE)
continue;
initPotentiometer(&config[i], getDigiralPotDevice(boardConfiguration->digitalPotentiometerSpiDevice),
getHwPort(csPin), getHwPin(csPin));
}
addConsoleActionI("pot0", setPotResistance0);
addConsoleActionI("pot1", setPotResistance1);
@ -140,6 +142,6 @@ void initPotentiometers() {
setPotResistance0(3000);
setPotResistance1(7000);
#else
print("potentiometer disabled\r\n");
print("digiPot logic disabled\r\n");
#endif
}

View File

@ -10,6 +10,7 @@
#define POTEN_H_
#include "main.h"
#include "engine_configuration.h"
typedef struct {
SPIDriver *spi;
@ -17,7 +18,7 @@ typedef struct {
} Mcp42010Driver;
void initPotentiometer(Mcp42010Driver *driver, SPIDriver *spi, ioportid_t port, ioportmask_t pin);
void initPotentiometers(void);
void initPotentiometers(board_configuration_s *boardConfiguration);
void setPotResistance(Mcp42010Driver *driver, int channel, int resistance);
#endif /* POTEN_H_ */

View File

@ -76,17 +76,17 @@ static void testRusefiMethods(const int count) {
start = currentTimeMillis();
for (int i = 0; i < count; i++)
tempi += getBaseFuel(4020, 2.21111);
tempi += getBaseTableFuel(4020, 2.21111);
time = currentTimeMillis() - start;
if (tempi != 0)
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);
// start = currentTimeMillis();
// for (int i = 0; i < count; i++)
// tempi += getFuelMs(1200, NULL); // todo
// time = currentTimeMillis() - start;
// if (tempi != 0)
// scheduleMsg(&logger, "Finished %d iterations of getFuelMs in %dms", count, time);
start = currentTimeMillis();
for (int i = 0; i < count; i++) {

View File

@ -16,6 +16,7 @@ public:
int size();
void init(void);
int conversionCount;
int errorsCount;
private:
ADCConversionGroup* hwConfig;
/**

View File

@ -1,5 +1,5 @@
/**
* @file adc_inputs.c
* @file adc_inputs.cpp
* @brief Low level ADC code
*
* @date Jan 14, 2013
@ -33,6 +33,8 @@ AdcConfiguration::AdcConfiguration(ADCConversionGroup* hwConfig) {
#define ADC_NUMBER_CHANNELS_FAST 1
// todo: migrate from hardware timer to software ADC conversion triggering
// todo: I guess we would have to use ChibiOS timer and not our own timer because
// todo: adcStartConversionI requires OS lock. currently slow ADC is 10Hz (?)
#define PWM_FREQ_SLOW 5000 /* PWM clock frequency. I wonder what does this setting mean? */
#define PWM_PERIOD_SLOW 500 /* PWM period (in PWM ticks). */
@ -40,7 +42,8 @@ AdcConfiguration::AdcConfiguration(ADCConversionGroup* hwConfig) {
* 8000 RPM is 133Hz
* If we want to sample MAP once per 5 degrees we need 133Hz * (360 / 5) = 9576Hz of fast ADC
*/
// todo: migrate to continues ADC mode?
// todo: migrate to continues ADC mode? probably not - we cannot afford the callback in
// todo: continues mode. todo: look into our options
#define PWM_FREQ_FAST 100000 /* PWM clock frequency. I wonder what does this setting mean? */
#define PWM_PERIOD_FAST 10 /* PWM period (in PWM ticks). */
@ -158,11 +161,13 @@ static void pwmpcb_slow(PWMDriver *pwmp) {
if (ADC_FAST_DEVICE.state != ADC_READY &&
ADC_FAST_DEVICE.state != ADC_COMPLETE &&
ADC_FAST_DEVICE.state != ADC_ERROR) {
firmwareError("ADC slow not ready?");
// todo: why and when does this happen? firmwareError("ADC slow not ready?");
slowAdc.errorsCount++;
chSysUnlockFromIsr()
;
return;
}
slowAdc.errorsCount++;
adcStartConversionI(&ADC_SLOW_DEVICE, &adcgrpcfgSlow, slowAdcState.samples, ADC_GRP1_BUF_DEPTH_SLOW);
chSysUnlockFromIsr()
;
@ -184,7 +189,8 @@ static void pwmpcb_fast(PWMDriver *pwmp) {
if (ADC_FAST_DEVICE.state != ADC_READY &&
ADC_FAST_DEVICE.state != ADC_COMPLETE &&
ADC_FAST_DEVICE.state != ADC_ERROR) {
firmwareError("ADC fast not ready?");
fastAdc.errorsCount++;
// todo: when? why? firmwareError("ADC fast not ready?");
chSysUnlockFromIsr()
;
return;

View File

@ -140,7 +140,7 @@ void initBoardTest(void) {
// print("ADC%d val= %d%s", hwIndex, value, DELIMETER);
float volts = adcToVolts(adcValue) * 2;
print("v=%f adc=%d c=%d\r\n", volts, adcValue, c++);
print("v=%f adc=%d c=%d (hit 'n'<ENTER> for next step\r\n", volts, adcValue, c++);
chThdSleepMilliseconds(300);

View File

@ -31,6 +31,11 @@
* @brief Initialize the hardware output pin while also assigning it a logical name
*/
void initOutputPinExt(const char *msg, OutputPin *outputPin, GPIO_TypeDef *port, uint32_t pinNumber, iomode_t mode) {
// if (outputPin->port != NULL) {
// todo: need to clear '&outputs' in io_pins.c
// firmwareError("outputPin already assigned to %x%d", outputPin->port, outputPin->pin);
// return;
// }
outputPin->currentLogicValue = -1;
outputPin->port = port;
outputPin->pin = pinNumber;

View File

@ -39,12 +39,12 @@
#include "engine_configuration.h"
#include "ec2.h"
McpAdcState adcState;
extern engine_configuration_s *engineConfiguration;
extern engine_configuration2_s * engineConfiguration2;
extern board_configuration_s *boardConfiguration;
static bool isSpiInitialized[5] = { false, false, false, false, false };
static void initSpiModule(SPIDriver *driver, ioportid_t sckPort, ioportmask_t sckPin, ioportid_t misoPort,
ioportmask_t misoPin, ioportid_t mosiPort, ioportmask_t mosiPin, int af) {
mySetPadMode("SPI clock", sckPort, sckPin, PAL_MODE_ALTERNATE(af));
@ -53,23 +53,59 @@ static void initSpiModule(SPIDriver *driver, ioportid_t sckPort, ioportmask_t sc
mySetPadMode("SPI master in ", misoPort, misoPin, PAL_MODE_ALTERNATE(af));
}
void initSpiModules(void) {
static Mutex spiMtx;
/**
* Only one consumer can use SPI bus at a given time
*/
void lockSpi(spi_device_e device) {
// todo: different locks for different SPI devices!
chMtxLock(&spiMtx);
}
void unlockSpi(void) {
chMtxUnlock();
}
void turnOnSpi(spi_device_e device) {
if (isSpiInitialized[device])
return; // already initialized
isSpiInitialized[device] = true;
if (device == SPI_DEVICE_1) {
#if STM32_SPI_USE_SPI1
// scheduleMsg(&logging, "Turning on SPI1 pins");
initSpiModule(&SPID1,
EFI_SPI1_SCK_PORT, EFI_SPI1_SCK_PIN,
EFI_SPI1_MISO_PORT, EFI_SPI1_MISO_PIN,
EFI_SPI1_MOSI_PORT, EFI_SPI1_MOSI_PIN,
EFI_SPI1_AF);
#endif
}
if (device == SPI_DEVICE_2) {
#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);
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);
#endif
}
if (device == SPI_DEVICE_3) {
#if STM32_SPI_USE_SPI3
// scheduleMsg(&logging, "Turning on SPI3 pins");
initSpiModule(&SPID3,
EFI_SPI3_SCK_PORT, EFI_SPI3_SCK_PIN,
EFI_SPI3_MISO_PORT, EFI_SPI3_MISO_PIN,
EFI_SPI3_MOSI_PORT, EFI_SPI3_MOSI_PIN,
EFI_SPI3_AF);
initSpiModule(&SPID3,
EFI_SPI3_SCK_PORT, EFI_SPI3_SCK_PIN,
EFI_SPI3_MISO_PORT, EFI_SPI3_MISO_PIN,
EFI_SPI3_MOSI_PORT, EFI_SPI3_MOSI_PIN,
EFI_SPI3_AF);
#endif
}
}
void initSpiModules(void) {
turnOnSpi(SPI_DEVICE_2);
turnOnSpi(SPI_DEVICE_3);
}
static I2CConfig i2cfg = { OPMODE_I2C, 100000, STD_DUTY_CYCLE, };
@ -100,6 +136,9 @@ void initHardware(Logging *logger) {
// 10 extra seconds to re-flash the chip
//flashProtect();
chMtxInit(&spiMtx);
#if EFI_HISTOGRAMS
/**
* histograms is a data structure for CPU monitor, it does not depend on configuration
@ -199,9 +238,7 @@ void initHardware(Logging *logger) {
if (hasFirmwareError())
return;
char buffer[16];
itoa10(buffer, SVN_VERSION);
lcd_HD44780_print_string(buffer);
lcd_HD44780_print_string(VCS_VERSION);
#endif /* EFI_HD44780_LCD */

View File

@ -10,6 +10,19 @@
#include "main.h"
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
void turnOnSpi(spi_device_e device);
void lockSpi(spi_device_e device);
void unlockSpi(void);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#define GET_BOARD_TEST_MODE_VALUE() (!palReadPad(getHwPort(boardConfiguration->boardTestModeJumperPin), getHwPin(boardConfiguration->boardTestModeJumperPin)))
void initHardware(Logging *logging);

View File

@ -114,6 +114,7 @@ static void errBlinkingThread(void *arg) {
static void outputPinRegisterExt(const char *msg, io_pin_e ioPin, GPIO_TypeDef *port, uint32_t pin,
pin_output_mode_e *outputMode) {
efiAssertVoid((int)ioPin < IO_PIN_COUNT, "io pin out of range");
if (port == GPIO_NULL) {
// that's for GRIO_NONE
outputs[ioPin].port = port;
@ -184,6 +185,13 @@ void initOutputPins(void) {
outputPinRegister("is running status", LED_RUNNING, LED_RUNNING_STATUS_PORT, LED_RUNNING_STATUS_PIN);
outputPinRegister("communication status 1", LED_COMMUNICATION_1, LED_COMMUNICATION_PORT, LED_COMMUNICATION_PIN);
/**
* want to make sure it's all zeros so that we can compare in initOutputPinExt() method
*/
// todo: it's too late to clear now? this breaks default status LEDs
// todo: fix this?
// memset(&outputs, 0, sizeof(outputs));
// outputPinRegister("ext led 1", LED_EXT_1, EXTRA_LED_1_PORT, EXTRA_LED_1_PIN);
// outputPinRegister("ext led 2", LED_EXT_2, EXTRA_LED_2_PORT, EXTRA_LED_2_PIN);
// outputPinRegister("ext led 3", LED_EXT_3, EXTRA_LED_2_PORT, EXTRA_LED_3_PIN);
@ -192,10 +200,11 @@ void initOutputPins(void) {
outputPinRegister("MalfunctionIndicator", LED_CHECK_ENGINE, getHwPort(boardConfiguration->malfunctionIndicatorPin),
getHwPin(boardConfiguration->malfunctionIndicatorPin));
outputPinRegister("spi CS1", SPI_CS_1, SPI_CS1_PORT, SPI_CS1_PIN);
outputPinRegister("spi CS2", SPI_CS_2, SPI_CS2_PORT, SPI_CS2_PIN);
outputPinRegister("spi CS3", SPI_CS_3, SPI_CS3_PORT, SPI_CS3_PIN);
outputPinRegister("spi CS4", SPI_CS_4, SPI_CS4_PORT, SPI_CS4_PIN);
// todo: are these needed here? todo: make configurable
// outputPinRegister("spi CS1", SPI_CS_1, SPI_CS1_PORT, SPI_CS1_PIN);
// outputPinRegister("spi CS2", SPI_CS_2, SPI_CS2_PORT, SPI_CS2_PIN);
// outputPinRegister("spi CS3", SPI_CS_3, SPI_CS3_PORT, SPI_CS3_PIN);
// outputPinRegister("spi CS4", SPI_CS_4, SPI_CS4_PORT, SPI_CS4_PIN);
outputPinRegister("spi CS5", SPI_CS_SD_MODULE, SPI_SD_MODULE_PORT, SPI_SD_MODULE_PIN);
// todo: should we move this code closer to the fuel pump logic?

View File

@ -150,7 +150,7 @@ void lcd_HD44780_print_char(char data) {
}
}
void lcd_HD44780_print_string(char* string) {
void lcd_HD44780_print_string(const char* string) {
while (*string != 0x00)
lcd_HD44780_print_char(*string++);
}

View File

@ -16,7 +16,7 @@ extern "C"
void lcd_HD44780_init(void);
void lcd_HD44780_set_position(uint8_t row, uint8_t column);
void lcd_HD44780_print_char(char data);
void lcd_HD44780_print_string(char *string);
void lcd_HD44780_print_string(const char *string);
void lcdShowFatalMessage(char *message);

View File

@ -19,6 +19,7 @@
#include "mmc_card.h"
#include "pin_repository.h"
#include "ff.h"
#include "hardware.h"
#define PUSHPULLDELAY 500
@ -88,20 +89,24 @@ static void sdStatistics(void) {
* so that we can later append to that file
*/
static void createLogFile(void) {
lockSpi(SPI_NONE);
memset(&FDLogFile, 0, sizeof(FIL)); // clear the memory
FRESULT err = f_open(&FDLogFile, "rusefi.log", FA_OPEN_ALWAYS | FA_WRITE); // Create new file
if (err != FR_OK && err != FR_EXIST) {
unlockSpi();
printError("Card mounted...\r\nCan't create Log file, check your SD.\r\nFS mount failed", err); // else - show error
return;
}
err = f_lseek(&FDLogFile, f_size(&FDLogFile)); // Move to end of the file to append data
if (err) {
unlockSpi();
printError("Seek error", err);
return;
}
f_sync(&FDLogFile);
fs_ready = TRUE; // everything Ok
unlockSpi();
}
static void ff_cmd_dir(char *path) {
@ -163,11 +168,13 @@ void appendToLog(char *line) {
}
int lineLength = strlen(line);
totalLoggedBytes += lineLength;
lockSpi(SPI_NONE);
FRESULT err = f_write(&FDLogFile, line, lineLength, &bytesWrited);
if (bytesWrited < lineLength) {
printError("write error or disk full", err); // error or disk full
}
f_sync(&FDLogFile);
unlockSpi();
}
/*
@ -203,11 +210,14 @@ static void MMCmount(void) {
mmcStart(&MMCD1, &mmccfg); // Configures and activates the MMC peripheral.
// Performs the initialization procedure on the inserted card.
lockSpi(SPI_NONE);
if (mmcConnect(&MMCD1) != CH_SUCCESS) {
scheduleMsg(&logger, "Can't connect or mount MMC/SD");
warning(OBD_PCM_Processor_Fault, "Can't connect or mount MMC/SD");
unlockSpi();
return;
}
unlockSpi();
// if Ok - mount FS now
memset(&MMC_FS, 0, sizeof(FATFS)); // reserve the memory
if (f_mount(0, &MMC_FS) == FR_OK) {

View File

@ -44,7 +44,7 @@ void startSimplePwm(PwmConfig *state, const char *msg, io_pin_e ioPin,
state->outputPins[0] = ioPin;
state->periodMs = frequency2period(frequency);
state->periodUs = frequency2periodUs(frequency);
weComplexInit(msg, state, 2, switchTimes, 1, pinStates, NULL, applyPinState);
}

View File

@ -15,16 +15,16 @@
#include "gpio_helper.h"
void startSimplePwm(PwmConfig *state, const char *msg, io_pin_e ioPin,
float dutyCycle, float frequency);
void applyPinState(PwmConfig *state, int stateIndex);
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
void applyPinState(PwmConfig *state, int stateIndex);
void startSimplePwm(PwmConfig *state, const char *msg, io_pin_e ioPin,
float dutyCycle, float frequency);
void startSimplePwmExt(PwmConfig *state, const char *msg, brain_pin_e brainPin, io_pin_e ioPin,
float frequency, float dutyCycle);

View File

@ -8,7 +8,16 @@
#ifndef USBCONSOLE_H_
#define USBCONSOLE_H_
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
void usb_serial_start(void);
int is_usb_serial_ready(void);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* USBCONSOLE_H_ */

View File

@ -22,6 +22,7 @@ static WaveReaderHw primaryCrankInput;
static WaveReaderHw secondaryCrankInput;
extern engine_configuration_s *engineConfiguration;
extern engine_configuration2_s *engineConfiguration2;
extern board_configuration_s *boardConfiguration;
@ -39,7 +40,7 @@ static inline ICUDriver *getSecondaryInputCaptureDriver(void) {
*/
static void shaft_icu_width_callback(ICUDriver *icup) {
int isPrimary = icup == getPrimaryInputCaptureDriver();
if (!isPrimary && !engineConfiguration->needSecondTriggerInput)
if (!isPrimary && !engineConfiguration2->triggerShape.needSecondTriggerInput)
return;
// icucnt_t last_width = icuGetWidth(icup); so far we are fine with system time
trigger_event_e signal = isPrimary ? SHAFT_PRIMARY_UP : SHAFT_SECONDARY_UP;
@ -49,7 +50,7 @@ static void shaft_icu_width_callback(ICUDriver *icup) {
static void shaft_icu_period_callback(ICUDriver *icup) {
int isPrimary = icup == getPrimaryInputCaptureDriver();
if (!isPrimary && !engineConfiguration->needSecondTriggerInput)
if (!isPrimary && !engineConfiguration2->triggerShape.needSecondTriggerInput)
return;
// icucnt_t last_period = icuGetPeriod(icup); so far we are fine with system time

View File

@ -2034,13 +2034,13 @@
<group>
<name>tunerstudio</name>
<file>
<name>$PROJ_DIR$\..\console\tunerstudio\tunerstudio.c</name>
<name>$PROJ_DIR$\..\console\tunerstudio\tunerstudio.cpp</name>
</file>
<file>
<name>$PROJ_DIR$\..\console\tunerstudio\tunerstudio.h</name>
</file>
<file>
<name>$PROJ_DIR$\..\console\tunerstudio\tunerstudio_algo.c</name>
<name>$PROJ_DIR$\..\console\tunerstudio\tunerstudio_algo.cpp</name>
</file>
<file>
<name>$PROJ_DIR$\..\console\tunerstudio\tunerstudio_algo.h</name>
@ -2111,6 +2111,12 @@
<file>
<name>$PROJ_DIR$\..\controllers\algo\ec2.h</name>
</file>
<file>
<name>$PROJ_DIR$\..\controllers\algo\engine.cpp</name>
</file>
<file>
<name>$PROJ_DIR$\..\controllers\algo\engine.h</name>
</file>
<file>
<name>$PROJ_DIR$\..\controllers\algo\engine_configuration.cpp</name>
</file>
@ -2153,6 +2159,12 @@
<file>
<name>$PROJ_DIR$\..\controllers\algo\malfunction_central.h</name>
</file>
<file>
<name>$PROJ_DIR$\..\controllers\algo\map_adjuster.c</name>
</file>
<file>
<name>$PROJ_DIR$\..\controllers\algo\map_adjuster.h</name>
</file>
<file>
<name>$PROJ_DIR$\..\controllers\algo\nmea.c</name>
</file>
@ -2210,6 +2222,12 @@
<file>
<name>$PROJ_DIR$\..\controllers\core\signal_filtering.h</name>
</file>
<file>
<name>$PROJ_DIR$\..\controllers\core\table_helper.cpp</name>
</file>
<file>
<name>$PROJ_DIR$\..\controllers\core\table_helper.h</name>
</file>
</group>
<group>
<name>math</name>
@ -2450,6 +2468,12 @@
<name>emulation</name>
<group>
<name>hw_layer</name>
<file>
<name>$PROJ_DIR$\..\emulation\hw_layer\poten.c</name>
</file>
<file>
<name>$PROJ_DIR$\..\emulation\hw_layer\poten.h</name>
</file>
</group>
<group>
<name>test</name>

View File

@ -150,7 +150,7 @@ void runRusEfi(void) {
#endif
#if EFI_ENGINE_EMULATOR
initEngineEmulator();
initEngineEmulator(boardConfiguration);
#endif
startStatusThreads();
@ -253,5 +253,5 @@ void firmwareError(const char *fmt, ...) {
}
int getRusEfiVersion(void) {
return 20140709;
return 20140724;
}

View File

@ -1,5 +1,5 @@
// This file was generated by Version2Header
// Sat Jul 05 19:09:48 EDT 2014
#ifndef SVN_VERSION
#define SVN_VERSION 3860
// Wed Jul 23 08:21:40 EDT 2014
#ifndef VCS_VERSION
#define VCS_VERSION "4047"
#endif

View File

@ -1,6 +1,6 @@
; this is TunerStudio project for www.rusefi.com DIY engine management system
; version 20140706
; version 20140721
; this should stop TS from looking for the CAN ID in the 2nd byte location and allow the page reads to work correctly.
enable2ndByteCanID = false
@ -15,7 +15,7 @@ enable2ndByteCanID = false
endianness = little
nPages = 1
pageSize = 5804
pageSize = 5824
pageIdentifier = "\x00\x00"
pageReadCommand = "R\x00\x00%2o%2c"
@ -110,7 +110,7 @@ enable2ndByteCanID = false
fuelKeyBins = array, F32, 792, [16], "V", 1, 0, 0.0, 10.0, 2; size 132
fuelRpmBins = array, F32, 856, [16], "RPM", 1, 0, 0.0, 25500.0, 2; size 92
displacement = scalar, F32, 920, "°C", 1, 0, 0, 1000.0, 2 ; size 4
rpmHardLimit = scalar, U32, 924, "°C", 1, 0, 0, 1000.0, 2 ; size 4
rpmHardLimit = scalar, U32, 924, "°C", 1, 0, 0, 10000.0, 2 ; size 4
crankingInjectionMode = scalar, U32, 928, "°C", 1, 0, 0, 1000.0, 2 ; size 4
injectionMode = scalar, U32, 932, "°C", 1, 0, 0, 1000.0, 2 ; size 4
globalTriggerOffsetAngle = scalar, F32, 936, "RPM", 1, 0, 0, 720, 0 ; size 4
@ -135,7 +135,7 @@ enable2ndByteCanID = false
tpsAdcInput = bits, U32, 1012, [0:4] "PA0", "PA1", "PA2", "PA3", "PA4", "PA5", "PA6", "PA7", "PB0", "PB1", "PB0", "PB1", "PB2", "PB3", "PB4", "PB5"
overrideCrankingIgnition= scalar, F32, 1016, "RPM", 1, 0.0, 0, 1000.0, 2 ; size 4
analogChartFrequency = scalar, U32, 1020, "index", 1, 0, 0, 300, 0 ; size 4
trigger_type = bits, U32, 1024, [0:1], "toothed wheel", "ford aspire", "dodge neon", "INVALID"
trigger_type = bits, U32, 1024, [0:3], "custom toothed wheel", "ford aspire", "dodge neon", "Miata NA", "Miata NB", "GM_7X", "Cooper", "Escort GT", "60/2", "36/1", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID"
isSynchronizationNeeded = bits, U32, 1028, [0:0], "false", "true"
totalToothCount = scalar, F32, 1032, "RPM", 1, 0.0, 0, 1000.0, 2 ; size 4
skippedToothCount = scalar, F32, 1036, "RPM", 1, 0.0, 0, 1000.0, 2 ; size 4
@ -210,9 +210,30 @@ enable2ndByteCanID = false
electronicThrottlePin1 = bits, U32, 5612, [0:6], "GPIOA_0", "GPIOA_1", "GPIOA_2", "GPIOA_3", "GPIOA_4", "GPIOA_5", "GPIOA_6", "GPIOA_7", "GPIOA_8", "GPIOA_9", "GPIOA_10", "GPIOA_11", "GPIOA_12", "GPIOA_13", "GPIOA_14", "GPIOA_15", "GPIOB_0", "GPIOB_1", "GPIOB_2", "GPIOB_3", "GPIOB_4", "GPIOB_5", "GPIOB_6", "GPIOB_7", "GPIOB_8", "GPIOB_9", "GPIOB_10", "GPIOB_11", "GPIOB_12", "GPIOB_13", "GPIOB_14", "GPIOB_15", "GPIOC_0", "GPIOC_1", "GPIOC_2", "GPIOC_3", "GPIOC_4", "GPIOC_5", "GPIOC_6", "GPIOC_7", "GPIOC_8", "GPIOC_9", "GPIOC_10", "GPIOC_11", "GPIOC_12", "GPIOC_13", "GPIOC_14", "GPIOC_15", "GPIOD_0", "GPIOD_1", "GPIOD_2", "GPIOD_3", "GPIOD_4", "GPIOD_5", "GPIOD_6", "GPIOD_7", "GPIOD_8", "GPIOD_9", "GPIOD_10", "GPIOD_11", "GPIOD_12", "GPIOD_13", "GPIOD_14", "GPIOD_15", "GPIOE_0", "GPIOE_1", "GPIOE_2", "GPIOE_3", "GPIOE_4", "GPIOE_5", "GPIOE_6", "GPIOE_7", "GPIOE_8", "GPIOE_9", "GPIOE_10", "GPIOE_11", "GPIOE_12", "GPIOE_13", "GPIOE_14", "GPIOE_15", "NONE", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID"
electronicThrottlePin1Mode = bits, U32, 5616, [0:1], "default", "default inverted", "open", "open inverted"
; idleSwitchPin
idleSwitchPin = bits, U32, 5620, [0:6], "GPIOA_0", "GPIOA_1", "GPIOA_2", "GPIOA_3", "GPIOA_4", "GPIOA_5", "GPIOA_6", "GPIOA_7", "GPIOA_8", "GPIOA_9", "GPIOA_10", "GPIOA_11", "GPIOA_12", "GPIOA_13", "GPIOA_14", "GPIOA_15", "GPIOB_0", "GPIOB_1", "GPIOB_2", "GPIOB_3", "GPIOB_4", "GPIOB_5", "GPIOB_6", "GPIOB_7", "GPIOB_8", "GPIOB_9", "GPIOB_10", "GPIOB_11", "GPIOB_12", "GPIOB_13", "GPIOB_14", "GPIOB_15", "GPIOC_0", "GPIOC_1", "GPIOC_2", "GPIOC_3", "GPIOC_4", "GPIOC_5", "GPIOC_6", "GPIOC_7", "GPIOC_8", "GPIOC_9", "GPIOC_10", "GPIOC_11", "GPIOC_12", "GPIOC_13", "GPIOC_14", "GPIOC_15", "GPIOD_0", "GPIOD_1", "GPIOD_2", "GPIOD_3", "GPIOD_4", "GPIOD_5", "GPIOD_6", "GPIOD_7", "GPIOD_8", "GPIOD_9", "GPIOD_10", "GPIOD_11", "GPIOD_12", "GPIOD_13", "GPIOD_14", "GPIOD_15", "GPIOE_0", "GPIOE_1", "GPIOE_2", "GPIOE_3", "GPIOE_4", "GPIOE_5", "GPIOE_6", "GPIOE_7", "GPIOE_8", "GPIOE_9", "GPIOE_10", "GPIOE_11", "GPIOE_12", "GPIOE_13", "GPIOE_14", "GPIOE_15", "NONE", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID"
; idleSwitchPinMode
alternatorControlPin = bits, U32, 5628, [0:6], "GPIOA_0", "GPIOA_1", "GPIOA_2", "GPIOA_3", "GPIOA_4", "GPIOA_5", "GPIOA_6", "GPIOA_7", "GPIOA_8", "GPIOA_9", "GPIOA_10", "GPIOA_11", "GPIOA_12", "GPIOA_13", "GPIOA_14", "GPIOA_15", "GPIOB_0", "GPIOB_1", "GPIOB_2", "GPIOB_3", "GPIOB_4", "GPIOB_5", "GPIOB_6", "GPIOB_7", "GPIOB_8", "GPIOB_9", "GPIOB_10", "GPIOB_11", "GPIOB_12", "GPIOB_13", "GPIOB_14", "GPIOB_15", "GPIOC_0", "GPIOC_1", "GPIOC_2", "GPIOC_3", "GPIOC_4", "GPIOC_5", "GPIOC_6", "GPIOC_7", "GPIOC_8", "GPIOC_9", "GPIOC_10", "GPIOC_11", "GPIOC_12", "GPIOC_13", "GPIOC_14", "GPIOC_15", "GPIOD_0", "GPIOD_1", "GPIOD_2", "GPIOD_3", "GPIOD_4", "GPIOD_5", "GPIOD_6", "GPIOD_7", "GPIOD_8", "GPIOD_9", "GPIOD_10", "GPIOD_11", "GPIOD_12", "GPIOD_13", "GPIOD_14", "GPIOD_15", "GPIOE_0", "GPIOE_1", "GPIOE_2", "GPIOE_3", "GPIOE_4", "GPIOE_5", "GPIOE_6", "GPIOE_7", "GPIOE_8", "GPIOE_9", "GPIOE_10", "GPIOE_11", "GPIOE_12", "GPIOE_13", "GPIOE_14", "GPIOE_15", "NONE", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID"
; alternatorControlPinMode
;todo
HD44780_rs = bits, U32, 5636, [0:6], "GPIOA_0", "GPIOA_1", "GPIOA_2", "GPIOA_3", "GPIOA_4", "GPIOA_5", "GPIOA_6", "GPIOA_7", "GPIOA_8", "GPIOA_9", "GPIOA_10", "GPIOA_11", "GPIOA_12", "GPIOA_13", "GPIOA_14", "GPIOA_15", "GPIOB_0", "GPIOB_1", "GPIOB_2", "GPIOB_3", "GPIOB_4", "GPIOB_5", "GPIOB_6", "GPIOB_7", "GPIOB_8", "GPIOB_9", "GPIOB_10", "GPIOB_11", "GPIOB_12", "GPIOB_13", "GPIOB_14", "GPIOB_15", "GPIOC_0", "GPIOC_1", "GPIOC_2", "GPIOC_3", "GPIOC_4", "GPIOC_5", "GPIOC_6", "GPIOC_7", "GPIOC_8", "GPIOC_9", "GPIOC_10", "GPIOC_11", "GPIOC_12", "GPIOC_13", "GPIOC_14", "GPIOC_15", "GPIOD_0", "GPIOD_1", "GPIOD_2", "GPIOD_3", "GPIOD_4", "GPIOD_5", "GPIOD_6", "GPIOD_7", "GPIOD_8", "GPIOD_9", "GPIOD_10", "GPIOD_11", "GPIOD_12", "GPIOD_13", "GPIOD_14", "GPIOD_15", "GPIOE_0", "GPIOE_1", "GPIOE_2", "GPIOE_3", "GPIOE_4", "GPIOE_5", "GPIOE_6", "GPIOE_7", "GPIOE_8", "GPIOE_9", "GPIOE_10", "GPIOE_11", "GPIOE_12", "GPIOE_13", "GPIOE_14", "GPIOE_15", "NONE", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID"
HD44780_e = bits, U32, 5640, [0:6], "GPIOA_0", "GPIOA_1", "GPIOA_2", "GPIOA_3", "GPIOA_4", "GPIOA_5", "GPIOA_6", "GPIOA_7", "GPIOA_8", "GPIOA_9", "GPIOA_10", "GPIOA_11", "GPIOA_12", "GPIOA_13", "GPIOA_14", "GPIOA_15", "GPIOB_0", "GPIOB_1", "GPIOB_2", "GPIOB_3", "GPIOB_4", "GPIOB_5", "GPIOB_6", "GPIOB_7", "GPIOB_8", "GPIOB_9", "GPIOB_10", "GPIOB_11", "GPIOB_12", "GPIOB_13", "GPIOB_14", "GPIOB_15", "GPIOC_0", "GPIOC_1", "GPIOC_2", "GPIOC_3", "GPIOC_4", "GPIOC_5", "GPIOC_6", "GPIOC_7", "GPIOC_8", "GPIOC_9", "GPIOC_10", "GPIOC_11", "GPIOC_12", "GPIOC_13", "GPIOC_14", "GPIOC_15", "GPIOD_0", "GPIOD_1", "GPIOD_2", "GPIOD_3", "GPIOD_4", "GPIOD_5", "GPIOD_6", "GPIOD_7", "GPIOD_8", "GPIOD_9", "GPIOD_10", "GPIOD_11", "GPIOD_12", "GPIOD_13", "GPIOD_14", "GPIOD_15", "GPIOE_0", "GPIOE_1", "GPIOE_2", "GPIOE_3", "GPIOE_4", "GPIOE_5", "GPIOE_6", "GPIOE_7", "GPIOE_8", "GPIOE_9", "GPIOE_10", "GPIOE_11", "GPIOE_12", "GPIOE_13", "GPIOE_14", "GPIOE_15", "NONE", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID"
HD44780_db4 = bits, U32, 5644, [0:6], "GPIOA_0", "GPIOA_1", "GPIOA_2", "GPIOA_3", "GPIOA_4", "GPIOA_5", "GPIOA_6", "GPIOA_7", "GPIOA_8", "GPIOA_9", "GPIOA_10", "GPIOA_11", "GPIOA_12", "GPIOA_13", "GPIOA_14", "GPIOA_15", "GPIOB_0", "GPIOB_1", "GPIOB_2", "GPIOB_3", "GPIOB_4", "GPIOB_5", "GPIOB_6", "GPIOB_7", "GPIOB_8", "GPIOB_9", "GPIOB_10", "GPIOB_11", "GPIOB_12", "GPIOB_13", "GPIOB_14", "GPIOB_15", "GPIOC_0", "GPIOC_1", "GPIOC_2", "GPIOC_3", "GPIOC_4", "GPIOC_5", "GPIOC_6", "GPIOC_7", "GPIOC_8", "GPIOC_9", "GPIOC_10", "GPIOC_11", "GPIOC_12", "GPIOC_13", "GPIOC_14", "GPIOC_15", "GPIOD_0", "GPIOD_1", "GPIOD_2", "GPIOD_3", "GPIOD_4", "GPIOD_5", "GPIOD_6", "GPIOD_7", "GPIOD_8", "GPIOD_9", "GPIOD_10", "GPIOD_11", "GPIOD_12", "GPIOD_13", "GPIOD_14", "GPIOD_15", "GPIOE_0", "GPIOE_1", "GPIOE_2", "GPIOE_3", "GPIOE_4", "GPIOE_5", "GPIOE_6", "GPIOE_7", "GPIOE_8", "GPIOE_9", "GPIOE_10", "GPIOE_11", "GPIOE_12", "GPIOE_13", "GPIOE_14", "GPIOE_15", "NONE", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID"
HD44780_db5 = bits, U32, 5648, [0:6], "GPIOA_0", "GPIOA_1", "GPIOA_2", "GPIOA_3", "GPIOA_4", "GPIOA_5", "GPIOA_6", "GPIOA_7", "GPIOA_8", "GPIOA_9", "GPIOA_10", "GPIOA_11", "GPIOA_12", "GPIOA_13", "GPIOA_14", "GPIOA_15", "GPIOB_0", "GPIOB_1", "GPIOB_2", "GPIOB_3", "GPIOB_4", "GPIOB_5", "GPIOB_6", "GPIOB_7", "GPIOB_8", "GPIOB_9", "GPIOB_10", "GPIOB_11", "GPIOB_12", "GPIOB_13", "GPIOB_14", "GPIOB_15", "GPIOC_0", "GPIOC_1", "GPIOC_2", "GPIOC_3", "GPIOC_4", "GPIOC_5", "GPIOC_6", "GPIOC_7", "GPIOC_8", "GPIOC_9", "GPIOC_10", "GPIOC_11", "GPIOC_12", "GPIOC_13", "GPIOC_14", "GPIOC_15", "GPIOD_0", "GPIOD_1", "GPIOD_2", "GPIOD_3", "GPIOD_4", "GPIOD_5", "GPIOD_6", "GPIOD_7", "GPIOD_8", "GPIOD_9", "GPIOD_10", "GPIOD_11", "GPIOD_12", "GPIOD_13", "GPIOD_14", "GPIOD_15", "GPIOE_0", "GPIOE_1", "GPIOE_2", "GPIOE_3", "GPIOE_4", "GPIOE_5", "GPIOE_6", "GPIOE_7", "GPIOE_8", "GPIOE_9", "GPIOE_10", "GPIOE_11", "GPIOE_12", "GPIOE_13", "GPIOE_14", "GPIOE_15", "NONE", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID"
HD44780_db6 = bits, U32, 5652, [0:6], "GPIOA_0", "GPIOA_1", "GPIOA_2", "GPIOA_3", "GPIOA_4", "GPIOA_5", "GPIOA_6", "GPIOA_7", "GPIOA_8", "GPIOA_9", "GPIOA_10", "GPIOA_11", "GPIOA_12", "GPIOA_13", "GPIOA_14", "GPIOA_15", "GPIOB_0", "GPIOB_1", "GPIOB_2", "GPIOB_3", "GPIOB_4", "GPIOB_5", "GPIOB_6", "GPIOB_7", "GPIOB_8", "GPIOB_9", "GPIOB_10", "GPIOB_11", "GPIOB_12", "GPIOB_13", "GPIOB_14", "GPIOB_15", "GPIOC_0", "GPIOC_1", "GPIOC_2", "GPIOC_3", "GPIOC_4", "GPIOC_5", "GPIOC_6", "GPIOC_7", "GPIOC_8", "GPIOC_9", "GPIOC_10", "GPIOC_11", "GPIOC_12", "GPIOC_13", "GPIOC_14", "GPIOC_15", "GPIOD_0", "GPIOD_1", "GPIOD_2", "GPIOD_3", "GPIOD_4", "GPIOD_5", "GPIOD_6", "GPIOD_7", "GPIOD_8", "GPIOD_9", "GPIOD_10", "GPIOD_11", "GPIOD_12", "GPIOD_13", "GPIOD_14", "GPIOD_15", "GPIOE_0", "GPIOE_1", "GPIOE_2", "GPIOE_3", "GPIOE_4", "GPIOE_5", "GPIOE_6", "GPIOE_7", "GPIOE_8", "GPIOE_9", "GPIOE_10", "GPIOE_11", "GPIOE_12", "GPIOE_13", "GPIOE_14", "GPIOE_15", "NONE", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID"
HD44780_db7 = bits, U32, 5656, [0:6], "GPIOA_0", "GPIOA_1", "GPIOA_2", "GPIOA_3", "GPIOA_4", "GPIOA_5", "GPIOA_6", "GPIOA_7", "GPIOA_8", "GPIOA_9", "GPIOA_10", "GPIOA_11", "GPIOA_12", "GPIOA_13", "GPIOA_14", "GPIOA_15", "GPIOB_0", "GPIOB_1", "GPIOB_2", "GPIOB_3", "GPIOB_4", "GPIOB_5", "GPIOB_6", "GPIOB_7", "GPIOB_8", "GPIOB_9", "GPIOB_10", "GPIOB_11", "GPIOB_12", "GPIOB_13", "GPIOB_14", "GPIOB_15", "GPIOC_0", "GPIOC_1", "GPIOC_2", "GPIOC_3", "GPIOC_4", "GPIOC_5", "GPIOC_6", "GPIOC_7", "GPIOC_8", "GPIOC_9", "GPIOC_10", "GPIOC_11", "GPIOC_12", "GPIOC_13", "GPIOC_14", "GPIOC_15", "GPIOD_0", "GPIOD_1", "GPIOD_2", "GPIOD_3", "GPIOD_4", "GPIOD_5", "GPIOD_6", "GPIOD_7", "GPIOD_8", "GPIOD_9", "GPIOD_10", "GPIOD_11", "GPIOD_12", "GPIOD_13", "GPIOD_14", "GPIOD_15", "GPIOE_0", "GPIOE_1", "GPIOE_2", "GPIOE_3", "GPIOE_4", "GPIOE_5", "GPIOE_6", "GPIOE_7", "GPIOE_8", "GPIOE_9", "GPIOE_10", "GPIOE_11", "GPIOE_12", "GPIOE_13", "GPIOE_14", "GPIOE_15", "NONE", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID"
;triggerSimulatorPin0
;triggerSimulatorPin1
;triggerSimulatorPinModes
digitalPotentiometerSpiDevice=bits,U32, 5676, [0:1], "Off", "SPI1", "SPI2", "SPI3"
digitalPotentiometerChipSelect0=bits,U32, 5680, [0:6], "GPIOA_0", "GPIOA_1", "GPIOA_2", "GPIOA_3", "GPIOA_4", "GPIOA_5", "GPIOA_6", "GPIOA_7", "GPIOA_8", "GPIOA_9", "GPIOA_10", "GPIOA_11", "GPIOA_12", "GPIOA_13", "GPIOA_14", "GPIOA_15", "GPIOB_0", "GPIOB_1", "GPIOB_2", "GPIOB_3", "GPIOB_4", "GPIOB_5", "GPIOB_6", "GPIOB_7", "GPIOB_8", "GPIOB_9", "GPIOB_10", "GPIOB_11", "GPIOB_12", "GPIOB_13", "GPIOB_14", "GPIOB_15", "GPIOC_0", "GPIOC_1", "GPIOC_2", "GPIOC_3", "GPIOC_4", "GPIOC_5", "GPIOC_6", "GPIOC_7", "GPIOC_8", "GPIOC_9", "GPIOC_10", "GPIOC_11", "GPIOC_12", "GPIOC_13", "GPIOC_14", "GPIOC_15", "GPIOD_0", "GPIOD_1", "GPIOD_2", "GPIOD_3", "GPIOD_4", "GPIOD_5", "GPIOD_6", "GPIOD_7", "GPIOD_8", "GPIOD_9", "GPIOD_10", "GPIOD_11", "GPIOD_12", "GPIOD_13", "GPIOD_14", "GPIOD_15", "GPIOE_0", "GPIOE_1", "GPIOE_2", "GPIOE_3", "GPIOE_4", "GPIOE_5", "GPIOE_6", "GPIOE_7", "GPIOE_8", "GPIOE_9", "GPIOE_10", "GPIOE_11", "GPIOE_12", "GPIOE_13", "GPIOE_14", "GPIOE_15", "NONE", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID"
digitalPotentiometerChipSelect1=bits,U32, 5684, [0:6], "GPIOA_0", "GPIOA_1", "GPIOA_2", "GPIOA_3", "GPIOA_4", "GPIOA_5", "GPIOA_6", "GPIOA_7", "GPIOA_8", "GPIOA_9", "GPIOA_10", "GPIOA_11", "GPIOA_12", "GPIOA_13", "GPIOA_14", "GPIOA_15", "GPIOB_0", "GPIOB_1", "GPIOB_2", "GPIOB_3", "GPIOB_4", "GPIOB_5", "GPIOB_6", "GPIOB_7", "GPIOB_8", "GPIOB_9", "GPIOB_10", "GPIOB_11", "GPIOB_12", "GPIOB_13", "GPIOB_14", "GPIOB_15", "GPIOC_0", "GPIOC_1", "GPIOC_2", "GPIOC_3", "GPIOC_4", "GPIOC_5", "GPIOC_6", "GPIOC_7", "GPIOC_8", "GPIOC_9", "GPIOC_10", "GPIOC_11", "GPIOC_12", "GPIOC_13", "GPIOC_14", "GPIOC_15", "GPIOD_0", "GPIOD_1", "GPIOD_2", "GPIOD_3", "GPIOD_4", "GPIOD_5", "GPIOD_6", "GPIOD_7", "GPIOD_8", "GPIOD_9", "GPIOD_10", "GPIOD_11", "GPIOD_12", "GPIOD_13", "GPIOD_14", "GPIOD_15", "GPIOE_0", "GPIOE_1", "GPIOE_2", "GPIOE_3", "GPIOE_4", "GPIOE_5", "GPIOE_6", "GPIOE_7", "GPIOE_8", "GPIOE_9", "GPIOE_10", "GPIOE_11", "GPIOE_12", "GPIOE_13", "GPIOE_14", "GPIOE_15", "NONE", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID"
digitalPotentiometerChipSelect2=bits,U32, 5688, [0:6], "GPIOA_0", "GPIOA_1", "GPIOA_2", "GPIOA_3", "GPIOA_4", "GPIOA_5", "GPIOA_6", "GPIOA_7", "GPIOA_8", "GPIOA_9", "GPIOA_10", "GPIOA_11", "GPIOA_12", "GPIOA_13", "GPIOA_14", "GPIOA_15", "GPIOB_0", "GPIOB_1", "GPIOB_2", "GPIOB_3", "GPIOB_4", "GPIOB_5", "GPIOB_6", "GPIOB_7", "GPIOB_8", "GPIOB_9", "GPIOB_10", "GPIOB_11", "GPIOB_12", "GPIOB_13", "GPIOB_14", "GPIOB_15", "GPIOC_0", "GPIOC_1", "GPIOC_2", "GPIOC_3", "GPIOC_4", "GPIOC_5", "GPIOC_6", "GPIOC_7", "GPIOC_8", "GPIOC_9", "GPIOC_10", "GPIOC_11", "GPIOC_12", "GPIOC_13", "GPIOC_14", "GPIOC_15", "GPIOD_0", "GPIOD_1", "GPIOD_2", "GPIOD_3", "GPIOD_4", "GPIOD_5", "GPIOD_6", "GPIOD_7", "GPIOD_8", "GPIOD_9", "GPIOD_10", "GPIOD_11", "GPIOD_12", "GPIOD_13", "GPIOD_14", "GPIOD_15", "GPIOE_0", "GPIOE_1", "GPIOE_2", "GPIOE_3", "GPIOE_4", "GPIOE_5", "GPIOE_6", "GPIOE_7", "GPIOE_8", "GPIOE_9", "GPIOE_10", "GPIOE_11", "GPIOE_12", "GPIOE_13", "GPIOE_14", "GPIOE_15", "NONE", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID"
digitalPotentiometerChipSelect3=bits,U32, 5692, [0:6], "GPIOA_0", "GPIOA_1", "GPIOA_2", "GPIOA_3", "GPIOA_4", "GPIOA_5", "GPIOA_6", "GPIOA_7", "GPIOA_8", "GPIOA_9", "GPIOA_10", "GPIOA_11", "GPIOA_12", "GPIOA_13", "GPIOA_14", "GPIOA_15", "GPIOB_0", "GPIOB_1", "GPIOB_2", "GPIOB_3", "GPIOB_4", "GPIOB_5", "GPIOB_6", "GPIOB_7", "GPIOB_8", "GPIOB_9", "GPIOB_10", "GPIOB_11", "GPIOB_12", "GPIOB_13", "GPIOB_14", "GPIOB_15", "GPIOC_0", "GPIOC_1", "GPIOC_2", "GPIOC_3", "GPIOC_4", "GPIOC_5", "GPIOC_6", "GPIOC_7", "GPIOC_8", "GPIOC_9", "GPIOC_10", "GPIOC_11", "GPIOC_12", "GPIOC_13", "GPIOC_14", "GPIOC_15", "GPIOD_0", "GPIOD_1", "GPIOD_2", "GPIOD_3", "GPIOD_4", "GPIOD_5", "GPIOD_6", "GPIOD_7", "GPIOD_8", "GPIOD_9", "GPIOD_10", "GPIOD_11", "GPIOD_12", "GPIOD_13", "GPIOD_14", "GPIOD_15", "GPIOE_0", "GPIOE_1", "GPIOE_2", "GPIOE_3", "GPIOE_4", "GPIOE_5", "GPIOE_6", "GPIOE_7", "GPIOE_8", "GPIOE_9", "GPIOE_10", "GPIOE_11", "GPIOE_12", "GPIOE_13", "GPIOE_14", "GPIOE_15", "NONE", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID"
adcModePA0 = bits, U32, 5696, [0:1], "Off", "Slow", "Fast", "INVALID"
adcModePA1 = bits, U32, 5700, [0:1], "Off", "Slow", "Fast", "INVALID"
adcModePA2 = bits, U32, 5704, [0:1], "Off", "Slow", "Fast", "INVALID"
@ -409,12 +430,14 @@ enable2ndByteCanID = false
menu = "&Engine"
subMenu = engineChars, "&Engine Characteristics"
subMenu = lcdScreen, "LCD screen"
subMenu = boardInputs, "&Board inputs"
subMenu = boardInputMode, "Board inputs mode"
subMenu = boardOutputs1, "Board outputs #1"
subMenu = boardOutputs2, "Board outputs #2"
subMenu = injChars, "&injector Characteristicks"
subMenu = injectorsDeadTime, "&Injectors Dead Time"
subMenu = ecuStimulator, "ECU stimulator"
menu = "&Sensors"
subMenu = clt_thermistor, "&CLT Thermistor"
subMenu = iat_thermistor, "&IAT Thermistor"
@ -471,9 +494,17 @@ enable2ndByteCanID = false
field = "Ignition Mode", IgnitionMode
field = "Firing Order", FiringOrder
field = "rpm Multiplier", rpmMultiplier
field = "display Mode", displayMode
field = "log format", logFormat
dialog = lcdScreen, "LCD screen"
field = "display Mode", displayMode
field = "RS pin", HD44780_rs
field = "E pin", HD44780_e
field = "D4 pin", HD44780_db4
field = "D5 pin", HD44780_db5
field = "D6 pin", HD44780_db6
field = "D7 pin", HD44780_db7
dialog = boardInputs, "Board inputs"
field = "Analog Input Divider Coefficient", analogInputDividerCoefficient
field = "Battery Input Divider Coefficient", VBattDividerCoefficient
@ -503,6 +534,12 @@ enable2ndByteCanID = false
field = "ADC on PC4", adcModePC4
field = "ADC on PC5", adcModePC5
dialog = ecuStimulator, "ECU stimulator"
field = "digipot spi", digitalPotentiometerSpiDevice
field = "digipot CS #0", digitalPotentiometerChipSelect0
field = "digipot CS #1", digitalPotentiometerChipSelect1
field = "digipot CS #2", digitalPotentiometerChipSelect2
field = "digipot CS #3", digitalPotentiometerChipSelect3
dialog = boardOutputs1, "Board properties #1"
field = "Injection Pin 1", injectionPin1
@ -585,13 +622,13 @@ enable2ndByteCanID = false
dialog = triggerConfiguration, "Trigger configuration"
field = "trigger type", trigger_type
field = "Synchronization Needed?", isSynchronizationNeeded
field = "total Tooth Count", totalToothCount
field = "skipped Tooth Count", skippedToothCount
field = "sync Ratio From", syncRatioFrom
field = "sync Ratio To", syncRatioTo
field = "use Rise Edge?", useRiseEdge
field = "needed Second Trigger Input?", needSecondTriggerInput
field = "Synchronization Needed?", isSynchronizationNeeded, {trigger_type == 0}
field = "total Tooth Count", totalToothCount, {trigger_type == 0}
field = "skipped Tooth Count", skippedToothCount, {trigger_type == 0}
field = "sync Ratio From", syncRatioFrom, {trigger_type == 0}
field = "sync Ratio To", syncRatioTo, {trigger_type == 0}
field = "use Rise Edge?", useRiseEdge, {trigger_type == 0}
field = "needed Second Trigger Input?", needSecondTriggerInput, {trigger_type == 0}
dialog = crankingFuel, "Cranking Fuel"

View File

@ -11,7 +11,11 @@
#include "stdint.h"
// number of milliseconds in one period of given frequency (per second)
#define frequency2period(freq) (((float)1000) / (freq))
#define frequency2periodMs(freq) ((1000.0f) / (freq))
// number of microseconds in one period of given frequency (per second)
#define frequency2periodUs(freq) ((1000000.0f) / (freq))
#ifndef FALSE
#define FALSE 0