rusefi-1/firmware/console/status_loop.cpp

795 lines
26 KiB
C++
Raw Normal View History

2015-07-10 06:01:56 -07:00
/**
* @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
2015-12-31 13:02:30 -08:00
* @author Andrey Belomutskiy, (c) 2012-2016
2015-07-10 06:01:56 -07:00
*
* This file is part of rusEfi - see http://rusefi.com
*
* rusEfi is free software; you can redistribute it and/or modify it under the terms of
* the GNU General Public License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* rusEfi is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program.
* If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "main.h"
#include "status_loop.h"
#include "adc_inputs.h"
#if EFI_WAVE_ANALYZER || defined(__DOXYGEN__)
#include "wave_analyzer.h"
2016-08-23 20:03:01 -07:00
#endif /* EFI_WAVE_ANALYZER */
2015-07-10 06:01:56 -07:00
2015-08-30 15:01:44 -07:00
// see RUS_EFI_VERSION_TAG in console source code
#define RUS_EFI_VERSION_TAG "rusEfiVersion"
2015-07-10 06:01:56 -07:00
#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"
2016-01-11 16:02:19 -08:00
extern bool main_loop_started;
2015-07-10 06:01:56 -07:00
#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
extern engine_pins_s enginePins;
2016-01-11 16:02:19 -08:00
static bool subscription[(int) RO_LAST_ELEMENT];
2015-07-10 06:01:56 -07:00
// 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];
static Logging logger("status loop", LOGGING_BUFFER, sizeof(LOGGING_BUFFER));
static void setWarningEnabled(int value) {
warningEnabled = value;
}
#if EFI_FILE_LOGGING || defined(__DOXYGEN__)
static LoggingWithStorage fileLogger("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
;
2016-05-12 14:03:37 -07:00
static char buf[6];
2015-07-10 06:01:56 -07:00
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);
int rpm = 0;
#if EFI_SHAFT_POSITION_INPUT || defined(__DOXYGEN__)
rpm = getRpmE(engine);
reportSensorI(log, fileFormat, "rpm", "RPM", rpm);
// reportSensorF(log, fileFormat, "TRG_0_DUTY", "%", getTriggerDutyCycle(0), 2);
// reportSensorF(log, fileFormat, "TRG_1_DUTY", "%", getTriggerDutyCycle(1), 2);
#endif
if (hasMafSensor()) {
2016-07-07 20:01:43 -07:00
reportSensorF(log, fileFormat, "maf", "V", getMaf(PASS_ENGINE_PARAMETER_F), 2);
reportSensorF(log, fileFormat, "mafr", "kg/hr", getRealMaf(PASS_ENGINE_PARAMETER_F), 2);
2015-07-10 06:01:56 -07:00
}
2016-07-07 20:01:43 -07:00
reportSensorF(log, fileFormat, "ENGINE_LOAD", "x", getEngineLoadT(PASS_ENGINE_PARAMETER_F), 2);
2015-07-10 06:01:56 -07:00
2016-05-12 14:03:37 -07:00
2015-07-10 06:01:56 -07:00
#if EFI_ANALOG_SENSORS || defined(__DOXYGEN__)
if (engineConfiguration->hasMapSensor) {
reportSensorF(log, fileFormat, "MAP", "kPa", getMap(), 2);
// reportSensorF(log, fileFormat, "map_r", "V", getRawMap(), 2);
}
if (hasBaroSensor()) {
reportSensorF(log, fileFormat, "baro", "kPa", getBaroPressure(), 2);
}
if (engineConfiguration->hasAfrSensor) {
2016-02-06 14:01:38 -08:00
reportSensorF(log, fileFormat, "afr", "AFR", getAfr(PASS_ENGINE_PARAMETER_F), 2);
2015-07-10 06:01:56 -07:00
}
2016-06-09 08:02:31 -07:00
reportSensorF(log, fileFormat, "target", "AFR", engine->engineState.targetAFR, 2);
2015-07-10 06:01:56 -07:00
#endif
if (engineConfiguration->hasVehicleSpeedSensor) {
2016-06-20 17:02:47 -07:00
#if EFI_VEHICLE_SPEED || defined(__DOXYGEN__)
float vehicleSpeed = getVehicleSpeed();
#else
float vehicleSpeed = 0;
2015-07-10 06:01:56 -07:00
#endif /* EFI_PROD_CODE */
2016-06-20 17:02:47 -07:00
reportSensorF(log, fileFormat, "vss", "kph", vehicleSpeed, 2);
reportSensorF(log, fileFormat, "sp2rpm", "x", vehicleSpeed / rpm, 2);
}
2015-07-10 06:01:56 -07:00
2016-07-13 16:03:06 -07:00
reportSensorI(log, fileFormat, "warn", "count", engine->engineState.warningCounter);
2016-07-13 19:02:35 -07:00
reportSensorI(log, fileFormat, "error", "code", engine->engineState.lastErrorCode);
2016-07-13 16:03:06 -07:00
2016-06-02 12:01:39 -07:00
reportSensorF(log, fileFormat, "knck_c", "count", engine->knockCount, 0);
reportSensorF(log, fileFormat, "knck_v", "v", engine->knockVolts, 2);
2015-07-10 06:01:56 -07:00
2016-07-19 21:03:19 -07:00
#if EFI_PROD_CODE || defined(__DOXYGEN__)
2016-07-19 20:03:32 -07:00
reportSensorF(log, fileFormat, "int_temp", "C", getMCUInternalTemperature(), 2);
2016-07-19 21:03:19 -07:00
#endif
2015-07-10 06:01:56 -07:00
// reportSensorF(log, fileFormat, "vref", "V", getVRef(engineConfiguration), 2);
if (hasVBatt(PASS_ENGINE_PARAMETER_F)) {
reportSensorF(log, fileFormat, "vbatt", "V", getVBatt(PASS_ENGINE_PARAMETER_F), 2);
}
reportSensorF(log, fileFormat, "TP", "%", getTPS(PASS_ENGINE_PARAMETER_F), 2);
if (fileFormat) {
reportSensorF(log, fileFormat, "tpsacc", "ms", engine->tpsAccelEnrichment.getTpsEnrichment(PASS_ENGINE_PARAMETER_F), 2);
2016-06-02 12:01:39 -07:00
reportSensorF(log, fileFormat, "advance", "deg", engine->engineState.timingAdvance, 2);
reportSensorF(log, fileFormat, "duty", "%", getInjectorDutyCycle(rpm PASS_ENGINE_PARAMETER), 2);
2016-06-09 08:02:31 -07:00
reportSensorF(log, fileFormat, "tCharge", "K", engine->engineState.tChargeK, 2);
2015-07-10 06:01:56 -07:00
}
if (engineConfiguration->hasCltSensor) {
reportSensorF(log, fileFormat, "CLT", "C", getCoolantTemperature(PASS_ENGINE_PARAMETER_F), 2);
}
reportSensorF(log, fileFormat, "MAT", "C", getIntakeAirTemperature(PASS_ENGINE_PARAMETER_F), 2);
// debugFloat(&logger, "tch", getTCharge1(tps), 2);
2016-08-17 21:02:22 -07:00
for (int i = 0;i<FSIO_ADC_COUNT;i++) {
if (engineConfiguration->fsioAdc[i] != EFI_ADC_NONE) {
strcpy(buf, "adcX");
buf[3] = '0' + i;
reportSensorF(log, fileFormat, buf, "", getVoltage("fsio", engineConfiguration->fsioAdc[i]), 2);
}
2016-05-12 14:03:37 -07:00
}
2015-07-10 06:01:56 -07:00
}
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;i<strlen(msg);i++) {
// ITM_SendChar(msg[i]);
// }
int rpm = getRpmE(engine);
if (subscription[(int) RO_TOTAL_REVOLUTION_COUNTER])
debugInt(&logger, "ckp_c", getCrankEventCounter());
if (subscription[(int) RO_RUNNING_REVOLUTION_COUNTER])
2015-09-13 14:02:44 -07:00
debugInt(&logger, "ckp_r", engine->triggerCentral.triggerState.runningRevolutionCounter);
2015-07-10 06:01:56 -07:00
if (subscription[(int) RO_RUNNING_TRIGGER_ERROR])
2015-09-13 14:02:44 -07:00
debugInt(&logger, "trg_r_errors", engine->triggerCentral.triggerState.runningTriggerErrorCounter);
2015-07-10 06:01:56 -07:00
if (subscription[(int) RO_RUNNING_ORDERING_TRIGGER_ERROR])
2015-09-13 14:02:44 -07:00
debugInt(&logger, "trg_r_order_errors", engine->triggerCentral.triggerState.runningOrderingErrorCounter);
2015-07-10 06:01:56 -07:00
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 engineLoad = getEngineLoadT(PASS_ENGINE_PARAMETER_F);
float baseFuel = getBaseFuel(rpm PASS_ENGINE_PARAMETER);
debugFloat(&logger, "fuel_base", baseFuel, 2);
2016-02-06 09:02:24 -08:00
debugFloat(&logger, "fuel_lag", engine->engineState.injectorLag, 2);
2015-08-23 20:02:37 -07:00
debugFloat(&logger, "fuel", ENGINE(actualLastInjection), 2);
2015-07-10 06:01:56 -07:00
debugFloat(&logger, "timing", engine->engineState.timingAdvance, 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) {
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;
2015-08-30 15:01:44 -07:00
appendPrintf(&logger, "%s%s%d@%s %s %d%s", RUS_EFI_VERSION_TAG, DELIMETER,
getRusEfiVersion(), VCS_VERSION,
2015-07-10 06:01:56 -07:00
getConfigurationName(engineConfiguration->engineType),
2015-08-30 15:01:44 -07:00
getTimeNowSeconds(),
2015-07-10 06:01:56 -07:00
DELIMETER);
#if EFI_PROD_CODE || defined(__DOXYGEN__)
printOutPin(CRANK1, boardConfiguration->triggerInputPins[0]);
printOutPin(CRANK2, boardConfiguration->triggerInputPins[1]);
2016-08-23 20:03:01 -07:00
printOutPin(VVT_NAME, engineConfiguration->camInput);
2015-07-10 06:01:56 -07:00
#if EFI_WAVE_ANALYZER || defined(__DOXYGEN__)
printOutPin(WA_CHANNEL_1, boardConfiguration->logicAnalyzerPins[0]);
printOutPin(WA_CHANNEL_2, boardConfiguration->logicAnalyzerPins[1]);
2016-08-23 20:03:01 -07:00
#endif /* EFI_WAVE_ANALYZER */
2015-07-10 06:01:56 -07:00
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]);
}
2016-08-23 20:03:01 -07:00
#endif /* EFI_PROD_CODE */
2015-07-10 06:01:56 -07:00
}
static systime_t timeOfPreviousReport = (systime_t) -1;
extern char errorMessageBuffer[200];
/**
* @brief Sends all pending data to dev console
*/
void updateDevConsoleState(Engine *engine) {
if (!isConsoleReady()) {
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__)
2016-01-20 14:01:53 -08:00
printFullAdcReportIfNeeded();
2015-07-10 06:01:56 -07:00
#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);
2015-12-02 17:10:06 -08:00
float magicAir = getAirMass(engineConfiguration, 1, 100, convertCelsiusToKelvin(20));
scheduleMsg(&logger, "SD magic fuel %f", sdMath(engineConfiguration, magicAir, 14.7));
2015-07-10 06:01:56 -07:00
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->algorithm),
boolToString(enginePins.fuelPumpRelay.getLogicValue()));
2015-08-30 20:01:27 -07:00
scheduleMsg(&logger2, "injection phase=%f/global fuel correction=%f", getinjectionOffset(rpm), engineConfiguration->globalFuelCorrection);
2015-07-10 06:01:56 -07:00
scheduleMsg(&logger2, "baro correction=%f", engine->engineState.baroCorrection);
2015-08-30 20:01:27 -07:00
#if EFI_ENGINE_CONTROL || defined(__DOXYGEN__)
2015-07-10 06:01:56 -07:00
scheduleMsg(&logger, "base cranking fuel %f", engineConfiguration->cranking.baseFuel);
scheduleMsg(&logger2, "cranking fuel: %f", getCrankingFuel(PASS_ENGINE_PARAMETER_F));
if (engine->rpmCalculator.isRunning()) {
float iatCorrection = engine->engineState.iatFuelCorrection;
float cltCorrection = engine->engineState.cltFuelCorrection;
2016-02-06 09:02:24 -08:00
floatms_t injectorLag = engine->engineState.injectorLag;
2015-07-10 06:01:56 -07:00
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
}
2015-08-23 19:01:55 -07:00
#if EFI_ENGINE_CONTROL || defined(__DOXYGEN__)
2015-07-10 06:01:56 -07:00
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);
static OutputPin communicationPin;
OutputPin checkEnginePin;
OutputPin warningPin;
OutputPin runningPin;
extern engine_pins_s enginePins;
static OutputPin *leds[] = { &warningPin, &runningPin, &enginePins.errorLedPin, &communicationPin, &checkEnginePin };
2015-10-31 14:01:24 -07:00
extern pin_output_mode_e DEFAULT_OUTPUT;
2015-07-10 06:01:56 -07:00
static void initStatisLeds() {
2015-08-23 19:01:55 -07:00
#if EFI_PROD_CODE || defined(__DOXYGEN__)
2015-10-31 14:01:24 -07:00
outputPinRegisterExt2("communication status 1", &communicationPin,
engineConfiguration->communicationPin, &DEFAULT_OUTPUT);
2015-07-10 06:01:56 -07:00
#endif
2015-08-23 19:01:55 -07:00
#if EFI_WARNING_LED || defined(__DOXYGEN__)
2015-07-10 06:01:56 -07:00
outputPinRegister("warning", &warningPin, LED_WARNING_PORT,
LED_WARNING_PIN);
2015-10-31 14:01:24 -07:00
outputPinRegisterExt2("is running status", &runningPin, engineConfiguration->runningPin,
&DEFAULT_OUTPUT);
2015-07-10 06:01:56 -07:00
#endif /* EFI_WARNING_LED */
}
/**
* This method would blink all the LEDs just to test them
*/
static void initialLedsBlink(void) {
2016-04-11 20:02:23 -07:00
if (hasFirmwareError()) {
// make sure we do not turn the fatal LED off if already have
// fatal error by now
return;
}
2015-07-10 06:01:56 -07:00
int size = sizeof(leds) / sizeof(leds[0]);
2016-04-11 20:02:23 -07:00
for (int i = 0; i < size && !hasFirmwareError(); i++)
2015-07-10 06:01:56 -07:00
leds[i]->setValue(1);
chThdSleepMilliseconds(100);
2016-04-11 20:02:23 -07:00
// re-checking in case the error has happened while we were sleeping
for (int i = 0; i < size && !hasFirmwareError(); i++)
2015-07-10 06:01:56 -07:00
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;
2016-01-11 16:02:19 -08:00
static bool isTriggerErrorNow() {
bool justHadError = (getTimeNowNt() - lastDecodingErrorTime) < US2NT(2 * 1000 * 3 * blinkingPeriod);
2015-07-10 06:01:56 -07:00
return justHadError || isTriggerDecoderError();
}
2016-02-13 18:02:14 -08:00
extern bool consoleByteArrived;
2015-07-10 06:01:56 -07:00
/**
* 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 = isConsoleReady() ? 3 * blinkingPeriod : blinkingPeriod;
#if EFI_INTERNAL_FLASH || defined(__DOXYGEN__)
if (getNeedToWriteConfiguration()) {
delayMs = 2 * delayMs;
}
#endif
communicationPin.setValue(0);
warningPin.setValue(0);
chThdSleepMilliseconds(delayMs);
communicationPin.setValue(1);
#if EFI_ENGINE_CONTROL || defined(__DOXYGEN__)
2016-02-13 18:02:14 -08:00
if (isTriggerErrorNow() || isIgnitionTimingError() || consoleByteArrived) {
consoleByteArrived = false;
2015-07-10 06:01:56 -07:00
warningPin.setValue(1);
2016-02-13 18:02:14 -08:00
}
2015-07-10 06:01:56 -07:00
#endif
chThdSleepMilliseconds(delayMs);
}
}
#endif /* EFI_PROD_CODE */
static void lcdThread(void *arg) {
(void)arg;
chRegSetThreadName("lcd");
while (true) {
2015-09-15 18:01:38 -07:00
if (engineConfiguration->bc.useLcdScreen) {
2015-07-10 06:01:56 -07:00
#if EFI_HD44780_LCD
2015-09-15 18:01:38 -07:00
updateHD44780lcd(engine);
2015-07-10 06:01:56 -07:00
#endif
2015-09-15 18:01:38 -07:00
}
2015-07-10 06:01:56 -07:00
chThdSleepMilliseconds(engineConfiguration->bc.lcdThreadPeriod);
}
}
2015-08-23 19:01:55 -07:00
#if EFI_TUNER_STUDIO || defined(__DOXYGEN__)
2015-07-10 06:01:56 -07:00
extern fuel_Map3D_t veMap;
2016-07-01 19:02:39 -07:00
extern afr_Map3D_t afrMap;
2015-07-10 06:01:56 -07:00
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;
2016-01-20 14:01:53 -08:00
tsOutputChannels->coolantTemperature = coolant;
2015-07-10 06:01:56 -07:00
tsOutputChannels->intakeAirTemperature = intake;
tsOutputChannels->throttlePositon = tps;
2015-08-30 14:01:21 -07:00
tsOutputChannels->massAirFlowVoltage = hasMafSensor() ? getMaf() : 0;
2016-01-20 14:01:53 -08:00
tsOutputChannels->massAirFlow = hasMafSensor() ? getRealMaf() : 0;
2015-08-30 14:01:21 -07:00
2016-03-11 12:01:58 -08:00
tsOutputChannels->veValue = veMap.getValue(rpm, getMap());
tsOutputChannels->currentTargetAfr = afrMap.getValue(rpm, getMap());
2016-02-06 14:01:38 -08:00
tsOutputChannels->airFuelRatio = getAfr(PASS_ENGINE_PARAMETER_F);
2015-07-10 06:01:56 -07:00
if (hasVBatt(PASS_ENGINE_PARAMETER_F)) {
tsOutputChannels->vBatt = getVBatt(PASS_ENGINE_PARAMETER_F);
}
2016-01-31 18:02:03 -08:00
tsOutputChannels->tpsADC = getTPS12bitAdc(PASS_ENGINE_PARAMETER_F) / TPS_TS_CONVERSION;
2015-07-10 06:01:56 -07:00
#if EFI_ANALOG_SENSORS || defined(__DOXYGEN__)
2015-08-30 14:01:21 -07:00
tsOutputChannels->baroPressure = hasBaroSensor() ? getBaroPressure() : 0;
2015-07-10 06:01:56 -07:00
#endif /* EFI_ANALOG_SENSORS */
2016-01-20 14:01:53 -08:00
tsOutputChannels->manifoldAirPressure = getMap();
2015-07-10 06:01:56 -07:00
tsOutputChannels->engineLoad = engineLoad;
tsOutputChannels->rpmAcceleration = engine->rpmCalculator.getRpmAcceleration();
2015-09-13 14:02:44 -07:00
tsOutputChannels->triggerErrorsCounter = engine->triggerCentral.triggerState.totalTriggerErrorCounter;
2015-07-10 06:01:56 -07:00
tsOutputChannels->baroCorrection = engine->engineState.baroCorrection;
2015-08-30 14:01:21 -07:00
tsOutputChannels->pedalPosition = hasPedalPositionSensor(PASS_ENGINE_PARAMETER_F) ? getPedalPosition(PASS_ENGINE_PARAMETER_F) : 0;
2015-07-10 06:01:56 -07:00
tsOutputChannels->knockCount = engine->knockCount;
2015-07-11 13:01:31 -07:00
tsOutputChannels->knockLevel = engine->knockVolts;
2015-12-26 09:03:13 -08:00
tsOutputChannels->fuelTankGauge = engine->engineState.fuelTankGauge;
2016-01-02 22:01:37 -08:00
2015-07-10 06:01:56 -07:00
tsOutputChannels->hasFatalError = hasFirmwareError();
2015-09-13 14:02:44 -07:00
tsOutputChannels->totalTriggerErrorCounter = engine->triggerCentral.triggerState.totalTriggerErrorCounter;
2016-01-02 22:01:37 -08:00
tsOutputChannels->injectorDutyCycle = getInjectorDutyCycle(rpm PASS_ENGINE_PARAMETER);
tsOutputChannels->runningFuel = ENGINE(engineState.runningFuel);
2016-02-06 09:02:24 -08:00
tsOutputChannels->injectorLagMs = ENGINE(engineState.injectorLag);
2016-05-23 18:01:32 -07:00
tsOutputChannels->baseFuel = engine->engineState.baseFuel;
tsOutputChannels->actualLastInjection = ENGINE(actualLastInjection);
2016-07-14 20:02:55 -07:00
efitimesec_t now = getTimeNowSeconds();
tsOutputChannels->timeSeconds = now;
tsOutputChannels->isWarnNow = isWarningNow(now);
2016-01-30 19:03:36 -08:00
2016-03-11 08:03:18 -08:00
if (engineConfiguration->debugMode == DBG_TPS_ACCEL) {
2016-02-04 20:02:52 -08:00
tsOutputChannels->debugIntField1 = engine->tpsAccelEnrichment.cb.getSize();
}
2016-02-02 19:01:38 -08:00
2016-04-09 10:02:13 -07:00
if (engineConfiguration->debugMode == TRIGGER_COUNT) {
tsOutputChannels->debugIntField1 = engine->triggerCentral.getHwEventCounter(0);
tsOutputChannels->debugIntField2 = engine->triggerCentral.getHwEventCounter(1);
tsOutputChannels->debugIntField3 = engine->triggerCentral.getHwEventCounter(2);
2016-05-15 21:02:01 -07:00
} 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]);
}
2016-04-09 10:02:13 -07:00
}
2016-02-06 07:01:34 -08:00
tsOutputChannels->wallFuelAmount = ENGINE(wallFuel).getWallFuel(0);
tsOutputChannels->wallFuelCorrection = ENGINE(wallFuelCorrection);
2016-01-30 19:03:36 -08:00
// TPS acceleration
2016-01-31 10:03:08 -08:00
tsOutputChannels->deltaTps = engine->tpsAccelEnrichment.getMaxDelta();
2016-01-02 22:01:37 -08:00
tsOutputChannels->tpsAccelFuel = engine->engineState.tpsAccelEnrich;
2016-01-30 19:03:36 -08:00
// engine load acceleration
2016-03-12 17:03:40 -08:00
tsOutputChannels->engineLoadAccelExtra = engine->engineLoadAccelEnrichment.getEngineLoadEnrichment(PASS_ENGINE_PARAMETER_F) * 100 / getMap();
tsOutputChannels->engineLoadDelta = engine->engineLoadAccelEnrichment.getMaxDelta();
2015-10-18 11:01:37 -07:00
2015-12-26 09:03:13 -08:00
tsOutputChannels->iatCorrection = ENGINE(engineState.iatFuelCorrection);
tsOutputChannels->cltCorrection = ENGINE(engineState.cltFuelCorrection);
2015-07-10 06:01:56 -07:00
tsOutputChannels->checkEngine = hasErrorCodes();
2016-08-20 20:02:09 -07:00
tsOutputChannels->vvtPosition = engine->triggerCentral.vvtPosition;
2015-07-10 06:01:56 -07:00
#if EFI_PROD_CODE || defined(__DOXYGEN__)
2016-07-19 20:03:32 -07:00
tsOutputChannels->internalMcuTemperature = getMCUInternalTemperature();
2015-10-18 12:01:22 -07:00
tsOutputChannels->idlePosition = getIdlePosition();
2015-07-10 06:01:56 -07:00
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;
2016-01-20 14:01:53 -08:00
tsOutputChannels->isInjectionEnabled = engineConfiguration->isInjectionEnabled;
tsOutputChannels->isCylinderCleanupEnabled = engineConfiguration->isCylinderCleanupEnabled;
tsOutputChannels->isCylinderCleanupActivated = engine->isCylinderCleanupMode;
2015-07-10 06:01:56 -07:00
tsOutputChannels->secondTriggerChannelEnabled = engineConfiguration->secondTriggerChannelEnabled;
#if EFI_VEHICLE_SPEED || defined(__DOXYGEN__)
2016-06-20 14:03:03 -07:00
float vehicleSpeed = getVehicleSpeed();
tsOutputChannels->vehicleSpeedKph = vehicleSpeed;
tsOutputChannels->speedToRpmRatio = vehicleSpeed / rpm;
2015-07-10 06:01:56 -07:00
#endif /* EFI_VEHICLE_SPEED */
tsOutputChannels->isCltError = !isValidCoolantTemperature(getCoolantTemperature(PASS_ENGINE_PARAMETER_F));
tsOutputChannels->isIatError = !isValidIntakeAirTemperature(getIntakeAirTemperature(PASS_ENGINE_PARAMETER_F));
#endif /* EFI_PROD_CODE */
2016-07-13 16:03:06 -07:00
tsOutputChannels->warningCounter = engine->engineState.warningCounter;
2016-07-13 19:02:35 -07:00
tsOutputChannels->lastErrorCode = engine->engineState.lastErrorCode;
2016-07-13 16:03:06 -07:00
2015-07-10 06:01:56 -07:00
tsOutputChannels->knockNowIndicator = engine->knockCount > 0;
tsOutputChannels->knockEverIndicator = engine->knockEver;
tsOutputChannels->clutchUpState = engine->clutchUpState;
tsOutputChannels->clutchDownState = engine->clutchDownState;
tsOutputChannels->tCharge = getTCharge(rpm, tps, coolant, intake);
float timing = engine->engineState.timingAdvance;
tsOutputChannels->ignitionAdvance = timing > 360 ? timing - 720 : timing;
tsOutputChannels->sparkDwell = ENGINE(engineState.sparkDwell);
tsOutputChannels->crankingFuelMs = getCrankingFuel(PASS_ENGINE_PARAMETER_F);
2015-12-02 17:10:06 -08:00
tsOutputChannels->chargeAirMass = engine->engineState.airMass;
2015-07-10 06:01:56 -07:00
}
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);
2015-08-30 20:01:27 -07:00
#if EFI_ENGINE_CONTROL || defined(__DOXYGEN__)
2015-07-10 06:01:56 -07:00
addConsoleActionFF("fuelinfo2", (VoidFloatFloat) showFuelInfo2);
addConsoleAction("fuelinfo", showFuelInfo);
#endif
2015-08-30 20:01:27 -07:00
#if EFI_PROD_CODE || defined(__DOXYGEN__)
2015-07-10 06:01:56 -07:00
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__)
initStatisLeds();
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;
}