diff --git a/firmware/config/stm32f4ems/efifeatures.h b/firmware/config/stm32f4ems/efifeatures.h index cf1896f869..939986ae33 100644 --- a/firmware/config/stm32f4ems/efifeatures.h +++ b/firmware/config/stm32f4ems/efifeatures.h @@ -45,17 +45,16 @@ */ #define EFI_WAVE_ANALYZER TRUE -//#define SERIAL_SPEED (8 * 115200) -//#define SERIAL_SPEED (2 * 115200) -//todo: make this configurable via Tuner Studio -//todo: see uartConsoleSerialSpeed -#define SERIAL_SPEED 115200 - /** * TunerStudio support. */ #define EFI_TUNER_STUDIO TRUE +/** + * Bluetooth UART setup support. + */ +#define EFI_BLUETOOTH_SETUP FALSE + /** * TunerStudio debug output */ diff --git a/firmware/console/binary/bluetooth.cpp b/firmware/console/binary/bluetooth.cpp new file mode 100644 index 0000000000..a160af4f70 --- /dev/null +++ b/firmware/console/binary/bluetooth.cpp @@ -0,0 +1,276 @@ +#include "main.h" + +#include "engine_state.h" +#include "tunerstudio.h" + +#include "tunerstudio_io.h" +#include "bluetooth.h" +#include "engine_configuration.h" + +#if EFI_BLUETOOTH_SETUP || defined(__DOXYGEN__) + +static bool btProcessIsStarted = false; +static bool btProcessIsRunning = false; +static const char *commands[5]; +static int numCommands = 0; +static int setBaudIdx = -1; + +static char cmdHello[5]; +static char cmdBaud[25]; +static char cmdName[30]; +static char cmdPin[16]; + +static const int baudRates[] = { 0, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200, -1 }; +static const int baudRateIndexList[] = { 4 /*9600*/, 6 /*38400*/, 8 /*115200*/, 7, 5, 3, 2, 1, -1 }; +static const int btModuleTimeout = MS2ST(1000); + +static ts_channel_s *tsChannel; + + +static THD_WORKING_AREA(btThreadStack, UTILITY_THREAD_STACK_SIZE); +static thread_t *btThread = NULL; +static thread_reference_t btThreadRef = NULL; // used by thread suspend/resume as a flag + +static LoggingWithStorage btLogger("bluetooth"); + + +EXTERN_ENGINE +; + + +// Main communication code +// We assume that the user has disconnected the software before starting the code. +static void runCommands() { + uint8_t buffer[2]; + + if (!btProcessIsStarted) + return; + + // Store current serial port speed - we're going to change it + int savedSerialSpeed = boardConfiguration->tunerStudioSerialSpeed; + + int prevBaudIdx = -1, baudIdx = -1, baudListIdx = 0; + int cmdIdx = 0; + + // run all commands + while (true) { + if (baudIdx < 0) { + // try all available baud rates, in order of preference + baudIdx = baudRateIndexList[baudListIdx++]; + // we've tried all baud rates? + if (baudIdx < 0) + break; + } + + bool restoreAndExit = (cmdIdx >= numCommands || baudIdx < 0); + + // if the baud rate is changed, reinit the UART + if (baudIdx != prevBaudIdx || restoreAndExit) { + // deinit UART + if (!stopTsPort(tsChannel)) { + scheduleMsg(&btLogger, "Failed! Cannot restart serial port connection!"); + return; + } + chThdSleepMilliseconds(10); // safety + // change the port speed + boardConfiguration->tunerStudioSerialSpeed = restoreAndExit ? savedSerialSpeed : baudRates[baudIdx]; + // init UART + startTsPort(tsChannel); + chThdSleepMilliseconds(10); // safety + prevBaudIdx = baudIdx; + } + + // exit if all commands were sent + if (restoreAndExit) + break; + + // send current command + sr5WriteData(tsChannel, (uint8_t *)commands[cmdIdx], strlen(commands[cmdIdx])); + + // waiting for an answer + bool wasAnswer = false; + if (sr5ReadDataTimeout(tsChannel, buffer, 2, btModuleTimeout) == 2) { + wasAnswer = (buffer[0] == 'O' && buffer[1] == 'K'); + } + + // wait 1 second and skip all remaining response bytes from the bluetooth module + while (true) { + if (sr5ReadDataTimeout(tsChannel, buffer, 1, btModuleTimeout) < 1) + break; + } + + if (wasAnswer) { + // if we changed the baud rate + if (commands[cmdIdx] == cmdBaud) { + // this is what we've set + baudIdx = setBaudIdx; + // if we fail somehow, try all other baud rates + baudListIdx = 0; + } + // move to the next command + cmdIdx++; + } else { + // try other baud rate + baudIdx = -1; + } + } + + // the connection is already restored to the current baud rate, so print the result + if (cmdIdx == numCommands) + scheduleMsg(&btLogger, "SUCCESS! All commands (%d of %d) passed to the Bluetooth module!", cmdIdx, numCommands); + else + scheduleMsg(&btLogger, "FAIL! Only %d commands (of %d total) were passed to the Bluetooth module!", cmdIdx, numCommands); +} + +static THD_FUNCTION(btThreadEntryPoint, arg) { + (void) arg; + chRegSetThreadName("bluetooth thread"); + + scheduleMsg(&btLogger, "*** Bluetooth module setup procedure ***"); + scheduleMsg(&btLogger, "!Warning! Please make sure you're not currently using the BT module for communication (not paired)!"); + scheduleMsg(&btLogger, "TO START THE PROCEDURE: PLEASE DISCONNECT YOUR PC COM-PORT FROM THE BOARD NOW!"); + scheduleMsg(&btLogger, "After that please don't turn off the board power and wait for ~15 seconds to complete. Then reconnect to the board!"); + + // now wait + chSysLock(); + msg_t msg = chThdSuspendTimeoutS(&btThreadRef, BLUETOOTH_COMMAND_TIMEOUT); + chSysUnlock(); + + if (msg == MSG_TIMEOUT) { + scheduleMsg(&btLogger, "The Bluetooth module init procedure is cancelled (timeout)!"); + return; + } else { + // call this when the thread is resumed (after the disconnect) + btProcessIsRunning = true; + runCommands(); + btProcessIsRunning = false; + } + + // release the command + btProcessIsStarted = false; + chThdExit(MSG_OK); +} + +void bluetoothStart(ts_channel_s *tsChan, bluetooth_module_e moduleType, const char *baudRate, const char *name, const char *pinCode) { + static const char *usage = "Usage: bluetooth_hc06 "; + + tsChannel = tsChan; + + // if a binary protocol uses USB, we cannot init the bluetooth module! + if (!boardConfiguration->useSerialPort) { + scheduleMsg(&btLogger, "Failed! Serial Port connection is disabled!"); + return; + } + + if (btProcessIsStarted) { + scheduleMsg(&btLogger, "The Bluetooth module init procedure is already started and waiting! To cancel it, run \"bluetooth_cancel\" command!"); + return; + } + + numCommands = 0; + + // now check the arguments and add other commands: + // 1) baud rate + int baud = (baudRate != NULL) ? atoi(baudRate) : 0; + int i; + // find a known baud rate in our list + setBaudIdx = -1; + for (i = 1; baudRates[i] > 0; i++) { + if (baudRates[i] == baud) { + setBaudIdx = i; + break; + } + } + // check the baud rate index + if (setBaudIdx < 1) { + if (baud == 0) + scheduleMsg(&btLogger, "The parameter is set to zero! The baud rate won't be set!"); + else { + // unknown baud rate + scheduleMsg(&btLogger, "Wrong parameter '%s'! %s", baudRate, usage); + return; + } + } else { + // ok, add command! + + } + + // 2) check name + if (name == NULL || strlen(name) < 1 || strlen(name) > 20) { + scheduleMsg(&btLogger, "Wrong parameter! Up to 20 characters expected! %s", usage); + return; + } + + // 3) check pin code + int numDigits = 0; + // check the pincode + if (pinCode != NULL && strlen(pinCode) == 4) { + for (i = 0; i < 4; i++) { + if (pinCode[i] >= '0' && pinCode[i] <= '9') // digit + numDigits++; + } + } + if (numDigits != 4) { + scheduleMsg(&btLogger, "Wrong parameter! 4 digits expected! %s", usage); + return; + } + + // ok, add commands! + switch (moduleType) { + case BLUETOOTH_HC_05: + chsnprintf(cmdHello, sizeof(cmdHello), "AT\r\n"); + chsnprintf(cmdBaud, sizeof(cmdBaud), "AT+UART=%d,0,0\r\n", baud); // baud rate, 0=(1 stop bit), 0=(no parity bits) + chsnprintf(cmdName, sizeof(cmdName), "AT+NAME=%s\r\n", name); + chsnprintf(cmdPin, sizeof(cmdPin), "AT+PSWD=%s\r\n", pinCode); + // todo: add more commands? + // AT+RMAAD + // AT+ROLE=0 + break; + case BLUETOOTH_HC_06: + chsnprintf(cmdHello, sizeof(cmdHello), "AT"); + chsnprintf(cmdBaud, sizeof(cmdBaud), "AT+BAUD%c", '0' + setBaudIdx); + chsnprintf(cmdName, sizeof(cmdName), "AT+NAME%s", name); + chsnprintf(cmdPin, sizeof(cmdPin), "AT+PIN%s", pinCode); + break; + default: + // todo: add support for other BT module types + scheduleMsg(&btLogger, "This Bluetooth module is currently not supported!"); + return; + } + commands[numCommands++] = cmdHello; // this command is added to test a connection + commands[numCommands++] = cmdBaud; + commands[numCommands++] = cmdName; + commands[numCommands++] = cmdPin; + + // create a thread to execute these commands later + btThread = chThdCreateStatic(btThreadStack, sizeof(btThreadStack), NORMALPRIO, (tfunc_t)btThreadEntryPoint, NULL); + + btProcessIsStarted = true; +} + +void bluetoothSoftwareDisconnectNotify() { + if (btProcessIsStarted) { + // start communication with the module + chThdResume(&btThreadRef, MSG_OK); + // wait the thread to finish + chThdWait(btThread); + } +} + +void bluetoothCancel() { + if (!btProcessIsStarted) { + scheduleMsg(&btLogger, "The Bluetooth module init procedure was not started! Nothing to cancel!"); + return; + } + + if (btProcessIsRunning) + return; + + // terminate thread + chThdTerminate(btThread); + + btProcessIsStarted = false; + scheduleMsg(&btLogger, "The Bluetooth module init procedure is cancelled!"); +} + +#endif /* EFI_BLUETOOTH_SETUP */ diff --git a/firmware/console/binary/bluetooth.h b/firmware/console/binary/bluetooth.h new file mode 100644 index 0000000000..1ee4415b87 --- /dev/null +++ b/firmware/console/binary/bluetooth.h @@ -0,0 +1,46 @@ +/** + * @file tunerstudio.h + * + * @date Aug 26, 2013 + * @author Andrey Belomutskiy, (c) 2012-2017 + */ + +#ifndef BLUETOOTH_H_ +#define BLUETOOTH_H_ + +#include "main.h" +#include "tunerstudio_io.h" + + +// The Bluetooth setup procedure will wait 10 seconds for the user to disconnect the UART cable. +// This is required because the BT setup procedure reads a response from the module during the communication. +// Thus any bytes sent from the Console Software may interfere with the procedure. +#define BLUETOOTH_COMMAND_TIMEOUT MS2ST(10000) + +// Supported Bluetooth module types +typedef enum { + BLUETOOTH_HC_05, + BLUETOOTH_HC_06, +} bluetooth_module_e; + +/** + * Start Bluetooth module initialization using UART connection: + * - wait for PC communication disconnect; + * - reconfigure the UART; + * - send AT-commands to the module; + * - restore connection to PC. + */ +void bluetoothStart(ts_channel_s *tsChannel, bluetooth_module_e moduleType, const char *baudRate, const char *name, const char *pinCode); + +/** + * Cancel Bluetooth procedure + */ +void bluetoothCancel(void); + +/** + * Called by runBinaryProtocolLoop() if a connection disconnect is detected. + * Bluetooth init code needs to make sure that there's no interference of the BT module and USB-UART (connected to PC) + */ +void bluetoothSoftwareDisconnectNotify(); + +#endif /* BLUETOOTH_H_ */ diff --git a/firmware/console/binary/bluetooth_readme.txt b/firmware/console/binary/bluetooth_readme.txt new file mode 100644 index 0000000000..9c0831b352 --- /dev/null +++ b/firmware/console/binary/bluetooth_readme.txt @@ -0,0 +1,38 @@ +Bluetooth module setup procedure. User Manual. + +To activate your Bluetooth module, you'll need: +1) Connect your PC to the rusEFI board using UART cable. +2) Run "rusEFI Console" software. +3) Turn on the board power and wait for the console connection. +4) Type the following command: + "bluetooth_hc06 " + Where: + - is the baud rate of the Bluetooth connection. Allowed values are: 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200. + Please set this to the baud rate currently used by your UART console. + - is the name of your Bluetooth connection. It will be visible in the device list on your PC. + - is 4-digit PIN-code needed to authorize the Bluetooth connection to your PC. + Example: "bluetooth_hc06 38400 rusefi 1234" +5) After entering the command the following text will appear: + *** Bluetooth module setup procedure *** + !Warning! Please make sure you're not currently using the BT module for communication (not paired)! + TO START THE PROCEDURE: PLEASE DISCONNECT YOUR PC COM-PORT FROM THE BOARD NOW! + After that please don't turn off the board power and wait for ~15 seconds to complete. Then reconnect to the board! +6) If you ignore this message and do nothing, the Bluetooth secup procedure will be cancelled in 10 seconds. + You can also use "bluetooth_cancel" command to cancel it. +7) If you disconnect the UART cable or close the software, then the procedure will begin. +8) It takes up to 15 seconds to complete. The Bluetooth LED may blink several times during the procedure - it's normal. +9) After that, you may restore the UART connection to your PC or start using Bluetooth module. + + +*** Developers Section *** + +How it works, in two words: +- adds 2 new commands: "bluetooth_hc06(baud, name, pincode)" and "bluetooth_cancel"; +- adds stopTsPort() to tunerstudio_io - needed to change the baud rate on fly; +- added bluetoothSoftwareDisconnectNotify() handler to runBinaryProtocolLoop() - to detect UART disconnects; +- added a thread with btThreadEntryPoint(): + - It will wait up to 10 seconds for the user to disconnect the UART cable. + This is required because the BT setup procedure reads a response from the module during the communication - using the same UART. + Thus any bytes sent from the Console Software may interfere with the procedure. +- added bluetoothStart() which processes user input and creates a command list; +- added runCommands() where all the Bluetooth magic happens! diff --git a/firmware/console/binary/tunerstudio.cpp b/firmware/console/binary/tunerstudio.cpp index 8f3e603417..945704c24d 100644 --- a/firmware/console/binary/tunerstudio.cpp +++ b/firmware/console/binary/tunerstudio.cpp @@ -73,6 +73,7 @@ #include "console_io.h" #include "crc.h" #include "fl_protocol.h" +#include "bluetooth.h" #include #include "engine_configuration.h" @@ -167,6 +168,17 @@ static void setTsSpeed(int value) { printTsStats(); } +#if EFI_BLUETOOTH_SETUP || defined(__DOXYGEN__) +// Bluetooth HC-05 module initialization start (it waits for disconnect and then communicates to the module) +static void bluetoothHC05(const char *baudRate, const char *name, const char *pinCode) { + bluetoothStart(&tsChannel, BLUETOOTH_HC_05, baudRate, name, pinCode); +} +// Bluetooth HC-06 module initialization start (it waits for disconnect and then communicates to the module) +static void bluetoothHC06(const char *baudRate, const char *name, const char *pinCode) { + bluetoothStart(&tsChannel, BLUETOOTH_HC_06, baudRate, name, pinCode); +} +#endif /* EFI_BLUETOOTH_SETUP */ + void tunerStudioDebug(const char *msg) { #if EFI_TUNER_STUDIO_VERBOSE || defined(__DOXYGEN__) scheduleMsg(&tsLogger, "%s", msg); @@ -452,6 +464,10 @@ void runBinaryProtocolLoop(ts_channel_s *tsChannel, bool isConsoleRedirect) { if (received != 1) { // tunerStudioError("ERROR: no command"); +#if EFI_BLUETOOTH_SETUP || defined(__DOXYGEN__) + // assume there's connection loss and notify the bluetooth init code + bluetoothSoftwareDisconnectNotify(); +#endif /* EFI_BLUETOOTH_SETUP */ continue; } onDataArrived(); @@ -828,6 +844,14 @@ void startTunerStudioConnectivity(void) { addConsoleAction("tsinfo", printTsStats); addConsoleAction("reset_ts", resetTs); addConsoleActionI("set_ts_speed", setTsSpeed); + +#if EFI_BLUETOOTH_SETUP || defined(__DOXYGEN__) + // Usage: "bluetooth_hc06 " + // Example: "bluetooth_hc06 38400 rusefi 1234" + addConsoleActionSSS("bluetooth_hc05", bluetoothHC05); + addConsoleActionSSS("bluetooth_hc06", bluetoothHC06); + addConsoleAction("bluetooth_cancel", bluetoothCancel); +#endif /* EFI_BLUETOOTH_SETUP */ chThdCreateStatic(tsThreadStack, sizeof(tsThreadStack), NORMALPRIO, (tfunc_t)tsThreadEntryPoint, NULL); } diff --git a/firmware/console/binary/tunerstudio.mk b/firmware/console/binary/tunerstudio.mk index 6620966dd2..0126d71c85 100644 --- a/firmware/console/binary/tunerstudio.mk +++ b/firmware/console/binary/tunerstudio.mk @@ -1,3 +1,4 @@ TUNERSTUDIO_SRC_CPP = $(PROJECT_DIR)/console/binary/tunerstudio_io.cpp \ - $(PROJECT_DIR)/console/binary/tunerstudio.cpp + $(PROJECT_DIR)/console/binary/tunerstudio.cpp \ + $(PROJECT_DIR)/console/binary/bluetooth.cpp diff --git a/firmware/console/binary/tunerstudio_configuration.h b/firmware/console/binary/tunerstudio_configuration.h index 569e04c574..8f2ed09265 100644 --- a/firmware/console/binary/tunerstudio_configuration.h +++ b/firmware/console/binary/tunerstudio_configuration.h @@ -82,6 +82,7 @@ typedef struct { unsigned int isTriggerError : 1; // bit 5 unsigned int hasFatalError : 1; // bit 6 unsigned int isWarnNow : 1; // bit 7 + unsigned int isCltBroken : 1; // bit 8 int tsConfigVersion; // 84 egt_values_s egtValues; // 88 float unusedOffset104; // 104 diff --git a/firmware/console/binary/tunerstudio_io.cpp b/firmware/console/binary/tunerstudio_io.cpp index b18e2e4883..79d3bbbb79 100644 --- a/firmware/console/binary/tunerstudio_io.cpp +++ b/firmware/console/binary/tunerstudio_io.cpp @@ -124,6 +124,36 @@ void startTsPort(ts_channel_s *tsChannel) { #endif /* EFI_PROD_CODE */ } +bool stopTsPort(ts_channel_s *tsChannel) { +#if EFI_PROD_CODE || defined(__DOXYGEN__) +#if EFI_USB_SERIAL || defined(__DOXYGEN__) + if (isCommandLineConsoleOverTTL()) { +#if 0 + usb_serial_stop(); +#endif + // don't stop USB! + return false; + } else +#endif + { + if (boardConfiguration->useSerialPort) { + // todo: disable Rx/Tx pads? +#if TS_UART_DMA_MODE + uartStop(TS_DMA_UART_DEVICE); +#else + sdStop(TS_SERIAL_UART_DEVICE); +#endif /* TS_UART_DMA_MODE */ + } + } + + tsChannel->channel = (BaseChannel *) NULL; + return true; +#else /* EFI_PROD_CODE */ + // don't stop simulator! + return false; +#endif /* EFI_PROD_CODE */ +} + void sr5WriteData(ts_channel_s *tsChannel, const uint8_t * buffer, int size) { efiAssertVoid(getRemainingStack(chThdGetSelfX()) > 64, "tunerStudioWriteData"); #if EFI_SIMULATOR || defined(__DOXYGEN__) diff --git a/firmware/console/binary/tunerstudio_io.h b/firmware/console/binary/tunerstudio_io.h index d7e2bd69b2..b34a3ae9b1 100644 --- a/firmware/console/binary/tunerstudio_io.h +++ b/firmware/console/binary/tunerstudio_io.h @@ -90,6 +90,7 @@ typedef struct { void startTsPort(ts_channel_s *tsChannel); +bool stopTsPort(ts_channel_s *tsChannel); // that's 1 second #define BINARY_IO_TIMEOUT MS2ST(1000) diff --git a/firmware/console/console_io.cpp b/firmware/console/console_io.cpp index 62958600c2..467e7e33c1 100644 --- a/firmware/console/console_io.cpp +++ b/firmware/console/console_io.cpp @@ -138,7 +138,7 @@ bool isCommandLineConsoleOverTTL(void) { } #if (defined(EFI_CONSOLE_UART_DEVICE) && ! EFI_SIMULATOR ) || defined(__DOXYGEN__) -static SerialConfig serialConfig = { SERIAL_SPEED, 0, USART_CR2_STOP1_BITS | USART_CR2_LINEN, 0 }; +static SerialConfig serialConfig = { 0, 0, USART_CR2_STOP1_BITS | USART_CR2_LINEN, 0 }; #endif bool consoleInBinaryMode = false; @@ -256,9 +256,10 @@ void startConsole(Logging *sharedLogger, CommandHandler console_line_callback_p) if (isCommandLineConsoleOverTTL()) { /* - * Activates the serial using the driver default configuration (that's 38400) + * Activates the serial * it is important to set 'NONE' as flow control! in terminal application on the PC */ + serialConfig.speed = engineConfiguration->uartConsoleSerialSpeed; sdStart(EFI_CONSOLE_UART_DEVICE, &serialConfig); // cannot use pin repository here because pin repository prints to console diff --git a/firmware/console/eficonsole.cpp b/firmware/console/eficonsole.cpp index 17922b9324..decfc9f883 100644 --- a/firmware/console/eficonsole.cpp +++ b/firmware/console/eficonsole.cpp @@ -56,9 +56,6 @@ static void sayHello(void) { #ifdef CH_FREQUENCY scheduleMsg(&logger, "CH_FREQUENCY=%d", CH_FREQUENCY); #endif -#ifdef SERIAL_SPEED - scheduleMsg(&logger, "SERIAL_SPEED=%d", SERIAL_SPEED); -#endif #ifdef CORTEX_MAX_KERNEL_PRIORITY scheduleMsg(&logger, "CORTEX_MAX_KERNEL_PRIORITY=%d", CORTEX_MAX_KERNEL_PRIORITY); diff --git a/firmware/console/status_loop.cpp b/firmware/console/status_loop.cpp index c607f4d343..eb4dc6e5b4 100644 --- a/firmware/console/status_loop.cpp +++ b/firmware/console/status_loop.cpp @@ -432,6 +432,7 @@ static void printInfo(systime_t nowSeconds) { static systime_t timeOfPreviousReport = (systime_t) -1; extern fatal_msg_t errorMessageBuffer; +extern bool consoleInBinaryMode; /** * @brief Sends all pending data to dev console @@ -442,7 +443,9 @@ void updateDevConsoleState(void) { } // looks like this is not needed anymore // checkIfShouldHalt(); - printPending(); + if (!consoleInBinaryMode) { + printPending(); + } /** * this should go before the firmware error so that console can detect connection @@ -731,6 +734,7 @@ void updateTunerStudioState(TunerStudioOutputChannels *tsOutputChannels DECLARE_ tsOutputChannels->firmwareVersion = getRusEfiVersion(); tsOutputChannels->isWarnNow = isWarningNow(now, true); + tsOutputChannels->isCltBroken = engine->isCltBroken; if (engineConfiguration->debugMode == DBG_TPS_ACCEL) { tsOutputChannels->debugIntField1 = engine->tpsAccelEnrichment.cb.getSize(); diff --git a/firmware/controllers/algo/engine_configuration.cpp b/firmware/controllers/algo/engine_configuration.cpp index ee699e0397..3e023aa3ea 100644 --- a/firmware/controllers/algo/engine_configuration.cpp +++ b/firmware/controllers/algo/engine_configuration.cpp @@ -693,6 +693,9 @@ void setDefaultConfiguration(DECLARE_ENGINE_PARAMETER_SIGNATURE) { engineConfiguration->cranking.baseFuel = 5; + engineConfiguration->idleRpmPid.pFactor = 0.05; + engineConfiguration->idleRpmPid.iFactor = 0.002; + engineConfiguration->idleRpmPid.minValue = 5; engineConfiguration->idleRpmPid.maxValue = 95; boardConfiguration->idlePidDeactivationTpsThreshold = 2; diff --git a/firmware/controllers/core/fsio_core.cpp b/firmware/controllers/core/fsio_core.cpp index a56cbffe97..830076d681 100644 --- a/firmware/controllers/core/fsio_core.cpp +++ b/firmware/controllers/core/fsio_core.cpp @@ -28,6 +28,7 @@ extern fsio8_Map3D_u8t fsioTable4; static fsio8_Map3D_u8t * fsio8t_tables[] = {NULL, NULL, &fsioTable2, &fsioTable3, &fsioTable4}; +EXTERN_ENGINE; LENameOrdinalPair * LE_FIRST = NULL; @@ -75,12 +76,6 @@ void LEElement::clear() { iValue = 0; } - -//void LEElement::init(le_action_e action, int iValue) { -// this->action = action; -// this->iValue = iValue; -//} - void LEElement::init(le_action_e action) { this->action = action; } @@ -142,7 +137,7 @@ void LECalculator::push(le_action_e action, float value) { /** * @return true in case of error, false otherwise */ -bool LECalculator::processElement(Engine *engine, LEElement *element) { +bool LECalculator::processElement(LEElement *element DECLARE_ENGINE_PARAMETER_SUFFIX) { #if EFI_PROD_CODE || defined(__DOXYGEN__) efiAssert(getRemainingStack(chThdGetSelfX()) > 64, "FSIO logic", false); #endif @@ -258,7 +253,7 @@ bool LECalculator::processElement(Engine *engine, LEElement *element) { float humanIndex = pop(LE_METHOD_FSIO_SETTING); int index = (int) humanIndex - 1; if (index >= 0 && index < LE_COMMAND_COUNT) { - push(element->action, engine->engineConfiguration->bc.fsio_setting[index]); + push(element->action, boardConfiguration->fsio_setting[index]); } else { push(element->action, NAN); } @@ -285,7 +280,7 @@ bool LECalculator::processElement(Engine *engine, LEElement *element) { } break; case LE_METHOD_FSIO_ANALOG_INPUT: - push(element->action, getVoltage("fsio", engine->engineConfiguration->fsioAdc[0])); + push(element->action, getVoltage("fsio", engineConfiguration->fsioAdc[0])); break; case LE_METHOD_KNOCK: push(element->action, engine->knockCount); @@ -294,21 +289,21 @@ bool LECalculator::processElement(Engine *engine, LEElement *element) { warning(CUSTOM_UNKNOWN_FSIO, "FSIO undefined action"); return true; default: - push(element->action, getLEValue(engine, &stack, element->action)); + push(element->action, getEngineValue(element->action PASS_ENGINE_PARAMETER_SUFFIX)); } return false; } -float LECalculator::getValue2(float selfValue, LEElement *fistElementInList, Engine *engine) { +float LECalculator::getValue2(float selfValue, LEElement *fistElementInList DECLARE_ENGINE_PARAMETER_SUFFIX) { reset(fistElementInList); - return getValue(selfValue, engine); + return getValue(selfValue PASS_ENGINE_PARAMETER_SUFFIX); } bool LECalculator::isEmpty() { return first == NULL; } -float LECalculator::getValue(float selfValue, Engine *engine) { +float LECalculator::getValue(float selfValue DECLARE_ENGINE_PARAMETER_SUFFIX) { if (isEmpty()) { warning(CUSTOM_NO_FSIO, "no FSIO code"); return NAN; @@ -324,7 +319,7 @@ float LECalculator::getValue(float selfValue, Engine *engine) { if (element->action == LE_METHOD_SELF) { push(element->action, selfValue); } else { - bool isError = processElement(engine, element); + bool isError = processElement(element PASS_ENGINE_PARAMETER_SUFFIX); if (isError) { // error already reported return NAN; @@ -432,7 +427,7 @@ LEElement *LEElementPool::parseExpression(const char * line) { /** * Cannot recognize token */ - warning((obd_code_e) 0, "unrecognized [%s]", parsingBuffer); + warning(CUSTOM_ERR_6536, "unrecognized [%s]", parsingBuffer); return NULL; } n->init(action); diff --git a/firmware/controllers/core/fsio_core.h b/firmware/controllers/core/fsio_core.h index ba4630184c..6ac2650887 100644 --- a/firmware/controllers/core/fsio_core.h +++ b/firmware/controllers/core/fsio_core.h @@ -52,6 +52,7 @@ typedef enum { LE_METHOD_FSIO_ANALOG_INPUT = 116, LE_METHOD_INTAKE_VVT = 117, LE_METHOD_EXHAUST_VVT = 118, + LE_METHOD_IS_COOLANT_BROKEN = 119, Force_4b_le_action = ENUM_32_BITS, @@ -95,8 +96,8 @@ typedef FLStack calc_stack_t; class LECalculator { public: LECalculator(); - float getValue(float selfValue, Engine *engine); - float getValue2(float selfValue, LEElement *fistElementInList, Engine *engine); + float getValue(float selfValue DECLARE_ENGINE_PARAMETER_SUFFIX); + float getValue2(float selfValue, LEElement *fistElementInList DECLARE_ENGINE_PARAMETER_SUFFIX); void add(LEElement *element); bool isEmpty(); void reset(); @@ -106,7 +107,7 @@ public: int currentCalculationLogPosition; private: void push(le_action_e action, float value); - bool processElement(Engine *engine, LEElement *element); + bool processElement(LEElement *element DECLARE_ENGINE_PARAMETER_SUFFIX); float pop(le_action_e action); LEElement *first; calc_stack_t stack; diff --git a/firmware/controllers/core/fsio_impl.cpp b/firmware/controllers/core/fsio_impl.cpp index e5b717e313..6e79f9e31e 100644 --- a/firmware/controllers/core/fsio_impl.cpp +++ b/firmware/controllers/core/fsio_impl.cpp @@ -33,6 +33,7 @@ static LENameOrdinalPair leMap(LE_METHOD_MAP, "map"); static LENameOrdinalPair leVBatt(LE_METHOD_VBATT, "vbatt"); static LENameOrdinalPair leFan(LE_METHOD_FAN, "fan"); static LENameOrdinalPair leCoolant(LE_METHOD_COOLANT, "coolant"); +static LENameOrdinalPair leIsCoolantBroken(LE_METHOD_IS_COOLANT_BROKEN, "is_clt_broken"); static LENameOrdinalPair leAcToggle(LE_METHOD_AC_TOGGLE, "ac_on_switch"); static LENameOrdinalPair leFanOnSetting(LE_METHOD_FAN_ON_SETTING, "fan_on_setting"); static LENameOrdinalPair leFanOffSetting(LE_METHOD_FAN_OFF_SETTING, "fan_off_setting"); @@ -73,8 +74,7 @@ EXTERN_ENGINE #if EFI_PROD_CODE || EFI_SIMULATOR static Logging *logger; -float getLEValue(Engine *engine, calc_stack_t *s, le_action_e action) { - engine_configuration_s *engineConfiguration = engine->engineConfiguration; +float getEngineValue(le_action_e action DECLARE_ENGINE_PARAMETER_SUFFIX) { efiAssert(engine!=NULL, "getLEValue", NAN); switch (action) { case LE_METHOD_FAN: @@ -83,6 +83,8 @@ float getLEValue(Engine *engine, calc_stack_t *s, le_action_e action) { return getAcToggle(PASS_ENGINE_PARAMETER_SIGNATURE); case LE_METHOD_COOLANT: return getCoolantTemperature(PASS_ENGINE_PARAMETER_SIGNATURE); + case LE_METHOD_IS_COOLANT_BROKEN: + return engine->isCltBroken; case LE_METHOD_INTAKE_AIR: return getIntakeAirTemperature(PASS_ENGINE_PARAMETER_SIGNATURE); case LE_METHOD_RPM: @@ -261,7 +263,7 @@ static void handleFsio(Engine *engine, int index) { warning(CUSTOM_NO_FSIO, "no FSIO for #%d %s", index + 1, hwPortname(boardConfiguration->fsioPins[index])); fvalue = NAN; } else { - fvalue = calc.getValue2(engine->fsioLastValue[index], fsioLogics[index], engine); + fvalue = calc.getValue2(engine->fsioLastValue[index], fsioLogics[index] PASS_ENGINE_PARAMETER_SUFFIX); } engine->fsioLastValue[index] = fvalue; @@ -298,11 +300,11 @@ static const char * action2String(le_action_e action) { return buffer; } -static void setPinState(const char * msg, OutputPin *pin, LEElement *element, Engine *engine) { +static void setPinState(const char * msg, OutputPin *pin, LEElement *element) { if (element == NULL) { warning(CUSTOM_OBD_11, "invalid expression for %s", msg); } else { - int value = (int)calc.getValue2(pin->getLogicValue(), element, engine); + int value = (int)calc.getValue2(pin->getLogicValue(), element PASS_ENGINE_PARAMETER_SUFFIX); if (pin->isInitialized() && value != pin->getLogicValue()) { if (isRunningBenchTest()) { return; // let's not mess with bench testing @@ -339,7 +341,7 @@ void runFsio(void) { #if EFI_FUEL_PUMP || defined(__DOXYGEN__) if (boardConfiguration->fuelPumpPin != GPIO_UNASSIGNED) { - setPinState("pump", &enginePins.fuelPumpRelay, fuelPumpLogic, engine); + setPinState("pump", &enginePins.fuelPumpRelay, fuelPumpLogic); } #endif /* EFI_FUEL_PUMP */ @@ -352,7 +354,7 @@ void runFsio(void) { enginePins.o2heater.setValue(engine->rpmCalculator.isRunning()); if (boardConfiguration->acRelayPin != GPIO_UNASSIGNED) { - setPinState("A/C", &enginePins.acRelay, acRelayLogic, engine); + setPinState("A/C", &enginePins.acRelay, acRelayLogic); } // if (boardConfiguration->alternatorControlPin != GPIO_UNASSIGNED) { @@ -360,7 +362,7 @@ void runFsio(void) { // } if (boardConfiguration->fanPin != GPIO_UNASSIGNED) { - setPinState("fan", &enginePins.fanRelay, radiatorFanLogic, engine); + setPinState("fan", &enginePins.fanRelay, radiatorFanLogic); } } @@ -465,7 +467,7 @@ static void setFsioExpression(const char *indexStr, const char *quotedLine, Engi #endif } -static void rpnEval(char *line, Engine *engine) { +static void rpnEval(char *line) { #if EFI_PROD_CODE || EFI_SIMULATOR line = unquote(line); scheduleMsg(logger, "Parsing [%s]", line); @@ -474,7 +476,7 @@ static void rpnEval(char *line, Engine *engine) { if (e == NULL) { scheduleMsg(logger, "parsing failed"); } else { - float result = evalCalc.getValue2(0, e, engine); + float result = evalCalc.getValue2(0, e PASS_ENGINE_PARAMETER_SUFFIX); scheduleMsg(logger, "Evaluate result: %f", result); } #endif @@ -527,11 +529,11 @@ void initFsioImpl(Logging *sharedLogger DECLARE_ENGINE_PARAMETER_SUFFIX) { #endif /* EFI_PROD_CODE */ #if EFI_PROD_CODE || EFI_SIMULATOR - addConsoleActionSSP("set_rpn_expression", (VoidCharPtrCharPtrVoidPtr) setFsioExpression, engine); + addConsoleActionSS("set_rpn_expression", (VoidCharPtrCharPtr) setFsioExpression); addConsoleActionFF("set_fsio_setting", setFsioSetting); addConsoleAction("fsioinfo", showFsioInfo); - addConsoleActionSP("rpn_eval", (VoidCharPtrVoidPtr) rpnEval, engine); -#endif + addConsoleActionS("rpn_eval", (VoidCharPtr) rpnEval); +#endif /* EFI_PROD_CODE || EFI_SIMULATOR */ fsioTable1.init(config->fsioTable1, config->fsioTable1LoadBins, config->fsioTable1RpmBins); diff --git a/firmware/controllers/core/fsio_impl.h b/firmware/controllers/core/fsio_impl.h index 742f6c42f1..90fbb7a918 100644 --- a/firmware/controllers/core/fsio_impl.h +++ b/firmware/controllers/core/fsio_impl.h @@ -18,7 +18,7 @@ typedef Map3D fsio8_Map3D_f32t; typedef Map3D fsio8_Map3D_u8t; -float getLEValue(Engine *engine, calc_stack_t *s, le_action_e action); +float getEngineValue(le_action_e action DECLARE_ENGINE_PARAMETER_SUFFIX); void setFsio(int index, brain_pin_e pin, const char * exp DECLARE_ENGINE_PARAMETER_SUFFIX); void setFsioExt(int index, brain_pin_e pin, const char * exp, int freq DECLARE_ENGINE_PARAMETER_SUFFIX); diff --git a/firmware/controllers/error_handling.cpp b/firmware/controllers/error_handling.cpp index 1b47996135..3f7c4fe011 100644 --- a/firmware/controllers/error_handling.cpp +++ b/firmware/controllers/error_handling.cpp @@ -171,9 +171,9 @@ void onUnlockHook(void) { if (lockedDuration > maxLockedDuration) { maxLockedDuration = lockedDuration; } -// if (t > 2800) { +// if (lockedDuration > 2800) { // // un-comment this if you want a nice stop for a breakpoint -// maxLockTime = t + 1; +// maxLockedDuration = lockedDuration + 1; // } } diff --git a/firmware/controllers/idle_thread.cpp b/firmware/controllers/idle_thread.cpp index 76265138bb..49dbb617f9 100644 --- a/firmware/controllers/idle_thread.cpp +++ b/firmware/controllers/idle_thread.cpp @@ -63,7 +63,6 @@ void idleDebug(const char *msg, percent_t value) { scheduleMsg(logger, "idle debug: %s%f", msg, value); } - static void showIdleInfo(void) { const char * idleModeStr = getIdle_mode_e(engineConfiguration->idleMode); scheduleMsg(logger, "idleMode=%s position=%f isStepper=%s", idleModeStr, @@ -150,14 +149,8 @@ static void undoIdleBlipIfNeeded() { } } -static percent_t currentIdleValve = -1; - percent_t getIdlePosition(void) { - if (engineConfiguration->idleMode == IM_AUTO) { - return currentIdleValve; - } else { - return boardConfiguration->manIdlePosition; - } + return currentIdlePosition; } static float autoIdle(float cltCorrection) { diff --git a/firmware/controllers/injector_central.cpp b/firmware/controllers/injector_central.cpp index 1ab40cc700..193fec45e1 100644 --- a/firmware/controllers/injector_central.cpp +++ b/firmware/controllers/injector_central.cpp @@ -39,13 +39,15 @@ EXTERN_ENGINE static Logging * logger; static bool isRunningBench = false; +// todo: move into Engine object? +// todo: looks like these flags are not currently used? dead functionality? unfinished functionality? static int is_injector_enabled[INJECTION_PIN_COUNT]; bool isRunningBenchTest(void) { return isRunningBench; } -void assertCylinderId(int cylinderId, const char *msg) { +static void assertCylinderId(int cylinderId, const char *msg) { int isValid = cylinderId >= 1 && cylinderId <= engineConfiguration->specs.cylindersCount; if (!isValid) { // we are here only in case of a fatal issue - at this point it is fine to make some blocking i-o @@ -58,12 +60,12 @@ void assertCylinderId(int cylinderId, const char *msg) { /** * @param cylinderId - from 1 to NUMBER_OF_CYLINDERS */ -int isInjectorEnabled(int cylinderId) { +static int isInjectorEnabled(int cylinderId) { assertCylinderId(cylinderId, "isInjectorEnabled"); return is_injector_enabled[cylinderId - 1]; } -static void printStatus(void) { +static void printInjectorsStatus(void) { for (int id = 1; id <= engineConfiguration->specs.cylindersCount; id++) { scheduleMsg(logger, "injector_%d_%d", isInjectorEnabled(id)); } @@ -72,7 +74,7 @@ static void printStatus(void) { static void setInjectorEnabled(int id, int value) { efiAssertVoid(id >= 0 && id < engineConfiguration->specs.cylindersCount, "injector id"); is_injector_enabled[id] = value; - printStatus(); + printInjectorsStatus(); } static void runBench(brain_pin_e brainPin, OutputPin *output, float delayMs, float onTimeMs, float offTimeMs, @@ -222,63 +224,11 @@ static msg_t benchThread(int param) { #endif } -static void unregister(brain_pin_e currentPin, OutputPin *output) { - if (currentPin == GPIO_UNASSIGNED) - return; - scheduleMsg(logger, "unregistering %s", hwPortname(currentPin)); - unmarkPin(currentPin); - output->unregister(); -} - -void unregisterOutput(brain_pin_e oldPin, brain_pin_e newPin, OutputPin *output) { - if (oldPin != newPin) { - unregister(oldPin, output); - } -} - -void stopIgnitionPins(void) { - for (int i = 0; i < IGNITION_PIN_COUNT; i++) { - NamedOutputPin *output = &enginePins.coils[i]; - unregisterOutput(activeConfiguration.bc.ignitionPins[i], - engineConfiguration->bc.ignitionPins[i], output); - } -} - -void stopInjectionPins(void) { - for (int i = 0; i < INJECTION_PIN_COUNT; i++) { - NamedOutputPin *output = &enginePins.injectors[i]; - unregisterOutput(activeConfiguration.bc.injectionPins[i], - engineConfiguration->bc.injectionPins[i], output); - } -} - -void startIgnitionPins(void) { - for (int i = 0; i < engineConfiguration->specs.cylindersCount; i++) { - NamedOutputPin *output = &enginePins.coils[i]; - // todo: we need to check if mode has changed - if (boardConfiguration->ignitionPins[i] != activeConfiguration.bc.ignitionPins[i]) { - output->initPin(output->name, boardConfiguration->ignitionPins[i], - &boardConfiguration->ignitionPinMode); - } - } - // todo: we need to check if mode has changed - if (engineConfiguration->dizzySparkOutputPin != activeConfiguration.dizzySparkOutputPin) { - enginePins.dizzyOutput.initPin("dizzy tach", engineConfiguration->dizzySparkOutputPin, - &engineConfiguration->dizzySparkOutputPinMode); - - } -} - -void startInjectionPins(void) { - // todo: should we move this code closer to the injection logic? - for (int i = 0; i < engineConfiguration->specs.cylindersCount; i++) { - NamedOutputPin *output = &enginePins.injectors[i]; - // todo: we need to check if mode has changed - if (engineConfiguration->bc.injectionPins[i] != activeConfiguration.bc.injectionPins[i]) { - - output->initPin(output->name, boardConfiguration->injectionPins[i], - &boardConfiguration->injectionPinMode); - } +void OutputPin::unregisterOutput(brain_pin_e oldPin, brain_pin_e newPin) { + if (oldPin != GPIO_UNASSIGNED && oldPin != newPin) { + scheduleMsg(logger, "unregistering %s", hwPortname(oldPin)); + unmarkPin(oldPin); + unregister(); } } @@ -304,14 +254,14 @@ void initInjectorCentral(Logging *sharedLogger) { logger = sharedLogger; chThdCreateStatic(benchThreadStack, sizeof(benchThreadStack), NORMALPRIO, (tfunc_t) benchThread, NULL); - for (int i = 0; i < engineConfiguration->specs.cylindersCount; i++) { + for (int i = 0; i < INJECTION_PIN_COUNT; i++) { is_injector_enabled[i] = true; } - startInjectionPins(); - startIgnitionPins(); + enginePins.startInjectionPins(); + enginePins.startIgnitionPins(); - printStatus(); + printInjectorsStatus(); addConsoleActionII("injector", setInjectorEnabled); addConsoleAction("fuelpumpbench", fuelPumpBench); diff --git a/firmware/controllers/injector_central.h b/firmware/controllers/injector_central.h index 91182857c0..06663ce228 100644 --- a/firmware/controllers/injector_central.h +++ b/firmware/controllers/injector_central.h @@ -19,15 +19,7 @@ void fuelPumpBench(void); void milBench(void); void initInjectorCentral(Logging *sharedLogger); bool isRunningBenchTest(void); -int isInjectorEnabled(int cylinderId); -void assertCylinderId(int cylinderId, const char *msg); -void stopInjectionPins(void); -void startInjectionPins(void); -void unregisterOutput(brain_pin_e oldPin, brain_pin_e newPin, OutputPin *output); - -void stopIgnitionPins(void); -void startIgnitionPins(void); void runIoTest(int subsystem, int index); #endif /* INJECTOR_CENTRAL_H_ */ diff --git a/firmware/controllers/math/pid.cpp b/firmware/controllers/math/pid.cpp index e28585fea8..d62b68f551 100644 --- a/firmware/controllers/math/pid.cpp +++ b/firmware/controllers/math/pid.cpp @@ -27,8 +27,11 @@ void Pid::init(pid_s *pid) { } bool Pid::isSame(pid_s *pid) { - return this->pid->dFactor == pid->dFactor && this->pid->iFactor == pid->iFactor && - this->pid->offset == pid->offset && this->pid->pFactor == pid->pFactor; + return this->pid->pFactor == pid->pFactor + && this->pid->iFactor == pid->iFactor + && this->pid->dFactor == pid->dFactor + && this->pid->offset == pid->offset + && this->pid->period == pid->period; } float Pid::getValue(float target, float input) { @@ -53,8 +56,9 @@ float Pid::getValue(float target, float input, float dTime) { if (iTerm > pid->maxValue) iTerm = pid->maxValue; - if (iTerm < pid->minValue) - iTerm = pid->minValue; + // this is kind of a hack. a proper fix would be having separate additional settings 'maxIValue' and 'minIValye' + if (iTerm < -pid->maxValue) + iTerm = -pid->maxValue; float result = pTerm + iTerm + dTerm + pid->offset; if (result > pid->maxValue) { diff --git a/firmware/controllers/system/efiGpio.cpp b/firmware/controllers/system/efiGpio.cpp index f5fba659d1..e81f8e6f34 100644 --- a/firmware/controllers/system/efiGpio.cpp +++ b/firmware/controllers/system/efiGpio.cpp @@ -50,8 +50,7 @@ EnginePins::EnginePins() { * Sets the value of the pin. On this layer the value is assigned as is, without any conversion. */ -#if EFI_PROD_CODE \ - +#if EFI_PROD_CODE #define setPinValue(outputPin, electricalValue, logicValue) \ { \ if ((outputPin)->currentLogicValue != (logicValue)) { \ @@ -79,6 +78,41 @@ bool EnginePins::stopPins() { return result; } +void EnginePins::unregisterPins() { +#if EFI_PROD_CODE || defined(__DOXYGEN__) + fuelPumpRelay.unregisterOutput(activeConfiguration.bc.fuelPumpPin, engineConfiguration->bc.fuelPumpPin); + fanRelay.unregisterOutput(activeConfiguration.bc.fanPin, engineConfiguration->bc.fanPin); + hipCs.unregisterOutput(activeConfiguration.bc.hip9011CsPin, engineConfiguration->bc.hip9011CsPin); + triggerDecoderErrorPin.unregisterOutput(activeConfiguration.bc.triggerErrorPin, + engineConfiguration->bc.triggerErrorPin); + + sdCsPin.unregisterOutput(activeConfiguration.bc.sdCardCsPin, engineConfiguration->bc.sdCardCsPin); + etbOutput1.unregisterOutput(activeConfiguration.bc.etbDirectionPin1, + engineConfiguration->bc.etbDirectionPin1); + etbOutput2.unregisterOutput(activeConfiguration.bc.etbDirectionPin2, + engineConfiguration->bc.etbDirectionPin2); + checkEnginePin.unregisterOutput(activeConfiguration.bc.malfunctionIndicatorPin, + engineConfiguration->bc.malfunctionIndicatorPin); + dizzyOutput.unregisterOutput(activeConfiguration.dizzySparkOutputPin, + engineConfiguration->dizzySparkOutputPin); + tachOut.unregisterOutput(activeConfiguration.bc.tachOutputPin, + engineConfiguration->bc.tachOutputPin); + idleSolenoidPin.unregisterOutput(activeConfiguration.bc.idle.solenoidPin, + engineConfiguration->bc.idle.solenoidPin); + + for (int i = 0;i < LE_COMMAND_COUNT;i++) { + fsioOutputs[i].unregisterOutput(activeConfiguration.bc.fsioPins[i], + engineConfiguration->bc.fsioPins[i]); + } + + alternatorPin.unregisterOutput(activeConfiguration.bc.alternatorControlPin, + engineConfiguration->bc.alternatorControlPin); + mainRelay.unregisterOutput(activeConfiguration.bc.mainRelayPin, + engineConfiguration->bc.mainRelayPin); + +#endif /* EFI_PROD_CODE */ +} + void EnginePins::reset() { for (int i = 0; i < INJECTION_PIN_COUNT;i++) { injectors[i].reset(); @@ -88,6 +122,60 @@ void EnginePins::reset() { } } +void EnginePins::stopIgnitionPins(void) { +#if EFI_PROD_CODE || defined(__DOXYGEN__) + for (int i = 0; i < IGNITION_PIN_COUNT; i++) { + NamedOutputPin *output = &enginePins.coils[i]; + output->unregisterOutput(activeConfiguration.bc.ignitionPins[i], + engineConfiguration->bc.ignitionPins[i]); + } +#endif /* EFI_PROD_CODE */ +} + +void EnginePins::stopInjectionPins(void) { +#if EFI_PROD_CODE || defined(__DOXYGEN__) + for (int i = 0; i < INJECTION_PIN_COUNT; i++) { + NamedOutputPin *output = &enginePins.injectors[i]; + output->unregisterOutput(activeConfiguration.bc.injectionPins[i], + engineConfiguration->bc.injectionPins[i]); + } +#endif /* EFI_PROD_CODE */ +} + +void EnginePins::startIgnitionPins(void) { +#if EFI_PROD_CODE || defined(__DOXYGEN__) + for (int i = 0; i < engineConfiguration->specs.cylindersCount; i++) { + NamedOutputPin *output = &enginePins.coils[i]; + // todo: we need to check if mode has changed + if (boardConfiguration->ignitionPins[i] != activeConfiguration.bc.ignitionPins[i]) { + output->initPin(output->name, boardConfiguration->ignitionPins[i], + &boardConfiguration->ignitionPinMode); + } + } + // todo: we need to check if mode has changed + if (engineConfiguration->dizzySparkOutputPin != activeConfiguration.dizzySparkOutputPin) { + enginePins.dizzyOutput.initPin("dizzy tach", engineConfiguration->dizzySparkOutputPin, + &engineConfiguration->dizzySparkOutputPinMode); + + } +#endif /* EFI_PROD_CODE */ +} + +void EnginePins::startInjectionPins(void) { +#if EFI_PROD_CODE || defined(__DOXYGEN__) + // todo: should we move this code closer to the injection logic? + for (int i = 0; i < engineConfiguration->specs.cylindersCount; i++) { + NamedOutputPin *output = &enginePins.injectors[i]; + // todo: we need to check if mode has changed + if (engineConfiguration->bc.injectionPins[i] != activeConfiguration.bc.injectionPins[i]) { + + output->initPin(output->name, boardConfiguration->injectionPins[i], + &boardConfiguration->injectionPinMode); + } + } +#endif /* EFI_PROD_CODE */ +} + NamedOutputPin::NamedOutputPin() : OutputPin() { name = NULL; } diff --git a/firmware/controllers/system/efiGpio.h b/firmware/controllers/system/efiGpio.h index e2ff3899c3..bbed4a3227 100644 --- a/firmware/controllers/system/efiGpio.h +++ b/firmware/controllers/system/efiGpio.h @@ -35,6 +35,8 @@ public: bool isPinAssigned(); void initPin(const char *msg, brain_pin_e brainPin); void initPin(const char *msg, brain_pin_e brainPin, pin_output_mode_e *outputMode); + void unregisterOutput(brain_pin_e oldPin, brain_pin_e newPin); + #if EFI_GPIO_HARDWARE || defined(__DOXYGEN__) ioportid_t port; @@ -88,6 +90,11 @@ public: EnginePins(); void reset(); bool stopPins(); + void unregisterPins(); + void startInjectionPins(); + void startIgnitionPins(); + void stopInjectionPins(); + void stopIgnitionPins(); OutputPin mainRelay; OutputPin fanRelay; OutputPin acRelay; diff --git a/firmware/controllers/system/event_queue.cpp b/firmware/controllers/system/event_queue.cpp index 4581488e1f..9c669018f5 100644 --- a/firmware/controllers/system/event_queue.cpp +++ b/firmware/controllers/system/event_queue.cpp @@ -50,7 +50,7 @@ bool EventQueue::insertTask(scheduling_s *scheduling, efitime_t timeX, schfunc_t #if EFI_UNIT_TEST || defined(__DOXYGEN__) printf("Already scheduled was %d\r\n", (int)scheduling->momentX); printf("Already scheduled now %d\r\n", (int)timeX); -#endif /* EFI_UNIT_TEST || EFI_SIMULATOR */ +#endif /* EFI_UNIT_TEST */ return false; } diff --git a/firmware/hw_layer/hardware.cpp b/firmware/hw_layer/hardware.cpp index 7f46721897..1a9ad26451 100644 --- a/firmware/hw_layer/hardware.cpp +++ b/firmware/hw_layer/hardware.cpp @@ -200,6 +200,7 @@ static void calcFastAdcIndexes(void) { } static void adcConfigListener(Engine *engine) { + // todo: something is not right here - looks like should be a callback for each configuration change? calcFastAdcIndexes(); } @@ -231,8 +232,8 @@ void applyNewHardwareSettings(void) { // all 'stop' methods need to go before we begin starting pins - stopInjectionPins(); - stopIgnitionPins(); + enginePins.stopInjectionPins(); + enginePins.stopIgnitionPins(); stopCanPins(); bool etbRestartNeeded = isETBRestartNeeded(); if (etbRestartNeeded) { @@ -261,40 +262,11 @@ void applyNewHardwareSettings(void) { unregisterPin(engineConfiguration->bc.clutchUpPin, activeConfiguration.bc.clutchUpPin); + enginePins.unregisterPins(); - unregisterOutput(activeConfiguration.bc.fuelPumpPin, engineConfiguration->bc.fuelPumpPin, - &enginePins.fuelPumpRelay); - unregisterOutput(activeConfiguration.bc.fanPin, engineConfiguration->bc.fanPin, &enginePins.fanRelay); - unregisterOutput(activeConfiguration.bc.hip9011CsPin, - engineConfiguration->bc.hip9011CsPin, &enginePins.hipCs); - unregisterOutput(activeConfiguration.bc.triggerErrorPin, - engineConfiguration->bc.triggerErrorPin, &enginePins.triggerDecoderErrorPin); - unregisterOutput(activeConfiguration.bc.sdCardCsPin, engineConfiguration->bc.sdCardCsPin, - &enginePins.sdCsPin); - unregisterOutput(activeConfiguration.bc.etbDirectionPin1, - engineConfiguration->bc.etbDirectionPin1, &enginePins.etbOutput1); - unregisterOutput(activeConfiguration.bc.etbDirectionPin2, - engineConfiguration->bc.etbDirectionPin2, &enginePins.etbOutput2); - unregisterOutput(activeConfiguration.bc.malfunctionIndicatorPin, - engineConfiguration->bc.malfunctionIndicatorPin, &enginePins.checkEnginePin); - unregisterOutput(activeConfiguration.dizzySparkOutputPin, - engineConfiguration->dizzySparkOutputPin, &enginePins.dizzyOutput); - unregisterOutput(activeConfiguration.bc.tachOutputPin, - engineConfiguration->bc.tachOutputPin, &enginePins.tachOut); - unregisterOutput(activeConfiguration.bc.idle.solenoidPin, - engineConfiguration->bc.idle.solenoidPin, &enginePins.idleSolenoidPin); - for (int i = 0;i < LE_COMMAND_COUNT;i++) - unregisterOutput(activeConfiguration.bc.fsioPins[i], - engineConfiguration->bc.fsioPins[i], &enginePins.fsioOutputs[i]); - - unregisterOutput(activeConfiguration.bc.alternatorControlPin, - engineConfiguration->bc.alternatorControlPin, &enginePins.alternatorPin); - unregisterOutput(activeConfiguration.bc.mainRelayPin, - engineConfiguration->bc.mainRelayPin, &enginePins.mainRelay); - - startInjectionPins(); - startIgnitionPins(); + enginePins.startInjectionPins(); + enginePins.startIgnitionPins(); startCanPins(); if (etbRestartNeeded) { startETBPins(); diff --git a/firmware/integration/rusefi_config.txt b/firmware/integration/rusefi_config.txt index 9c54a62bc0..7b25b6750f 100644 --- a/firmware/integration/rusefi_config.txt +++ b/firmware/integration/rusefi_config.txt @@ -107,8 +107,8 @@ struct pid_s float dFactor;;"value", 1, 0, -1000, 1000, 5 int16_t offset;Linear addition to PID logic;"value", 1, 0, 0, 1000, 0 int16_t period;PID dTime;"ms", 1, 0, 0, 3000, 0 - int16_t minValue;;"v", 1, 0, 0, 3000.0, 3 - int16_t maxValue;;"v", 1, 0, 0, 3000.0, 3 + int16_t minValue;;"", 1, 0, 0, 3000.0, 3 + int16_t maxValue;;"", 1, 0, 0, 3000.0, 3 end_struct struct cranking_parameters_s diff --git a/firmware/rusefi.cpp b/firmware/rusefi.cpp index 03e871e051..dd055ee238 100644 --- a/firmware/rusefi.cpp +++ b/firmware/rusefi.cpp @@ -260,5 +260,5 @@ int getRusEfiVersion(void) { if (initBootloader() != 0) return 123; #endif /* EFI_BOOTLOADER_INCLUDE_CODE */ - return 20170602; + return 20170604; } diff --git a/firmware/svnversion.h b/firmware/svnversion.h index 5404c5ece6..2397ca1b8b 100644 --- a/firmware/svnversion.h +++ b/firmware/svnversion.h @@ -1,5 +1,5 @@ // This file was generated by Version2Header -// Fri Jun 02 23:03:47 EDT 2017 +// Sun Jun 04 19:14:56 EDT 2017 #ifndef VCS_VERSION -#define VCS_VERSION "14281" +#define VCS_VERSION "14317" #endif diff --git a/firmware/tunerstudio/rusefi.input b/firmware/tunerstudio/rusefi.input index 601dad2598..390000556c 100644 --- a/firmware/tunerstudio/rusefi.input +++ b/firmware/tunerstudio/rusefi.input @@ -188,7 +188,7 @@ fileVersion = { 20161225 } wallFuelAmount = scalar, F32, 160, "ms", 1, 0 iatCorrection = scalar, F32, 164, "%", 1, 0 wallFuelCorrection = scalar, F32, 168, "ms", 1, 0 - curIdlePosition = scalar, F32, 172, "percent", 1, 0 + idleAirValvePosition = scalar, F32, 172, "percent", 1, 0 currentTargetAfr = scalar, F32, 176, "ratio", 1, 0 chargeAirMass = scalar, F32, 180, "g", 1, 0 cltCorrection = scalar, F32, 184, "%", 1, 0 @@ -478,7 +478,7 @@ fileVersion = { 20161225 } massAirFlowValueGa = massAirFlowValue,"Air Flow", "kg/hr", 0, 50, -999, -999, 999, 999, 1, 1 veValueGauge = veValue, "fuel: VE", "", 0, 120, 10, 10, 100, 100, 1, 1 baroCorrectionGauge = baroCorrection,"BaroCorr", "%", 0, 120, 10, 10, 100, 100, 1, 1 - pedalPositionGauge = pedalPosition,"Pedal Position", "%", 0, 120, 10, 10, 100, 100, 1, 1 + pedalPositionGauge = pedalPosition,"Throttle Pedal Position", "%", 0, 120, 10, 10, 100, 100, 1, 1 knockCountGauge = knockCount,"Knock count", "count", 0, 120, 10, 10, 100, 100, 1, 1 knockLevelGauge = knockLevel,"Knock level", "volts", 0, 7, 10, 10, 100, 100, 1, 2 @@ -503,7 +503,7 @@ fileVersion = { 20161225 } wallFuelAmountGauge = wallFuelAmount, "fuel: wall amount", "ms", 0, 100, 0, 0, 100, 100, 0, 0 wallFuelCorrectionGauge = wallFuelCorrection, "fuel: wall correction extra", "ms", 0, 100, 0, 0, 100, 100, 0, 0 - curIdlePositionGauge = curIdlePosition, "idle position", "%", 0, 100, 0, 0, 100, 100, 0, 0 + idleAirValvePositionGauge = idleAirValvePosition, "idle position", "%", 0, 100, 0, 0, 100, 100, 0, 0 debugFloatField1Gauge = debugFloatField1, "debug f1", "%", 0, 100, 0, 0, 100, 100, 4, 4 debugFloatField2Gauge = debugFloatField2, "debug f2", "%", 0, 100, 0, 0, 100, 100, 4, 4 @@ -592,7 +592,7 @@ fileVersion = { 20161225 } entry = massAirFlowValue,"airMass", float, "%.3f" entry = pedalPosition, "pedal", float, "%.3f" entry = triggerErrorsCounter, "trg err",int, "%d" - entry = curIdlePosition, @@GAUGE_NAME_IAC@@, float, "%.3f" + entry = idleAirValvePosition, @@GAUGE_NAME_IAC@@, float, "%.3f" entry = fuelRunning, @@GAUGE_NAME_FUEL_RUNNING@@, float, "%.3f" @@ -1011,7 +1011,7 @@ cmd_call_from_pit = "w\x00\x20\x34\x56" field = "AFR ADC input", afr_hwChannel field = "fuelLevelSensor", fuelLevelSensor field = "Baro ADC input", baroSensor_hwChannel - field = "pedal Position Channel", pedalPositionChannel + field = "Throttle pedal Position Channel", pedalPositionChannel field = "Primary input channel", triggerInputPins1 field = "Secondary channel", triggerInputPins2 field = "Cam Sync/VVT input", camInput @@ -1221,6 +1221,7 @@ cmd_call_from_pit = "w\x00\x20\x34\x56" field = "idle I", idleRpmPid_iFactor, { idleMode == 0} field = "idle D", idleRpmPid_dFactor, { idleMode == 0} field = "idle offset", idleRpmPid_offset, { idleMode == 0} + field = "period", idleRpmPid_period field = "pid min", idleRpmPid_minValue, { idleMode == 0} field = "pid max", idleRpmPid_maxValue, { idleMode == 0} field = "pid TPS deactivation", idlePidDeactivationTpsThreshold, { idleMode == 0} @@ -1628,17 +1629,18 @@ cmd_call_from_pit = "w\x00\x20\x34\x56" field = "verbose", isVerboseETB field = "Throttle Pedal Up", throttlePedalUpVoltage field = "Throttle Pedal Wide Open", throttlePedalWOTVoltage - field = "PWM Frequency", etbFreq - field = "Dir #1", etbDirectionPin1 - field = "Dir #2", etbDirectionPin2 - field = "Control #1", etbControlPin1 - field = "Control #2", etbControlPin2 - field = "pFactor", etb_pFactor - field = "iFactor", etb_iFactor - field = "dFactor", etb_dFactor - field = "offset", etb_offset - field = "pid min", etb_minValue - field = "pid max", etb_maxValue + field = "PWM Frequency", etbFreq, {pedalPositionChannel != 16} + field = "Dir #1", etbDirectionPin1, {pedalPositionChannel != 16} + field = "Dir #2", etbDirectionPin2, {pedalPositionChannel != 16} + field = "Control #1", etbControlPin1, {pedalPositionChannel != 16} + field = "Control #2", etbControlPin2, {pedalPositionChannel != 16} + field = "pFactor", etb_pFactor, {pedalPositionChannel != 16} + field = "iFactor", etb_iFactor, {pedalPositionChannel != 16} + field = "dFactor", etb_dFactor, {pedalPositionChannel != 16} + field = "offset", etb_offset, {pedalPositionChannel != 16} + field = "control period", etb_period, {pedalPositionChannel != 16} + field = "pid min", etb_minValue, {pedalPositionChannel != 16} + field = "pid max", etb_maxValue, {pedalPositionChannel != 16} dialog = testSpark, "Spark" commandButton = "Spark #1", cmd_test_spk1 diff --git a/firmware/util/datalogging.cpp b/firmware/util/datalogging.cpp index 2e8617cf4a..9f24a01285 100644 --- a/firmware/util/datalogging.cpp +++ b/firmware/util/datalogging.cpp @@ -58,7 +58,7 @@ static ALWAYS_INLINE bool validateBuffer(Logging *logging, uint32_t extraLen) { if (remainingSize(logging) < extraLen + 1) { #if EFI_PROD_CODE warning(CUSTOM_LOGGING_BUFFER_OVERFLOW, "output overflow %s", logging->name); -#endif +#endif /* EFI_PROD_CODE */ return true; } return false; @@ -67,8 +67,8 @@ static ALWAYS_INLINE bool validateBuffer(Logging *logging, uint32_t extraLen) { void append(Logging *logging, const char *text) { efiAssertVoid(text != NULL, "append NULL"); uint32_t extraLen = efiStrlen(text); - bool isError = validateBuffer(logging, extraLen); - if (isError) { + bool isCapacityProblem = validateBuffer(logging, extraLen); + if (isCapacityProblem) { return; } strcpy(logging->linePointer, text); @@ -82,24 +82,11 @@ void append(Logging *logging, const char *text) { * @note This method if fast because it does not validate much, be sure what you are doing */ void appendFast(Logging *logging, const char *text) { -// todo: fix this implementation? this would be a one-pass implementation instead of a two-pass -// char c; -// char *s = (char *) text; -// do { -// c = *s++; -// *logging->linePointer++ = c; -// } while (c != '\0'); register char *s; - for (s = (char *) text; *s; ++s) - ; - int extraLen = (s - text); - s = logging->linePointer; while ((*s++ = *text++) != 0) ; - -// strcpy(logging->linePointer, text); - logging->linePointer += extraLen; + logging->linePointer = s - 1; } // todo: look into chsnprintf once on Chibios 3 @@ -225,11 +212,6 @@ void printWithLength(char *line) { consoleOutputBuffer((const uint8_t *) line, p - line); } -void printLine(Logging *logging) { - printWithLength(logging->buffer); - resetLogging(logging); -} - void appendMsgPrefix(Logging *logging) { append(logging, "msg" DELIMETER); } @@ -263,7 +245,8 @@ void printMsg(Logging *logger, const char *fmt, ...) { va_end(ap); append(logger, DELIMETER); - printLine(logger); + printWithLength(logger->buffer); + resetLogging(logger); } /** diff --git a/firmware/util/datalogging.h b/firmware/util/datalogging.h index 87d8cfb89b..1999dc5af5 100644 --- a/firmware/util/datalogging.h +++ b/firmware/util/datalogging.h @@ -56,7 +56,6 @@ void debugFloat(Logging *logging, const char *text, float value, int precision); void appendFloat(Logging *logging, float value, int precision); void resetLogging(Logging *logging); -void printLine(Logging *logging); void appendMsgPrefix(Logging *logging); void appendMsgPostfix(Logging *logging); diff --git a/firmware/util/loggingcentral.cpp b/firmware/util/loggingcentral.cpp index c905021f55..84f0c68046 100644 --- a/firmware/util/loggingcentral.cpp +++ b/firmware/util/loggingcentral.cpp @@ -73,7 +73,7 @@ char * swapOutputBuffers(int *actualOutputBufferSize) { int expectedOutputSize; #endif /* EFI_ENABLE_ASSERTS */ { // start of critical section - lockOutputBuffer(); + bool alreadyLocked = lockOutputBuffer(); /** * we cannot output under syslock, we simply rotate which buffer is which */ @@ -88,7 +88,9 @@ char * swapOutputBuffers(int *actualOutputBufferSize) { accumulatedSize = 0; accumulationBuffer[0] = 0; - unlockOutputBuffer(); + if (!alreadyLocked) { + unlockOutputBuffer(); + } } // end of critical section *actualOutputBufferSize = efiStrlen(outputBuffer); @@ -104,16 +106,12 @@ char * swapOutputBuffers(int *actualOutputBufferSize) { return outputBuffer; } -extern bool consoleInBinaryMode; - /** * This method actually sends all the pending data to the communication layer. * This method is invoked by the main thread - that's the only thread which should be sending * actual data to console in order to avoid concurrent access to serial hardware. */ void printPending(void) { - if (consoleInBinaryMode) - return; int actualOutputBufferSize; char *output = swapOutputBuffers(&actualOutputBufferSize); diff --git a/simulator/simulator/efifeatures.h b/simulator/simulator/efifeatures.h index 9ad90ff434..22b9cb4520 100644 --- a/simulator/simulator/efifeatures.h +++ b/simulator/simulator/efifeatures.h @@ -14,6 +14,8 @@ #define EFI_PRINTF_FUEL_DETAILS TRUE +#define EFI_BLUETOOTH_SETUP FALSE + #define EFI_GPIO_HARDWARE FALSE #define EFI_CLOCK_LOCKS FALSE diff --git a/unit_tests/test_logic_expression.cpp b/unit_tests/test_logic_expression.cpp index e555d10efc..b2398403a9 100644 --- a/unit_tests/test_logic_expression.cpp +++ b/unit_tests/test_logic_expression.cpp @@ -11,6 +11,7 @@ #include "test_logic_expression.h" #include "fsio_impl.h" #include "cli_registry.h" +#include "engine_test_helper.h" #define TEST_POOL_SIZE 256 @@ -19,7 +20,7 @@ static float mockFan; static float mockRpm; static float mockTimeSinceBoot; -float getLEValue(Engine *engine, calc_stack_t *s, le_action_e action) { +float getEngineValue(le_action_e action DECLARE_ENGINE_PARAMETER_SUFFIX) { switch(action) { case LE_METHOD_FAN: return mockFan; @@ -91,7 +92,11 @@ static void testExpression2(float selfValue, const char *line, float expected) { print("Parsing [%s]", line); assertTrueM("Not NULL expected", element != NULL); LECalculator c; - assertEqualsM(line, expected, c.getValue2(selfValue, element, NULL)); + + EngineTestHelper eth(FORD_INLINE_6_1995); + EXPAND_EngineTestHelper; + + assertEqualsM(line, expected, c.getValue2(selfValue, element PASS_ENGINE_PARAMETER_SUFFIX)); } static void testExpression(const char *line, float expected) { @@ -103,13 +108,16 @@ void testLogicExpressions(void) { testParsing(); + EngineTestHelper eth(FORD_INLINE_6_1995); + EXPAND_EngineTestHelper; + LECalculator c; LEElement value1; value1.init(LE_NUMERIC_VALUE, 123.0); c.add(&value1); - assertEqualsM("123", 123.0, c.getValue(0, NULL)); + assertEqualsM("123", 123.0, c.getValue(0 PASS_ENGINE_PARAMETER_SUFFIX)); LEElement value2; value2.init(LE_NUMERIC_VALUE, 321.0); @@ -118,7 +126,7 @@ void testLogicExpressions(void) { LEElement value3; value3.init(LE_OPERATOR_AND); c.add(&value3); - assertEqualsM("123 and 321", 1.0, c.getValue(0, NULL)); + assertEqualsM("123 and 321", 1.0, c.getValue(0 PASS_ENGINE_PARAMETER_SUFFIX)); /** * fuel_pump = (time_since_boot < 4 seconds) OR (rpm > 0) @@ -183,7 +191,7 @@ void testLogicExpressions(void) { LEElement * element = pool.parseExpression("fan NOT coolant 90 > AND fan coolant 85 > AND OR"); assertTrueM("Not NULL expected", element != NULL); LECalculator c; - assertEqualsM("that expression", 1, c.getValue2(0, element, NULL)); + assertEqualsM("that expression", 1, c.getValue2(0, element PASS_ENGINE_PARAMETER_SUFFIX)); assertEquals(12, c.currentCalculationLogPosition); assertEquals(102, c.calcLogAction[0]);