rusefi/firmware/controllers/trigger/decoders/trigger_structure.cpp

792 lines
23 KiB
C++
Raw Normal View History

2015-07-10 06:01:56 -07:00
/**
* @file trigger_structure.cpp
*
* @date Jan 20, 2014
2020-01-14 00:54:46 -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/>.
*/
2018-12-08 13:31:46 -08:00
#include "pch.h"
#include "os_access.h"
#include "trigger_chrysler.h"
#include "trigger_gm.h"
#include "trigger_nissan.h"
#include "trigger_mazda.h"
#include "trigger_misc.h"
#include "trigger_mitsubishi.h"
#include "trigger_subaru.h"
#include "trigger_suzuki.h"
2015-07-10 06:01:56 -07:00
#include "trigger_structure.h"
#include "trigger_toyota.h"
2020-04-18 19:20:17 -07:00
#include "trigger_renix.h"
#include "trigger_rover.h"
#include "trigger_honda.h"
#include "trigger_vw.h"
2017-01-03 13:02:43 -08:00
#include "trigger_universal.h"
2019-04-12 19:07:03 -07:00
#if EFI_SENSOR_CHART
2017-05-18 13:39:04 -07:00
#include "sensor_chart.h"
2017-05-19 10:04:16 -07:00
#endif /* EFI_SENSOR_CHART */
2015-07-10 06:01:56 -07:00
2019-11-23 21:15:44 -08:00
void event_trigger_position_s::setAngle(angle_t angle DECLARE_ENGINE_PARAMETER_SUFFIX) {
2020-08-24 21:59:07 -07:00
findTriggerPosition(&ENGINE(triggerCentral.triggerShape),
&ENGINE(triggerCentral.triggerFormDetails),
this, angle PASS_CONFIG_PARAM(engineConfiguration->globalTriggerAngleOffset));
2019-11-23 21:15:44 -08:00
}
2015-07-10 06:01:56 -07:00
trigger_shape_helper::trigger_shape_helper() {
memset(&pinStates, 0, sizeof(pinStates));
2018-12-25 07:13:00 -08:00
for (int channelIndex = 0; channelIndex < TRIGGER_CHANNEL_COUNT; channelIndex++) {
channels[channelIndex].init(pinStates[channelIndex]);
2015-07-10 06:01:56 -07:00
}
}
TriggerWaveform::TriggerWaveform() :
2015-07-10 06:01:56 -07:00
wave(switchTimesBuffer, NULL) {
initialize(OM_NONE);
2018-12-25 07:13:00 -08:00
wave.channels = h.channels;
2020-08-24 21:59:07 -07:00
}
2016-08-18 21:02:50 -07:00
2020-08-24 21:59:07 -07:00
TriggerFormDetails::TriggerFormDetails() {
2015-07-10 06:01:56 -07:00
memset(triggerIndexByAngle, 0, sizeof(triggerIndexByAngle));
}
void TriggerWaveform::initialize(operation_mode_e operationMode) {
2016-08-17 21:02:22 -07:00
isSynchronizationNeeded = true; // that's default value
bothFrontsRequired = false;
needSecondTriggerInput = false;
2020-01-14 00:54:46 -08:00
shapeWithoutTdc = false;
2018-02-05 14:16:34 -08:00
memset(expectedDutyCycle, 0, sizeof(expectedDutyCycle));
2016-08-17 21:02:22 -07:00
// memset(triggerIndexByAngle, 0, sizeof(triggerIndexByAngle));
2016-08-18 19:01:57 -07:00
2018-10-21 10:58:54 -07:00
setTriggerSynchronizationGap(2);
2018-12-25 07:20:13 -08:00
for (int gapIndex = 1; gapIndex < GAP_TRACKING_LENGTH ; gapIndex++) {
2018-10-21 10:58:54 -07:00
// NaN means do not use this gap ratio
2018-12-25 07:20:13 -08:00
setTriggerSynchronizationGap3(gapIndex, NAN, 100000);
2018-10-21 10:58:54 -07:00
}
gapTrackingLength = 1;
2016-08-18 19:01:57 -07:00
2015-07-10 06:01:56 -07:00
tdcPosition = 0;
2017-02-23 10:53:27 -08:00
shapeDefinitionError = useOnlyPrimaryForSync = false;
2015-07-10 06:01:56 -07:00
useRiseEdge = true;
2017-03-18 17:59:52 -07:00
gapBothDirections = false;
2015-07-10 06:01:56 -07:00
invertOnAdd = false;
this->operationMode = operationMode;
privateTriggerDefinitionSize = 0;
2015-07-10 06:01:56 -07:00
triggerShapeSynchPointIndex = 0;
memset(initialState, 0, sizeof(initialState));
memset(switchTimesBuffer, 0, sizeof(switchTimesBuffer));
memset(expectedEventCount, 0, sizeof(expectedEventCount));
wave.reset();
previousAngle = 0;
memset(isRiseEvent, 0, sizeof(isRiseEvent));
2019-04-12 19:07:03 -07:00
#if EFI_UNIT_TEST
memset(&triggerSignalIndeces, 0, sizeof(triggerSignalIndeces));
memset(&triggerSignalStates, 0, sizeof(triggerSignalStates));
2016-08-19 21:02:28 -07:00
#endif
2015-07-10 06:01:56 -07:00
}
2020-03-03 05:37:02 -08:00
size_t TriggerWaveform::getSize() const {
return privateTriggerDefinitionSize;
2016-08-20 06:02:06 -07:00
}
int TriggerWaveform::getTriggerWaveformSynchPointIndex() const {
2016-08-20 06:02:06 -07:00
return triggerShapeSynchPointIndex;
}
2015-07-10 06:01:56 -07:00
/**
2016-11-14 12:04:44 -08:00
* physical primary trigger duration
* @see getEngineCycle
2021-07-01 19:10:37 -07:00
* @see getCrankDivider
2015-07-10 06:01:56 -07:00
*/
angle_t TriggerWaveform::getCycleDuration() const {
2016-11-13 21:02:13 -08:00
switch (operationMode) {
2020-04-19 06:59:55 -07:00
case FOUR_STROKE_THREE_TIMES_CRANK_SENSOR:
2021-07-05 20:07:36 -07:00
return 720 / SYMMETRICAL_THREE_TIMES_CRANK_SENSOR_DIVIDER;
2016-11-13 21:02:13 -08:00
case FOUR_STROKE_SYMMETRICAL_CRANK_SENSOR:
2021-07-05 20:07:36 -07:00
return 720 / SYMMETRICAL_CRANK_SENSOR_DIVIDER;
2016-11-13 21:02:13 -08:00
case FOUR_STROKE_CRANK_SENSOR:
2016-11-14 12:04:44 -08:00
case TWO_STROKE:
return 360;
2016-11-13 21:02:13 -08:00
default:
2016-11-14 12:04:44 -08:00
return 720;
2016-11-13 21:02:13 -08:00
}
2015-07-10 06:01:56 -07:00
}
2016-11-14 12:04:44 -08:00
/**
* Trigger event count equals engine cycle event count if we have a cam sensor.
* Two trigger cycles make one engine cycle in case of a four stroke engine If we only have a cranksensor.
2020-08-26 20:35:11 -07:00
*
* 'engine->engineCycleEventCount' hold a pre-calculated copy of this value as a performance optimization
2016-11-14 12:04:44 -08:00
*/
2020-03-03 05:37:02 -08:00
size_t TriggerWaveform::getLength() const {
2016-11-14 12:04:44 -08:00
/**
2021-07-05 20:07:36 -07:00
* 6 for FOUR_STROKE_THREE_TIMES_CRANK_SENSOR
2016-11-14 12:04:44 -08:00
* 4 for FOUR_STROKE_SYMMETRICAL_CRANK_SENSOR
* 2 for FOUR_STROKE_CRANK_SENSOR
* 1 otherwise
*/
int multiplier = getEngineCycle(operationMode) / getCycleDuration();
return multiplier * getSize();
}
angle_t TriggerWaveform::getAngle(int index) const {
2015-07-10 06:01:56 -07:00
/**
* FOUR_STROKE_CRANK_SENSOR magic:
* We have two crank shaft revolutions for each engine cycle
* See also trigger_central.cpp
* See also getEngineCycleEventCount()
*/
efiAssert(CUSTOM_ERR_ASSERT, privateTriggerDefinitionSize != 0, "shapeSize=0", NAN);
int crankCycle = index / privateTriggerDefinitionSize;
int remainder = index % privateTriggerDefinitionSize;
2016-11-13 21:02:13 -08:00
auto cycleStartAngle = getCycleDuration() * crankCycle;
auto positionWithinCycle = getSwitchAngle(remainder);
return cycleStartAngle + positionWithinCycle;
2015-07-10 06:01:56 -07:00
}
void TriggerWaveform::addEventClamped(angle_t angle, trigger_wheel_e const channelIndex, trigger_value_e const stateParam, float filterLeft, float filterRight) {
2019-07-23 16:22:40 -07:00
if (angle > filterLeft && angle < filterRight) {
#if EFI_UNIT_TEST
// printf("addEventClamped %f %s\r\n", angle, getTrigger_value_e(stateParam));
#endif /* EFI_UNIT_TEST */
2019-02-02 22:34:20 -08:00
addEvent(angle / getEngineCycle(operationMode), channelIndex, stateParam);
2019-07-23 16:22:40 -07:00
}
2015-07-10 06:01:56 -07:00
}
operation_mode_e TriggerWaveform::getOperationMode() const {
2015-07-10 06:01:56 -07:00
return operationMode;
}
2019-04-12 19:07:03 -07:00
#if EFI_UNIT_TEST
2015-09-10 20:01:32 -07:00
extern bool printTriggerDebug;
#endif
2021-07-13 11:50:10 -07:00
size_t TriggerWaveform::getExpectedEventCount(int channelIndex) const {
2021-06-26 19:07:26 -07:00
return expectedEventCount[channelIndex];
}
void TriggerWaveform::calculateExpectedEventCounts(bool useOnlyRisingEdgeForTrigger) {
if (!useOnlyRisingEdgeForTrigger) {
for (size_t i = 0; i < efi::size(expectedEventCount); i++) {
2021-06-26 19:11:42 -07:00
if (getExpectedEventCount(i) % 2 != 0) {
2021-06-26 19:17:07 -07:00
firmwareError(ERROR_TRIGGER_DRAMA, "Trigger: should be even %d %d", i, getExpectedEventCount(i));
}
}
}
2021-06-26 19:17:07 -07:00
bool isSingleToothOnPrimaryChannel = useOnlyRisingEdgeForTrigger ? getExpectedEventCount(0) == 1 : getExpectedEventCount(0) == 2;
2020-01-14 00:54:46 -08:00
// todo: next step would be to set 'isSynchronizationNeeded' automatically based on the logic we have here
if (!shapeWithoutTdc && isSingleToothOnPrimaryChannel != !isSynchronizationNeeded) {
2020-05-08 22:15:55 -07:00
firmwareError(ERROR_TRIGGER_DRAMA, "trigger sync constraint violation");
2020-01-14 00:54:46 -08:00
}
if (isSingleToothOnPrimaryChannel) {
useOnlyPrimaryForSync = true;
}
2020-01-14 00:54:46 -08:00
2018-12-24 20:16:33 -08:00
// todo: move the following logic from below here
// if (!useOnlyRisingEdgeForTrigger || stateParam == TV_RISE) {
2018-12-25 07:13:00 -08:00
// expectedEventCount[channelIndex]++;
2018-12-24 20:16:33 -08:00
// }
}
2020-04-18 17:28:03 -07:00
void TriggerWaveform::addEvent720(angle_t angle, trigger_wheel_e const channelIndex, trigger_value_e const state) {
addEvent(angle / 720, channelIndex, state);
}
2021-07-16 21:45:47 -07:00
void TriggerWaveform::addEvent360(angle_t angle, trigger_wheel_e const channelIndex, trigger_value_e const state) {
addEvent(CRANK_MODE_MULTIPLIER * angle / 720, channelIndex, state);
}
2020-04-18 17:28:03 -07:00
void TriggerWaveform::addEventAngle(angle_t angle, trigger_wheel_e const channelIndex, trigger_value_e const state) {
addEvent(angle / getCycleDuration(), channelIndex, state);
2018-12-25 07:20:13 -08:00
}
void TriggerWaveform::addEvent(angle_t angle, trigger_wheel_e const channelIndex, trigger_value_e const stateParam) {
2018-09-10 19:10:55 -07:00
efiAssertVoid(CUSTOM_OMODE_UNDEF, operationMode != OM_NONE, "operationMode not set");
2015-07-10 06:01:56 -07:00
if (channelIndex == T_SECONDARY) {
needSecondTriggerInput = true;
}
2015-07-10 06:01:56 -07:00
2019-04-12 19:07:03 -07:00
#if EFI_UNIT_TEST
2015-09-10 20:01:32 -07:00
if (printTriggerDebug) {
2018-12-25 07:13:00 -08:00
printf("addEvent2 %.2f i=%d r/f=%d\r\n", angle, channelIndex, stateParam);
2015-09-10 20:01:32 -07:00
}
#endif
2015-07-10 06:01:56 -07:00
trigger_value_e state;
if (invertOnAdd) {
2015-10-31 13:02:10 -07:00
state = (stateParam == TV_FALL) ? TV_RISE : TV_FALL;
2015-07-10 06:01:56 -07:00
} else {
state = stateParam;
}
2019-04-12 19:07:03 -07:00
#if EFI_UNIT_TEST
assertIsInBounds(privateTriggerDefinitionSize, triggerSignalIndeces, "trigger shape overflow");
triggerSignalIndeces[privateTriggerDefinitionSize] = channelIndex;
triggerSignalStates[privateTriggerDefinitionSize] = stateParam;
#endif // EFI_UNIT_TEST
2015-07-10 06:01:56 -07:00
2019-02-02 22:34:20 -08:00
// todo: the whole 'useOnlyRisingEdgeForTrigger' parameter and logic should not be here
// todo: see calculateExpectedEventCounts
// related calculation should be done once trigger is initialized outside of trigger shape scope
if (!useOnlyRisingEdgeForTriggerTemp || stateParam == TV_RISE) {
2018-12-25 07:13:00 -08:00
expectedEventCount[channelIndex]++;
2015-07-10 06:01:56 -07:00
}
2020-12-04 12:22:53 -08:00
efiAssertVoid(CUSTOM_ERR_6599, angle > 0 && angle <= 1, "angle should be positive not above 1");
if (privateTriggerDefinitionSize > 0) {
2015-07-10 06:01:56 -07:00
if (angle <= previousAngle) {
warning(CUSTOM_ERR_TRG_ANGLE_ORDER, "invalid angle order %s %s: new=%.2f/%f and prev=%.2f/%f, size=%d",
getTrigger_wheel_e(channelIndex),
getTrigger_value_e(state),
2020-05-08 22:49:17 -07:00
angle, angle * getCycleDuration(),
previousAngle, previousAngle * getCycleDuration(),
privateTriggerDefinitionSize);
setShapeDefinitionError(true);
2015-07-10 06:01:56 -07:00
return;
}
}
previousAngle = angle;
if (privateTriggerDefinitionSize == 0) {
privateTriggerDefinitionSize = 1;
2015-07-10 06:01:56 -07:00
for (int i = 0; i < PWM_PHASE_MAX_WAVE_PER_PWM; i++) {
SingleChannelStateSequence *wave = &this->wave.channels[i];
2015-07-10 06:01:56 -07:00
2020-01-20 22:47:58 -08:00
if (wave->pinStates == nullptr) {
2017-03-12 19:46:01 -07:00
warning(CUSTOM_ERR_STATE_NULL, "wave pinStates is NULL");
setShapeDefinitionError(true);
2015-07-10 06:01:56 -07:00
return;
}
2019-02-02 22:04:24 -08:00
wave->setState(/* switchIndex */ 0, /* value */ initialState[i]);
2015-07-10 06:01:56 -07:00
}
isRiseEvent[0] = TV_RISE == stateParam;
2015-07-10 06:01:56 -07:00
wave.setSwitchTime(0, angle);
2018-12-25 07:13:00 -08:00
wave.channels[channelIndex].setState(/* channelIndex */ 0, /* value */ state);
2015-07-10 06:01:56 -07:00
return;
}
int exactMatch = wave.findAngleMatch(angle, privateTriggerDefinitionSize);
if (exactMatch != (int)EFI_ERROR_CODE) {
2017-04-19 19:03:14 -07:00
warning(CUSTOM_ERR_SAME_ANGLE, "same angle: not supported");
setShapeDefinitionError(true);
2015-07-10 06:01:56 -07:00
return;
}
int index = wave.findInsertionAngle(angle, privateTriggerDefinitionSize);
2015-07-10 06:01:56 -07:00
/**
* todo: it would be nice to be able to provide trigger angles without sorting them externally
* The idea here is to shift existing data - including handling high vs low state of the signals
*/
2018-02-05 14:16:34 -08:00
// todo: does this logic actually work? I think it does not! due to broken state handling
/*
2015-07-10 06:01:56 -07:00
for (int i = size - 1; i >= index; i--) {
for (int j = 0; j < PWM_PHASE_MAX_WAVE_PER_PWM; j++) {
wave.waves[j].pinStates[i + 1] = wave.getChannelState(j, index);
}
wave.setSwitchTime(i + 1, wave.getSwitchTime(i));
}
*/
isRiseEvent[index] = TV_RISE == stateParam;
2015-07-10 06:01:56 -07:00
if ((unsigned)index != privateTriggerDefinitionSize) {
2017-05-29 16:23:15 -07:00
firmwareError(ERROR_TRIGGER_DRAMA, "are we ever here?");
2015-07-10 06:01:56 -07:00
}
privateTriggerDefinitionSize++;
2015-07-10 06:01:56 -07:00
for (int i = 0; i < PWM_PHASE_MAX_WAVE_PER_PWM; i++) {
2019-02-02 22:27:47 -08:00
pin_state_t value = wave.getChannelState(/* channelIndex */i, index - 1);
2018-12-25 07:13:00 -08:00
wave.channels[i].setState(index, value);
2015-07-10 06:01:56 -07:00
}
wave.setSwitchTime(index, angle);
2018-12-25 07:13:00 -08:00
wave.channels[channelIndex].setState(index, state);
2015-07-10 06:01:56 -07:00
}
angle_t TriggerWaveform::getSwitchAngle(int index) const {
2015-07-10 06:01:56 -07:00
return getCycleDuration() * wave.getSwitchTime(index);
}
void setToothedWheelConfiguration(TriggerWaveform *s, int total, int skipped,
2018-12-25 17:09:35 -08:00
operation_mode_e operationMode) {
2019-04-12 19:07:03 -07:00
#if EFI_ENGINE_CONTROL
2015-07-10 06:01:56 -07:00
s->useRiseEdge = true;
initializeSkippedToothTriggerWaveformExt(s, total, skipped,
2018-12-25 17:09:35 -08:00
operationMode);
2015-07-10 06:01:56 -07:00
#endif
}
void TriggerWaveform::setTriggerSynchronizationGap2(float syncRatioFrom, float syncRatioTo) {
2018-12-25 07:20:13 -08:00
setTriggerSynchronizationGap3(/*gapIndex*/0, syncRatioFrom, syncRatioTo);
2018-10-21 10:41:01 -07:00
}
void TriggerWaveform::setTriggerSynchronizationGap3(int gapIndex, float syncRatioFrom, float syncRatioTo) {
2015-07-10 06:01:56 -07:00
isSynchronizationNeeded = true;
2020-12-04 12:22:53 -08:00
efiAssertVoid(OBD_PCM_Processor_Fault, gapIndex >= 0 && gapIndex < GAP_TRACKING_LENGTH, "gapIndex out of range");
2021-05-25 14:15:48 -07:00
syncronizationRatioFrom[gapIndex] = syncRatioFrom;
syncronizationRatioTo[gapIndex] = syncRatioTo;
2018-12-25 07:20:13 -08:00
if (gapIndex == 0) {
2018-10-21 10:41:01 -07:00
// we have a special case here - only sync with one gap has this feature
this->syncRatioAvg = (int)efiRound((syncRatioFrom + syncRatioTo) * 0.5f, 1.0f);
}
gapTrackingLength = maxI(1 + gapIndex, gapTrackingLength);
2018-10-21 10:41:01 -07:00
2019-04-12 19:07:03 -07:00
#if EFI_UNIT_TEST
2017-03-04 16:47:15 -08:00
if (printTriggerDebug) {
2018-12-25 07:20:13 -08:00
printf("setTriggerSynchronizationGap3 %d %.2f %.2f\r\n", gapIndex, syncRatioFrom, syncRatioTo);
2017-03-04 16:47:15 -08:00
}
#endif /* EFI_UNIT_TEST */
2018-10-21 10:41:01 -07:00
2015-07-10 06:01:56 -07:00
}
2018-12-25 09:27:34 -08:00
/**
* this method is only used on initialization
*/
uint16_t TriggerWaveform::findAngleIndex(TriggerFormDetails *details, angle_t targetAngle) const {
2021-01-16 18:22:30 -08:00
size_t engineCycleEventCount = getLength();
2018-12-25 09:27:34 -08:00
efiAssert(CUSTOM_ERR_ASSERT, engineCycleEventCount != 0 && engineCycleEventCount <= 0xFFFF, "engineCycleEventCount", 0);
2018-12-25 09:27:34 -08:00
uint32_t left = 0;
uint32_t right = engineCycleEventCount - 1;
/**
* Let's find the last trigger angle which is less or equal to the desired angle
* todo: extract binary search as template method?
*/
while (left <= right) {
int middle = (left + right) / 2;
2020-08-24 21:59:07 -07:00
angle_t eventAngle = details->eventAngles[middle];
2018-12-25 09:27:34 -08:00
if (eventAngle < targetAngle) {
2018-12-25 09:27:34 -08:00
left = middle + 1;
} else if (eventAngle > targetAngle) {
2018-12-25 09:27:34 -08:00
right = middle - 1;
} else {
// Values are equal
return middle; // Key found
}
}
return left - 1;
}
void TriggerWaveform::setShapeDefinitionError(bool value) {
shapeDefinitionError = value;
}
2020-08-24 21:59:07 -07:00
void findTriggerPosition(TriggerWaveform *triggerShape,
TriggerFormDetails *details,
event_trigger_position_s *position,
2019-10-07 21:30:20 -07:00
angle_t angle DEFINE_CONFIG_PARAM(angle_t, globalTriggerAngleOffset)) {
efiAssertVoid(CUSTOM_ERR_6574, !cisnan(angle), "findAngle#1");
assertAngleRange(angle, "findAngle#a1", CUSTOM_ERR_6545);
2018-12-25 09:27:34 -08:00
2020-08-24 21:59:07 -07:00
efiAssertVoid(CUSTOM_ERR_6575, !cisnan(triggerShape->tdcPosition), "tdcPos#1")
assertAngleRange(triggerShape->tdcPosition, "tdcPos#a1", CUSTOM_UNEXPECTED_TDC_ANGLE);
2018-12-25 09:27:34 -08:00
efiAssertVoid(CUSTOM_ERR_6576, !cisnan(CONFIG_PARAM(globalTriggerAngleOffset)), "tdcPos#2")
assertAngleRange(CONFIG_PARAM(globalTriggerAngleOffset), "tdcPos#a2", CUSTOM_INVALID_GLOBAL_OFFSET);
2018-12-25 09:27:34 -08:00
// convert engine cycle angle into trigger cycle angle
2020-08-24 21:59:07 -07:00
angle += triggerShape->tdcPosition + CONFIG_PARAM(globalTriggerAngleOffset);
2019-10-07 21:30:20 -07:00
efiAssertVoid(CUSTOM_ERR_6577, !cisnan(angle), "findAngle#2");
2020-08-24 21:59:07 -07:00
fixAngle2(angle, "addFuel#2", CUSTOM_ERR_6555, getEngineCycle(triggerShape->getOperationMode()));
2018-12-25 09:27:34 -08:00
2020-08-24 21:59:07 -07:00
int triggerEventIndex = details->triggerIndexByAngle[(int)angle];
angle_t triggerEventAngle = details->eventAngles[triggerEventIndex];
angle_t offsetFromTriggerEvent = angle - triggerEventAngle;
// Guarantee that we aren't going to try and schedule an event prior to the tooth
if (offsetFromTriggerEvent < 0) {
2019-10-07 21:42:47 -07:00
warning(CUSTOM_OBD_ANGLE_CONSTRAINT_VIOLATION, "angle constraint violation in findTriggerPosition(): %.2f/%.2f", angle, triggerEventAngle);
2018-12-25 09:27:34 -08:00
return;
}
{
// This must happen under lock so that the tooth and offset don't get partially read and mismatched
chibios_rt::CriticalSectionLocker csl;
position->triggerEventIndex = triggerEventIndex;
position->angleOffsetFromTriggerEvent = offsetFromTriggerEvent;
}
2018-12-25 09:27:34 -08:00
}
2020-08-25 09:45:18 -07:00
void TriggerWaveform::prepareShape(TriggerFormDetails *details DECLARE_ENGINE_PARAMETER_SUFFIX) {
2019-04-12 19:07:03 -07:00
#if EFI_ENGINE_CONTROL && EFI_SHAFT_POSITION_INPUT
if (shapeDefinitionError) {
// Nothing to do here if there's a problem with the trigger shape
return;
}
2020-08-25 09:45:18 -07:00
prepareEventAngles(this, details PASS_ENGINE_PARAMETER_SUFFIX);
int engineCycleInt = (int) getEngineCycle(operationMode);
for (int angle = 0; angle < engineCycleInt; angle++) {
2021-01-16 18:22:30 -08:00
uint16_t triggerShapeIndex = findAngleIndex(details, angle);
if (useOnlyRisingEdgeForTriggerTemp) {
2021-01-16 18:22:30 -08:00
// we need even index for front_only mode - so if odd indexes are rounded down by clearing the low bit
triggerShapeIndex &= 0xFFFE;
}
2021-01-16 18:22:30 -08:00
2020-08-24 21:59:07 -07:00
details->triggerIndexByAngle[angle] = triggerShapeIndex;
}
2019-01-31 15:30:40 -08:00
#endif
}
void TriggerWaveform::setTriggerSynchronizationGap(float syncRatio) {
2020-12-04 13:24:19 -08:00
setTriggerSynchronizationGap3(/*gapIndex*/0, syncRatio * TRIGGER_GAP_DEVIATION_LOW, syncRatio * TRIGGER_GAP_DEVIATION_HIGH);
2015-09-12 12:02:40 -07:00
}
2021-10-24 14:12:19 -07:00
void TriggerWaveform::setSecondTriggerSynchronizationGap(float syncRatio) {
setTriggerSynchronizationGap3(/*gapIndex*/1, syncRatio * TRIGGER_GAP_DEVIATION_LOW, syncRatio * TRIGGER_GAP_DEVIATION_HIGH);
}
void TriggerWaveform::setSecondTriggerSynchronizationGap2(float syncRatioFrom, float syncRatioTo) {
2018-12-25 07:20:13 -08:00
setTriggerSynchronizationGap3(/*gapIndex*/1, syncRatioFrom, syncRatioTo);
2015-09-12 12:02:40 -07:00
}
void TriggerWaveform::setThirdTriggerSynchronizationGap(float syncRatio) {
2020-12-04 13:24:19 -08:00
setTriggerSynchronizationGap3(/*gapIndex*/2, syncRatio * TRIGGER_GAP_DEVIATION_LOW, syncRatio * TRIGGER_GAP_DEVIATION_HIGH);
2015-12-27 13:02:44 -08:00
}
/**
* External logger is needed because at this point our logger is not yet initialized
*/
void TriggerWaveform::initializeTriggerWaveform(operation_mode_e ambiguousOperationMode, bool useOnlyRisingEdgeForTrigger, const trigger_config_s *triggerConfig) {
2019-04-12 19:07:03 -07:00
#if EFI_PROD_CODE
efiAssertVoid(CUSTOM_ERR_6641, getCurrentRemainingStack() > EXPECTED_REMAINING_STACK, "init t");
efiPrintf("initializeTriggerWaveform(%s/%d)", getTrigger_type_e(triggerConfig->type), (int) triggerConfig->type);
#endif
shapeDefinitionError = false;
this->useOnlyRisingEdgeForTriggerTemp = useOnlyRisingEdgeForTrigger;
switch (triggerConfig->type) {
case TT_TOOTHED_WHEEL:
initializeSkippedToothTriggerWaveformExt(this, triggerConfig->customTotalToothCount,
triggerConfig->customSkippedToothCount, ambiguousOperationMode);
break;
case TT_MAZDA_MIATA_NA:
2019-02-02 21:40:25 -08:00
initializeMazdaMiataNaShape(this);
break;
case TT_MAZDA_MIATA_NB1:
initializeMazdaMiataNb1Shape(this);
break;
case TT_MAZDA_MIATA_VVT_TEST:
initializeMazdaMiataVVtTestShape(this);
break;
case TT_SUZUKI_G13B:
initializeSuzukiG13B(this);
break;
case TT_FORD_TFI_PIP:
configureFordPip(this);
break;
case TT_FORD_ST170:
configureFordST170(this);
break;
2020-08-24 22:38:56 -07:00
case TT_VVT_MIATA_NB2:
2020-02-04 22:49:33 -08:00
initializeMazdaMiataVVtCamShape(this);
break;
2020-04-19 06:59:55 -07:00
case TT_RENIX_66_2_2_2:
2020-04-19 11:54:02 -07:00
initializeRenix66_2_2(this);
break;
2020-04-18 19:20:17 -07:00
case TT_RENIX_44_2_2:
2020-04-19 06:59:55 -07:00
initializeRenix44_2_2(this);
2020-04-18 19:20:17 -07:00
break;
case TT_MIATA_VVT:
initializeMazdaMiataNb2Crank(this);
break;
case TT_DODGE_NEON_1995:
configureNeon1995TriggerWaveform(this);
break;
case TT_DODGE_NEON_1995_ONLY_CRANK:
configureNeon1995TriggerWaveformOnlyCrank(this);
break;
case TT_DODGE_STRATUS:
configureDodgeStratusTriggerWaveform(this);
break;
case TT_DODGE_NEON_2003_CAM:
configureNeon2003TriggerWaveformCam(this);
break;
case TT_DODGE_NEON_2003_CRANK:
configureNeon2003TriggerWaveformCam(this);
// configureNeon2003TriggerWaveformCrank(triggerShape);
break;
case TT_FORD_ASPIRE:
configureFordAspireTriggerWaveform(this);
break;
case TT_VVT_NISSAN_VQ35:
2021-07-01 18:48:14 -07:00
initializeNissanVQvvt(this);
break;
case TT_NISSAN_QR25:
2021-08-11 01:16:51 -07:00
case TT_TEMP_62:
initializeNissanQR25crank(this);
break;
case TT_NISSAN_VQ30:
initializeNissanVQ30cam(this);
break;
case TT_NISSAN_VQ35:
2021-07-16 21:45:47 -07:00
initializeNissanVQ35crank(this);
2021-07-01 19:10:37 -07:00
break;
case TT_NISSAN_MR18_CRANK:
initializeNissanMR18crank(this);
break;
2021-04-08 19:16:14 -07:00
case TT_KAWA_KX450F:
2021-04-08 20:23:01 -07:00
configureKawaKX450F(this);
break;
case TT_SKODA_FAVORIT:
setSkodaFavorit(this);
break;
case TT_GM_60_2_2_2:
configureGm60_2_2_2(this);
break;
case TT_GM_7X:
configureGmTriggerWaveform(this);
break;
case TT_MAZDA_DOHC_1_4:
configureMazdaProtegeLx(this);
break;
case TT_ONE_PLUS_ONE:
2020-04-25 19:23:53 -07:00
configureOnePlusOne(this);
break;
case TT_3_1_CAM:
2020-04-25 19:23:53 -07:00
configure3_1_cam(this);
break;
case TT_ONE:
setToothedWheelConfiguration(this, 1, 0, ambiguousOperationMode);
break;
case TT_MAZDA_SOHC_4:
configureMazdaProtegeSOHC(this);
break;
case TT_DAIHATSU:
configureDaihatsu4(this);
break;
2020-08-25 13:19:23 -07:00
case TT_VVT_JZ:
setToothedWheelConfiguration(this, 3, 0, ambiguousOperationMode);
break;
case TT_TOOTHED_WHEEL_60_2:
setToothedWheelConfiguration(this, 60, 2, ambiguousOperationMode);
setSecondTriggerSynchronizationGap(1); // this gap is not required to synch on perfect signal but is needed to handle to reject cranking transition noise
break;
2020-05-09 20:47:51 -07:00
case TT_TOOTHED_WHEEL_36_2:
setToothedWheelConfiguration(this, 36, 2, ambiguousOperationMode);
setSecondTriggerSynchronizationGap(1); // this gap is not required to synch on perfect signal but is needed to handle to reject cranking transition noise
2020-05-09 20:47:51 -07:00
break;
case TT_60_2_VW:
setVwConfiguration(this);
break;
case TT_TOOTHED_WHEEL_36_1:
setToothedWheelConfiguration(this, 36, 1, ambiguousOperationMode);
setSecondTriggerSynchronizationGap(1); // this gap is not required to synch on perfect signal but is needed to handle to reject cranking transition noise
break;
2020-08-24 22:24:15 -07:00
case TT_VVT_BOSCH_QUICK_START:
2020-04-25 19:23:53 -07:00
configureQuickStartSenderWheel(this);
break;
case TT_VVT_BARRA_3_PLUS_1:
configureBarra3plus1cam(this);
break;
2021-10-24 14:12:19 -07:00
case TT_HONDA_K_4_1:
configureHondaK_4_1(this);
break;
2020-04-19 11:23:01 -07:00
case TT_HONDA_K_12_1:
configureHondaK_12_1(this);
break;
2021-10-20 09:57:07 -07:00
case TT_UNUSED_10:
case TT_HONDA_4_24:
configureHonda_1_4_24(this, false, true, T_NONE, T_PRIMARY, 0);
2020-01-14 00:54:46 -08:00
shapeWithoutTdc = true;
break;
case TT_HONDA_1_24:
configureHonda_1_4_24(this, true, false, T_PRIMARY, T_NONE, 10);
break;
case TT_HONDA_ACCORD_1_24_SHIFTED:
configureHondaAccordShifted(this);
break;
case TT_HONDA_1_4_24:
configureHondaAccordCDDip(this);
break;
2020-09-28 18:18:47 -07:00
case TT_1_16:
configureOnePlus16(this);
break;
case TT_HONDA_CBR_600:
configureHondaCbr600(this);
break;
2020-12-03 21:30:22 -08:00
case TT_CHRYSLER_NGC_36_2_2:
configureChryslerNGC_36_2_2(this);
break;
case TT_MITSUBISHI:
initializeMitsubishi4g18(this);
break;
case TT_DODGE_RAM:
initDodgeRam(this);
break;
case TT_JEEP_4_CYL:
initJeep_XJ_4cyl_2500(this);
break;
case TT_JEEP_18_2_2_2:
initJeep18_2_2_2(this);
break;
case TT_SUBARU_7_6:
initializeSubaru7_6(this);
break;
case TT_36_2_2_2:
initialize36_2_2_2(this);
break;
case TT_2JZ_3_34:
2020-05-08 22:15:55 -07:00
initialize2jzGE3_34_simulation_shape(this);
break;
case TT_2JZ_1_12:
initialize2jzGE1_12(this);
break;
case TT_NISSAN_SR20VE:
initializeNissanSR20VE_4(this);
break;
case TT_NISSAN_SR20VE_360:
initializeNissanSR20VE_4_360(this);
break;
case TT_ROVER_K:
initializeRoverK(this);
break;
case TT_FIAT_IAW_P8:
configureFiatIAQ_P8(this);
break;
case TT_TRI_TACH:
configureTriTach(this);
break;
case TT_GM_LS_24:
initGmLS24(this);
break;
2020-12-13 14:46:48 -08:00
case TT_SUBARU_7_WITHOUT_6:
2020-12-13 13:22:02 -08:00
case TT_52:
initializeSubaruOnly7(this);
break;
case TT_SUBARU_SVX:
initializeSubaru_SVX(this);
break;
2021-08-31 02:54:04 -07:00
case TT_SUBARU_SVX_CRANK_1:
2021-08-31 03:05:57 -07:00
initializeSubaru_SVX(this);
break;
2021-08-31 02:54:04 -07:00
case TT_SUBARU_SVX_CAM_VVT:
2021-08-31 03:05:57 -07:00
initializeSubaru_SVX(this);
break;
2021-08-31 02:54:04 -07:00
default:
setShapeDefinitionError(true);
warning(CUSTOM_ERR_NO_SHAPE, "initializeTriggerWaveform() not implemented: %d", triggerConfig->type);
}
2019-02-02 21:40:25 -08:00
/**
* Feb 2019 suggestion: it would be an improvement to remove 'expectedEventCount' logic from 'addEvent'
* and move it here, after all events were added.
*/
calculateExpectedEventCounts(useOnlyRisingEdgeForTrigger);
version++;
if (!shapeDefinitionError) {
2020-05-08 22:49:17 -07:00
wave.checkSwitchTimes(getSize(), getCycleDuration());
}
2020-08-26 20:35:11 -07:00
if (bothFrontsRequired && useOnlyRisingEdgeForTrigger) {
#if EFI_PROD_CODE || EFI_SIMULATOR
firmwareError(CUSTOM_ERR_BOTH_FRONTS_REQUIRED, "trigger: both fronts required");
#else
warning(CUSTOM_ERR_BOTH_FRONTS_REQUIRED, "trigger: both fronts required");
#endif
}
}