From f38cdfcf0d0527c0d63cc43a3c7b8092dc91ebc4 Mon Sep 17 00:00:00 2001 From: rusefi Date: Mon, 20 Feb 2017 14:58:46 -0500 Subject: [PATCH] fixes #2 --- firmware/console/status_loop.cpp | 1743 +++++++++++++++--------------- firmware/rusefi.cpp | 2 +- firmware/svnversion.h | 9 +- 3 files changed, 886 insertions(+), 868 deletions(-) diff --git a/firmware/console/status_loop.cpp b/firmware/console/status_loop.cpp index d9a5b253de..8975c29221 100644 --- a/firmware/console/status_loop.cpp +++ b/firmware/console/status_loop.cpp @@ -1,862 +1,881 @@ -/** - * @file status_loop.cpp - * @brief Human-readable protocol status messages - * - * http://rusefi.com/forum/viewtopic.php?t=263 Dev console overview - * http://rusefi.com/forum/viewtopic.php?t=210 Commands overview - * - * - * @date Mar 15, 2013 - * @author Andrey Belomutskiy, (c) 2012-2017 - * - * 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 . - * - */ - -#include "main.h" -#include "status_loop.h" - -#include "adc_inputs.h" -#if EFI_WAVE_ANALYZER || defined(__DOXYGEN__) -#include "wave_analyzer.h" -#endif /* EFI_WAVE_ANALYZER */ - -// see RUS_EFI_VERSION_TAG in console source code -#define RUS_EFI_VERSION_TAG "rusEfiVersion" - -#include "trigger_central.h" -#include "engine_state.h" -#include "io_pins.h" -#include "efiGpio.h" -#include "mmc_card.h" -#include "console_io.h" -#include "malfunction_central.h" -#include "speed_density.h" - -#include "advance_map.h" -#include "tunerstudio.h" -#include "fuel_math.h" -#include "main_trigger_callback.h" -#include "engine_math.h" -#include "idle_thread.h" -#include "engine_configuration.h" -#include "rfiutil.h" -#include "svnversion.h" -#include "engine.h" -#include "lcd_controller.h" -#include "settings.h" -#include "rusefi_outputs.h" - -extern fuel_Map3D_t veMap; -extern afr_Map3D_t afrMap; -extern bool main_loop_started; - -#if EFI_PROD_CODE || defined(__DOXYGEN__) -// todo: move this logic to algo folder! -#include "rtc_helper.h" -#include "lcd_HD44780.h" -#include "rusefi.h" -#include "pin_repository.h" -#include "flash_main.h" -#include "max31855.h" -#include "vehicle_speed.h" -#endif - -static bool subscription[(int) RO_LAST_ELEMENT]; - -// this 'true' value is needed for simulator -static volatile bool fullLog = true; -int warningEnabled = true; -//int warningEnabled = FALSE; - -extern bool hasFirmwareErrorFlag; -#define FULL_LOGGING_KEY "fl" - -static char LOGGING_BUFFER[1400] CCM_OPTIONAL; -static Logging logger("status loop", LOGGING_BUFFER, sizeof(LOGGING_BUFFER)); - -static void setWarningEnabled(int value) { - warningEnabled = value; -} - -#if EFI_FILE_LOGGING || defined(__DOXYGEN__) -static char FILE_LOGGER[1000] CCM_OPTIONAL; -static Logging fileLogger("file logger", FILE_LOGGER, sizeof(FILE_LOGGER)); -#endif /* EFI_FILE_LOGGING */ - -static int logFileLineIndex = 0; -#define TAB "\t" - -static void reportSensorF(Logging *log, bool fileFormat, const char *caption, const char *units, float value, - int precision) { - if (!fileFormat) { -#if (EFI_PROD_CODE || EFI_SIMULATOR) || defined(__DOXYGEN__) - debugFloat(log, caption, value, precision); -#endif /* EFI_PROD_CODE || EFI_SIMULATOR */ - } else { - -#if EFI_FILE_LOGGING || defined(__DOXYGEN__) - if (logFileLineIndex == 0) { - append(log, caption); - append(log, TAB); - } else if (logFileLineIndex == 1) { - append(log, units); - append(log, TAB); - } else { - appendFloat(log, value, precision); - append(log, TAB); - } -#endif /* EFI_FILE_LOGGING */ - } -} - -static void reportSensorI(Logging *log, bool fileFormat, const char *caption, const char *units, int value) { - if (!fileFormat) { - -#if (EFI_PROD_CODE || EFI_SIMULATOR) || defined(__DOXYGEN__) - debugInt(log, caption, value); -#endif /* EFI_PROD_CODE || EFI_SIMULATOR */ - } else { -#if EFI_FILE_LOGGING || defined(__DOXYGEN__) - if (logFileLineIndex == 0) { - append(log, caption); - append(log, TAB); - } else if (logFileLineIndex == 1) { - append(log, units); - append(log, TAB); - } else { - appendPrintf(log, "%d%s", value, TAB); - } -#endif /* EFI_FILE_LOGGING */ - } -} - -EXTERN_ENGINE -; - -static char buf[6]; - -/** - * This is useful if we are changing engine mode dynamically - * For example http://rusefi.com/forum/viewtopic.php?f=5&t=1085 - */ -static int packEngineMode(DECLARE_ENGINE_PARAMETER_F) { - return (engineConfiguration->fuelAlgorithm << 4) + - (engineConfiguration->injectionMode << 2) + - engineConfiguration->ignitionMode; -} - -static void printSensors(Logging *log, bool fileFormat) { - // current time, in milliseconds - int nowMs = currentTimeMillis(); - float sec = ((float) nowMs) / 1000; - reportSensorF(log, fileFormat, "time", "", sec, 3); // log column 1 - - int rpm = 0; -#if EFI_SHAFT_POSITION_INPUT || defined(__DOXYGEN__) - rpm = getRpmE(engine); - reportSensorI(log, fileFormat, "rpm", "RPM", rpm); // log column 2 - -// reportSensorF(log, fileFormat, "TRG_0_DUTY", "%", getTriggerDutyCycle(0), 2); -// reportSensorF(log, fileFormat, "TRG_1_DUTY", "%", getTriggerDutyCycle(1), 2); -#endif - -#if EFI_PROD_CODE || defined(__DOXYGEN__) - reportSensorF(log, fileFormat, "int_temp", "C", getMCUInternalTemperature(), 2); // log column #3 -#endif - - reportSensorI(log, fileFormat, "mode", "v", packEngineMode(PASS_ENGINE_PARAMETER_F)); // log column #3 - - if (hasCltSensor()) { - reportSensorF(log, fileFormat, "CLT", "C", getCoolantTemperature(PASS_ENGINE_PARAMETER_F), 2); // log column #4 - } - if (hasTpsSensor()) { - reportSensorF(log, fileFormat, "TPS", "%", getTPS(PASS_ENGINE_PARAMETER_F), 2); // log column #5 - } - - if (hasVBatt(PASS_ENGINE_PARAMETER_F)) { - reportSensorF(log, fileFormat, "vbatt", "V", getVBatt(PASS_ENGINE_PARAMETER_F), 2); // log column #6 - } - - if (hasIatSensor()) { - reportSensorF(log, fileFormat, "IAT", "C", getIntakeAirTemperature(PASS_ENGINE_PARAMETER_F), 2); // log column #7 - } - - if (hasMafSensor()) { - reportSensorF(log, fileFormat, "maf", "V", getMaf(PASS_ENGINE_PARAMETER_F), 2); - reportSensorF(log, fileFormat, "mafr", "kg/hr", getRealMaf(PASS_ENGINE_PARAMETER_F), 2); - } -#if EFI_ANALOG_SENSORS || defined(__DOXYGEN__) - if (engineConfiguration->map.sensor.hwChannel != EFI_ADC_NONE) { - reportSensorF(log, fileFormat, "MAP", "kPa", getMap(), 2); -// reportSensorF(log, fileFormat, "map_r", "V", getRawMap(), 2); - } -#endif /* EFI_ANALOG_SENSORS */ -#if EFI_ANALOG_SENSORS || defined(__DOXYGEN__) - if (hasBaroSensor()) { - reportSensorF(log, fileFormat, "baro", "kPa", getBaroPressure(), 2); - } -#endif /* EFI_ANALOG_SENSORS */ - - if (hasAfrSensor(PASS_ENGINE_PARAMETER_F)) { - reportSensorF(log, fileFormat, "afr", "AFR", getAfr(PASS_ENGINE_PARAMETER_F), 2); - } - -#if EFI_IDLE_CONTROL || defined(__DOXYGEN__) - if (fileFormat) { - reportSensorF(log, fileFormat, "idle", "%", getIdlePosition(), 2); - } -#endif /* EFI_IDLE_CONTROL */ - -#if EFI_ANALOG_SENSORS || defined(__DOXYGEN__) - reportSensorF(log, fileFormat, "target", "AFR", engine->engineState.targetAFR, 2); -#endif /* EFI_ANALOG_SENSORS */ - - if (fileFormat) { - reportSensorF(log, fileFormat, "tCharge", "K", engine->engineState.tChargeK, 2); // log column #8 - reportSensorF(log, fileFormat, "curVE", "%", veMap.getValue(rpm, getMap()), 2); - reportSensorF(log, fileFormat, "VVT", "deg", engine->triggerCentral.vvtPosition, 1); - } - - float engineLoad = getEngineLoadT(PASS_ENGINE_PARAMETER_F); - reportSensorF(log, fileFormat, "ENGINE_LOAD", "x", engineLoad, 2); - - - reportSensorF(log, fileFormat, "dwell", "ms", ENGINE(engineState.sparkDwell), 2); - if (fileFormat) { - reportSensorF(log, fileFormat, "timing", "deg", engine->engineState.timingAdvance, 2); - - } - - if (fileFormat) { - floatms_t fuelBase = getBaseFuel(rpm PASS_ENGINE_PARAMETER); - reportSensorF(log, fileFormat, "f: base", "ms", fuelBase, 2); - reportSensorF(log, fileFormat, "f: actual", "ms", ENGINE(actualLastInjection), 2); - reportSensorF(log, fileFormat, "f: lag", "ms", engine->engineState.injectorLag, 2); - reportSensorF(log, fileFormat, "f: running", "ms", ENGINE(engineState.runningFuel), 2); - reportSensorF(log, fileFormat, "f: pid", "ms", ENGINE(engineState.fuelPidCorrection), 2); - - reportSensorF(log, fileFormat, "f: wall amt", "v", ENGINE(wallFuel).getWallFuel(0), 2); - reportSensorF(log, fileFormat, "f: wall crr", "v", ENGINE(wallFuelCorrection), 2); - - reportSensorI(log, fileFormat, "version", "#", getRusEfiVersion()); - } - -#if EFI_VEHICLE_SPEED || defined(__DOXYGEN__) - if (hasVehicleSpeedSensor()) { - float vehicleSpeed = getVehicleSpeed(); - reportSensorF(log, fileFormat, "vss", "kph", vehicleSpeed, 2); - float sp2rpm = rpm == 0 ? 0 : vehicleSpeed / rpm; - reportSensorF(log, fileFormat, "sp2rpm", "x", sp2rpm, 2); - } -#endif /* EFI_PROD_CODE */ - - reportSensorF(log, fileFormat, "knck_c", "count", engine->knockCount, 0); - reportSensorF(log, fileFormat, "knck_v", "v", engine->knockVolts, 2); - -// reportSensorF(log, fileFormat, "vref", "V", getVRef(engineConfiguration), 2); - - if (fileFormat) { - reportSensorF(log, fileFormat, "f: tps delta", "v", engine->tpsAccelEnrichment.getMaxDelta(), 2); - reportSensorF(log, fileFormat, "f: tps fuel", "ms", engine->engineState.tpsAccelEnrich, 2); - - reportSensorF(log, fileFormat, "f: el delta", "v", engine->engineLoadAccelEnrichment.getMaxDelta(), 2); - reportSensorF(log, fileFormat, "f: el fuel", "v", engine->engineLoadAccelEnrichment.getEngineLoadEnrichment(PASS_ENGINE_PARAMETER_F) * 100 / getMap(), 2); - - reportSensorF(log, fileFormat, "f: duty", "%", getInjectorDutyCycle(rpm PASS_ENGINE_PARAMETER), 2); - } - - -// debugFloat(&logger, "tch", getTCharge1(tps), 2); - - for (int i = 0;ifsioAdc[i] != EFI_ADC_NONE) { - strcpy(buf, "adcX"); - buf[3] = '0' + i; - reportSensorF(log, fileFormat, buf, "", getVoltage("fsio", engineConfiguration->fsioAdc[i]), 2); - } - } - - reportSensorI(log, fileFormat, "warn", "count", engine->engineState.warningCounter); - reportSensorI(log, fileFormat, "error", "code", engine->engineState.lastErrorCode); - -} - - -void writeLogLine(void) { -#if EFI_FILE_LOGGING || defined(__DOXYGEN__) - if (!main_loop_started) - return; - resetLogging(&fileLogger); - printSensors(&fileLogger, true); - - if (isSdCardAlive()) { - appendPrintf(&fileLogger, "\r\n"); - appendToLog(fileLogger.buffer); - logFileLineIndex++; - } -#endif /* EFI_FILE_LOGGING */ -} - -static void printState(void) { -#if EFI_SHAFT_POSITION_INPUT || defined(__DOXYGEN__) - - // todo: make SWO work -// char *msg = "hello\r\n"; -// for(int i=0;itriggerCentral.triggerState.runningRevolutionCounter); - - if (subscription[(int) RO_RUNNING_TRIGGER_ERROR]) - debugInt(&logger, "trg_r_errors", engine->triggerCentral.triggerState.runningTriggerErrorCounter); - - if (subscription[(int) RO_RUNNING_ORDERING_TRIGGER_ERROR]) - debugInt(&logger, "trg_r_order_errors", engine->triggerCentral.triggerState.runningOrderingErrorCounter); - - if (subscription[(int) RO_WAVE_CHART_CURRENT_SIZE]) - debugInt(&logger, "wave_chart_current", 0); - -// debugInt(&logger, "idl", getIdleSwitch()); - -// debugFloat(&logger, "table_spark", getAdvance(rpm, getMaf()), 2); - -// float map = getMap(); - -#endif /* EFI_SHAFT_POSITION_INPUT */ -} - -#define INITIAL_FULL_LOG TRUE -//#define INITIAL_FULL_LOG FALSE - -volatile int needToReportStatus = FALSE; -static int prevCkpEventCounter = -1; - -static LoggingWithStorage logger2("main event handler"); - -static void printStatus(void) { - needToReportStatus = TRUE; -} - -/** - * Time when the firmware version was reported last time, in seconds - * TODO: implement a request/response instead of just constantly sending this out - */ -static systime_t timeOfPreviousPrintVersion = (systime_t) -1; - -#if EFI_PROD_CODE || defined(__DOXYGEN__) -static void printOutPin(const char *pinName, brain_pin_e hwPin) { - if (hwPin != GPIO_UNASSIGNED) { - appendPrintf(&logger, "outpin%s%s@%s%s", DELIMETER, pinName, hwPortname(hwPin), DELIMETER); - } -} -#endif /* EFI_PROD_CODE */ - -static void printInfo(systime_t nowSeconds) { - /** - * we report the version every 4 seconds - this way the console does not need to - * request it and we will display it pretty soon - */ - if (overflowDiff(nowSeconds, timeOfPreviousPrintVersion) < 4) { - return; - } - timeOfPreviousPrintVersion = nowSeconds; - appendPrintf(&logger, "%s%s%d@%s %s %d%s", RUS_EFI_VERSION_TAG, DELIMETER, - getRusEfiVersion(), VCS_VERSION, - getConfigurationName(engineConfiguration->engineType), - getTimeNowSeconds(), - DELIMETER); -#if EFI_PROD_CODE || defined(__DOXYGEN__) - printOutPin(CRANK1, boardConfiguration->triggerInputPins[0]); - printOutPin(CRANK2, boardConfiguration->triggerInputPins[1]); - printOutPin(VVT_NAME, engineConfiguration->camInput); - printOutPin(HIP_NAME, boardConfiguration->hip9011IntHoldPin); - printOutPin(TACH_NAME, boardConfiguration->tachOutputPin); - printOutPin(DIZZY_NAME, engineConfiguration->dizzySparkOutputPin); -#if EFI_WAVE_ANALYZER || defined(__DOXYGEN__) - printOutPin(WA_CHANNEL_1, boardConfiguration->logicAnalyzerPins[0]); - printOutPin(WA_CHANNEL_2, boardConfiguration->logicAnalyzerPins[1]); -#endif /* EFI_WAVE_ANALYZER */ - - for (int i = 0; i < engineConfiguration->specs.cylindersCount; i++) { - printOutPin(enginePins.coils[i].name, boardConfiguration->ignitionPins[i]); - - printOutPin(enginePins.injectors[i].name, boardConfiguration->injectionPins[i]); - } -#endif /* EFI_PROD_CODE */ - -} - -static systime_t timeOfPreviousReport = (systime_t) -1; - -extern fatal_msg_t errorMessageBuffer; - -/** - * @brief Sends all pending data to dev console - */ -void updateDevConsoleState(Engine *engine) { - if (!isCommandLineConsoleReady()) { - return; - } -// looks like this is not needed anymore -// checkIfShouldHalt(); - printPending(); - - /** - * this should go before the firmware error so that console can detect connection - */ - printSensors(&logger, false); - -#if EFI_PROD_CODE || defined(__DOXYGEN__) - // todo: unify with simulator! - if (hasFirmwareError()) { - scheduleMsg(&logger, "FATAL error: %s", errorMessageBuffer); - warningEnabled = false; - scheduleLogging(&logger); - return; - } -#endif - -#if (EFI_PROD_CODE && HAL_USE_ADC) || defined(__DOXYGEN__) - printFullAdcReportIfNeeded(&logger); -#endif - - if (!fullLog) { - return; - } - - systime_t nowSeconds = getTimeNowSeconds(); - printInfo(nowSeconds); - -#if EFI_ENGINE_CONTROL || defined(__DOXYGEN__) - int currentCkpEventCounter = getCrankEventCounter(); - if (prevCkpEventCounter == currentCkpEventCounter && timeOfPreviousReport == nowSeconds) { - return; - } - timeOfPreviousReport = nowSeconds; - - prevCkpEventCounter = currentCkpEventCounter; -#else - chThdSleepMilliseconds(200); -#endif - - printState(); - -#if EFI_WAVE_ANALYZER - printWave(&logger); -#endif - - scheduleLogging(&logger); -} - -/* - * command example: - * sfm 3500 400 - * that would be 'show fuel for rpm 3500 maf 4.0' - */ - -static void showFuelInfo2(float rpm, float engineLoad) { - - float baseFuelMs = getBaseTableFuel(engineConfiguration, (int) rpm, engineLoad); - - float magicAir = getAirMass(engineConfiguration, 1, 100, convertCelsiusToKelvin(20)); - - scheduleMsg(&logger, "SD magic fuel %f", sdMath(engineConfiguration, magicAir, 14.7)); - scheduleMsg(&logger, "inj flow %fcc/min displacement %fL", engineConfiguration->injector.flow, - engineConfiguration->specs.displacement); - - scheduleMsg(&logger2, "algo=%s/pump=%s", getEngine_load_mode_e(engineConfiguration->fuelAlgorithm), - boolToString(enginePins.fuelPumpRelay.getLogicValue())); - - scheduleMsg(&logger2, "injection phase=%f/global fuel correction=%f", getinjectionOffset(rpm), engineConfiguration->globalFuelCorrection); - - scheduleMsg(&logger2, "baro correction=%f", engine->engineState.baroCorrection); - -#if EFI_ENGINE_CONTROL || defined(__DOXYGEN__) - scheduleMsg(&logger, "base cranking fuel %f", engineConfiguration->cranking.baseFuel); - scheduleMsg(&logger2, "cranking fuel: %f", getCrankingFuel(PASS_ENGINE_PARAMETER_F)); - - if (engine->rpmCalculator.isRunning(PASS_ENGINE_PARAMETER_F)) { - float iatCorrection = engine->engineState.iatFuelCorrection; - float cltCorrection = engine->engineState.cltFuelCorrection; - floatms_t injectorLag = engine->engineState.injectorLag; - scheduleMsg(&logger2, "rpm=%f engineLoad=%f", rpm, engineLoad); - scheduleMsg(&logger2, "baseFuel=%f", baseFuelMs); - - scheduleMsg(&logger2, "iatCorrection=%f cltCorrection=%f injectorLag=%f", iatCorrection, cltCorrection, - injectorLag); - - float value = getRunningFuel(baseFuelMs, (int) rpm PASS_ENGINE_PARAMETER); - scheduleMsg(&logger2, "injection pulse width: %f", value); - } -#endif -} - -#if EFI_ENGINE_CONTROL || defined(__DOXYGEN__) -static void showFuelInfo(void) { - showFuelInfo2((float) getRpmE(engine), getEngineLoadT(PASS_ENGINE_PARAMETER_F)); -} -#endif - -static THD_WORKING_AREA(lcdThreadStack, UTILITY_THREAD_STACK_SIZE); - -/** - * blinking thread to show that we are alive - * that's a trivial task - a smaller stack should work - */ -static THD_WORKING_AREA(blinkingStack, 128); - -// move this into EnginePins? -OutputPin communicationPin; // blue LED on brain board by default -OutputPin warningPin; // orange LED on brain board by default -OutputPin runningPin; // green LED on brain board by default - -static OutputPin *leds[] = { &warningPin, &runningPin, &enginePins.checkEnginePin, - &enginePins.errorLedPin, &communicationPin, &enginePins.checkEnginePin }; - -extern pin_output_mode_e DEFAULT_OUTPUT; - -static void initStatusLeds(void) { -#if EFI_PROD_CODE || defined(__DOXYGEN__) - outputPinRegisterExt2("led: comm status", &communicationPin, - engineConfiguration->communicationPin, &DEFAULT_OUTPUT); - // we initialize this here so that we can blink it on start-up - outputPinRegisterExt2("MalfunctionIndicator", &enginePins.checkEnginePin, boardConfiguration->malfunctionIndicatorPin, &DEFAULT_OUTPUT); -#endif - -#if EFI_WARNING_LED || defined(__DOXYGEN__) - outputPinRegister("led: warning status", &warningPin, LED_WARNING_PORT, - LED_WARNING_PIN); - outputPinRegisterExt2("led: running status", &runningPin, engineConfiguration->runningPin, - &DEFAULT_OUTPUT); -#endif /* EFI_WARNING_LED */ -} - -/** - * This method would blink all the LEDs just to test them - */ -static void initialLedsBlink(void) { - if (hasFirmwareError()) { - // make sure we do not turn the fatal LED off if already have - // fatal error by now - return; - } - int size = sizeof(leds) / sizeof(leds[0]); - for (int i = 0; i < size && !hasFirmwareError(); i++) - leds[i]->setValue(1); - - chThdSleepMilliseconds(100); - - // re-checking in case the error has happened while we were sleeping - for (int i = 0; i < size && !hasFirmwareError(); i++) - leds[i]->setValue(0); -} - -int blinkingPeriod = 33; - -/** - * this is useful to test connectivity - */ -static void setBlinkingPeriod(int value) { - if (value > 0) - blinkingPeriod = value; -} - -#if EFI_PROD_CODE || defined(__DOXYGEN__) - -extern efitick_t lastDecodingErrorTime; - -static bool isTriggerErrorNow() { - bool justHadError = (getTimeNowNt() - lastDecodingErrorTime) < US2NT(2 * 1000 * 3 * blinkingPeriod); - return justHadError || isTriggerDecoderError(); -} - -extern bool consoleByteArrived; - -/** - * this thread has a lower-then-usual stack size so we cannot afford *print* methods here - */ -static void blinkingThread(void *arg) { - (void) arg; - chRegSetThreadName("communication blinking"); - - initialLedsBlink(); - - while (true) { - int delayMs = is_usb_serial_ready() ? 3 * blinkingPeriod : blinkingPeriod; - -#if EFI_INTERNAL_FLASH || defined(__DOXYGEN__) - if (getNeedToWriteConfiguration()) { - delayMs = 2 * delayMs; - } -#endif - - if (!hasFirmwareError() && !hasFirmwareErrorFlag) { - communicationPin.setValue(0); - } - warningPin.setValue(0); - chThdSleepMilliseconds(delayMs); - - communicationPin.setValue(1); -#if EFI_ENGINE_CONTROL || defined(__DOXYGEN__) - if (isTriggerErrorNow() || isIgnitionTimingError() || consoleByteArrived) { - consoleByteArrived = false; - warningPin.setValue(1); - } -#endif - chThdSleepMilliseconds(delayMs); - - } -} - -#endif /* EFI_PROD_CODE */ - -static void lcdThread(void *arg) { - (void)arg; - chRegSetThreadName("lcd"); - while (true) { - if (engineConfiguration->bc.useLcdScreen) { -#if EFI_HD44780_LCD - updateHD44780lcd(engine); -#endif - } - chThdSleepMilliseconds(engineConfiguration->bc.lcdThreadPeriod); - } -} - -#if EFI_TUNER_STUDIO || defined(__DOXYGEN__) - -void updateTunerStudioState(TunerStudioOutputChannels *tsOutputChannels DECLARE_ENGINE_PARAMETER_S) { -#if EFI_SHAFT_POSITION_INPUT || defined(__DOXYGEN__) - int rpm = getRpmE(engine); -#else - int rpm = 0; -#endif - - float tps = getTPS(PASS_ENGINE_PARAMETER_F); - float coolant = getCoolantTemperature(PASS_ENGINE_PARAMETER_F); - float intake = getIntakeAirTemperature(PASS_ENGINE_PARAMETER_F); - - float engineLoad = getEngineLoadT(PASS_ENGINE_PARAMETER_F); - - // header - tsOutputChannels->tsConfigVersion = TS_FILE_VERSION; - - // engine state - tsOutputChannels->rpm = rpm; - tsOutputChannels->coolantTemperature = coolant; - tsOutputChannels->intakeAirTemperature = intake; - tsOutputChannels->throttlePositon = tps; - tsOutputChannels->massAirFlowVoltage = hasMafSensor() ? getMaf(PASS_ENGINE_PARAMETER_F) : 0; - tsOutputChannels->massAirFlow = hasMafSensor() ? getRealMaf(PASS_ENGINE_PARAMETER_F) : 0; - - tsOutputChannels->veValue = veMap.getValue(rpm, getMap()); - tsOutputChannels->currentTargetAfr = afrMap.getValue(rpm, getMap()); - tsOutputChannels->airFuelRatio = getAfr(PASS_ENGINE_PARAMETER_F); - if (hasVBatt(PASS_ENGINE_PARAMETER_F)) { - tsOutputChannels->vBatt = getVBatt(PASS_ENGINE_PARAMETER_F); - } - tsOutputChannels->tpsADC = getTPS12bitAdc(PASS_ENGINE_PARAMETER_F) / TPS_TS_CONVERSION; -#if EFI_ANALOG_SENSORS || defined(__DOXYGEN__) - tsOutputChannels->baroPressure = hasBaroSensor() ? getBaroPressure() : 0; -#endif /* EFI_ANALOG_SENSORS */ - tsOutputChannels->manifoldAirPressure = getMap(); - tsOutputChannels->engineLoad = engineLoad; - tsOutputChannels->rpmAcceleration = engine->rpmCalculator.getRpmAcceleration(); - tsOutputChannels->triggerErrorsCounter = engine->triggerCentral.triggerState.totalTriggerErrorCounter; - tsOutputChannels->baroCorrection = engine->engineState.baroCorrection; - tsOutputChannels->pedalPosition = hasPedalPositionSensor(PASS_ENGINE_PARAMETER_F) ? getPedalPosition(PASS_ENGINE_PARAMETER_F) : 0; - tsOutputChannels->knockCount = engine->knockCount; - tsOutputChannels->knockLevel = engine->knockVolts; - tsOutputChannels->fuelTankGauge = engine->engineState.fuelTankGauge; - - tsOutputChannels->hasFatalError = hasFirmwareError(); - tsOutputChannels->totalTriggerErrorCounter = engine->triggerCentral.triggerState.totalTriggerErrorCounter; - - tsOutputChannels->injectorDutyCycle = getInjectorDutyCycle(rpm PASS_ENGINE_PARAMETER); - tsOutputChannels->fuelRunning = ENGINE(engineState.runningFuel); - tsOutputChannels->fuelPidCorrection = ENGINE(engineState.fuelPidCorrection); - tsOutputChannels->injectorLagMs = ENGINE(engineState.injectorLag); - tsOutputChannels->fuelBase = engine->engineState.baseFuel; - tsOutputChannels->actualLastInjection = ENGINE(actualLastInjection); - - efitimesec_t now = getTimeNowSeconds(); - tsOutputChannels->timeSeconds = now; - tsOutputChannels->firmwareVersion = getRusEfiVersion(); - - tsOutputChannels->isWarnNow = isWarningNow(now, true); - - if (engineConfiguration->debugMode == DBG_TPS_ACCEL) { - tsOutputChannels->debugIntField1 = engine->tpsAccelEnrichment.cb.getSize(); - } - - if (engineConfiguration->debugMode == DBG_TRIGGER_INPUT) { - tsOutputChannels->debugIntField1 = engine->triggerCentral.getHwEventCounter((int)SHAFT_PRIMARY_FALLING); - tsOutputChannels->debugIntField2 = engine->triggerCentral.getHwEventCounter((int)SHAFT_SECONDARY_FALLING); - tsOutputChannels->debugIntField3 = engine->triggerCentral.getHwEventCounter((int)SHAFT_3RD_FALLING); - - tsOutputChannels->debugFloatField1 = engine->triggerCentral.getHwEventCounter((int)SHAFT_PRIMARY_RISING); - tsOutputChannels->debugFloatField2 = engine->triggerCentral.getHwEventCounter((int)SHAFT_SECONDARY_RISING); - tsOutputChannels->debugFloatField3 = engine->triggerCentral.getHwEventCounter((int)SHAFT_3RD_RISING); - - } else if (engineConfiguration->debugMode == FSIO_ADC) { - // todo: implement a proper loop - if (engineConfiguration->fsioAdc[0] != EFI_ADC_NONE) { - strcpy(buf, "adcX"); - tsOutputChannels->debugFloatField1 = getVoltage("fsio", engineConfiguration->fsioAdc[0]); - } - } else if (engineConfiguration->debugMode == DBG_VEHICLE_SPEED_SENSOR) { - tsOutputChannels->debugIntField1 = engine->engineState.vssCounter; - } else if (engineConfiguration->debugMode == DBG_SD_CARD) { - tsOutputChannels->debugIntField1 = engine->engineState.totalLoggedBytes; - } else if (engineConfiguration->debugMode == DBG_CRANKING_DETAILS) { - tsOutputChannels->debugIntField1 = engine->rpmCalculator.getRevolutionCounterSinceStart(); - } - - - tsOutputChannels->wallFuelAmount = ENGINE(wallFuel).getWallFuel(0); - tsOutputChannels->wallFuelCorrection = ENGINE(wallFuelCorrection); - // TPS acceleration - tsOutputChannels->deltaTps = engine->tpsAccelEnrichment.getMaxDelta(); - tsOutputChannels->tpsAccelFuel = engine->engineState.tpsAccelEnrich; - // engine load acceleration - tsOutputChannels->engineLoadAccelExtra = engine->engineLoadAccelEnrichment.getEngineLoadEnrichment(PASS_ENGINE_PARAMETER_F) * 100 / getMap(); - tsOutputChannels->engineLoadDelta = engine->engineLoadAccelEnrichment.getMaxDelta(); - - - tsOutputChannels->iatCorrection = ENGINE(engineState.iatFuelCorrection); - tsOutputChannels->cltCorrection = ENGINE(engineState.cltFuelCorrection); - - tsOutputChannels->checkEngine = hasErrorCodes(); - - tsOutputChannels->vvtPosition = engine->triggerCentral.vvtPosition; - - tsOutputChannels->engineMode = packEngineMode(PASS_ENGINE_PARAMETER_F); - -#if EFI_PROD_CODE || defined(__DOXYGEN__) - tsOutputChannels->internalMcuTemperature = getMCUInternalTemperature(); - tsOutputChannels->idlePosition = getIdlePosition(); - tsOutputChannels->isTriggerError = isTriggerErrorNow(); - -#if EFI_MAX_31855 || defined(__DOXYGEN__) - for (int i = 0; i < EGT_CHANNEL_COUNT; i++) - tsOutputChannels->egtValues.values[i] = getEgtValue(i); -#endif /* EFI_MAX_31855 */ - -#if EFI_INTERNAL_FLASH || defined(__DOXYGEN__) - tsOutputChannels->needBurn = getNeedToWriteConfiguration(); -#endif -#if EFI_FILE_LOGGING || defined(__DOXYGEN__) - tsOutputChannels->hasSdCard = isSdCardAlive(); -#endif - tsOutputChannels->isFuelPumpOn = enginePins.fuelPumpRelay.getLogicValue(); - tsOutputChannels->isFanOn = enginePins.fanRelay.getLogicValue(); - tsOutputChannels->isO2HeaterOn = enginePins.o2heater.getLogicValue(); - tsOutputChannels->isIgnitionEnabled = engineConfiguration->isIgnitionEnabled; - tsOutputChannels->isInjectionEnabled = engineConfiguration->isInjectionEnabled; - tsOutputChannels->isCylinderCleanupEnabled = engineConfiguration->isCylinderCleanupEnabled; - tsOutputChannels->isCylinderCleanupActivated = engine->isCylinderCleanupMode; - tsOutputChannels->secondTriggerChannelEnabled = engineConfiguration->secondTriggerChannelEnabled; -#if EFI_VEHICLE_SPEED || defined(__DOXYGEN__) - float vehicleSpeed = getVehicleSpeed(); - tsOutputChannels->vehicleSpeedKph = vehicleSpeed; - tsOutputChannels->speedToRpmRatio = vehicleSpeed / rpm; - -#endif /* EFI_VEHICLE_SPEED */ - tsOutputChannels->isCltError = !isValidCoolantTemperature(getCoolantTemperature(PASS_ENGINE_PARAMETER_F)); - tsOutputChannels->isIatError = !isValidIntakeAirTemperature(getIntakeAirTemperature(PASS_ENGINE_PARAMETER_F)); -#endif /* EFI_PROD_CODE */ - - tsOutputChannels->warningCounter = engine->engineState.warningCounter; - tsOutputChannels->lastErrorCode = engine->engineState.lastErrorCode; - - tsOutputChannels->knockNowIndicator = engine->knockCount > 0; - tsOutputChannels->knockEverIndicator = engine->knockEver; - - tsOutputChannels->clutchUpState = engine->clutchUpState; - tsOutputChannels->clutchDownState = engine->clutchDownState; - tsOutputChannels->tCharge = getTCharge(rpm, tps, coolant, intake PASS_ENGINE_PARAMETER); - float timing = engine->engineState.timingAdvance; - tsOutputChannels->ignitionAdvance = timing > 360 ? timing - 720 : timing; - tsOutputChannels->sparkDwell = ENGINE(engineState.sparkDwell); - tsOutputChannels->crankingFuelMs = getCrankingFuel(PASS_ENGINE_PARAMETER_F); - tsOutputChannels->chargeAirMass = engine->engineState.airMass; -} - -extern TunerStudioOutputChannels tsOutputChannels; - -void prepareTunerStudioOutputs(void) { - // sensor state for EFI Analytics Tuner Studio - updateTunerStudioState(&tsOutputChannels PASS_ENGINE_PARAMETER); -} - -#endif /* EFI_TUNER_STUDIO */ - -static void subscribe(int outputOrdinal) { - subscription[outputOrdinal] = true; -} - -static void unsubscribe(int outputOrdinal) { - subscription[outputOrdinal] = false; -} - -void initStatusLoop(Engine *engine) { - setFullLog(INITIAL_FULL_LOG); - addConsoleActionI(FULL_LOGGING_KEY, setFullLog); - addConsoleActionI("warn", setWarningEnabled); - -#if EFI_ENGINE_CONTROL || defined(__DOXYGEN__) - addConsoleActionFF("fuelinfo2", (VoidFloatFloat) showFuelInfo2); - addConsoleAction("fuelinfo", showFuelInfo); -#endif - -#if EFI_PROD_CODE || defined(__DOXYGEN__) - subscription[(int) RO_TRG1_DUTY] = true; - subscription[(int) RO_TRG2_DUTY] = true; - subscription[(int) RO_TRG3_DUTY] = false; - subscription[(int) RO_TRG4_DUTY] = false; - subscription[(int) RO_TOTAL_REVOLUTION_COUNTER] = true; - subscription[(int) RO_RUNNING_REVOLUTION_COUNTER] = false; - - addConsoleActionI("subscribe", subscribe); - addConsoleActionI("unsubscribe", unsubscribe); - addConsoleActionI("set_led_blinking_period", setBlinkingPeriod); - - addConsoleAction("status", printStatus); -#endif /* EFI_PROD_CODE */ -} - -void startStatusThreads(Engine *engine) { - // todo: refactoring needed, this file should probably be split into pieces - chThdCreateStatic(lcdThreadStack, sizeof(lcdThreadStack), NORMALPRIO, (tfunc_t) lcdThread, engine); -#if EFI_PROD_CODE || defined(__DOXYGEN__) - initStatusLeds(); - chThdCreateStatic(blinkingStack, sizeof(blinkingStack), NORMALPRIO, (tfunc_t) blinkingThread, NULL); -#endif /* EFI_PROD_CODE */ -} - -void setFullLog(int value) { - print("Setting full logging: %s\r\n", boolToString(value)); - printMsg(&logger, "%s%d", FULL_LOGGING_KEY, value); - fullLog = value; -} - -bool getFullLog(void) { - return fullLog; -} +/** + * @file status_loop.cpp + * @brief Human-readable protocol status messages + * + * http://rusefi.com/forum/viewtopic.php?t=263 Dev console overview + * http://rusefi.com/forum/viewtopic.php?t=210 Commands overview + * + * + * @date Mar 15, 2013 + * @author Andrey Belomutskiy, (c) 2012-2017 + * + * 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 . + * + */ + +#include "main.h" +#include "status_loop.h" + +#include "adc_inputs.h" +#if EFI_WAVE_ANALYZER || defined(__DOXYGEN__) +#include "wave_analyzer.h" +#endif /* EFI_WAVE_ANALYZER */ + +// see RUS_EFI_VERSION_TAG in console source code +#define RUS_EFI_VERSION_TAG "rusEfiVersion" + +#include "trigger_central.h" +#include "engine_state.h" +#include "io_pins.h" +#include "efiGpio.h" +#include "mmc_card.h" +#include "console_io.h" +#include "malfunction_central.h" +#include "speed_density.h" + +#include "advance_map.h" +#include "tunerstudio.h" +#include "fuel_math.h" +#include "main_trigger_callback.h" +#include "engine_math.h" +#include "idle_thread.h" +#include "engine_configuration.h" +#include "rfiutil.h" +#include "svnversion.h" +#include "engine.h" +#include "lcd_controller.h" +#include "settings.h" +#include "rusefi_outputs.h" + +extern fuel_Map3D_t veMap; +extern afr_Map3D_t afrMap; +extern bool main_loop_started; + +#if EFI_PROD_CODE || defined(__DOXYGEN__) +// todo: move this logic to algo folder! +#include "rtc_helper.h" +#include "lcd_HD44780.h" +#include "rusefi.h" +#include "pin_repository.h" +#include "flash_main.h" +#include "max31855.h" +#include "vehicle_speed.h" +#endif + +static bool subscription[(int) RO_LAST_ELEMENT]; + +// this 'true' value is needed for simulator +static volatile bool fullLog = true; +int warningEnabled = true; +//int warningEnabled = FALSE; + +#if EFI_TUNER_STUDIO || defined(__DOXYGEN__) +extern TunerStudioOutputChannels tsOutputChannels; +#endif + +extern bool hasFirmwareErrorFlag; +#define FULL_LOGGING_KEY "fl" + +static char LOGGING_BUFFER[1400] CCM_OPTIONAL; +static Logging logger("status loop", LOGGING_BUFFER, sizeof(LOGGING_BUFFER)); + +static void setWarningEnabled(int value) { + warningEnabled = value; +} + +#if EFI_FILE_LOGGING || defined(__DOXYGEN__) +static char FILE_LOGGER[1000] CCM_OPTIONAL; +static Logging fileLogger("file logger", FILE_LOGGER, sizeof(FILE_LOGGER)); +#endif /* EFI_FILE_LOGGING */ + +static int logFileLineIndex = 0; +#define TAB "\t" + +static void reportSensorF(Logging *log, bool fileFormat, const char *caption, const char *units, float value, + int precision) { + if (!fileFormat) { +#if (EFI_PROD_CODE || EFI_SIMULATOR) || defined(__DOXYGEN__) + debugFloat(log, caption, value, precision); +#endif /* EFI_PROD_CODE || EFI_SIMULATOR */ + } else { + +#if EFI_FILE_LOGGING || defined(__DOXYGEN__) + if (logFileLineIndex == 0) { + append(log, caption); + append(log, TAB); + } else if (logFileLineIndex == 1) { + append(log, units); + append(log, TAB); + } else { + appendFloat(log, value, precision); + append(log, TAB); + } +#endif /* EFI_FILE_LOGGING */ + } +} + +static void reportSensorI(Logging *log, bool fileFormat, const char *caption, const char *units, int value) { + if (!fileFormat) { + +#if (EFI_PROD_CODE || EFI_SIMULATOR) || defined(__DOXYGEN__) + debugInt(log, caption, value); +#endif /* EFI_PROD_CODE || EFI_SIMULATOR */ + } else { +#if EFI_FILE_LOGGING || defined(__DOXYGEN__) + if (logFileLineIndex == 0) { + append(log, caption); + append(log, TAB); + } else if (logFileLineIndex == 1) { + append(log, units); + append(log, TAB); + } else { + appendPrintf(log, "%d%s", value, TAB); + } +#endif /* EFI_FILE_LOGGING */ + } +} + +EXTERN_ENGINE +; + +static char buf[6]; + +/** + * This is useful if we are changing engine mode dynamically + * For example http://rusefi.com/forum/viewtopic.php?f=5&t=1085 + */ +static int packEngineMode(DECLARE_ENGINE_PARAMETER_F) { + return (engineConfiguration->fuelAlgorithm << 4) + + (engineConfiguration->injectionMode << 2) + + engineConfiguration->ignitionMode; +} + +static void printSensors(Logging *log, bool fileFormat) { + // current time, in milliseconds + int nowMs = currentTimeMillis(); + float sec = ((float) nowMs) / 1000; + reportSensorF(log, fileFormat, "time", "", sec, 3); // log column 1 + + int rpm = 0; +#if EFI_SHAFT_POSITION_INPUT || defined(__DOXYGEN__) + rpm = getRpmE(engine); + reportSensorI(log, fileFormat, "rpm", "RPM", rpm); // log column 2 + +// reportSensorF(log, fileFormat, "TRG_0_DUTY", "%", getTriggerDutyCycle(0), 2); +// reportSensorF(log, fileFormat, "TRG_1_DUTY", "%", getTriggerDutyCycle(1), 2); +#endif + +#if EFI_PROD_CODE || defined(__DOXYGEN__) + reportSensorF(log, fileFormat, "int_temp", "C", getMCUInternalTemperature(), 2); // log column #3 +#endif + + reportSensorI(log, fileFormat, "mode", "v", packEngineMode(PASS_ENGINE_PARAMETER_F)); // log column #3 + + if (hasCltSensor()) { + reportSensorF(log, fileFormat, "CLT", "C", getCoolantTemperature(PASS_ENGINE_PARAMETER_F), 2); // log column #4 + } + if (hasTpsSensor()) { + reportSensorF(log, fileFormat, "TPS", "%", getTPS(PASS_ENGINE_PARAMETER_F), 2); // log column #5 + } + + if (hasVBatt(PASS_ENGINE_PARAMETER_F)) { + reportSensorF(log, fileFormat, "vbatt", "V", getVBatt(PASS_ENGINE_PARAMETER_F), 2); // log column #6 + } + + if (hasIatSensor()) { + reportSensorF(log, fileFormat, "IAT", "C", getIntakeAirTemperature(PASS_ENGINE_PARAMETER_F), 2); // log column #7 + } + + if (hasMafSensor()) { + reportSensorF(log, fileFormat, "maf", "V", getMaf(PASS_ENGINE_PARAMETER_F), 2); + reportSensorF(log, fileFormat, "mafr", "kg/hr", getRealMaf(PASS_ENGINE_PARAMETER_F), 2); + } +#if EFI_ANALOG_SENSORS || defined(__DOXYGEN__) + if (engineConfiguration->map.sensor.hwChannel != EFI_ADC_NONE) { + reportSensorF(log, fileFormat, "MAP", "kPa", getMap(), 2); +// reportSensorF(log, fileFormat, "map_r", "V", getRawMap(), 2); + } +#endif /* EFI_ANALOG_SENSORS */ +#if EFI_ANALOG_SENSORS || defined(__DOXYGEN__) + if (hasBaroSensor()) { + reportSensorF(log, fileFormat, "baro", "kPa", getBaroPressure(), 2); + } +#endif /* EFI_ANALOG_SENSORS */ + + if (hasAfrSensor(PASS_ENGINE_PARAMETER_F)) { + reportSensorF(log, fileFormat, "afr", "AFR", getAfr(PASS_ENGINE_PARAMETER_F), 2); + } + +#if EFI_IDLE_CONTROL || defined(__DOXYGEN__) + if (fileFormat) { + reportSensorF(log, fileFormat, "idle", "%", getIdlePosition(), 2); + } +#endif /* EFI_IDLE_CONTROL */ + +#if EFI_ANALOG_SENSORS || defined(__DOXYGEN__) + reportSensorF(log, fileFormat, "target", "AFR", engine->engineState.targetAFR, 2); +#endif /* EFI_ANALOG_SENSORS */ + + if (fileFormat) { + +#if EFI_TUNER_STUDIO || defined(__DOXYGEN__) + reportSensorF(log, fileFormat, "debugF1", "v", tsOutputChannels.debugFloatField1, 4); + reportSensorF(log, fileFormat, "debugF2", "v", tsOutputChannels.debugFloatField2, 4); + reportSensorF(log, fileFormat, "debugF3", "v", tsOutputChannels.debugFloatField3, 4); + reportSensorF(log, fileFormat, "debugF4", "v", tsOutputChannels.debugFloatField4, 4); + reportSensorF(log, fileFormat, "debugF5", "v", tsOutputChannels.debugFloatField5, 4); + reportSensorF(log, fileFormat, "debugF6", "v", tsOutputChannels.debugFloatField6, 4); + reportSensorF(log, fileFormat, "debugF7", "v", tsOutputChannels.debugFloatField7, 4); + + reportSensorI(log, fileFormat, "debugInt1", "v", tsOutputChannels.debugIntField1); + reportSensorI(log, fileFormat, "debugInt2", "v", tsOutputChannels.debugIntField2); + reportSensorI(log, fileFormat, "debugInt3", "v", tsOutputChannels.debugIntField3); +#endif /* EFI_TUNER_STUDIO */ + + reportSensorF(log, fileFormat, "tCharge", "K", engine->engineState.tChargeK, 2); // log column #8 + reportSensorF(log, fileFormat, "curVE", "%", veMap.getValue(rpm, getMap()), 2); + reportSensorF(log, fileFormat, "VVT", "deg", engine->triggerCentral.vvtPosition, 1); + } + + float engineLoad = getEngineLoadT(PASS_ENGINE_PARAMETER_F); + reportSensorF(log, fileFormat, "ENGINE_LOAD", "x", engineLoad, 2); + + + reportSensorF(log, fileFormat, "dwell", "ms", ENGINE(engineState.sparkDwell), 2); + if (fileFormat) { + reportSensorF(log, fileFormat, "timing", "deg", engine->engineState.timingAdvance, 2); + + } + + if (fileFormat) { + floatms_t fuelBase = getBaseFuel(rpm PASS_ENGINE_PARAMETER); + reportSensorF(log, fileFormat, "f: base", "ms", fuelBase, 2); + reportSensorF(log, fileFormat, "f: actual", "ms", ENGINE(actualLastInjection), 2); + reportSensorF(log, fileFormat, "f: lag", "ms", engine->engineState.injectorLag, 2); + reportSensorF(log, fileFormat, "f: running", "ms", ENGINE(engineState.runningFuel), 2); + reportSensorF(log, fileFormat, "f: pid", "ms", ENGINE(engineState.fuelPidCorrection), 2); + + reportSensorF(log, fileFormat, "f: wall amt", "v", ENGINE(wallFuel).getWallFuel(0), 2); + reportSensorF(log, fileFormat, "f: wall crr", "v", ENGINE(wallFuelCorrection), 2); + + reportSensorI(log, fileFormat, "version", "#", getRusEfiVersion()); + } + +#if EFI_VEHICLE_SPEED || defined(__DOXYGEN__) + if (hasVehicleSpeedSensor()) { + float vehicleSpeed = getVehicleSpeed(); + reportSensorF(log, fileFormat, "vss", "kph", vehicleSpeed, 2); + float sp2rpm = rpm == 0 ? 0 : vehicleSpeed / rpm; + reportSensorF(log, fileFormat, "sp2rpm", "x", sp2rpm, 2); + } +#endif /* EFI_PROD_CODE */ + + reportSensorF(log, fileFormat, "knck_c", "count", engine->knockCount, 0); + reportSensorF(log, fileFormat, "knck_v", "v", engine->knockVolts, 2); + +// reportSensorF(log, fileFormat, "vref", "V", getVRef(engineConfiguration), 2); + + if (fileFormat) { + reportSensorF(log, fileFormat, "f: tps delta", "v", engine->tpsAccelEnrichment.getMaxDelta(), 2); + reportSensorF(log, fileFormat, "f: tps fuel", "ms", engine->engineState.tpsAccelEnrich, 2); + + reportSensorF(log, fileFormat, "f: el delta", "v", engine->engineLoadAccelEnrichment.getMaxDelta(), 2); + reportSensorF(log, fileFormat, "f: el fuel", "v", engine->engineLoadAccelEnrichment.getEngineLoadEnrichment(PASS_ENGINE_PARAMETER_F) * 100 / getMap(), 2); + + reportSensorF(log, fileFormat, "f: duty", "%", getInjectorDutyCycle(rpm PASS_ENGINE_PARAMETER), 2); + } + + +// debugFloat(&logger, "tch", getTCharge1(tps), 2); + + for (int i = 0;ifsioAdc[i] != EFI_ADC_NONE) { + strcpy(buf, "adcX"); + buf[3] = '0' + i; + reportSensorF(log, fileFormat, buf, "", getVoltage("fsio", engineConfiguration->fsioAdc[i]), 2); + } + } + + reportSensorI(log, fileFormat, "warn", "count", engine->engineState.warningCounter); + reportSensorI(log, fileFormat, "error", "code", engine->engineState.lastErrorCode); + +} + + +void writeLogLine(void) { +#if EFI_FILE_LOGGING || defined(__DOXYGEN__) + if (!main_loop_started) + return; + resetLogging(&fileLogger); + printSensors(&fileLogger, true); + + if (isSdCardAlive()) { + appendPrintf(&fileLogger, "\r\n"); + appendToLog(fileLogger.buffer); + logFileLineIndex++; + } +#endif /* EFI_FILE_LOGGING */ +} + +static void printState(void) { +#if EFI_SHAFT_POSITION_INPUT || defined(__DOXYGEN__) + + // todo: make SWO work +// char *msg = "hello\r\n"; +// for(int i=0;itriggerCentral.triggerState.runningRevolutionCounter); + + if (subscription[(int) RO_RUNNING_TRIGGER_ERROR]) + debugInt(&logger, "trg_r_errors", engine->triggerCentral.triggerState.runningTriggerErrorCounter); + + if (subscription[(int) RO_RUNNING_ORDERING_TRIGGER_ERROR]) + debugInt(&logger, "trg_r_order_errors", engine->triggerCentral.triggerState.runningOrderingErrorCounter); + + if (subscription[(int) RO_WAVE_CHART_CURRENT_SIZE]) + debugInt(&logger, "wave_chart_current", 0); + +// debugInt(&logger, "idl", getIdleSwitch()); + +// debugFloat(&logger, "table_spark", getAdvance(rpm, getMaf()), 2); + +// float map = getMap(); + +#endif /* EFI_SHAFT_POSITION_INPUT */ +} + +#define INITIAL_FULL_LOG TRUE +//#define INITIAL_FULL_LOG FALSE + +volatile int needToReportStatus = FALSE; +static int prevCkpEventCounter = -1; + +static LoggingWithStorage logger2("main event handler"); + +static void printStatus(void) { + needToReportStatus = TRUE; +} + +/** + * Time when the firmware version was reported last time, in seconds + * TODO: implement a request/response instead of just constantly sending this out + */ +static systime_t timeOfPreviousPrintVersion = (systime_t) -1; + +#if EFI_PROD_CODE || defined(__DOXYGEN__) +static void printOutPin(const char *pinName, brain_pin_e hwPin) { + if (hwPin != GPIO_UNASSIGNED) { + appendPrintf(&logger, "outpin%s%s@%s%s", DELIMETER, pinName, hwPortname(hwPin), DELIMETER); + } +} +#endif /* EFI_PROD_CODE */ + +static void printInfo(systime_t nowSeconds) { + /** + * we report the version every 4 seconds - this way the console does not need to + * request it and we will display it pretty soon + */ + if (overflowDiff(nowSeconds, timeOfPreviousPrintVersion) < 4) { + return; + } + timeOfPreviousPrintVersion = nowSeconds; + appendPrintf(&logger, "%s%s%d@%s %s %d%s", RUS_EFI_VERSION_TAG, DELIMETER, + getRusEfiVersion(), VCS_VERSION, + getConfigurationName(engineConfiguration->engineType), + getTimeNowSeconds(), + DELIMETER); +#if EFI_PROD_CODE || defined(__DOXYGEN__) + printOutPin(CRANK1, boardConfiguration->triggerInputPins[0]); + printOutPin(CRANK2, boardConfiguration->triggerInputPins[1]); + printOutPin(VVT_NAME, engineConfiguration->camInput); + printOutPin(HIP_NAME, boardConfiguration->hip9011IntHoldPin); + printOutPin(TACH_NAME, boardConfiguration->tachOutputPin); + printOutPin(DIZZY_NAME, engineConfiguration->dizzySparkOutputPin); +#if EFI_WAVE_ANALYZER || defined(__DOXYGEN__) + printOutPin(WA_CHANNEL_1, boardConfiguration->logicAnalyzerPins[0]); + printOutPin(WA_CHANNEL_2, boardConfiguration->logicAnalyzerPins[1]); +#endif /* EFI_WAVE_ANALYZER */ + + for (int i = 0; i < engineConfiguration->specs.cylindersCount; i++) { + printOutPin(enginePins.coils[i].name, boardConfiguration->ignitionPins[i]); + + printOutPin(enginePins.injectors[i].name, boardConfiguration->injectionPins[i]); + } +#endif /* EFI_PROD_CODE */ + +} + +static systime_t timeOfPreviousReport = (systime_t) -1; + +extern fatal_msg_t errorMessageBuffer; + +/** + * @brief Sends all pending data to dev console + */ +void updateDevConsoleState(Engine *engine) { + if (!isCommandLineConsoleReady()) { + return; + } +// looks like this is not needed anymore +// checkIfShouldHalt(); + printPending(); + + /** + * this should go before the firmware error so that console can detect connection + */ + printSensors(&logger, false); + +#if EFI_PROD_CODE || defined(__DOXYGEN__) + // todo: unify with simulator! + if (hasFirmwareError()) { + scheduleMsg(&logger, "FATAL error: %s", errorMessageBuffer); + warningEnabled = false; + scheduleLogging(&logger); + return; + } +#endif + +#if (EFI_PROD_CODE && HAL_USE_ADC) || defined(__DOXYGEN__) + printFullAdcReportIfNeeded(&logger); +#endif + + if (!fullLog) { + return; + } + + systime_t nowSeconds = getTimeNowSeconds(); + printInfo(nowSeconds); + +#if EFI_ENGINE_CONTROL || defined(__DOXYGEN__) + int currentCkpEventCounter = getCrankEventCounter(); + if (prevCkpEventCounter == currentCkpEventCounter && timeOfPreviousReport == nowSeconds) { + return; + } + timeOfPreviousReport = nowSeconds; + + prevCkpEventCounter = currentCkpEventCounter; +#else + chThdSleepMilliseconds(200); +#endif + + printState(); + +#if EFI_WAVE_ANALYZER + printWave(&logger); +#endif + + scheduleLogging(&logger); +} + +/* + * command example: + * sfm 3500 400 + * that would be 'show fuel for rpm 3500 maf 4.0' + */ + +static void showFuelInfo2(float rpm, float engineLoad) { + + float baseFuelMs = getBaseTableFuel(engineConfiguration, (int) rpm, engineLoad); + + float magicAir = getAirMass(engineConfiguration, 1, 100, convertCelsiusToKelvin(20)); + + scheduleMsg(&logger, "SD magic fuel %f", sdMath(engineConfiguration, magicAir, 14.7)); + scheduleMsg(&logger, "inj flow %fcc/min displacement %fL", engineConfiguration->injector.flow, + engineConfiguration->specs.displacement); + + scheduleMsg(&logger2, "algo=%s/pump=%s", getEngine_load_mode_e(engineConfiguration->fuelAlgorithm), + boolToString(enginePins.fuelPumpRelay.getLogicValue())); + + scheduleMsg(&logger2, "injection phase=%f/global fuel correction=%f", getinjectionOffset(rpm), engineConfiguration->globalFuelCorrection); + + scheduleMsg(&logger2, "baro correction=%f", engine->engineState.baroCorrection); + +#if EFI_ENGINE_CONTROL || defined(__DOXYGEN__) + scheduleMsg(&logger, "base cranking fuel %f", engineConfiguration->cranking.baseFuel); + scheduleMsg(&logger2, "cranking fuel: %f", getCrankingFuel(PASS_ENGINE_PARAMETER_F)); + + if (engine->rpmCalculator.isRunning(PASS_ENGINE_PARAMETER_F)) { + float iatCorrection = engine->engineState.iatFuelCorrection; + float cltCorrection = engine->engineState.cltFuelCorrection; + floatms_t injectorLag = engine->engineState.injectorLag; + scheduleMsg(&logger2, "rpm=%f engineLoad=%f", rpm, engineLoad); + scheduleMsg(&logger2, "baseFuel=%f", baseFuelMs); + + scheduleMsg(&logger2, "iatCorrection=%f cltCorrection=%f injectorLag=%f", iatCorrection, cltCorrection, + injectorLag); + + float value = getRunningFuel(baseFuelMs, (int) rpm PASS_ENGINE_PARAMETER); + scheduleMsg(&logger2, "injection pulse width: %f", value); + } +#endif +} + +#if EFI_ENGINE_CONTROL || defined(__DOXYGEN__) +static void showFuelInfo(void) { + showFuelInfo2((float) getRpmE(engine), getEngineLoadT(PASS_ENGINE_PARAMETER_F)); +} +#endif + +static THD_WORKING_AREA(lcdThreadStack, UTILITY_THREAD_STACK_SIZE); + +/** + * blinking thread to show that we are alive + * that's a trivial task - a smaller stack should work + */ +static THD_WORKING_AREA(blinkingStack, 128); + +// move this into EnginePins? +OutputPin communicationPin; // blue LED on brain board by default +OutputPin warningPin; // orange LED on brain board by default +OutputPin runningPin; // green LED on brain board by default + +static OutputPin *leds[] = { &warningPin, &runningPin, &enginePins.checkEnginePin, + &enginePins.errorLedPin, &communicationPin, &enginePins.checkEnginePin }; + +extern pin_output_mode_e DEFAULT_OUTPUT; + +static void initStatusLeds(void) { +#if EFI_PROD_CODE || defined(__DOXYGEN__) + outputPinRegisterExt2("led: comm status", &communicationPin, + engineConfiguration->communicationPin, &DEFAULT_OUTPUT); + // we initialize this here so that we can blink it on start-up + outputPinRegisterExt2("MalfunctionIndicator", &enginePins.checkEnginePin, boardConfiguration->malfunctionIndicatorPin, &DEFAULT_OUTPUT); +#endif + +#if EFI_WARNING_LED || defined(__DOXYGEN__) + outputPinRegister("led: warning status", &warningPin, LED_WARNING_PORT, + LED_WARNING_PIN); + outputPinRegisterExt2("led: running status", &runningPin, engineConfiguration->runningPin, + &DEFAULT_OUTPUT); +#endif /* EFI_WARNING_LED */ +} + +/** + * This method would blink all the LEDs just to test them + */ +static void initialLedsBlink(void) { + if (hasFirmwareError()) { + // make sure we do not turn the fatal LED off if already have + // fatal error by now + return; + } + int size = sizeof(leds) / sizeof(leds[0]); + for (int i = 0; i < size && !hasFirmwareError(); i++) + leds[i]->setValue(1); + + chThdSleepMilliseconds(100); + + // re-checking in case the error has happened while we were sleeping + for (int i = 0; i < size && !hasFirmwareError(); i++) + leds[i]->setValue(0); +} + +int blinkingPeriod = 33; + +/** + * this is useful to test connectivity + */ +static void setBlinkingPeriod(int value) { + if (value > 0) + blinkingPeriod = value; +} + +#if EFI_PROD_CODE || defined(__DOXYGEN__) + +extern efitick_t lastDecodingErrorTime; + +static bool isTriggerErrorNow() { + bool justHadError = (getTimeNowNt() - lastDecodingErrorTime) < US2NT(2 * 1000 * 3 * blinkingPeriod); + return justHadError || isTriggerDecoderError(); +} + +extern bool consoleByteArrived; + +/** + * this thread has a lower-then-usual stack size so we cannot afford *print* methods here + */ +static void blinkingThread(void *arg) { + (void) arg; + chRegSetThreadName("communication blinking"); + + initialLedsBlink(); + + while (true) { + int delayMs = is_usb_serial_ready() ? 3 * blinkingPeriod : blinkingPeriod; + +#if EFI_INTERNAL_FLASH || defined(__DOXYGEN__) + if (getNeedToWriteConfiguration()) { + delayMs = 2 * delayMs; + } +#endif + + if (!hasFirmwareError() && !hasFirmwareErrorFlag) { + communicationPin.setValue(0); + } + warningPin.setValue(0); + chThdSleepMilliseconds(delayMs); + + communicationPin.setValue(1); +#if EFI_ENGINE_CONTROL || defined(__DOXYGEN__) + if (isTriggerErrorNow() || isIgnitionTimingError() || consoleByteArrived) { + consoleByteArrived = false; + warningPin.setValue(1); + } +#endif + chThdSleepMilliseconds(delayMs); + + } +} + +#endif /* EFI_PROD_CODE */ + +static void lcdThread(void *arg) { + (void)arg; + chRegSetThreadName("lcd"); + while (true) { + if (engineConfiguration->bc.useLcdScreen) { +#if EFI_HD44780_LCD + updateHD44780lcd(engine); +#endif + } + chThdSleepMilliseconds(engineConfiguration->bc.lcdThreadPeriod); + } +} + +#if EFI_TUNER_STUDIO || defined(__DOXYGEN__) + +void updateTunerStudioState(TunerStudioOutputChannels *tsOutputChannels DECLARE_ENGINE_PARAMETER_S) { +#if EFI_SHAFT_POSITION_INPUT || defined(__DOXYGEN__) + int rpm = getRpmE(engine); +#else + int rpm = 0; +#endif + + float tps = getTPS(PASS_ENGINE_PARAMETER_F); + float coolant = getCoolantTemperature(PASS_ENGINE_PARAMETER_F); + float intake = getIntakeAirTemperature(PASS_ENGINE_PARAMETER_F); + + float engineLoad = getEngineLoadT(PASS_ENGINE_PARAMETER_F); + + // header + tsOutputChannels->tsConfigVersion = TS_FILE_VERSION; + + // engine state + tsOutputChannels->rpm = rpm; + tsOutputChannels->coolantTemperature = coolant; + tsOutputChannels->intakeAirTemperature = intake; + tsOutputChannels->throttlePositon = tps; + tsOutputChannels->massAirFlowVoltage = hasMafSensor() ? getMaf(PASS_ENGINE_PARAMETER_F) : 0; + tsOutputChannels->massAirFlow = hasMafSensor() ? getRealMaf(PASS_ENGINE_PARAMETER_F) : 0; + + tsOutputChannels->veValue = veMap.getValue(rpm, getMap()); + tsOutputChannels->currentTargetAfr = afrMap.getValue(rpm, getMap()); + tsOutputChannels->airFuelRatio = getAfr(PASS_ENGINE_PARAMETER_F); + if (hasVBatt(PASS_ENGINE_PARAMETER_F)) { + tsOutputChannels->vBatt = getVBatt(PASS_ENGINE_PARAMETER_F); + } + tsOutputChannels->tpsADC = getTPS12bitAdc(PASS_ENGINE_PARAMETER_F) / TPS_TS_CONVERSION; +#if EFI_ANALOG_SENSORS || defined(__DOXYGEN__) + tsOutputChannels->baroPressure = hasBaroSensor() ? getBaroPressure() : 0; +#endif /* EFI_ANALOG_SENSORS */ + tsOutputChannels->manifoldAirPressure = getMap(); + tsOutputChannels->engineLoad = engineLoad; + tsOutputChannels->rpmAcceleration = engine->rpmCalculator.getRpmAcceleration(); + tsOutputChannels->triggerErrorsCounter = engine->triggerCentral.triggerState.totalTriggerErrorCounter; + tsOutputChannels->baroCorrection = engine->engineState.baroCorrection; + tsOutputChannels->pedalPosition = hasPedalPositionSensor(PASS_ENGINE_PARAMETER_F) ? getPedalPosition(PASS_ENGINE_PARAMETER_F) : 0; + tsOutputChannels->knockCount = engine->knockCount; + tsOutputChannels->knockLevel = engine->knockVolts; + tsOutputChannels->fuelTankGauge = engine->engineState.fuelTankGauge; + + tsOutputChannels->hasFatalError = hasFirmwareError(); + tsOutputChannels->totalTriggerErrorCounter = engine->triggerCentral.triggerState.totalTriggerErrorCounter; + + tsOutputChannels->injectorDutyCycle = getInjectorDutyCycle(rpm PASS_ENGINE_PARAMETER); + tsOutputChannels->fuelRunning = ENGINE(engineState.runningFuel); + tsOutputChannels->fuelPidCorrection = ENGINE(engineState.fuelPidCorrection); + tsOutputChannels->injectorLagMs = ENGINE(engineState.injectorLag); + tsOutputChannels->fuelBase = engine->engineState.baseFuel; + tsOutputChannels->actualLastInjection = ENGINE(actualLastInjection); + + efitimesec_t now = getTimeNowSeconds(); + tsOutputChannels->timeSeconds = now; + tsOutputChannels->firmwareVersion = getRusEfiVersion(); + + tsOutputChannels->isWarnNow = isWarningNow(now, true); + + if (engineConfiguration->debugMode == DBG_TPS_ACCEL) { + tsOutputChannels->debugIntField1 = engine->tpsAccelEnrichment.cb.getSize(); + } + + if (engineConfiguration->debugMode == DBG_TRIGGER_INPUT) { + tsOutputChannels->debugIntField1 = engine->triggerCentral.getHwEventCounter((int)SHAFT_PRIMARY_FALLING); + tsOutputChannels->debugIntField2 = engine->triggerCentral.getHwEventCounter((int)SHAFT_SECONDARY_FALLING); + tsOutputChannels->debugIntField3 = engine->triggerCentral.getHwEventCounter((int)SHAFT_3RD_FALLING); + + tsOutputChannels->debugFloatField1 = engine->triggerCentral.getHwEventCounter((int)SHAFT_PRIMARY_RISING); + tsOutputChannels->debugFloatField2 = engine->triggerCentral.getHwEventCounter((int)SHAFT_SECONDARY_RISING); + tsOutputChannels->debugFloatField3 = engine->triggerCentral.getHwEventCounter((int)SHAFT_3RD_RISING); + + } else if (engineConfiguration->debugMode == FSIO_ADC) { + // todo: implement a proper loop + if (engineConfiguration->fsioAdc[0] != EFI_ADC_NONE) { + strcpy(buf, "adcX"); + tsOutputChannels->debugFloatField1 = getVoltage("fsio", engineConfiguration->fsioAdc[0]); + } + } else if (engineConfiguration->debugMode == DBG_VEHICLE_SPEED_SENSOR) { + tsOutputChannels->debugIntField1 = engine->engineState.vssCounter; + } else if (engineConfiguration->debugMode == DBG_SD_CARD) { + tsOutputChannels->debugIntField1 = engine->engineState.totalLoggedBytes; + } else if (engineConfiguration->debugMode == DBG_CRANKING_DETAILS) { + tsOutputChannels->debugIntField1 = engine->rpmCalculator.getRevolutionCounterSinceStart(); + } + + + tsOutputChannels->wallFuelAmount = ENGINE(wallFuel).getWallFuel(0); + tsOutputChannels->wallFuelCorrection = ENGINE(wallFuelCorrection); + // TPS acceleration + tsOutputChannels->deltaTps = engine->tpsAccelEnrichment.getMaxDelta(); + tsOutputChannels->tpsAccelFuel = engine->engineState.tpsAccelEnrich; + // engine load acceleration + tsOutputChannels->engineLoadAccelExtra = engine->engineLoadAccelEnrichment.getEngineLoadEnrichment(PASS_ENGINE_PARAMETER_F) * 100 / getMap(); + tsOutputChannels->engineLoadDelta = engine->engineLoadAccelEnrichment.getMaxDelta(); + + + tsOutputChannels->iatCorrection = ENGINE(engineState.iatFuelCorrection); + tsOutputChannels->cltCorrection = ENGINE(engineState.cltFuelCorrection); + + tsOutputChannels->checkEngine = hasErrorCodes(); + + tsOutputChannels->vvtPosition = engine->triggerCentral.vvtPosition; + + tsOutputChannels->engineMode = packEngineMode(PASS_ENGINE_PARAMETER_F); + +#if EFI_PROD_CODE || defined(__DOXYGEN__) + tsOutputChannels->internalMcuTemperature = getMCUInternalTemperature(); + tsOutputChannels->idlePosition = getIdlePosition(); + tsOutputChannels->isTriggerError = isTriggerErrorNow(); + +#if EFI_MAX_31855 || defined(__DOXYGEN__) + for (int i = 0; i < EGT_CHANNEL_COUNT; i++) + tsOutputChannels->egtValues.values[i] = getEgtValue(i); +#endif /* EFI_MAX_31855 */ + +#if EFI_INTERNAL_FLASH || defined(__DOXYGEN__) + tsOutputChannels->needBurn = getNeedToWriteConfiguration(); +#endif +#if EFI_FILE_LOGGING || defined(__DOXYGEN__) + tsOutputChannels->hasSdCard = isSdCardAlive(); +#endif + tsOutputChannels->isFuelPumpOn = enginePins.fuelPumpRelay.getLogicValue(); + tsOutputChannels->isFanOn = enginePins.fanRelay.getLogicValue(); + tsOutputChannels->isO2HeaterOn = enginePins.o2heater.getLogicValue(); + tsOutputChannels->isIgnitionEnabled = engineConfiguration->isIgnitionEnabled; + tsOutputChannels->isInjectionEnabled = engineConfiguration->isInjectionEnabled; + tsOutputChannels->isCylinderCleanupEnabled = engineConfiguration->isCylinderCleanupEnabled; + tsOutputChannels->isCylinderCleanupActivated = engine->isCylinderCleanupMode; + tsOutputChannels->secondTriggerChannelEnabled = engineConfiguration->secondTriggerChannelEnabled; +#if EFI_VEHICLE_SPEED || defined(__DOXYGEN__) + float vehicleSpeed = getVehicleSpeed(); + tsOutputChannels->vehicleSpeedKph = vehicleSpeed; + tsOutputChannels->speedToRpmRatio = vehicleSpeed / rpm; + +#endif /* EFI_VEHICLE_SPEED */ + tsOutputChannels->isCltError = !isValidCoolantTemperature(getCoolantTemperature(PASS_ENGINE_PARAMETER_F)); + tsOutputChannels->isIatError = !isValidIntakeAirTemperature(getIntakeAirTemperature(PASS_ENGINE_PARAMETER_F)); +#endif /* EFI_PROD_CODE */ + + tsOutputChannels->warningCounter = engine->engineState.warningCounter; + tsOutputChannels->lastErrorCode = engine->engineState.lastErrorCode; + + tsOutputChannels->knockNowIndicator = engine->knockCount > 0; + tsOutputChannels->knockEverIndicator = engine->knockEver; + + tsOutputChannels->clutchUpState = engine->clutchUpState; + tsOutputChannels->clutchDownState = engine->clutchDownState; + tsOutputChannels->tCharge = getTCharge(rpm, tps, coolant, intake PASS_ENGINE_PARAMETER); + float timing = engine->engineState.timingAdvance; + tsOutputChannels->ignitionAdvance = timing > 360 ? timing - 720 : timing; + tsOutputChannels->sparkDwell = ENGINE(engineState.sparkDwell); + tsOutputChannels->crankingFuelMs = getCrankingFuel(PASS_ENGINE_PARAMETER_F); + tsOutputChannels->chargeAirMass = engine->engineState.airMass; +} + +extern TunerStudioOutputChannels tsOutputChannels; + +void prepareTunerStudioOutputs(void) { + // sensor state for EFI Analytics Tuner Studio + updateTunerStudioState(&tsOutputChannels PASS_ENGINE_PARAMETER); +} + +#endif /* EFI_TUNER_STUDIO */ + +static void subscribe(int outputOrdinal) { + subscription[outputOrdinal] = true; +} + +static void unsubscribe(int outputOrdinal) { + subscription[outputOrdinal] = false; +} + +void initStatusLoop(Engine *engine) { + setFullLog(INITIAL_FULL_LOG); + addConsoleActionI(FULL_LOGGING_KEY, setFullLog); + addConsoleActionI("warn", setWarningEnabled); + +#if EFI_ENGINE_CONTROL || defined(__DOXYGEN__) + addConsoleActionFF("fuelinfo2", (VoidFloatFloat) showFuelInfo2); + addConsoleAction("fuelinfo", showFuelInfo); +#endif + +#if EFI_PROD_CODE || defined(__DOXYGEN__) + subscription[(int) RO_TRG1_DUTY] = true; + subscription[(int) RO_TRG2_DUTY] = true; + subscription[(int) RO_TRG3_DUTY] = false; + subscription[(int) RO_TRG4_DUTY] = false; + subscription[(int) RO_TOTAL_REVOLUTION_COUNTER] = true; + subscription[(int) RO_RUNNING_REVOLUTION_COUNTER] = false; + + addConsoleActionI("subscribe", subscribe); + addConsoleActionI("unsubscribe", unsubscribe); + addConsoleActionI("set_led_blinking_period", setBlinkingPeriod); + + addConsoleAction("status", printStatus); +#endif /* EFI_PROD_CODE */ +} + +void startStatusThreads(Engine *engine) { + // todo: refactoring needed, this file should probably be split into pieces + chThdCreateStatic(lcdThreadStack, sizeof(lcdThreadStack), NORMALPRIO, (tfunc_t) lcdThread, engine); +#if EFI_PROD_CODE || defined(__DOXYGEN__) + initStatusLeds(); + chThdCreateStatic(blinkingStack, sizeof(blinkingStack), NORMALPRIO, (tfunc_t) blinkingThread, NULL); +#endif /* EFI_PROD_CODE */ +} + +void setFullLog(int value) { + print("Setting full logging: %s\r\n", boolToString(value)); + printMsg(&logger, "%s%d", FULL_LOGGING_KEY, value); + fullLog = value; +} + +bool getFullLog(void) { + return fullLog; +} diff --git a/firmware/rusefi.cpp b/firmware/rusefi.cpp index 48e37bda3a..00f429064d 100644 --- a/firmware/rusefi.cpp +++ b/firmware/rusefi.cpp @@ -249,5 +249,5 @@ int getRusEfiVersion(void) { return 123; // this is here to make the compiler happy about the unused array if (UNUSED_CCM_SIZE[0] * 0 != 0) return 3211; // this is here to make the compiler happy about the unused array - return 20170218; + return 20170220; } diff --git a/firmware/svnversion.h b/firmware/svnversion.h index 96c68c093f..791bce512c 100644 --- a/firmware/svnversion.h +++ b/firmware/svnversion.h @@ -1,5 +1,4 @@ -// This file was generated by Version2Header -// Sat Feb 18 17:30:53 EST 2017 -#ifndef VCS_VERSION -#define VCS_VERSION "11558" -#endif +// This file was generated by Version2Header +#ifndef SVN_VERSION +#define SVN_VERSION 2922 +#endif