2015-07-10 06:01:56 -07:00
|
|
|
/**
|
2019-12-03 22:11:10 -08:00
|
|
|
* @file logic_analyzer.cpp
|
2019-05-02 14:52:48 -07:00
|
|
|
* @brief Initialization of Input Capture pins used for rusEfi console sniffer
|
2015-07-10 06:01:56 -07:00
|
|
|
*
|
|
|
|
* This file is responsible for sniffing of external digital signals and registering
|
2019-05-02 14:52:48 -07:00
|
|
|
* these digital events in WaveChart used by the Engine Sniffer tab of rusEfi Console.
|
2015-07-10 06:01:56 -07:00
|
|
|
*
|
2018-04-01 20:28:04 -07:00
|
|
|
* this is rusEfi build-in logic analyzer
|
2015-07-10 06:01:56 -07:00
|
|
|
*
|
|
|
|
* @date Jan 7, 2013
|
2020-01-07 21:02:40 -08:00
|
|
|
* @author Andrey Belomutskiy, (c) 2012-2020
|
2015-07-10 06:01:56 -07:00
|
|
|
*/
|
|
|
|
|
2021-08-03 19:05:01 -07:00
|
|
|
#include "pch.h"
|
2020-10-17 05:00:11 -07:00
|
|
|
#include "logic_analyzer.h"
|
2022-09-07 12:56:45 -07:00
|
|
|
|
2015-07-10 06:01:56 -07:00
|
|
|
#include "eficonsole.h"
|
|
|
|
#include "trigger_central.h"
|
2019-07-06 17:15:49 -07:00
|
|
|
#include "os_util.h"
|
2015-07-10 06:01:56 -07:00
|
|
|
#include "rpm_calculator.h"
|
2015-07-15 18:01:45 -07:00
|
|
|
#include "engine_sniffer.h"
|
2022-06-22 17:13:17 -07:00
|
|
|
#include "digital_input_exti.h"
|
2015-07-10 06:01:56 -07:00
|
|
|
|
2019-12-03 22:11:10 -08:00
|
|
|
#if EFI_LOGIC_ANALYZER
|
2015-07-10 06:01:56 -07:00
|
|
|
|
|
|
|
#define CHART_RESET_DELAY 1
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Difference between current 1st trigger event and previous 1st trigger event.
|
|
|
|
*/
|
|
|
|
static volatile uint32_t engineCycleDurationUs;
|
2019-12-21 18:11:09 -08:00
|
|
|
static volatile efitimeus_t previousEngineCycleTimeUs = 0;
|
2015-07-10 06:01:56 -07:00
|
|
|
|
2022-09-10 20:33:37 -07:00
|
|
|
class WaveReader {
|
|
|
|
public:
|
|
|
|
void onFallEvent();
|
|
|
|
|
|
|
|
ioline_t line = 0;
|
|
|
|
|
|
|
|
int laIndex;
|
|
|
|
volatile int fallEventCounter = 0;
|
|
|
|
volatile int riseEventCounter = 0;
|
|
|
|
|
|
|
|
int currentRevolutionCounter = 0;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Total ON time during last engine cycle
|
|
|
|
*/
|
|
|
|
efitimeus_t prevTotalOnTimeUs = 0;
|
|
|
|
|
|
|
|
efitimeus_t totalOnTimeAccumulatorUs = 0;
|
|
|
|
|
|
|
|
volatile efitimeus_t lastActivityTimeUs = 0; // timestamp in microseconds ticks
|
|
|
|
/**
|
|
|
|
* time of signal fall event, in microseconds
|
|
|
|
*/
|
|
|
|
volatile efitimeus_t periodEventTimeUs = 0;
|
|
|
|
volatile efitimeus_t widthEventTimeUs = 0; // time of signal rise in microseconds
|
|
|
|
|
|
|
|
volatile efitimeus_t signalPeriodUs = 0; // period between two signal rises in microseconds
|
|
|
|
|
|
|
|
/**
|
|
|
|
* offset from engine cycle start in microseconds
|
|
|
|
*/
|
|
|
|
volatile efitimeus_t waveOffsetUs = 0;
|
|
|
|
volatile efitimeus_t last_wave_low_widthUs = 0; // time period in systimer ticks
|
|
|
|
volatile efitimeus_t last_wave_high_widthUs = 0; // time period in systimer ticks
|
|
|
|
};
|
|
|
|
|
|
|
|
static WaveReader readers[LOGIC_ANALYZER_CHANNEL_COUNT];
|
2015-07-10 06:01:56 -07:00
|
|
|
|
2022-06-22 17:13:17 -07:00
|
|
|
static void riseCallback(WaveReader *reader) {
|
2015-07-10 06:01:56 -07:00
|
|
|
efitick_t nowUs = getTimeNowUs();
|
2017-01-12 06:02:19 -08:00
|
|
|
reader->riseEventCounter++;
|
2015-07-10 06:01:56 -07:00
|
|
|
reader->lastActivityTimeUs = nowUs;
|
2018-09-10 19:24:50 -07:00
|
|
|
assertIsrContext(CUSTOM_ERR_6670);
|
2022-09-10 20:33:37 -07:00
|
|
|
addEngineSnifferLogicAnalyzerEvent(reader->laIndex, FrontDirection::UP);
|
2015-07-10 06:01:56 -07:00
|
|
|
|
|
|
|
uint32_t width = nowUs - reader->periodEventTimeUs;
|
|
|
|
reader->last_wave_low_widthUs = width;
|
|
|
|
|
|
|
|
reader->signalPeriodUs = nowUs - reader->widthEventTimeUs;
|
|
|
|
reader->widthEventTimeUs = nowUs;
|
|
|
|
}
|
|
|
|
|
|
|
|
void WaveReader::onFallEvent() {
|
|
|
|
efitick_t nowUs = getTimeNowUs();
|
2017-01-12 06:02:19 -08:00
|
|
|
fallEventCounter++;
|
2015-07-10 06:01:56 -07:00
|
|
|
lastActivityTimeUs = nowUs;
|
2018-09-10 19:24:50 -07:00
|
|
|
assertIsrContext(CUSTOM_ERR_6670);
|
2022-09-10 20:33:37 -07:00
|
|
|
addEngineSnifferLogicAnalyzerEvent(laIndex, FrontDirection::DOWN);
|
2015-07-10 06:01:56 -07:00
|
|
|
|
|
|
|
efitick_t width = nowUs - widthEventTimeUs;
|
|
|
|
last_wave_high_widthUs = width;
|
|
|
|
|
2020-02-26 15:16:35 -08:00
|
|
|
#if EFI_SHAFT_POSITION_INPUT
|
2019-10-14 03:18:08 -07:00
|
|
|
int revolutionCounter = getRevolutionCounter();
|
2020-02-26 15:16:35 -08:00
|
|
|
#else
|
|
|
|
int revolutionCounter = 0;
|
|
|
|
#endif
|
2015-07-10 06:01:56 -07:00
|
|
|
|
|
|
|
totalOnTimeAccumulatorUs += width;
|
|
|
|
if (currentRevolutionCounter != revolutionCounter) {
|
|
|
|
/**
|
|
|
|
* We are here in case of a new engine cycle
|
|
|
|
*/
|
|
|
|
currentRevolutionCounter = revolutionCounter;
|
|
|
|
prevTotalOnTimeUs = totalOnTimeAccumulatorUs;
|
|
|
|
totalOnTimeAccumulatorUs = 0;
|
|
|
|
|
|
|
|
waveOffsetUs = nowUs - previousEngineCycleTimeUs;
|
|
|
|
}
|
|
|
|
|
|
|
|
periodEventTimeUs = nowUs;
|
|
|
|
}
|
|
|
|
|
2022-10-30 06:47:53 -07:00
|
|
|
void logicAnalyzerCallback(void* arg, efitick_t /*stamp*/) {
|
2022-06-22 17:13:17 -07:00
|
|
|
WaveReader* instance = reinterpret_cast<WaveReader*>(arg);
|
|
|
|
|
|
|
|
bool rise = palReadLine(instance->line) == PAL_HIGH;
|
|
|
|
|
2022-09-10 20:33:37 -07:00
|
|
|
if (rise) {
|
2022-06-22 17:13:17 -07:00
|
|
|
riseCallback(instance);
|
|
|
|
} else {
|
|
|
|
instance->onFallEvent();
|
|
|
|
}
|
2015-07-10 06:01:56 -07:00
|
|
|
}
|
|
|
|
|
2022-10-30 06:47:53 -07:00
|
|
|
static void initWave(size_t index) {
|
2021-11-17 00:54:21 -08:00
|
|
|
brain_pin_e brainPin = engineConfiguration->logicAnalyzerPins[index];
|
2015-07-10 06:01:56 -07:00
|
|
|
|
2022-06-22 17:13:17 -07:00
|
|
|
efiAssertVoid(CUSTOM_ERR_6655, index < efi::size(readers), "too many ICUs");
|
2015-07-10 06:01:56 -07:00
|
|
|
WaveReader *reader = &readers[index];
|
2020-12-15 11:52:48 -08:00
|
|
|
|
2021-01-08 17:01:26 -08:00
|
|
|
if (!isBrainPinValid(brainPin)) {
|
2020-12-15 11:52:48 -08:00
|
|
|
/**
|
|
|
|
* in case we are running, and we select none for a channel that was running,
|
|
|
|
* this way we ensure that we do not get false report from that channel
|
|
|
|
**/
|
2022-06-22 17:13:17 -07:00
|
|
|
reader->line = 0;
|
2020-12-15 11:52:48 -08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-09-10 20:33:37 -07:00
|
|
|
reader->laIndex = index;
|
2015-07-10 06:01:56 -07:00
|
|
|
|
2022-06-22 17:13:17 -07:00
|
|
|
reader->line = PAL_LINE(getHwPort("logic", brainPin), getHwPin("logic", brainPin));
|
2019-11-11 20:04:27 -08:00
|
|
|
|
2022-06-22 17:13:17 -07:00
|
|
|
efiExtiEnablePin("logic", brainPin, PAL_EVENT_MODE_BOTH_EDGES, logicAnalyzerCallback, (void*)reader);
|
2015-07-10 06:01:56 -07:00
|
|
|
|
2021-04-21 09:53:13 -07:00
|
|
|
efiPrintf("wave%d input on %s", index, hwPortname(brainPin));
|
2015-07-10 06:01:56 -07:00
|
|
|
}
|
|
|
|
|
2021-11-16 01:15:29 -08:00
|
|
|
void waTriggerEventListener(trigger_event_e ckpSignalType, uint32_t index, efitick_t edgeTimestamp) {
|
2015-07-10 06:01:56 -07:00
|
|
|
(void)ckpSignalType;
|
|
|
|
if (index != 0) {
|
|
|
|
return;
|
|
|
|
}
|
2020-01-09 12:45:13 -08:00
|
|
|
|
|
|
|
efitimeus_t nowUs = NT2US(edgeTimestamp);
|
2015-07-10 06:01:56 -07:00
|
|
|
engineCycleDurationUs = nowUs - previousEngineCycleTimeUs;
|
|
|
|
previousEngineCycleTimeUs = nowUs;
|
|
|
|
}
|
|
|
|
|
|
|
|
static float getSignalOnTime(int index) {
|
2022-06-22 17:13:17 -07:00
|
|
|
WaveReader& reader = readers[index];
|
|
|
|
|
|
|
|
if (getTimeNowUs() - reader.lastActivityTimeUs > 4 * US_PER_SECOND) {
|
2015-07-10 06:01:56 -07:00
|
|
|
return 0.0f; // dwell time has expired
|
|
|
|
}
|
2022-06-22 17:13:17 -07:00
|
|
|
return reader.last_wave_high_widthUs / 1000.0f;
|
2015-07-10 06:01:56 -07:00
|
|
|
}
|
|
|
|
|
2022-09-11 13:08:11 -07:00
|
|
|
static efitimeus_t getWaveOffset(int index) {
|
2022-06-22 17:13:17 -07:00
|
|
|
return readers[index].waveOffsetUs;
|
2015-07-10 06:01:56 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static float getSignalPeriodMs(int index) {
|
2022-06-22 17:13:17 -07:00
|
|
|
return readers[index].signalPeriodUs / 1000.0f;
|
2015-07-10 06:01:56 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void reportWave(Logging *logging, int index) {
|
2022-06-22 17:13:17 -07:00
|
|
|
if (readers[index].line == 0) {
|
2019-01-11 14:40:00 -08:00
|
|
|
return;
|
|
|
|
}
|
2022-06-22 17:13:17 -07:00
|
|
|
|
2015-07-10 06:01:56 -07:00
|
|
|
// int counter = getEventCounter(index);
|
|
|
|
// debugInt2(logging, "ev", index, counter);
|
|
|
|
|
2022-06-22 17:13:17 -07:00
|
|
|
float dwellMs = getSignalOnTime(index);
|
|
|
|
float periodMs = getSignalPeriodMs(index);
|
|
|
|
|
|
|
|
logging->appendPrintf("duty%d%s", index, LOG_DELIMITER);
|
|
|
|
logging->appendFloat(100.0f * dwellMs / periodMs, 2);
|
|
|
|
logging->appendPrintf("%s", LOG_DELIMITER);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* that's the ON time of the LAST signal
|
|
|
|
*/
|
|
|
|
logging->appendPrintf("dwell%d%s", index, LOG_DELIMITER);
|
|
|
|
logging->appendFloat(dwellMs, 2);
|
|
|
|
logging->appendPrintf("%s", LOG_DELIMITER);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* that's the total ON time during the previous engine cycle
|
|
|
|
*/
|
|
|
|
logging->appendPrintf("total_dwell%d%s", index, LOG_DELIMITER);
|
|
|
|
logging->appendFloat(readers[index].prevTotalOnTimeUs / 1000.0f, 2);
|
|
|
|
logging->appendPrintf("%s", LOG_DELIMITER);
|
|
|
|
|
|
|
|
logging->appendPrintf("period%d%s", index, LOG_DELIMITER);
|
|
|
|
logging->appendFloat(periodMs, 2);
|
|
|
|
logging->appendPrintf("%s", LOG_DELIMITER);
|
|
|
|
|
2022-09-11 13:08:11 -07:00
|
|
|
efitimeus_t offsetUs = getWaveOffset(index);
|
2022-06-22 17:13:17 -07:00
|
|
|
int rpm = Sensor::getOrZero(SensorType::Rpm);
|
|
|
|
if (rpm != 0) {
|
|
|
|
float oneDegreeUs = getOneDegreeTimeUs(rpm);
|
|
|
|
|
|
|
|
logging->appendPrintf("advance%d%s", index, LOG_DELIMITER);
|
|
|
|
float angle = (offsetUs / oneDegreeUs) - tdcPosition();
|
|
|
|
fixAngle(angle, "waveAn", CUSTOM_ERR_6564);
|
|
|
|
logging->appendFloat(angle, 3);
|
2021-11-19 01:01:45 -08:00
|
|
|
logging->appendPrintf("%s", LOG_DELIMITER);
|
2015-07-10 06:01:56 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void printWave(Logging *logging) {
|
|
|
|
reportWave(logging, 0);
|
|
|
|
reportWave(logging, 1);
|
|
|
|
}
|
|
|
|
|
2017-01-12 06:02:19 -08:00
|
|
|
void showWaveInfo(void) {
|
2021-04-21 09:53:13 -07:00
|
|
|
efiPrintf("logic input #1: %d/%d", readers[0].fallEventCounter, readers[0].riseEventCounter);
|
2017-01-12 06:02:19 -08:00
|
|
|
}
|
|
|
|
|
2021-04-21 11:28:48 -07:00
|
|
|
void initWaveAnalyzer() {
|
2016-06-01 17:01:36 -07:00
|
|
|
if (hasFirmwareError()) {
|
|
|
|
return;
|
|
|
|
}
|
2019-11-11 20:32:09 -08:00
|
|
|
|
2020-12-07 17:01:05 -08:00
|
|
|
addConsoleAction("waveinfo", showWaveInfo);
|
|
|
|
}
|
|
|
|
|
|
|
|
void startLogicAnalyzerPins() {
|
2022-10-30 06:47:53 -07:00
|
|
|
for (size_t index = 0; index < LOGIC_ANALYZER_CHANNEL_COUNT; index++) {
|
2022-09-10 20:33:37 -07:00
|
|
|
initWave(index);
|
|
|
|
}
|
2015-07-10 06:01:56 -07:00
|
|
|
}
|
|
|
|
|
2020-12-07 17:01:05 -08:00
|
|
|
void stopLogicAnalyzerPins() {
|
|
|
|
for (int index = 0; index < LOGIC_ANALYZER_CHANNEL_COUNT; index++) {
|
2020-12-07 17:42:47 -08:00
|
|
|
brain_pin_e brainPin = activeConfiguration.logicAnalyzerPins[index];
|
2020-12-06 15:39:50 -08:00
|
|
|
|
2021-01-08 17:01:26 -08:00
|
|
|
if (isBrainPinValid(brainPin)) {
|
2022-06-22 17:13:17 -07:00
|
|
|
efiExtiDisablePin(brainPin);
|
2020-12-07 17:01:05 -08:00
|
|
|
}
|
|
|
|
}
|
2020-12-06 15:39:50 -08:00
|
|
|
}
|
|
|
|
|
2022-10-11 17:58:43 -07:00
|
|
|
template <typename TFreq>
|
|
|
|
static void getChannelFreqAndDuty(int index, float& duty, TFreq& freq) {
|
2022-06-22 17:13:17 -07:00
|
|
|
if (readers[index].line == 0) {
|
2022-10-11 17:58:43 -07:00
|
|
|
duty = 0.0;
|
|
|
|
freq = 0;
|
2020-12-15 11:52:48 -08:00
|
|
|
} else {
|
2022-10-11 17:58:43 -07:00
|
|
|
float high = getSignalOnTime(index);
|
|
|
|
float period = getSignalPeriodMs(index);
|
2020-12-15 11:52:48 -08:00
|
|
|
|
2022-06-22 17:13:17 -07:00
|
|
|
if (period != 0) {
|
2020-12-15 11:52:48 -08:00
|
|
|
|
2022-10-11 17:58:43 -07:00
|
|
|
duty = (high * 1000.0f) /(period * 10.0f);
|
|
|
|
freq = (int)(1 / (period / 1000.0f));
|
2020-12-15 11:52:48 -08:00
|
|
|
} else {
|
2022-10-11 17:58:43 -07:00
|
|
|
duty = 0.0;
|
|
|
|
freq = 0;
|
2020-12-15 11:52:48 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void reportLogicAnalyzerToTS() {
|
2022-10-11 17:58:43 -07:00
|
|
|
#if EFI_TUNER_STUDIO
|
|
|
|
getChannelFreqAndDuty(0, engine->outputChannels.debugFloatField1, engine->outputChannels.debugIntField1);
|
|
|
|
getChannelFreqAndDuty(1, engine->outputChannels.debugFloatField2, engine->outputChannels.debugIntField2);
|
|
|
|
getChannelFreqAndDuty(2, engine->outputChannels.debugFloatField3, engine->outputChannels.debugIntField3);
|
|
|
|
getChannelFreqAndDuty(3, engine->outputChannels.debugFloatField4, engine->outputChannels.debugIntField4);
|
2020-12-15 11:52:48 -08:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2019-12-03 22:11:10 -08:00
|
|
|
#endif /* EFI_LOGIC_ANALYZER */
|