rusefi-1/firmware/controllers/trigger/trigger_decoder.cpp

671 lines
23 KiB
C++
Raw Normal View History

2015-07-10 06:01:56 -07:00
/**
* @file trigger_decoder.cpp
*
* @date Dec 24, 2013
2018-01-20 17:55:31 -08:00
* @author Andrey Belomutskiy, (c) 2012-2018
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"
2015-07-10 06:01:56 -07:00
#if EFI_SHAFT_POSITION_INPUT || defined(__DOXYGEN__)
#include "obd_error_codes.h"
#include "trigger_decoder.h"
#include "cyclic_buffer.h"
#include "efiGpio.h"
#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"
2018-02-03 13:06:34 -08:00
#include "rfiutil.h"
2015-09-12 18:03:09 -07:00
2015-09-13 09:01:42 -07:00
#if EFI_SENSOR_CHART || defined(__DOXYGEN__)
2015-09-12 18:03:09 -07:00
#include "sensor_chart.h"
#endif
2015-07-10 06:01:56 -07:00
EXTERN_ENGINE
;
static cyclic_buffer<int> errorDetection;
2016-05-17 21:03:11 -07:00
static bool isInitializingTrigger = false; // #286 miata NA config - sync error on startup
2015-07-10 06:01:56 -07:00
2015-09-05 20:02:46 -07:00
#if ! EFI_PROD_CODE || defined(__DOXYGEN__)
2015-07-10 06:01:56 -07:00
bool printTriggerDebug = false;
float actualSynchGap;
#endif /* ! EFI_PROD_CODE */
#if EFI_TUNER_STUDIO || defined(__DOXYGEN__)
2017-05-12 19:31:02 -07:00
extern TunerStudioOutputChannels tsOutputChannels;
#endif /* EFI_TUNER_STUDIO */
2017-05-12 19:31:02 -07:00
2015-07-10 06:01:56 -07:00
static Logging * logger;
efitick_t lastDecodingErrorTime = US2NT(-10000000LL);
2015-09-25 06:06:35 -07:00
// the boolean flag is a performance optimization so that complex comparison is avoided if no error
2017-12-06 15:38:25 -08:00
static bool someSortOfTriggerError = false;
2015-07-10 06:01:56 -07:00
/**
* @return TRUE is something is wrong with trigger decoding
*/
2016-01-11 14:01:33 -08:00
bool isTriggerDecoderError(void) {
2015-07-10 06:01:56 -07:00
return errorDetection.sum(6) > 4;
}
void calculateTriggerSynchPoint(TriggerShape *shape, TriggerState *state DECLARE_ENGINE_PARAMETER_SUFFIX) {
#if EFI_PROD_CODE || defined(__DOXYGEN__)
efiAssertVoid(CUSTOM_ERR_6642, getRemainingStack(chThdGetSelfX()) > 256, "calc s");
#endif
trigger_config_s const*triggerConfig = &engineConfiguration->trigger;
shape->triggerShapeSynchPointIndex = findTriggerZeroEventIndex(state, shape, triggerConfig PASS_ENGINE_PARAMETER_SUFFIX);
int length = shape->getLength();
engine->engineCycleEventCount = length;
efiAssertVoid(CUSTOM_SHAPE_LEN_ZERO, length > 0, "shapeLength=0");
if (length >= PWM_PHASE_MAX_COUNT) {
warning(CUSTOM_ERR_TRIGGER_SHAPE_TOO_LONG, "Count above %d", length);
shape->shapeDefinitionError = true;
return;
}
float firstAngle = shape->getAngle(shape->triggerShapeSynchPointIndex);
assertAngleRange(shape->triggerShapeSynchPointIndex, "firstAngle", CUSTOM_ERR_6551);
int frontOnlyIndex = 0;
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;
shape->frontOnlyIndexes[0] = 0;
} else {
assertAngleRange(shape->triggerShapeSynchPointIndex, "triggerShapeSynchPointIndex", CUSTOM_ERR_6552);
int triggerDefinitionCoordinate = (shape->triggerShapeSynchPointIndex + eventIndex) % engine->engineCycleEventCount;
efiAssertVoid(CUSTOM_ERR_6595, engine->engineCycleEventCount != 0, "zero engineCycleEventCount");
int triggerDefinitionIndex = triggerDefinitionCoordinate >= shape->privateTriggerDefinitionSize ? triggerDefinitionCoordinate - shape->privateTriggerDefinitionSize : triggerDefinitionCoordinate;
float angle = shape->getAngle(triggerDefinitionCoordinate) - firstAngle;
efiAssertVoid(CUSTOM_ERR_6596, !cisnan(angle), "trgSyncNaN");
fixAngle(angle, "trgSync", CUSTOM_ERR_6559);
if (engineConfiguration->useOnlyRisingEdgeForTrigger) {
if (shape->isFrontEvent[triggerDefinitionIndex]) {
frontOnlyIndex += 2;
shape->eventAngles[frontOnlyIndex] = angle;
shape->eventAngles[frontOnlyIndex + 1] = angle;
}
} else {
shape->eventAngles[eventIndex] = angle;
}
shape->frontOnlyIndexes[eventIndex] = frontOnlyIndex;
}
}
}
efitime_t TriggerState::getTotalEventCounter() {
return totalEventCountBase + currentCycle.current_index;
}
int TriggerState::getTotalRevolutionCounter() {
return totalRevolutionCounter;
}
TriggerStateWithRunningStatistics::TriggerStateWithRunningStatistics() {
instantRpm = 0;
prevInstantRpmValue = 0;
// avoid ill-defined instant RPM when the data is not gathered yet
efitime_t nowNt = getTimeNowNt();
for (int i = 0; i < PWM_PHASE_MAX_COUNT; i++) {
timeOfLastEvent[i] = nowNt;
}
}
float TriggerStateWithRunningStatistics::calculateInstantRpm(int *prevIndex, efitime_t nowNt DECLARE_ENGINE_PARAMETER_SUFFIX) {
int current_index = currentCycle.current_index; // local copy so that noone changes the value on us
/**
* Here we calculate RPM based on last 90 degrees
*/
angle_t currentAngle = TRIGGER_SHAPE(eventAngles[current_index]);
// todo: make this '90' depend on cylinder count or trigger shape?
angle_t previousAngle = currentAngle - 90;
fixAngle(previousAngle, "prevAngle", CUSTOM_ERR_6560);
// todo: prevIndex should be pre-calculated
*prevIndex = TRIGGER_SHAPE(triggerIndexByAngle[(int)previousAngle]);
// now let's get precise angle for that event
angle_t prevIndexAngle = TRIGGER_SHAPE(eventAngles[*prevIndex]);
uint32_t time = nowNt - timeOfLastEvent[*prevIndex];
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;
timeOfLastEvent[current_index] = nowNt;
// This fixes early RPM instability based on incomplete data
if (instantRpm < RPM_LOW_THRESHOLD)
return prevInstantRpmValue;
prevInstantRpmValue = instantRpm;
return instantRpm;
}
void TriggerStateWithRunningStatistics::setLastEventTimeForInstantRpm(efitime_t nowNt DECLARE_ENGINE_PARAMETER_SUFFIX) {
timeOfLastEvent[currentCycle.current_index] = nowNt;
}
void TriggerStateWithRunningStatistics::runtimeStatistics(efitime_t nowNt DECLARE_ENGINE_PARAMETER_SUFFIX) {
if (engineConfiguration->debugMode == DBG_INSTANT_RPM) {
int prevIndex;
instantRpm = calculateInstantRpm(&prevIndex, nowNt PASS_ENGINE_PARAMETER_SUFFIX);
}
if (ENGINE(sensorChartMode) == SC_RPM_ACCEL || ENGINE(sensorChartMode) == SC_DETAILED_RPM) {
int prevIndex;
instantRpm = calculateInstantRpm(&prevIndex, nowNt PASS_ENGINE_PARAMETER_SUFFIX);
#if EFI_SENSOR_CHART || defined(__DOXYGEN__)
angle_t currentAngle = TRIGGER_SHAPE(eventAngles[currentCycle.current_index]);
if (boardConfiguration->sensorChartMode == SC_DETAILED_RPM) {
scAddData(currentAngle, instantRpm);
} else {
scAddData(currentAngle, instantRpm / instantRpmValue[prevIndex]);
}
#endif /* EFI_SENSOR_CHART */
}
}
2017-05-15 20:28:49 -07:00
bool TriggerState::isValidIndex(DECLARE_ENGINE_PARAMETER_SIGNATURE) {
return currentCycle.current_index < getTriggerSize();
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)
2017-03-03 19:07:25 -08:00
#if EFI_UNIT_TEST || defined(__DOXYGEN__)
#define PRINT_INC_INDEX if (printTriggerDebug) {\
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
}
2017-03-18 18:36:51 -07:00
#define considerEventForGap() (!TRIGGER_SHAPE(useOnlyPrimaryForSync) || isPrimary)
2017-03-18 18:42:17 -07:00
#define needToSkipFall(type) ((!TRIGGER_SHAPE(gapBothDirections)) && (( TRIGGER_SHAPE(useRiseEdge)) && (type != TV_RISE)))
#define needToSkipRise(type) ((!TRIGGER_SHAPE(gapBothDirections)) && ((!TRIGGER_SHAPE(useRiseEdge)) && (type != TV_FALL)))
2017-03-18 18:36:51 -07:00
#define isLessImportant(type) (needToSkipFall(type) || needToSkipRise(type) || (!considerEventForGap()) )
2018-02-05 14:25:01 -08:00
TriggerState::TriggerState() {
reset();
}
2017-03-18 18:36:51 -07:00
2018-02-05 14:25:01 -08:00
void TriggerState::reset() {
triggerCycleCallback = NULL;
shaft_is_synchronized = false;
toothed_previous_time = 0;
2018-10-21 09:03:08 -07:00
2018-10-21 08:27:14 -07:00
memset(toothDurations, 0, sizeof(toothDurations));
2018-02-05 14:25:01 -08:00
totalRevolutionCounter = 0;
totalTriggerErrorCounter = 0;
orderingErrorCounter = 0;
2018-10-21 11:03:51 -07:00
memset(toothDurations, 0, sizeof(toothDurations));
2018-02-05 14:25:01 -08:00
curSignal = SHAFT_PRIMARY_FALLING;
prevSignal = SHAFT_PRIMARY_FALLING;
startOfCycleNt = 0;
resetRunningCounters();
resetCurrentCycleState();
memset(expectedTotalTime, 0, sizeof(expectedTotalTime));
totalEventCountBase = 0;
isFirstEvent = true;
}
int TriggerState::getCurrentIndex() {
return currentCycle.current_index;
}
2018-02-05 14:29:16 -08:00
void TriggerState::incrementTotalEventCounter() {
totalRevolutionCounter++;
}
bool TriggerState::isEvenRevolution() {
return totalRevolutionCounter & 1;
}
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;
}
2018-03-03 16:26:59 -08:00
void TriggerState::onSynchronizationLost(DECLARE_ENGINE_PARAMETER_SIGNATURE) {
shaft_is_synchronized = false;
// Needed for early instant-RPM detection
engine->rpmCalculator.setStopSpinning(PASS_ENGINE_PARAMETER_SIGNATURE);
2018-03-03 16:26:59 -08:00
}
2015-07-10 06:01:56 -07:00
/**
* @brief Trigger decoding happens here
2015-08-22 08:02:10 -07:00
* 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
*/
2017-05-15 20:28:49 -07:00
void TriggerState::decodeTriggerEvent(trigger_event_e const signal, efitime_t nowNt DECLARE_ENGINE_PARAMETER_SUFFIX) {
2018-12-25 09:27:34 -08:00
bool useOnlyRisingEdgeForTrigger = CONFIG(useOnlyRisingEdgeForTrigger);
// todo: use 'triggerShape' instead of TRIGGER_SHAPE in order to decouple this method from engine #635
TriggerShape *triggerShape = &ENGINE(triggerCentral.triggerShape);
2018-07-25 20:03:04 -07:00
efiAssertVoid(CUSTOM_ERR_6640, 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
efitime_t currentDurationLong = getCurrentGapDuration(nowNt);
/**
* 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] =
2015-07-10 06:01:56 -07:00
currentDurationLong > 10 * US2NT(US_PER_SECOND_LL) ? 10 * US2NT(US_PER_SECOND_LL) : currentDurationLong;
2016-01-11 14:01:33 -08:00
bool isPrimary = triggerWheel == T_PRIMARY;
2015-07-15 20:07:51 -07:00
2016-06-14 00:02:57 -07:00
if (isLessImportant(type)) {
2015-09-13 07:01:39 -07:00
#if EFI_UNIT_TEST || defined(__DOXYGEN__)
2015-07-10 06:01:56 -07:00
if (printTriggerDebug) {
printf("%s isLessImportant %s now=%lld 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),
2017-03-03 19:07:25 -08:00
nowNt,
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
2015-09-22 20:01:31 -07:00
#if EFI_UNIT_TEST || defined(__DOXYGEN__)
if (printTriggerDebug) {
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
2015-09-13 07:01:39 -07:00
#if EFI_PROD_CODE || defined(__DOXYGEN__)
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
2017-03-03 18:49:55 -08:00
if (printTriggerDebug) {
2018-10-21 09:29:41 -07:00
printf("ratio %.2f: current=%d previous=%d\r\n", 1.0 * toothDurations[0] / toothDurations[1],
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;
2015-07-10 06:01:56 -07:00
2018-12-25 09:27:34 -08:00
if (triggerShape->isSynchronizationNeeded) {
// this is getting a little out of hand, any ideas?
2017-05-25 20:23:51 -07:00
if (CONFIG(debugMode) == DBG_TRIGGER_SYNC) {
2018-10-21 09:29:41 -07:00
float currentGap = 1.0 * toothDurations[0] / toothDurations[1];
#if EFI_TUNER_STUDIO || defined(__DOXYGEN__)
tsOutputChannels.debugFloatField1 = currentGap;
2017-05-13 05:25:47 -07:00
tsOutputChannels.debugFloatField2 = currentCycle.current_index;
#endif /* EFI_TUNER_STUDIO */
2017-05-12 19:31:02 -07:00
}
2018-10-23 00:47:30 -07:00
bool isGapCondition[GAP_TRACKING_LENGTH];
2018-10-21 09:29:41 -07:00
2018-10-23 00:47:30 -07:00
for (int i = 0;i<GAP_TRACKING_LENGTH;i++) {
2018-12-25 09:27:34 -08:00
isGapCondition[i] = cisnan(triggerShape->syncronizationRatioFrom[i]) || (toothDurations[i] > toothDurations[i + 1] * TRIGGER_SHAPE(syncronizationRatioFrom[i])
&& toothDurations[i] < toothDurations[i + 1] * triggerShape->syncronizationRatioTo[i]);
2018-10-21 09:29:41 -07:00
}
2018-10-28 12:42:15 -07:00
bool isSync = isGapCondition[0];
for (int index = 1; index < GAP_TRACKING_LENGTH ; index++) {
isSync = isSync && isGapCondition[index];
}
isSynchronizationPoint = isSync;
2015-07-10 06:01:56 -07:00
2015-09-11 22:02:28 -07:00
#if EFI_PROD_CODE || defined(__DOXYGEN__)
2017-05-25 20:23:51 -07:00
if (CONFIG(isPrintTriggerSynchDetails) || (someSortOfTriggerError && !CONFIG(silentTriggerError))) {
2015-07-10 06:01:56 -07:00
#else
2015-09-23 20:01:40 -07:00
if (printTriggerDebug) {
2015-07-10 06:01:56 -07:00
#endif /* EFI_PROD_CODE */
2018-10-28 12:42:15 -07:00
2015-09-11 22:02:28 -07:00
#if EFI_PROD_CODE || defined(__DOXYGEN__)
2018-10-21 08:27:14 -07:00
2018-10-23 00:47:30 -07:00
for (int i = 0;i<GAP_TRACKING_LENGTH;i++) {
2018-10-28 12:42:15 -07:00
float gap = 1.0 * toothDurations[i] / toothDurations[i + 1];
scheduleMsg(logger, "%d %d: cur %.2f expected from %.2f to %.2f error=%d",
getTimeNowSeconds(),
i,
gap,
TRIGGER_SHAPE(syncronizationRatioFrom[i]),
TRIGGER_SHAPE(syncronizationRatioTo[i]),
someSortOfTriggerError);
2018-10-21 08:27:14 -07:00
}
2015-07-10 06:01:56 -07:00
#else
2018-10-28 12:42:15 -07:00
float gap = 1.0 * toothDurations[0] / toothDurations[1];
2015-09-23 20:01:40 -07:00
actualSynchGap = gap;
2018-10-28 12:42:15 -07:00
for (int i = 0;i<GAP_TRACKING_LENGTH;i++) {
float gap = 1.0 * toothDurations[i] / toothDurations[i + 1];
2018-11-21 19:15:22 -08:00
print("%d: cur %.2f expected from %.2f to %.2f error=%d\r\n",
2018-10-28 12:42:15 -07:00
i,
gap,
TRIGGER_SHAPE(syncronizationRatioFrom[i]),
TRIGGER_SHAPE(syncronizationRatioTo[i]),
someSortOfTriggerError);
}
2015-07-10 06:01:56 -07:00
#endif /* EFI_PROD_CODE */
2015-09-23 20:01:40 -07:00
}
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
#if EFI_UNIT_TEST || defined(__DOXYGEN__)
if (printTriggerDebug) {
printf("sync=%d index=%d size=%d\r\n",
2017-03-03 18:49:55 -08:00
shaft_is_synchronized,
currentCycle.current_index,
getTriggerSize());
}
2017-05-25 20:23:51 -07:00
#endif /* EFI_UNIT_TEST */
int endOfCycleIndex = getTriggerSize() - (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
2017-03-03 21:43:53 -08:00
#if EFI_UNIT_TEST || defined(__DOXYGEN__)
2017-05-25 20:23:51 -07:00
if (printTriggerDebug) {
printf("isSynchronizationPoint=%d index=%d size=%d\r\n",
isSynchronizationPoint,
currentCycle.current_index,
getTriggerSize());
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
2015-09-13 07:01:39 -07:00
#if EFI_UNIT_TEST || defined(__DOXYGEN__)
2015-07-10 06:01:56 -07:00
if (printTriggerDebug) {
printf("%s isSynchronizationPoint=%d index=%d %s\r\n",
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
2015-09-23 20:01:40 -07:00
/**
* We can check if things are fine by comparing the number of events in a cycle with the expected number of event.
*/
bool isDecodingError = currentCycle.eventCount[0] != TRIGGER_SHAPE(expectedEventCount[0])
|| currentCycle.eventCount[1] != TRIGGER_SHAPE(expectedEventCount[1])
|| currentCycle.eventCount[2] != TRIGGER_SHAPE(expectedEventCount[2]);
2018-11-22 07:01:48 -08:00
#if EFI_UNIT_TEST
printf("sync point: isDecodingError=%d isInit=%d\r\n", isDecodingError, isInitializingTrigger);
if (isDecodingError) {
printf("count: cur=%d exp=%d\r\n", currentCycle.eventCount[0], TRIGGER_SHAPE(expectedEventCount[0]));
printf("count: cur=%d exp=%d\r\n", currentCycle.eventCount[1], TRIGGER_SHAPE(expectedEventCount[1]));
printf("count: cur=%d exp=%d\r\n", currentCycle.eventCount[2], TRIGGER_SHAPE(expectedEventCount[2]));
}
#endif
2016-09-14 16:03:00 -07:00
enginePins.triggerDecoderErrorPin.setValue(isDecodingError);
2016-12-16 18:02:54 -08:00
if (isDecodingError && !isInitializingTrigger) {
2017-05-22 12:30:39 -07:00
if (engineConfiguration->debugMode == DBG_TRIGGER_SYNC) {
#if EFI_TUNER_STUDIO || defined(__DOXYGEN__)
2017-05-12 19:31:02 -07:00
tsOutputChannels.debugIntField1 = currentCycle.eventCount[0];
tsOutputChannels.debugIntField2 = currentCycle.eventCount[1];
tsOutputChannels.debugIntField3 = currentCycle.eventCount[2];
#endif /* EFI_TUNER_STUDIO */
2017-05-12 19:31:02 -07:00
}
2017-01-15 12:06:23 -08:00
warning(CUSTOM_SYNC_COUNT_MISMATCH, "trigger not happy current %d/%d/%d expected %d/%d/%d",
2016-11-08 19:02:47 -08:00
currentCycle.eventCount[0],
currentCycle.eventCount[1],
currentCycle.eventCount[2],
TRIGGER_SHAPE(expectedEventCount[0]),
TRIGGER_SHAPE(expectedEventCount[1]),
TRIGGER_SHAPE(expectedEventCount[2]));
2015-09-23 20:01:40 -07:00
lastDecodingErrorTime = getTimeNowNt();
2015-09-25 06:06:35 -07:00
someSortOfTriggerError = true;
2015-09-23 20:01:40 -07:00
totalTriggerErrorCounter++;
2017-12-06 15:38:25 -08:00
if (CONFIG(isPrintTriggerSynchDetails) || someSortOfTriggerError) {
2015-09-13 07:01:39 -07:00
#if EFI_PROD_CODE || defined(__DOXYGEN__)
2015-09-23 20:01:40 -07:00
scheduleMsg(logger, "error: synchronizationPoint @ index %d expected %d/%d/%d got %d/%d/%d",
currentCycle.current_index, TRIGGER_SHAPE(expectedEventCount[0]),
TRIGGER_SHAPE(expectedEventCount[1]), TRIGGER_SHAPE(expectedEventCount[2]),
currentCycle.eventCount[0], currentCycle.eventCount[1], currentCycle.eventCount[2]);
2015-07-10 06:01:56 -07:00
#endif /* EFI_PROD_CODE */
2015-09-23 20:01:40 -07:00
}
2015-07-10 06:01:56 -07:00
}
2015-09-23 20:01:40 -07:00
errorDetection.add(isDecodingError);
2015-07-10 06:01:56 -07:00
2015-09-23 20:01:40 -07:00
if (isTriggerDecoderError()) {
2016-12-25 18:02:31 -08:00
warning(CUSTOM_OBD_TRG_DECODING, "trigger decoding issue. expected %d/%d/%d got %d/%d/%d",
2015-09-23 20:01:40 -07:00
TRIGGER_SHAPE(expectedEventCount[0]), TRIGGER_SHAPE(expectedEventCount[1]),
TRIGGER_SHAPE(expectedEventCount[2]), currentCycle.eventCount[0], currentCycle.eventCount[1],
currentCycle.eventCount[2]);
}
2015-07-10 06:01:56 -07:00
2015-09-23 20:01:40 -07:00
shaft_is_synchronized = true;
// this call would update duty cycle values
nextTriggerEvent()
;
2015-07-10 06:01:56 -07:00
2018-02-05 14:25:01 -08:00
if (triggerCycleCallback != NULL) {
triggerCycleCallback(this);
}
startOfCycleNt = nowNt;
resetCurrentCycleState();
incrementTotalEventCounter();
runningRevolutionCounter++;
totalEventCountBase += getTriggerSize();
2018-02-05 14:25:01 -08:00
2017-03-03 21:43:53 -08:00
2017-03-03 21:46:02 -08:00
#if EFI_UNIT_TEST || defined(__DOXYGEN__)
2017-03-03 21:43:53 -08:00
if (printTriggerDebug) {
printf("index=%d %d\r\n",
currentCycle.current_index,
runningRevolutionCounter);
}
2017-03-03 21:46:02 -08:00
#endif /* EFI_UNIT_TEST */
} 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
}
2017-05-15 20:28:49 -07:00
if (!isValidIndex(PASS_ENGINE_PARAMETER_SIGNATURE) && !isInitializingTrigger) {
2016-08-26 13:03:22 -07:00
// let's not show a warning if we are just starting to spin
2018-07-24 16:58:32 -07:00
if (GET_RPM() != 0) {
warning(CUSTOM_SYNC_ERROR, "sync error: index #%d above total size %d", currentCycle.current_index, getTriggerSize());
2016-08-26 13:03:22 -07:00
lastDecodingErrorTime = getTimeNowNt();
someSortOfTriggerError = true;
}
2015-09-25 06:06:35 -07:00
}
if (someSortOfTriggerError) {
if (getTimeNowNt() - lastDecodingErrorTime > US2NT(US_PER_SECOND_LL)) {
someSortOfTriggerError = false;
}
2015-09-24 19:02:47 -07:00
}
2017-12-03 21:04:47 -08:00
runtimeStatistics(nowNt PASS_ENGINE_PARAMETER_SUFFIX);
2015-09-13 13:01:38 -07:00
// Needed for early instant-RPM detection
if (!isInitializingTrigger) {
engine->rpmCalculator.setSpinningUp(nowNt PASS_ENGINE_PARAMETER_SUFFIX);
}
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.
*
* This function finds the index of synchronization event within TriggerShape
*/
2015-09-23 20:01:40 -07:00
uint32_t findTriggerZeroEventIndex(TriggerState *state, TriggerShape * shape,
2017-05-15 20:28:49 -07:00
trigger_config_s const*triggerConfig DECLARE_ENGINE_PARAMETER_SUFFIX) {
2015-09-13 07:01:39 -07:00
#if EFI_PROD_CODE || defined(__DOXYGEN__)
2018-07-25 20:30:00 -07:00
efiAssert(CUSTOM_ERR_ASSERT, getRemainingStack(chThdGetSelfX()) > 128, "findPos", -1);
2015-09-13 07:01:39 -07:00
#endif
2016-05-17 21:03:11 -07:00
isInitializingTrigger = true;
2015-07-10 06:01:56 -07:00
errorDetection.clear();
2018-07-25 20:30:00 -07:00
efiAssert(CUSTOM_ERR_ASSERT, state != NULL, "NULL state", -1);
2015-07-10 06:01:56 -07:00
2015-09-13 13:01:38 -07:00
state->reset();
2015-09-13 07:01:39 -07:00
2017-02-23 11:00:03 -08:00
if (shape->shapeDefinitionError) {
return 0;
}
2015-07-10 06:01:56 -07:00
// todo: should this variable be declared 'static' to reduce stack usage?
TriggerStimulatorHelper helper;
2018-02-05 14:41:05 -08:00
uint32_t syncIndex = helper.findTriggerSyncPoint(shape, state PASS_ENGINE_PARAMETER_SUFFIX);
2017-03-04 05:55:53 -08:00
if (syncIndex == EFI_ERROR_CODE) {
2016-05-17 21:03:11 -07:00
isInitializingTrigger = false;
2017-03-04 05:55:53 -08:00
return syncIndex;
2015-07-10 06:01:56 -07:00
}
2018-07-25 20:30:00 -07:00
efiAssert(CUSTOM_ERR_ASSERT, state->getTotalRevolutionCounter() == 1, "findZero_revCounter", EFI_ERROR_CODE);
2015-07-10 06:01:56 -07:00
2017-03-04 05:55:53 -08:00
#if EFI_UNIT_TEST || defined(__DOXYGEN__)
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?
*/
2018-02-05 14:30:19 -08:00
state->triggerCycleCallback = onFindIndexCallback;
2015-07-10 06:01:56 -07:00
2018-02-05 14:44:10 -08:00
helper.assertSyncPositionAndSetDutyCycle(syncIndex, state, shape PASS_ENGINE_PARAMETER_SUFFIX);
2015-07-10 06:01:56 -07:00
2016-05-17 21:03:11 -07:00
isInitializingTrigger = false;
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;
}
efitime_t TriggerState::getStartOfRevolutionIndex() {
return totalEventCountBase;
}
void TriggerState::resetRunningCounters() {
runningRevolutionCounter = 0;
runningTriggerErrorCounter = 0;
runningOrderingErrorCounter = 0;
}
void TriggerState::runtimeStatistics(efitime_t nowNt DECLARE_ENGINE_PARAMETER_SUFFIX) {
// empty base implementation
}
void initTriggerDecoder(void) {
2017-04-21 13:20:06 -07:00
#if EFI_GPIO_HARDWARE || defined(__DOXYGEN__)
2017-04-21 15:11:36 -07:00
enginePins.triggerDecoderErrorPin.initPin("trg_err", boardConfiguration->triggerErrorPin,
2015-09-23 20:01:40 -07:00
&boardConfiguration->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 */