#625 big step - no more engine dependency from TriggerShape

This commit is contained in:
rusefi 2018-12-25 22:47:29 -05:00
parent 72f87ce425
commit f0344fd16c
14 changed files with 457 additions and 460 deletions

View File

@ -67,7 +67,9 @@ void Engine::initializeTriggerShape(Logging *logger DECLARE_ENGINE_PARAMETER_SUF
bool alreadyLocked = lockAnyContext();
#endif /* EFI_UNIT_TEST */
TRIGGER_SHAPE(initializeTriggerShape(logger, engineConfiguration->useOnlyRisingEdgeForTrigger PASS_ENGINE_PARAMETER_SUFFIX));
TRIGGER_SHAPE(initializeTriggerShape(logger,
engineConfiguration->operationMode,
engineConfiguration->useOnlyRisingEdgeForTrigger, &engineConfiguration->trigger));
if (!TRIGGER_SHAPE(shapeDefinitionError)) {
/**
@ -75,7 +77,8 @@ void Engine::initializeTriggerShape(Logging *logger DECLARE_ENGINE_PARAMETER_SUF
* #192 BUG real hardware trigger events could be coming even while we are initializing trigger
*/
initState.reset();
TRIGGER_SHAPE(calculateTriggerSynchPoint(&initState PASS_ENGINE_PARAMETER_SUFFIX));
calculateTriggerSynchPoint(&ENGINE(triggerCentral.triggerShape),
&initState PASS_ENGINE_PARAMETER_SUFFIX);
if (engine->triggerCentral.triggerShape.getSize() == 0) {
firmwareError(CUSTOM_ERR_TRIGGER_ZERO, "triggerShape size is zero");

View File

@ -52,6 +52,7 @@
#define DEFINE_CONFIG_PARAM(x, y)
#define CONFIG_PARAM(x) CONFIG(x)
#define PASS_CONFIG_PARAM(x)
#endif /* GLOBAL_SHARED_H_ */

View File

@ -211,7 +211,7 @@ bool FuelSchedule::addFuelEventsForCylinder(int i DECLARE_ENGINE_PARAMETER_SUFF
efiAssert(CUSTOM_ERR_ASSERT, !cisnan(angle), "findAngle#3", false);
assertAngleRange(angle, "findAngle#a33", CUSTOM_ERR_6544);
TRIGGER_SHAPE(findTriggerPosition(&ev->injectionStart, angle PASS_ENGINE_PARAMETER_SUFFIX));
TRIGGER_SHAPE(findTriggerPosition(&ev->injectionStart, angle PASS_CONFIG_PARAM(engineConfiguration->globalTriggerAngleOffset)));
#if EFI_UNIT_TEST || defined(__DOXYGEN__)
printf("registerInjectionEvent angle=%.2f trgIndex=%d inj %d\r\n", angle, ev->injectionStart.eventIndex, injectorIndex);
#endif
@ -460,18 +460,6 @@ ignition_mode_e getIgnitionMode(DECLARE_ENGINE_PARAMETER_SIGNATURE) {
return ignitionMode;
}
void TriggerShape::prepareShape(DECLARE_ENGINE_PARAMETER_SIGNATURE) {
int engineCycleInt = (int) getEngineCycle(CONFIG(operationMode));
for (int angle = 0; angle < engineCycleInt; angle++) {
int triggerShapeIndex = findAngleIndex(angle);
if (engineConfiguration->useOnlyRisingEdgeForTrigger) {
// we need even index for front_only mode - so if odd indexes are rounded down
triggerShapeIndex = triggerShapeIndex & 0xFFFFFFFE;
}
triggerIndexByAngle[angle] = triggerShapeIndex;
}
}
#if EFI_ENGINE_CONTROL || defined(__DOXYGEN__)
/**
@ -500,7 +488,7 @@ void prepareOutputSignals(DECLARE_ENGINE_PARAMETER_SIGNATURE) {
prepareIgnitionPinIndices(CONFIG(ignitionMode) PASS_ENGINE_PARAMETER_SUFFIX);
TRIGGER_SHAPE(prepareShape(PASS_ENGINE_PARAMETER_SIGNATURE));
TRIGGER_SHAPE(prepareShape());
}
#endif

View File

@ -18,36 +18,10 @@ void setAlgorithm(engine_load_mode_e algo DECLARE_ENGINE_PARAMETER_SUFFIX);
#define assertEngineReference() efiAssertVoid(CUSTOM_ENGINE_REF, engine != NULL, "engine is NULL")
#if EFI_ENABLE_ASSERTS
#define assertAngleRange(angle, msg, code) if(angle > 10000000 || angle < -10000000) { firmwareError(code, "angle range %s %.2f", msg, angle);angle = 0;}
#else
#define assertAngleRange(angle, msg, code) {}
#endif
void setFlatInjectorLag(float value DECLARE_ENGINE_PARAMETER_SUFFIX);
#define fixAngle(angle, msg, code) fixAngle2(angle, msg, code, ENGINE(engineCycle))
/**
* @brief Shifts angle into the [0..720) range for four stroke and [0..360) for two stroke
* I guess this implementation would be faster than 'angle % engineCycle'
*/
#define fixAngle(angle, msg, code) \
{ \
if (cisnan(angle)) { \
firmwareError(CUSTOM_ERR_ANGLE, "aNaN%s", msg); \
angle = 0; \
} \
assertAngleRange(angle, msg, code); \
float engineCycleDurationLocalCopy = ENGINE(engineCycle); \
/* todo: split this method into 'fixAngleUp' and 'fixAngleDown'*/ \
/* as a performance optimization?*/ \
while (angle < 0) \
angle += engineCycleDurationLocalCopy; \
/* todo: would 'if' work as good as 'while'? */ \
while (angle >= engineCycleDurationLocalCopy) \
angle -= engineCycleDurationLocalCopy; \
}
/**
* @return time needed to rotate crankshaft by one degree, in milliseconds.

View File

@ -0,0 +1 @@
This folder is and should not be aware of engine.h or engine_configuration.h

View File

@ -20,15 +20,28 @@
#include "global.h"
#include "trigger_bmw.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_structure.h"
#include "trigger_decoder.h"
#include "engine_math.h"
#include "trigger_toyota.h"
#include "trigger_rover.h"
#include "trigger_honda.h"
#include "trigger_vw.h"
#include "trigger_universal.h"
#if EFI_SENSOR_CHART || defined(__DOXYGEN__)
#include "sensor_chart.h"
#endif /* EFI_SENSOR_CHART */
EXTERN_ENGINE;
#include "engine_configuration.h"
extern persistent_config_container_s persistentState;
trigger_shape_helper::trigger_shape_helper() {
memset(&pinStates, 0, sizeof(pinStates));
@ -46,58 +59,6 @@ TriggerShape::TriggerShape() :
memset(triggerIndexByAngle, 0, sizeof(triggerIndexByAngle));
}
void TriggerShape::calculateTriggerSynchPoint(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;
triggerShapeSynchPointIndex = findTriggerZeroEventIndex(state, this, triggerConfig PASS_ENGINE_PARAMETER_SUFFIX);
int length = 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);
shapeDefinitionError = true;
return;
}
float firstAngle = getAngle(triggerShapeSynchPointIndex);
assertAngleRange(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
eventAngles[0] = 0;
// this value would be used in case of front-only
eventAngles[1] = 0;
frontOnlyIndexes[0] = 0;
} else {
assertAngleRange(triggerShapeSynchPointIndex, "triggerShapeSynchPointIndex", CUSTOM_ERR_6552);
int triggerDefinitionCoordinate = (triggerShapeSynchPointIndex + eventIndex) % engine->engineCycleEventCount;
efiAssertVoid(CUSTOM_ERR_6595, engine->engineCycleEventCount != 0, "zero engineCycleEventCount");
int triggerDefinitionIndex = triggerDefinitionCoordinate >= privateTriggerDefinitionSize ? triggerDefinitionCoordinate - privateTriggerDefinitionSize : triggerDefinitionCoordinate;
float angle = getAngle(triggerDefinitionCoordinate) - firstAngle;
efiAssertVoid(CUSTOM_ERR_6596, !cisnan(angle), "trgSyncNaN");
fixAngle(angle, "trgSync", CUSTOM_ERR_6559);
if (engineConfiguration->useOnlyRisingEdgeForTrigger) {
if (isFrontEvent[triggerDefinitionIndex]) {
frontOnlyIndex += 2;
eventAngles[frontOnlyIndex] = angle;
eventAngles[frontOnlyIndex + 1] = angle;
}
} else {
eventAngles[eventIndex] = angle;
}
frontOnlyIndexes[eventIndex] = frontOnlyIndex;
}
}
}
void TriggerShape::initialize(operation_mode_e operationMode, bool needSecondTriggerInput) {
isSynchronizationNeeded = true; // that's default value
this->needSecondTriggerInput = needSecondTriggerInput;
@ -141,98 +102,6 @@ int TriggerShape::getTriggerShapeSynchPointIndex() {
return triggerShapeSynchPointIndex;
}
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
}
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 */
}
}
efitime_t TriggerState::getTotalEventCounter() {
return totalEventCountBase + currentCycle.current_index;
}
int TriggerState::getTotalRevolutionCounter() {
return totalRevolutionCounter;
}
/**
* physical primary trigger duration
*/
@ -301,16 +170,6 @@ void TriggerShape::calculateExpectedEventCounts(bool useOnlyRisingEdgeForTrigger
}
/**
* Deprecated - see https://github.com/rusefi/rusefi/issues/635
*/
void TriggerShape::addEvent2(angle_t angle, trigger_wheel_e const channelIndex, trigger_value_e const stateParam DECLARE_ENGINE_PARAMETER_SUFFIX) {
/**
* While '720' value works perfectly it has not much sense for crank sensor-only scenario.
*/
addEvent(engineConfiguration->useOnlyRisingEdgeForTrigger, angle / getEngineCycle(operationMode), channelIndex, stateParam);
}
void TriggerShape::addEvent720(angle_t angle, trigger_wheel_e const channelIndex, trigger_value_e const stateParam) {
addEvent(useOnlyRisingEdgeForTriggerTemp, angle / 720, channelIndex, stateParam);
}
@ -480,20 +339,21 @@ int TriggerShape::findAngleIndex(float target) {
return left - 1;
}
void TriggerShape::findTriggerPosition(event_trigger_position_s *position, angle_t angleOffset DECLARE_ENGINE_PARAMETER_SUFFIX) {
void TriggerShape::findTriggerPosition(event_trigger_position_s *position,
angle_t angleOffset DEFINE_CONFIG_PARAM(angle_t, globalTriggerAngleOffset)) {
efiAssertVoid(CUSTOM_ERR_6574, !cisnan(angleOffset), "findAngle#1");
assertAngleRange(angleOffset, "findAngle#a1", CUSTOM_ERR_6545);
efiAssertVoid(CUSTOM_ERR_6575, !cisnan(TRIGGER_SHAPE(tdcPosition)), "tdcPos#1")
assertAngleRange(TRIGGER_SHAPE(tdcPosition), "tdcPos#a1", CUSTOM_ERR_6546);
efiAssertVoid(CUSTOM_ERR_6575, !cisnan(tdcPosition), "tdcPos#1")
assertAngleRange(tdcPosition, "tdcPos#a1", CUSTOM_ERR_6546);
efiAssertVoid(CUSTOM_ERR_6576, !cisnan(CONFIG(globalTriggerAngleOffset)), "tdcPos#2")
assertAngleRange(CONFIG(globalTriggerAngleOffset), "tdcPos#a2", CUSTOM_ERR_6547);
efiAssertVoid(CUSTOM_ERR_6576, !cisnan(CONFIG_PARAM(globalTriggerAngleOffset)), "tdcPos#2")
assertAngleRange(CONFIG_PARAM(globalTriggerAngleOffset), "tdcPos#a2", CUSTOM_ERR_6547);
// convert engine cycle angle into trigger cycle angle
angleOffset += tdcPosition();
angleOffset += tdcPosition + CONFIG_PARAM(globalTriggerAngleOffset);
efiAssertVoid(CUSTOM_ERR_6577, !cisnan(angleOffset), "findAngle#2");
fixAngle(angleOffset, "addFuel#2", CUSTOM_ERR_6555);
fixAngle2(angleOffset, "addFuel#2", CUSTOM_ERR_6555, getEngineCycle(operationMode));
int index = triggerIndexByAngle[(int)angleOffset];
angle_t eventAngle = eventAngles[index];
@ -507,6 +367,18 @@ void TriggerShape::findTriggerPosition(event_trigger_position_s *position, angle
position->angleOffset = angleOffset - eventAngle;
}
void TriggerShape::prepareShape() {
int engineCycleInt = (int) getEngineCycle(operationMode);
for (int angle = 0; angle < engineCycleInt; angle++) {
int triggerShapeIndex = findAngleIndex(angle);
if (useOnlyRisingEdgeForTriggerTemp) {
// we need even index for front_only mode - so if odd indexes are rounded down
triggerShapeIndex = triggerShapeIndex & 0xFFFFFFFE;
}
triggerIndexByAngle[angle] = triggerShapeIndex;
}
}
void TriggerShape::setTriggerSynchronizationGap(float syncRatio) {
setTriggerSynchronizationGap3(/*gapIndex*/0, syncRatio * 0.75f, syncRatio * 1.25f);
}
@ -522,3 +394,207 @@ void TriggerShape::setThirdTriggerSynchronizationGap(float syncRatio) {
void TriggerShape::setSecondTriggerSynchronizationGap(float syncRatio) {
setTriggerSynchronizationGap3(/*gapIndex*/1, syncRatio * 0.75f, syncRatio * 1.25f);
}
/**
* External logger is needed because at this point our logger is not yet initialized
*/
void TriggerShape::initializeTriggerShape(Logging *logger, operation_mode_e operationMode, bool useOnlyRisingEdgeForTrigger, const trigger_config_s *triggerConfig) {
#if EFI_PROD_CODE || defined(__DOXYGEN__)
efiAssertVoid(CUSTOM_ERR_6641, getRemainingStack(chThdGetSelfX()) > 256, "init t");
scheduleMsg(logger, "initializeTriggerShape(%s/%d)", getTrigger_type_e(triggerConfig->type), (int) triggerConfig->type);
#endif
shapeDefinitionError = false;
this->useOnlyRisingEdgeForTriggerTemp = useOnlyRisingEdgeForTrigger;
switch (triggerConfig->type) {
case TT_TOOTHED_WHEEL:
initializeSkippedToothTriggerShapeExt(this, triggerConfig->customTotalToothCount,
triggerConfig->customSkippedToothCount, operationMode);
break;
case TT_MAZDA_MIATA_NA:
initializeMazdaMiataNaShape(this, useOnlyRisingEdgeForTrigger);
break;
case TT_MAZDA_MIATA_NB1:
initializeMazdaMiataNb1Shape(this);
break;
case TT_MAZDA_MIATA_VVT_TEST:
initializeMazdaMiataVVtTestShape(this);
break;
case TT_MAZDA_Z5:
initialize_Mazda_Engine_z5_Shape(this);
break;
case TT_MIATA_VVT:
initializeMazdaMiataNb2Crank(this);
break;
case TT_DODGE_NEON_1995:
configureNeon1995TriggerShape(this);
break;
case TT_DODGE_NEON_1995_ONLY_CRANK:
configureNeon1995TriggerShapeOnlyCrank(this);
break;
case TT_DODGE_STRATUS:
configureDodgeStratusTriggerShape(this);
break;
case TT_DODGE_NEON_2003_CAM:
configureNeon2003TriggerShapeCam(this);
break;
case TT_DODGE_NEON_2003_CRANK:
configureNeon2003TriggerShapeCam(this);
// configureNeon2003TriggerShapeCrank(triggerShape);
break;
case TT_FORD_ASPIRE:
configureFordAspireTriggerShape(this);
break;
case TT_GM_7X:
configureGmTriggerShape(this);
break;
case TT_MAZDA_DOHC_1_4:
configureMazdaProtegeLx(this);
break;
case TT_ONE_PLUS_ONE:
configureOnePlusOne(this, operationMode);
break;
case TT_3_1_CAM:
configure3_1_cam(this, operationMode);
break;
case TT_ONE_PLUS_TOOTHED_WHEEL_60_2:
configureOnePlus60_2(this, operationMode);
break;
case TT_ONE:
setToothedWheelConfiguration(this, 1, 0, operationMode);
break;
case TT_MAZDA_SOHC_4:
configureMazdaProtegeSOHC(this);
break;
case TT_MINI_COOPER_R50:
configureMiniCooperTriggerShape(this);
break;
case TT_TOOTHED_WHEEL_60_2:
setToothedWheelConfiguration(this, 60, 2, operationMode);
break;
case TT_60_2_VW:
setVwConfiguration(this);
break;
case TT_TOOTHED_WHEEL_36_1:
setToothedWheelConfiguration(this, 36, 1, operationMode);
break;
case TT_HONDA_4_24_1:
configureHonda_1_4_24(this, true, true, T_CHANNEL_3, T_PRIMARY, 0);
break;
case TT_HONDA_4_24:
configureHonda_1_4_24(this, false, true, T_NONE, T_PRIMARY, 0);
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;
case TT_HONDA_CBR_600:
configureHondaCbr600(this);
break;
case TT_HONDA_CBR_600_CUSTOM:
configureHondaCbr600custom(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:
initialize2jzGE3_34(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_GM_LS_24:
initGmLS24(this);
break;
default:
shapeDefinitionError = true;
warning(CUSTOM_ERR_NO_SHAPE, "initializeTriggerShape() not implemented: %d", triggerConfig->type);
}
calculateExpectedEventCounts(useOnlyRisingEdgeForTrigger);
version++;
if (!shapeDefinitionError) {
wave.checkSwitchTimes(getSize());
}
}

View File

@ -2,17 +2,42 @@
* @file trigger_structure.h
*
* @date Dec 22, 2013
* @author Andrey Belomutskiy, (c) 2012-2017
* @author Andrey Belomutskiy, (c) 2012-2018
*/
#ifndef TRIGGER_STRUCTURE_H_
#define TRIGGER_STRUCTURE_H_
#include "global.h"
#include "engine_configuration_generated_structures.h"
#include "EfiWave.h"
// todo: this header should know nothing about engine or engine configuration. todo: refactor
#include "engine_configuration.h"
#if EFI_ENABLE_ASSERTS
#define assertAngleRange(angle, msg, code) if(angle > 10000000 || angle < -10000000) { firmwareError(code, "angle range %s %.2f", msg, angle);angle = 0;}
#else
#define assertAngleRange(angle, msg, code) {}
#endif
/**
* @brief Shifts angle into the [0..720) range for four stroke and [0..360) for two stroke
* I guess this implementation would be faster than 'angle % engineCycle'
*/
#define fixAngle2(angle, msg, code, engineCycle) \
{ \
if (cisnan(angle)) { \
firmwareError(CUSTOM_ERR_ANGLE, "aNaN%s", msg); \
angle = 0; \
} \
assertAngleRange(angle, msg, code); \
float engineCycleDurationLocalCopy = engineCycle; \
/* todo: split this method into 'fixAngleUp' and 'fixAngleDown'*/ \
/* as a performance optimization?*/ \
while (angle < 0) \
angle += engineCycleDurationLocalCopy; \
/* todo: would 'if' work as good as 'while'? */ \
while (angle >= engineCycleDurationLocalCopy) \
angle -= engineCycleDurationLocalCopy; \
}
/**
* This structure defines an angle position within the trigger
@ -54,9 +79,10 @@ class TriggerState;
class TriggerShape {
public:
TriggerShape();
void initializeTriggerShape(Logging *logger, bool useOnlyRisingEdgeForTrigger DECLARE_ENGINE_PARAMETER_SUFFIX);
void findTriggerPosition(
event_trigger_position_s *position, angle_t angleOffset DECLARE_ENGINE_PARAMETER_SUFFIX);
void initializeTriggerShape(Logging *logger, operation_mode_e operationMode,
bool useOnlyRisingEdgeForTrigger, const trigger_config_s *triggerConfig);
void findTriggerPosition(event_trigger_position_s *position,
angle_t angleOffset DEFINE_CONFIG_PARAM(angle_t, globalTriggerAngleOffset));
bool isSynchronizationNeeded;
/**
@ -183,10 +209,6 @@ public:
* Deprecated?
*/
void addEvent720(angle_t angle, trigger_wheel_e const channelIndex, trigger_value_e const state);
/* 0..720 angle range
* Deprecated?
*/
void addEvent2(angle_t angle, trigger_wheel_e const channelIndex, trigger_value_e const state DECLARE_ENGINE_PARAMETER_SUFFIX);
/* 0..720 angle range
* Deprecated?
@ -208,19 +230,24 @@ public:
int getSize() const;
int getTriggerShapeSynchPointIndex();
void prepareShape(DECLARE_ENGINE_PARAMETER_SIGNATURE);
void calculateTriggerSynchPoint(TriggerState *state DECLARE_ENGINE_PARAMETER_SUFFIX);
void prepareShape();
private:
trigger_shape_helper h;
int findAngleIndex(float angle);
/**
* This private method should only be used to prepare the array of pre-calculated values
* See eventAngles array
*/
angle_t getAngle(int phaseIndex) const;
/**
* index of synchronization event within TriggerShape
* See findTriggerZeroEventIndex()
*/
int triggerShapeSynchPointIndex;
private:
trigger_shape_helper h;
int findAngleIndex(float angle);
/**
* Working buffer for 'wave' instance
* Values are in the 0..1 range
@ -241,11 +268,6 @@ private:
*/
operation_mode_e operationMode;
/**
* This private method should only be used to prepare the array of pre-calculated values
* See eventAngles array
*/
angle_t getAngle(int phaseIndex) const;
angle_t getCycleDuration() const;
};

View File

@ -100,7 +100,7 @@ static void prepareCylinderIgnitionSchedule(angle_t dwellAngle, IgnitionEvent *e
angle_t a = localAdvance - dwellAngle;
efiAssertVoid(CUSTOM_ERR_6590, !cisnan(a), "findAngle#5");
assertAngleRange(a, "findAngle#a6", CUSTOM_ERR_6550);
TRIGGER_SHAPE(findTriggerPosition(&event->dwellPosition, a PASS_ENGINE_PARAMETER_SUFFIX));
TRIGGER_SHAPE(findTriggerPosition(&event->dwellPosition, a PASS_CONFIG_PARAM(engineConfiguration->globalTriggerAngleOffset)));
#if FUEL_MATH_EXTREME_LOGGING || defined(__DOXYGEN__)
printf("addIgnitionEvent %s ind=%d\n", output->name, event->dwellPosition.eventIndex);
@ -233,7 +233,7 @@ static ALWAYS_INLINE void handleSparkEvent(bool limitedSpark, uint32_t trgEventI
efiAssertVoid(CUSTOM_ERR_6591, !cisnan(advance), "findAngle#4");
assertAngleRange(advance, "findAngle#a5", CUSTOM_ERR_6549);
TRIGGER_SHAPE(findTriggerPosition(&iEvent->sparkPosition, advance PASS_ENGINE_PARAMETER_SUFFIX));
TRIGGER_SHAPE(findTriggerPosition(&iEvent->sparkPosition, advance PASS_CONFIG_PARAM(engineConfiguration->globalTriggerAngleOffset)));
#if EFI_UNIT_TEST || defined(__DOXYGEN__)
printf("spark dwell@ %d/%d spark@ %d/%d id=%d\r\n", iEvent->dwellPosition.eventIndex, (int)iEvent->dwellPosition.angleOffset,

View File

@ -3,7 +3,7 @@ TRIGGER_DECODERS_SRC_CPP = \
$(PROJECT_DIR)/controllers/trigger/decoders/trigger_bmw.cpp \
$(PROJECT_DIR)/controllers/trigger/decoders/trigger_mazda.cpp \
$(PROJECT_DIR)/controllers/trigger/decoders/trigger_chrysler.cpp \
$(PROJECT_DIR)/controllers/trigger/trigger_structure.cpp \
$(PROJECT_DIR)/controllers/trigger/decoders/trigger_structure.cpp \
$(PROJECT_DIR)/controllers/trigger/trigger_decoder.cpp \
$(PROJECT_DIR)/controllers/trigger/trigger_simulator.cpp \
$(PROJECT_DIR)/controllers/trigger/decoders/trigger_mitsubishi.cpp \

View File

@ -25,25 +25,11 @@
#include "obd_error_codes.h"
#include "trigger_decoder.h"
#include "cyclic_buffer.h"
#include "trigger_mazda.h"
#include "trigger_chrysler.h"
#include "trigger_gm.h"
#include "trigger_bmw.h"
#include "trigger_mitsubishi.h"
#include "trigger_subaru.h"
#include "trigger_nissan.h"
#include "trigger_toyota.h"
#include "trigger_rover.h"
#include "trigger_honda.h"
#include "trigger_vw.h"
#include "trigger_structure.h"
#include "efiGpio.h"
#include "engine.h"
#include "engine_math.h"
#include "trigger_central.h"
#include "trigger_simulator.h"
#include "trigger_universal.h"
#include "trigger_misc.h"
#include "rfiutil.h"
#if EFI_SENSOR_CHART || defined(__DOXYGEN__)
@ -79,6 +65,135 @@ bool isTriggerDecoderError(void) {
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 */
}
}
bool TriggerState::isValidIndex(DECLARE_ENGINE_PARAMETER_SIGNATURE) {
return currentCycle.current_index < getTriggerSize();
}
@ -469,210 +584,6 @@ void TriggerState::decodeTriggerEvent(trigger_event_e const signal, efitime_t no
}
}
/**
* External logger is needed because at this point our logger is not yet initialized
*/
void TriggerShape::initializeTriggerShape(Logging *logger, bool useOnlyRisingEdgeForTrigger DECLARE_ENGINE_PARAMETER_SUFFIX) {
const trigger_config_s *triggerConfig = &engineConfiguration->trigger;
#if EFI_PROD_CODE || defined(__DOXYGEN__)
efiAssertVoid(CUSTOM_ERR_6641, getRemainingStack(chThdGetSelfX()) > 256, "init t");
scheduleMsg(logger, "initializeTriggerShape(%s/%d)", getTrigger_type_e(triggerConfig->type), (int) triggerConfig->type);
#endif
shapeDefinitionError = false;
this->useOnlyRisingEdgeForTriggerTemp = useOnlyRisingEdgeForTrigger;
switch (triggerConfig->type) {
case TT_TOOTHED_WHEEL:
initializeSkippedToothTriggerShapeExt(this, triggerConfig->customTotalToothCount,
triggerConfig->customSkippedToothCount, engineConfiguration->operationMode);
break;
case TT_MAZDA_MIATA_NA:
initializeMazdaMiataNaShape(this, useOnlyRisingEdgeForTrigger);
break;
case TT_MAZDA_MIATA_NB1:
initializeMazdaMiataNb1Shape(this);
break;
case TT_MAZDA_MIATA_VVT_TEST:
initializeMazdaMiataVVtTestShape(this);
break;
case TT_MAZDA_Z5:
initialize_Mazda_Engine_z5_Shape(this);
break;
case TT_MIATA_VVT:
initializeMazdaMiataNb2Crank(this);
break;
case TT_DODGE_NEON_1995:
configureNeon1995TriggerShape(this);
break;
case TT_DODGE_NEON_1995_ONLY_CRANK:
configureNeon1995TriggerShapeOnlyCrank(this);
break;
case TT_DODGE_STRATUS:
configureDodgeStratusTriggerShape(this);
break;
case TT_DODGE_NEON_2003_CAM:
configureNeon2003TriggerShapeCam(this);
break;
case TT_DODGE_NEON_2003_CRANK:
configureNeon2003TriggerShapeCam(this);
// configureNeon2003TriggerShapeCrank(triggerShape);
break;
case TT_FORD_ASPIRE:
configureFordAspireTriggerShape(this);
break;
case TT_GM_7X:
configureGmTriggerShape(this);
break;
case TT_MAZDA_DOHC_1_4:
configureMazdaProtegeLx(this);
break;
case TT_ONE_PLUS_ONE:
configureOnePlusOne(this, engineConfiguration->operationMode);
break;
case TT_3_1_CAM:
configure3_1_cam(this, engineConfiguration->operationMode);
break;
case TT_ONE_PLUS_TOOTHED_WHEEL_60_2:
configureOnePlus60_2(this, engineConfiguration->operationMode);
break;
case TT_ONE:
setToothedWheelConfiguration(this, 1, 0, engineConfiguration->operationMode);
break;
case TT_MAZDA_SOHC_4:
configureMazdaProtegeSOHC(this);
break;
case TT_MINI_COOPER_R50:
configureMiniCooperTriggerShape(this);
break;
case TT_TOOTHED_WHEEL_60_2:
setToothedWheelConfiguration(this, 60, 2, engineConfiguration->operationMode);
break;
case TT_60_2_VW:
setVwConfiguration(this);
break;
case TT_TOOTHED_WHEEL_36_1:
setToothedWheelConfiguration(this, 36, 1, engineConfiguration->operationMode);
break;
case TT_HONDA_4_24_1:
configureHonda_1_4_24(this, true, true, T_CHANNEL_3, T_PRIMARY, 0);
break;
case TT_HONDA_4_24:
configureHonda_1_4_24(this, false, true, T_NONE, T_PRIMARY, 0);
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;
case TT_HONDA_CBR_600:
configureHondaCbr600(this);
break;
case TT_HONDA_CBR_600_CUSTOM:
configureHondaCbr600custom(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:
initialize2jzGE3_34(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_GM_LS_24:
initGmLS24(this);
break;
default:
shapeDefinitionError = true;
warning(CUSTOM_ERR_NO_SHAPE, "initializeTriggerShape() not implemented: %d", triggerConfig->type);
}
calculateExpectedEventCounts(useOnlyRisingEdgeForTrigger);
version++;
if (!shapeDefinitionError) {
wave.checkSwitchTimes(getSize());
}
}
static void onFindIndexCallback(TriggerState *state) {
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!
@ -735,7 +646,21 @@ void initTriggerDecoderLogger(Logging *sharedLogger) {
logger = sharedLogger;
}
void initTriggerDecoder(void) {
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) {
#if EFI_GPIO_HARDWARE || defined(__DOXYGEN__)
enginePins.triggerDecoderErrorPin.initPin("trg_err", boardConfiguration->triggerErrorPin,
&boardConfiguration->triggerErrorPinMode);

View File

@ -154,5 +154,7 @@ void initTriggerDecoderLogger(Logging *sharedLogger);
bool isTriggerDecoderError(void);
void calculateTriggerSynchPoint(TriggerShape *shape, TriggerState *state DECLARE_ENGINE_PARAMETER_SUFFIX);
#endif /* TRIGGER_DECODER_H_ */

View File

@ -70,6 +70,9 @@ class Engine;
#define PASS_ENGINE_PARAMETER_SUFFIX , engine, engineConfiguration, config, boardConfiguration
#define DEFINE_CONFIG_PARAM(x, y) , x y
#define PASS_CONFIG_PARAM(x) , x
/**
* this macro is a work-around for uint tests to get all needed pointers only
* if engine is in scope
@ -90,4 +93,6 @@ class Engine;
#define CONFIG(x) engineConfiguration->x
#define ENGINE(x) engine->x
#define CONFIG_PARAM(x) (x)
#endif /* GLOBAL_H_ */

View File

@ -184,32 +184,32 @@ void testAngleResolver(void) {
event_trigger_position_s injectionStart;
printf("*************************************************** testAngleResolver 0\r\n");
TRIGGER_SHAPE(findTriggerPosition(&injectionStart, -122 PASS_ENGINE_PARAMETER_SUFFIX));
TRIGGER_SHAPE(findTriggerPosition(&injectionStart, -122, engineConfiguration->globalTriggerAngleOffset));
assertEqualsM("eventIndex@0", 2, injectionStart.eventIndex);
assertEquals(0.24, injectionStart.angleOffset);
printf("*************************************************** testAngleResolver 0.1\r\n");
TRIGGER_SHAPE(findTriggerPosition(&injectionStart, -80 PASS_ENGINE_PARAMETER_SUFFIX));
TRIGGER_SHAPE(findTriggerPosition(&injectionStart, -80, engineConfiguration->globalTriggerAngleOffset));
assertEqualsM("eventIndex@0", 2, injectionStart.eventIndex);
assertEquals(42.24, injectionStart.angleOffset);
printf("*************************************************** testAngleResolver 0.2\r\n");
TRIGGER_SHAPE(findTriggerPosition(&injectionStart, -54 PASS_ENGINE_PARAMETER_SUFFIX));
TRIGGER_SHAPE(findTriggerPosition(&injectionStart, -54, engineConfiguration->globalTriggerAngleOffset));
assertEqualsM("eventIndex@0", 2, injectionStart.eventIndex);
assertEquals(68.2400, injectionStart.angleOffset);
printf("*************************************************** testAngleResolver 0.3\r\n");
TRIGGER_SHAPE(findTriggerPosition(&injectionStart, -53 PASS_ENGINE_PARAMETER_SUFFIX));
TRIGGER_SHAPE(findTriggerPosition(&injectionStart, -53, engineConfiguration->globalTriggerAngleOffset));
assertEquals(2, injectionStart.eventIndex);
assertEquals(69.24, injectionStart.angleOffset);
printf("*************************************************** testAngleResolver 1\r\n");
TRIGGER_SHAPE(findTriggerPosition(&injectionStart, 0 PASS_ENGINE_PARAMETER_SUFFIX));
TRIGGER_SHAPE(findTriggerPosition(&injectionStart, 0, engineConfiguration->globalTriggerAngleOffset));
assertEquals(2, injectionStart.eventIndex);
assertEquals(122.24, injectionStart.angleOffset);
printf("*************************************************** testAngleResolver 2\r\n");
TRIGGER_SHAPE(findTriggerPosition(&injectionStart, 56 PASS_ENGINE_PARAMETER_SUFFIX));
TRIGGER_SHAPE(findTriggerPosition(&injectionStart, 56, engineConfiguration->globalTriggerAngleOffset));
assertEquals(2, injectionStart.eventIndex);
assertEquals(178.24, injectionStart.angleOffset);

View File

@ -168,13 +168,13 @@ void test1995FordInline6TriggerDecoder(void) {
event_trigger_position_s position;
assertEqualsM("globalTriggerAngleOffset", 0, engineConfiguration->globalTriggerAngleOffset);
TRIGGER_SHAPE(findTriggerPosition(&position, 0 PASS_ENGINE_PARAMETER_SUFFIX));
TRIGGER_SHAPE(findTriggerPosition(&position, 0, engineConfiguration->globalTriggerAngleOffset));
assertTriggerPosition(&position, 0, 0);
TRIGGER_SHAPE(findTriggerPosition(&position, 200 PASS_ENGINE_PARAMETER_SUFFIX));
TRIGGER_SHAPE(findTriggerPosition(&position, 200, engineConfiguration->globalTriggerAngleOffset));
assertTriggerPosition(&position, 3, 20);
TRIGGER_SHAPE(findTriggerPosition(&position, 360 PASS_ENGINE_PARAMETER_SUFFIX));
TRIGGER_SHAPE(findTriggerPosition(&position, 360, engineConfiguration->globalTriggerAngleOffset));
assertTriggerPosition(&position, 6, 0);
eth.applyTriggerShape();