VVT support for VAG trigger #883

This commit is contained in:
rusefi 2020-08-25 00:59:07 -04:00
parent 7e5ded02e7
commit 540eef5e0d
13 changed files with 113 additions and 76 deletions

View File

@ -347,7 +347,7 @@ static percent_t automaticIdleController(float tpsPos DECLARE_ENGINE_PARAMETER_S
float rpm; float rpm;
if (CONFIG(useInstantRpmForIdle)) { if (CONFIG(useInstantRpmForIdle)) {
rpm = engine->triggerCentral.triggerState.calculateInstantRpm(NULL, nowNt PASS_ENGINE_PARAMETER_SUFFIX); rpm = engine->triggerCentral.triggerState.calculateInstantRpm(&engine->triggerCentral.triggerFormDetails, NULL, nowNt PASS_ENGINE_PARAMETER_SUFFIX);
} else { } else {
rpm = GET_RPM(); rpm = GET_RPM();
} }

View File

@ -98,6 +98,7 @@ void Engine::initializeTriggerWaveform(Logging *logger DECLARE_ENGINE_PARAMETER_
*/ */
initState.resetTriggerState(); initState.resetTriggerState();
calculateTriggerSynchPoint(&ENGINE(triggerCentral.triggerShape), calculateTriggerSynchPoint(&ENGINE(triggerCentral.triggerShape),
&ENGINE(triggerCentral.triggerFormDetails),
&initState PASS_ENGINE_PARAMETER_SUFFIX); &initState PASS_ENGINE_PARAMETER_SUFFIX);
if (engine->triggerCentral.triggerShape.getSize() == 0) { if (engine->triggerCentral.triggerShape.getSize() == 0) {
@ -311,7 +312,7 @@ void Engine::OnTriggerStateProperState(efitick_t nowNt) {
Engine *engine = this; Engine *engine = this;
EXPAND_Engine; EXPAND_Engine;
triggerCentral.triggerState.runtimeStatistics(nowNt PASS_ENGINE_PARAMETER_SUFFIX); triggerCentral.triggerState.runtimeStatistics(&triggerCentral.triggerFormDetails, nowNt PASS_ENGINE_PARAMETER_SUFFIX);
rpmCalculator.setSpinningUp(nowNt PASS_ENGINE_PARAMETER_SUFFIX); rpmCalculator.setSpinningUp(nowNt PASS_ENGINE_PARAMETER_SUFFIX);
} }

View File

@ -241,7 +241,7 @@ void refreshMapAveragingPreCalc(DECLARE_ENGINE_PARAMETER_SIGNATURE) {
angle_t start = interpolate2d("mapa", rpm, c->samplingAngleBins, c->samplingAngle); angle_t start = interpolate2d("mapa", rpm, c->samplingAngleBins, c->samplingAngle);
efiAssertVoid(CUSTOM_ERR_MAP_START_ASSERT, !cisnan(start), "start"); efiAssertVoid(CUSTOM_ERR_MAP_START_ASSERT, !cisnan(start), "start");
angle_t offsetAngle = TRIGGER_WAVEFORM(eventAngles[CONFIG(mapAveragingSchedulingAtIndex)]); angle_t offsetAngle = ENGINE(triggerCentral.triggerFormDetails).eventAngles[CONFIG(mapAveragingSchedulingAtIndex)];
efiAssertVoid(CUSTOM_ERR_MAP_AVG_OFFSET, !cisnan(offsetAngle), "offsetAngle"); efiAssertVoid(CUSTOM_ERR_MAP_AVG_OFFSET, !cisnan(offsetAngle), "offsetAngle");
for (int i = 0; i < engineConfiguration->specs.cylindersCount; i++) { for (int i = 0; i < engineConfiguration->specs.cylindersCount; i++) {

View File

@ -278,7 +278,8 @@ void rpmShaftPositionCallback(trigger_event_e ckpSignalType,
// Replace 'normal' RPM with instant RPM for the initial spin-up period // Replace 'normal' RPM with instant RPM for the initial spin-up period
engine->triggerCentral.triggerState.movePreSynchTimestamps(PASS_ENGINE_PARAMETER_SIGNATURE); engine->triggerCentral.triggerState.movePreSynchTimestamps(PASS_ENGINE_PARAMETER_SIGNATURE);
int prevIndex; int prevIndex;
int instantRpm = engine->triggerCentral.triggerState.calculateInstantRpm(&prevIndex, nowNt PASS_ENGINE_PARAMETER_SUFFIX); int instantRpm = engine->triggerCentral.triggerState.calculateInstantRpm(&engine->triggerCentral.triggerFormDetails,
&prevIndex, nowNt PASS_ENGINE_PARAMETER_SUFFIX);
// validate instant RPM - we shouldn't skip the cranking state // validate instant RPM - we shouldn't skip the cranking state
instantRpm = minI(instantRpm, CONFIG(cranking.rpm) - 1); instantRpm = minI(instantRpm, CONFIG(cranking.rpm) - 1);
rpmState->assignRpmValue(instantRpm PASS_ENGINE_PARAMETER_SUFFIX); rpmState->assignRpmValue(instantRpm PASS_ENGINE_PARAMETER_SUFFIX);

View File

@ -414,7 +414,7 @@ void prepareOutputSignals(DECLARE_ENGINE_PARAMETER_SIGNATURE) {
prepareIgnitionPinIndices(CONFIG(ignitionMode) PASS_ENGINE_PARAMETER_SUFFIX); prepareIgnitionPinIndices(CONFIG(ignitionMode) PASS_ENGINE_PARAMETER_SUFFIX);
TRIGGER_WAVEFORM(prepareShape()); TRIGGER_WAVEFORM(prepareShape(&ENGINE(triggerCentral.triggerFormDetails)));
} }
void setTimingRpmBin(float from, float to DECLARE_CONFIG_PARAMETER_SUFFIX) { void setTimingRpmBin(float from, float to DECLARE_CONFIG_PARAMETER_SUFFIX) {

View File

@ -48,7 +48,9 @@
EXTERN_ENGINE; EXTERN_ENGINE;
void event_trigger_position_s::setAngle(angle_t angle DECLARE_ENGINE_PARAMETER_SUFFIX) { void event_trigger_position_s::setAngle(angle_t angle DECLARE_ENGINE_PARAMETER_SUFFIX) {
TRIGGER_WAVEFORM(findTriggerPosition(this, angle PASS_CONFIG_PARAM(engineConfiguration->globalTriggerAngleOffset))); findTriggerPosition(&ENGINE(triggerCentral.triggerShape),
&ENGINE(triggerCentral.triggerFormDetails),
this, angle PASS_CONFIG_PARAM(engineConfiguration->globalTriggerAngleOffset));
} }
trigger_shape_helper::trigger_shape_helper() { trigger_shape_helper::trigger_shape_helper() {
@ -62,7 +64,9 @@ TriggerWaveform::TriggerWaveform() :
wave(switchTimesBuffer, NULL) { wave(switchTimesBuffer, NULL) {
initialize(OM_NONE); initialize(OM_NONE);
wave.channels = h.channels; wave.channels = h.channels;
}
TriggerFormDetails::TriggerFormDetails() {
memset(triggerIndexByAngle, 0, sizeof(triggerIndexByAngle)); memset(triggerIndexByAngle, 0, sizeof(triggerIndexByAngle));
} }
@ -72,7 +76,6 @@ void TriggerWaveform::initialize(operation_mode_e operationMode) {
needSecondTriggerInput = false; needSecondTriggerInput = false;
shapeWithoutTdc = false; shapeWithoutTdc = false;
memset(expectedDutyCycle, 0, sizeof(expectedDutyCycle)); memset(expectedDutyCycle, 0, sizeof(expectedDutyCycle));
memset(eventAngles, 0, sizeof(eventAngles));
// memset(triggerIndexByAngle, 0, sizeof(triggerIndexByAngle)); // memset(triggerIndexByAngle, 0, sizeof(triggerIndexByAngle));
setTriggerSynchronizationGap(2); setTriggerSynchronizationGap(2);
@ -342,7 +345,7 @@ void TriggerWaveform::setTriggerSynchronizationGap3(int gapIndex, float syncRati
/** /**
* this method is only used on initialization * this method is only used on initialization
*/ */
int TriggerWaveform::findAngleIndex(float target) const { int TriggerWaveform::findAngleIndex(TriggerFormDetails *details, float target) const {
int engineCycleEventCount = getLength(); int engineCycleEventCount = getLength();
efiAssert(CUSTOM_ERR_ASSERT, engineCycleEventCount > 0, "engineCycleEventCount", 0); efiAssert(CUSTOM_ERR_ASSERT, engineCycleEventCount > 0, "engineCycleEventCount", 0);
@ -356,7 +359,7 @@ int TriggerWaveform::findAngleIndex(float target) const {
*/ */
while (left <= right) { while (left <= right) {
int middle = (left + right) / 2; int middle = (left + right) / 2;
angle_t eventAngle = eventAngles[middle]; angle_t eventAngle = details->eventAngles[middle];
if (eventAngle < target) { if (eventAngle < target) {
left = middle + 1; left = middle + 1;
@ -374,24 +377,26 @@ void TriggerWaveform::setShapeDefinitionError(bool value) {
shapeDefinitionError = value; shapeDefinitionError = value;
} }
void TriggerWaveform::findTriggerPosition(event_trigger_position_s *position, void findTriggerPosition(TriggerWaveform *triggerShape,
TriggerFormDetails *details,
event_trigger_position_s *position,
angle_t angle DEFINE_CONFIG_PARAM(angle_t, globalTriggerAngleOffset)) { angle_t angle DEFINE_CONFIG_PARAM(angle_t, globalTriggerAngleOffset)) {
efiAssertVoid(CUSTOM_ERR_6574, !cisnan(angle), "findAngle#1"); efiAssertVoid(CUSTOM_ERR_6574, !cisnan(angle), "findAngle#1");
assertAngleRange(angle, "findAngle#a1", CUSTOM_ERR_6545); assertAngleRange(angle, "findAngle#a1", CUSTOM_ERR_6545);
efiAssertVoid(CUSTOM_ERR_6575, !cisnan(tdcPosition), "tdcPos#1") efiAssertVoid(CUSTOM_ERR_6575, !cisnan(triggerShape->tdcPosition), "tdcPos#1")
assertAngleRange(tdcPosition, "tdcPos#a1", CUSTOM_UNEXPECTED_TDC_ANGLE); assertAngleRange(triggerShape->tdcPosition, "tdcPos#a1", CUSTOM_UNEXPECTED_TDC_ANGLE);
efiAssertVoid(CUSTOM_ERR_6576, !cisnan(CONFIG_PARAM(globalTriggerAngleOffset)), "tdcPos#2") efiAssertVoid(CUSTOM_ERR_6576, !cisnan(CONFIG_PARAM(globalTriggerAngleOffset)), "tdcPos#2")
assertAngleRange(CONFIG_PARAM(globalTriggerAngleOffset), "tdcPos#a2", CUSTOM_INVALID_GLOBAL_OFFSET); assertAngleRange(CONFIG_PARAM(globalTriggerAngleOffset), "tdcPos#a2", CUSTOM_INVALID_GLOBAL_OFFSET);
// convert engine cycle angle into trigger cycle angle // convert engine cycle angle into trigger cycle angle
angle += tdcPosition + CONFIG_PARAM(globalTriggerAngleOffset); angle += triggerShape->tdcPosition + CONFIG_PARAM(globalTriggerAngleOffset);
efiAssertVoid(CUSTOM_ERR_6577, !cisnan(angle), "findAngle#2"); efiAssertVoid(CUSTOM_ERR_6577, !cisnan(angle), "findAngle#2");
fixAngle2(angle, "addFuel#2", CUSTOM_ERR_6555, getEngineCycle(operationMode)); fixAngle2(angle, "addFuel#2", CUSTOM_ERR_6555, getEngineCycle(triggerShape->getOperationMode()));
int triggerEventIndex = triggerIndexByAngle[(int)angle]; int triggerEventIndex = details->triggerIndexByAngle[(int)angle];
angle_t triggerEventAngle = eventAngles[triggerEventIndex]; angle_t triggerEventAngle = details->eventAngles[triggerEventIndex];
if (angle < triggerEventAngle) { if (angle < triggerEventAngle) {
warning(CUSTOM_OBD_ANGLE_CONSTRAINT_VIOLATION, "angle constraint violation in findTriggerPosition(): %.2f/%.2f", angle, triggerEventAngle); warning(CUSTOM_OBD_ANGLE_CONSTRAINT_VIOLATION, "angle constraint violation in findTriggerPosition(): %.2f/%.2f", angle, triggerEventAngle);
return; return;
@ -401,16 +406,16 @@ void TriggerWaveform::findTriggerPosition(event_trigger_position_s *position,
position->angleOffsetFromTriggerEvent = angle - triggerEventAngle; position->angleOffsetFromTriggerEvent = angle - triggerEventAngle;
} }
void TriggerWaveform::prepareShape() { void TriggerWaveform::prepareShape(TriggerFormDetails *details) {
#if EFI_ENGINE_CONTROL && EFI_SHAFT_POSITION_INPUT #if EFI_ENGINE_CONTROL && EFI_SHAFT_POSITION_INPUT
int engineCycleInt = (int) getEngineCycle(operationMode); int engineCycleInt = (int) getEngineCycle(operationMode);
for (int angle = 0; angle < engineCycleInt; angle++) { for (int angle = 0; angle < engineCycleInt; angle++) {
int triggerShapeIndex = findAngleIndex(angle); int triggerShapeIndex = findAngleIndex(details, angle);
if (useOnlyRisingEdgeForTriggerTemp) { if (useOnlyRisingEdgeForTriggerTemp) {
// we need even index for front_only mode - so if odd indexes are rounded down // we need even index for front_only mode - so if odd indexes are rounded down
triggerShapeIndex = triggerShapeIndex & 0xFFFFFFFE; triggerShapeIndex = triggerShapeIndex & 0xFFFFFFFE;
} }
triggerIndexByAngle[angle] = triggerShapeIndex; details->triggerIndexByAngle[angle] = triggerShapeIndex;
} }
#endif #endif
} }

View File

@ -65,6 +65,7 @@ private:
class Engine; class Engine;
class TriggerState; class TriggerState;
class TriggerFormDetails;
#define GAP_TRACKING_LENGTH 4 #define GAP_TRACKING_LENGTH 4
@ -77,8 +78,6 @@ public:
TriggerWaveform(); TriggerWaveform();
void initializeTriggerWaveform(Logging *logger, operation_mode_e ambiguousOperationMode, void initializeTriggerWaveform(Logging *logger, operation_mode_e ambiguousOperationMode,
bool useOnlyRisingEdgeForTrigger, const trigger_config_s *triggerConfig); bool useOnlyRisingEdgeForTrigger, const trigger_config_s *triggerConfig);
void findTriggerPosition(event_trigger_position_s *position,
angle_t angle DEFINE_CONFIG_PARAM(angle_t, globalTriggerAngleOffset));
void setShapeDefinitionError(bool value); void setShapeDefinitionError(bool value);
/** /**
@ -122,17 +121,6 @@ public:
*/ */
float expectedDutyCycle[PWM_PHASE_MAX_WAVE_PER_PWM]; float expectedDutyCycle[PWM_PHASE_MAX_WAVE_PER_PWM];
/**
* These angles are in event coordinates - with synchronization point located at angle zero.
* These values are pre-calculated for performance reasons.
*/
angle_t eventAngles[PWM_PHASE_MAX_COUNT];
/**
* this cache allows us to find a close-enough (with one degree precision) trigger wheel index by
* given angle with fast constant speed. That's a performance optimization for event scheduling.
*/
int triggerIndexByAngle[720];
/** /**
* Depending on trigger shape, we use betweeb one and three previous gap ranges to detect synchronizaiton. * Depending on trigger shape, we use betweeb one and three previous gap ranges to detect synchronizaiton.
@ -247,7 +235,7 @@ public:
size_t getSize() const; size_t getSize() const;
int getTriggerWaveformSynchPointIndex() const; int getTriggerWaveformSynchPointIndex() const;
void prepareShape(); void prepareShape(TriggerFormDetails *details);
/** /**
* This private method should only be used to prepare the array of pre-calculated values * This private method should only be used to prepare the array of pre-calculated values
@ -265,7 +253,7 @@ public:
private: private:
trigger_shape_helper h; trigger_shape_helper h;
int findAngleIndex(float angle) const; int findAngleIndex(TriggerFormDetails *details, float angle) const;
/** /**
* Working buffer for 'wave' instance * Working buffer for 'wave' instance
@ -288,6 +276,30 @@ private:
operation_mode_e operationMode; operation_mode_e operationMode;
}; };
/**
* Misc values calculated from TriggerWaveform
*/
class TriggerFormDetails {
public:
TriggerFormDetails();
/**
* These angles are in event coordinates - with synchronization point located at angle zero.
* These values are pre-calculated for performance reasons.
*/
angle_t eventAngles[PWM_PHASE_MAX_COUNT];
/**
* this cache allows us to find a close-enough (with one degree precision) trigger wheel index by
* given angle with fast constant speed. That's a performance optimization for event scheduling.
*/
int triggerIndexByAngle[720];
};
void findTriggerPosition(
TriggerWaveform *shape,
TriggerFormDetails *details,
event_trigger_position_s *position,
angle_t angle DEFINE_CONFIG_PARAM(angle_t, globalTriggerAngleOffset));
void setToothedWheelConfiguration(TriggerWaveform *s, int total, int skipped, operation_mode_e operationMode); void setToothedWheelConfiguration(TriggerWaveform *s, int total, int skipped, operation_mode_e operationMode);
#define TRIGGER_WAVEFORM(x) ENGINE(triggerCentral.triggerShape.x) #define TRIGGER_WAVEFORM(x) ENGINE(triggerCentral.triggerShape.x)

View File

@ -507,12 +507,13 @@ EXTERN_ENGINE;
static void triggerShapeInfo(void) { static void triggerShapeInfo(void) {
#if EFI_PROD_CODE || EFI_SIMULATOR #if EFI_PROD_CODE || EFI_SIMULATOR
TriggerWaveform *s = &engine->triggerCentral.triggerShape; TriggerWaveform *shape = &engine->triggerCentral.triggerShape;
TriggerFormDetails *triggerFormDetails = &engine->triggerCentral.triggerFormDetails;
scheduleMsg(logger, "useRise=%s", boolToString(TRIGGER_WAVEFORM(useRiseEdge))); scheduleMsg(logger, "useRise=%s", boolToString(TRIGGER_WAVEFORM(useRiseEdge)));
scheduleMsg(logger, "gap from %.2f to %.2f", TRIGGER_WAVEFORM(syncronizationRatioFrom[0]), TRIGGER_WAVEFORM(syncronizationRatioTo[0])); scheduleMsg(logger, "gap from %.2f to %.2f", TRIGGER_WAVEFORM(syncronizationRatioFrom[0]), TRIGGER_WAVEFORM(syncronizationRatioTo[0]));
for (size_t i = 0; i < s->getSize(); i++) { for (size_t i = 0; i < shape->getSize(); i++) {
scheduleMsg(logger, "event %d %.2f", i, s->eventAngles[i]); scheduleMsg(logger, "event %d %.2f", i, triggerFormDetails->eventAngles[i]);
} }
#endif #endif
} }
@ -551,24 +552,25 @@ void printAllTriggers() {
engineConfiguration->trigger.type = tt; engineConfiguration->trigger.type = tt;
engineConfiguration->ambiguousOperationMode = FOUR_STROKE_CAM_SENSOR; engineConfiguration->ambiguousOperationMode = FOUR_STROKE_CAM_SENSOR;
TriggerWaveform *s = &engine->triggerCentral.triggerShape; TriggerWaveform *shape = &engine->triggerCentral.triggerShape;
TriggerFormDetails *triggerFormDetails = &engine->triggerCentral.triggerFormDetails;
engine->initializeTriggerWaveform(NULL PASS_ENGINE_PARAMETER_SUFFIX); engine->initializeTriggerWaveform(NULL PASS_ENGINE_PARAMETER_SUFFIX);
if (s->shapeDefinitionError) { if (shape->shapeDefinitionError) {
printf("Trigger error %d\r\n", triggerId); printf("Trigger error %d\r\n", triggerId);
exit(-1); exit(-1);
} }
fprintf(fp, "TRIGGERTYPE %d %d %s %.2f\n", triggerId, s->getLength(), getTrigger_type_e(tt), s->tdcPosition); fprintf(fp, "TRIGGERTYPE %d %d %s %.2f\n", triggerId, shape->getLength(), getTrigger_type_e(tt), shape->tdcPosition);
fprintf(fp, "# duty %.2f %.2f\n", s->expectedDutyCycle[0], s->expectedDutyCycle[1]); fprintf(fp, "# duty %.2f %.2f\n", shape->expectedDutyCycle[0], shape->expectedDutyCycle[1]);
for (int i = 0; i < s->getLength(); i++) { for (int i = 0; i < shape->getLength(); i++) {
int triggerDefinitionCoordinate = (s->getTriggerWaveformSynchPointIndex() + i) % s->getSize(); int triggerDefinitionCoordinate = (shape->getTriggerWaveformSynchPointIndex() + i) % shape->getSize();
fprintf(fp, "event %d %d %.2f\n", i, s->triggerSignals[triggerDefinitionCoordinate], s->eventAngles[i]); fprintf(fp, "event %d %d %.2f\n", i, shape->triggerSignals[triggerDefinitionCoordinate], triggerFormDetails->eventAngles[i]);
} }
} }

View File

@ -62,6 +62,8 @@ public:
TriggerWaveform triggerShape; TriggerWaveform triggerShape;
TriggerFormDetails triggerFormDetails;
efitick_t previousVvtCamTime = DEEP_IN_THE_PAST_SECONDS * NT_PER_SECOND; efitick_t previousVvtCamTime = DEEP_IN_THE_PAST_SECONDS * NT_PER_SECOND;
efitick_t previousVvtCamDuration = 0; efitick_t previousVvtCamDuration = 0;

View File

@ -114,7 +114,9 @@ float actualSynchGap;
static Logging * logger = nullptr; static Logging * logger = nullptr;
void calculateTriggerSynchPoint(TriggerWaveform *shape, TriggerState *state DECLARE_ENGINE_PARAMETER_SUFFIX) { void calculateTriggerSynchPoint(TriggerWaveform *shape,
TriggerFormDetails *details,
TriggerState *state DECLARE_ENGINE_PARAMETER_SUFFIX) {
#if EFI_PROD_CODE #if EFI_PROD_CODE
efiAssertVoid(CUSTOM_TRIGGER_STACK, getCurrentRemainingStack() > EXPECTED_REMAINING_STACK, "calc s"); efiAssertVoid(CUSTOM_TRIGGER_STACK, getCurrentRemainingStack() > EXPECTED_REMAINING_STACK, "calc s");
#endif #endif
@ -139,12 +141,14 @@ void calculateTriggerSynchPoint(TriggerWaveform *shape, TriggerState *state DECL
int riseOnlyIndex = 0; int riseOnlyIndex = 0;
memset(details->eventAngles, 0, sizeof(details->eventAngles));
for (int eventIndex = 0; eventIndex < length; eventIndex++) { for (int eventIndex = 0; eventIndex < length; eventIndex++) {
if (eventIndex == 0) { if (eventIndex == 0) {
// explicit check for zero to avoid issues where logical zero is not exactly zero due to float nature // explicit check for zero to avoid issues where logical zero is not exactly zero due to float nature
shape->eventAngles[0] = 0; details->eventAngles[0] = 0;
// this value would be used in case of front-only // this value would be used in case of front-only
shape->eventAngles[1] = 0; details->eventAngles[1] = 0;
} else { } else {
assertAngleRange(shape->triggerShapeSynchPointIndex, "triggerShapeSynchPointIndex", CUSTOM_TRIGGER_SYNC_ANGLE2); assertAngleRange(shape->triggerShapeSynchPointIndex, "triggerShapeSynchPointIndex", CUSTOM_TRIGGER_SYNC_ANGLE2);
unsigned int triggerDefinitionCoordinate = (shape->triggerShapeSynchPointIndex + eventIndex) % engine->engineCycleEventCount; unsigned int triggerDefinitionCoordinate = (shape->triggerShapeSynchPointIndex + eventIndex) % engine->engineCycleEventCount;
@ -156,11 +160,11 @@ void calculateTriggerSynchPoint(TriggerWaveform *shape, TriggerState *state DECL
if (engineConfiguration->useOnlyRisingEdgeForTrigger) { if (engineConfiguration->useOnlyRisingEdgeForTrigger) {
if (shape->isRiseEvent[triggerDefinitionIndex]) { if (shape->isRiseEvent[triggerDefinitionIndex]) {
riseOnlyIndex += 2; riseOnlyIndex += 2;
shape->eventAngles[riseOnlyIndex] = angle; details->eventAngles[riseOnlyIndex] = angle;
shape->eventAngles[riseOnlyIndex + 1] = angle; details->eventAngles[riseOnlyIndex + 1] = angle;
} }
} else { } else {
shape->eventAngles[eventIndex] = angle; details->eventAngles[eventIndex] = angle;
} }
} }
} }
@ -182,13 +186,14 @@ void TriggerStateWithRunningStatistics::movePreSynchTimestamps(DECLARE_ENGINE_PA
} }
} }
float TriggerStateWithRunningStatistics::calculateInstantRpm(int *prevIndexOut, efitick_t nowNt DECLARE_ENGINE_PARAMETER_SUFFIX) { float TriggerStateWithRunningStatistics::calculateInstantRpm(TriggerFormDetails *triggerFormDetails,
int *prevIndexOut, efitick_t nowNt DECLARE_ENGINE_PARAMETER_SUFFIX) {
int current_index = currentCycle.current_index; // local copy so that noone changes the value on us int current_index = currentCycle.current_index; // local copy so that noone changes the value on us
timeOfLastEvent[current_index] = nowNt; timeOfLastEvent[current_index] = nowNt;
/** /**
* Here we calculate RPM based on last 90 degrees * Here we calculate RPM based on last 90 degrees
*/ */
angle_t currentAngle = TRIGGER_WAVEFORM(eventAngles[current_index]); angle_t currentAngle = triggerFormDetails->eventAngles[current_index];
// todo: make this '90' depend on cylinder count or trigger shape? // todo: make this '90' depend on cylinder count or trigger shape?
if (cisnan(currentAngle)) { if (cisnan(currentAngle)) {
return NOISY_RPM; return NOISY_RPM;
@ -196,14 +201,14 @@ float TriggerStateWithRunningStatistics::calculateInstantRpm(int *prevIndexOut,
angle_t previousAngle = currentAngle - 90; angle_t previousAngle = currentAngle - 90;
fixAngle(previousAngle, "prevAngle", CUSTOM_ERR_TRIGGER_ANGLE_RANGE); fixAngle(previousAngle, "prevAngle", CUSTOM_ERR_TRIGGER_ANGLE_RANGE);
// todo: prevIndex should be pre-calculated // todo: prevIndex should be pre-calculated
int prevIndex = TRIGGER_WAVEFORM(triggerIndexByAngle[(int)previousAngle]); int prevIndex = triggerFormDetails->triggerIndexByAngle[(int)previousAngle];
if (prevIndexOut) { if (prevIndexOut) {
*prevIndexOut = prevIndex; *prevIndexOut = prevIndex;
} }
// now let's get precise angle for that event // now let's get precise angle for that event
angle_t prevIndexAngle = TRIGGER_WAVEFORM(eventAngles[prevIndex]); angle_t prevIndexAngle = triggerFormDetails->eventAngles[prevIndex];
efitick_t time90ago = timeOfLastEvent[prevIndex]; efitick_t time90ago = timeOfLastEvent[prevIndex];
if (time90ago == 0) { if (time90ago == 0) {
return prevInstantRpmValue; return prevInstantRpmValue;
@ -244,16 +249,16 @@ void TriggerStateWithRunningStatistics::setLastEventTimeForInstantRpm(efitick_t
spinningEvents[spinningEventIndex++] = nowNt; spinningEvents[spinningEventIndex++] = nowNt;
} }
void TriggerStateWithRunningStatistics::runtimeStatistics(efitick_t nowNt DECLARE_ENGINE_PARAMETER_SUFFIX) { void TriggerStateWithRunningStatistics::runtimeStatistics(TriggerFormDetails *triggerFormDetails, efitick_t nowNt DECLARE_ENGINE_PARAMETER_SUFFIX) {
if (engineConfiguration->debugMode == DBG_INSTANT_RPM) { if (engineConfiguration->debugMode == DBG_INSTANT_RPM) {
instantRpm = calculateInstantRpm(NULL, nowNt PASS_ENGINE_PARAMETER_SUFFIX); instantRpm = calculateInstantRpm(triggerFormDetails, NULL, nowNt PASS_ENGINE_PARAMETER_SUFFIX);
} }
if (ENGINE(sensorChartMode) == SC_RPM_ACCEL || ENGINE(sensorChartMode) == SC_DETAILED_RPM) { if (ENGINE(sensorChartMode) == SC_RPM_ACCEL || ENGINE(sensorChartMode) == SC_DETAILED_RPM) {
int prevIndex; int prevIndex;
instantRpm = calculateInstantRpm(&prevIndex, nowNt PASS_ENGINE_PARAMETER_SUFFIX); instantRpm = calculateInstantRpm(triggerFormDetails, &prevIndex, nowNt PASS_ENGINE_PARAMETER_SUFFIX);
#if EFI_SENSOR_CHART #if EFI_SENSOR_CHART
angle_t currentAngle = TRIGGER_WAVEFORM(eventAngles[currentCycle.current_index]); angle_t currentAngle = triggerFormDetails->eventAngles[currentCycle.current_index];
if (CONFIG(sensorChartMode) == SC_DETAILED_RPM) { if (CONFIG(sensorChartMode) == SC_DETAILED_RPM) {
scAddData(currentAngle, instantRpm); scAddData(currentAngle, instantRpm);
} else { } else {

View File

@ -173,9 +173,9 @@ public:
*/ */
float prevInstantRpmValue = 0; float prevInstantRpmValue = 0;
void movePreSynchTimestamps(DECLARE_ENGINE_PARAMETER_SIGNATURE); void movePreSynchTimestamps(DECLARE_ENGINE_PARAMETER_SIGNATURE);
float calculateInstantRpm(int *prevIndex, efitick_t nowNt DECLARE_ENGINE_PARAMETER_SUFFIX); float calculateInstantRpm(TriggerFormDetails *triggerFormDetails, int *prevIndex, efitick_t nowNt DECLARE_ENGINE_PARAMETER_SUFFIX);
#if EFI_ENGINE_CONTROL && EFI_SHAFT_POSITION_INPUT #if EFI_ENGINE_CONTROL && EFI_SHAFT_POSITION_INPUT
void runtimeStatistics(efitick_t nowNt DECLARE_ENGINE_PARAMETER_SUFFIX); void runtimeStatistics(TriggerFormDetails *triggerFormDetails, efitick_t nowNt DECLARE_ENGINE_PARAMETER_SUFFIX);
#endif #endif
/** /**
* Update timeOfLastEvent[] on every trigger event - even without synchronization * Update timeOfLastEvent[] on every trigger event - even without synchronization
@ -190,5 +190,7 @@ class Engine;
void initTriggerDecoderLogger(Logging *sharedLogger); void initTriggerDecoderLogger(Logging *sharedLogger);
void calculateTriggerSynchPoint(TriggerWaveform *shape, TriggerState *state DECLARE_ENGINE_PARAMETER_SUFFIX); void calculateTriggerSynchPoint(TriggerWaveform *shape,
TriggerFormDetails *details,
TriggerState *state DECLARE_ENGINE_PARAMETER_SUFFIX);

View File

@ -146,11 +146,12 @@ TEST(misc, testAngleResolver) {
engineConfiguration->globalTriggerAngleOffset = 175; engineConfiguration->globalTriggerAngleOffset = 175;
TriggerWaveform * ts = &engine->triggerCentral.triggerShape; TriggerWaveform * ts = &engine->triggerCentral.triggerShape;
TriggerFormDetails *triggerFormDetails = &engine->triggerCentral.triggerFormDetails;
engine->initializeTriggerWaveform(NULL PASS_ENGINE_PARAMETER_SUFFIX); engine->initializeTriggerWaveform(NULL PASS_ENGINE_PARAMETER_SUFFIX);
assertEqualsM("index 2", 52.76, ts->eventAngles[3]); // this angle is relation to synch point assertEqualsM("index 2", 52.76, triggerFormDetails->eventAngles[3]); // this angle is relation to synch point
assertEqualsM("time 2", 0.3233, ts->wave.getSwitchTime(2)); assertEqualsM("time 2", 0.3233, ts->wave.getSwitchTime(2));
assertEqualsM("index 5", 412.76, ts->eventAngles[6]); assertEqualsM("index 5", 412.76, triggerFormDetails->eventAngles[6]);
assertEqualsM("time 5", 0.5733, ts->wave.getSwitchTime(5)); assertEqualsM("time 5", 0.5733, ts->wave.getSwitchTime(5));
ASSERT_EQ(4, ts->getTriggerWaveformSynchPointIndex()); ASSERT_EQ(4, ts->getTriggerWaveformSynchPointIndex());
@ -160,32 +161,32 @@ TEST(misc, testAngleResolver) {
event_trigger_position_s injectionStart; event_trigger_position_s injectionStart;
printf("*************************************************** testAngleResolver 0\r\n"); printf("*************************************************** testAngleResolver 0\r\n");
TRIGGER_WAVEFORM(findTriggerPosition(&injectionStart, -122, engineConfiguration->globalTriggerAngleOffset)); findTriggerPosition(&ENGINE(triggerCentral.triggerShape), &ENGINE(triggerCentral.triggerFormDetails),&injectionStart, -122, engineConfiguration->globalTriggerAngleOffset);
ASSERT_EQ( 2, injectionStart.triggerEventIndex) << "eventIndex@0"; ASSERT_EQ( 2, injectionStart.triggerEventIndex) << "eventIndex@0";
ASSERT_NEAR(0.24, injectionStart.angleOffsetFromTriggerEvent, EPS5D); ASSERT_NEAR(0.24, injectionStart.angleOffsetFromTriggerEvent, EPS5D);
printf("*************************************************** testAngleResolver 0.1\r\n"); printf("*************************************************** testAngleResolver 0.1\r\n");
TRIGGER_WAVEFORM(findTriggerPosition(&injectionStart, -80, engineConfiguration->globalTriggerAngleOffset)); findTriggerPosition(&ENGINE(triggerCentral.triggerShape), &ENGINE(triggerCentral.triggerFormDetails),&injectionStart, -80, engineConfiguration->globalTriggerAngleOffset);
ASSERT_EQ( 2, injectionStart.triggerEventIndex) << "eventIndex@0"; ASSERT_EQ( 2, injectionStart.triggerEventIndex) << "eventIndex@0";
ASSERT_FLOAT_EQ(42.24, injectionStart.angleOffsetFromTriggerEvent); ASSERT_FLOAT_EQ(42.24, injectionStart.angleOffsetFromTriggerEvent);
printf("*************************************************** testAngleResolver 0.2\r\n"); printf("*************************************************** testAngleResolver 0.2\r\n");
TRIGGER_WAVEFORM(findTriggerPosition(&injectionStart, -54, engineConfiguration->globalTriggerAngleOffset)); findTriggerPosition(&ENGINE(triggerCentral.triggerShape), &ENGINE(triggerCentral.triggerFormDetails),&injectionStart, -54, engineConfiguration->globalTriggerAngleOffset);
ASSERT_EQ( 2, injectionStart.triggerEventIndex) << "eventIndex@0"; ASSERT_EQ( 2, injectionStart.triggerEventIndex) << "eventIndex@0";
ASSERT_FLOAT_EQ(68.2400, injectionStart.angleOffsetFromTriggerEvent); ASSERT_FLOAT_EQ(68.2400, injectionStart.angleOffsetFromTriggerEvent);
printf("*************************************************** testAngleResolver 0.3\r\n"); printf("*************************************************** testAngleResolver 0.3\r\n");
TRIGGER_WAVEFORM(findTriggerPosition(&injectionStart, -53, engineConfiguration->globalTriggerAngleOffset)); findTriggerPosition(&ENGINE(triggerCentral.triggerShape), &ENGINE(triggerCentral.triggerFormDetails),&injectionStart, -53, engineConfiguration->globalTriggerAngleOffset);
ASSERT_EQ(2, injectionStart.triggerEventIndex); ASSERT_EQ(2, injectionStart.triggerEventIndex);
ASSERT_FLOAT_EQ(69.24, injectionStart.angleOffsetFromTriggerEvent); ASSERT_FLOAT_EQ(69.24, injectionStart.angleOffsetFromTriggerEvent);
printf("*************************************************** testAngleResolver 1\r\n"); printf("*************************************************** testAngleResolver 1\r\n");
TRIGGER_WAVEFORM(findTriggerPosition(&injectionStart, 0, engineConfiguration->globalTriggerAngleOffset)); findTriggerPosition(&ENGINE(triggerCentral.triggerShape), &ENGINE(triggerCentral.triggerFormDetails),&injectionStart, 0, engineConfiguration->globalTriggerAngleOffset);
ASSERT_EQ(2, injectionStart.triggerEventIndex); ASSERT_EQ(2, injectionStart.triggerEventIndex);
ASSERT_FLOAT_EQ(122.24, injectionStart.angleOffsetFromTriggerEvent); ASSERT_FLOAT_EQ(122.24, injectionStart.angleOffsetFromTriggerEvent);
printf("*************************************************** testAngleResolver 2\r\n"); printf("*************************************************** testAngleResolver 2\r\n");
TRIGGER_WAVEFORM(findTriggerPosition(&injectionStart, 56, engineConfiguration->globalTriggerAngleOffset)); findTriggerPosition(&ENGINE(triggerCentral.triggerShape), &ENGINE(triggerCentral.triggerFormDetails),&injectionStart, 56, engineConfiguration->globalTriggerAngleOffset);
ASSERT_EQ(2, injectionStart.triggerEventIndex); ASSERT_EQ(2, injectionStart.triggerEventIndex);
ASSERT_FLOAT_EQ(178.24, injectionStart.angleOffsetFromTriggerEvent); ASSERT_FLOAT_EQ(178.24, injectionStart.angleOffsetFromTriggerEvent);

View File

@ -166,13 +166,19 @@ TEST(misc, test1995FordInline6TriggerDecoder) {
event_trigger_position_s position; event_trigger_position_s position;
ASSERT_EQ( 0, engineConfiguration->globalTriggerAngleOffset) << "globalTriggerAngleOffset"; ASSERT_EQ( 0, engineConfiguration->globalTriggerAngleOffset) << "globalTriggerAngleOffset";
TRIGGER_WAVEFORM(findTriggerPosition(&position, 0, engineConfiguration->globalTriggerAngleOffset)); findTriggerPosition(&ENGINE(triggerCentral.triggerShape),
&ENGINE(triggerCentral.triggerFormDetails),
&position, 0, engineConfiguration->globalTriggerAngleOffset);
assertTriggerPosition(&position, 0, 0); assertTriggerPosition(&position, 0, 0);
TRIGGER_WAVEFORM(findTriggerPosition(&position, 200, engineConfiguration->globalTriggerAngleOffset)); findTriggerPosition(&ENGINE(triggerCentral.triggerShape),
&ENGINE(triggerCentral.triggerFormDetails),
&position, 200, engineConfiguration->globalTriggerAngleOffset);
assertTriggerPosition(&position, 3, 20); assertTriggerPosition(&position, 3, 20);
TRIGGER_WAVEFORM(findTriggerPosition(&position, 360, engineConfiguration->globalTriggerAngleOffset)); findTriggerPosition(&ENGINE(triggerCentral.triggerShape),
&ENGINE(triggerCentral.triggerFormDetails),
&position, 360, engineConfiguration->globalTriggerAngleOffset);
assertTriggerPosition(&position, 6, 0); assertTriggerPosition(&position, 6, 0);
eth.applyTriggerWaveform(); eth.applyTriggerWaveform();
@ -320,8 +326,8 @@ TEST(misc, testRpmCalculator) {
ASSERT_EQ(0, GET_RPM()); ASSERT_EQ(0, GET_RPM());
// triggerIndexByAngle update is now fixed! prepareOutputSignals() wasn't reliably called // triggerIndexByAngle update is now fixed! prepareOutputSignals() wasn't reliably called
ASSERT_EQ(5, TRIGGER_WAVEFORM(triggerIndexByAngle[240])); ASSERT_EQ(5, engine->triggerCentral.triggerFormDetails.triggerIndexByAngle[240]);
ASSERT_EQ(5, TRIGGER_WAVEFORM(triggerIndexByAngle[241])); ASSERT_EQ(5, engine->triggerCentral.triggerFormDetails.triggerIndexByAngle[241]);
eth.fireTriggerEvents(/* count */ 48); eth.fireTriggerEvents(/* count */ 48);
@ -384,8 +390,8 @@ TEST(misc, testRpmCalculator) {
assertEqualsM("3/3", start + 14777, engine->executor.getForUnitTest(2)->momentX); assertEqualsM("3/3", start + 14777, engine->executor.getForUnitTest(2)->momentX);
engine->executor.clear(); engine->executor.clear();
ASSERT_EQ(5, TRIGGER_WAVEFORM(triggerIndexByAngle[240])); ASSERT_EQ(5, engine->triggerCentral.triggerFormDetails.triggerIndexByAngle[240]);
ASSERT_EQ(5, TRIGGER_WAVEFORM(triggerIndexByAngle[241])); ASSERT_EQ(5, engine->triggerCentral.triggerFormDetails.triggerIndexByAngle[241]);
eth.fireFall(5); eth.fireFall(5);