2015-07-10 06:01:56 -07:00
|
|
|
/**
|
|
|
|
* @file trigger_decoder.cpp
|
|
|
|
*
|
|
|
|
* @date Dec 24, 2013
|
2020-01-07 21:02:40 -08:00
|
|
|
* @author Andrey Belomutskiy, (c) 2012-2020
|
2015-07-10 06:01:56 -07:00
|
|
|
*
|
2019-09-03 20:35:49 -07:00
|
|
|
*
|
|
|
|
*
|
|
|
|
* enable trigger_details
|
2020-04-10 10:19:54 -07:00
|
|
|
* DBG_TRIGGER_COUNTERS = 5
|
|
|
|
* set debug_mode 5
|
2019-09-03 20:35:49 -07:00
|
|
|
*
|
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/>.
|
|
|
|
*/
|
|
|
|
|
2018-09-16 19:26:57 -07:00
|
|
|
#include "global.h"
|
2019-07-03 18:48:04 -07:00
|
|
|
#include "os_access.h"
|
|
|
|
|
2015-07-10 06:01:56 -07:00
|
|
|
#include "obd_error_codes.h"
|
|
|
|
#include "trigger_decoder.h"
|
|
|
|
#include "cyclic_buffer.h"
|
2019-03-29 06:11:13 -07:00
|
|
|
#include "efi_gpio.h"
|
2015-07-10 06:01:56 -07:00
|
|
|
#include "engine.h"
|
2015-09-12 18:03:09 -07:00
|
|
|
#include "engine_math.h"
|
2015-09-13 13:01:38 -07:00
|
|
|
#include "trigger_central.h"
|
2015-09-23 18:02:33 -07:00
|
|
|
#include "trigger_simulator.h"
|
2019-10-11 17:43:21 -07:00
|
|
|
#include "perf_trace.h"
|
2015-09-12 18:03:09 -07:00
|
|
|
|
2019-04-12 19:07:03 -07:00
|
|
|
#if EFI_SENSOR_CHART
|
2015-09-12 18:03:09 -07:00
|
|
|
#include "sensor_chart.h"
|
|
|
|
#endif
|
2015-07-10 06:01:56 -07:00
|
|
|
|
2019-01-31 14:55:23 -08:00
|
|
|
TriggerState::TriggerState() {
|
|
|
|
resetTriggerState();
|
|
|
|
}
|
|
|
|
|
2019-08-18 12:53:38 -07:00
|
|
|
void TriggerState::setShaftSynchronized(bool value) {
|
|
|
|
if (value) {
|
|
|
|
if (!shaft_is_synchronized) {
|
|
|
|
// just got synchronized
|
|
|
|
mostRecentSyncTime = getTimeNowNt();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// sync loss
|
|
|
|
mostRecentSyncTime = 0;
|
|
|
|
}
|
|
|
|
shaft_is_synchronized = value;
|
|
|
|
}
|
|
|
|
|
2019-01-31 14:55:23 -08:00
|
|
|
void TriggerState::resetTriggerState() {
|
2019-08-18 12:53:38 -07:00
|
|
|
setShaftSynchronized(false);
|
2019-01-31 14:55:23 -08:00
|
|
|
toothed_previous_time = 0;
|
|
|
|
|
|
|
|
memset(toothDurations, 0, sizeof(toothDurations));
|
|
|
|
|
|
|
|
totalRevolutionCounter = 0;
|
|
|
|
totalTriggerErrorCounter = 0;
|
|
|
|
orderingErrorCounter = 0;
|
2020-01-26 09:02:54 -08:00
|
|
|
// we need this initial to have not_running at first invocation
|
|
|
|
previousShaftEventTimeNt = (efitimems_t) -10 * NT_PER_SECOND;
|
2019-01-31 14:55:23 -08:00
|
|
|
lastDecodingErrorTime = US2NT(-10000000LL);
|
|
|
|
someSortOfTriggerError = false;
|
|
|
|
|
|
|
|
memset(toothDurations, 0, sizeof(toothDurations));
|
|
|
|
curSignal = SHAFT_PRIMARY_FALLING;
|
|
|
|
prevSignal = SHAFT_PRIMARY_FALLING;
|
|
|
|
startOfCycleNt = 0;
|
|
|
|
|
|
|
|
resetCurrentCycleState();
|
|
|
|
memset(expectedTotalTime, 0, sizeof(expectedTotalTime));
|
|
|
|
|
|
|
|
totalEventCountBase = 0;
|
|
|
|
isFirstEvent = true;
|
|
|
|
}
|
|
|
|
|
2020-01-26 03:28:33 -08:00
|
|
|
void TriggerState::setTriggerErrorState() {
|
|
|
|
lastDecodingErrorTime = getTimeNowNt();
|
|
|
|
someSortOfTriggerError = true;
|
|
|
|
}
|
|
|
|
|
2019-01-31 14:55:23 -08:00
|
|
|
void TriggerState::resetCurrentCycleState() {
|
|
|
|
memset(currentCycle.eventCount, 0, sizeof(currentCycle.eventCount));
|
|
|
|
memset(currentCycle.timeOfPreviousEventNt, 0, sizeof(currentCycle.timeOfPreviousEventNt));
|
|
|
|
memset(currentCycle.totalTimeNt, 0, sizeof(currentCycle.totalTimeNt));
|
|
|
|
currentCycle.current_index = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
TriggerStateWithRunningStatistics::TriggerStateWithRunningStatistics() :
|
|
|
|
//https://en.cppreference.com/w/cpp/language/zero_initialization
|
|
|
|
timeOfLastEvent(), instantRpmValue()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2019-04-12 19:07:03 -07:00
|
|
|
#if EFI_SHAFT_POSITION_INPUT
|
2015-07-10 06:01:56 -07:00
|
|
|
|
2020-03-29 16:06:03 -07:00
|
|
|
EXTERN_ENGINE;
|
2015-07-10 06:01:56 -07:00
|
|
|
|
2019-04-12 19:07:03 -07:00
|
|
|
#if ! EFI_PROD_CODE
|
2015-07-10 06:01:56 -07:00
|
|
|
bool printTriggerDebug = false;
|
2020-07-19 12:47:21 -07:00
|
|
|
bool printTriggerTrace = false;
|
2015-07-10 06:01:56 -07:00
|
|
|
float actualSynchGap;
|
|
|
|
#endif /* ! EFI_PROD_CODE */
|
|
|
|
|
2020-01-21 22:22:44 -08:00
|
|
|
static Logging * logger = nullptr;
|
2015-07-10 06:01:56 -07:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @return TRUE is something is wrong with trigger decoding
|
|
|
|
*/
|
2020-01-21 22:22:44 -08:00
|
|
|
bool isTriggerDecoderError(DECLARE_ENGINE_PARAMETER_SIGNATURE) {
|
|
|
|
return engine->triggerErrorDetection.sum(6) > 4;
|
2015-07-10 06:01:56 -07:00
|
|
|
}
|
|
|
|
|
2019-12-07 22:09:39 -08:00
|
|
|
void calculateTriggerSynchPoint(TriggerWaveform *shape, TriggerState *state DECLARE_ENGINE_PARAMETER_SUFFIX) {
|
2019-04-12 19:07:03 -07:00
|
|
|
#if EFI_PROD_CODE
|
2020-01-27 21:16:33 -08:00
|
|
|
efiAssertVoid(CUSTOM_TRIGGER_STACK, getCurrentRemainingStack() > EXPECTED_REMAINING_STACK, "calc s");
|
2018-12-25 19:47:29 -08:00
|
|
|
#endif
|
|
|
|
trigger_config_s const*triggerConfig = &engineConfiguration->trigger;
|
|
|
|
|
2020-01-26 11:20:55 -08:00
|
|
|
engine->triggerErrorDetection.clear();
|
|
|
|
shape->triggerShapeSynchPointIndex = state->findTriggerZeroEventIndex(shape, triggerConfig PASS_CONFIG_PARAMETER_SUFFIX);
|
2018-12-25 19:47:29 -08:00
|
|
|
|
|
|
|
int length = shape->getLength();
|
|
|
|
engine->engineCycleEventCount = length;
|
|
|
|
efiAssertVoid(CUSTOM_SHAPE_LEN_ZERO, length > 0, "shapeLength=0");
|
|
|
|
if (length >= PWM_PHASE_MAX_COUNT) {
|
2020-05-23 07:46:28 -07:00
|
|
|
firmwareError(CUSTOM_ERR_TRIGGER_WAVEFORM_TOO_LONG, "Trigger length above maximum: %d", length);
|
2019-08-07 19:02:08 -07:00
|
|
|
shape->setShapeDefinitionError(true);
|
2018-12-25 19:47:29 -08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
float firstAngle = shape->getAngle(shape->triggerShapeSynchPointIndex);
|
2020-01-27 21:16:33 -08:00
|
|
|
assertAngleRange(shape->triggerShapeSynchPointIndex, "firstAngle", CUSTOM_TRIGGER_SYNC_ANGLE);
|
2018-12-25 19:47:29 -08:00
|
|
|
|
2019-02-02 22:49:41 -08:00
|
|
|
int riseOnlyIndex = 0;
|
2018-12-25 19:47:29 -08:00
|
|
|
|
|
|
|
for (int eventIndex = 0; eventIndex < length; eventIndex++) {
|
|
|
|
if (eventIndex == 0) {
|
|
|
|
// explicit check for zero to avoid issues where logical zero is not exactly zero due to float nature
|
|
|
|
shape->eventAngles[0] = 0;
|
|
|
|
// this value would be used in case of front-only
|
|
|
|
shape->eventAngles[1] = 0;
|
2019-02-02 22:49:41 -08:00
|
|
|
shape->riseOnlyIndexes[0] = 0;
|
2018-12-25 19:47:29 -08:00
|
|
|
} else {
|
2020-01-27 21:16:33 -08:00
|
|
|
assertAngleRange(shape->triggerShapeSynchPointIndex, "triggerShapeSynchPointIndex", CUSTOM_TRIGGER_SYNC_ANGLE2);
|
2019-02-21 02:44:45 -08:00
|
|
|
unsigned int triggerDefinitionCoordinate = (shape->triggerShapeSynchPointIndex + eventIndex) % engine->engineCycleEventCount;
|
2020-01-27 21:16:33 -08:00
|
|
|
efiAssertVoid(CUSTOM_TRIGGER_CYCLE, engine->engineCycleEventCount != 0, "zero engineCycleEventCount");
|
2018-12-25 19:47:29 -08:00
|
|
|
int triggerDefinitionIndex = triggerDefinitionCoordinate >= shape->privateTriggerDefinitionSize ? triggerDefinitionCoordinate - shape->privateTriggerDefinitionSize : triggerDefinitionCoordinate;
|
|
|
|
float angle = shape->getAngle(triggerDefinitionCoordinate) - firstAngle;
|
2020-01-27 21:16:33 -08:00
|
|
|
efiAssertVoid(CUSTOM_TRIGGER_CYCLE, !cisnan(angle), "trgSyncNaN");
|
|
|
|
fixAngle(angle, "trgSync", CUSTOM_TRIGGER_SYNC_ANGLE_RANGE);
|
2018-12-25 19:47:29 -08:00
|
|
|
if (engineConfiguration->useOnlyRisingEdgeForTrigger) {
|
2019-02-02 22:49:41 -08:00
|
|
|
if (shape->isRiseEvent[triggerDefinitionIndex]) {
|
|
|
|
riseOnlyIndex += 2;
|
|
|
|
shape->eventAngles[riseOnlyIndex] = angle;
|
|
|
|
shape->eventAngles[riseOnlyIndex + 1] = angle;
|
2018-12-25 19:47:29 -08:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
shape->eventAngles[eventIndex] = angle;
|
|
|
|
}
|
|
|
|
|
2019-02-02 22:49:41 -08:00
|
|
|
shape->riseOnlyIndexes[eventIndex] = riseOnlyIndex;
|
2018-12-25 19:47:29 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-21 18:11:09 -08:00
|
|
|
int64_t TriggerState::getTotalEventCounter() const {
|
2018-12-25 19:47:29 -08:00
|
|
|
return totalEventCountBase + currentCycle.current_index;
|
|
|
|
}
|
|
|
|
|
2019-01-15 17:24:36 -08:00
|
|
|
int TriggerState::getTotalRevolutionCounter() const {
|
2018-12-25 19:47:29 -08:00
|
|
|
return totalRevolutionCounter;
|
|
|
|
}
|
|
|
|
|
2019-01-24 18:12:55 -08:00
|
|
|
void TriggerStateWithRunningStatistics::movePreSynchTimestamps(DECLARE_ENGINE_PARAMETER_SIGNATURE) {
|
|
|
|
// here we take timestamps of events which happened prior to synchronization and place them
|
|
|
|
// at appropriate locations
|
|
|
|
for (int i = 0; i < spinningEventIndex;i++) {
|
|
|
|
timeOfLastEvent[getTriggerSize() - i] = spinningEvents[i];
|
2018-12-25 19:47:29 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-21 18:11:09 -08:00
|
|
|
float TriggerStateWithRunningStatistics::calculateInstantRpm(int *prevIndexOut, efitick_t nowNt DECLARE_ENGINE_PARAMETER_SUFFIX) {
|
2018-12-25 19:47:29 -08:00
|
|
|
int current_index = currentCycle.current_index; // local copy so that noone changes the value on us
|
2019-01-24 18:12:55 -08:00
|
|
|
timeOfLastEvent[current_index] = nowNt;
|
2018-12-25 19:47:29 -08:00
|
|
|
/**
|
|
|
|
* Here we calculate RPM based on last 90 degrees
|
|
|
|
*/
|
2019-12-07 22:09:39 -08:00
|
|
|
angle_t currentAngle = TRIGGER_WAVEFORM(eventAngles[current_index]);
|
2018-12-25 19:47:29 -08:00
|
|
|
// todo: make this '90' depend on cylinder count or trigger shape?
|
2019-06-25 15:20:01 -07:00
|
|
|
if (cisnan(currentAngle)) {
|
|
|
|
return NOISY_RPM;
|
|
|
|
}
|
2018-12-25 19:47:29 -08:00
|
|
|
angle_t previousAngle = currentAngle - 90;
|
2019-11-03 18:19:13 -08:00
|
|
|
fixAngle(previousAngle, "prevAngle", CUSTOM_ERR_TRIGGER_ANGLE_RANGE);
|
2018-12-25 19:47:29 -08:00
|
|
|
// todo: prevIndex should be pre-calculated
|
2019-12-07 22:09:39 -08:00
|
|
|
int prevIndex = TRIGGER_WAVEFORM(triggerIndexByAngle[(int)previousAngle]);
|
2019-09-09 11:41:26 -07:00
|
|
|
|
2020-01-26 09:02:54 -08:00
|
|
|
if (prevIndexOut) {
|
2019-09-09 11:41:26 -07:00
|
|
|
*prevIndexOut = prevIndex;
|
|
|
|
}
|
2018-12-25 19:47:29 -08:00
|
|
|
|
|
|
|
// now let's get precise angle for that event
|
2019-12-07 22:09:39 -08:00
|
|
|
angle_t prevIndexAngle = TRIGGER_WAVEFORM(eventAngles[prevIndex]);
|
2019-09-09 11:41:26 -07:00
|
|
|
efitick_t time90ago = timeOfLastEvent[prevIndex];
|
2019-01-24 18:12:55 -08:00
|
|
|
if (time90ago == 0) {
|
|
|
|
return prevInstantRpmValue;
|
|
|
|
}
|
|
|
|
// we are OK to subtract 32 bit value from more precise 64 bit since the result would 32 bit which is
|
|
|
|
// OK for small time differences like this one
|
|
|
|
uint32_t time = nowNt - time90ago;
|
2018-12-25 19:47:29 -08:00
|
|
|
angle_t angleDiff = currentAngle - prevIndexAngle;
|
|
|
|
// todo: angle diff should be pre-calculated
|
|
|
|
fixAngle(angleDiff, "angleDiff", CUSTOM_ERR_6561);
|
|
|
|
|
|
|
|
// just for safety
|
|
|
|
if (time == 0)
|
|
|
|
return prevInstantRpmValue;
|
|
|
|
|
|
|
|
float instantRpm = (60000000.0 / 360 * US_TO_NT_MULTIPLIER) * angleDiff / time;
|
|
|
|
instantRpmValue[current_index] = instantRpm;
|
|
|
|
|
|
|
|
// This fixes early RPM instability based on incomplete data
|
|
|
|
if (instantRpm < RPM_LOW_THRESHOLD)
|
|
|
|
return prevInstantRpmValue;
|
|
|
|
prevInstantRpmValue = instantRpm;
|
|
|
|
|
|
|
|
return instantRpm;
|
|
|
|
}
|
|
|
|
|
2019-12-21 18:11:09 -08:00
|
|
|
void TriggerStateWithRunningStatistics::setLastEventTimeForInstantRpm(efitick_t nowNt DECLARE_ENGINE_PARAMETER_SUFFIX) {
|
2019-01-24 18:12:55 -08:00
|
|
|
if (shaft_is_synchronized) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// here we remember tooth timestamps which happen prior to synchronization
|
|
|
|
if (spinningEventIndex >= PRE_SYNC_EVENTS) {
|
|
|
|
// too many events while trying to find synchronization point
|
|
|
|
// todo: better implementation would be to shift here or use cyclic buffer so that we keep last
|
|
|
|
// 'PRE_SYNC_EVENTS' events
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
spinningEvents[spinningEventIndex++] = nowNt;
|
2018-12-25 19:47:29 -08:00
|
|
|
}
|
|
|
|
|
2019-12-21 18:11:09 -08:00
|
|
|
void TriggerStateWithRunningStatistics::runtimeStatistics(efitick_t nowNt DECLARE_ENGINE_PARAMETER_SUFFIX) {
|
2018-12-25 19:47:29 -08:00
|
|
|
if (engineConfiguration->debugMode == DBG_INSTANT_RPM) {
|
2019-09-09 11:41:26 -07:00
|
|
|
instantRpm = calculateInstantRpm(NULL, nowNt PASS_ENGINE_PARAMETER_SUFFIX);
|
2018-12-25 19:47:29 -08:00
|
|
|
}
|
|
|
|
if (ENGINE(sensorChartMode) == SC_RPM_ACCEL || ENGINE(sensorChartMode) == SC_DETAILED_RPM) {
|
|
|
|
int prevIndex;
|
|
|
|
instantRpm = calculateInstantRpm(&prevIndex, nowNt PASS_ENGINE_PARAMETER_SUFFIX);
|
|
|
|
|
2019-04-12 19:07:03 -07:00
|
|
|
#if EFI_SENSOR_CHART
|
2019-12-07 22:09:39 -08:00
|
|
|
angle_t currentAngle = TRIGGER_WAVEFORM(eventAngles[currentCycle.current_index]);
|
2019-12-11 14:48:55 -08:00
|
|
|
if (CONFIG(sensorChartMode) == SC_DETAILED_RPM) {
|
2018-12-25 19:47:29 -08:00
|
|
|
scAddData(currentAngle, instantRpm);
|
|
|
|
} else {
|
|
|
|
scAddData(currentAngle, instantRpm / instantRpmValue[prevIndex]);
|
|
|
|
}
|
|
|
|
#endif /* EFI_SENSOR_CHART */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-24 10:42:09 -08:00
|
|
|
bool TriggerState::isValidIndex(TriggerWaveform *triggerShape) const {
|
|
|
|
return currentCycle.current_index < triggerShape->getSize();
|
2015-09-24 19:02:47 -07:00
|
|
|
}
|
|
|
|
|
2015-07-10 06:01:56 -07:00
|
|
|
static trigger_wheel_e eventIndex[6] = { T_PRIMARY, T_PRIMARY, T_SECONDARY, T_SECONDARY, T_CHANNEL_3, T_CHANNEL_3 };
|
2016-06-11 20:02:58 -07:00
|
|
|
static trigger_value_e eventType[6] = { TV_FALL, TV_RISE, TV_FALL, TV_RISE, TV_FALL, TV_RISE };
|
2015-07-10 06:01:56 -07:00
|
|
|
|
|
|
|
#define getCurrentGapDuration(nowNt) \
|
|
|
|
(isFirstEvent ? 0 : (nowNt) - toothed_previous_time)
|
|
|
|
|
2019-04-12 19:07:03 -07:00
|
|
|
#if EFI_UNIT_TEST
|
2020-07-19 12:47:21 -07:00
|
|
|
#define PRINT_INC_INDEX if (printTriggerTrace) {\
|
2017-03-03 19:07:25 -08:00
|
|
|
printf("nextTriggerEvent index=%d\r\n", currentCycle.current_index); \
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
#define PRINT_INC_INDEX {}
|
|
|
|
#endif /* EFI_UNIT_TEST */
|
|
|
|
|
2015-07-10 06:01:56 -07:00
|
|
|
#define nextTriggerEvent() \
|
|
|
|
{ \
|
2015-09-12 13:01:43 -07:00
|
|
|
uint32_t prevTime = currentCycle.timeOfPreviousEventNt[triggerWheel]; \
|
2015-07-10 06:01:56 -07:00
|
|
|
if (prevTime != 0) { \
|
|
|
|
/* even event - apply the value*/ \
|
2015-09-08 20:01:07 -07:00
|
|
|
currentCycle.totalTimeNt[triggerWheel] += (nowNt - prevTime); \
|
|
|
|
currentCycle.timeOfPreviousEventNt[triggerWheel] = 0; \
|
2015-07-10 06:01:56 -07:00
|
|
|
} else { \
|
|
|
|
/* odd event - start accumulation */ \
|
2015-09-08 20:01:07 -07:00
|
|
|
currentCycle.timeOfPreviousEventNt[triggerWheel] = nowNt; \
|
2015-07-10 06:01:56 -07:00
|
|
|
} \
|
2016-02-27 20:03:34 -08:00
|
|
|
if (engineConfiguration->useOnlyRisingEdgeForTrigger) {currentCycle.current_index++;} \
|
2015-09-08 20:01:07 -07:00
|
|
|
currentCycle.current_index++; \
|
2017-03-03 19:07:25 -08:00
|
|
|
PRINT_INC_INDEX; \
|
2015-07-10 06:01:56 -07:00
|
|
|
}
|
|
|
|
|
2020-01-26 00:33:45 -08:00
|
|
|
#define considerEventForGap() (!triggerShape->useOnlyPrimaryForSync || isPrimary)
|
2017-03-18 18:36:51 -07:00
|
|
|
|
2020-01-26 00:33:45 -08:00
|
|
|
#define needToSkipFall(type) ((!triggerShape->gapBothDirections) && (( triggerShape->useRiseEdge) && (type != TV_RISE)))
|
|
|
|
#define needToSkipRise(type) ((!triggerShape->gapBothDirections) && ((!triggerShape->useRiseEdge) && (type != TV_FALL)))
|
2017-03-18 18:36:51 -07:00
|
|
|
|
2019-01-15 17:24:36 -08:00
|
|
|
int TriggerState::getCurrentIndex() const {
|
2018-02-05 14:25:01 -08:00
|
|
|
return currentCycle.current_index;
|
|
|
|
}
|
2018-02-05 14:29:16 -08:00
|
|
|
|
2019-09-02 11:47:05 -07:00
|
|
|
void TriggerCentral::validateCamVvtCounters() {
|
2019-05-10 21:21:37 -07:00
|
|
|
// micro-optimized 'totalRevolutionCounter % 256'
|
2019-09-02 11:47:05 -07:00
|
|
|
int camVvtValidationIndex = triggerState.getTotalRevolutionCounter() & 0xFF;
|
2019-05-10 21:21:37 -07:00
|
|
|
if (camVvtValidationIndex == 0) {
|
|
|
|
vvtCamCounter = 0;
|
|
|
|
} else if (camVvtValidationIndex == 0xFE && vvtCamCounter < 60) {
|
|
|
|
// magic logic: we expect at least 60 CAM/VVT events for each 256 trigger cycles, otherwise throw a code
|
|
|
|
warning(OBD_Camshaft_Position_Sensor_Circuit_Range_Performance, "no CAM signals");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-05 14:29:16 -08:00
|
|
|
void TriggerState::incrementTotalEventCounter() {
|
|
|
|
totalRevolutionCounter++;
|
|
|
|
}
|
|
|
|
|
2019-01-15 17:24:36 -08:00
|
|
|
bool TriggerState::isEvenRevolution() const {
|
2018-02-05 14:29:16 -08:00
|
|
|
return totalRevolutionCounter & 1;
|
|
|
|
}
|
|
|
|
|
2020-01-26 00:48:25 -08:00
|
|
|
bool TriggerState::validateEventCounters(TriggerWaveform *triggerShape) const {
|
2020-01-26 03:35:51 -08:00
|
|
|
bool isDecodingError = false;
|
2020-01-26 06:00:46 -08:00
|
|
|
for (int i = 0;i < PWM_PHASE_MAX_WAVE_PER_PWM;i++) {
|
2020-04-06 08:29:09 -07:00
|
|
|
isDecodingError |= (currentCycle.eventCount[i] != triggerShape->expectedEventCount[i]);
|
2020-01-26 03:35:51 -08:00
|
|
|
}
|
|
|
|
|
2019-01-23 19:06:42 -08:00
|
|
|
|
|
|
|
#if EFI_UNIT_TEST
|
2019-12-05 22:57:11 -08:00
|
|
|
printf("sync point: isDecodingError=%d\r\n", isDecodingError);
|
2019-01-23 19:06:42 -08:00
|
|
|
if (isDecodingError) {
|
2020-01-26 06:00:46 -08:00
|
|
|
for (int i = 0;i < PWM_PHASE_MAX_WAVE_PER_PWM;i++) {
|
2020-01-26 03:35:51 -08:00
|
|
|
printf("count: cur=%d exp=%d\r\n", currentCycle.eventCount[i], triggerShape->expectedEventCount[i]);
|
|
|
|
}
|
2019-01-23 19:06:42 -08:00
|
|
|
}
|
|
|
|
#endif /* EFI_UNIT_TEST */
|
|
|
|
|
|
|
|
return isDecodingError;
|
|
|
|
}
|
|
|
|
|
2019-12-05 22:05:19 -08:00
|
|
|
void TriggerState::onShaftSynchronization(const TriggerStateCallback triggerCycleCallback,
|
2020-04-12 06:39:14 -07:00
|
|
|
efitick_t nowNt, TriggerWaveform *triggerShape) {
|
2020-01-24 10:42:09 -08:00
|
|
|
|
2019-01-23 19:31:16 -08:00
|
|
|
|
2020-01-26 09:02:54 -08:00
|
|
|
if (triggerCycleCallback) {
|
2019-01-23 19:31:16 -08:00
|
|
|
triggerCycleCallback(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
startOfCycleNt = nowNt;
|
|
|
|
resetCurrentCycleState();
|
|
|
|
incrementTotalEventCounter();
|
2020-01-24 10:42:09 -08:00
|
|
|
totalEventCountBase += triggerShape->getSize();
|
2019-01-23 19:31:16 -08:00
|
|
|
|
2019-04-12 19:07:03 -07:00
|
|
|
#if EFI_UNIT_TEST
|
2019-01-23 19:31:16 -08:00
|
|
|
if (printTriggerDebug) {
|
2019-05-14 16:24:18 -07:00
|
|
|
printf("onShaftSynchronization index=%d %d\r\n",
|
2019-01-23 19:31:16 -08:00
|
|
|
currentCycle.current_index,
|
|
|
|
totalRevolutionCounter);
|
|
|
|
}
|
|
|
|
#endif /* EFI_UNIT_TEST */
|
|
|
|
}
|
|
|
|
|
2015-07-10 06:01:56 -07:00
|
|
|
/**
|
|
|
|
* @brief Trigger decoding happens here
|
2020-07-30 16:24:55 -07:00
|
|
|
* VR falls are filtered out and some VR noise detection happens prior to invoking this method, for
|
|
|
|
* Hall this method is invoked every time we have a fall or rise on one of the trigger sensors.
|
2015-07-10 06:01:56 -07:00
|
|
|
* This method changes the state of trigger_state_s data structure according to the trigger event
|
2015-08-22 08:02:10 -07:00
|
|
|
* @param signal type of event which just happened
|
|
|
|
* @param nowNt current time
|
2015-07-10 06:01:56 -07:00
|
|
|
*/
|
2020-01-26 00:33:45 -08:00
|
|
|
void TriggerState::decodeTriggerEvent(TriggerWaveform *triggerShape, const TriggerStateCallback triggerCycleCallback,
|
2019-12-05 22:57:11 -08:00
|
|
|
TriggerStateListener * triggerStateListener,
|
2020-01-26 00:33:45 -08:00
|
|
|
trigger_event_e const signal, efitick_t nowNt DECLARE_CONFIG_PARAMETER_SUFFIX) {
|
2020-04-29 07:53:35 -07:00
|
|
|
ScopePerf perf(PE::DecodeTriggerEvent);
|
2019-10-11 17:43:21 -07:00
|
|
|
|
2020-01-26 09:02:54 -08:00
|
|
|
if (nowNt - previousShaftEventTimeNt > NT_PER_SECOND) {
|
|
|
|
/**
|
|
|
|
* We are here if there is a time gap between now and previous shaft event - that means the engine is not running.
|
|
|
|
* That means we have lost synchronization since the engine is not running :)
|
|
|
|
*/
|
|
|
|
setShaftSynchronized(false);
|
|
|
|
if (triggerStateListener) {
|
|
|
|
triggerStateListener->OnTriggerSynchronizationLost();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
previousShaftEventTimeNt = nowNt;
|
|
|
|
|
|
|
|
|
2018-12-25 09:27:34 -08:00
|
|
|
bool useOnlyRisingEdgeForTrigger = CONFIG(useOnlyRisingEdgeForTrigger);
|
2020-01-26 00:33:45 -08:00
|
|
|
|
2018-12-25 09:27:34 -08:00
|
|
|
|
2020-01-27 21:16:33 -08:00
|
|
|
efiAssertVoid(CUSTOM_TRIGGER_UNEXPECTED, signal <= SHAFT_3RD_RISING, "unexpected signal");
|
2015-07-10 06:01:56 -07:00
|
|
|
|
|
|
|
trigger_wheel_e triggerWheel = eventIndex[signal];
|
2016-06-11 20:02:58 -07:00
|
|
|
trigger_value_e type = eventType[signal];
|
2015-07-10 06:01:56 -07:00
|
|
|
|
2018-12-25 09:27:34 -08:00
|
|
|
if (!useOnlyRisingEdgeForTrigger && curSignal == prevSignal) {
|
2015-07-10 06:01:56 -07:00
|
|
|
orderingErrorCounter++;
|
|
|
|
}
|
|
|
|
|
|
|
|
prevSignal = curSignal;
|
|
|
|
curSignal = signal;
|
|
|
|
|
2015-09-08 20:01:07 -07:00
|
|
|
currentCycle.eventCount[triggerWheel]++;
|
2015-07-10 06:01:56 -07:00
|
|
|
|
2019-01-22 20:15:33 -08:00
|
|
|
efiAssertVoid(CUSTOM_OBD_93, toothed_previous_time <= nowNt, "toothed_previous_time after nowNt");
|
|
|
|
|
2019-12-21 18:11:09 -08:00
|
|
|
efitick_t currentDurationLong = getCurrentGapDuration(nowNt);
|
2015-07-10 06:01:56 -07:00
|
|
|
|
|
|
|
/**
|
|
|
|
* For performance reasons, we want to work with 32 bit values. If there has been more then
|
|
|
|
* 10 seconds since previous trigger event we do not really care.
|
|
|
|
*/
|
2018-10-21 11:03:51 -07:00
|
|
|
toothDurations[0] =
|
2020-01-19 19:23:41 -08:00
|
|
|
currentDurationLong > 10 * NT_PER_SECOND ? 10 * NT_PER_SECOND : currentDurationLong;
|
2015-07-10 06:01:56 -07:00
|
|
|
|
2016-01-11 14:01:33 -08:00
|
|
|
bool isPrimary = triggerWheel == T_PRIMARY;
|
2015-07-15 20:07:51 -07:00
|
|
|
|
2019-10-29 18:12:44 -07:00
|
|
|
if (needToSkipFall(type) || needToSkipRise(type) || (!considerEventForGap())) {
|
2019-04-12 19:07:03 -07:00
|
|
|
#if EFI_UNIT_TEST
|
2020-07-19 12:47:21 -07:00
|
|
|
if (printTriggerTrace) {
|
2019-12-02 07:03:50 -08:00
|
|
|
printf("%s isLessImportant %s now=%d index=%d\r\n",
|
2015-07-10 06:01:56 -07:00
|
|
|
getTrigger_type_e(engineConfiguration->trigger.type),
|
2015-09-22 20:01:31 -07:00
|
|
|
getTrigger_event_e(signal),
|
2019-12-02 07:03:50 -08:00
|
|
|
(int)nowNt,
|
2017-03-03 19:07:25 -08:00
|
|
|
currentCycle.current_index);
|
2015-07-10 06:01:56 -07:00
|
|
|
}
|
2017-05-25 20:23:51 -07:00
|
|
|
#endif /* EFI_UNIT_TEST */
|
2015-07-10 06:01:56 -07:00
|
|
|
|
|
|
|
/**
|
|
|
|
* For less important events we simply increment the index.
|
|
|
|
*/
|
|
|
|
nextTriggerEvent()
|
|
|
|
;
|
2015-09-13 13:01:38 -07:00
|
|
|
} else {
|
2015-07-10 06:01:56 -07:00
|
|
|
|
2019-04-12 19:07:03 -07:00
|
|
|
#if EFI_UNIT_TEST
|
2020-07-19 12:47:21 -07:00
|
|
|
if (printTriggerTrace) {
|
2015-09-22 20:01:31 -07:00
|
|
|
printf("%s event %s %d\r\n",
|
|
|
|
getTrigger_type_e(engineConfiguration->trigger.type),
|
|
|
|
getTrigger_event_e(signal),
|
|
|
|
nowNt);
|
|
|
|
}
|
2017-05-25 20:23:51 -07:00
|
|
|
#endif /* EFI_UNIT_TEST */
|
2015-09-22 20:01:31 -07:00
|
|
|
|
2015-09-23 20:01:40 -07:00
|
|
|
isFirstEvent = false;
|
2015-07-10 06:01:56 -07:00
|
|
|
// todo: skip a number of signal from the beginning
|
|
|
|
|
2019-04-12 19:07:03 -07:00
|
|
|
#if EFI_PROD_CODE
|
2018-10-21 09:29:41 -07:00
|
|
|
// scheduleMsg(&logger, "from %.2f to %.2f %d %d", triggerConfig->syncRatioFrom, triggerConfig->syncRatioTo, toothDurations[0], shaftPositionState->toothDurations[1]);
|
|
|
|
// scheduleMsg(&logger, "ratio %.2f", 1.0 * toothDurations[0]/ shaftPositionState->toothDurations[1]);
|
2015-07-10 06:01:56 -07:00
|
|
|
#else
|
2020-07-19 12:47:21 -07:00
|
|
|
if (printTriggerTrace) {
|
2020-07-19 11:17:15 -07:00
|
|
|
printf("decodeTriggerEvent ratio %.2f: current=%d previous=%d\r\n", 1.0 * toothDurations[0] / toothDurations[1],
|
2018-10-21 09:29:41 -07:00
|
|
|
toothDurations[0], toothDurations[1]);
|
2015-09-23 20:01:40 -07:00
|
|
|
}
|
2015-07-10 06:01:56 -07:00
|
|
|
#endif
|
|
|
|
|
2016-01-11 14:01:33 -08:00
|
|
|
bool isSynchronizationPoint;
|
2019-05-10 19:55:08 -07:00
|
|
|
bool wasSynchronized = shaft_is_synchronized;
|
2015-07-10 06:01:56 -07:00
|
|
|
|
2019-09-03 16:30:51 -07:00
|
|
|
DISPLAY_STATE(Trigger_State)
|
|
|
|
DISPLAY_TEXT(Current_Gap);
|
|
|
|
DISPLAY(DISPLAY_FIELD(currentGap));
|
|
|
|
DISPLAY_TEXT(EOL);
|
|
|
|
|
|
|
|
DISPLAY_STATE(Trigger_Central)
|
2019-07-20 11:56:56 -07:00
|
|
|
DISPLAY(DISPLAY_CONFIG(TRIGGERINPUTPINS1));
|
2020-02-22 12:39:00 -08:00
|
|
|
DISPLAY_TEXT("Trigger 1: Fall");
|
2019-07-20 11:56:56 -07:00
|
|
|
DISPLAY(DISPLAY_FIELD(HWEVENTCOUNTERS1));
|
2020-02-22 12:39:00 -08:00
|
|
|
DISPLAY_TEXT(", Rise");
|
2019-07-20 11:56:56 -07:00
|
|
|
DISPLAY(DISPLAY_FIELD(HWEVENTCOUNTERS2));
|
|
|
|
DISPLAY_TEXT(EOL);
|
|
|
|
|
|
|
|
DISPLAY(DISPLAY_CONFIG(TRIGGERINPUTPINS2));
|
2020-02-22 12:39:00 -08:00
|
|
|
DISPLAY_TEXT("Trigger 2: Fall");
|
2019-07-20 11:56:56 -07:00
|
|
|
DISPLAY(DISPLAY_FIELD(HWEVENTCOUNTERS3));
|
2020-02-22 12:39:00 -08:00
|
|
|
DISPLAY_TEXT(", Rise");
|
2019-07-20 11:56:56 -07:00
|
|
|
DISPLAY(DISPLAY_FIELD(HWEVENTCOUNTERS4));
|
2019-09-02 11:47:05 -07:00
|
|
|
DISPLAY_TEXT(EOL);
|
|
|
|
|
|
|
|
DISPLAY_TEXT(VVT_1);
|
|
|
|
DISPLAY(DISPLAY_CONFIG(CAMINPUTS1));
|
2019-09-02 18:02:08 -07:00
|
|
|
DISPLAY(DISPLAY_FIELD(vvtEventRiseCounter));
|
|
|
|
DISPLAY(DISPLAY_FIELD(vvtEventFallCounter));
|
2019-09-02 11:47:05 -07:00
|
|
|
DISPLAY(DISPLAY_FIELD(vvtCamCounter));
|
2019-07-20 11:56:56 -07:00
|
|
|
|
2018-12-25 09:27:34 -08:00
|
|
|
if (triggerShape->isSynchronizationNeeded) {
|
2017-03-04 17:19:14 -08:00
|
|
|
|
2019-09-03 16:30:51 -07:00
|
|
|
currentGap = 1.0 * toothDurations[0] / toothDurations[1];
|
|
|
|
|
2020-04-10 10:19:54 -07:00
|
|
|
if (CONFIG(debugMode) == DBG_TRIGGER_COUNTERS) {
|
2019-04-12 19:07:03 -07:00
|
|
|
#if EFI_TUNER_STUDIO
|
2020-04-10 10:19:54 -07:00
|
|
|
tsOutputChannels.debugFloatField6 = currentGap;
|
|
|
|
tsOutputChannels.debugIntField3 = currentCycle.current_index;
|
2018-11-16 04:40:06 -08:00
|
|
|
#endif /* EFI_TUNER_STUDIO */
|
2017-05-12 19:31:02 -07:00
|
|
|
}
|
|
|
|
|
2019-07-12 18:31:58 -07:00
|
|
|
bool isSync = true;
|
2018-10-23 00:47:30 -07:00
|
|
|
for (int i = 0;i<GAP_TRACKING_LENGTH;i++) {
|
2020-01-26 00:33:45 -08:00
|
|
|
bool isGapCondition = cisnan(triggerShape->syncronizationRatioFrom[i]) || (toothDurations[i] > toothDurations[i + 1] * triggerShape->syncronizationRatioFrom[i]
|
2018-12-25 09:27:34 -08:00
|
|
|
&& toothDurations[i] < toothDurations[i + 1] * triggerShape->syncronizationRatioTo[i]);
|
2017-03-04 17:19:14 -08:00
|
|
|
|
2019-07-12 18:31:58 -07:00
|
|
|
isSync &= isGapCondition;
|
|
|
|
|
2018-10-28 12:42:15 -07:00
|
|
|
}
|
|
|
|
isSynchronizationPoint = isSync;
|
2019-11-10 09:39:47 -08:00
|
|
|
if (isSynchronizationPoint) {
|
|
|
|
enginePins.debugTriggerSync.setValue(1);
|
|
|
|
}
|
2017-03-04 17:19:14 -08:00
|
|
|
|
2015-07-10 06:01:56 -07:00
|
|
|
|
2019-07-22 14:38:52 -07:00
|
|
|
/**
|
|
|
|
* todo: technically we can afford detailed logging even with 60/2 as long as low RPM
|
|
|
|
* todo: figure out exact threshold as a function of RPM and tooth count?
|
|
|
|
* Open question what is 'triggerShape->getSize()' for 60/2 is it 58 or 58*2 or 58*4?
|
|
|
|
*/
|
|
|
|
bool silentTriggerError = triggerShape->getSize() > 40 && CONFIG(silentTriggerError);
|
|
|
|
|
2019-08-24 22:35:36 -07:00
|
|
|
#if EFI_UNIT_TEST
|
|
|
|
actualSynchGap = 1.0 * toothDurations[0] / toothDurations[1];
|
|
|
|
#endif /* EFI_UNIT_TEST */
|
2018-10-28 12:42:15 -07:00
|
|
|
|
2019-10-29 18:12:44 -07:00
|
|
|
#if EFI_PROD_CODE || EFI_SIMULATOR
|
2019-08-24 22:35:36 -07:00
|
|
|
if (CONFIG(verboseTriggerSynchDetails) || (someSortOfTriggerError && !silentTriggerError)) {
|
2018-10-23 00:47:30 -07:00
|
|
|
for (int i = 0;i<GAP_TRACKING_LENGTH;i++) {
|
2020-01-26 00:33:45 -08:00
|
|
|
float ratioFrom = triggerShape->syncronizationRatioFrom[i];
|
2019-12-25 12:05:02 -08:00
|
|
|
if (cisnan(ratioFrom)) {
|
|
|
|
// we do not track gap at this depth
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2018-10-28 12:42:15 -07:00
|
|
|
float gap = 1.0 * toothDurations[i] / toothDurations[i + 1];
|
2019-06-25 17:51:29 -07:00
|
|
|
if (cisnan(gap)) {
|
2019-07-14 10:15:48 -07:00
|
|
|
scheduleMsg(logger, "index=%d NaN gap, you have noise issues?",
|
2019-06-25 17:51:29 -07:00
|
|
|
i);
|
|
|
|
} else {
|
2020-04-15 17:07:56 -07:00
|
|
|
scheduleMsg(logger, "rpm=%d time=%d index=%d: gap=%.3f expected from %.3f to %.3f error=%s",
|
|
|
|
GET_RPM(),
|
2019-10-29 18:12:44 -07:00
|
|
|
/* cast is needed to make sure we do not put 64 bit value to stack*/ (int)getTimeNowSeconds(),
|
2018-10-28 12:42:15 -07:00
|
|
|
i,
|
|
|
|
gap,
|
2019-12-25 12:05:02 -08:00
|
|
|
ratioFrom,
|
2020-01-26 00:33:45 -08:00
|
|
|
triggerShape->syncronizationRatioTo[i],
|
2019-07-14 10:15:48 -07:00
|
|
|
boolToString(someSortOfTriggerError));
|
2019-06-25 17:51:29 -07:00
|
|
|
}
|
2018-10-21 08:27:14 -07:00
|
|
|
}
|
2019-08-24 22:35:36 -07:00
|
|
|
}
|
2015-07-10 06:01:56 -07:00
|
|
|
#else
|
2020-07-19 12:47:21 -07:00
|
|
|
if (printTriggerTrace) {
|
2018-10-28 12:42:15 -07:00
|
|
|
float gap = 1.0 * toothDurations[0] / toothDurations[1];
|
|
|
|
for (int i = 0;i<GAP_TRACKING_LENGTH;i++) {
|
|
|
|
float gap = 1.0 * toothDurations[i] / toothDurations[i + 1];
|
2019-07-14 09:25:54 -07:00
|
|
|
print("index=%d: gap=%.2f expected from %.2f to %.2f error=%s\r\n",
|
2018-10-28 12:42:15 -07:00
|
|
|
i,
|
|
|
|
gap,
|
2020-01-26 00:33:45 -08:00
|
|
|
triggerShape->syncronizationRatioFrom[i],
|
|
|
|
triggerShape->syncronizationRatioTo[i],
|
2019-07-14 09:25:54 -07:00
|
|
|
boolToString(someSortOfTriggerError));
|
2018-10-28 12:42:15 -07:00
|
|
|
}
|
2019-08-24 22:35:36 -07:00
|
|
|
}
|
2018-10-28 12:42:15 -07:00
|
|
|
|
|
|
|
|
2015-07-10 06:01:56 -07:00
|
|
|
#endif /* EFI_PROD_CODE */
|
2019-11-10 09:39:47 -08:00
|
|
|
enginePins.debugTriggerSync.setValue(0);
|
2015-07-10 06:01:56 -07:00
|
|
|
|
2015-09-23 20:01:40 -07:00
|
|
|
} else {
|
|
|
|
/**
|
2017-03-03 18:57:28 -08:00
|
|
|
* We are here in case of a wheel without synchronization - we just need to count events,
|
|
|
|
* synchronization point simply happens once we have the right number of events
|
|
|
|
*
|
|
|
|
* in case of noise the counter could be above the expected number of events, that's why 'more or equals' and not just 'equals'
|
2015-09-23 20:01:40 -07:00
|
|
|
*/
|
2017-03-03 18:49:55 -08:00
|
|
|
|
2019-04-12 19:07:03 -07:00
|
|
|
#if EFI_UNIT_TEST
|
2020-07-19 12:47:21 -07:00
|
|
|
if (printTriggerTrace) {
|
|
|
|
printf("decodeTriggerEvent sync=%d index=%d size=%d\r\n",
|
2017-03-03 18:49:55 -08:00
|
|
|
shaft_is_synchronized,
|
|
|
|
currentCycle.current_index,
|
2020-01-24 10:42:09 -08:00
|
|
|
triggerShape->getSize());
|
2018-04-25 23:11:51 -07:00
|
|
|
}
|
2017-05-25 20:23:51 -07:00
|
|
|
#endif /* EFI_UNIT_TEST */
|
2020-01-24 10:42:09 -08:00
|
|
|
unsigned int endOfCycleIndex = triggerShape->getSize() - (CONFIG(useOnlyRisingEdgeForTrigger) ? 2 : 1);
|
2017-03-03 18:49:55 -08:00
|
|
|
|
2017-03-03 18:57:28 -08:00
|
|
|
|
2017-03-03 18:59:00 -08:00
|
|
|
isSynchronizationPoint = !shaft_is_synchronized || (currentCycle.current_index >= endOfCycleIndex);
|
2015-07-10 06:01:56 -07:00
|
|
|
|
2019-04-12 19:07:03 -07:00
|
|
|
#if EFI_UNIT_TEST
|
2020-07-19 12:47:21 -07:00
|
|
|
if (printTriggerTrace) {
|
|
|
|
printf("decodeTriggerEvent decodeTriggerEvent isSynchronizationPoint=%d index=%d size=%d\r\n",
|
2017-05-25 20:23:51 -07:00
|
|
|
isSynchronizationPoint,
|
|
|
|
currentCycle.current_index,
|
2020-01-24 10:42:09 -08:00
|
|
|
triggerShape->getSize());
|
2017-05-25 20:23:51 -07:00
|
|
|
}
|
|
|
|
#endif /* EFI_UNIT_TEST */
|
2017-03-03 21:43:53 -08:00
|
|
|
|
2015-09-23 20:01:40 -07:00
|
|
|
}
|
2015-07-10 06:01:56 -07:00
|
|
|
|
2019-04-12 19:07:03 -07:00
|
|
|
#if EFI_UNIT_TEST
|
2020-07-19 12:47:21 -07:00
|
|
|
if (printTriggerTrace) {
|
|
|
|
printf("decodeTriggerEvent %s isSynchronizationPoint=%d index=%d %s\r\n",
|
2015-07-10 06:01:56 -07:00
|
|
|
getTrigger_type_e(engineConfiguration->trigger.type),
|
2015-09-08 20:01:07 -07:00
|
|
|
isSynchronizationPoint, currentCycle.current_index,
|
2015-07-10 06:01:56 -07:00
|
|
|
getTrigger_event_e(signal));
|
|
|
|
}
|
2017-05-25 20:23:51 -07:00
|
|
|
#endif /* EFI_UNIT_TEST */
|
2015-07-10 06:01:56 -07:00
|
|
|
|
2015-09-23 20:01:40 -07:00
|
|
|
if (isSynchronizationPoint) {
|
2015-07-10 06:01:56 -07:00
|
|
|
|
2020-01-22 10:25:35 -08:00
|
|
|
if (triggerStateListener) {
|
|
|
|
triggerStateListener->OnTriggerSyncronization(wasSynchronized);
|
|
|
|
}
|
|
|
|
|
2020-01-24 10:42:09 -08:00
|
|
|
setShaftSynchronized(true);
|
|
|
|
// this call would update duty cycle values
|
|
|
|
nextTriggerEvent()
|
|
|
|
;
|
2015-07-10 06:01:56 -07:00
|
|
|
|
2020-04-12 06:39:14 -07:00
|
|
|
onShaftSynchronization(triggerCycleCallback, nowNt, triggerShape);
|
2015-07-10 06:01:56 -07:00
|
|
|
|
2018-04-25 23:11:51 -07:00
|
|
|
} else { /* if (!isSynchronizationPoint) */
|
2015-09-23 20:01:40 -07:00
|
|
|
nextTriggerEvent()
|
|
|
|
;
|
|
|
|
}
|
2015-07-10 06:01:56 -07:00
|
|
|
|
2018-10-23 00:47:30 -07:00
|
|
|
for (int i = GAP_TRACKING_LENGTH; i > 0; i--) {
|
2018-10-21 11:55:52 -07:00
|
|
|
toothDurations[i] = toothDurations[i - 1];
|
|
|
|
}
|
|
|
|
|
2015-09-23 20:01:40 -07:00
|
|
|
toothed_previous_time = nowNt;
|
2015-09-13 13:01:38 -07:00
|
|
|
}
|
2020-01-24 10:42:09 -08:00
|
|
|
if (!isValidIndex(triggerShape) && triggerStateListener) {
|
2020-01-26 00:33:45 -08:00
|
|
|
triggerStateListener->OnTriggerInvalidIndex(currentCycle.current_index);
|
2015-09-25 06:06:35 -07:00
|
|
|
}
|
|
|
|
if (someSortOfTriggerError) {
|
2020-01-19 19:23:41 -08:00
|
|
|
if (getTimeNowNt() - lastDecodingErrorTime > NT_PER_SECOND) {
|
2015-09-25 06:06:35 -07:00
|
|
|
someSortOfTriggerError = false;
|
|
|
|
}
|
2015-09-24 19:02:47 -07:00
|
|
|
}
|
|
|
|
|
2015-09-13 13:01:38 -07:00
|
|
|
|
2018-03-10 17:58:51 -08:00
|
|
|
// Needed for early instant-RPM detection
|
2020-01-22 10:25:35 -08:00
|
|
|
if (triggerStateListener) {
|
2019-12-05 22:57:11 -08:00
|
|
|
triggerStateListener->OnTriggerStateProperState(nowNt);
|
2018-03-10 17:58:51 -08:00
|
|
|
}
|
2015-07-10 06:01:56 -07:00
|
|
|
}
|
|
|
|
|
2018-02-05 14:30:19 -08:00
|
|
|
static void onFindIndexCallback(TriggerState *state) {
|
2015-07-10 06:01:56 -07:00
|
|
|
for (int i = 0; i < PWM_PHASE_MAX_WAVE_PER_PWM; i++) {
|
|
|
|
// todo: that's not the best place for this intermediate data storage, fix it!
|
2015-09-08 20:01:07 -07:00
|
|
|
state->expectedTotalTime[i] = state->currentCycle.totalTimeNt[i];
|
2015-07-10 06:01:56 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Trigger shape is defined in a way which is convenient for trigger shape definition
|
|
|
|
* On the other hand, trigger decoder indexing begins from synchronization event.
|
|
|
|
*
|
2019-12-07 22:09:39 -08:00
|
|
|
* This function finds the index of synchronization event within TriggerWaveform
|
2015-07-10 06:01:56 -07:00
|
|
|
*/
|
2020-01-21 21:40:26 -08:00
|
|
|
uint32_t TriggerState::findTriggerZeroEventIndex(TriggerWaveform * shape,
|
2020-01-26 11:20:55 -08:00
|
|
|
trigger_config_s const*triggerConfig DECLARE_CONFIG_PARAMETER_SUFFIX) {
|
2019-02-21 02:44:45 -08:00
|
|
|
UNUSED(triggerConfig);
|
2019-04-12 19:07:03 -07:00
|
|
|
#if EFI_PROD_CODE
|
2019-02-23 09:33:49 -08:00
|
|
|
efiAssert(CUSTOM_ERR_ASSERT, getCurrentRemainingStack() > 128, "findPos", -1);
|
2015-09-13 07:01:39 -07:00
|
|
|
#endif
|
2015-07-10 06:01:56 -07:00
|
|
|
|
2020-01-21 21:40:26 -08:00
|
|
|
|
|
|
|
resetTriggerState();
|
2015-09-13 07:01:39 -07:00
|
|
|
|
2017-02-23 11:00:03 -08:00
|
|
|
if (shape->shapeDefinitionError) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-01-14 08:33:58 -08:00
|
|
|
|
2015-07-10 06:01:56 -07:00
|
|
|
// todo: should this variable be declared 'static' to reduce stack usage?
|
|
|
|
TriggerStimulatorHelper helper;
|
|
|
|
|
2020-01-26 11:20:55 -08:00
|
|
|
uint32_t syncIndex = helper.findTriggerSyncPoint(shape, this PASS_CONFIG_PARAMETER_SUFFIX);
|
2017-03-04 05:55:53 -08:00
|
|
|
if (syncIndex == EFI_ERROR_CODE) {
|
|
|
|
return syncIndex;
|
2015-07-10 06:01:56 -07:00
|
|
|
}
|
2020-01-21 21:40:26 -08:00
|
|
|
efiAssert(CUSTOM_ERR_ASSERT, getTotalRevolutionCounter() == 1, "findZero_revCounter", EFI_ERROR_CODE);
|
2015-07-10 06:01:56 -07:00
|
|
|
|
2019-04-12 19:07:03 -07:00
|
|
|
#if EFI_UNIT_TEST
|
2017-03-04 05:55:53 -08:00
|
|
|
if (printTriggerDebug) {
|
2017-03-04 06:06:06 -08:00
|
|
|
printf("findTriggerZeroEventIndex: syncIndex located %d!\r\n", syncIndex);
|
2017-03-04 05:55:53 -08:00
|
|
|
}
|
|
|
|
#endif /* EFI_UNIT_TEST */
|
|
|
|
|
2015-07-10 06:01:56 -07:00
|
|
|
/**
|
|
|
|
* Now that we have just located the synch point, we can simulate the whole cycle
|
|
|
|
* in order to calculate expected duty cycle
|
|
|
|
*
|
|
|
|
* todo: add a comment why are we doing '2 * shape->getSize()' here?
|
|
|
|
*/
|
|
|
|
|
2020-01-26 10:51:35 -08:00
|
|
|
helper.assertSyncPositionAndSetDutyCycle(onFindIndexCallback, syncIndex, this, shape PASS_CONFIG_PARAMETER_SUFFIX);
|
2015-07-10 06:01:56 -07:00
|
|
|
|
2017-03-04 05:55:53 -08:00
|
|
|
return syncIndex % shape->getSize();
|
2015-07-10 06:01:56 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void initTriggerDecoderLogger(Logging *sharedLogger) {
|
|
|
|
logger = sharedLogger;
|
|
|
|
}
|
|
|
|
|
2019-09-19 18:41:52 -07:00
|
|
|
void initTriggerDecoder(DECLARE_ENGINE_PARAMETER_SIGNATURE) {
|
2019-04-12 19:07:03 -07:00
|
|
|
#if EFI_GPIO_HARDWARE
|
2020-05-12 22:16:05 -07:00
|
|
|
enginePins.triggerDecoderErrorPin.initPin("led: trigger debug", CONFIG(triggerErrorPin),
|
2019-12-11 14:48:55 -08:00
|
|
|
&CONFIG(triggerErrorPinMode));
|
2017-04-21 13:20:06 -07:00
|
|
|
#endif /* EFI_GPIO_HARDWARE */
|
2015-07-10 06:01:56 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* EFI_SHAFT_POSITION_INPUT */
|