rusefi/firmware/development/engine_sniffer.cpp

289 lines
8.0 KiB
C++
Raw Permalink Normal View History

2015-07-10 06:01:56 -07:00
/**
2015-07-15 18:01:45 -07:00
* @file engine_sniffer.cpp
2019-05-02 14:52:48 -07:00
* @brief rusEfi console wave sniffer logic
2015-07-10 06:01:56 -07:00
*
* Here we have our own build-in logic analyzer. The data we aggregate here is sent to the
2019-05-02 14:52:48 -07:00
* java UI rusEfi Console so that it can be displayed nicely in the Sniffer tab.
2015-07-10 06:01:56 -07:00
*
* Both external events (see logic_analyzer.cpp) and internal (see signal executors) are supported
2015-07-10 06:01:56 -07:00
*
* @date Jun 23, 2013
2020-01-07 21:02:40 -08:00
* @author Andrey Belomutskiy, (c) 2012-2020
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 "pch.h"
2022-09-07 12:56:45 -07:00
2015-07-15 18:01:45 -07:00
#include "engine_sniffer.h"
2016-01-22 23:01:34 -08:00
// a bit weird because of conditional compilation
static char shaft_signal_msg_index[15];
2022-10-29 19:33:50 -07:00
#if EFI_ENGINE_SNIFFER
#define addEngineSnifferEvent(name, msg) { if (getTriggerCentral()->isEngineSnifferEnabled) { waveChart.addEvent3((name), (msg)); } }
#else
#define addEngineSnifferEvent(name, msg) { UNUSED(name); }
2022-10-29 19:33:50 -07:00
#endif /* EFI_ENGINE_SNIFFER */
2019-04-12 19:10:57 -07:00
#if EFI_ENGINE_SNIFFER
2015-07-10 06:01:56 -07:00
#include "eficonsole.h"
#include "status_loop.h"
#define CHART_DELIMETER '!'
2022-09-10 17:25:13 -07:00
extern WaveChart waveChart;
2015-07-10 06:01:56 -07:00
/**
* This is the number of events in the digital chart which would be displayed
* on the 'digital sniffer' pane
*/
#if EFI_PROD_CODE
#define WAVE_LOGGING_SIZE 5000
#else
#define WAVE_LOGGING_SIZE 35000
#endif
static char WAVE_LOGGING_BUFFER[WAVE_LOGGING_SIZE] CCM_OPTIONAL;
2015-07-10 06:01:56 -07:00
int waveChartUsedSize;
//#define DEBUG_WAVE 1
/**
* We want to skip some engine cycles to skip what was scheduled before parameters were changed
*/
2015-07-14 06:01:29 -07:00
static uint32_t skipUntilEngineCycle = 0;
2015-07-10 06:01:56 -07:00
2019-04-12 19:10:57 -07:00
#if ! EFI_UNIT_TEST
2015-07-10 06:01:56 -07:00
extern WaveChart waveChart;
static void resetNow() {
skipUntilEngineCycle = getRevolutionCounter() + 3;
2016-01-30 19:03:36 -08:00
waveChart.reset();
2015-07-10 06:01:56 -07:00
}
2021-04-04 19:01:04 -07:00
#endif // EFI_UNIT_TEST
2015-07-10 06:01:56 -07:00
WaveChart::WaveChart() : logging("wave chart", WAVE_LOGGING_BUFFER, sizeof(WAVE_LOGGING_BUFFER)) {
}
void WaveChart::init() {
isInitialized = true;
reset();
}
2016-01-30 19:03:36 -08:00
void WaveChart::reset() {
2015-07-10 06:01:56 -07:00
#if DEBUG_WAVE
efiPrintf("reset while at ", counter);
2015-07-10 06:01:56 -07:00
#endif /* DEBUG_WAVE */
logging.reset();
2015-07-10 06:01:56 -07:00
counter = 0;
startTimeNt = 0;
collectingData = false;
logging.appendPrintf( "%s%s", PROTOCOL_ENGINE_SNIFFER, LOG_DELIMITER);
2015-07-10 06:01:56 -07:00
}
void WaveChart::startDataCollection() {
collectingData = true;
}
2015-07-10 06:01:56 -07:00
bool WaveChart::isStartedTooLongAgo() const {
2015-07-10 06:01:56 -07:00
/**
* Say at 300rpm we should get at least four events per revolution.
* That's 300/60*4=20 events per second
* engineChartSize/20 is the longest meaningful chart.
*
*/
efitick_t chartDurationNt = getTimeNowNt() - startTimeNt;
2015-07-10 06:01:56 -07:00
return startTimeNt != 0 && NT2US(chartDurationNt) > engineConfiguration->engineChartSize * 1000000 / 20;
}
bool WaveChart::isFull() const {
return counter >= engineConfiguration->engineChartSize;
2015-07-10 06:01:56 -07:00
}
2021-04-04 19:48:48 -07:00
int WaveChart::getSize() {
return counter;
}
2021-04-04 19:01:04 -07:00
#if ! EFI_UNIT_TEST
static void printStatus() {
efiPrintf("engine sniffer: %s", boolToString(getTriggerCentral()->isEngineSnifferEnabled));
efiPrintf("engine sniffer size=%d", engineConfiguration->engineChartSize);
2015-07-10 06:01:56 -07:00
}
void setChartSize(int newSize) {
if (newSize < 5) {
return;
}
engineConfiguration->engineChartSize = newSize;
printStatus();
}
2021-04-04 19:01:04 -07:00
#endif // EFI_UNIT_TEST
2015-07-10 06:01:56 -07:00
2016-01-30 19:03:36 -08:00
void WaveChart::publishIfFull() {
if (isFull() || isStartedTooLongAgo()) {
publish();
reset();
2015-07-10 06:01:56 -07:00
}
}
2016-01-30 19:03:36 -08:00
void WaveChart::publish() {
2022-12-17 11:58:10 -08:00
#if EFI_ENGINE_SNIFFER
logging.appendPrintf( LOG_DELIMITER);
waveChartUsedSize = logging.loggingSize();
2015-07-10 06:01:56 -07:00
#if DEBUG_WAVE
Logging *l = &chart->logging;
efiPrintf("IT'S TIME", strlen(l->buffer));
2022-12-17 11:58:10 -08:00
#endif // DEBUG_WAVE
if (getTriggerCentral()->isEngineSnifferEnabled) {
2015-07-10 06:01:56 -07:00
scheduleLogging(&logging);
}
2022-12-17 11:58:10 -08:00
#endif /* EFI_ENGINE_SNIFFER */
2015-07-10 06:01:56 -07:00
}
/**
* @brief Register an event for digital sniffer
*/
2016-01-30 19:03:36 -08:00
void WaveChart::addEvent3(const char *name, const char * msg) {
#if EFI_TEXT_LOGGING
ScopePerf perf(PE::EngineSniffer);
2020-05-25 20:38:15 -07:00
efitick_t nowNt = getTimeNowNt();
2020-05-25 20:38:15 -07:00
if (nowNt < pauseEngineSnifferUntilNt) {
return;
}
if (!getTriggerCentral()->isEngineSnifferEnabled) {
2015-07-10 06:01:56 -07:00
return;
}
if (skipUntilEngineCycle != 0 && getRevolutionCounter() < skipUntilEngineCycle)
2017-05-25 20:22:35 -07:00
return;
#if EFI_SIMULATOR
// todo: add UI control to enable this for firmware if desired
// engineConfiguration->alignEngineSnifferAtTDC &&
if (!collectingData) {
return;
}
#endif
efiAssertVoid(ObdCode::CUSTOM_ERR_6651, name!=NULL, "WC: NULL name");
2015-07-10 06:01:56 -07:00
#if EFI_PROD_CODE
efiAssertVoid(ObdCode::CUSTOM_ERR_6652, getCurrentRemainingStack() > 32, "lowstck#2c");
#endif /* EFI_PROD_CODE */
2015-07-10 06:01:56 -07:00
efiAssertVoid(ObdCode::CUSTOM_ERR_6653, isInitialized, "chart not initialized");
2015-07-10 06:01:56 -07:00
#if DEBUG_WAVE
efiPrintf("current", chart->counter);
#endif /* DEBUG_WAVE */
2016-01-30 19:03:36 -08:00
if (isFull()) {
2015-07-10 06:01:56 -07:00
return;
}
// we have multiple threads writing to the same output buffer
chibios_rt::CriticalSectionLocker csl;
2015-07-10 06:01:56 -07:00
if (counter == 0) {
startTimeNt = nowNt;
}
counter++;
/**
* We want smaller times within a chart in order to reduce packet size.
*/
/**
* todo: migrate to binary fractions in order to eliminate
* this division? I do not like division
*
* at least that's 32 bit division now
*/
uint32_t diffNt = nowNt - startTimeNt;
2020-05-25 22:08:21 -07:00
uint32_t time100 = NT2US(diffNt / ENGINE_SNIFFER_UNIT_US);
2015-07-10 06:01:56 -07:00
if (logging.remainingSize() > 35) {
2015-07-10 06:01:56 -07:00
/**
* printf is a heavy method, append is used here as a performance optimization
*/
logging.appendFast(name);
logging.appendChar(CHART_DELIMETER);
logging.appendFast(msg);
logging.appendChar(CHART_DELIMETER);
2015-07-10 06:01:56 -07:00
// time100 -= startTime100;
itoa10(timeBuffer, time100);
logging.appendFast(timeBuffer);
logging.appendChar(CHART_DELIMETER);
logging.terminate();
2015-07-10 06:01:56 -07:00
}
2018-09-16 21:00:19 -07:00
#endif /* EFI_TEXT_LOGGING */
2015-07-10 06:01:56 -07:00
}
void initWaveChart(WaveChart *chart) {
strcpy((char*) shaft_signal_msg_index, "x_");
2015-07-10 06:01:56 -07:00
/**
* constructor does not work because we need specific initialization order
*/
chart->init();
2019-04-12 19:10:57 -07:00
#if EFI_HISTOGRAMS
initHistogram(&engineSnifferHisto, "engine sniffer");
2015-07-10 06:01:56 -07:00
#endif /* EFI_HISTOGRAMS */
2021-04-04 19:01:04 -07:00
#if ! EFI_UNIT_TEST
printStatus();
2015-07-10 06:01:56 -07:00
addConsoleActionI("chartsize", setChartSize);
2022-06-17 19:10:34 -07:00
// this is used by HW CI
2019-12-21 16:59:33 -08:00
addConsoleAction(CMD_RESET_ENGINE_SNIFFER, resetNow);
2021-04-04 19:01:04 -07:00
#endif // EFI_UNIT_TEST
2015-07-10 06:01:56 -07:00
}
2015-07-15 18:01:45 -07:00
#endif /* EFI_ENGINE_SNIFFER */
2022-10-29 18:27:49 -07:00
void addEngineSnifferOutputPinEvent(NamedOutputPin *pin, FrontDirection frontDirection) {
if (!engineConfiguration->engineSnifferFocusOnInputs) {
addEngineSnifferEvent(pin->getShortName(), frontDirection == FrontDirection::UP ? PROTOCOL_ES_UP : PROTOCOL_ES_DOWN);
}
}
void addEngineSnifferTdcEvent(int rpm) {
static char rpmBuffer[_MAX_FILLER];
itoa10(rpmBuffer, rpm);
#if EFI_ENGINE_SNIFFER
waveChart.startDataCollection();
#endif
addEngineSnifferEvent(TOP_DEAD_CENTER_MESSAGE, (char* ) rpmBuffer);
}
void addEngineSnifferLogicAnalyzerEvent(int laIndex, FrontDirection frontDirection) {
extern const char *laNames[];
const char *name = laNames[laIndex];
addEngineSnifferEvent(name, frontDirection == FrontDirection::UP ? PROTOCOL_ES_UP : PROTOCOL_ES_DOWN);
}
void addEngineSnifferCrankEvent(int wheelIndex, int triggerEventIndex, FrontDirection frontDirection) {
static const char *crankName[2] = { PROTOCOL_CRANK1, PROTOCOL_CRANK2 };
shaft_signal_msg_index[0] = frontDirection == FrontDirection::UP ? 'u' : 'd';
// shaft_signal_msg_index[1] is assigned once and forever in the init method below
itoa10(&shaft_signal_msg_index[2], triggerEventIndex);
addEngineSnifferEvent(crankName[wheelIndex], (char* ) shaft_signal_msg_index);
}
void addEngineSnifferVvtEvent(int vvtIndex, FrontDirection frontDirection) {
extern const char *vvtNames[];
const char *vvtName = vvtNames[vvtIndex];
addEngineSnifferEvent(vvtName, frontDirection == FrontDirection::UP ? PROTOCOL_ES_UP : PROTOCOL_ES_DOWN);
}